reader_test.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. /**
  2. * @fileoverview Tests for reader.js.
  3. */
  4. goog.module('protobuf.binary.ReaderTest');
  5. goog.setTestOnly();
  6. // Note to the reader:
  7. // Since the reader behavior changes with the checking level some of the
  8. // tests in this file have to know which checking level is enable to make
  9. // correct assertions.
  10. const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
  11. const ByteString = goog.require('protobuf.ByteString');
  12. const reader = goog.require('protobuf.binary.reader');
  13. const {CHECK_CRITICAL_STATE} = goog.require('protobuf.internal.checks');
  14. const {createBufferDecoder} = goog.require('protobuf.binary.bufferDecoderHelper');
  15. const {encode} = goog.require('protobuf.binary.textencoding');
  16. const {getBoolPairs} = goog.require('protobuf.binary.boolTestPairs');
  17. const {getDoublePairs} = goog.require('protobuf.binary.doubleTestPairs');
  18. const {getFixed32Pairs} = goog.require('protobuf.binary.fixed32TestPairs');
  19. const {getFloatPairs} = goog.require('protobuf.binary.floatTestPairs');
  20. const {getInt32Pairs} = goog.require('protobuf.binary.int32TestPairs');
  21. const {getInt64Pairs} = goog.require('protobuf.binary.int64TestPairs');
  22. const {getPackedBoolPairs} = goog.require('protobuf.binary.packedBoolTestPairs');
  23. const {getPackedDoublePairs} = goog.require('protobuf.binary.packedDoubleTestPairs');
  24. const {getPackedFixed32Pairs} = goog.require('protobuf.binary.packedFixed32TestPairs');
  25. const {getPackedFloatPairs} = goog.require('protobuf.binary.packedFloatTestPairs');
  26. const {getPackedInt32Pairs} = goog.require('protobuf.binary.packedInt32TestPairs');
  27. const {getPackedInt64Pairs} = goog.require('protobuf.binary.packedInt64TestPairs');
  28. const {getPackedSfixed32Pairs} = goog.require('protobuf.binary.packedSfixed32TestPairs');
  29. const {getPackedSfixed64Pairs} = goog.require('protobuf.binary.packedSfixed64TestPairs');
  30. const {getPackedSint32Pairs} = goog.require('protobuf.binary.packedSint32TestPairs');
  31. const {getPackedSint64Pairs} = goog.require('protobuf.binary.packedSint64TestPairs');
  32. const {getPackedUint32Pairs} = goog.require('protobuf.binary.packedUint32TestPairs');
  33. const {getSfixed32Pairs} = goog.require('protobuf.binary.sfixed32TestPairs');
  34. const {getSfixed64Pairs} = goog.require('protobuf.binary.sfixed64TestPairs');
  35. const {getSint32Pairs} = goog.require('protobuf.binary.sint32TestPairs');
  36. const {getSint64Pairs} = goog.require('protobuf.binary.sint64TestPairs');
  37. const {getUint32Pairs} = goog.require('protobuf.binary.uint32TestPairs');
  38. /******************************************************************************
  39. * Optional FUNCTIONS
  40. ******************************************************************************/
  41. describe('Read bool does', () => {
  42. for (const pair of getBoolPairs()) {
  43. it(`decode ${pair.name}`, () => {
  44. if (pair.error && CHECK_CRITICAL_STATE) {
  45. expect(() => reader.readBool(pair.bufferDecoder, 0)).toThrow();
  46. } else {
  47. const d = reader.readBool(
  48. pair.bufferDecoder, pair.bufferDecoder.startIndex());
  49. expect(d).toEqual(pair.boolValue);
  50. }
  51. });
  52. }
  53. });
  54. describe('readBytes does', () => {
  55. it('throw exception if data is too short', () => {
  56. const bufferDecoder = createBufferDecoder();
  57. expect(() => reader.readBytes(bufferDecoder, 0)).toThrow();
  58. });
  59. it('read bytes by index', () => {
  60. const bufferDecoder = createBufferDecoder(3, 1, 2, 3);
  61. const byteString = reader.readBytes(bufferDecoder, 0);
  62. expect(ByteString.fromArrayBuffer(new Uint8Array([1, 2, 3]).buffer))
  63. .toEqual(byteString);
  64. });
  65. });
  66. describe('readDouble does', () => {
  67. it('throw exception if data is too short', () => {
  68. const bufferDecoder = createBufferDecoder();
  69. expect(() => reader.readDouble(bufferDecoder, 0)).toThrow();
  70. });
  71. for (const pair of getDoublePairs()) {
  72. it(`decode ${pair.name}`, () => {
  73. const d = reader.readDouble(pair.bufferDecoder, 0);
  74. expect(d).toEqual(pair.doubleValue);
  75. });
  76. }
  77. });
  78. describe('readFixed32 does', () => {
  79. it('throw exception if data is too short', () => {
  80. const bufferDecoder = createBufferDecoder();
  81. expect(() => reader.readFixed32(bufferDecoder, 0)).toThrow();
  82. });
  83. for (const pair of getFixed32Pairs()) {
  84. it(`decode ${pair.name}`, () => {
  85. const d = reader.readFixed32(pair.bufferDecoder, 0);
  86. expect(d).toEqual(pair.intValue);
  87. });
  88. }
  89. });
  90. describe('readFloat does', () => {
  91. it('throw exception if data is too short', () => {
  92. const bufferDecoder = createBufferDecoder();
  93. expect(() => reader.readFloat(bufferDecoder, 0)).toThrow();
  94. });
  95. for (const pair of getFloatPairs()) {
  96. it(`decode ${pair.name}`, () => {
  97. const d = reader.readFloat(pair.bufferDecoder, 0);
  98. expect(d).toEqual(Math.fround(pair.floatValue));
  99. });
  100. }
  101. });
  102. describe('readInt32 does', () => {
  103. it('throw exception if data is too short', () => {
  104. const bufferDecoder = createBufferDecoder(0x80);
  105. expect(() => reader.readInt32(bufferDecoder, 0)).toThrow();
  106. });
  107. for (const pair of getInt32Pairs()) {
  108. it(`decode ${pair.name}`, () => {
  109. if (pair.error && CHECK_CRITICAL_STATE) {
  110. expect(() => reader.readInt32(pair.bufferDecoder, 0)).toThrow();
  111. } else {
  112. const d = reader.readInt32(pair.bufferDecoder, 0);
  113. expect(d).toEqual(pair.intValue);
  114. }
  115. });
  116. }
  117. });
  118. describe('readSfixed32 does', () => {
  119. it('throw exception if data is too short', () => {
  120. const bufferDecoder = createBufferDecoder(0x80);
  121. expect(() => reader.readSfixed32(bufferDecoder, 0)).toThrow();
  122. });
  123. for (const pair of getSfixed32Pairs()) {
  124. it(`decode ${pair.name}`, () => {
  125. const d = reader.readSfixed32(pair.bufferDecoder, 0);
  126. expect(d).toEqual(pair.intValue);
  127. });
  128. }
  129. });
  130. describe('readSfixed64 does', () => {
  131. it('throw exception if data is too short', () => {
  132. const bufferDecoder = createBufferDecoder(0x80);
  133. expect(() => reader.readSfixed64(bufferDecoder, 0)).toThrow();
  134. });
  135. for (const pair of getSfixed64Pairs()) {
  136. it(`decode ${pair.name}`, () => {
  137. const d = reader.readSfixed64(pair.bufferDecoder, 0);
  138. expect(d).toEqual(pair.longValue);
  139. });
  140. }
  141. });
  142. describe('readSint32 does', () => {
  143. it('throw exception if data is too short', () => {
  144. const bufferDecoder = createBufferDecoder(0x80);
  145. expect(() => reader.readSint32(bufferDecoder, 0)).toThrow();
  146. });
  147. for (const pair of getSint32Pairs()) {
  148. it(`decode ${pair.name}`, () => {
  149. if (pair.error && CHECK_CRITICAL_STATE) {
  150. expect(() => reader.readSint32(pair.bufferDecoder, 0)).toThrow();
  151. } else {
  152. const d = reader.readSint32(pair.bufferDecoder, 0);
  153. expect(d).toEqual(pair.intValue);
  154. }
  155. });
  156. }
  157. });
  158. describe('readInt64 does', () => {
  159. it('throw exception if data is too short', () => {
  160. const bufferDecoder = createBufferDecoder(0x80);
  161. expect(() => reader.readInt64(bufferDecoder, 0)).toThrow();
  162. });
  163. for (const pair of getInt64Pairs()) {
  164. it(`decode ${pair.name}`, () => {
  165. if (pair.error && CHECK_CRITICAL_STATE) {
  166. expect(() => reader.readInt64(pair.bufferDecoder, 0)).toThrow();
  167. } else {
  168. const d = reader.readInt64(pair.bufferDecoder, 0);
  169. expect(d).toEqual(pair.longValue);
  170. }
  171. });
  172. }
  173. });
  174. describe('readSint64 does', () => {
  175. it('throw exception if data is too short', () => {
  176. const bufferDecoder = createBufferDecoder(0x80);
  177. expect(() => reader.readSint64(bufferDecoder, 0)).toThrow();
  178. });
  179. for (const pair of getSint64Pairs()) {
  180. it(`decode ${pair.name}`, () => {
  181. if (pair.error && CHECK_CRITICAL_STATE) {
  182. expect(() => reader.readSint64(pair.bufferDecoder, 0)).toThrow();
  183. } else {
  184. const d = reader.readSint64(pair.bufferDecoder, 0);
  185. expect(d).toEqual(pair.longValue);
  186. }
  187. });
  188. }
  189. });
  190. describe('readUint32 does', () => {
  191. it('throw exception if data is too short', () => {
  192. const bufferDecoder = createBufferDecoder(0x80);
  193. expect(() => reader.readUint32(bufferDecoder, 0)).toThrow();
  194. });
  195. for (const pair of getUint32Pairs()) {
  196. if (!pair.skip_reader) {
  197. it(`decode ${pair.name}`, () => {
  198. if (pair.error && CHECK_CRITICAL_STATE) {
  199. expect(() => reader.readUint32(pair.bufferDecoder, 0)).toThrow();
  200. } else {
  201. const d = reader.readUint32(pair.bufferDecoder, 0);
  202. expect(d).toEqual(pair.intValue);
  203. }
  204. });
  205. }
  206. }
  207. });
  208. /**
  209. *
  210. * @param {string} s
  211. * @return {!Uint8Array}
  212. */
  213. function encodeString(s) {
  214. if (typeof TextEncoder !== 'undefined') {
  215. const textEncoder = new TextEncoder('utf-8');
  216. return textEncoder.encode(s);
  217. } else {
  218. return encode(s);
  219. }
  220. }
  221. /** @param {string} s */
  222. function expectEncodedStringToMatch(s) {
  223. const array = encodeString(s);
  224. const length = array.length;
  225. if (length > 127) {
  226. throw new Error('Test only works for strings shorter than 128');
  227. }
  228. const encodedArray = new Uint8Array(length + 1);
  229. encodedArray[0] = length;
  230. encodedArray.set(array, 1);
  231. const bufferDecoder = BufferDecoder.fromArrayBuffer(encodedArray.buffer);
  232. expect(reader.readString(bufferDecoder, 0)).toEqual(s);
  233. }
  234. describe('readString does', () => {
  235. it('return empty string for zero length string', () => {
  236. const s = reader.readString(createBufferDecoder(0x00), 0);
  237. expect(s).toEqual('');
  238. });
  239. it('decode random strings', () => {
  240. // 1 byte strings
  241. expectEncodedStringToMatch('hello');
  242. expectEncodedStringToMatch('HELLO1!');
  243. // 2 byte String
  244. expectEncodedStringToMatch('©');
  245. // 3 byte string
  246. expectEncodedStringToMatch('❄');
  247. // 4 byte string
  248. expectEncodedStringToMatch('😁');
  249. });
  250. it('decode 1 byte strings', () => {
  251. for (let i = 0; i < 0x80; i++) {
  252. const s = String.fromCharCode(i);
  253. expectEncodedStringToMatch(s);
  254. }
  255. });
  256. it('decode 2 byte strings', () => {
  257. for (let i = 0xC0; i < 0x7FF; i++) {
  258. const s = String.fromCharCode(i);
  259. expectEncodedStringToMatch(s);
  260. }
  261. });
  262. it('decode 3 byte strings', () => {
  263. for (let i = 0x7FF; i < 0x8FFF; i++) {
  264. const s = String.fromCharCode(i);
  265. expectEncodedStringToMatch(s);
  266. }
  267. });
  268. it('throw exception on invalid bytes', () => {
  269. // This test will only succeed with the native TextDecoder since
  270. // our polyfill does not do any validation. IE10 and IE11 don't support
  271. // TextDecoder.
  272. // TODO: Remove this check once we no longer need to support IE
  273. if (typeof TextDecoder !== 'undefined') {
  274. expect(
  275. () => reader.readString(
  276. createBufferDecoder(0x01, /* invalid utf data point*/ 0xFF), 0))
  277. .toThrow();
  278. }
  279. });
  280. it('throw exception if data is too short', () => {
  281. const array = createBufferDecoder(0x02, '?'.charCodeAt(0));
  282. expect(() => reader.readString(array, 0)).toThrow();
  283. });
  284. });
  285. /******************************************************************************
  286. * REPEATED FUNCTIONS
  287. ******************************************************************************/
  288. describe('readPackedBool does', () => {
  289. for (const pair of getPackedBoolPairs()) {
  290. it(`decode ${pair.name}`, () => {
  291. const d = reader.readPackedBool(pair.bufferDecoder, 0);
  292. expect(d).toEqual(pair.boolValues);
  293. });
  294. }
  295. });
  296. describe('readPackedDouble does', () => {
  297. for (const pair of getPackedDoublePairs()) {
  298. it(`decode ${pair.name}`, () => {
  299. const d = reader.readPackedDouble(pair.bufferDecoder, 0);
  300. expect(d).toEqual(pair.doubleValues);
  301. });
  302. }
  303. });
  304. describe('readPackedFixed32 does', () => {
  305. for (const pair of getPackedFixed32Pairs()) {
  306. it(`decode ${pair.name}`, () => {
  307. const d = reader.readPackedFixed32(pair.bufferDecoder, 0);
  308. expect(d).toEqual(pair.fixed32Values);
  309. });
  310. }
  311. });
  312. describe('readPackedFloat does', () => {
  313. for (const pair of getPackedFloatPairs()) {
  314. it(`decode ${pair.name}`, () => {
  315. const d = reader.readPackedFloat(pair.bufferDecoder, 0);
  316. expect(d).toEqual(pair.floatValues);
  317. });
  318. }
  319. });
  320. describe('readPackedInt32 does', () => {
  321. for (const pair of getPackedInt32Pairs()) {
  322. it(`decode ${pair.name}`, () => {
  323. const d = reader.readPackedInt32(pair.bufferDecoder, 0);
  324. expect(d).toEqual(pair.int32Values);
  325. });
  326. }
  327. });
  328. describe('readPackedInt64 does', () => {
  329. for (const pair of getPackedInt64Pairs()) {
  330. it(`decode ${pair.name}`, () => {
  331. const d = reader.readPackedInt64(pair.bufferDecoder, 0);
  332. expect(d).toEqual(pair.int64Values);
  333. });
  334. }
  335. });
  336. describe('readPackedSfixed32 does', () => {
  337. for (const pair of getPackedSfixed32Pairs()) {
  338. it(`decode ${pair.name}`, () => {
  339. const d = reader.readPackedSfixed32(pair.bufferDecoder, 0);
  340. expect(d).toEqual(pair.sfixed32Values);
  341. });
  342. }
  343. });
  344. describe('readPackedSfixed64 does', () => {
  345. for (const pair of getPackedSfixed64Pairs()) {
  346. it(`decode ${pair.name}`, () => {
  347. const d = reader.readPackedSfixed64(pair.bufferDecoder, 0);
  348. expect(d).toEqual(pair.sfixed64Values);
  349. });
  350. }
  351. });
  352. describe('readPackedSint32 does', () => {
  353. for (const pair of getPackedSint32Pairs()) {
  354. it(`decode ${pair.name}`, () => {
  355. const d = reader.readPackedSint32(pair.bufferDecoder, 0);
  356. expect(d).toEqual(pair.sint32Values);
  357. });
  358. }
  359. });
  360. describe('readPackedSint64 does', () => {
  361. for (const pair of getPackedSint64Pairs()) {
  362. it(`decode ${pair.name}`, () => {
  363. const d = reader.readPackedSint64(pair.bufferDecoder, 0);
  364. expect(d).toEqual(pair.sint64Values);
  365. });
  366. }
  367. });
  368. describe('readPackedUint32 does', () => {
  369. for (const pair of getPackedUint32Pairs()) {
  370. it(`decode ${pair.name}`, () => {
  371. const d = reader.readPackedUint32(pair.bufferDecoder, 0);
  372. expect(d).toEqual(pair.uint32Values);
  373. });
  374. }
  375. });