writer_test.js 29 KB

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