From 32027d8a586b679ee8c79ef0020d13b19b8909b0 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Wed, 17 Mar 2021 11:11:40 -0700 Subject: [PATCH] test: add atob wpt Signed-off-by: James M Snell --- test/fixtures/wpt/README.md | 15 +- .../wpt/html/webappapis/atob/base64.any.js | 163 ++++++++++++++++++ test/fixtures/wpt/versions.json | 48 +++--- test/wpt/status/html/webappapis/atob.json | 5 + test/wpt/test-atob.js | 19 ++ 5 files changed, 221 insertions(+), 29 deletions(-) create mode 100644 test/fixtures/wpt/html/webappapis/atob/base64.any.js create mode 100644 test/wpt/status/html/webappapis/atob.json create mode 100644 test/wpt/test-atob.js diff --git a/test/fixtures/wpt/README.md b/test/fixtures/wpt/README.md index a3cbbe667434e2..f873123a2e3ab5 100644 --- a/test/fixtures/wpt/README.md +++ b/test/fixtures/wpt/README.md @@ -10,17 +10,18 @@ See [test/wpt](../../wpt/README.md) for information on how these tests are run. Last update: +- common: https://github.com/web-platform-tests/wpt/tree/841a51412f/common - console: https://github.com/web-platform-tests/wpt/tree/3b1f72e99a/console +- dom/abort: https://github.com/web-platform-tests/wpt/tree/7caa3de747/dom/abort - encoding: https://github.com/web-platform-tests/wpt/tree/3c9820d1cc/encoding -- url: https://github.com/web-platform-tests/wpt/tree/1783c9bccf/url -- resources: https://github.com/web-platform-tests/wpt/tree/351a99782b/resources -- interfaces: https://github.com/web-platform-tests/wpt/tree/b4be9a3fdf/interfaces +- FileAPI: https://github.com/web-platform-tests/wpt/tree/3b279420d4/FileAPI +- hr-time: https://github.com/web-platform-tests/wpt/tree/a5d1774ecf/hr-time +- html/webappapis/atob: https://github.com/web-platform-tests/wpt/tree/f267e1dca6/html/webappapis/atob - html/webappapis/microtask-queuing: https://github.com/web-platform-tests/wpt/tree/2c5c3c4c27/html/webappapis/microtask-queuing - html/webappapis/timers: https://github.com/web-platform-tests/wpt/tree/264f12bc7b/html/webappapis/timers -- hr-time: https://github.com/web-platform-tests/wpt/tree/a5d1774ecf/hr-time -- common: https://github.com/web-platform-tests/wpt/tree/841a51412f/common -- dom/abort: https://github.com/web-platform-tests/wpt/tree/7caa3de747/dom/abort -- FileAPI: https://github.com/web-platform-tests/wpt/tree/3b279420d4/FileAPI +- interfaces: https://github.com/web-platform-tests/wpt/tree/b4be9a3fdf/interfaces +- resources: https://github.com/web-platform-tests/wpt/tree/351a99782b/resources +- url: https://github.com/web-platform-tests/wpt/tree/1783c9bccf/url [Web Platform Tests]: https://github.com/web-platform-tests/wpt [`git node wpt`]: https://github.com/nodejs/node-core-utils/blob/master/docs/git-node.md#git-node-wpt diff --git a/test/fixtures/wpt/html/webappapis/atob/base64.any.js b/test/fixtures/wpt/html/webappapis/atob/base64.any.js new file mode 100644 index 00000000000000..7f433f4d8a9ee2 --- /dev/null +++ b/test/fixtures/wpt/html/webappapis/atob/base64.any.js @@ -0,0 +1,163 @@ +/** + * btoa() as defined by the HTML5 spec, which mostly just references RFC4648. + */ +function mybtoa(s) { + // String conversion as required by WebIDL. + s = String(s); + + // "The btoa() method must throw an INVALID_CHARACTER_ERR exception if the + // method's first argument contains any character whose code point is + // greater than U+00FF." + for (var i = 0; i < s.length; i++) { + if (s.charCodeAt(i) > 255) { + return "INVALID_CHARACTER_ERR"; + } + } + + var out = ""; + for (var i = 0; i < s.length; i += 3) { + var groupsOfSix = [undefined, undefined, undefined, undefined]; + groupsOfSix[0] = s.charCodeAt(i) >> 2; + groupsOfSix[1] = (s.charCodeAt(i) & 0x03) << 4; + if (s.length > i + 1) { + groupsOfSix[1] |= s.charCodeAt(i + 1) >> 4; + groupsOfSix[2] = (s.charCodeAt(i + 1) & 0x0f) << 2; + } + if (s.length > i + 2) { + groupsOfSix[2] |= s.charCodeAt(i + 2) >> 6; + groupsOfSix[3] = s.charCodeAt(i + 2) & 0x3f; + } + for (var j = 0; j < groupsOfSix.length; j++) { + if (typeof groupsOfSix[j] == "undefined") { + out += "="; + } else { + out += btoaLookup(groupsOfSix[j]); + } + } + } + return out; +} + +/** + * Lookup table for mybtoa(), which converts a six-bit number into the + * corresponding ASCII character. + */ +function btoaLookup(idx) { + if (idx < 26) { + return String.fromCharCode(idx + 'A'.charCodeAt(0)); + } + if (idx < 52) { + return String.fromCharCode(idx - 26 + 'a'.charCodeAt(0)); + } + if (idx < 62) { + return String.fromCharCode(idx - 52 + '0'.charCodeAt(0)); + } + if (idx == 62) { + return '+'; + } + if (idx == 63) { + return '/'; + } + // Throw INVALID_CHARACTER_ERR exception here -- won't be hit in the tests. +} + +function btoaException(input) { + input = String(input); + for (var i = 0; i < input.length; i++) { + if (input.charCodeAt(i) > 255) { + return true; + } + } + return false; +} + +function testBtoa(input) { + // "The btoa() method must throw an INVALID_CHARACTER_ERR exception if the + // method's first argument contains any character whose code point is + // greater than U+00FF." + var normalizedInput = String(input); + for (var i = 0; i < normalizedInput.length; i++) { + if (normalizedInput.charCodeAt(i) > 255) { + assert_throws_dom("InvalidCharacterError", function() { btoa(input); }, + "Code unit " + i + " has value " + normalizedInput.charCodeAt(i) + ", which is greater than 255"); + return; + } + } + assert_equals(btoa(input), mybtoa(input)); + assert_equals(atob(btoa(input)), String(input), "atob(btoa(input)) must be the same as String(input)"); +} + +var tests = ["עברית", "", "ab", "abc", "abcd", "abcde", + // This one is thrown in because IE9 seems to fail atob(btoa()) on it. Or + // possibly to fail btoa(). I actually can't tell what's happening here, + // but it doesn't hurt. + "\xff\xff\xc0", + // Is your DOM implementation binary-safe? + "\0a", "a\0b", + // WebIDL tests. + undefined, null, 7, 12, 1.5, true, false, NaN, +Infinity, -Infinity, 0, -0, + {toString: function() { return "foo" }}, +]; +for (var i = 0; i < 258; i++) { + tests.push(String.fromCharCode(i)); +} +tests.push(String.fromCharCode(10000)); +tests.push(String.fromCharCode(65534)); +tests.push(String.fromCharCode(65535)); + +// This is supposed to be U+10000. +tests.push(String.fromCharCode(0xd800, 0xdc00)); +tests = tests.map( + function(elem) { + var expected = mybtoa(elem); + if (expected === "INVALID_CHARACTER_ERR") { + return ["btoa(" + format_value(elem) + ") must raise INVALID_CHARACTER_ERR", elem]; + } + return ["btoa(" + format_value(elem) + ") == " + format_value(mybtoa(elem)), elem]; + } +); + +var everything = ""; +for (var i = 0; i < 256; i++) { + everything += String.fromCharCode(i); +} +tests.push(["btoa(first 256 code points concatenated)", everything]); + +generate_tests(testBtoa, tests); + +promise_test(() => fetch("../../../fetch/data-urls/resources/base64.json").then(res => res.json()).then(runAtobTests), "atob() setup."); + +const idlTests = [ + [undefined, null], + [null, [158, 233, 101]], + [7, null], + [12, [215]], + [1.5, null], + [true, [182, 187]], + [false, null], + [NaN, [53, 163]], + [+Infinity, [34, 119, 226, 158, 43, 114]], + [-Infinity, null], + [0, null], + [-0, null], + [{toString: function() { return "foo" }}, [126, 138]], + [{toString: function() { return "abcd" }}, [105, 183, 29]] +]; + +function runAtobTests(tests) { + const allTests = tests.concat(idlTests); + for(let i = 0; i < allTests.length; i++) { + const input = allTests[i][0], + output = allTests[i][1]; + test(() => { + if(output === null) { + assert_throws_dom("InvalidCharacterError", () => globalThis.atob(input)); + } else { + const result = globalThis.atob(input); + for(let ii = 0; ii < output.length; ii++) { + assert_equals(result.charCodeAt(ii), output[ii]); + } + } + }, "atob(" + format_value(input) + ")"); + } +} diff --git a/test/fixtures/wpt/versions.json b/test/fixtures/wpt/versions.json index 91bb213072cb92..07d4c70ebb0e0a 100644 --- a/test/fixtures/wpt/versions.json +++ b/test/fixtures/wpt/versions.json @@ -1,23 +1,31 @@ { + "common": { + "commit": "841a51412f236ad63655daca843d3b8e83e0777b", + "path": "common" + }, "console": { "commit": "3b1f72e99a91d31551edd2147dc7b564eaf25d72", "path": "console" }, + "dom/abort": { + "commit": "7caa3de7471cf19b78ee9efa313c7341a462b5e3", + "path": "dom/abort" + }, "encoding": { "commit": "3c9820d1cc5d9d2627c26ef1268b6d54a35adf22", "path": "encoding" }, - "url": { - "commit": "1783c9bccf48c426ec1017f36e1ccfcf90a8af47", - "path": "url" + "FileAPI": { + "commit": "3b279420d40afea32506e823f9ac005448f4f3d8", + "path": "FileAPI" }, - "resources": { - "commit": "351a99782b9677706b5dc0dd78e85978fa4ab130", - "path": "resources" + "hr-time": { + "commit": "a5d1774ecf41751d1c9357c27c709ee33bf3e279", + "path": "hr-time" }, - "interfaces": { - "commit": "b4be9a3fdf18459a924f88e49bc55d8b30faa93a", - "path": "interfaces" + "html/webappapis/atob": { + "commit": "f267e1dca6f57a9f4d69f32a6920adfdb3268656", + "path": "html/webappapis/atob" }, "html/webappapis/microtask-queuing": { "commit": "2c5c3c4c27d27a419c1fdba3e9879c2d22037074", @@ -27,20 +35,16 @@ "commit": "264f12bc7bf5db0c6dd064842a5d39ccbf9208c5", "path": "html/webappapis/timers" }, - "hr-time": { - "commit": "a5d1774ecf41751d1c9357c27c709ee33bf3e279", - "path": "hr-time" - }, - "common": { - "commit": "841a51412f236ad63655daca843d3b8e83e0777b", - "path": "common" + "interfaces": { + "commit": "b4be9a3fdf18459a924f88e49bc55d8b30faa93a", + "path": "interfaces" }, - "dom/abort": { - "commit": "7caa3de7471cf19b78ee9efa313c7341a462b5e3", - "path": "dom/abort" + "resources": { + "commit": "351a99782b9677706b5dc0dd78e85978fa4ab130", + "path": "resources" }, - "FileAPI": { - "commit": "3b279420d40afea32506e823f9ac005448f4f3d8", - "path": "FileAPI" + "url": { + "commit": "1783c9bccf48c426ec1017f36e1ccfcf90a8af47", + "path": "url" } } \ No newline at end of file diff --git a/test/wpt/status/html/webappapis/atob.json b/test/wpt/status/html/webappapis/atob.json new file mode 100644 index 00000000000000..65deda7312d426 --- /dev/null +++ b/test/wpt/status/html/webappapis/atob.json @@ -0,0 +1,5 @@ +{ + "base64.any.js": { + "fail": "promise_test: Unhandled rejection with value: object \"Error: ENOENT: no such file or directory, open '/root/node/node/fetch/data-urls/resources/base64.json'\"" + } +} diff --git a/test/wpt/test-atob.js b/test/wpt/test-atob.js new file mode 100644 index 00000000000000..51fa27e36d3f2f --- /dev/null +++ b/test/wpt/test-atob.js @@ -0,0 +1,19 @@ +'use strict'; + +require('../common'); +const { WPTRunner } = require('../common/wpt'); + +const runner = new WPTRunner('html/webappapis/atob'); + +// Needed to access to DOMException. +runner.setFlags(['--expose-internals']); + +// Set a script that will be executed in the worker before running the tests. +runner.setInitScript(` + const { internalBinding } = require('internal/test/binding'); + const { atob, btoa } = require('buffer'); + const { DOMException } = internalBinding('messaging'); + global.DOMException = DOMException; +`); + +runner.runJsTests();