browser.test.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
  2. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  3. return new (P || (P = Promise))(function (resolve, reject) {
  4. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  5. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  6. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  7. step((generator = generator.apply(thisArg, _arguments || [])).next());
  8. });
  9. };
  10. import { expect } from 'chai.js';
  11. import { mkdirSync, writeFileSync } from 'fs.js';
  12. import { createServer } from 'http.js';
  13. import { tmpdir } from 'os.js';
  14. import { resolve } from 'path.js';
  15. import puppeteer from 'puppeteer.js';
  16. import handler from 'serve-handler.js';
  17. import webpack from 'webpack.js';
  18. import { hello48, inputs, ogTestVectors } from './base/test-helpers.js';
  19. // Much of the browser code is also used in Node's wasm. We test things more
  20. // thoroughly there because tests are easier to write and debug, these tests
  21. // are primarily for sanity and checking browser-specific behavior.
  22. describe('browser', () => {
  23. const addInputs = `window.inputs = ${JSON.stringify(inputs)}`;
  24. describe('webpack', () => {
  25. const testDir = resolve(tmpdir(), 'blake3-browser-test');
  26. let server;
  27. let page;
  28. /**
  29. * Builds the browser lib into the testDir.
  30. */
  31. function buildWebpack() {
  32. return __awaiter(this, void 0, void 0, function* () {
  33. try {
  34. mkdirSync(testDir);
  35. }
  36. catch (_a) {
  37. // already exists, probably
  38. }
  39. writeFileSync(resolve(testDir, 'entry-src.js'), `import("blake3/browser").then(b3 => window.blake3 = b3);`);
  40. const stats = yield new Promise((res, rej) => webpack({
  41. mode: 'production',
  42. devtool: 'source-map',
  43. entry: resolve(testDir, 'entry-src.js'),
  44. output: {
  45. path: testDir,
  46. filename: 'main.js',
  47. },
  48. resolve: {
  49. alias: {
  50. 'blake3/browser': resolve(__dirname, '../', 'browser.js'),
  51. },
  52. },
  53. }, (err, stats) => (err ? rej(err) : res(stats))));
  54. if (stats.hasErrors()) {
  55. throw stats.toString('errors-only');
  56. }
  57. writeFileSync(resolve(testDir, 'index.html'), `<script src="/main.js"></script>`);
  58. });
  59. }
  60. function serve() {
  61. return __awaiter(this, void 0, void 0, function* () {
  62. server = createServer((req, res) => handler(req, res, { public: testDir }));
  63. yield new Promise(resolve => server.listen(0, resolve));
  64. });
  65. }
  66. before(function () {
  67. return __awaiter(this, void 0, void 0, function* () {
  68. yield buildWebpack();
  69. yield serve();
  70. this.timeout(20 * 1000);
  71. const { port } = server.address();
  72. const browser = yield puppeteer.launch({
  73. executablePath: 'google-chrome-stable',
  74. args: ['--no-sandbox'],
  75. });
  76. page = yield browser.newPage();
  77. yield page.goto(`http://localhost:${port}`);
  78. yield page.waitForFunction('!!window.blake3');
  79. yield page.evaluate(addInputs);
  80. });
  81. });
  82. runTests({
  83. get page() {
  84. return page;
  85. },
  86. });
  87. after(() => {
  88. page === null || page === void 0 ? void 0 : page.browser().close();
  89. server === null || server === void 0 ? void 0 : server.close();
  90. });
  91. });
  92. describe('native browser', () => {
  93. let server;
  94. let page;
  95. function serve() {
  96. return __awaiter(this, void 0, void 0, function* () {
  97. server = createServer((req, res) => handler(req, res, { public: resolve(__dirname, '..') }));
  98. yield new Promise(resolve => server.listen(0, resolve));
  99. });
  100. }
  101. before(function () {
  102. return __awaiter(this, void 0, void 0, function* () {
  103. yield serve();
  104. this.timeout(20 * 1000);
  105. const { port } = server.address();
  106. const browser = yield puppeteer.launch({
  107. executablePath: 'google-chrome-stable',
  108. args: ['--no-sandbox'],
  109. });
  110. page = yield browser.newPage();
  111. page.on('console', console.log);
  112. page.on('pageerror', console.log);
  113. page.on('error', console.log);
  114. yield page.goto(`http://localhost:${port}/browser-async.test.html`);
  115. yield page.waitForFunction('!!window.blake3');
  116. yield page.evaluate(addInputs);
  117. });
  118. });
  119. runTests({
  120. get page() {
  121. return page;
  122. },
  123. });
  124. after(() => {
  125. page === null || page === void 0 ? void 0 : page.browser().close();
  126. server.close();
  127. });
  128. });
  129. });
  130. function runTests(opts) {
  131. it('hashes a string', () => __awaiter(this, void 0, void 0, function* () {
  132. const result = yield opts.page.evaluate('blake3.hash(inputs.large.input).toString("hex")');
  133. expect(result).to.equal(inputs.large.hash.toString('hex'));
  134. }));
  135. describe('input encoding', () => {
  136. it('hashes a uint8array', () => __awaiter(this, void 0, void 0, function* () {
  137. const contents = [...new Uint8Array(Buffer.from(inputs.hello.input))];
  138. const result = yield opts.page.evaluate(`blake3.hash(new Uint8Array([${contents.join(',')}])).toString("hex")`);
  139. expect(result).to.equal(inputs.hello.hash.toString('hex'));
  140. }));
  141. it('hashes a string', () => __awaiter(this, void 0, void 0, function* () {
  142. const result = yield opts.page.evaluate('blake3.hash(inputs.large.input).toString("hex")');
  143. expect(result).to.equal(inputs.large.hash.toString('hex'));
  144. }));
  145. it('customizes output length', () => __awaiter(this, void 0, void 0, function* () {
  146. const result = yield opts.page.evaluate('blake3.hash(inputs.hello.input, { length: 16 }).toString("hex")');
  147. expect(result).to.equal(inputs.hello.hash.slice(0, 16).toString('hex'));
  148. }));
  149. });
  150. describe('output encoding', () => {
  151. const tcases = [
  152. { encoding: 'hex', expected: inputs.hello.hash.toString('hex') },
  153. { encoding: 'base64', expected: inputs.hello.hash.toString('base64') },
  154. { encoding: 'utf8', expected: inputs.hello.hash.toString('utf8') },
  155. ];
  156. tcases.forEach(({ encoding, expected }) => it(encoding, () => __awaiter(this, void 0, void 0, function* () {
  157. const result = yield opts.page.evaluate(`blake3.hash(inputs.hello.input).toString("${encoding}")`);
  158. expect(result).to.equal(expected);
  159. })));
  160. it('raw', () => __awaiter(this, void 0, void 0, function* () {
  161. const result = (yield opts.page.evaluate(`blake3.hash(inputs.hello.input)`));
  162. const actual = Buffer.alloc(32);
  163. for (let i = 0; i < actual.length; i++) {
  164. actual[i] = result[i]; // it comes as a plain object, we need to convert it to a buffer
  165. }
  166. expect(actual).to.deep.equal(inputs.hello.hash);
  167. }));
  168. });
  169. describe('hash class', () => {
  170. it('digests', () => __awaiter(this, void 0, void 0, function* () {
  171. const result = yield opts.page.evaluate(`(() => {
  172. const hash = blake3.createHash();
  173. ${[...Buffer.from(inputs.hello.input)]
  174. .map(byte => `hash.update(new Uint8Array([${byte}]));`)
  175. .join('\n')}
  176. return hash.digest('hex');
  177. })()`);
  178. expect(result).to.equal(inputs.hello.hash.toString('hex'));
  179. }));
  180. it('customizes the output length', () => __awaiter(this, void 0, void 0, function* () {
  181. const result = yield opts.page.evaluate(`(() => {
  182. const hash = blake3.createHash();
  183. hash.update(${JSON.stringify(inputs.hello.input)});
  184. return hash.digest('hex', { length: 16 });
  185. })()`);
  186. expect(result).to.equal(inputs.hello.hash.slice(0, 16).toString('hex'));
  187. }));
  188. it('returns a hash instance from digest', () => __awaiter(this, void 0, void 0, function* () {
  189. const result = yield opts.page.evaluate(`(() => {
  190. const hash = blake3.createHash();
  191. ${[...Buffer.from(inputs.hello.input)]
  192. .map(byte => `hash.update(new Uint8Array([${byte}]));`)
  193. .join('\n')}
  194. return hash.digest('hex');
  195. })()`);
  196. expect(result).to.equal(inputs.hello.hash.toString('hex'));
  197. }));
  198. });
  199. describe('reader', () => {
  200. it('is sane with a Hash', () => __awaiter(this, void 0, void 0, function* () {
  201. const result = yield opts.page.evaluate(`(() => {
  202. const hash = blake3.createHash();
  203. hash.update("hello");
  204. return blake3.using(hash.reader(), reader => [
  205. reader.read(48).toString('hex'),
  206. reader.toArray().toString('hex'),
  207. reader.toString('hex'),
  208. ]);
  209. })()`);
  210. expect(result).to.deep.equal([
  211. hello48.toString('hex'),
  212. inputs.hello.hash.toString('hex'),
  213. inputs.hello.hash.toString('hex'),
  214. ]);
  215. }));
  216. });
  217. describe('original test vectors', () => {
  218. for (const { inputLen, expectedDerive, expectedHash, expectedKeyed, } of ogTestVectors.cases.slice(0, 6)) {
  219. describe(`${inputLen}`, () => __awaiter(this, void 0, void 0, function* () {
  220. const input = Buffer.alloc(inputLen);
  221. for (let i = 0; i < inputLen; i++) {
  222. input[i] = i % 251;
  223. }
  224. const inputStr = `new Uint8Array([${input.join(',')}])`;
  225. it('hash()', () => __awaiter(this, void 0, void 0, function* () {
  226. const result = yield opts.page.evaluate(`blake3.hash(
  227. ${inputStr},
  228. { length: ${expectedHash.length / 2} }
  229. ).toString("hex")`);
  230. expect(result).to.equal(expectedHash);
  231. }));
  232. it('deriveKey()', () => __awaiter(this, void 0, void 0, function* () {
  233. const result = yield opts.page.evaluate(`blake3.deriveKey(
  234. ${JSON.stringify(ogTestVectors.context)},
  235. ${inputStr},
  236. { length: ${expectedHash.length / 2} }
  237. ).toString("hex")`);
  238. expect(result).to.equal(expectedDerive);
  239. }));
  240. it('createKeyed()', () => __awaiter(this, void 0, void 0, function* () {
  241. const result = yield opts.page.evaluate(`(() => {
  242. const hasher = blake3.createKeyed(new Uint8Array([${Buffer.from(ogTestVectors.key).join(',')}]));
  243. hasher.update(${inputStr});
  244. return hasher.digest({ length: ${expectedHash.length / 2} }).toString('hex');
  245. })()`);
  246. expect(result).to.equal(expectedKeyed);
  247. }));
  248. it('keyedHash()', () => __awaiter(this, void 0, void 0, function* () {
  249. const result = yield opts.page.evaluate(`blake3.keyedHash(
  250. new Uint8Array([${Buffer.from(ogTestVectors.key).join(',')}]),
  251. ${inputStr},
  252. { length: ${expectedHash.length / 2} }
  253. ).toString("hex")`);
  254. expect(result).to.equal(expectedKeyed);
  255. }));
  256. }));
  257. }
  258. });
  259. }
  260. //# sourceMappingURL=browser.test.js.map