writer_test.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927
  1. /**
  2. * @fileoverview Tests for writer.js.
  3. */
  4. goog.module('protobuf.binary.WriterTest');
  5. goog.setTestOnly();
  6. // Note to the reader:
  7. // Since the writer behavior changes with the checking level some of the tests
  8. // in this file have to know which checking level is enable to make correct
  9. // assertions.
  10. const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
  11. const ByteString = goog.require('protobuf.ByteString');
  12. const WireType = goog.require('protobuf.binary.WireType');
  13. const Writer = goog.require('protobuf.binary.Writer');
  14. const {CHECK_BOUNDS, CHECK_TYPE, MAX_FIELD_NUMBER} = goog.require('protobuf.internal.checks');
  15. const {arrayBufferSlice} = goog.require('protobuf.binary.typedArrays');
  16. const {getDoublePairs} = goog.require('protobuf.binary.doubleTestPairs');
  17. const {getFixed32Pairs} = goog.require('protobuf.binary.fixed32TestPairs');
  18. const {getFloatPairs} = goog.require('protobuf.binary.floatTestPairs');
  19. const {getInt32Pairs} = goog.require('protobuf.binary.int32TestPairs');
  20. const {getInt64Pairs} = goog.require('protobuf.binary.int64TestPairs');
  21. const {getPackedBoolPairs} = goog.require('protobuf.binary.packedBoolTestPairs');
  22. const {getPackedDoublePairs} = goog.require('protobuf.binary.packedDoubleTestPairs');
  23. const {getPackedFixed32Pairs} = goog.require('protobuf.binary.packedFixed32TestPairs');
  24. const {getPackedFloatPairs} = goog.require('protobuf.binary.packedFloatTestPairs');
  25. const {getPackedInt32Pairs} = goog.require('protobuf.binary.packedInt32TestPairs');
  26. const {getPackedInt64Pairs} = goog.require('protobuf.binary.packedInt64TestPairs');
  27. const {getPackedSfixed32Pairs} = goog.require('protobuf.binary.packedSfixed32TestPairs');
  28. const {getPackedSfixed64Pairs} = goog.require('protobuf.binary.packedSfixed64TestPairs');
  29. const {getPackedSint32Pairs} = goog.require('protobuf.binary.packedSint32TestPairs');
  30. const {getPackedSint64Pairs} = goog.require('protobuf.binary.packedSint64TestPairs');
  31. const {getPackedUint32Pairs} = goog.require('protobuf.binary.packedUint32TestPairs');
  32. const {getSfixed32Pairs} = goog.require('protobuf.binary.sfixed32TestPairs');
  33. const {getSfixed64Pairs} = goog.require('protobuf.binary.sfixed64TestPairs');
  34. const {getSint32Pairs} = goog.require('protobuf.binary.sint32TestPairs');
  35. const {getSint64Pairs} = goog.require('protobuf.binary.sint64TestPairs');
  36. const {getUint32Pairs} = goog.require('protobuf.binary.uint32TestPairs');
  37. /**
  38. * @param {...number} bytes
  39. * @return {!ArrayBuffer}
  40. */
  41. function createArrayBuffer(...bytes) {
  42. return new Uint8Array(bytes).buffer;
  43. }
  44. /******************************************************************************
  45. * OPTIONAL FUNCTIONS
  46. ******************************************************************************/
  47. describe('Writer does', () => {
  48. it('return an empty ArrayBuffer when nothing is encoded', () => {
  49. const writer = new Writer();
  50. expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
  51. });
  52. it('encode tag', () => {
  53. const writer = new Writer();
  54. writer.writeTag(1, WireType.VARINT);
  55. expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer(0x08));
  56. writer.writeTag(0x0FFFFFFF, WireType.VARINT);
  57. expect(writer.getAndResetResultBuffer())
  58. .toEqual(createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0x7));
  59. writer.writeTag(0x10000000, WireType.VARINT);
  60. expect(writer.getAndResetResultBuffer())
  61. .toEqual(createArrayBuffer(0x80, 0x80, 0x80, 0x80, 0x08));
  62. writer.writeTag(0x1FFFFFFF, WireType.VARINT);
  63. expect(writer.getAndResetResultBuffer())
  64. .toEqual(createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0x0F));
  65. });
  66. it('reset after calling getAndResetResultBuffer', () => {
  67. const writer = new Writer();
  68. writer.writeTag(1, WireType.VARINT);
  69. writer.getAndResetResultBuffer();
  70. expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
  71. });
  72. it('fail when field number is too large for writeTag', () => {
  73. const writer = new Writer();
  74. if (CHECK_TYPE) {
  75. expect(() => writer.writeTag(MAX_FIELD_NUMBER + 1, WireType.VARINT))
  76. .toThrowError('Field number is out of range: 536870912');
  77. } else {
  78. // Note in unchecked mode we produce invalid output for invalid inputs.
  79. // This test just documents our behavior in those cases.
  80. // These values might change at any point and are not considered
  81. // what the implementation should be doing here.
  82. writer.writeTag(MAX_FIELD_NUMBER + 1, WireType.VARINT);
  83. expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer(0));
  84. }
  85. });
  86. it('fail when field number is negative for writeTag', () => {
  87. const writer = new Writer();
  88. if (CHECK_TYPE) {
  89. expect(() => writer.writeTag(-1, WireType.VARINT))
  90. .toThrowError('Field number is out of range: -1');
  91. } else {
  92. // Note in unchecked mode we produce invalid output for invalid inputs.
  93. // This test just documents our behavior in those cases.
  94. // These values might change at any point and are not considered
  95. // what the implementation should be doing here.
  96. writer.writeTag(-1, WireType.VARINT);
  97. expect(writer.getAndResetResultBuffer())
  98. .toEqual(createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0xF));
  99. }
  100. });
  101. it('fail when wire type is invalid for writeTag', () => {
  102. const writer = new Writer();
  103. if (CHECK_TYPE) {
  104. expect(() => writer.writeTag(1, /** @type {!WireType} */ (0x08)))
  105. .toThrowError('Invalid wire type: 8');
  106. } else {
  107. // Note in unchecked mode we produce invalid output for invalid inputs.
  108. // This test just documents our behavior in those cases.
  109. // These values might change at any point and are not considered
  110. // what the implementation should be doing here.
  111. writer.writeTag(1, /** @type {!WireType} */ (0x08));
  112. expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer(0x08));
  113. }
  114. });
  115. it('encode singular boolean value', () => {
  116. const writer = new Writer();
  117. writer.writeBool(1, true);
  118. expect(writer.getAndResetResultBuffer())
  119. .toEqual(createArrayBuffer(0x08, 0x01));
  120. });
  121. it('encode length delimited', () => {
  122. const writer = new Writer();
  123. writer.writeDelimited(1, createArrayBuffer(0x01, 0x02));
  124. expect(writer.getAndResetResultBuffer())
  125. .toEqual(createArrayBuffer(0x0A, 0x02, 0x01, 0x02));
  126. });
  127. });
  128. describe('Writer.writeBufferDecoder does', () => {
  129. it('encode BufferDecoder containing a varint value', () => {
  130. const writer = new Writer();
  131. const expected = createArrayBuffer(
  132. 0x08, /* varint start= */ 0xFF, /* varint end= */ 0x01, 0x08, 0x01);
  133. writer.writeBufferDecoder(
  134. BufferDecoder.fromArrayBuffer(expected), 1, WireType.VARINT, 1);
  135. const result = writer.getAndResetResultBuffer();
  136. expect(result).toEqual(arrayBufferSlice(expected, 1, 3));
  137. });
  138. it('encode BufferDecoder containing a fixed64 value', () => {
  139. const writer = new Writer();
  140. const expected = createArrayBuffer(
  141. 0x09, /* fixed64 start= */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  142. /* fixed64 end= */ 0x08, 0x08, 0x01);
  143. writer.writeBufferDecoder(
  144. BufferDecoder.fromArrayBuffer(expected), 1, WireType.FIXED64, 1);
  145. const result = writer.getAndResetResultBuffer();
  146. expect(result).toEqual(arrayBufferSlice(expected, 1, 9));
  147. });
  148. it('encode BufferDecoder containing a length delimited value', () => {
  149. const writer = new Writer();
  150. const expected = createArrayBuffer(
  151. 0xA, /* length= */ 0x03, /* data start= */ 0x01, 0x02,
  152. /* data end= */ 0x03, 0x08, 0x01);
  153. writer.writeBufferDecoder(
  154. BufferDecoder.fromArrayBuffer(expected), 1, WireType.DELIMITED, 1);
  155. const result = writer.getAndResetResultBuffer();
  156. expect(result).toEqual(arrayBufferSlice(expected, 1, 5));
  157. });
  158. it('encode BufferDecoder containing a group', () => {
  159. const writer = new Writer();
  160. const expected = createArrayBuffer(
  161. 0xB, /* group start= */ 0x08, 0x01, /* nested group start= */ 0x0B,
  162. /* nested group end= */ 0x0C, /* group end= */ 0x0C, 0x08, 0x01);
  163. writer.writeBufferDecoder(
  164. BufferDecoder.fromArrayBuffer(expected), 1, WireType.START_GROUP, 1);
  165. const result = writer.getAndResetResultBuffer();
  166. expect(result).toEqual(arrayBufferSlice(expected, 1, 6));
  167. });
  168. it('encode BufferDecoder containing a fixed32 value', () => {
  169. const writer = new Writer();
  170. const expected = createArrayBuffer(
  171. 0x09, /* fixed64 start= */ 0x01, 0x02, 0x03, /* fixed64 end= */ 0x04,
  172. 0x08, 0x01);
  173. writer.writeBufferDecoder(
  174. BufferDecoder.fromArrayBuffer(expected), 1, WireType.FIXED32, 1);
  175. const result = writer.getAndResetResultBuffer();
  176. expect(result).toEqual(arrayBufferSlice(expected, 1, 5));
  177. });
  178. it('fail when encoding out of bound data', () => {
  179. const writer = new Writer();
  180. const buffer = createArrayBuffer(0x4, 0x0, 0x1, 0x2, 0x3);
  181. const subBuffer = arrayBufferSlice(buffer, 0, 2);
  182. expect(
  183. () => writer.writeBufferDecoder(
  184. BufferDecoder.fromArrayBuffer(subBuffer), 0, WireType.DELIMITED, 1))
  185. .toThrow();
  186. });
  187. });
  188. describe('Writer.writeBytes does', () => {
  189. let writer;
  190. beforeEach(() => {
  191. writer = new Writer();
  192. });
  193. it('encodes empty ByteString', () => {
  194. writer.writeBytes(1, ByteString.EMPTY);
  195. const buffer = writer.getAndResetResultBuffer();
  196. expect(buffer.byteLength).toBe(2);
  197. });
  198. it('encodes empty array', () => {
  199. writer.writeBytes(1, ByteString.fromArrayBuffer(new ArrayBuffer(0)));
  200. expect(writer.getAndResetResultBuffer())
  201. .toEqual(createArrayBuffer(
  202. 1 << 3 | 0x02, // tag (fieldnumber << 3 | (length delimited))
  203. 0, // length of the bytes
  204. ));
  205. });
  206. it('encodes ByteString', () => {
  207. const array = createArrayBuffer(1, 2, 3);
  208. writer.writeBytes(1, ByteString.fromArrayBuffer(array));
  209. expect(writer.getAndResetResultBuffer())
  210. .toEqual(createArrayBuffer(
  211. 1 << 3 | 0x02, // tag (fieldnumber << 3 | (length delimited))
  212. 3, // length of the bytes
  213. 1,
  214. 2,
  215. 3,
  216. ));
  217. });
  218. });
  219. describe('Writer.writeDouble does', () => {
  220. let writer;
  221. beforeEach(() => {
  222. writer = new Writer();
  223. });
  224. for (const pair of getDoublePairs()) {
  225. it(`encode ${pair.name}`, () => {
  226. writer.writeDouble(1, pair.doubleValue);
  227. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  228. expect(buffer.length).toBe(9);
  229. // ensure we have a correct tag
  230. expect(buffer[0]).toEqual(0x09);
  231. // Encoded values are stored right after the tag
  232. expect(buffer.subarray(1, 9))
  233. .toEqual(pair.bufferDecoder.asUint8Array());
  234. });
  235. }
  236. /**
  237. * NaN may have different value in different browsers. Thus, we need to make
  238. * the test lenient.
  239. */
  240. it('encode NaN', () => {
  241. writer.writeDouble(1, NaN);
  242. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  243. expect(buffer.length).toBe(9);
  244. // ensure we have a correct tag
  245. expect(buffer[0]).toEqual(0x09);
  246. // Encoded values are stored right after the tag
  247. const float64 = new DataView(buffer.buffer);
  248. expect(float64.getFloat64(1, true)).toBeNaN();
  249. });
  250. });
  251. describe('Writer.writeFixed32 does', () => {
  252. let writer;
  253. beforeEach(() => {
  254. writer = new Writer();
  255. });
  256. for (const pair of getFixed32Pairs()) {
  257. it(`encode ${pair.name}`, () => {
  258. writer.writeFixed32(1, pair.intValue);
  259. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  260. expect(buffer.length).toBe(5);
  261. // ensure we have a correct tag
  262. expect(buffer[0]).toEqual(0x0D);
  263. // Encoded values are stored right after the tag
  264. expect(buffer.subarray(1, 5)).toEqual(pair.bufferDecoder.asUint8Array());
  265. });
  266. }
  267. });
  268. describe('Writer.writeFloat does', () => {
  269. let writer;
  270. beforeEach(() => {
  271. writer = new Writer();
  272. });
  273. for (const pair of getFloatPairs()) {
  274. it(`encode ${pair.name}`, () => {
  275. writer.writeFloat(1, pair.floatValue);
  276. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  277. expect(buffer.length).toBe(5);
  278. // ensure we have a correct tag
  279. expect(buffer[0]).toEqual(0x0D);
  280. // Encoded values are stored right after the tag
  281. expect(buffer.subarray(1, 5)).toEqual(pair.bufferDecoder.asUint8Array());
  282. });
  283. }
  284. /**
  285. * NaN may have different value in different browsers. Thus, we need to make
  286. * the test lenient.
  287. */
  288. it('encode NaN', () => {
  289. writer.writeFloat(1, NaN);
  290. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  291. expect(buffer.length).toBe(5);
  292. // ensure we have a correct tag
  293. expect(buffer[0]).toEqual(0x0D);
  294. // Encoded values are stored right after the tag
  295. const float32 = new DataView(buffer.buffer);
  296. expect(float32.getFloat32(1, true)).toBeNaN();
  297. });
  298. });
  299. describe('Writer.writeInt32 does', () => {
  300. let writer;
  301. beforeEach(() => {
  302. writer = new Writer();
  303. });
  304. for (const pair of getInt32Pairs()) {
  305. if (!pair.skip_writer) {
  306. it(`encode ${pair.name}`, () => {
  307. writer.writeInt32(1, pair.intValue);
  308. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  309. // ensure we have a correct tag
  310. expect(buffer[0]).toEqual(0x08);
  311. // Encoded values are stored right after the tag
  312. expect(buffer.subarray(1, buffer.length))
  313. .toEqual(pair.bufferDecoder.asUint8Array());
  314. });
  315. }
  316. }
  317. });
  318. describe('Writer.writeSfixed32 does', () => {
  319. let writer;
  320. beforeEach(() => {
  321. writer = new Writer();
  322. });
  323. it('encode empty array', () => {
  324. writer.writePackedSfixed32(1, []);
  325. expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
  326. });
  327. for (const pair of getSfixed32Pairs()) {
  328. it(`encode ${pair.name}`, () => {
  329. writer.writeSfixed32(1, pair.intValue);
  330. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  331. expect(buffer.length).toBe(5);
  332. // ensure we have a correct tag
  333. expect(buffer[0]).toEqual(0x0D);
  334. // Encoded values are stored right after the tag
  335. expect(buffer.subarray(1, 5)).toEqual(pair.bufferDecoder.asUint8Array());
  336. });
  337. }
  338. });
  339. describe('Writer.writeSfixed64 does', () => {
  340. let writer;
  341. beforeEach(() => {
  342. writer = new Writer();
  343. });
  344. for (const pair of getSfixed64Pairs()) {
  345. it(`encode ${pair.name}`, () => {
  346. writer.writeSfixed64(1, pair.longValue);
  347. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  348. expect(buffer.length).toBe(9);
  349. // ensure we have a correct tag
  350. expect(buffer[0]).toEqual(0x09);
  351. // Encoded values are stored right after the tag
  352. expect(buffer.subarray(1, 9)).toEqual(pair.bufferDecoder.asUint8Array());
  353. });
  354. }
  355. });
  356. describe('Writer.writeSint32 does', () => {
  357. let writer;
  358. beforeEach(() => {
  359. writer = new Writer();
  360. });
  361. for (const pair of getSint32Pairs()) {
  362. if (!pair.skip_writer) {
  363. it(`encode ${pair.name}`, () => {
  364. writer.writeSint32(1, pair.intValue);
  365. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  366. // ensure we have a correct tag
  367. expect(buffer[0]).toEqual(0x08);
  368. // Encoded values are stored right after the tag
  369. expect(buffer.subarray(1, buffer.length))
  370. .toEqual(pair.bufferDecoder.asUint8Array());
  371. });
  372. }
  373. }
  374. });
  375. describe('Writer.writeSint64 does', () => {
  376. let writer;
  377. beforeEach(() => {
  378. writer = new Writer();
  379. });
  380. for (const pair of getSint64Pairs()) {
  381. if (!pair.skip_writer) {
  382. it(`encode ${pair.name}`, () => {
  383. writer.writeSint64(1, pair.longValue);
  384. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  385. // ensure we have a correct tag
  386. expect(buffer[0]).toEqual(0x08);
  387. // Encoded values are stored right after the tag
  388. expect(buffer.subarray(1, buffer.length))
  389. .toEqual(pair.bufferDecoder.asUint8Array());
  390. });
  391. }
  392. }
  393. });
  394. describe('Writer.writeInt64 does', () => {
  395. let writer;
  396. beforeEach(() => {
  397. writer = new Writer();
  398. });
  399. for (const pair of getInt64Pairs()) {
  400. if (!pair.skip_writer) {
  401. it(`encode ${pair.name}`, () => {
  402. writer.writeInt64(1, pair.longValue);
  403. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  404. // ensure we have a correct tag
  405. expect(buffer[0]).toEqual(0x08);
  406. // Encoded values are stored right after the tag
  407. expect(buffer.subarray(1, buffer.length))
  408. .toEqual(pair.bufferDecoder.asUint8Array());
  409. });
  410. }
  411. }
  412. });
  413. describe('Writer.writeUint32 does', () => {
  414. let writer;
  415. beforeEach(() => {
  416. writer = new Writer();
  417. });
  418. for (const pair of getUint32Pairs()) {
  419. if (!pair.skip_writer) {
  420. it(`encode ${pair.name}`, () => {
  421. writer.writeUint32(1, pair.intValue);
  422. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  423. // ensure we have a correct tag
  424. expect(buffer[0]).toEqual(0x08);
  425. // Encoded values are stored right after the tag
  426. expect(buffer.subarray(1, buffer.length))
  427. .toEqual(pair.bufferDecoder.asUint8Array());
  428. });
  429. }
  430. }
  431. });
  432. describe('Writer.writeString does', () => {
  433. let writer;
  434. beforeEach(() => {
  435. writer = new Writer();
  436. });
  437. it('encode empty string', () => {
  438. writer.writeString(1, '');
  439. expect(writer.getAndResetResultBuffer())
  440. .toEqual(createArrayBuffer(
  441. 1 << 3 | 0x02, // tag (fieldnumber << 3 | (length delimited))
  442. 0, // length of the string
  443. ));
  444. });
  445. it('encode simple string', () => {
  446. writer.writeString(1, 'hello');
  447. expect(writer.getAndResetResultBuffer())
  448. .toEqual(createArrayBuffer(
  449. 1 << 3 | 0x02, // tag (fieldnumber << 3 | (length delimited))
  450. 5, // length of the string
  451. 'h'.charCodeAt(0),
  452. 'e'.charCodeAt(0),
  453. 'l'.charCodeAt(0),
  454. 'l'.charCodeAt(0),
  455. 'o'.charCodeAt(0),
  456. ));
  457. });
  458. it('throw for invalid fieldnumber', () => {
  459. if (CHECK_BOUNDS) {
  460. expect(() => writer.writeString(-1, 'a'))
  461. .toThrowError('Field number is out of range: -1');
  462. } else {
  463. writer.writeString(-1, 'a');
  464. expect(new Uint8Array(writer.getAndResetResultBuffer()))
  465. .toEqual(new Uint8Array(createArrayBuffer(
  466. -6, // invalid tag
  467. 0xff,
  468. 0xff,
  469. 0xff,
  470. 0x0f,
  471. 1, // string length
  472. 'a'.charCodeAt(0),
  473. )));
  474. }
  475. });
  476. it('throw for null string value', () => {
  477. expect(
  478. () => writer.writeString(
  479. 1, /** @type {string} */ (/** @type {*} */ (null))))
  480. .toThrow();
  481. });
  482. });
  483. /******************************************************************************
  484. * REPEATED FUNCTIONS
  485. ******************************************************************************/
  486. describe('Writer.writePackedBool does', () => {
  487. let writer;
  488. beforeEach(() => {
  489. writer = new Writer();
  490. });
  491. it('encode empty array', () => {
  492. writer.writePackedBool(1, []);
  493. expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
  494. });
  495. for (const pair of getPackedBoolPairs()) {
  496. if (!pair.skip_writer) {
  497. it(`encode ${pair.name}`, () => {
  498. writer.writePackedBool(1, pair.boolValues);
  499. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  500. // ensure we have a correct tag
  501. expect(buffer[0]).toEqual(0x0A);
  502. // Encoded values are stored right after the tag
  503. expect(buffer.subarray(1, buffer.length))
  504. .toEqual(pair.bufferDecoder.asUint8Array());
  505. });
  506. }
  507. }
  508. });
  509. describe('Writer.writeRepeatedBool does', () => {
  510. let writer;
  511. beforeEach(() => {
  512. writer = new Writer();
  513. });
  514. it('encode empty array', () => {
  515. writer.writeRepeatedBool(1, []);
  516. expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
  517. });
  518. it('encode repeated unpacked boolean values', () => {
  519. const writer = new Writer();
  520. writer.writeRepeatedBool(1, [true, false]);
  521. expect(writer.getAndResetResultBuffer())
  522. .toEqual(createArrayBuffer(
  523. 1 << 3 | 0x00, // tag (fieldnumber << 3 | (varint))
  524. 0x01, // value[0]
  525. 1 << 3 | 0x00, // tag (fieldnumber << 3 | (varint))
  526. 0x00, // value[1]
  527. ));
  528. });
  529. });
  530. describe('Writer.writePackedDouble does', () => {
  531. let writer;
  532. beforeEach(() => {
  533. writer = new Writer();
  534. });
  535. it('encode empty array', () => {
  536. writer.writePackedDouble(1, []);
  537. expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
  538. });
  539. for (const pair of getPackedDoublePairs()) {
  540. if (!pair.skip_writer) {
  541. it(`encode ${pair.name}`, () => {
  542. writer.writePackedDouble(1, pair.doubleValues);
  543. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  544. // ensure we have a correct tag
  545. expect(buffer[0]).toEqual(0x0A);
  546. // Encoded values are stored right after the tag
  547. expect(buffer.subarray(1, buffer.length))
  548. .toEqual(pair.bufferDecoder.asUint8Array());
  549. });
  550. }
  551. }
  552. });
  553. describe('Writer.writePackedFixed32 does', () => {
  554. let writer;
  555. beforeEach(() => {
  556. writer = new Writer();
  557. });
  558. it('encode empty array', () => {
  559. writer.writePackedFixed32(1, []);
  560. expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
  561. });
  562. for (const pair of getPackedFixed32Pairs()) {
  563. if (!pair.skip_writer) {
  564. it(`encode ${pair.name}`, () => {
  565. writer.writePackedFixed32(1, pair.fixed32Values);
  566. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  567. // ensure we have a correct tag
  568. expect(buffer[0]).toEqual(0x0A);
  569. // Encoded values are stored right after the tag
  570. expect(buffer.subarray(1, buffer.length))
  571. .toEqual(pair.bufferDecoder.asUint8Array());
  572. });
  573. }
  574. }
  575. });
  576. describe('Writer.writePackedFloat does', () => {
  577. let writer;
  578. beforeEach(() => {
  579. writer = new Writer();
  580. });
  581. it('encode empty array', () => {
  582. writer.writePackedFloat(1, []);
  583. expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
  584. });
  585. for (const pair of getPackedFloatPairs()) {
  586. if (!pair.skip_writer) {
  587. it(`encode ${pair.name}`, () => {
  588. writer.writePackedFloat(1, pair.floatValues);
  589. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  590. // ensure we have a correct tag
  591. expect(buffer[0]).toEqual(0x0A);
  592. // Encoded values are stored right after the tag
  593. expect(buffer.subarray(1, buffer.length))
  594. .toEqual(pair.bufferDecoder.asUint8Array());
  595. });
  596. }
  597. }
  598. });
  599. describe('Writer.writePackedInt32 does', () => {
  600. let writer;
  601. beforeEach(() => {
  602. writer = new Writer();
  603. });
  604. it('encode empty array', () => {
  605. writer.writePackedInt32(1, []);
  606. expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
  607. });
  608. for (const pair of getPackedInt32Pairs()) {
  609. if (!pair.skip_writer) {
  610. it(`encode ${pair.name}`, () => {
  611. writer.writePackedInt32(1, pair.int32Values);
  612. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  613. // ensure we have a correct tag
  614. expect(buffer[0]).toEqual(0x0A);
  615. // Encoded values are stored right after the tag
  616. expect(buffer.subarray(1, buffer.length))
  617. .toEqual(pair.bufferDecoder.asUint8Array());
  618. });
  619. }
  620. }
  621. });
  622. describe('Writer.writePackedInt64 does', () => {
  623. let writer;
  624. beforeEach(() => {
  625. writer = new Writer();
  626. });
  627. it('encode empty array', () => {
  628. writer.writePackedInt64(1, []);
  629. expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
  630. });
  631. for (const pair of getPackedInt64Pairs()) {
  632. if (!pair.skip_writer) {
  633. it(`encode ${pair.name}`, () => {
  634. writer.writePackedInt64(1, pair.int64Values);
  635. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  636. // ensure we have a correct tag
  637. expect(buffer[0]).toEqual(0x0A);
  638. // Encoded values are stored right after the tag
  639. expect(buffer.subarray(1, buffer.length))
  640. .toEqual(pair.bufferDecoder.asUint8Array());
  641. });
  642. }
  643. }
  644. });
  645. describe('Writer.writePackedSfixed32 does', () => {
  646. let writer;
  647. beforeEach(() => {
  648. writer = new Writer();
  649. });
  650. it('encode empty array', () => {
  651. writer.writePackedSfixed32(1, []);
  652. expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
  653. });
  654. for (const pair of getPackedSfixed32Pairs()) {
  655. if (!pair.skip_writer) {
  656. it(`encode ${pair.name}`, () => {
  657. writer.writePackedSfixed32(1, pair.sfixed32Values);
  658. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  659. // ensure we have a correct tag
  660. expect(buffer[0]).toEqual(0x0A);
  661. // Encoded values are stored right after the tag
  662. expect(buffer.subarray(1, buffer.length))
  663. .toEqual(pair.bufferDecoder.asUint8Array());
  664. });
  665. }
  666. }
  667. });
  668. describe('Writer.writePackedSfixed64 does', () => {
  669. let writer;
  670. beforeEach(() => {
  671. writer = new Writer();
  672. });
  673. it('encode empty array', () => {
  674. writer.writePackedSfixed64(1, []);
  675. expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
  676. });
  677. for (const pair of getPackedSfixed64Pairs()) {
  678. if (!pair.skip_writer) {
  679. it(`encode ${pair.name}`, () => {
  680. writer.writePackedSfixed64(1, pair.sfixed64Values);
  681. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  682. // ensure we have a correct tag
  683. expect(buffer[0]).toEqual(0x0A);
  684. // Encoded values are stored right after the tag
  685. expect(buffer.subarray(1, buffer.length))
  686. .toEqual(pair.bufferDecoder.asUint8Array());
  687. });
  688. }
  689. }
  690. });
  691. describe('Writer.writePackedSint32 does', () => {
  692. let writer;
  693. beforeEach(() => {
  694. writer = new Writer();
  695. });
  696. it('encode empty array', () => {
  697. writer.writePackedSint32(1, []);
  698. expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
  699. });
  700. for (const pair of getPackedSint32Pairs()) {
  701. if (!pair.skip_writer) {
  702. it(`encode ${pair.name}`, () => {
  703. writer.writePackedSint32(1, pair.sint32Values);
  704. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  705. // ensure we have a correct tag
  706. expect(buffer[0]).toEqual(0x0A);
  707. // Encoded values are stored right after the tag
  708. expect(buffer.subarray(1, buffer.length))
  709. .toEqual(pair.bufferDecoder.asUint8Array());
  710. });
  711. }
  712. }
  713. });
  714. describe('Writer.writePackedSint64 does', () => {
  715. let writer;
  716. beforeEach(() => {
  717. writer = new Writer();
  718. });
  719. it('encode empty array', () => {
  720. writer.writePackedSint64(1, []);
  721. expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
  722. });
  723. for (const pair of getPackedSint64Pairs()) {
  724. if (!pair.skip_writer) {
  725. it(`encode ${pair.name}`, () => {
  726. writer.writePackedSint64(1, pair.sint64Values);
  727. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  728. // ensure we have a correct tag
  729. expect(buffer[0]).toEqual(0x0A);
  730. // Encoded values are stored right after the tag
  731. expect(buffer.subarray(1, buffer.length))
  732. .toEqual(pair.bufferDecoder.asUint8Array());
  733. });
  734. }
  735. }
  736. });
  737. describe('Writer.writePackedUint32 does', () => {
  738. let writer;
  739. beforeEach(() => {
  740. writer = new Writer();
  741. });
  742. it('encode empty array', () => {
  743. writer.writePackedUint32(1, []);
  744. expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
  745. });
  746. for (const pair of getPackedUint32Pairs()) {
  747. if (!pair.skip_writer) {
  748. it(`encode ${pair.name}`, () => {
  749. writer.writePackedUint32(1, pair.uint32Values);
  750. const buffer = new Uint8Array(writer.getAndResetResultBuffer());
  751. // ensure we have a correct tag
  752. expect(buffer[0]).toEqual(0x0A);
  753. // Encoded values are stored right after the tag
  754. expect(buffer.subarray(1, buffer.length))
  755. .toEqual(pair.bufferDecoder.asUint8Array());
  756. });
  757. }
  758. }
  759. });
  760. describe('Writer.writeRepeatedBytes does', () => {
  761. let writer;
  762. beforeEach(() => {
  763. writer = new Writer();
  764. });
  765. it('encode empty array', () => {
  766. writer.writeRepeatedBytes(1, []);
  767. expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
  768. });
  769. it('encode single value', () => {
  770. const value = createArrayBuffer(0x61);
  771. writer.writeRepeatedBytes(1, [ByteString.fromArrayBuffer(value)]);
  772. expect(writer.getAndResetResultBuffer())
  773. .toEqual(createArrayBuffer(
  774. 0x0A,
  775. 0x01,
  776. 0x61, // a
  777. ));
  778. });
  779. it('encode multiple values', () => {
  780. const value1 = createArrayBuffer(0x61);
  781. const value2 = createArrayBuffer(0x62);
  782. writer.writeRepeatedBytes(1, [
  783. ByteString.fromArrayBuffer(value1),
  784. ByteString.fromArrayBuffer(value2),
  785. ]);
  786. expect(writer.getAndResetResultBuffer())
  787. .toEqual(createArrayBuffer(
  788. 0x0A,
  789. 0x01,
  790. 0x61, // a
  791. 0x0A,
  792. 0x01,
  793. 0x62, // b
  794. ));
  795. });
  796. });
  797. describe('Writer.writeRepeatedString does', () => {
  798. let writer;
  799. beforeEach(() => {
  800. writer = new Writer();
  801. });
  802. it('encode empty array', () => {
  803. writer.writeRepeatedString(1, []);
  804. expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
  805. });
  806. it('encode single value', () => {
  807. writer.writeRepeatedString(1, ['a']);
  808. expect(writer.getAndResetResultBuffer())
  809. .toEqual(createArrayBuffer(
  810. 0x0A,
  811. 0x01,
  812. 0x61, // a
  813. ));
  814. });
  815. it('encode multiple values', () => {
  816. writer.writeRepeatedString(1, ['a', 'b']);
  817. expect(writer.getAndResetResultBuffer())
  818. .toEqual(createArrayBuffer(
  819. 0x0A,
  820. 0x01,
  821. 0x61, // a
  822. 0x0A,
  823. 0x01,
  824. 0x62, // b
  825. ));
  826. });
  827. });