browser.test.js 13 KB

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