summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/mozilla/tests/webgpu/common
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/mozilla/tests/webgpu/common')
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/framework/fixture.js15
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/framework/test_config.js20
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/file_loader.js2
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/logging/log_message.js51
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/logging/logger.js7
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/logging/result.js32
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/logging/test_case_recorder.js8
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/query/compare.js5
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/query/parseQuery.js43
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/query/query.js6
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/test_group.js10
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/test_suite_listing.js2
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/tree.js5
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/version.js2
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/internal/websocket_logger.js17
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/options.js53
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker-worker.js51
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker.js192
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/utils_worker.js35
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/wrap_for_worker.js54
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/runtime/wpt.js18
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/util/crc32.js57
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/util/parse_imports.js36
-rw-r--r--testing/web-platform/mozilla/tests/webgpu/common/util/util.js7
24 files changed, 624 insertions, 104 deletions
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/framework/fixture.js b/testing/web-platform/mozilla/tests/webgpu/common/framework/fixture.js
index d64245f5f8..149226a6e2 100644
--- a/testing/web-platform/mozilla/tests/webgpu/common/framework/fixture.js
+++ b/testing/web-platform/mozilla/tests/webgpu/common/framework/fixture.js
@@ -17,6 +17,7 @@ export { TestCaseRecorder } from '../internal/logging/test_case_recorder.js';
+
export class SubcaseBatchState {
constructor(
recorder,
@@ -124,8 +125,12 @@ export class Fixture {
if (WEBGL_lose_context) WEBGL_lose_context.loseContext();
} else if ('destroy' in o) {
o.destroy();
- } else {
+ } else if ('close' in o) {
o.close();
+ } else {
+ // HTMLVideoElement
+ o.src = '';
+ o.srcObject = null;
}
}
}
@@ -161,6 +166,14 @@ export class Fixture {
this.rec.debug(new Error(msg));
}
+ /**
+ * Log an info message.
+ * **Use sparingly. Use `debug()` instead if logs are only needed with debug logging enabled.**
+ */
+ info(msg) {
+ this.rec.info(new Error(msg));
+ }
+
/** Throws an exception marking the subcase as skipped. */
skip(msg) {
throw new SkipTestCase(msg);
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/framework/test_config.js b/testing/web-platform/mozilla/tests/webgpu/common/framework/test_config.js
index 81984dbec5..5d8a59217f 100644
--- a/testing/web-platform/mozilla/tests/webgpu/common/framework/test_config.js
+++ b/testing/web-platform/mozilla/tests/webgpu/common/framework/test_config.js
@@ -23,10 +23,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
export const globalTestConfig = {
+ enableDebugLogs: false,
maxSubcasesInFlight: 500,
testHeartbeatCallback: () => {},
noRaceWithRejectOnTimeout: false,
unrollConstEvalLoops: false,
- compatibility: false
+ compatibility: false,
+ forceFallbackAdapter: false,
+ logToWebSocket: false
}; \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/file_loader.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/file_loader.js
index f9f4f17fb4..3956108027 100644
--- a/testing/web-platform/mozilla/tests/webgpu/common/internal/file_loader.js
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/file_loader.js
@@ -73,6 +73,7 @@ export class TestFileLoader extends EventTarget {
query,
{
subqueriesToExpand = [],
+ fullyExpandSubtrees = [],
maxChunkTime = Infinity
} = {})
{
@@ -82,6 +83,7 @@ export class TestFileLoader extends EventTarget {
assert(q.level >= 2, () => `subqueriesToExpand entries should not be multi-file:\n ${q}`);
return q;
}),
+ fullyExpandSubtrees: fullyExpandSubtrees.map((s) => parseQuery(s)),
maxChunkTime
});
this.dispatchEvent(new MessageEvent('finish'));
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/log_message.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/log_message.js
index 234b7c2cc9..53d2cd4b9c 100644
--- a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/log_message.js
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/log_message.js
@@ -1,19 +1,36 @@
/**
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
**/import { extractImportantStackTrace } from '../stack.js';
+
+
export class LogMessageWithStack extends Error {
stackHiddenMessage = undefined;
- constructor(name, ex) {
- super(ex.message);
+ /**
+ * Wrap an Error (which was created to capture the stack at that point) into a
+ * LogMessageWithStack (which has extra stuff for good log messages).
+ *
+ * The original `ex.name` is ignored. Inclued it in the `name` parameter if it
+ * needs to be preserved.
+ */
+ static wrapError(name, ex) {
+ return new LogMessageWithStack({
+ name,
+ message: ex.message,
+ stackHiddenMessage: undefined,
+ stack: ex.stack,
+ extra: 'extra' in ex ? ex.extra : undefined
+ });
+ }
- this.name = name;
- this.stack = ex.stack;
- if ('extra' in ex) {
- this.extra = ex.extra;
- }
+ constructor(o) {
+ super(o.message);
+ this.name = o.name;
+ this.stackHiddenMessage = o.stackHiddenMessage;
+ this.stack = o.stack;
+ this.extra = o.extra;
}
/** Set a flag so the stack is not printed in toJSON(). */
@@ -21,6 +38,11 @@ export class LogMessageWithStack extends Error {
this.stackHiddenMessage ??= stackHiddenMessage;
}
+ /**
+ * Print the message for display.
+ *
+ * Note: This is toJSON instead of toString to make it easy to save logs using JSON.stringify.
+ */
toJSON() {
let m = this.name;
if (this.message) m += ': ' + this.message;
@@ -33,6 +55,21 @@ export class LogMessageWithStack extends Error {
}
return m;
}
+
+ /**
+ * Flatten the message for sending over a message channel.
+ *
+ * Note `extra` may get mangled by postMessage.
+ */
+ toRawData() {
+ return {
+ name: this.name,
+ message: this.message,
+ stackHiddenMessage: this.stackHiddenMessage,
+ stack: this.stack,
+ extra: this.extra
+ };
+ }
}
/**
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/logger.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/logger.js
index 224af20ddc..4ec505cb69 100644
--- a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/logger.js
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/logger.js
@@ -1,13 +1,12 @@
/**
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
-**/import { version } from '../version.js';
+**/import { globalTestConfig } from '../../framework/test_config.js';import { version } from '../version.js';
+
import { TestCaseRecorder } from './test_case_recorder.js';
export class Logger {
- static globalDebugMode = false;
-
results = new Map();
@@ -19,7 +18,7 @@ export class Logger {
const result = { status: 'running', timems: -1 };
this.results.set(name, result);
return [
- new TestCaseRecorder(result, this.overriddenDebugMode ?? Logger.globalDebugMode),
+ new TestCaseRecorder(result, this.overriddenDebugMode ?? globalTestConfig.enableDebugLogs),
result];
}
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/result.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/result.js
index a7eb281daf..cd4d0e86f1 100644
--- a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/result.js
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/result.js
@@ -1,4 +1,34 @@
/**
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
**/ // MAINTENANCE_TODO: Add warn expectations
-export {}; \ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+/**
+ * Raw data for a test log message.
+ *
+ * This form is sendable over a message channel, except `extra` may get mangled.
+ */
+
+
+
+
+
+
+
+
+/**
+ * Test case results in a form sendable over a message channel.
+ *
+ * Note `extra` may get mangled by postMessage.
+ */export {}; \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/test_case_recorder.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/test_case_recorder.js
index 7b9a5302ce..5b2a4e8b8e 100644
--- a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/test_case_recorder.js
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/test_case_recorder.js
@@ -45,8 +45,6 @@ export class TestCaseRecorder {
logs = [];
logLinesAtCurrentSeverity = 0;
debugging = false;
- /** Used to dedup log messages which have identical stacks. */
- messagesForPreviouslySeenStacks = new Map();
constructor(result, debugging) {
this.result = result;
@@ -143,13 +141,15 @@ export class TestCaseRecorder {
this.skipped(ex);
return;
}
- this.logImpl(LogSeverity.ThrewException, 'EXCEPTION', ex);
+ // logImpl will discard the original error's ex.name. Preserve it here.
+ const name = ex instanceof Error ? `EXCEPTION: ${ex.name}` : 'EXCEPTION';
+ this.logImpl(LogSeverity.ThrewException, name, ex);
}
logImpl(level, name, baseException) {
assert(baseException instanceof Error, 'test threw a non-Error object');
globalTestConfig.testHeartbeatCallback();
- const logMessage = new LogMessageWithStack(name, baseException);
+ const logMessage = LogMessageWithStack.wrapError(name, baseException);
// Final case status should be the "worst" of all log entries.
if (this.inSubCase) {
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/compare.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/compare.js
index 8af64919a2..f2bb1b62f3 100644
--- a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/compare.js
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/compare.js
@@ -58,7 +58,10 @@ function compareOneLevel(ordering, aIsBig, bIsBig) {
return Ordering.Unordered;
}
-function comparePaths(a, b) {
+/**
+ * Compare two file paths, or file-local test paths, returning an Ordering between the two.
+ */
+export function comparePaths(a, b) {
const shorter = Math.min(a.length, b.length);
for (let i = 0; i < shorter; ++i) {
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/parseQuery.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/parseQuery.js
index b66b16ce91..4c8bf32341 100644
--- a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/parseQuery.js
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/parseQuery.js
@@ -17,12 +17,49 @@ import {
import { kBigSeparator, kWildcard, kPathSeparator, kParamSeparator } from './separators.js';
import { validQueryPart } from './validQueryPart.js';
-export function parseQuery(s) {
+/**
+ * converts foo/bar/src/webgpu/this/that/file.spec.ts to webgpu:this,that,file,*
+ */
+function convertPathToQuery(path) {
+ // removes .spec.ts and splits by directory separators.
+ const parts = path.substring(0, path.length - 8).split(/\/|\\/g);
+ // Gets parts only after the last `src`. Example: returns ['webgpu', 'foo', 'bar', 'test']
+ // for ['Users', 'me', 'src', 'cts', 'src', 'webgpu', 'foo', 'bar', 'test']
+ const partsAfterSrc = parts.slice(parts.lastIndexOf('src') + 1);
+ const suite = partsAfterSrc.shift();
+ return `${suite}:${partsAfterSrc.join(',')},*`;
+}
+
+/**
+ * If a query looks like a path (ends in .spec.ts and has directory separators)
+ * then convert try to convert it to a query.
+ */
+function convertPathLikeToQuery(queryOrPath) {
+ return queryOrPath.endsWith('.spec.ts') && (
+ queryOrPath.includes('/') || queryOrPath.includes('\\')) ?
+ convertPathToQuery(queryOrPath) :
+ queryOrPath;
+}
+
+/**
+ * Convert long suite names (the part before the first colon) to the
+ * shortest last word
+ * foo.bar.moo:test,subtest,foo -> moo:test,subtest,foo
+ */
+function shortenSuiteName(query) {
+ const parts = query.split(':');
+ // converts foo.bar.moo to moo
+ const suite = parts.shift()?.replace(/.*\.(\w+)$/, '$1');
+ return [suite, ...parts].join(':');
+}
+
+export function parseQuery(queryLike) {
try {
- return parseQueryImpl(s);
+ const query = shortenSuiteName(convertPathLikeToQuery(queryLike));
+ return parseQueryImpl(query);
} catch (ex) {
if (ex instanceof Error) {
- ex.message += '\n on: ' + s;
+ ex.message += `\n on: ${queryLike}`;
}
throw ex;
}
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/query.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/query.js
index e1db875061..8fd443652a 100644
--- a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/query.js
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/query.js
@@ -1,6 +1,6 @@
/**
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
-**/import { optionEnabled } from '../../runtime/helper/options.js';import { assert, unreachable } from '../../util/util.js';
+**/import { optionWorkerMode } from '../../runtime/helper/options.js';import { assert, unreachable } from '../../util/util.js';
import { compareQueries, Ordering } from './compare.js';
@@ -188,12 +188,12 @@ wptURL)
assert(
expectationURL.pathname === wptURL.pathname,
`Invalid expectation path ${expectationURL.pathname}
-Expectation should be of the form path/to/cts.https.html?worker=0&q=suite:test_path:test_name:foo=1;bar=2;...
+Expectation should be of the form path/to/cts.https.html?debug=0&q=suite:test_path:test_name:foo=1;bar=2;...
`
);
const params = expectationURL.searchParams;
- if (optionEnabled('worker', params) !== optionEnabled('worker', wptURL.searchParams)) {
+ if (optionWorkerMode('worker', params) !== optionWorkerMode('worker', wptURL.searchParams)) {
continue;
}
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/test_group.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_group.js
index 3db409ffe7..2772194667 100644
--- a/testing/web-platform/mozilla/tests/webgpu/common/internal/test_group.js
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_group.js
@@ -34,7 +34,7 @@ import { validQueryPart } from '../internal/query/validQueryPart.js';
import { assert, unreachable } from '../util/util.js';
-import { logToWebsocket } from './websocket_logger.js';
+import { logToWebSocket } from './websocket_logger.js';
@@ -294,9 +294,11 @@ class TestBuilder {
(this.description ? this.description + '\n\n' : '') + 'TODO: .unimplemented()';
this.isUnimplemented = true;
- this.testFn = () => {
+ // Use the beforeFn to skip the test, so we don't have to iterate the subcases.
+ this.beforeFn = () => {
throw new SkipTestCase('test unimplemented');
};
+ this.testFn = () => {};
}
/** Perform various validation/"lint" chenks. */
@@ -350,7 +352,7 @@ class TestBuilder {
const testcaseStringUnique = stringifyPublicParamsUniquely(params);
assert(
!seen.has(testcaseStringUnique),
- `Duplicate public test case+subcase params for test ${testPathString}: ${testcaseString}`
+ `Duplicate public test case+subcase params for test ${testPathString}: ${testcaseString} (${caseQuery})`
);
seen.add(testcaseStringUnique);
}
@@ -737,7 +739,7 @@ class RunCaseSpecific {
timems: rec.result.timems,
nonskippedSubcaseCount: rec.nonskippedSubcaseCount
};
- logToWebsocket(JSON.stringify(msg));
+ logToWebSocket(JSON.stringify(msg));
}
}
} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/test_suite_listing.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_suite_listing.js
index 81a15cf712..7ea1c066f5 100644
--- a/testing/web-platform/mozilla/tests/webgpu/common/internal/test_suite_listing.js
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_suite_listing.js
@@ -2,5 +2,5 @@
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
**/ // A listing of all specs within a single suite. This is the (awaited) type of
// `groups` in '{cts,unittests}/listing.ts' and `listing` in the auto-generated
-// 'out/{cts,unittests}/listing.js' files (see tools/gen_listings).
+// 'out/{cts,unittests}/listing.js' files (see tools/gen_listings_and_webworkers).
export {}; \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/tree.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/tree.js
index 8f1e6bad66..3b33542752 100644
--- a/testing/web-platform/mozilla/tests/webgpu/common/internal/tree.js
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/tree.js
@@ -286,6 +286,7 @@ loader,
queryToLoad,
{
subqueriesToExpand,
+ fullyExpandSubtrees = [],
maxChunkTime = Infinity
})
{
@@ -303,6 +304,10 @@ queryToLoad,
// If toExpand == subquery, no expansion is needed (but it's still "seen").
if (ordering === Ordering.Equal) seenSubqueriesToExpand[i] = true;
return ordering !== Ordering.StrictSubset;
+ }) &&
+ fullyExpandSubtrees.every((toExpand) => {
+ const ordering = compareQueries(toExpand, subquery);
+ return ordering === Ordering.Unordered;
});
// L0 = suite-level, e.g. suite:*
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/version.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/version.js
index 7a632d5635..d300878e0e 100644
--- a/testing/web-platform/mozilla/tests/webgpu/common/internal/version.js
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/version.js
@@ -1,3 +1,3 @@
// AUTO-GENERATED - DO NOT EDIT. See tools/gen_version.
-export const version = '41f89e77b67e6b66cb017be4e00235a0a9429ca7';
+export const version = '5c8510ec0d47180d1cd4dd92790b5a69335e162c';
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/websocket_logger.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/websocket_logger.js
index 7a8f92b1a8..1790e5632d 100644
--- a/testing/web-platform/mozilla/tests/webgpu/common/internal/websocket_logger.js
+++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/websocket_logger.js
@@ -1,19 +1,24 @@
/**
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
-**/ /**
+**/import { globalTestConfig } from '../framework/test_config.js'; /**
* - 'uninitialized' means we haven't tried to connect yet
* - Promise means it's pending
* - 'failed' means it failed (this is the most common case, where the logger isn't running)
* - WebSocket means it succeeded
- */let connection = 'uninitialized';
+ */
+let connection =
+'uninitialized';
/**
- * Log a string to a websocket at `localhost:59497`. See `tools/websocket-logger`.
+ * If the logToWebSocket option is enabled (?log_to_web_socket=1 in browser,
+ * --log-to-web-socket on command line, or enable it by default in options.ts),
+ * log a string to a websocket at `localhost:59497`. See `tools/websocket-logger`.
*
- * This does nothing if a connection couldn't be established on the first call.
+ * This does nothing if a logToWebSocket is not enabled, or if a connection
+ * couldn't be established on the first call.
*/
-export function logToWebsocket(msg) {
- if (connection === 'failed') {
+export function logToWebSocket(msg) {
+ if (!globalTestConfig.logToWebSocket || connection === 'failed') {
return;
}
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/options.js b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/options.js
index 139c3bc29f..01b7d95889 100644
--- a/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/options.js
+++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/options.js
@@ -1,11 +1,14 @@
/**
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
-**/let windowURL = undefined;function getWindowURL() {if (windowURL === undefined) {
+**/import { unreachable } from '../../util/util.js';let windowURL = undefined;
+function getWindowURL() {
+ if (windowURL === undefined) {
windowURL = new URL(window.location.toString());
}
return windowURL;
}
+/** Parse a runner option that is always boolean-typed. False if missing or '0'. */
export function optionEnabled(
opt,
searchParams = getWindowURL().searchParams)
@@ -14,11 +17,32 @@ searchParams = getWindowURL().searchParams)
return val !== null && val !== '0';
}
+/** Parse a runner option that is string-typed. If the option is missing, returns `null`. */
export function optionString(
opt,
searchParams = getWindowURL().searchParams)
{
- return searchParams.get(opt) || '';
+ return searchParams.get(opt);
+}
+
+/** Runtime modes for running tests in different types of workers. */
+
+/** Parse a runner option for different worker modes (as in `?worker=shared`). Null if no worker. */
+export function optionWorkerMode(
+opt,
+searchParams = getWindowURL().searchParams)
+{
+ const value = searchParams.get(opt);
+ if (value === null || value === '0') {
+ return null;
+ } else if (value === 'service') {
+ return 'service';
+ } else if (value === 'shared') {
+ return 'shared';
+ } else if (value === '' || value === '1' || value === 'dedicated') {
+ return 'dedicated';
+ }
+ unreachable('invalid worker= option value');
}
/**
@@ -32,12 +56,16 @@ searchParams = getWindowURL().searchParams)
+
+
export const kDefaultCTSOptions = {
- worker: false,
+ worker: null,
debug: true,
compatibility: false,
+ forceFallbackAdapter: false,
unrollConstEvalLoops: false,
- powerPreference: ''
+ powerPreference: null,
+ logToWebSocket: false
};
/**
@@ -59,19 +87,30 @@ export const kDefaultCTSOptions = {
* Options to the CTS.
*/
export const kCTSOptionsInfo = {
- worker: { description: 'run in a worker' },
+ worker: {
+ description: 'run in a worker',
+ parser: optionWorkerMode,
+ selectValueDescriptions: [
+ { value: null, description: 'no worker' },
+ { value: 'dedicated', description: 'dedicated worker' },
+ { value: 'shared', description: 'shared worker' },
+ { value: 'service', description: 'service worker' }]
+
+ },
debug: { description: 'show more info' },
compatibility: { description: 'run in compatibility mode' },
+ forceFallbackAdapter: { description: 'pass forceFallbackAdapter: true to requestAdapter' },
unrollConstEvalLoops: { description: 'unroll const eval loops in WGSL' },
powerPreference: {
description: 'set default powerPreference for some tests',
parser: optionString,
selectValueDescriptions: [
- { value: '', description: 'default' },
+ { value: null, description: 'default' },
{ value: 'low-power', description: 'low-power' },
{ value: 'high-performance', description: 'high-performance' }]
- }
+ },
+ logToWebSocket: { description: 'send some logs to ws://localhost:59497/' }
};
/**
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker-worker.js b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker-worker.js
index a0f13c54af..c5df860d0b 100644
--- a/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker-worker.js
+++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker-worker.js
@@ -1,15 +1,11 @@
/**
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
-**/import { setBaseResourcePath } from '../../framework/resources.js';import { globalTestConfig } from '../../framework/test_config.js';import { DefaultTestFileLoader } from '../../internal/file_loader.js';
-import { Logger } from '../../internal/logging/logger.js';
-import { parseQuery } from '../../internal/query/parseQuery.js';
-
-import { setDefaultRequestAdapterOptions } from '../../util/navigator_gpu.js';
+**/import { setBaseResourcePath } from '../../framework/resources.js';import { DefaultTestFileLoader } from '../../internal/file_loader.js';import { parseQuery } from '../../internal/query/parseQuery.js';
import { assert } from '../../util/util.js';
+import { setupWorkerEnvironment } from './utils_worker.js';
-
-// Should be DedicatedWorkerGlobalScope, but importing lib "webworker" conflicts with lib "dom".
+// Should be WorkerGlobalScope, but importing lib "webworker" conflicts with lib "dom".
@@ -17,25 +13,10 @@ const loader = new DefaultTestFileLoader();
setBaseResourcePath('../../../resources');
-self.onmessage = async (ev) => {
- const query = ev.data.query;
- const expectations = ev.data.expectations;
- const ctsOptions = ev.data.ctsOptions;
-
- const { debug, unrollConstEvalLoops, powerPreference, compatibility } = ctsOptions;
- globalTestConfig.unrollConstEvalLoops = unrollConstEvalLoops;
- globalTestConfig.compatibility = compatibility;
-
- Logger.globalDebugMode = debug;
- const log = new Logger();
+async function reportTestResults(ev) {
+ const { query, expectations, ctsOptions } = ev.data;
- if (powerPreference || compatibility) {
- setDefaultRequestAdapterOptions({
- ...(powerPreference && { powerPreference }),
- // MAINTENANCE_TODO: Change this to whatever the option ends up being
- ...(compatibility && { compatibilityMode: true })
- });
- }
+ const log = setupWorkerEnvironment(ctsOptions);
const testcases = Array.from(await loader.loadCases(parseQuery(query)));
assert(testcases.length === 1, 'worker query resulted in != 1 cases');
@@ -44,5 +25,23 @@ self.onmessage = async (ev) => {
const [rec, result] = log.record(testcase.query.toString());
await testcase.run(rec, expectations);
- self.postMessage({ query, result });
+ this.postMessage({
+ query,
+ result: {
+ ...result,
+ logs: result.logs?.map((l) => l.toRawData())
+ }
+ });
+}
+
+self.onmessage = (ev) => {
+ void reportTestResults.call(ev.source || self, ev);
+};
+
+self.onconnect = (event) => {
+ const port = event.ports[0];
+
+ port.onmessage = (ev) => {
+ void reportTestResults.call(port, ev);
+ };
}; \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker.js b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker.js
index 1d65394180..4039aa1332 100644
--- a/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker.js
+++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker.js
@@ -2,48 +2,190 @@
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
**/import { LogMessageWithStack } from '../../internal/logging/log_message.js';
+import { timeout } from '../../util/timeout.js';
+import { assert } from '../../util/util.js';
import { kDefaultCTSOptions } from './options.js';
-export class TestWorker {
+/** Query all currently-registered service workers, and unregister them. */
+function unregisterAllServiceWorkers() {
+ void navigator.serviceWorker.getRegistrations().then((registrations) => {
+ for (const registration of registrations) {
+ void registration.unregister();
+ }
+ });
+}
+
+// NOTE: This code runs on startup for any runtime with worker support. Here, we use that chance to
+// delete any leaked service workers, and register to clean up after ourselves at shutdown.
+unregisterAllServiceWorkers();
+window.addEventListener('beforeunload', () => {
+ unregisterAllServiceWorkers();
+});
+
+class TestBaseWorker {
resolvers = new Map();
- constructor(ctsOptions) {
- this.ctsOptions = { ...(ctsOptions || kDefaultCTSOptions), ...{ worker: true } };
- const selfPath = import.meta.url;
- const selfPathDir = selfPath.substring(0, selfPath.lastIndexOf('/'));
- const workerPath = selfPathDir + '/test_worker-worker.js';
- this.worker = new Worker(workerPath, { type: 'module' });
- this.worker.onmessage = (ev) => {
- const query = ev.data.query;
- const result = ev.data.result;
- if (result.logs) {
- for (const l of result.logs) {
- Object.setPrototypeOf(l, LogMessageWithStack.prototype);
- }
- }
- this.resolvers.get(query)(result);
+ constructor(worker, ctsOptions) {
+ this.ctsOptions = { ...(ctsOptions || kDefaultCTSOptions), ...{ worker } };
+ }
+
+ onmessage(ev) {
+ const query = ev.data.query;
+ const transferredResult = ev.data.result;
- // MAINTENANCE_TODO(kainino0x): update the Logger with this result (or don't have a logger and
- // update the entire results JSON somehow at some point).
+ const result = {
+ status: transferredResult.status,
+ timems: transferredResult.timems,
+ logs: transferredResult.logs?.map((l) => new LogMessageWithStack(l))
};
+
+ this.resolvers.get(query)(result);
+ this.resolvers.delete(query);
+
+ // MAINTENANCE_TODO(kainino0x): update the Logger with this result (or don't have a logger and
+ // update the entire results JSON somehow at some point).
}
- async run(
- rec,
+ makeRequestAndRecordResult(
+ target,
query,
- expectations = [])
+ expectations)
{
- this.worker.postMessage({
+ const request = {
query,
expectations,
ctsOptions: this.ctsOptions
- });
- const workerResult = await new Promise((resolve) => {
+ };
+ target.postMessage(request);
+
+ return new Promise((resolve) => {
+ assert(!this.resolvers.has(query), "can't request same query twice simultaneously");
this.resolvers.set(query, resolve);
});
- rec.injectResult(workerResult);
+ }
+
+ async run(
+ rec,
+ query,
+ expectations = [])
+ {
+ try {
+ rec.injectResult(await this.runImpl(query, expectations));
+ } catch (ex) {
+ rec.start();
+ rec.threw(ex);
+ rec.finish();
+ }
+ }
+
+
+
+
+
+}
+
+export class TestDedicatedWorker extends TestBaseWorker {
+
+
+ constructor(ctsOptions) {
+ super('dedicated', ctsOptions);
+ try {
+ if (typeof Worker === 'undefined') {
+ throw new Error('Dedicated Workers not available');
+ }
+
+ const selfPath = import.meta.url;
+ const selfPathDir = selfPath.substring(0, selfPath.lastIndexOf('/'));
+ const workerPath = selfPathDir + '/test_worker-worker.js';
+ this.worker = new Worker(workerPath, { type: 'module' });
+ this.worker.onmessage = (ev) => this.onmessage(ev);
+ } catch (ex) {
+ assert(ex instanceof Error);
+ // Save the exception to re-throw in runImpl().
+ this.worker = ex;
+ }
+ }
+
+ runImpl(query, expectations = []) {
+ if (this.worker instanceof Worker) {
+ return this.makeRequestAndRecordResult(this.worker, query, expectations);
+ } else {
+ throw this.worker;
+ }
+ }
+}
+
+/** @deprecated Use TestDedicatedWorker instead. */
+export class TestWorker extends TestDedicatedWorker {}
+
+export class TestSharedWorker extends TestBaseWorker {
+ /** MessagePort to the SharedWorker, or an Error if it couldn't be initialized. */
+
+
+ constructor(ctsOptions) {
+ super('shared', ctsOptions);
+ try {
+ if (typeof SharedWorker === 'undefined') {
+ throw new Error('Shared Workers not available');
+ }
+
+ const selfPath = import.meta.url;
+ const selfPathDir = selfPath.substring(0, selfPath.lastIndexOf('/'));
+ const workerPath = selfPathDir + '/test_worker-worker.js';
+ const worker = new SharedWorker(workerPath, { type: 'module' });
+ this.port = worker.port;
+ this.port.start();
+ this.port.onmessage = (ev) => this.onmessage(ev);
+ } catch (ex) {
+ assert(ex instanceof Error);
+ // Save the exception to re-throw in runImpl().
+ this.port = ex;
+ }
+ }
+
+ runImpl(query, expectations = []) {
+ if (this.port instanceof MessagePort) {
+ return this.makeRequestAndRecordResult(this.port, query, expectations);
+ } else {
+ throw this.port;
+ }
+ }
+}
+
+export class TestServiceWorker extends TestBaseWorker {
+ constructor(ctsOptions) {
+ super('service', ctsOptions);
+ }
+
+ async runImpl(query, expectations = []) {
+ if (!('serviceWorker' in navigator)) {
+ throw new Error('Service Workers not available');
+ }
+ const [suite, name] = query.split(':', 2);
+ const fileName = name.split(',').join('/');
+
+ const selfPath = import.meta.url;
+ const selfPathDir = selfPath.substring(0, selfPath.lastIndexOf('/'));
+ // Construct the path to the worker file, then use URL to resolve the `../` components.
+ const serviceWorkerURL = new URL(
+ `${selfPathDir}/../../../${suite}/webworker/${fileName}.worker.js`
+ ).toString();
+
+ // If a registration already exists for this path, it will be ignored.
+ const registration = await navigator.serviceWorker.register(serviceWorkerURL, {
+ type: 'module'
+ });
+ // Make sure the registration we just requested is active. (We don't worry about it being
+ // outdated from a previous page load, because we wipe all service workers on shutdown/startup.)
+ while (!registration.active || registration.active.scriptURL !== serviceWorkerURL) {
+ await new Promise((resolve) => timeout(resolve, 0));
+ }
+ const serviceWorker = registration.active;
+
+ navigator.serviceWorker.onmessage = (ev) => this.onmessage(ev);
+ return this.makeRequestAndRecordResult(serviceWorker, query, expectations);
}
} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/utils_worker.js b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/utils_worker.js
new file mode 100644
index 0000000000..5a34070e14
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/utils_worker.js
@@ -0,0 +1,35 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/import { globalTestConfig } from '../../framework/test_config.js';import { Logger } from '../../internal/logging/logger.js';
+import { setDefaultRequestAdapterOptions } from '../../util/navigator_gpu.js';
+
+
+
+
+
+
+
+
+
+/**
+ * Set config environment for workers with ctsOptions and return a Logger.
+ */
+export function setupWorkerEnvironment(ctsOptions) {
+ const { powerPreference, compatibility } = ctsOptions;
+ globalTestConfig.enableDebugLogs = ctsOptions.debug;
+ globalTestConfig.unrollConstEvalLoops = ctsOptions.unrollConstEvalLoops;
+ globalTestConfig.compatibility = compatibility;
+ globalTestConfig.logToWebSocket = ctsOptions.logToWebSocket;
+
+ const log = new Logger();
+
+ if (powerPreference || compatibility) {
+ setDefaultRequestAdapterOptions({
+ ...(powerPreference && { powerPreference }),
+ // MAINTENANCE_TODO: Change this to whatever the option ends up being
+ ...(compatibility && { compatibilityMode: true })
+ });
+ }
+
+ return log;
+} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/wrap_for_worker.js b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/wrap_for_worker.js
new file mode 100644
index 0000000000..69b5f375f1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/wrap_for_worker.js
@@ -0,0 +1,54 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/import { LogMessageWithStack } from '../../internal/logging/log_message.js';import { comparePaths, comparePublicParamsPaths, Ordering } from '../../internal/query/compare.js';
+import { parseQuery } from '../../internal/query/parseQuery.js';
+import { TestQuerySingleCase } from '../../internal/query/query.js';
+
+import { assert } from '../../util/util.js';
+
+import { setupWorkerEnvironment } from './utils_worker.js';
+
+/**
+ * Sets up the currently running Web Worker to wrap the TestGroup object `g`.
+ * `g` is the `g` exported from a `.spec.ts` file: a TestGroupBuilder<F> interface,
+ * which underneath is actually a TestGroup<F> object.
+ *
+ * This is used in the generated `.worker.js` files that are generated to use as service workers.
+ */
+export function wrapTestGroupForWorker(g) {
+ self.onmessage = async (ev) => {
+ const { query, expectations, ctsOptions } = ev.data;
+ try {
+ const log = setupWorkerEnvironment(ctsOptions);
+
+ const testQuery = parseQuery(query);
+ assert(testQuery instanceof TestQuerySingleCase);
+ let testcase = null;
+ for (const t of g.iterate()) {
+ if (comparePaths(t.testPath, testQuery.testPathParts) !== Ordering.Equal) {
+ continue;
+ }
+ for (const c of t.iterate(testQuery.params)) {
+ if (comparePublicParamsPaths(c.id.params, testQuery.params) === Ordering.Equal) {
+ testcase = c;
+ }
+ }
+ }
+ assert(!!testcase, 'testcase not found');
+ const [rec, result] = log.record(query);
+ await testcase.run(rec, testQuery, expectations);
+
+ ev.source?.postMessage({ query, result });
+ } catch (thrown) {
+ const ex = thrown instanceof Error ? thrown : new Error(`${thrown}`);
+ ev.source?.postMessage({
+ query,
+ result: {
+ status: 'fail',
+ timems: 0,
+ logs: [LogMessageWithStack.wrapError('INTERNAL', ex)]
+ }
+ });
+ }
+ };
+} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/runtime/wpt.js b/testing/web-platform/mozilla/tests/webgpu/common/runtime/wpt.js
index 97c6a3886e..d1a025d1f8 100644
--- a/testing/web-platform/mozilla/tests/webgpu/common/runtime/wpt.js
+++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/wpt.js
@@ -8,8 +8,8 @@ import { parseQuery } from '../internal/query/parseQuery.js';
import { parseExpectationsForTestQuery, relativeQueryString } from '../internal/query/query.js';
import { assert } from '../util/util.js';
-import { optionEnabled } from './helper/options.js';
-import { TestWorker } from './helper/test_worker.js';
+import { optionEnabled, optionWorkerMode } from './helper/options.js';
+import { TestDedicatedWorker, TestServiceWorker, TestSharedWorker } from './helper/test_worker.js';
// testharness.js API (https://web-platform-tests.org/writing-tests/testharness-api.html)
@@ -31,8 +31,10 @@ setup({
});
void (async () => {
- const workerEnabled = optionEnabled('worker');
- const worker = workerEnabled ? new TestWorker() : undefined;
+ const workerString = optionWorkerMode('worker');
+ const dedicatedWorker = workerString === 'dedicated' ? new TestDedicatedWorker() : undefined;
+ const sharedWorker = workerString === 'shared' ? new TestSharedWorker() : undefined;
+ const serviceWorker = workerString === 'service' ? new TestServiceWorker() : undefined;
globalTestConfig.unrollConstEvalLoops = optionEnabled('unroll_const_eval_loops');
@@ -63,8 +65,12 @@ void (async () => {
const wpt_fn = async () => {
const [rec, res] = log.record(name);
- if (worker) {
- await worker.run(rec, name, expectations);
+ if (dedicatedWorker) {
+ await dedicatedWorker.run(rec, name, expectations);
+ } else if (sharedWorker) {
+ await sharedWorker.run(rec, name, expectations);
+ } else if (serviceWorker) {
+ await serviceWorker.run(rec, name, expectations);
} else {
await testcase.run(rec, expectations);
}
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/crc32.js b/testing/web-platform/mozilla/tests/webgpu/common/util/crc32.js
new file mode 100644
index 0000000000..392d3b947c
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/util/crc32.js
@@ -0,0 +1,57 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/ /// CRC32 immutable lookup table data.
+const kCRC32LUT = [0, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064,
+0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8,
+0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa,
+0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac,
+0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e,
+0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2,
+0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4,
+0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6,
+0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158,
+0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c,
+0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e,
+0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320,
+0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12,
+0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76,
+0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8,
+0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda,
+0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c,
+0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0,
+0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82,
+0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4,
+0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6,
+0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a,
+0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c,
+0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e,
+0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d];
+
+
+/**
+ * @param str the input string
+ * @returns the CRC32 of the input string
+ * @see https://en.wikipedia.org/wiki/Cyclic_redundancy_check#CRC-32_algorithm
+ */
+export function crc32(str) {
+ const utf8 = new TextEncoder().encode(str);
+ const u32 = new Uint32Array(1);
+
+ u32[0] = 0xffffffff;
+ for (const c of utf8) {
+ u32[0] = u32[0] >>> 8 ^ kCRC32LUT[u32[0] & 0xff ^ c];
+ }
+ u32[0] = u32[0] ^ 0xffffffff;
+ return u32[0];
+}
+
+/** @returns the input number has a 8-character hex string */
+export function toHexString(number) {
+ return ('00000000' + number.toString(16)).slice(-8);
+} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/parse_imports.js b/testing/web-platform/mozilla/tests/webgpu/common/util/parse_imports.js
new file mode 100644
index 0000000000..bc970572b1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/webgpu/common/util/parse_imports.js
@@ -0,0 +1,36 @@
+/**
+* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
+**/ /**
+ * Parses all the paths of the typescript `import` statements from content
+ * @param path the current path of the file
+ * @param content the file content
+ * @returns the list of import paths
+ */export function parseImports(path, content) {const out = [];
+ const importRE = /^import\s[^'"]*(['"])([./\w]*)(\1);/gm;
+ let importMatch;
+ while (importMatch = importRE.exec(content)) {
+ const importPath = importMatch[2].replace(`'`, '').replace(`"`, '');
+ out.push(joinPath(path, importPath));
+ }
+ return out;
+}
+
+function joinPath(a, b) {
+ const aParts = a.split('/');
+ const bParts = b.split('/');
+ aParts.pop(); // remove file
+ let bStart = 0;
+ while (aParts.length > 0) {
+ switch (bParts[bStart]) {
+ case '.':
+ bStart++;
+ continue;
+ case '..':
+ aParts.pop();
+ bStart++;
+ continue;
+ }
+ break;
+ }
+ return [...aParts, ...bParts.slice(bStart)].join('/');
+} \ No newline at end of file
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/util.js b/testing/web-platform/mozilla/tests/webgpu/common/util/util.js
index 34934af6c0..d0a3c0a8f7 100644
--- a/testing/web-platform/mozilla/tests/webgpu/common/util/util.js
+++ b/testing/web-platform/mozilla/tests/webgpu/common/util/util.js
@@ -1,7 +1,6 @@
/**
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
**/import { Float16Array } from '../../external/petamoriken/float16/float16.js';import { SkipTestCase } from '../framework/fixture.js';import { globalTestConfig } from '../framework/test_config.js';
-import { Logger } from '../internal/logging/logger.js';
import { keysOf } from './data_tables.js';
import { timeout } from './timeout.js';
@@ -24,7 +23,7 @@ export class ErrorWithExtra extends Error {
super(message);
const oldExtras = baseOrMessage instanceof ErrorWithExtra ? baseOrMessage.extra : {};
- this.extra = Logger.globalDebugMode ?
+ this.extra = globalTestConfig.enableDebugLogs ?
{ ...oldExtras, ...newExtra() } :
{ omitted: 'pass ?debug=1' };
}
@@ -303,7 +302,9 @@ new Int16Array(),
new Int32Array(),
new Float16Array(),
new Float32Array(),
-new Float64Array()];
+new Float64Array(),
+new BigInt64Array(),
+new BigUint64Array()];