suite.js 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005
  1. /*
  2. Copyright 2013 Daniel Wirtz <dcode@dcode.io>
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. var ByteBuffer = require("../dist/bytebuffer-node.js");
  14. var ByteBufferNode = ByteBuffer;
  15. var ByteBufferBrowser = require("../dist/bytebuffer.min.js");
  16. var ByteBufferBrowser_DataView = require("../dist/bytebuffer-dataview.min.js");
  17. var pkg = require("../package.json");
  18. /**
  19. * Constructs a new Sandbox for module loaders and shim testing.
  20. * @param {Object.<string,*>} properties Additional properties to set
  21. * @constructor
  22. */
  23. var Sandbox = function(properties) {
  24. this.Int8Array = function() {};
  25. this.Uint8Array = function() {};
  26. this.Int16Array = function() {};
  27. this.Uint16Array = function() {};
  28. this.Int32Array = function() {};
  29. this.Uint32Array = function() {};
  30. this.Float32Array = function() {};
  31. this.Float64Array = function() {};
  32. this.DataView = function() {};
  33. for (var i in properties) {
  34. this[i] = properties[i];
  35. }
  36. this.console = {
  37. log: function(s) {
  38. console.log(s);
  39. }
  40. };
  41. };
  42. function makeSuite(ByteBuffer) {
  43. var type = ByteBuffer.type(), // Buffer or ArrayBuffer
  44. accessor = ByteBuffer.accessor(),
  45. Long = ByteBuffer.Long;
  46. var suite = {};
  47. suite.init = function(test) {
  48. test.ok(require("../index.js"));
  49. if (ByteBuffer == ByteBufferNode)
  50. test.log("\n\n --- ByteBufferNB ---\n".bold.white),
  51. test.log("[optional] node-memcpy is "+(ByteBuffer.memcpy ? "present" : "not present"));
  52. else if (ByteBuffer == ByteBufferBrowser)
  53. test.log("\n\n --- ByteBufferAB ---\n".bold.white);
  54. else if (ByteBuffer == ByteBufferBrowser_DataView)
  55. test.log("\n\n --- ByteBufferAB_DataView ---\n".bold.white);
  56. test.ok(type === Buffer || type === ArrayBuffer);
  57. test.ok(typeof ByteBuffer == "function");
  58. test.strictEqual(pkg.version, ByteBuffer.VERSION);
  59. test.done();
  60. };
  61. suite.base = {};
  62. suite.base.allocate = function(test) {
  63. var bb = new ByteBuffer();
  64. test.ok(bb.buffer instanceof type);
  65. test.equal(bb.offset, 0);
  66. test.equal(bb.limit, ByteBuffer.DEFAULT_CAPACITY);
  67. test.equal(bb.littleEndian, ByteBuffer.DEFAULT_ENDIAN);
  68. test.equal(bb.noAssert, ByteBuffer.DEFAULT_NOASSERT);
  69. if (type === Buffer)
  70. test.equal(bb.buffer.length, bb.capacity());
  71. else
  72. test.equal(bb.buffer.byteLength, bb.capacity());
  73. test.equal(bb.capacity(), ByteBuffer.DEFAULT_CAPACITY);
  74. bb = ByteBuffer.allocate(undefined, !ByteBuffer.DEFAULT_ENDIAN, !ByteBuffer.DEFAULT_NOASSERT);
  75. test.equal(bb.capacity(), ByteBuffer.DEFAULT_CAPACITY);
  76. test.equal(bb.littleEndian, !ByteBuffer.DEFAULT_ENDIAN);
  77. test.equal(bb.noAssert, !ByteBuffer.DEFAULT_NOASSERT);
  78. // __isByteBuffer__
  79. test.strictEqual(bb.__isByteBuffer__, true);
  80. bb.__isByteBuffer__ = false;
  81. test.strictEqual(bb.__isByteBuffer__, true);
  82. test.equal(ByteBuffer.isByteBuffer(bb), true);
  83. // Fixed set of properties
  84. for (var i in bb)
  85. if (bb.hasOwnProperty(i) && ["offset", "markedOffset", "limit", "littleEndian", "noAssert", "buffer", "view"].indexOf(i) < 0)
  86. test.fail("Illegal enumerable property: "+i);
  87. test.done();
  88. };
  89. suite.base.clone = function(test) {
  90. var bb = new ByteBuffer(1, true, false);
  91. var bb2 = bb.clone();
  92. test.strictEqual(bb.buffer, bb2.buffer);
  93. test.equal(bb.offset, bb2.offset);
  94. test.equal(bb.limit, bb2.limit);
  95. test.equal(bb.markedOffset, bb2.markedOffset);
  96. test.equal(bb.littleEndian, bb2.littleEndian);
  97. test.equal(bb.noAssert, bb2.noAssert);
  98. test.notStrictEqual(bb, bb2);
  99. test.done();
  100. };
  101. suite.base.assert = function(test) {
  102. var bb = new ByteBuffer();
  103. test.strictEqual(bb.noAssert, false);
  104. test.strictEqual(bb.assert(false), bb);
  105. test.strictEqual(bb.noAssert, true);
  106. test.strictEqual(bb.assert(true), bb);
  107. test.strictEqual(bb.noAssert, false);
  108. test.done();
  109. };
  110. suite.wrap = {};
  111. if (type === Buffer) {
  112. suite.wrap.Buffer = function(test) {
  113. var buf = new Buffer(1);
  114. buf[0] = 0x01;
  115. var bb = ByteBuffer.wrap(buf);
  116. test.strictEqual(bb.capacity(), 1);
  117. test.strictEqual(bb.buffer, buf);
  118. test.strictEqual(bb.toDebug(), "<01>");
  119. test.done();
  120. };
  121. }
  122. suite.wrap.ArrayBuffer = function(test) {
  123. var buf = new ArrayBuffer(1);
  124. var bb = ByteBuffer.wrap(buf);
  125. test.strictEqual(bb.capacity(), 1);
  126. if (type === ArrayBuffer)
  127. test.strictEqual(bb.buffer, buf);
  128. else
  129. test.ok(bb.buffer instanceof Buffer);
  130. test.equal(bb.offset, 0);
  131. test.equal(bb.limit, 1);
  132. test.done();
  133. };
  134. suite.wrap.Uint8Array = function(test) {
  135. // Full view
  136. var buf = new Uint8Array(1);
  137. buf[0] = 0x01;
  138. var bb = ByteBuffer.wrap(buf);
  139. test.strictEqual(bb.capacity(), 1);
  140. if (type === ArrayBuffer)
  141. test.strictEqual(bb.buffer, buf.buffer);
  142. else
  143. test.ok(bb.buffer instanceof Buffer);
  144. test.strictEqual(bb.toDebug(), "<01>");
  145. // Partial view (not on node, node copies)
  146. if (type === ArrayBuffer) {
  147. buf = new Uint8Array(3);
  148. buf[0] = 0x01; buf[1] = 0x02; buf[2] = 0x03;
  149. buf = new Uint8Array(buf.buffer, 1, 1);
  150. bb = ByteBuffer.wrap(buf);
  151. test.strictEqual(bb.capacity(), 3);
  152. test.strictEqual(bb.toDebug(), "01<02>03");
  153. }
  154. test.done();
  155. };
  156. suite.wrap.Array = function(test) {
  157. var arr = [1,255,-1];
  158. var bb = ByteBuffer.wrap(arr);
  159. test.strictEqual(bb.capacity(), 3);
  160. test.strictEqual(bb.toDebug(), "<01 FF FF>");
  161. test.done();
  162. };
  163. suite.wrap.ByteBuffer = function(test) {
  164. var bb2 = ByteBuffer.wrap("\x12\x34\x56\x78", "binary");
  165. bb2.offset = 1;
  166. var bb = ByteBuffer.wrap(bb2);
  167. test.strictEqual(bb2.offset, bb.offset);
  168. test.strictEqual(bb2.limit, bb.limit);
  169. test.strictEqual(bb2.capacity(), bb.capacity());
  170. test.strictEqual(bb2.toString("debug"), bb.toString("debug"));
  171. test.done();
  172. };
  173. suite.wrap.string = function(test) {
  174. var bb = ByteBuffer.wrap("\u0061\u0062");
  175. test.equal(bb.toDebug(), "<61 62>");
  176. test.done();
  177. };
  178. suite.encodings = {};
  179. suite.encodings.UTF8 = function(test) {
  180. ["aäöü߀b", ""].forEach(function(str) {
  181. var bb = ByteBuffer.wrap(str, "utf8"); // Calls ByteBuffer#fromUTF8
  182. test.strictEqual(bb.toUTF8(), str);
  183. if (str.length > 2) {
  184. bb.offset = 1;
  185. bb.limit = bb.capacity()-1;
  186. test.strictEqual(bb.toUTF8(), str.substring(1, str.length-1));
  187. }
  188. });
  189. test.done();
  190. };
  191. suite.encodings.debug = function(test) {
  192. ["60<61 62]63", "<60 61 62 63]", "|", "|61", "<61>", "!12"].forEach(function(str) {
  193. var bb = ByteBuffer.wrap(str, "debug"); // Calls ByteBuffer#fromDebug
  194. test.equal(bb.toDebug(), str);
  195. });
  196. test.done();
  197. };
  198. suite.encodings.binary = function(test) {
  199. ["\x61\x62\x63\x64", "", " "].forEach(function(str) {
  200. var bb = ByteBuffer.wrap(str, "binary"); // Calls ByteBuffer#fromBinary
  201. test.strictEqual(bb.toBinary(), str);
  202. if (str.length > 2) {
  203. bb.offset = 1;
  204. bb.limit = bb.capacity()-1;
  205. test.strictEqual(bb.toBinary(), str.substring(1, str.length-1));
  206. }
  207. });
  208. test.done();
  209. };
  210. suite.encodings.hex = function(test) {
  211. ["61626364", "61", ""].forEach(function(str) {
  212. var bb = ByteBuffer.wrap(str, "hex"); // Calls ByteBuffer#fromHex
  213. test.strictEqual(bb.toHex(), str);
  214. if (str.length > 2) {
  215. bb.offset = 1;
  216. bb.limit = bb.capacity()-1;
  217. test.strictEqual(bb.toHex(), str.substring(2, str.length-2));
  218. }
  219. });
  220. test.done();
  221. };
  222. suite.encodings.base64 = function(test) {
  223. ["", "YWI=", "YWJjZGVmZw==", "YWJjZGVmZ2g=", "YWJjZGVmZ2hp"].forEach(function(str) {
  224. var bb = ByteBuffer.wrap(str, "base64"); // Calls ByteBuffer#fromBase64
  225. test.strictEqual(bb.toBase64(), str);
  226. if (str.length > 8) {
  227. bb.offset = 3;
  228. bb.limit = bb.offset + 3;
  229. test.strictEqual(bb.toBase64(), str.substr(4, 4));
  230. }
  231. });
  232. test.done();
  233. };
  234. suite.methods = {};
  235. suite.methods.concat = function(test) {
  236. var bbs = [
  237. new ArrayBuffer(1),
  238. ByteBuffer.fromDebug('00<01 02>'),
  239. ByteBuffer.fromDebug('00 01 02<03>00'),
  240. ByteBuffer.fromDebug('00|'),
  241. ByteBuffer.fromDebug('<04>'),
  242. type === Buffer ? new Buffer(0) : new ArrayBuffer(0),
  243. new Uint8Array(0),
  244. '05'
  245. ];
  246. var bb = ByteBuffer.concat(bbs, 'hex', !ByteBuffer.DEFAULT_ENDIAN, !ByteBuffer.DEFAULT_NOASSERT);
  247. test.strictEqual(bb.littleEndian, !ByteBuffer.DEFAULT_ENDIAN);
  248. test.strictEqual(bb.noAssert, !ByteBuffer.DEFAULT_NOASSERT);
  249. test.equal(bb.toDebug(), '<00 01 02 03 04 05>');
  250. bb = ByteBuffer.concat([]);
  251. test.strictEqual(bb.buffer, new ByteBuffer(0).buffer); // EMPTY_BUFFER
  252. test.done();
  253. };
  254. suite.methods.resize = function(test) {
  255. var bb = new ByteBuffer(1);
  256. bb.offset = 1;
  257. bb.resize(2);
  258. bb.fill(0, 0, 2);
  259. test.equal(bb.capacity(), 2);
  260. test.equal(bb.toDebug(), "00|00");
  261. test.done();
  262. };
  263. suite.methods.ensureCapacity = function(test) {
  264. var bb = new ByteBuffer(5);
  265. test.equal(bb.capacity(), 5);
  266. bb.ensureCapacity(6); // Doubles
  267. test.equal(bb.capacity(), 10);
  268. bb.ensureCapacity(21); // Uses 21
  269. test.equal(bb.capacity(), 21);
  270. test.done();
  271. };
  272. suite.methods.slice = function(test) {
  273. var bb = new ByteBuffer.wrap("\x12\x34\x56"),
  274. bb2 = bb.slice(1,2);
  275. test.strictEqual(bb.buffer, bb2.buffer);
  276. test.equal(bb.offset, 0);
  277. test.equal(bb.limit, 3);
  278. test.equal(bb2.offset, 1);
  279. test.equal(bb2.limit, 2);
  280. test.done();
  281. };
  282. suite.methods.flip = function(test) {
  283. var bb = ByteBuffer.wrap('\x12\x34\x56\x78');
  284. bb.offset = 4;
  285. test.equal(bb.offset, 4);
  286. test.equal(bb.limit, 4);
  287. bb.flip();
  288. test.equal(bb.offset, 0);
  289. test.equal(bb.limit, 4);
  290. test.done();
  291. };
  292. suite.methods.mark = function(test) {
  293. var bb = ByteBuffer.wrap('\x12\x34\x56\x78');
  294. test.equal(bb.offset, 0);
  295. test.equal(bb.limit, 4);
  296. test.equal(bb.markedOffset, -1);
  297. bb.mark();
  298. test.equal(bb.markedOffset, 0);
  299. test.done();
  300. };
  301. suite.methods.reset = function(test) {
  302. var bb = ByteBuffer.wrap('\x12\x34\x56\x78');
  303. bb.reset();
  304. test.equal(bb.offset, 0);
  305. test.equal(bb.limit, 4);
  306. bb.offset = 1;
  307. bb.mark();
  308. test.equal(bb.markedOffset, 1);
  309. bb.reset();
  310. test.equal(bb.offset, 1);
  311. test.equal(bb.markedOffset, -1);
  312. test.done();
  313. };
  314. suite.methods.copy = function(test) {
  315. var bb = ByteBuffer.wrap("\x01", !ByteBuffer.DEFAULT_ENDIAN),
  316. bb2 = bb.copy();
  317. test.equal(bb.offset, 0);
  318. test.notStrictEqual(bb, bb2);
  319. test.notStrictEqual(bb.buffer, bb2.buffer);
  320. test.equal(bb2.offset, bb.offset);
  321. test.equal(bb2.limit, bb.limit);
  322. test.equal(bb2.markedOffset, bb.markedOffset);
  323. test.equal(bb2.littleEndian, bb.littleEndian);
  324. test.equal(bb2.noAssert, bb.noAssert);
  325. test.done();
  326. };
  327. suite.methods.copyTo = function(test) {
  328. var bb = ByteBuffer.wrap("\x01"),
  329. bb2 = new ByteBuffer(2).fill(0).flip();
  330. test.equal(bb.toDebug(), "<01>");
  331. // Modifies source and target offsets
  332. bb.copyTo(bb2 /* all offsets omitted */);
  333. test.equal(bb.toDebug(), "01|"); // Read 1 byte
  334. test.equal(bb2.toDebug(), "01<00>"); // Written 1 byte
  335. bb.reset();
  336. test.equal(bb.toDebug(), "<01>");
  337. // Again, but with bb2.offset=1
  338. bb.copyTo(bb2 /* all offsets omitted */);
  339. test.equal(bb.toDebug(), "01|"); // Read 1 byte
  340. test.equal(bb2.toDebug(), "01 01|"); // Written 1 byte at 2
  341. bb.reset();
  342. bb2.clear().fill(0).flip();
  343. // Modifies source offsets only
  344. bb.copyTo(bb2, 0 /* source offsets omitted */);
  345. test.equal(bb.toDebug(), "01|"); // Read 1 byte
  346. test.equal(bb2.toDebug(), "<01 00>"); // Written 1 byte (no change)
  347. // Modifies no offsets at all
  348. bb.reset();
  349. bb2.fill(0).flip();
  350. bb.copyTo(bb2, 1, 0, bb.capacity() /* no offsets omitted */);
  351. test.equal(bb.toDebug(), "<01>"); // Read 1 byte (no change)
  352. test.equal(bb2.toDebug(), "<00 01>"); // Written 1 byte (no change)
  353. test.done();
  354. };
  355. suite.methods.compact = function(test) {
  356. var bb = ByteBuffer.wrap("\x01\x02");
  357. bb.limit = 1;
  358. bb.markedOffset = 2;
  359. var prevBuffer = bb.buffer,
  360. prevView = bb.view;
  361. bb.compact();
  362. test.notStrictEqual(bb.buffer, prevBuffer);
  363. if (type === ArrayBuffer) {
  364. test.notStrictEqual(bb.buffer, prevView);
  365. }
  366. test.equal(bb.capacity(), 1);
  367. test.equal(bb.offset, 0);
  368. test.equal(bb.limit, 1);
  369. test.equal(bb.markedOffset, 2); // Actually out of bounds
  370. // Empty region
  371. bb.offset = 1;
  372. prevBuffer = bb.buffer;
  373. bb.compact();
  374. test.notStrictEqual(bb.buffer, prevBuffer);
  375. test.strictEqual(bb.buffer, new ByteBuffer(0).buffer); // EMPTY_BUFFER
  376. if (type === ArrayBuffer) {
  377. test.strictEqual(bb.view, null);
  378. }
  379. test.equal(bb.capacity(), 0);
  380. test.equal(bb.offset, 0);
  381. test.equal(bb.limit, 0);
  382. test.done();
  383. };
  384. suite.methods.reverse = function(test) {
  385. var bb = ByteBuffer.wrap("\x12\x34\x56\x78");
  386. bb.reverse(1, 3);
  387. test.equal(bb.toString("debug"), "<12 56 34 78>");
  388. bb.reverse();
  389. test.equal(bb.toString("debug"), "<78 34 56 12>");
  390. bb.offset = 1;
  391. bb.limit = 3;
  392. bb.reverse();
  393. test.equal(bb.toString("debug"), "78<56 34>12");
  394. bb.reverse(0, 4).clear();
  395. test.equal(bb.toString("debug"), "<12 34 56 78>");
  396. test.done();
  397. };
  398. suite.methods.append = function(test) {
  399. var bb = ByteBuffer.wrap("\x12\x34");
  400. var bb2 = ByteBuffer.wrap("\x56\x78");
  401. bb.offset = 2;
  402. bb.append(bb2); // Modifies offsets of both
  403. test.equal(bb.toString("debug"), "12 34>56 78<");
  404. test.equal(bb2.toString("debug"), "56 78|");
  405. bb2.reset();
  406. bb.append(bb2, 1); // Modifies offsets of bb2 only
  407. test.equal(bb.toString("debug"), "12 56>78 78<");
  408. test.equal(bb2.toString("debug"), "56 78|");
  409. test.done();
  410. };
  411. suite.methods.prepend = function(test) {
  412. var bb = ByteBuffer.wrap("\x12\x34"),
  413. bb2 = ByteBuffer.wrap("\x56\x78");
  414. test.strictEqual(bb.prepend(bb2), bb); // Relative prepend at 0, 2 bytes (2 overflow)
  415. test.equal(bb.toDebug(), "<56 78 12 34>");
  416. test.equal(bb2.toDebug(), "56 78|");
  417. bb.offset = 4;
  418. bb2.offset = 1;
  419. bb.prepend(bb2, 3); // Absolute prepend at 3, 1 byte
  420. test.equal(bb.toDebug(), "56 78 78 34|");
  421. test.equal(bb2.toDebug(), "56 78|");
  422. bb2.offset = 0;
  423. bb.prepend(bb2); // Relative prepend at 4, 2 bytes
  424. test.equal(bb.toDebug(), "56 78<56 78>");
  425. test.equal(bb2.toDebug(), "56 78|");
  426. bb.offset = 3;
  427. bb2.offset = 0;
  428. test.throws(function() {
  429. bb.prepend(bb2, 6); // Absolute out of bounds
  430. }, RangeError);
  431. bb.prepend("abcde", "utf8"); // Relative prepend at 3, 5 bytes (1 overflow)
  432. test.equal(bb.toDebug(), "<61 62 63 64 65 78>");
  433. test.done();
  434. };
  435. suite.methods.prependTo = function(test) {
  436. var bb = ByteBuffer.wrap("\x12\x34"),
  437. bb2 = ByteBuffer.wrap("\x56\x78");
  438. test.strictEqual(bb2.prependTo(bb), bb2);
  439. test.equal(bb.toDebug(), "<56 78 12 34>");
  440. test.equal(bb2.toDebug(), "56 78|");
  441. test.done();
  442. };
  443. suite.methods.remaining = function(test) {
  444. var bb = ByteBuffer.wrap("\x12\x34");
  445. test.strictEqual(bb.remaining(), 2);
  446. bb.offset = 2;
  447. test.strictEqual(bb.remaining(), 0);
  448. bb.offset = 3;
  449. test.strictEqual(bb.remaining(), -1);
  450. test.done();
  451. };
  452. suite.methods.skip = function(test) {
  453. var bb = ByteBuffer.wrap("\x12\x34\x56");
  454. test.strictEqual(bb.offset, 0);
  455. bb.skip(3);
  456. test.strictEqual(bb.offset, 3);
  457. test.strictEqual(bb.noAssert, false);
  458. test.throws(function() {
  459. bb.skip(1);
  460. });
  461. test.strictEqual(bb.offset, 3);
  462. bb.noAssert = true;
  463. test.doesNotThrow(function() {
  464. bb.skip(1);
  465. });
  466. test.strictEqual(bb.offset, 4);
  467. test.done();
  468. };
  469. suite.methods.order = function(test) {
  470. test.strictEqual(ByteBuffer.LITTLE_ENDIAN, true);
  471. test.strictEqual(ByteBuffer.BIG_ENDIAN, false);
  472. var bb = new ByteBuffer(2);
  473. test.strictEqual(bb.littleEndian, false);
  474. bb.writeInt32(0x12345678);
  475. bb.flip();
  476. test.strictEqual(bb.toHex(), "12345678");
  477. bb.clear();
  478. test.strictEqual(bb.LE(), bb);
  479. test.strictEqual(bb.littleEndian, true);
  480. bb.writeInt32(0x12345678);
  481. bb.flip();
  482. test.strictEqual(bb.toHex(), "78563412");
  483. test.strictEqual(bb.BE(), bb);
  484. test.strictEqual(bb.littleEndian, false);
  485. test.strictEqual(bb.order(ByteBuffer.LITTLE_ENDIAN), bb);
  486. test.strictEqual(bb.littleEndian, true);
  487. test.strictEqual(bb.order(ByteBuffer.BIG_ENDIAN), bb);
  488. test.strictEqual(bb.littleEndian, false);
  489. test.done();
  490. };
  491. var types = [
  492. // name | alias | size | input | output | BE representation
  493. ["Int8" , "Byte" , 1 , 0xFE , -2 , "fe" ],
  494. ["Uint8" , null , 1 , -2 , 0xFE , "fe" ],
  495. ["Int16" , "Short" , 2 , 0xFFFE , -2 , "fffe" ],
  496. ["Uint16" , null , 2 , -2 , 0xFFFE , "fffe" ],
  497. ["Int32" , "Int" , 4 , 0xFFFFFFFE , -2 , "fffffffe" ],
  498. ["Uint32" , null , 4 , -2 , 0xFFFFFFFE , "fffffffe" ],
  499. ["Float32" , "Float" , 4 , 0.5 , 0.5 , "3f000000" ],
  500. ["Float64" , "Double", 8 , 0.1 , 0.1 , "3fb999999999999a" ],
  501. ["Int64" , "Long" , 8 , new Long(0xFFFFFFFE, 0xFFFFFFFF, true) , new Long(0xFFFFFFFE, 0xFFFFFFFF, false) , "fffffffffffffffe" ],
  502. ["Uint64" , null , 8 , new Long(0xFFFFFFFE, 0xFFFFFFFF, false) , new Long(0xFFFFFFFE, 0xFFFFFFFF, true) , "fffffffffffffffe" ],
  503. // name | alias | size | input | output | representation
  504. ["Varint32" , null , 5 , 0xFFFFFFFE , -2 , "feffffff0f" ],
  505. ["Varint32ZigZag", null , 1 , -1 , -1 , "01" ],
  506. ["Varint64" , null , 10 , new Long(0xFFFFFFFE, 0xFFFFFFFF, true) , new Long(0xFFFFFFFE, 0xFFFFFFFF, false) , "feffffffffffffffff01"],
  507. ["Varint64ZigZag", null , 1 , Long.fromNumber(-1) , Long.fromNumber(-1) , "01" ]
  508. ];
  509. suite.types = {};
  510. types.forEach(function(type) {
  511. var name = type[0],
  512. varint = name.indexOf("Varint") >= 0,
  513. alias = type[1],
  514. size = type[2],
  515. input = type[3],
  516. output = type[4],
  517. be = type[5],
  518. le = "";
  519. for (var i=be.length; i>0; i-=2) {
  520. le += be.substr(i-2, 2);
  521. }
  522. suite.types[name.toLowerCase()] = function(test) {
  523. var bb = new ByteBuffer(size);
  524. // Relative BE (always LE for varints)
  525. test.strictEqual(bb["write"+name](input), bb);
  526. bb.flip();
  527. var val = bb["read"+name]();
  528. if (output instanceof Long) {
  529. test.deepEqual(val, output);
  530. } else {
  531. test.strictEqual(val, output);
  532. }
  533. bb.flip();
  534. test.strictEqual(bb.toHex(), be);
  535. if (!varint) {
  536. // Relative LE
  537. bb.LE();
  538. bb["write"+name](input);
  539. bb.flip();
  540. val = bb["read"+name]();
  541. if (output instanceof Long) {
  542. test.deepEqual(val, output);
  543. } else {
  544. test.strictEqual(val, output);
  545. }
  546. bb.flip();
  547. test.strictEqual(bb.toHex(), le);
  548. }
  549. test.throws(function() { // OOB
  550. bb.offset = bb.capacity() - size + 1;
  551. bb["read"+name](input);
  552. });
  553. test.doesNotThrow(function() { // OOB, automatic resizing * 2
  554. bb["write"+name](input);
  555. });
  556. test.strictEqual(bb.capacity(), size * 2);
  557. // Absolute
  558. bb.clear();
  559. if (!varint)
  560. test.strictEqual(bb["write"+name](input, 1), bb);
  561. else
  562. test.strictEqual(bb["write"+name](input, 1), size);
  563. val = bb["read"+name](1);
  564. if (output instanceof Long) {
  565. if (!varint)
  566. test.deepEqual(val, output);
  567. else
  568. test.deepEqual(val, {value: output, length: size});
  569. } else {
  570. if (!varint)
  571. test.strictEqual(val, output);
  572. else
  573. test.deepEqual(val, {value: output, length: size});
  574. }
  575. // Alias
  576. if (alias) {
  577. test.strictEqual(bb["write"+name], bb["write"+alias]);
  578. test.strictEqual(bb["read"+name], bb["read"+alias]);
  579. }
  580. test.done();
  581. };
  582. });
  583. suite.types.bitset = function(test) {
  584. var bb = new ByteBuffer(2),
  585. arr;
  586. function run(data) {
  587. bb.reset();
  588. bb.writeBitSet(data);
  589. bb.reset();
  590. test.deepEqual(bb.readBitSet(),data);
  591. };
  592. run([]);
  593. run([true]);
  594. run([false]);
  595. run([false,true]);
  596. run([false,false,false,false,false,false,false,false]);
  597. run([true,false,true,false,true,false,true,false]);
  598. run([true,true,true,true,true,true,true,true]);
  599. run([true,false,true,false,true,false,true,false]);
  600. run([true,false,true,false,true,false,true,false,true]);
  601. bb.reset();
  602. bb.writeBitSet([,null,"",0,42,"hello world",new Date(0),{},[]]);
  603. bb.reset();
  604. test.deepEqual(bb.readBitSet(),[false,false,false,false,true,true,true,true,true]);
  605. test.done();
  606. };
  607. suite.types.calculateVarint = function(test) {
  608. test.equal(ByteBuffer.MAX_VARINT32_BYTES, 5);
  609. test.equal(ByteBuffer.MAX_VARINT64_BYTES, 10);
  610. var values = [
  611. [0, 1],
  612. [-1, 5, 10],
  613. [1<<7, 2],
  614. [1<<14, 3],
  615. [1<<21, 4],
  616. [1<<28, 5],
  617. [0x7FFFFFFF | 0, 5],
  618. [0xFFFFFFFF, 5],
  619. [0xFFFFFFFF | 0, 5, 10]
  620. ];
  621. for (var i=0; i<values.length; i++) {
  622. test.equal(ByteBuffer.calculateVarint32(values[i][0]), values[i][1]);
  623. test.equal(ByteBuffer.calculateVarint64(values[i][0]), values[i].length > 2 ? values[i][2] : values[i][1]);
  624. }
  625. var Long = ByteBuffer.Long;
  626. values = [
  627. [Long.fromNumber(1).shiftLeft(35), 6],
  628. [Long.fromNumber(1).shiftLeft(42), 7],
  629. [Long.fromNumber(1).shiftLeft(49), 8],
  630. [Long.fromNumber(1).shiftLeft(56), 9],
  631. [Long.fromNumber(1).shiftLeft(63), 10],
  632. [Long.fromNumber(1, true).shiftLeft(63), 10]
  633. ];
  634. for (i=0; i<values.length; i++) {
  635. test.equal(ByteBuffer.calculateVarint64(values[i][0]), values[i][1]);
  636. }
  637. test.done();
  638. };
  639. suite.types.zigZagVarint = function(test) {
  640. var Long = ByteBuffer.Long;
  641. var values = [
  642. [ 0, 0],
  643. [-1, 1],
  644. [ 1, 2],
  645. [-2, 3],
  646. [ 2, 4],
  647. [-3, 5],
  648. [ 3, 6],
  649. [ 2147483647, 4294967294],
  650. [-2147483648, 4294967295]
  651. ];
  652. for (var i=0; i<values.length; i++) {
  653. test.equal(ByteBuffer.zigZagEncode32(values[i][0]), values[i][1]);
  654. test.equal(ByteBuffer.zigZagDecode32(values[i][1]), values[i][0]);
  655. test.equal(ByteBuffer.zigZagEncode64(values[i][0]).toNumber(), values[i][1]);
  656. test.equal(ByteBuffer.zigZagDecode64(values[i][1]).toNumber(), values[i][0]);
  657. }
  658. values = [
  659. [Long.MAX_VALUE, Long.MAX_UNSIGNED_VALUE.subtract(Long.ONE)],
  660. [Long.MIN_VALUE, Long.MAX_UNSIGNED_VALUE]
  661. ];
  662. // NOTE: Even 64bit doubles from toNumber() fail for these values so we are using toString() here
  663. for (i=0; i<values.length; i++) {
  664. test.equal(ByteBuffer.zigZagEncode64(values[i][0]).toString(), values[i][1].toString());
  665. test.equal(ByteBuffer.zigZagDecode64(values[i][1]).toString(), values[i][0].toString());
  666. }
  667. // 32 bit ZZ
  668. values = [
  669. 0,
  670. 1,
  671. 300,
  672. -300,
  673. 2147483647,
  674. -2147483648
  675. ];
  676. bb = new ByteBuffer(10);
  677. for (i=0; i<values.length; i++) {
  678. var encLen = bb.writeVarint32ZigZag(values[i], 0);
  679. bb.limit = encLen;
  680. var dec = bb.readVarint32ZigZag(0);
  681. test.equal(dec['value'], values[i]);
  682. test.equal(encLen, dec['length']);
  683. bb.clear();
  684. }
  685. // 64 bit ZZ
  686. values = [
  687. Long.ONE, 1,
  688. Long.fromNumber(-3),
  689. Long.fromNumber(300),
  690. Long.fromNumber(-300),
  691. Long.fromNumber(0x7FFFFFFF),
  692. Long.fromNumber(0x8FFFFFFF),
  693. Long.fromNumber(0xFFFFFFFF),
  694. Long.fromBits(0xFFFFFFFF, 0x7FFFFFFF),
  695. Long.fromBits(0xFFFFFFFF, 0xFFFFFFFF)
  696. ];
  697. var bb = new ByteBuffer(10);
  698. for (i=0; i<values.length; i++) {
  699. encLen = bb.writeVarint64ZigZag(values[i], 0);
  700. dec = bb.readVarint64ZigZag(0);
  701. test.equal(values[i].toString(), dec['value'].toString());
  702. test.equal(encLen, dec['length']);
  703. }
  704. test.done();
  705. };
  706. suite.types.utf8string = function(test) {
  707. var bb = new ByteBuffer(2);
  708. // Aliases
  709. test.strictEqual(bb.writeUTF8String, bb.writeString);
  710. test.strictEqual(bb.readUTF8String, bb.readString);
  711. var str = "ä☺𠜎️☁️", str2;
  712. // Writing
  713. test.strictEqual(bb.writeUTF8String(str), bb);
  714. bb.flip();
  715. // bb.printDebug();
  716. // Reading
  717. str2 = bb.readUTF8String(ByteBuffer.calculateUTF8Chars(str), ByteBuffer.METRICS_CHARS);
  718. // bb.printDebug();
  719. test.strictEqual(str2.length, str.length);
  720. test.strictEqual(str2, str);
  721. bb.reset();
  722. str2 = bb.readUTF8String(bb.limit, ByteBuffer.METRICS_BYTES);
  723. test.strictEqual(str2, str);
  724. test.done();
  725. };
  726. suite.types.istring = function(test) {
  727. var bb = new ByteBuffer(2);
  728. test.strictEqual(bb.writeIString("ab"), bb); // resizes to 4+2=6
  729. test.strictEqual(bb.capacity(), 6);
  730. test.strictEqual(bb.offset, 6);
  731. test.strictEqual(bb.limit, 2);
  732. bb.flip();
  733. test.equal(bb.toString("debug"), "<00 00 00 02 61 62>");
  734. test.deepEqual(bb.readIString(0), {"string": "ab", "length": 6});
  735. test.strictEqual(bb.readIString(), "ab");
  736. bb.reset();
  737. test.equal(bb.toString("debug"), "<00 00 00 02 61 62>");
  738. test.strictEqual(bb.readIString(), "ab");
  739. test.equal(bb.toString("debug"), "00 00 00 02 61 62|");
  740. test.done();
  741. };
  742. suite.types.vstring = function(test) {
  743. var bb = new ByteBuffer(2);
  744. bb.writeVString("ab"); // resizes to 2*2=4
  745. test.strictEqual(bb.capacity(), 4);
  746. test.strictEqual(bb.offset, 3);
  747. test.strictEqual(bb.limit, 2);
  748. bb.flip();
  749. test.equal(bb.toString("debug").substr(0, 10), "<02 61 62>");
  750. test.deepEqual(bb.readVString(0), {"string": "ab", "length": 3});
  751. test.equal(bb.toString("debug").substr(0, 10), "<02 61 62>");
  752. test.equal(bb.readVString(), "ab");
  753. test.equal(bb.toString("debug").substr(0, 9), "02 61 62|");
  754. test.done();
  755. };
  756. suite.types.cstring = function(test) {
  757. var bb = new ByteBuffer(2);
  758. bb.writeCString("a");
  759. test.equal(bb.capacity(), 2);
  760. test.equal(bb.offset, 2);
  761. test.equal(bb.limit, 2);
  762. bb.offset = 1;
  763. bb.writeCString("b"); // resizes to 4
  764. test.equal(bb.capacity(), 4);
  765. test.equal(bb.offset, 3);
  766. test.equal(bb.limit, 2);
  767. bb.flip();
  768. test.equal(bb.toString("debug").substr(0, 10), "<61 62 00>");
  769. test.deepEqual(bb.readCString(0), {"string": "ab", "length": 3});
  770. test.equal(bb.toString("debug").substr(0, 10), "<61 62 00>");
  771. test.equal(bb.readCString(), "ab");
  772. test.equal(bb.toString("debug").substr(0, 9), "61 62 00|");
  773. test.done();
  774. };
  775. suite.convert = {};
  776. suite.convert.toHex = function(test) {
  777. var bb = new ByteBuffer(4);
  778. bb.writeUint16(0x1234);
  779. bb.writeUint8(0x56);
  780. bb.flip();
  781. test.equal(bb.toHex(), "123456");
  782. test.strictEqual(bb.offset, 0);
  783. test.equal(bb.toHex(1), "3456");
  784. test.equal(bb.toHex(1,2), "34");
  785. test.equal(bb.toHex(1,1), "");
  786. test.throws(function() {
  787. bb.toHex(1,0);
  788. });
  789. test.done();
  790. };
  791. suite.convert.toBase64 = function(test) {
  792. var bb = new ByteBuffer(8);
  793. bb.writeUTF8String("abcdefg"); // 7 chars
  794. bb.flip();
  795. test.equal(bb.toBase64(), "YWJjZGVmZw==");
  796. test.strictEqual(bb.offset, 0);
  797. test.equal(bb.toBase64(3), "ZGVmZw==");
  798. test.equal(bb.toBase64(3,6), "ZGVm");
  799. test.equal(bb.toBase64(3,3), "");
  800. test.throws(function() {
  801. bb.toBase64(1,0);
  802. });
  803. test.done();
  804. };
  805. suite.convert.toBinary = function(test) {
  806. var bb = new ByteBuffer(5);
  807. bb.writeUint32(0x001234FF);
  808. bb.flip();
  809. test.strictEqual(bb.toBinary(), "\x00\x12\x34\xFF");
  810. test.strictEqual(bb.offset, 0);
  811. test.done();
  812. };
  813. suite.convert.toString = function(test) {
  814. var bb = new ByteBuffer(3);
  815. bb.writeUint16(0x6162).flip();
  816. test.equal(bb.toString("hex"), "6162");
  817. test.equal(bb.toString("base64"), "YWI=");
  818. test.equal(bb.toString("utf8"), "ab");
  819. test.equal(bb.toString("debug").substr(0,7), "<61 62>");
  820. test.equal(bb.toString(), (type === ArrayBuffer ? (accessor === DataView ? "ByteBufferAB_DataView" : "ByteBufferAB") : "ByteBufferNB")+"(offset=0,markedOffset=-1,limit=2,capacity=3)");
  821. test.strictEqual(bb.offset, 0);
  822. test.done();
  823. };
  824. suite.convert.toBuffer = function(test) {
  825. var bb = new ByteBuffer(2);
  826. bb.writeUint16(0x1234).flip();
  827. var buf = bb.toBuffer();
  828. test.strictEqual(buf, bb.buffer);
  829. if (type === ArrayBuffer) {
  830. test.ok(buf instanceof ArrayBuffer);
  831. test.strictEqual(buf.byteLength, 2);
  832. } else {
  833. test.ok(buf instanceof Buffer);
  834. test.strictEqual(buf.length, 2);
  835. }
  836. bb.limit = 1;
  837. buf = bb.toBuffer();
  838. test.notStrictEqual(buf, bb.buffer);
  839. if (type === ArrayBuffer) {
  840. test.ok(buf instanceof ArrayBuffer);
  841. test.strictEqual(buf.byteLength, 1);
  842. } else {
  843. test.ok(buf instanceof Buffer);
  844. test.strictEqual(buf.length, 1);
  845. }
  846. test.done();
  847. };
  848. suite.convert.toArrayBuffer = function(test) {
  849. var bb = new ByteBuffer(3);
  850. if (type === ArrayBuffer) {
  851. test.strictEqual(bb.toArrayBuffer, bb.toBuffer);
  852. } else {
  853. test.ok(bb.buffer instanceof Buffer);
  854. bb.writeUint16(0x1234);
  855. bb.flip();
  856. bb.offset = 1;
  857. var ab = bb.toArrayBuffer();
  858. test.ok(ab instanceof ArrayBuffer);
  859. test.strictEqual(ab.byteLength, 1);
  860. }
  861. test.done();
  862. };
  863. suite.misc = {};
  864. suite.misc.pbjsi19 = function(test) {
  865. // test that this issue is fixed: https://github.com/dcodeIO/ProtoBuf.js/issues/19
  866. var bb = new ByteBuffer(9); // Trigger resize to 18 in writeVarint64
  867. bb.writeVarint32(16);
  868. bb.writeVarint32(2);
  869. bb.writeVarint32(24);
  870. bb.writeVarint32(0);
  871. bb.writeVarint32(32);
  872. bb.writeVarint64(ByteBuffer.Long.fromString("1368057600000"));
  873. bb.writeVarint32(40);
  874. bb.writeVarint64(ByteBuffer.Long.fromString("1235455123"));
  875. bb.flip();
  876. test.equal(bb.toString("debug").substr(0,52), "<10 02 18 00 20 80 B0 D9 B4 E8 27 28 93 99 8E CD 04>");
  877. test.done();
  878. };
  879. suite.misc.NaN = function(test) {
  880. var bb = new ByteBuffer(4);
  881. test.ok(isNaN(bb.writeFloat(NaN).flip().readFloat(0)));
  882. test.strictEqual(bb.writeFloat(+Infinity).flip().readFloat(0), +Infinity);
  883. test.strictEqual(bb.writeFloat(-Infinity).flip().readFloat(0), -Infinity);
  884. bb.resize(8);
  885. test.ok(isNaN(bb.writeDouble(NaN).flip().readDouble(0)));
  886. test.strictEqual(bb.writeDouble(+Infinity).flip().readDouble(0), +Infinity);
  887. test.strictEqual(bb.writeDouble(-Infinity).flip().readDouble(0), -Infinity);
  888. // Varints, however, always need a cast, which results in the following:
  889. test.strictEqual(NaN >>> 0, 0);
  890. test.strictEqual(NaN | 0, 0);
  891. test.strictEqual(Infinity >>> 0, 0);
  892. test.strictEqual(Infinity | 0, 0);
  893. test.strictEqual(-Infinity >>> 0, 0);
  894. test.strictEqual(-Infinity | 0, 0);
  895. test.done();
  896. };
  897. suite.debug = {};
  898. suite.debug.printDebug = function(test) {
  899. var bb = new ByteBuffer(3);
  900. function callMe() { callMe.called = true; }
  901. bb.printDebug(callMe);
  902. test.ok(callMe.called);
  903. test.done();
  904. };
  905. if (type === ArrayBuffer) {
  906. suite.debug.printDebugVisual = function(test) {
  907. var bb = ByteBuffer.wrap("Hello world! from byteBuffer.js. This is just a last visual test of ByteBuffer#printDebug.");
  908. console.log("");
  909. bb.printDebug(console.log);
  910. test.done();
  911. };
  912. }
  913. return suite;
  914. }
  915. module.exports = {
  916. "info": function(test) {
  917. test.log("Version "+ByteBuffer.VERSION+", "+new Date().toISOString()+"\n");
  918. test.done();
  919. },
  920. "node": makeSuite(ByteBufferNode),
  921. "browser": makeSuite(ByteBufferBrowser),
  922. "dataview": makeSuite(ByteBufferBrowser_DataView)
  923. };