diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /testing/web-platform/mozilla/tests/webgpu/common | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/mozilla/tests/webgpu/common')
68 files changed, 4280 insertions, 0 deletions
diff --git a/testing/web-platform/mozilla/tests/webgpu/common/framework/data_cache.js b/testing/web-platform/mozilla/tests/webgpu/common/framework/data_cache.js new file mode 100644 index 0000000000..e426ffbbc9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/framework/data_cache.js @@ -0,0 +1,89 @@ +/** + * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts + **/ + +/** DataCache is an interface to a data store used to hold cached data */ +export class DataCache { + /** setDataStore() sets the backing data store used by the data cache */ + setStore(dataStore) { + this.dataStore = dataStore; + } + + /** setDebugLogger() sets the verbose logger */ + setDebugLogger(logger) { + this.debugLogger = logger; + } + + /** + * fetch() retrieves cacheable data from the data cache, first checking the + * in-memory cache, then the data store (if specified), then resorting to + * building the data and storing it in the cache. + */ + async fetch(cacheable) { + // First check the in-memory cache + let data = this.cache.get(cacheable.path); + if (data !== undefined) { + this.log('in-memory cache hit'); + return Promise.resolve(data); + } + this.log('in-memory cache miss'); + // In in-memory cache miss. + // Next, try the data store. + if (this.dataStore !== null && !this.unavailableFiles.has(cacheable.path)) { + let serialized; + try { + serialized = await this.dataStore.load(cacheable.path); + this.log('loaded serialized'); + } catch (err) { + // not found in data store + this.log(`failed to load (${cacheable.path}): ${err}`); + this.unavailableFiles.add(cacheable.path); + } + if (serialized !== undefined) { + this.log(`deserializing`); + data = cacheable.deserialize(serialized); + this.cache.set(cacheable.path, data); + return data; + } + } + // Not found anywhere. Build the data, and cache for future lookup. + this.log(`cache: building (${cacheable.path})`); + data = await cacheable.build(); + this.cache.set(cacheable.path, data); + return data; + } + + log(msg) { + if (this.debugLogger !== null) { + this.debugLogger(`DataCache: ${msg}`); + } + } + + cache = new Map(); + unavailableFiles = new Set(); + dataStore = null; + debugLogger = null; +} + +/** The data cache */ +export const dataCache = new DataCache(); + +/** true if the current process is building the cache */ +let isBuildingDataCache = false; + +/** @returns true if the data cache is currently being built */ +export function getIsBuildingDataCache() { + return isBuildingDataCache; +} + +/** Sets whether the data cache is currently being built */ +export function setIsBuildingDataCache(value = true) { + isBuildingDataCache = value; +} + +/** + * Cacheable is the interface to something that can be stored into the + * DataCache. + * The 'npm run gen_cache' tool will look for module-scope variables of this + * interface, with the name `d`. + */ diff --git a/testing/web-platform/mozilla/tests/webgpu/common/framework/fixture.js b/testing/web-platform/mozilla/tests/webgpu/common/framework/fixture.js new file mode 100644 index 0000000000..1611e9a742 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/framework/fixture.js @@ -0,0 +1,310 @@ +/** + * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts + **/ import { assert, unreachable } from '../util/util.js'; + +export class SkipTestCase extends Error {} +export class UnexpectedPassError extends Error {} + +export { TestCaseRecorder } from '../internal/logging/test_case_recorder.js'; + +/** The fully-general type for params passed to a test function invocation. */ + +export class SubcaseBatchState { + constructor(params) { + this._params = params; + } + + /** + * Returns the case parameters for this test fixture shared state. Subcase params + * are not included. + */ + get params() { + return this._params; + } + + /** + * Runs before the `.before()` function. + * @internal MAINTENANCE_TODO: Make this not visible to test code? + */ + async init() {} + /** + * Runs between the `.before()` function and the subcases. + * @internal MAINTENANCE_TODO: Make this not visible to test code? + */ + async postInit() {} + /** + * Runs after all subcases finish. + * @internal MAINTENANCE_TODO: Make this not visible to test code? + */ + async finalize() {} +} + +/** + * A Fixture is a class used to instantiate each test sub/case at run time. + * A new instance of the Fixture is created for every single test subcase + * (i.e. every time the test function is run). + */ +export class Fixture { + /** + * Interface for recording logs and test status. + * + * @internal + */ + + eventualExpectations = []; + numOutstandingAsyncExpectations = 0; + objectsToCleanUp = []; + + static MakeSharedState(params) { + return new SubcaseBatchState(params); + } + + /** @internal */ + constructor(sharedState, rec, params) { + this._sharedState = sharedState; + this.rec = rec; + this._params = params; + } + + /** + * Returns the (case+subcase) parameters for this test function invocation. + */ + get params() { + return this._params; + } + + /** + * Gets the test fixture's shared state. This object is shared between subcases + * within the same testcase. + */ + get sharedState() { + return this._sharedState; + } + + /** + * Override this to do additional pre-test-function work in a derived fixture. + * This has to be a member function instead of an async `createFixture` function, because + * we need to be able to ergonomically override it in subclasses. + * + * @internal MAINTENANCE_TODO: Make this not visible to test code? + */ + async init() {} + + /** + * Override this to do additional post-test-function work in a derived fixture. + * + * Called even if init was unsuccessful. + * + * @internal MAINTENANCE_TODO: Make this not visible to test code? + */ + async finalize() { + assert( + this.numOutstandingAsyncExpectations === 0, + 'there were outstanding immediateAsyncExpectations (e.g. expectUncapturedError) at the end of the test' + ); + + // Loop to exhaust the eventualExpectations in case they chain off each other. + while (this.eventualExpectations.length) { + const p = this.eventualExpectations.shift(); + try { + await p; + } catch (ex) { + this.rec.threw(ex); + } + } + + // And clean up any objects now that they're done being used. + for (const o of this.objectsToCleanUp) { + if ('getExtension' in o) { + const WEBGL_lose_context = o.getExtension('WEBGL_lose_context'); + if (WEBGL_lose_context) WEBGL_lose_context.loseContext(); + } else if ('destroy' in o) { + o.destroy(); + } else { + o.close(); + } + } + } + + /** + * Tracks an object to be cleaned up after the test finishes. + * + * MAINTENANCE_TODO: Use this in more places. (Will be easier once .destroy() is allowed on + * invalid objects.) + */ + trackForCleanup(o) { + this.objectsToCleanUp.push(o); + return o; + } + + /** Tracks an object, if it's destroyable, to be cleaned up after the test finishes. */ + tryTrackForCleanup(o) { + if (typeof o === 'object' && o !== null) { + if ( + 'destroy' in o || + 'close' in o || + o instanceof WebGLRenderingContext || + o instanceof WebGL2RenderingContext + ) { + this.objectsToCleanUp.push(o); + } + } + return o; + } + + /** Log a debug message. */ + debug(msg) { + this.rec.debug(new Error(msg)); + } + + /** Throws an exception marking the subcase as skipped. */ + skip(msg) { + throw new SkipTestCase(msg); + } + + /** Log a warning and increase the result status to "Warn". */ + warn(msg) { + this.rec.warn(new Error(msg)); + } + + /** Log an error and increase the result status to "ExpectFailed". */ + fail(msg) { + this.rec.expectationFailed(new Error(msg)); + } + + /** + * Wraps an async function. Tracks its status to fail if the test tries to report a test status + * before the async work has finished. + */ + async immediateAsyncExpectation(fn) { + this.numOutstandingAsyncExpectations++; + const ret = await fn(); + this.numOutstandingAsyncExpectations--; + return ret; + } + + /** + * Wraps an async function, passing it an `Error` object recording the original stack trace. + * The async work will be implicitly waited upon before reporting a test status. + */ + eventualAsyncExpectation(fn) { + const promise = fn(new Error()); + this.eventualExpectations.push(promise); + } + + expectErrorValue(expectedError, ex, niceStack) { + if (!(ex instanceof Error)) { + niceStack.message = `THREW non-error value, of type ${typeof ex}: ${ex}`; + this.rec.expectationFailed(niceStack); + return; + } + const actualName = ex.name; + if (expectedError !== true && actualName !== expectedError) { + niceStack.message = `THREW ${actualName}, instead of ${expectedError}: ${ex}`; + this.rec.expectationFailed(niceStack); + } else { + niceStack.message = `OK: threw ${actualName}: ${ex.message}`; + this.rec.debug(niceStack); + } + } + + /** Expect that the provided promise resolves (fulfills). */ + shouldResolve(p, msg) { + this.eventualAsyncExpectation(async niceStack => { + const m = msg ? ': ' + msg : ''; + try { + await p; + niceStack.message = 'resolved as expected' + m; + } catch (ex) { + niceStack.message = `REJECTED${m}`; + if (ex instanceof Error) { + niceStack.message += '\n' + ex.message; + } + this.rec.expectationFailed(niceStack); + } + }); + } + + /** Expect that the provided promise rejects, with the provided exception name. */ + shouldReject(expectedName, p, msg) { + this.eventualAsyncExpectation(async niceStack => { + const m = msg ? ': ' + msg : ''; + try { + await p; + niceStack.message = 'DID NOT REJECT' + m; + this.rec.expectationFailed(niceStack); + } catch (ex) { + niceStack.message = 'rejected as expected' + m; + this.expectErrorValue(expectedName, ex, niceStack); + } + }); + } + + /** + * Expect that the provided function throws. + * If an `expectedName` is provided, expect that the throw exception has that name. + */ + shouldThrow(expectedError, fn, msg) { + const m = msg ? ': ' + msg : ''; + try { + fn(); + if (expectedError === false) { + this.rec.debug(new Error('did not throw, as expected' + m)); + } else { + this.rec.expectationFailed(new Error('unexpectedly did not throw' + m)); + } + } catch (ex) { + if (expectedError === false) { + this.rec.expectationFailed(new Error('threw unexpectedly' + m)); + } else { + this.expectErrorValue(expectedError, ex, new Error(m)); + } + } + } + + /** Expect that a condition is true. */ + expect(cond, msg) { + if (cond) { + const m = msg ? ': ' + msg : ''; + this.rec.debug(new Error('expect OK' + m)); + } else { + this.rec.expectationFailed(new Error(msg)); + } + return cond; + } + + /** + * If the argument is an `Error`, fail (or warn). If it's `undefined`, no-op. + * If the argument is an array, apply the above behavior on each of elements. + */ + expectOK(error, { mode = 'fail', niceStack } = {}) { + const handleError = error => { + if (error instanceof Error) { + if (niceStack) { + error.stack = niceStack.stack; + } + if (mode === 'fail') { + this.rec.expectationFailed(error); + } else if (mode === 'warn') { + this.rec.warn(error); + } else { + unreachable(); + } + } + }; + + if (Array.isArray(error)) { + for (const e of error) { + handleError(e); + } + } else { + handleError(error); + } + } + + eventualExpectOK(error, { mode = 'fail' } = {}) { + this.eventualAsyncExpectation(async niceStack => { + this.expectOK(await error, { mode, niceStack }); + }); + } +} diff --git a/testing/web-platform/mozilla/tests/webgpu/common/framework/params_builder.js b/testing/web-platform/mozilla/tests/webgpu/common/framework/params_builder.js new file mode 100644 index 0000000000..787911f964 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/framework/params_builder.js @@ -0,0 +1,213 @@ +/** + * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts + **/ import { mergeParams } from '../internal/params_utils.js'; +import { stringifyPublicParams } from '../internal/query/stringify_params.js'; +import { assert, mapLazy } from '../util/util.js'; + +// ================================================================ +// "Public" ParamsBuilder API / Documentation +// ================================================================ + +/** + * Provides doc comments for the methods of CaseParamsBuilder and SubcaseParamsBuilder. + * (Also enforces rough interface match between them.) + */ + +/** + * Base class for `CaseParamsBuilder` and `SubcaseParamsBuilder`. + */ +export class ParamsBuilderBase { + constructor(cases) { + this.cases = cases; + } + + /** + * Hidden from test files. Use `builderIterateCasesWithSubcases` to access this. + */ +} + +/** + * Calls the (normally hidden) `iterateCasesWithSubcases()` method. + */ +export function builderIterateCasesWithSubcases(builder) { + return builder.iterateCasesWithSubcases(); +} + +/** + * Builder for combinatorial test **case** parameters. + * + * CaseParamsBuilder is immutable. Each method call returns a new, immutable object, + * modifying the list of cases according to the method called. + * + * This means, for example, that the `unit` passed into `TestBuilder.params()` can be reused. + */ +export class CaseParamsBuilder extends ParamsBuilderBase { + *iterateCasesWithSubcases() { + for (const a of this.cases()) { + yield [a, undefined]; + } + } + + [Symbol.iterator]() { + return this.cases(); + } + + /** @inheritDoc */ + expandWithParams(expander) { + const newGenerator = expanderGenerator(this.cases, expander); + return new CaseParamsBuilder(() => newGenerator({})); + } + + /** @inheritDoc */ + expand(key, expander) { + return this.expandWithParams(function* (p) { + for (const value of expander(p)) { + yield { [key]: value }; + } + }); + } + + /** @inheritDoc */ + combineWithParams(newParams) { + assertNotGenerator(newParams); + const seenValues = new Set(); + for (const params of newParams) { + const paramsStr = stringifyPublicParams(params); + assert(!seenValues.has(paramsStr), `Duplicate entry in combine[WithParams]: ${paramsStr}`); + seenValues.add(paramsStr); + } + + return this.expandWithParams(() => newParams); + } + + /** @inheritDoc */ + combine(key, values) { + assertNotGenerator(values); + const mapped = mapLazy(values, v => ({ [key]: v })); + return this.combineWithParams(mapped); + } + + /** @inheritDoc */ + filter(pred) { + const newGenerator = filterGenerator(this.cases, pred); + return new CaseParamsBuilder(() => newGenerator({})); + } + + /** @inheritDoc */ + unless(pred) { + return this.filter(x => !pred(x)); + } + + /** + * "Finalize" the list of cases and begin defining subcases. + * Returns a new SubcaseParamsBuilder. Methods called on SubcaseParamsBuilder + * generate new subcases instead of new cases. + */ + beginSubcases() { + return new SubcaseParamsBuilder( + () => this.cases(), + function* () { + yield {}; + } + ); + } +} + +/** + * The unit CaseParamsBuilder, representing a single case with no params: `[ {} ]`. + * + * `punit` is passed to every `.params()`/`.paramsSubcasesOnly()` call, so `kUnitCaseParamsBuilder` + * is only explicitly needed if constructing a ParamsBuilder outside of a test builder. + */ +export const kUnitCaseParamsBuilder = new CaseParamsBuilder(function* () { + yield {}; +}); + +/** + * Builder for combinatorial test _subcase_ parameters. + * + * SubcaseParamsBuilder is immutable. Each method call returns a new, immutable object, + * modifying the list of subcases according to the method called. + */ +export class SubcaseParamsBuilder extends ParamsBuilderBase { + constructor(cases, generator) { + super(cases); + this.subcases = generator; + } + + *iterateCasesWithSubcases() { + for (const caseP of this.cases()) { + const subcases = Array.from(this.subcases(caseP)); + if (subcases.length) { + yield [caseP, subcases]; + } + } + } + + /** @inheritDoc */ + expandWithParams(expander) { + return new SubcaseParamsBuilder(this.cases, expanderGenerator(this.subcases, expander)); + } + + /** @inheritDoc */ + expand(key, expander) { + return this.expandWithParams(function* (p) { + for (const value of expander(p)) { + // TypeScript doesn't know here that NewPKey is always a single literal string type. + yield { [key]: value }; + } + }); + } + + /** @inheritDoc */ + combineWithParams(newParams) { + assertNotGenerator(newParams); + return this.expandWithParams(() => newParams); + } + + /** @inheritDoc */ + combine(key, values) { + assertNotGenerator(values); + return this.expand(key, () => values); + } + + /** @inheritDoc */ + filter(pred) { + return new SubcaseParamsBuilder(this.cases, filterGenerator(this.subcases, pred)); + } + + /** @inheritDoc */ + unless(pred) { + return this.filter(x => !pred(x)); + } +} + +function expanderGenerator(baseGenerator, expander) { + return function* (base) { + for (const a of baseGenerator(base)) { + for (const b of expander(mergeParams(base, a))) { + yield mergeParams(a, b); + } + } + }; +} + +function filterGenerator(baseGenerator, pred) { + return function* (base) { + for (const a of baseGenerator(base)) { + if (pred(mergeParams(base, a))) { + yield a; + } + } + }; +} + +/** Assert an object is not a Generator (a thing returned from a generator function). */ +function assertNotGenerator(x) { + if ('constructor' in x) { + assert( + x.constructor !== (function* () {})().constructor, + 'Argument must not be a generator, as generators are not reusable' + ); + } +} diff --git a/testing/web-platform/mozilla/tests/webgpu/common/framework/resources.js b/testing/web-platform/mozilla/tests/webgpu/common/framework/resources.js new file mode 100644 index 0000000000..72eabeda4e --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/framework/resources.js @@ -0,0 +1,111 @@ +/** + * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts + **/ /** + * Base path for resources. The default value is correct for non-worker WPT, but standalone and + * workers must access resources using a different base path, so this is overridden in + * `test_worker-worker.ts` and `standalone.ts`. + */ let baseResourcePath = './resources'; +let crossOriginHost = ''; + +function getAbsoluteBaseResourcePath(path) { + // Path is already an absolute one. + if (path[0] === '/') { + return path; + } + + // Path is relative + const relparts = window.location.pathname.split('/'); + relparts.pop(); + const pathparts = path.split('/'); + + let i; + for (i = 0; i < pathparts.length; ++i) { + switch (pathparts[i]) { + case '': + break; + case '.': + break; + case '..': + relparts.pop(); + break; + default: + relparts.push(pathparts[i]); + break; + } + } + + return relparts.join('/'); +} + +function runningOnLocalHost() { + const hostname = window.location.hostname; + return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1'; +} + +/** + * Get a path to a resource in the `resources` directory relative to the current execution context + * (html file or worker .js file), for `fetch()`, `<img>`, `<video>`, etc but from cross origin host. + * Provide onlineUrl if the case running online. + * @internal MAINTENANCE_TODO: Cases may run in the LAN environment (not localhost but no internet + * access). We temporarily use `crossOriginHost` to configure the cross origin host name in that situation. + * But opening to auto-detect mechanism or other solutions. + */ +export function getCrossOriginResourcePath(pathRelativeToResourcesDir, onlineUrl = '') { + // A cross origin host has been configured. Use this to load resource. + if (crossOriginHost !== '') { + return ( + crossOriginHost + + getAbsoluteBaseResourcePath(baseResourcePath) + + '/' + + pathRelativeToResourcesDir + ); + } + + // Using 'localhost' and '127.0.0.1' trick to load cross origin resource. Set cross origin host name + // to 'localhost' if case is not running in 'localhost' domain. Otherwise, use '127.0.0.1'. + // host name to locahost unless the server running in + if (runningOnLocalHost()) { + let crossOriginHostName = ''; + if (location.hostname === 'localhost') { + crossOriginHostName = 'http://127.0.0.1'; + } else { + crossOriginHostName = 'http://localhost'; + } + + return ( + crossOriginHostName + + ':' + + location.port + + getAbsoluteBaseResourcePath(baseResourcePath) + + '/' + + pathRelativeToResourcesDir + ); + } + + return onlineUrl; +} + +/** + * Get a path to a resource in the `resources` directory, relative to the current execution context + * (html file or worker .js file), for `fetch()`, `<img>`, `<video>`, etc. Pass the cross origin host + * name if wants to load resoruce from cross origin host. + */ +export function getResourcePath(pathRelativeToResourcesDir) { + return baseResourcePath + '/' + pathRelativeToResourcesDir; +} + +/** + * Set the base resource path (path to the `resources` directory relative to the current + * execution context). + */ +export function setBaseResourcePath(path) { + baseResourcePath = path; +} + +/** + * Set the cross origin host and cases related to cross origin + * will load resource from the given host. + */ +export function setCrossOriginHost(host) { + crossOriginHost = host; +} 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 new file mode 100644 index 0000000000..de016471cd --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/framework/test_config.js @@ -0,0 +1,10 @@ +/** + * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts + **/ + +export const globalTestConfig = { + maxSubcasesInFlight: 500, + testHeartbeatCallback: () => {}, + noRaceWithRejectOnTimeout: false, + unrollConstEvalLoops: false, +}; diff --git a/testing/web-platform/mozilla/tests/webgpu/common/framework/test_group.js b/testing/web-platform/mozilla/tests/webgpu/common/framework/test_group.js new file mode 100644 index 0000000000..2d1d3c1c07 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/framework/test_group.js @@ -0,0 +1,3 @@ +/** + * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts + **/ export { makeTestGroup } from '../internal/test_group.js'; 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 new file mode 100644 index 0000000000..e9aa0f66fc --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/file_loader.js @@ -0,0 +1,96 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { assert } from '../util/util.js'; +import { parseQuery } from './query/parseQuery.js'; + + +import { loadTreeForQuery } from './tree.js'; + +// A listing file, e.g. either of: +// - `src/webgpu/listing.ts` (which is dynamically computed, has a Promise<TestSuiteListing>) +// - `out/webgpu/listing.js` (which is pre-baked, has a TestSuiteListing) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// Base class for DefaultTestFileLoader and FakeTestFileLoader. +export class TestFileLoader extends EventTarget { + + + + importSpecFile(suite, path) { + const url = `${suite}/${path.join('/')}.spec.js`; + this.dispatchEvent( + new MessageEvent('import', { data: { url } })); + + return this.import(url); + } + + async loadTree(query, subqueriesToExpand = []) { + const tree = await loadTreeForQuery( + this, + query, + subqueriesToExpand.map((s) => { + const q = parseQuery(s); + assert(q.level >= 2, () => `subqueriesToExpand entries should not be multi-file:\n ${q}`); + return q; + })); + + this.dispatchEvent(new MessageEvent('finish')); + return tree; + } + + async loadCases(query) { + const tree = await this.loadTree(query); + return tree.iterateLeaves(); + } +} + +export class DefaultTestFileLoader extends TestFileLoader { + async listing(suite) { + return (await import(`../../${suite}/listing.js`)).listing; + } + + import(path) { + return import(`../../${path}`); + } +} +//# sourceMappingURL=file_loader.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/file_loader.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/file_loader.js.map new file mode 100644 index 0000000000..3a5d5b17f4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/file_loader.js.map @@ -0,0 +1 @@ +{"version":3,"file":"file_loader.js","names":["assert","parseQuery","loadTreeForQuery","TestFileLoader","EventTarget","importSpecFile","suite","path","url","join","dispatchEvent","MessageEvent","data","import","loadTree","query","subqueriesToExpand","tree","map","s","q","level","loadCases","iterateLeaves","DefaultTestFileLoader","listing"],"sources":["../../../src/common/internal/file_loader.ts"],"sourcesContent":["import { IterableTestGroup } from '../internal/test_group.js';\nimport { assert } from '../util/util.js';\n\nimport { parseQuery } from './query/parseQuery.js';\nimport { TestQuery } from './query/query.js';\nimport { TestSuiteListing } from './test_suite_listing.js';\nimport { loadTreeForQuery, TestTree, TestTreeLeaf } from './tree.js';\n\n// A listing file, e.g. either of:\n// - `src/webgpu/listing.ts` (which is dynamically computed, has a Promise<TestSuiteListing>)\n// - `out/webgpu/listing.js` (which is pre-baked, has a TestSuiteListing)\ninterface ListingFile {\n listing: Promise<TestSuiteListing> | TestSuiteListing;\n}\n\n// A .spec.ts file, as imported.\nexport interface SpecFile {\n readonly description: string;\n readonly g: IterableTestGroup;\n}\n\nexport interface ImportInfo {\n url: string;\n}\n\ninterface TestFileLoaderEventMap {\n import: MessageEvent<ImportInfo>;\n finish: MessageEvent<void>;\n}\n\nexport interface TestFileLoader extends EventTarget {\n addEventListener<K extends keyof TestFileLoaderEventMap>(\n type: K,\n listener: (this: TestFileLoader, ev: TestFileLoaderEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions\n ): void;\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions\n ): void;\n removeEventListener<K extends keyof TestFileLoaderEventMap>(\n type: K,\n listener: (this: TestFileLoader, ev: TestFileLoaderEventMap[K]) => void,\n options?: boolean | EventListenerOptions\n ): void;\n removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions\n ): void;\n}\n\n// Base class for DefaultTestFileLoader and FakeTestFileLoader.\nexport abstract class TestFileLoader extends EventTarget {\n abstract listing(suite: string): Promise<TestSuiteListing>;\n protected abstract import(path: string): Promise<SpecFile>;\n\n importSpecFile(suite: string, path: string[]): Promise<SpecFile> {\n const url = `${suite}/${path.join('/')}.spec.js`;\n this.dispatchEvent(\n new MessageEvent<ImportInfo>('import', { data: { url } })\n );\n return this.import(url);\n }\n\n async loadTree(query: TestQuery, subqueriesToExpand: string[] = []): Promise<TestTree> {\n const tree = await loadTreeForQuery(\n this,\n query,\n subqueriesToExpand.map(s => {\n const q = parseQuery(s);\n assert(q.level >= 2, () => `subqueriesToExpand entries should not be multi-file:\\n ${q}`);\n return q;\n })\n );\n this.dispatchEvent(new MessageEvent<void>('finish'));\n return tree;\n }\n\n async loadCases(query: TestQuery): Promise<IterableIterator<TestTreeLeaf>> {\n const tree = await this.loadTree(query);\n return tree.iterateLeaves();\n }\n}\n\nexport class DefaultTestFileLoader extends TestFileLoader {\n async listing(suite: string): Promise<TestSuiteListing> {\n return ((await import(`../../${suite}/listing.js`)) as ListingFile).listing;\n }\n\n import(path: string): Promise<SpecFile> {\n return import(`../../${path}`);\n }\n}\n"],"mappings":";AAAA;AAAA,GACA,SAASA,MAAM,QAAQ,iBAAiB;AAExC,SAASC,UAAU,QAAQ,uBAAuB;;;AAGlD,SAASC,gBAAgB,QAAgC,WAAW;;AAEpE;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CA;AACA,OAAO,MAAeC,cAAc,SAASC,WAAW,CAAC;;;;EAIvDC,cAAc,CAACC,KAAa,EAAEC,IAAc,EAAqB;IAC/D,MAAMC,GAAG,GAAI,GAAEF,KAAM,IAAGC,IAAI,CAACE,IAAI,CAAC,GAAG,CAAE,UAAS;IAChD,IAAI,CAACC,aAAa;IAChB,IAAIC,YAAY,CAAa,QAAQ,EAAE,EAAEC,IAAI,EAAE,EAAEJ,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAC1D;;IACD,OAAO,IAAI,CAACK,MAAM,CAACL,GAAG,CAAC;EACzB;;EAEA,MAAMM,QAAQ,CAACC,KAAgB,EAAEC,kBAA4B,GAAG,EAAE,EAAqB;IACrF,MAAMC,IAAI,GAAG,MAAMf,gBAAgB;IACjC,IAAI;IACJa,KAAK;IACLC,kBAAkB,CAACE,GAAG,CAAC,CAAAC,CAAC,KAAI;MAC1B,MAAMC,CAAC,GAAGnB,UAAU,CAACkB,CAAC,CAAC;MACvBnB,MAAM,CAACoB,CAAC,CAACC,KAAK,IAAI,CAAC,EAAE,MAAO,2DAA0DD,CAAE,EAAC,CAAC;MAC1F,OAAOA,CAAC;IACV,CAAC,CAAC,CACH;;IACD,IAAI,CAACV,aAAa,CAAC,IAAIC,YAAY,CAAO,QAAQ,CAAC,CAAC;IACpD,OAAOM,IAAI;EACb;;EAEA,MAAMK,SAAS,CAACP,KAAgB,EAA2C;IACzE,MAAME,IAAI,GAAG,MAAM,IAAI,CAACH,QAAQ,CAACC,KAAK,CAAC;IACvC,OAAOE,IAAI,CAACM,aAAa,EAAE;EAC7B;AACF;;AAEA,OAAO,MAAMC,qBAAqB,SAASrB,cAAc,CAAC;EACxD,MAAMsB,OAAO,CAACnB,KAAa,EAA6B;IACtD,OAAO,CAAE,MAAM,MAAM,CAAE,SAAQA,KAAM,aAAY,CAAC,EAAkBmB,OAAO;EAC7E;;EAEAZ,MAAM,CAACN,IAAY,EAAqB;IACtC,OAAO,MAAM,CAAE,SAAQA,IAAK,EAAC,CAAC;EAChC;AACF"}
\ No newline at end of file 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 new file mode 100644 index 0000000000..0414e45def --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/log_message.js @@ -0,0 +1,45 @@ +/** +* 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); + + this.name = name; + this.stack = ex.stack; + if ('extra' in ex) { + this.extra = ex.extra; + } + } + + /** Set a flag so the stack is not printed in toJSON(). */ + setStackHidden(stackHiddenMessage) { + this.stackHiddenMessage ??= stackHiddenMessage; + } + + toJSON() { + let m = this.name; + if (this.message) m += ': ' + this.message; + if (this.stack) { + if (this.stackHiddenMessage === undefined) { + m += '\n' + extractImportantStackTrace(this); + } else if (this.stackHiddenMessage) { + m += `\n at (elided: ${this.stackHiddenMessage})`; + } + } + return m; + } +} + +/** + * Returns a string, nicely indented, for debug logs. + * This is used in the cmdline and wpt runtimes. In WPT, it shows up in the `*-actual.txt` file. + */ +export function prettyPrintLog(log) { + return ' - ' + log.toJSON().replace(/\n/g, '\n '); +} +//# sourceMappingURL=log_message.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/log_message.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/log_message.js.map new file mode 100644 index 0000000000..2af81c7452 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/log_message.js.map @@ -0,0 +1 @@ +{"version":3,"file":"log_message.js","names":["extractImportantStackTrace","LogMessageWithStack","Error","stackHiddenMessage","undefined","constructor","name","ex","message","stack","extra","setStackHidden","toJSON","m","prettyPrintLog","log","replace"],"sources":["../../../../src/common/internal/logging/log_message.ts"],"sourcesContent":["import { ErrorWithExtra } from '../../util/util.js';\nimport { extractImportantStackTrace } from '../stack.js';\n\nexport class LogMessageWithStack extends Error {\n readonly extra: unknown;\n\n private stackHiddenMessage: string | undefined = undefined;\n\n constructor(name: string, ex: Error | ErrorWithExtra) {\n super(ex.message);\n\n this.name = name;\n this.stack = ex.stack;\n if ('extra' in ex) {\n this.extra = ex.extra;\n }\n }\n\n /** Set a flag so the stack is not printed in toJSON(). */\n setStackHidden(stackHiddenMessage: string) {\n this.stackHiddenMessage ??= stackHiddenMessage;\n }\n\n toJSON(): string {\n let m = this.name;\n if (this.message) m += ': ' + this.message;\n if (this.stack) {\n if (this.stackHiddenMessage === undefined) {\n m += '\\n' + extractImportantStackTrace(this);\n } else if (this.stackHiddenMessage) {\n m += `\\n at (elided: ${this.stackHiddenMessage})`;\n }\n }\n return m;\n }\n}\n\n/**\n * Returns a string, nicely indented, for debug logs.\n * This is used in the cmdline and wpt runtimes. In WPT, it shows up in the `*-actual.txt` file.\n */\nexport function prettyPrintLog(log: LogMessageWithStack): string {\n return ' - ' + log.toJSON().replace(/\\n/g, '\\n ');\n}\n"],"mappings":";AAAA;AAAA,GACA,SAASA,0BAA0B,QAAQ,aAAa;AAExD,OAAO,MAAMC,mBAAmB,SAASC,KAAK,CAAC;;;EAGrCC,kBAAkB,GAAuBC,SAAS;;EAE1DC,WAAW,CAACC,IAAY,EAAEC,EAA0B,EAAE;IACpD,KAAK,CAACA,EAAE,CAACC,OAAO,CAAC;;IAEjB,IAAI,CAACF,IAAI,GAAGA,IAAI;IAChB,IAAI,CAACG,KAAK,GAAGF,EAAE,CAACE,KAAK;IACrB,IAAI,OAAO,IAAIF,EAAE,EAAE;MACjB,IAAI,CAACG,KAAK,GAAGH,EAAE,CAACG,KAAK;IACvB;EACF;;EAEA;EACAC,cAAc,CAACR,kBAA0B,EAAE;IACzC,IAAI,CAACA,kBAAkB,KAAKA,kBAAkB;EAChD;;EAEAS,MAAM,GAAW;IACf,IAAIC,CAAC,GAAG,IAAI,CAACP,IAAI;IACjB,IAAI,IAAI,CAACE,OAAO,EAAEK,CAAC,IAAI,IAAI,GAAG,IAAI,CAACL,OAAO;IAC1C,IAAI,IAAI,CAACC,KAAK,EAAE;MACd,IAAI,IAAI,CAACN,kBAAkB,KAAKC,SAAS,EAAE;QACzCS,CAAC,IAAI,IAAI,GAAGb,0BAA0B,CAAC,IAAI,CAAC;MAC9C,CAAC,MAAM,IAAI,IAAI,CAACG,kBAAkB,EAAE;QAClCU,CAAC,IAAK,mBAAkB,IAAI,CAACV,kBAAmB,GAAE;MACpD;IACF;IACA,OAAOU,CAAC;EACV;AACF;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASC,cAAc,CAACC,GAAwB,EAAU;EAC/D,OAAO,MAAM,GAAGA,GAAG,CAACH,MAAM,EAAE,CAACI,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC;AACvD"}
\ No newline at end of file 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 new file mode 100644 index 0000000000..c197579d4a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/logger.js @@ -0,0 +1,31 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { version } from '../version.js'; +import { TestCaseRecorder } from './test_case_recorder.js'; + + + +export class Logger { + static globalDebugMode = false; + + + results = new Map(); + + constructor({ overrideDebugMode } = {}) { + this.overriddenDebugMode = overrideDebugMode; + } + + record(name) { + const result = { status: 'running', timems: -1 }; + this.results.set(name, result); + return [ + new TestCaseRecorder(result, this.overriddenDebugMode ?? Logger.globalDebugMode), + result]; + + } + + asJSON(space) { + return JSON.stringify({ version, results: Array.from(this.results) }, undefined, space); + } +} +//# sourceMappingURL=logger.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/logger.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/logger.js.map new file mode 100644 index 0000000000..185f17edef --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/logger.js.map @@ -0,0 +1 @@ +{"version":3,"file":"logger.js","names":["version","TestCaseRecorder","Logger","globalDebugMode","results","Map","constructor","overrideDebugMode","overriddenDebugMode","record","name","result","status","timems","set","asJSON","space","JSON","stringify","Array","from","undefined"],"sources":["../../../../src/common/internal/logging/logger.ts"],"sourcesContent":["import { version } from '../version.js';\n\nimport { LiveTestCaseResult } from './result.js';\nimport { TestCaseRecorder } from './test_case_recorder.js';\n\nexport type LogResults = Map<string, LiveTestCaseResult>;\n\nexport class Logger {\n static globalDebugMode: boolean = false;\n\n readonly overriddenDebugMode: boolean | undefined;\n readonly results: LogResults = new Map();\n\n constructor({ overrideDebugMode }: { overrideDebugMode?: boolean } = {}) {\n this.overriddenDebugMode = overrideDebugMode;\n }\n\n record(name: string): [TestCaseRecorder, LiveTestCaseResult] {\n const result: LiveTestCaseResult = { status: 'running', timems: -1 };\n this.results.set(name, result);\n return [\n new TestCaseRecorder(result, this.overriddenDebugMode ?? Logger.globalDebugMode),\n result,\n ];\n }\n\n asJSON(space?: number): string {\n return JSON.stringify({ version, results: Array.from(this.results) }, undefined, space);\n }\n}\n"],"mappings":";AAAA;AAAA,GAAA,SAASA,OAAO,QAAQ,eAAe;AAGvC,SAASC,gBAAgB,QAAQ,yBAAyB;;;;AAI1D,OAAO,MAAMC,MAAM,CAAC;EAClB,OAAOC,eAAe,GAAY,KAAK;;;EAG9BC,OAAO,GAAe,IAAIC,GAAG,EAAE;;EAExCC,WAAW,CAAC,EAAEC,iBAAiB,CAAkC,CAAC,GAAG,CAAC,CAAC,EAAE;IACvE,IAAI,CAACC,mBAAmB,GAAGD,iBAAiB;EAC9C;;EAEAE,MAAM,CAACC,IAAY,EAA0C;IAC3D,MAAMC,MAA0B,GAAG,EAAEC,MAAM,EAAE,SAAS,EAAEC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IACpE,IAAI,CAACT,OAAO,CAACU,GAAG,CAACJ,IAAI,EAAEC,MAAM,CAAC;IAC9B,OAAO;IACL,IAAIV,gBAAgB,CAACU,MAAM,EAAE,IAAI,CAACH,mBAAmB,IAAIN,MAAM,CAACC,eAAe,CAAC;IAChFQ,MAAM,CACP;;EACH;;EAEAI,MAAM,CAACC,KAAc,EAAU;IAC7B,OAAOC,IAAI,CAACC,SAAS,CAAC,EAAElB,OAAO,EAAEI,OAAO,EAAEe,KAAK,CAACC,IAAI,CAAC,IAAI,CAAChB,OAAO,CAAC,CAAC,CAAC,EAAEiB,SAAS,EAAEL,KAAK,CAAC;EACzF;AACF"}
\ No newline at end of file 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 new file mode 100644 index 0000000000..bbf217be6f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/result.js @@ -0,0 +1,4 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export {}; +//# sourceMappingURL=result.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/result.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/result.js.map new file mode 100644 index 0000000000..091c7cba8c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/result.js.map @@ -0,0 +1 @@ +{"version":3,"file":"result.js","names":[],"sources":["../../../../src/common/internal/logging/result.ts"],"sourcesContent":["import { LogMessageWithStack } from './log_message.js';\n\n// MAINTENANCE_TODO: Add warn expectations\nexport type Expectation = 'pass' | 'skip' | 'fail';\n\nexport type Status = 'running' | 'warn' | Expectation;\n\nexport interface TestCaseResult {\n status: Status;\n timems: number;\n}\n\nexport interface LiveTestCaseResult extends TestCaseResult {\n logs?: LogMessageWithStack[];\n}\n\nexport interface TransferredTestCaseResult extends TestCaseResult {\n // When transferred from a worker, a LogMessageWithStack turns into a generic Error\n // (its prototype gets lost and replaced with Error).\n logs?: Error[];\n}\n"],"mappings":";AAAA;AAAA,G"}
\ 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 new file mode 100644 index 0000000000..85ea61d862 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/test_case_recorder.js @@ -0,0 +1,159 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { SkipTestCase, UnexpectedPassError } from '../../framework/fixture.js';import { globalTestConfig } from '../../framework/test_config.js';import { now, assert } from '../../util/util.js'; + +import { LogMessageWithStack } from './log_message.js';var + + +LogSeverity;(function (LogSeverity) {LogSeverity[LogSeverity["Pass"] = 0] = "Pass";LogSeverity[LogSeverity["Skip"] = 1] = "Skip";LogSeverity[LogSeverity["Warn"] = 2] = "Warn";LogSeverity[LogSeverity["ExpectFailed"] = 3] = "ExpectFailed";LogSeverity[LogSeverity["ValidationFailed"] = 4] = "ValidationFailed";LogSeverity[LogSeverity["ThrewException"] = 5] = "ThrewException";})(LogSeverity || (LogSeverity = {})); + + + + + + + + +const kMaxLogStacks = 2; +const kMinSeverityForStack = LogSeverity.Warn; + +/** Holds onto a LiveTestCaseResult owned by the Logger, and writes the results into it. */ +export class TestCaseRecorder { + + inSubCase = false; + subCaseStatus = LogSeverity.Pass; + finalCaseStatus = LogSeverity.Pass; + hideStacksBelowSeverity = kMinSeverityForStack; + startTime = -1; + logs = []; + logLinesAtCurrentSeverity = 0; + debugging = false; + /** Used to dedup log messages which have identical stacks. */ + messagesForPreviouslySeenStacks = new Map(); + + constructor(result, debugging) { + this.result = result; + this.debugging = debugging; + } + + start() { + assert(this.startTime < 0, 'TestCaseRecorder cannot be reused'); + this.startTime = now(); + } + + finish() { + assert(this.startTime >= 0, 'finish() before start()'); + + const timeMilliseconds = now() - this.startTime; + // Round to next microsecond to avoid storing useless .xxxx00000000000002 in results. + this.result.timems = Math.ceil(timeMilliseconds * 1000) / 1000; + + // Convert numeric enum back to string (but expose 'exception' as 'fail') + this.result.status = + this.finalCaseStatus === LogSeverity.Pass ? + 'pass' : + this.finalCaseStatus === LogSeverity.Skip ? + 'skip' : + this.finalCaseStatus === LogSeverity.Warn ? + 'warn' : + 'fail'; // Everything else is an error + + this.result.logs = this.logs; + } + + beginSubCase() { + this.subCaseStatus = LogSeverity.Pass; + this.inSubCase = true; + } + + endSubCase(expectedStatus) { + try { + if (expectedStatus === 'fail') { + if (this.subCaseStatus <= LogSeverity.Warn) { + throw new UnexpectedPassError(); + } else { + this.subCaseStatus = LogSeverity.Pass; + } + } + } finally { + this.inSubCase = false; + if (this.subCaseStatus > this.finalCaseStatus) { + this.finalCaseStatus = this.subCaseStatus; + } + } + } + + injectResult(injectedResult) { + Object.assign(this.result, injectedResult); + } + + debug(ex) { + if (!this.debugging) return; + this.logImpl(LogSeverity.Pass, 'DEBUG', ex); + } + + info(ex) { + this.logImpl(LogSeverity.Pass, 'INFO', ex); + } + + skipped(ex) { + this.logImpl(LogSeverity.Skip, 'SKIP', ex); + } + + warn(ex) { + this.logImpl(LogSeverity.Warn, 'WARN', ex); + } + + expectationFailed(ex) { + this.logImpl(LogSeverity.ExpectFailed, 'EXPECTATION FAILED', ex); + } + + validationFailed(ex) { + this.logImpl(LogSeverity.ValidationFailed, 'VALIDATION FAILED', ex); + } + + threw(ex) { + if (ex instanceof SkipTestCase) { + this.skipped(ex); + return; + } + this.logImpl(LogSeverity.ThrewException, 'EXCEPTION', ex); + } + + logImpl(level, name, baseException) { + assert(baseException instanceof Error, 'test threw a non-Error object'); + globalTestConfig.testHeartbeatCallback(); + const logMessage = new LogMessageWithStack(name, baseException); + + // Final case status should be the "worst" of all log entries. + if (this.inSubCase) { + if (level > this.subCaseStatus) this.subCaseStatus = level; + } else { + if (level > this.finalCaseStatus) this.finalCaseStatus = level; + } + + // setFirstLineOnly for all logs except `kMaxLogStacks` stacks at the highest severity + if (level > this.hideStacksBelowSeverity) { + this.logLinesAtCurrentSeverity = 0; + this.hideStacksBelowSeverity = level; + + // Go back and setFirstLineOnly for everything of a lower log level + for (const log of this.logs) { + log.setStackHidden('below max severity'); + } + } + if (level === this.hideStacksBelowSeverity) { + this.logLinesAtCurrentSeverity++; + } else if (level < kMinSeverityForStack) { + logMessage.setStackHidden(''); + } else if (level < this.hideStacksBelowSeverity) { + logMessage.setStackHidden('below max severity'); + } + if (this.logLinesAtCurrentSeverity > kMaxLogStacks) { + logMessage.setStackHidden(`only ${kMaxLogStacks} shown`); + } + + this.logs.push(logMessage); + } +} +//# sourceMappingURL=test_case_recorder.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/test_case_recorder.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/test_case_recorder.js.map new file mode 100644 index 0000000000..06c2e79bcd --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/logging/test_case_recorder.js.map @@ -0,0 +1 @@ +{"version":3,"file":"test_case_recorder.js","names":["SkipTestCase","UnexpectedPassError","globalTestConfig","now","assert","LogMessageWithStack","LogSeverity","kMaxLogStacks","kMinSeverityForStack","Warn","TestCaseRecorder","inSubCase","subCaseStatus","Pass","finalCaseStatus","hideStacksBelowSeverity","startTime","logs","logLinesAtCurrentSeverity","debugging","messagesForPreviouslySeenStacks","Map","constructor","result","start","finish","timeMilliseconds","timems","Math","ceil","status","Skip","beginSubCase","endSubCase","expectedStatus","injectResult","injectedResult","Object","assign","debug","ex","logImpl","info","skipped","warn","expectationFailed","ExpectFailed","validationFailed","ValidationFailed","threw","ThrewException","level","name","baseException","Error","testHeartbeatCallback","logMessage","log","setStackHidden","push"],"sources":["../../../../src/common/internal/logging/test_case_recorder.ts"],"sourcesContent":["import { SkipTestCase, UnexpectedPassError } from '../../framework/fixture.js';\nimport { globalTestConfig } from '../../framework/test_config.js';\nimport { now, assert } from '../../util/util.js';\n\nimport { LogMessageWithStack } from './log_message.js';\nimport { Expectation, LiveTestCaseResult } from './result.js';\n\nenum LogSeverity {\n Pass = 0,\n Skip = 1,\n Warn = 2,\n ExpectFailed = 3,\n ValidationFailed = 4,\n ThrewException = 5,\n}\n\nconst kMaxLogStacks = 2;\nconst kMinSeverityForStack = LogSeverity.Warn;\n\n/** Holds onto a LiveTestCaseResult owned by the Logger, and writes the results into it. */\nexport class TestCaseRecorder {\n private result: LiveTestCaseResult;\n private inSubCase: boolean = false;\n private subCaseStatus = LogSeverity.Pass;\n private finalCaseStatus = LogSeverity.Pass;\n private hideStacksBelowSeverity = kMinSeverityForStack;\n private startTime = -1;\n private logs: LogMessageWithStack[] = [];\n private logLinesAtCurrentSeverity = 0;\n private debugging = false;\n /** Used to dedup log messages which have identical stacks. */\n private messagesForPreviouslySeenStacks = new Map<string, LogMessageWithStack>();\n\n constructor(result: LiveTestCaseResult, debugging: boolean) {\n this.result = result;\n this.debugging = debugging;\n }\n\n start(): void {\n assert(this.startTime < 0, 'TestCaseRecorder cannot be reused');\n this.startTime = now();\n }\n\n finish(): void {\n assert(this.startTime >= 0, 'finish() before start()');\n\n const timeMilliseconds = now() - this.startTime;\n // Round to next microsecond to avoid storing useless .xxxx00000000000002 in results.\n this.result.timems = Math.ceil(timeMilliseconds * 1000) / 1000;\n\n // Convert numeric enum back to string (but expose 'exception' as 'fail')\n this.result.status =\n this.finalCaseStatus === LogSeverity.Pass\n ? 'pass'\n : this.finalCaseStatus === LogSeverity.Skip\n ? 'skip'\n : this.finalCaseStatus === LogSeverity.Warn\n ? 'warn'\n : 'fail'; // Everything else is an error\n\n this.result.logs = this.logs;\n }\n\n beginSubCase() {\n this.subCaseStatus = LogSeverity.Pass;\n this.inSubCase = true;\n }\n\n endSubCase(expectedStatus: Expectation) {\n try {\n if (expectedStatus === 'fail') {\n if (this.subCaseStatus <= LogSeverity.Warn) {\n throw new UnexpectedPassError();\n } else {\n this.subCaseStatus = LogSeverity.Pass;\n }\n }\n } finally {\n this.inSubCase = false;\n if (this.subCaseStatus > this.finalCaseStatus) {\n this.finalCaseStatus = this.subCaseStatus;\n }\n }\n }\n\n injectResult(injectedResult: LiveTestCaseResult): void {\n Object.assign(this.result, injectedResult);\n }\n\n debug(ex: Error): void {\n if (!this.debugging) return;\n this.logImpl(LogSeverity.Pass, 'DEBUG', ex);\n }\n\n info(ex: Error): void {\n this.logImpl(LogSeverity.Pass, 'INFO', ex);\n }\n\n skipped(ex: SkipTestCase): void {\n this.logImpl(LogSeverity.Skip, 'SKIP', ex);\n }\n\n warn(ex: Error): void {\n this.logImpl(LogSeverity.Warn, 'WARN', ex);\n }\n\n expectationFailed(ex: Error): void {\n this.logImpl(LogSeverity.ExpectFailed, 'EXPECTATION FAILED', ex);\n }\n\n validationFailed(ex: Error): void {\n this.logImpl(LogSeverity.ValidationFailed, 'VALIDATION FAILED', ex);\n }\n\n threw(ex: unknown): void {\n if (ex instanceof SkipTestCase) {\n this.skipped(ex);\n return;\n }\n this.logImpl(LogSeverity.ThrewException, 'EXCEPTION', ex);\n }\n\n private logImpl(level: LogSeverity, name: string, baseException: unknown): void {\n assert(baseException instanceof Error, 'test threw a non-Error object');\n globalTestConfig.testHeartbeatCallback();\n const logMessage = new LogMessageWithStack(name, baseException);\n\n // Final case status should be the \"worst\" of all log entries.\n if (this.inSubCase) {\n if (level > this.subCaseStatus) this.subCaseStatus = level;\n } else {\n if (level > this.finalCaseStatus) this.finalCaseStatus = level;\n }\n\n // setFirstLineOnly for all logs except `kMaxLogStacks` stacks at the highest severity\n if (level > this.hideStacksBelowSeverity) {\n this.logLinesAtCurrentSeverity = 0;\n this.hideStacksBelowSeverity = level;\n\n // Go back and setFirstLineOnly for everything of a lower log level\n for (const log of this.logs) {\n log.setStackHidden('below max severity');\n }\n }\n if (level === this.hideStacksBelowSeverity) {\n this.logLinesAtCurrentSeverity++;\n } else if (level < kMinSeverityForStack) {\n logMessage.setStackHidden('');\n } else if (level < this.hideStacksBelowSeverity) {\n logMessage.setStackHidden('below max severity');\n }\n if (this.logLinesAtCurrentSeverity > kMaxLogStacks) {\n logMessage.setStackHidden(`only ${kMaxLogStacks} shown`);\n }\n\n this.logs.push(logMessage);\n }\n}\n"],"mappings":"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"}
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/params_utils.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/params_utils.js new file mode 100644 index 0000000000..d1ba896d90 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/params_utils.js @@ -0,0 +1,125 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { assert } from '../util/util.js'; + +import { comparePublicParamsPaths, Ordering } from './query/compare.js'; +import { kWildcard, kParamSeparator, kParamKVSeparator } from './query/separators.js'; + + + + + + + + + + + + + + + +export function paramKeyIsPublic(key) { + return !key.startsWith('_'); +} + +export function extractPublicParams(params) { + const publicParams = {}; + for (const k of Object.keys(params)) { + if (paramKeyIsPublic(k)) { + publicParams[k] = params[k]; + } + } + return publicParams; +} + +export const badParamValueChars = new RegExp( +'[' + kParamKVSeparator + kParamSeparator + kWildcard + ']'); + + +export function publicParamsEquals(x, y) { + return comparePublicParamsPaths(x, y) === Ordering.Equal; +} + + + + + + + + + + + + + + + + + + + + + + + + + + +function typeAssert() {} +{ + + + + + + + + + + + + + + + + + + + + + + + { + typeAssert(); + typeAssert(); + typeAssert(); + typeAssert(); + typeAssert(); + + typeAssert(); + + typeAssert(); + typeAssert(); + typeAssert(); + typeAssert(); + typeAssert(); + + // Unexpected test results - hopefully okay to ignore these + typeAssert(); + typeAssert(); + } +} + + + + + + +export function mergeParams(a, b) { + for (const key of Object.keys(a)) { + assert(!(key in b), 'Duplicate key: ' + key); + } + return { ...a, ...b }; +} +//# sourceMappingURL=params_utils.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/params_utils.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/params_utils.js.map new file mode 100644 index 0000000000..eb03517c23 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/params_utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"params_utils.js","names":["assert","comparePublicParamsPaths","Ordering","kWildcard","kParamSeparator","kParamKVSeparator","paramKeyIsPublic","key","startsWith","extractPublicParams","params","publicParams","k","Object","keys","badParamValueChars","RegExp","publicParamsEquals","x","y","Equal","typeAssert","mergeParams","a","b"],"sources":["../../../src/common/internal/params_utils.ts"],"sourcesContent":["import { TestParams } from '../framework/fixture.js';\nimport { ResolveType, UnionToIntersection } from '../util/types.js';\nimport { assert } from '../util/util.js';\n\nimport { comparePublicParamsPaths, Ordering } from './query/compare.js';\nimport { kWildcard, kParamSeparator, kParamKVSeparator } from './query/separators.js';\n\nexport type JSONWithUndefined =\n | undefined\n | null\n | number\n | string\n | boolean\n | readonly JSONWithUndefined[]\n // Ideally this would recurse into JSONWithUndefined, but it breaks code.\n | { readonly [k: string]: unknown };\nexport interface TestParamsRW {\n [k: string]: JSONWithUndefined;\n}\nexport type TestParamsIterable = Iterable<TestParams>;\n\nexport function paramKeyIsPublic(key: string): boolean {\n return !key.startsWith('_');\n}\n\nexport function extractPublicParams(params: TestParams): TestParams {\n const publicParams: TestParamsRW = {};\n for (const k of Object.keys(params)) {\n if (paramKeyIsPublic(k)) {\n publicParams[k] = params[k];\n }\n }\n return publicParams;\n}\n\nexport const badParamValueChars = new RegExp(\n '[' + kParamKVSeparator + kParamSeparator + kWildcard + ']'\n);\n\nexport function publicParamsEquals(x: TestParams, y: TestParams): boolean {\n return comparePublicParamsPaths(x, y) === Ordering.Equal;\n}\n\nexport type KeyOfNeverable<T> = T extends never ? never : keyof T;\nexport type AllKeysFromUnion<T> = keyof T | KeyOfNeverable<UnionToIntersection<T>>;\nexport type KeyOfOr<T, K, Default> = K extends keyof T ? T[K] : Default;\n\n/**\n * Flatten a union of interfaces into a single interface encoding the same type.\n *\n * Flattens a union in such a way that:\n * `{ a: number, b?: undefined } | { b: string, a?: undefined }`\n * (which is the value type of `[{ a: 1 }, { b: 1 }]`)\n * becomes `{ a: number | undefined, b: string | undefined }`.\n *\n * And also works for `{ a: number } | { b: string }` which maps to the same.\n */\nexport type FlattenUnionOfInterfaces<T> = {\n [K in AllKeysFromUnion<T>]: KeyOfOr<\n T,\n // If T always has K, just take T[K] (union of C[K] for each component C of T):\n K,\n // Otherwise, take the union of C[K] for each component C of T, PLUS undefined:\n undefined | KeyOfOr<UnionToIntersection<T>, K, void>\n >;\n};\n\n/* eslint-disable-next-line @typescript-eslint/no-unused-vars */\nfunction typeAssert<T extends 'pass'>() {}\n{\n type Test<T, U> = [T] extends [U]\n ? [U] extends [T]\n ? 'pass'\n : { actual: ResolveType<T>; expected: U }\n : { actual: ResolveType<T>; expected: U };\n\n type T01 = { a: number } | { b: string };\n type T02 = { a: number } | { b?: string };\n type T03 = { a: number } | { a?: number };\n type T04 = { a: number } | { a: string };\n type T05 = { a: number } | { a?: string };\n\n type T11 = { a: number; b?: undefined } | { a?: undefined; b: string };\n\n type T21 = { a: number; b?: undefined } | { b: string };\n type T22 = { a: number; b?: undefined } | { b?: string };\n type T23 = { a: number; b?: undefined } | { a?: number };\n type T24 = { a: number; b?: undefined } | { a: string };\n type T25 = { a: number; b?: undefined } | { a?: string };\n type T26 = { a: number; b?: undefined } | { a: undefined };\n type T27 = { a: number; b?: undefined } | { a: undefined; b: undefined };\n\n /* prettier-ignore */ {\n typeAssert<Test<FlattenUnionOfInterfaces<T01>, { a: number | undefined; b: string | undefined }>>();\n typeAssert<Test<FlattenUnionOfInterfaces<T02>, { a: number | undefined; b: string | undefined }>>();\n typeAssert<Test<FlattenUnionOfInterfaces<T03>, { a: number | undefined }>>();\n typeAssert<Test<FlattenUnionOfInterfaces<T04>, { a: number | string }>>();\n typeAssert<Test<FlattenUnionOfInterfaces<T05>, { a: number | string | undefined }>>();\n\n typeAssert<Test<FlattenUnionOfInterfaces<T11>, { a: number | undefined; b: string | undefined }>>();\n\n typeAssert<Test<FlattenUnionOfInterfaces<T22>, { a: number | undefined; b: string | undefined }>>();\n typeAssert<Test<FlattenUnionOfInterfaces<T23>, { a: number | undefined; b: undefined }>>();\n typeAssert<Test<FlattenUnionOfInterfaces<T24>, { a: number | string; b: undefined }>>();\n typeAssert<Test<FlattenUnionOfInterfaces<T25>, { a: number | string | undefined; b: undefined }>>();\n typeAssert<Test<FlattenUnionOfInterfaces<T27>, { a: number | undefined; b: undefined }>>();\n\n // Unexpected test results - hopefully okay to ignore these\n typeAssert<Test<FlattenUnionOfInterfaces<T21>, { b: string | undefined }>>();\n typeAssert<Test<FlattenUnionOfInterfaces<T26>, { a: number | undefined }>>();\n }\n}\n\nexport type Merged<A, B> = MergedFromFlat<A, FlattenUnionOfInterfaces<B>>;\nexport type MergedFromFlat<A, B> = {\n [K in keyof A | keyof B]: K extends keyof B ? B[K] : K extends keyof A ? A[K] : never;\n};\n\nexport function mergeParams<A extends {}, B extends {}>(a: A, b: B): Merged<A, B> {\n for (const key of Object.keys(a)) {\n assert(!(key in b), 'Duplicate key: ' + key);\n }\n return { ...a, ...b } as Merged<A, B>;\n}\n"],"mappings":";AAAA;AAAA,GAEA,SAASA,MAAM,QAAQ,iBAAiB;;AAExC,SAASC,wBAAwB,EAAEC,QAAQ,QAAQ,oBAAoB;AACvE,SAASC,SAAS,EAAEC,eAAe,EAAEC,iBAAiB,QAAQ,uBAAuB;;;;;;;;;;;;;;;;AAgBrF,OAAO,SAASC,gBAAgB,CAACC,GAAW,EAAW;EACrD,OAAO,CAACA,GAAG,CAACC,UAAU,CAAC,GAAG,CAAC;AAC7B;;AAEA,OAAO,SAASC,mBAAmB,CAACC,MAAkB,EAAc;EAClE,MAAMC,YAA0B,GAAG,CAAC,CAAC;EACrC,KAAK,MAAMC,CAAC,IAAIC,MAAM,CAACC,IAAI,CAACJ,MAAM,CAAC,EAAE;IACnC,IAAIJ,gBAAgB,CAACM,CAAC,CAAC,EAAE;MACvBD,YAAY,CAACC,CAAC,CAAC,GAAGF,MAAM,CAACE,CAAC,CAAC;IAC7B;EACF;EACA,OAAOD,YAAY;AACrB;;AAEA,OAAO,MAAMI,kBAAkB,GAAG,IAAIC,MAAM;AAC1C,GAAG,GAAGX,iBAAiB,GAAGD,eAAe,GAAGD,SAAS,GAAG,GAAG,CAC5D;;;AAED,OAAO,SAASc,kBAAkB,CAACC,CAAa,EAAEC,CAAa,EAAW;EACxE,OAAOlB,wBAAwB,CAACiB,CAAC,EAAEC,CAAC,CAAC,KAAKjB,QAAQ,CAACkB,KAAK;AAC1D;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,SAASC,UAAU,GAAqB,CAAC;AACzC;;;;;;;;;;;;;;;;;;;;;;;EAuBwB;IACpBA,UAAU,EAAyF;IACnGA,UAAU,EAAyF;IACnGA,UAAU,EAAkE;IAC5EA,UAAU,EAA+D;IACzEA,UAAU,EAA2E;;IAErFA,UAAU,EAAyF;;IAEnGA,UAAU,EAAyF;IACnGA,UAAU,EAAgF;IAC1FA,UAAU,EAA6E;IACvFA,UAAU,EAAyF;IACnGA,UAAU,EAAgF;;IAE1F;IACAA,UAAU,EAAkE;IAC5EA,UAAU,EAAkE;EAC9E;AACF;;;;;;;AAOA,OAAO,SAASC,WAAW,CAA6BC,CAAI,EAAEC,CAAI,EAAgB;EAChF,KAAK,MAAMjB,GAAG,IAAIM,MAAM,CAACC,IAAI,CAACS,CAAC,CAAC,EAAE;IAChCvB,MAAM,CAAC,EAAEO,GAAG,IAAIiB,CAAC,CAAC,EAAE,iBAAiB,GAAGjB,GAAG,CAAC;EAC9C;EACA,OAAO,EAAE,GAAGgB,CAAC,EAAE,GAAGC,CAAC,CAAC,CAAC;AACvB"}
\ No newline at end of file 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 new file mode 100644 index 0000000000..57975be912 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/compare.js @@ -0,0 +1,95 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { assert, objectEquals } from '../../util/util.js';import { paramKeyIsPublic } from '../params_utils.js'; + + + +export let Ordering; + + + + + + +/** + * Compares two queries for their ordering (which is used to build the tree). + * + * See src/unittests/query_compare.spec.ts for examples. + */(function (Ordering) {Ordering[Ordering["Unordered"] = 0] = "Unordered";Ordering[Ordering["StrictSuperset"] = 1] = "StrictSuperset";Ordering[Ordering["Equal"] = 2] = "Equal";Ordering[Ordering["StrictSubset"] = 3] = "StrictSubset";})(Ordering || (Ordering = {})); +export function compareQueries(a, b) { + if (a.suite !== b.suite) { + return Ordering.Unordered; + } + + const filePathOrdering = comparePaths(a.filePathParts, b.filePathParts); + if (filePathOrdering !== Ordering.Equal || a.isMultiFile || b.isMultiFile) { + return compareOneLevel(filePathOrdering, a.isMultiFile, b.isMultiFile); + } + assert('testPathParts' in a && 'testPathParts' in b); + + const testPathOrdering = comparePaths(a.testPathParts, b.testPathParts); + if (testPathOrdering !== Ordering.Equal || a.isMultiTest || b.isMultiTest) { + return compareOneLevel(testPathOrdering, a.isMultiTest, b.isMultiTest); + } + assert('params' in a && 'params' in b); + + const paramsPathOrdering = comparePublicParamsPaths(a.params, b.params); + if (paramsPathOrdering !== Ordering.Equal || a.isMultiCase || b.isMultiCase) { + return compareOneLevel(paramsPathOrdering, a.isMultiCase, b.isMultiCase); + } + return Ordering.Equal; +} + +/** + * Compares a single level of a query. + * + * "IsBig" means the query is big relative to the level, e.g. for test-level: + * - Anything >= `suite:a,*` is big + * - Anything <= `suite:a:*` is small + */ +function compareOneLevel(ordering, aIsBig, bIsBig) { + assert(ordering !== Ordering.Equal || aIsBig || bIsBig); + if (ordering === Ordering.Unordered) return Ordering.Unordered; + if (aIsBig && bIsBig) return ordering; + if (!aIsBig && !bIsBig) return Ordering.Unordered; // Equal case is already handled + // Exactly one of (a, b) is big. + if (aIsBig && ordering !== Ordering.StrictSubset) return Ordering.StrictSuperset; + if (bIsBig && ordering !== Ordering.StrictSuperset) return Ordering.StrictSubset; + return Ordering.Unordered; +} + +function comparePaths(a, b) { + const shorter = Math.min(a.length, b.length); + + for (let i = 0; i < shorter; ++i) { + if (a[i] !== b[i]) { + return Ordering.Unordered; + } + } + if (a.length === b.length) { + return Ordering.Equal; + } else if (a.length < b.length) { + return Ordering.StrictSuperset; + } else { + return Ordering.StrictSubset; + } +} + +export function comparePublicParamsPaths(a, b) { + const aKeys = Object.keys(a).filter((k) => paramKeyIsPublic(k)); + const commonKeys = new Set(aKeys.filter((k) => k in b)); + + for (const k of commonKeys) { + if (!objectEquals(a[k], b[k])) { + return Ordering.Unordered; + } + } + const bKeys = Object.keys(b).filter((k) => paramKeyIsPublic(k)); + const aRemainingKeys = aKeys.length - commonKeys.size; + const bRemainingKeys = bKeys.length - commonKeys.size; + if (aRemainingKeys === 0 && bRemainingKeys === 0) return Ordering.Equal; + if (aRemainingKeys === 0) return Ordering.StrictSuperset; + if (bRemainingKeys === 0) return Ordering.StrictSubset; + return Ordering.Unordered; +} +//# sourceMappingURL=compare.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/compare.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/compare.js.map new file mode 100644 index 0000000000..d4e90794ff --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/compare.js.map @@ -0,0 +1 @@ +{"version":3,"file":"compare.js","names":["assert","objectEquals","paramKeyIsPublic","Ordering","compareQueries","a","b","suite","Unordered","filePathOrdering","comparePaths","filePathParts","Equal","isMultiFile","compareOneLevel","testPathOrdering","testPathParts","isMultiTest","paramsPathOrdering","comparePublicParamsPaths","params","isMultiCase","ordering","aIsBig","bIsBig","StrictSubset","StrictSuperset","shorter","Math","min","length","i","aKeys","Object","keys","filter","k","commonKeys","Set","bKeys","aRemainingKeys","size","bRemainingKeys"],"sources":["../../../../src/common/internal/query/compare.ts"],"sourcesContent":["import { TestParams } from '../../framework/fixture.js';\nimport { assert, objectEquals } from '../../util/util.js';\nimport { paramKeyIsPublic } from '../params_utils.js';\n\nimport { TestQuery } from './query.js';\n\nexport const enum Ordering {\n Unordered,\n StrictSuperset,\n Equal,\n StrictSubset,\n}\n\n/**\n * Compares two queries for their ordering (which is used to build the tree).\n *\n * See src/unittests/query_compare.spec.ts for examples.\n */\nexport function compareQueries(a: TestQuery, b: TestQuery): Ordering {\n if (a.suite !== b.suite) {\n return Ordering.Unordered;\n }\n\n const filePathOrdering = comparePaths(a.filePathParts, b.filePathParts);\n if (filePathOrdering !== Ordering.Equal || a.isMultiFile || b.isMultiFile) {\n return compareOneLevel(filePathOrdering, a.isMultiFile, b.isMultiFile);\n }\n assert('testPathParts' in a && 'testPathParts' in b);\n\n const testPathOrdering = comparePaths(a.testPathParts, b.testPathParts);\n if (testPathOrdering !== Ordering.Equal || a.isMultiTest || b.isMultiTest) {\n return compareOneLevel(testPathOrdering, a.isMultiTest, b.isMultiTest);\n }\n assert('params' in a && 'params' in b);\n\n const paramsPathOrdering = comparePublicParamsPaths(a.params, b.params);\n if (paramsPathOrdering !== Ordering.Equal || a.isMultiCase || b.isMultiCase) {\n return compareOneLevel(paramsPathOrdering, a.isMultiCase, b.isMultiCase);\n }\n return Ordering.Equal;\n}\n\n/**\n * Compares a single level of a query.\n *\n * \"IsBig\" means the query is big relative to the level, e.g. for test-level:\n * - Anything >= `suite:a,*` is big\n * - Anything <= `suite:a:*` is small\n */\nfunction compareOneLevel(ordering: Ordering, aIsBig: boolean, bIsBig: boolean): Ordering {\n assert(ordering !== Ordering.Equal || aIsBig || bIsBig);\n if (ordering === Ordering.Unordered) return Ordering.Unordered;\n if (aIsBig && bIsBig) return ordering;\n if (!aIsBig && !bIsBig) return Ordering.Unordered; // Equal case is already handled\n // Exactly one of (a, b) is big.\n if (aIsBig && ordering !== Ordering.StrictSubset) return Ordering.StrictSuperset;\n if (bIsBig && ordering !== Ordering.StrictSuperset) return Ordering.StrictSubset;\n return Ordering.Unordered;\n}\n\nfunction comparePaths(a: readonly string[], b: readonly string[]): Ordering {\n const shorter = Math.min(a.length, b.length);\n\n for (let i = 0; i < shorter; ++i) {\n if (a[i] !== b[i]) {\n return Ordering.Unordered;\n }\n }\n if (a.length === b.length) {\n return Ordering.Equal;\n } else if (a.length < b.length) {\n return Ordering.StrictSuperset;\n } else {\n return Ordering.StrictSubset;\n }\n}\n\nexport function comparePublicParamsPaths(a: TestParams, b: TestParams): Ordering {\n const aKeys = Object.keys(a).filter(k => paramKeyIsPublic(k));\n const commonKeys = new Set(aKeys.filter(k => k in b));\n\n for (const k of commonKeys) {\n if (!objectEquals(a[k], b[k])) {\n return Ordering.Unordered;\n }\n }\n const bKeys = Object.keys(b).filter(k => paramKeyIsPublic(k));\n const aRemainingKeys = aKeys.length - commonKeys.size;\n const bRemainingKeys = bKeys.length - commonKeys.size;\n if (aRemainingKeys === 0 && bRemainingKeys === 0) return Ordering.Equal;\n if (aRemainingKeys === 0) return Ordering.StrictSuperset;\n if (bRemainingKeys === 0) return Ordering.StrictSubset;\n return Ordering.Unordered;\n}\n"],"mappings":"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"}
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/encode_selectively.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/encode_selectively.js new file mode 100644 index 0000000000..518ff5ea34 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/encode_selectively.js @@ -0,0 +1,24 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ /** + * Encodes a stringified TestQuery so that it can be placed in a `?q=` parameter in a URL. + * + * `encodeURIComponent` encodes in accordance with `application/x-www-form-urlencoded`, + * but URLs don't actually have to be as strict as HTML form encoding + * (we interpret this purely from JavaScript). + * So we encode the component, then selectively convert some %-encoded escape codes + * back to their original form for readability/copyability. + */export function encodeURIComponentSelectively(s) {let ret = encodeURIComponent(s); + ret = ret.replace(/%22/g, '"'); // for JSON strings + ret = ret.replace(/%2C/g, ','); // for path separator, and JSON arrays + ret = ret.replace(/%3A/g, ':'); // for big separator + ret = ret.replace(/%3B/g, ';'); // for param separator + ret = ret.replace(/%3D/g, '='); // for params (k=v) + ret = ret.replace(/%5B/g, '['); // for JSON arrays + ret = ret.replace(/%5D/g, ']'); // for JSON arrays + ret = ret.replace(/%7B/g, '{'); // for JSON objects + ret = ret.replace(/%7D/g, '}'); // for JSON objects + ret = ret.replace(/%E2%9C%97/g, '✗'); // for jsUndefinedMagicValue + return ret; +} +//# sourceMappingURL=encode_selectively.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/encode_selectively.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/encode_selectively.js.map new file mode 100644 index 0000000000..d70d890a32 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/encode_selectively.js.map @@ -0,0 +1 @@ +{"version":3,"file":"encode_selectively.js","names":["encodeURIComponentSelectively","s","ret","encodeURIComponent","replace"],"sources":["../../../../src/common/internal/query/encode_selectively.ts"],"sourcesContent":["/**\n * Encodes a stringified TestQuery so that it can be placed in a `?q=` parameter in a URL.\n *\n * `encodeURIComponent` encodes in accordance with `application/x-www-form-urlencoded`,\n * but URLs don't actually have to be as strict as HTML form encoding\n * (we interpret this purely from JavaScript).\n * So we encode the component, then selectively convert some %-encoded escape codes\n * back to their original form for readability/copyability.\n */\nexport function encodeURIComponentSelectively(s: string): string {\n let ret = encodeURIComponent(s);\n ret = ret.replace(/%22/g, '\"'); // for JSON strings\n ret = ret.replace(/%2C/g, ','); // for path separator, and JSON arrays\n ret = ret.replace(/%3A/g, ':'); // for big separator\n ret = ret.replace(/%3B/g, ';'); // for param separator\n ret = ret.replace(/%3D/g, '='); // for params (k=v)\n ret = ret.replace(/%5B/g, '['); // for JSON arrays\n ret = ret.replace(/%5D/g, ']'); // for JSON arrays\n ret = ret.replace(/%7B/g, '{'); // for JSON objects\n ret = ret.replace(/%7D/g, '}'); // for JSON objects\n ret = ret.replace(/%E2%9C%97/g, '✗'); // for jsUndefinedMagicValue\n return ret;\n}\n"],"mappings":";AAAA;AAAA,G,CAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GACA,OAAO,SAASA,6BAA6B,CAACC,CAAS,EAAU,CAC/D,IAAIC,GAAG,GAAGC,kBAAkB,CAACF,CAAC,CAAC;EAC/BC,GAAG,GAAGA,GAAG,CAACE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;EAChCF,GAAG,GAAGA,GAAG,CAACE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;EAChCF,GAAG,GAAGA,GAAG,CAACE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;EAChCF,GAAG,GAAGA,GAAG,CAACE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;EAChCF,GAAG,GAAGA,GAAG,CAACE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;EAChCF,GAAG,GAAGA,GAAG,CAACE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;EAChCF,GAAG,GAAGA,GAAG,CAACE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;EAChCF,GAAG,GAAGA,GAAG,CAACE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;EAChCF,GAAG,GAAGA,GAAG,CAACE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;EAChCF,GAAG,GAAGA,GAAG,CAACE,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC;EACtC,OAAOF,GAAG;AACZ"}
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/json_param_value.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/json_param_value.js new file mode 100644 index 0000000000..dc5e20e439 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/json_param_value.js @@ -0,0 +1,84 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { assert, sortObjectByKey } from '../../util/util.js'; +// JSON can't represent various values and by default stores them as `null`. +// Instead, storing them as a magic string values in JSON. +const jsUndefinedMagicValue = '_undef_'; +const jsNaNMagicValue = '_nan_'; +const jsPositiveInfinityMagicValue = '_posinfinity_'; +const jsNegativeInfinityMagicValue = '_neginfinity_'; + +// -0 needs to be handled separately, because -0 === +0 returns true. Not +// special casing +0/0, since it behaves intuitively. Assuming that if -0 is +// being used, the differentiation from +0 is desired. +const jsNegativeZeroMagicValue = '_negzero_'; + +const toStringMagicValue = new Map([ +[undefined, jsUndefinedMagicValue], +[NaN, jsNaNMagicValue], +[Number.POSITIVE_INFINITY, jsPositiveInfinityMagicValue], +[Number.NEGATIVE_INFINITY, jsNegativeInfinityMagicValue] +// No -0 handling because it is special cased. +]); + +const fromStringMagicValue = new Map([ +[jsUndefinedMagicValue, undefined], +[jsNaNMagicValue, NaN], +[jsPositiveInfinityMagicValue, Number.POSITIVE_INFINITY], +[jsNegativeInfinityMagicValue, Number.NEGATIVE_INFINITY], +// -0 is handled in this direction because there is no comparison issue. +[jsNegativeZeroMagicValue, -0]]); + + +function stringifyFilter(k, v) { + // Make sure no one actually uses a magic value as a parameter. + if (typeof v === 'string') { + assert( + !fromStringMagicValue.has(v), + `${v} is a magic value for stringification, so cannot be used`); + + + assert( + v !== jsNegativeZeroMagicValue, + `${v} is a magic value for stringification, so cannot be used`); + + } + + if (Object.is(v, -0)) { + return jsNegativeZeroMagicValue; + } + + return toStringMagicValue.has(v) ? toStringMagicValue.get(v) : v; +} + +export function stringifyParamValue(value) { + return JSON.stringify(value, stringifyFilter); +} + +/** + * Like stringifyParamValue but sorts dictionaries by key, for hashing. + */ +export function stringifyParamValueUniquely(value) { + return JSON.stringify(value, (k, v) => { + if (typeof v === 'object' && v !== null) { + return sortObjectByKey(v); + } + + return stringifyFilter(k, v); + }); +} + +// 'any' is part of the JSON.parse reviver interface, so cannot be avoided. + +function parseParamValueReviver(k, v) { + if (fromStringMagicValue.has(v)) { + return fromStringMagicValue.get(v); + } + + return v; +} + +export function parseParamValue(s) { + return JSON.parse(s, parseParamValueReviver); +} +//# sourceMappingURL=json_param_value.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/json_param_value.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/json_param_value.js.map new file mode 100644 index 0000000000..d97066ae17 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/json_param_value.js.map @@ -0,0 +1 @@ +{"version":3,"file":"json_param_value.js","names":["assert","sortObjectByKey","jsUndefinedMagicValue","jsNaNMagicValue","jsPositiveInfinityMagicValue","jsNegativeInfinityMagicValue","jsNegativeZeroMagicValue","toStringMagicValue","Map","undefined","NaN","Number","POSITIVE_INFINITY","NEGATIVE_INFINITY","fromStringMagicValue","stringifyFilter","k","v","has","Object","is","get","stringifyParamValue","value","JSON","stringify","stringifyParamValueUniquely","parseParamValueReviver","parseParamValue","s","parse"],"sources":["../../../../src/common/internal/query/json_param_value.ts"],"sourcesContent":["import { assert, sortObjectByKey } from '../../util/util.js';\nimport { JSONWithUndefined } from '../params_utils.js';\n\n// JSON can't represent various values and by default stores them as `null`.\n// Instead, storing them as a magic string values in JSON.\nconst jsUndefinedMagicValue = '_undef_';\nconst jsNaNMagicValue = '_nan_';\nconst jsPositiveInfinityMagicValue = '_posinfinity_';\nconst jsNegativeInfinityMagicValue = '_neginfinity_';\n\n// -0 needs to be handled separately, because -0 === +0 returns true. Not\n// special casing +0/0, since it behaves intuitively. Assuming that if -0 is\n// being used, the differentiation from +0 is desired.\nconst jsNegativeZeroMagicValue = '_negzero_';\n\nconst toStringMagicValue = new Map<unknown, string>([\n [undefined, jsUndefinedMagicValue],\n [NaN, jsNaNMagicValue],\n [Number.POSITIVE_INFINITY, jsPositiveInfinityMagicValue],\n [Number.NEGATIVE_INFINITY, jsNegativeInfinityMagicValue],\n // No -0 handling because it is special cased.\n]);\n\nconst fromStringMagicValue = new Map<string, unknown>([\n [jsUndefinedMagicValue, undefined],\n [jsNaNMagicValue, NaN],\n [jsPositiveInfinityMagicValue, Number.POSITIVE_INFINITY],\n [jsNegativeInfinityMagicValue, Number.NEGATIVE_INFINITY],\n // -0 is handled in this direction because there is no comparison issue.\n [jsNegativeZeroMagicValue, -0],\n]);\n\nfunction stringifyFilter(k: string, v: unknown): unknown {\n // Make sure no one actually uses a magic value as a parameter.\n if (typeof v === 'string') {\n assert(\n !fromStringMagicValue.has(v),\n `${v} is a magic value for stringification, so cannot be used`\n );\n\n assert(\n v !== jsNegativeZeroMagicValue,\n `${v} is a magic value for stringification, so cannot be used`\n );\n }\n\n if (Object.is(v, -0)) {\n return jsNegativeZeroMagicValue;\n }\n\n return toStringMagicValue.has(v) ? toStringMagicValue.get(v) : v;\n}\n\nexport function stringifyParamValue(value: JSONWithUndefined): string {\n return JSON.stringify(value, stringifyFilter);\n}\n\n/**\n * Like stringifyParamValue but sorts dictionaries by key, for hashing.\n */\nexport function stringifyParamValueUniquely(value: JSONWithUndefined): string {\n return JSON.stringify(value, (k, v) => {\n if (typeof v === 'object' && v !== null) {\n return sortObjectByKey(v);\n }\n\n return stringifyFilter(k, v);\n });\n}\n\n// 'any' is part of the JSON.parse reviver interface, so cannot be avoided.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction parseParamValueReviver(k: string, v: any): any {\n if (fromStringMagicValue.has(v)) {\n return fromStringMagicValue.get(v);\n }\n\n return v;\n}\n\nexport function parseParamValue(s: string): JSONWithUndefined {\n return JSON.parse(s, parseParamValueReviver);\n}\n"],"mappings":";AAAA;AAAA,GAAA,SAASA,MAAM,EAAEC,eAAe,QAAQ,oBAAoB;AAG5D;AACA;AACA,MAAMC,qBAAqB,GAAG,SAAS;AACvC,MAAMC,eAAe,GAAG,OAAO;AAC/B,MAAMC,4BAA4B,GAAG,eAAe;AACpD,MAAMC,4BAA4B,GAAG,eAAe;;AAEpD;AACA;AACA;AACA,MAAMC,wBAAwB,GAAG,WAAW;;AAE5C,MAAMC,kBAAkB,GAAG,IAAIC,GAAG,CAAkB;AAClD,CAACC,SAAS,EAAEP,qBAAqB,CAAC;AAClC,CAACQ,GAAG,EAAEP,eAAe,CAAC;AACtB,CAACQ,MAAM,CAACC,iBAAiB,EAAER,4BAA4B,CAAC;AACxD,CAACO,MAAM,CAACE,iBAAiB,EAAER,4BAA4B;AACvD;AAAA,CACD,CAAC;;AAEF,MAAMS,oBAAoB,GAAG,IAAIN,GAAG,CAAkB;AACpD,CAACN,qBAAqB,EAAEO,SAAS,CAAC;AAClC,CAACN,eAAe,EAAEO,GAAG,CAAC;AACtB,CAACN,4BAA4B,EAAEO,MAAM,CAACC,iBAAiB,CAAC;AACxD,CAACP,4BAA4B,EAAEM,MAAM,CAACE,iBAAiB,CAAC;AACxD;AACA,CAACP,wBAAwB,EAAE,CAAC,CAAC,CAAC,CAC/B,CAAC;;;AAEF,SAASS,eAAe,CAACC,CAAS,EAAEC,CAAU,EAAW;EACvD;EACA,IAAI,OAAOA,CAAC,KAAK,QAAQ,EAAE;IACzBjB,MAAM;IACJ,CAACc,oBAAoB,CAACI,GAAG,CAACD,CAAC,CAAC;IAC3B,GAAEA,CAAE,0DAAyD,CAC/D;;;IAEDjB,MAAM;IACJiB,CAAC,KAAKX,wBAAwB;IAC7B,GAAEW,CAAE,0DAAyD,CAC/D;;EACH;;EAEA,IAAIE,MAAM,CAACC,EAAE,CAACH,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;IACpB,OAAOX,wBAAwB;EACjC;;EAEA,OAAOC,kBAAkB,CAACW,GAAG,CAACD,CAAC,CAAC,GAAGV,kBAAkB,CAACc,GAAG,CAACJ,CAAC,CAAC,GAAGA,CAAC;AAClE;;AAEA,OAAO,SAASK,mBAAmB,CAACC,KAAwB,EAAU;EACpE,OAAOC,IAAI,CAACC,SAAS,CAACF,KAAK,EAAER,eAAe,CAAC;AAC/C;;AAEA;AACA;AACA;AACA,OAAO,SAASW,2BAA2B,CAACH,KAAwB,EAAU;EAC5E,OAAOC,IAAI,CAACC,SAAS,CAACF,KAAK,EAAE,CAACP,CAAC,EAAEC,CAAC,KAAK;IACrC,IAAI,OAAOA,CAAC,KAAK,QAAQ,IAAIA,CAAC,KAAK,IAAI,EAAE;MACvC,OAAOhB,eAAe,CAACgB,CAAC,CAAC;IAC3B;;IAEA,OAAOF,eAAe,CAACC,CAAC,EAAEC,CAAC,CAAC;EAC9B,CAAC,CAAC;AACJ;;AAEA;;AAEA,SAASU,sBAAsB,CAACX,CAAS,EAAEC,CAAM,EAAO;EACtD,IAAIH,oBAAoB,CAACI,GAAG,CAACD,CAAC,CAAC,EAAE;IAC/B,OAAOH,oBAAoB,CAACO,GAAG,CAACJ,CAAC,CAAC;EACpC;;EAEA,OAAOA,CAAC;AACV;;AAEA,OAAO,SAASW,eAAe,CAACC,CAAS,EAAqB;EAC5D,OAAOL,IAAI,CAACM,KAAK,CAACD,CAAC,EAAEF,sBAAsB,CAAC;AAC9C"}
\ No newline at end of file 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 new file mode 100644 index 0000000000..4cfa6faf58 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/parseQuery.js @@ -0,0 +1,156 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { assert } from '../../util/util.js';import { + +badParamValueChars, +paramKeyIsPublic } from +'../params_utils.js'; + +import { parseParamValue } from './json_param_value.js'; +import { + +TestQueryMultiFile, +TestQueryMultiTest, +TestQueryMultiCase, +TestQuerySingleCase } from +'./query.js'; +import { kBigSeparator, kWildcard, kPathSeparator, kParamSeparator } from './separators.js'; +import { validQueryPart } from './validQueryPart.js'; + +export function parseQuery(s) { + try { + return parseQueryImpl(s); + } catch (ex) { + if (ex instanceof Error) { + ex.message += '\n on: ' + s; + } + throw ex; + } +} + +function parseQueryImpl(s) { + // Undo encodeURIComponentSelectively + s = decodeURIComponent(s); + + // bigParts are: suite, file, test, params (note kBigSeparator could appear in params) + let suite; + let fileString; + let testString; + let paramsString; + { + const i1 = s.indexOf(kBigSeparator); + assert(i1 !== -1, `query string must have at least one ${kBigSeparator}`); + suite = s.substring(0, i1); + const i2 = s.indexOf(kBigSeparator, i1 + 1); + if (i2 === -1) { + fileString = s.substring(i1 + 1); + } else { + fileString = s.substring(i1 + 1, i2); + const i3 = s.indexOf(kBigSeparator, i2 + 1); + if (i3 === -1) { + testString = s.substring(i2 + 1); + } else { + testString = s.substring(i2 + 1, i3); + paramsString = s.substring(i3 + 1); + } + } + } + + const { parts: file, wildcard: filePathHasWildcard } = parseBigPart(fileString, kPathSeparator); + + if (testString === undefined) { + // Query is file-level + assert( + filePathHasWildcard, + `File-level query without wildcard ${kWildcard}. Did you want a file-level query \ +(append ${kPathSeparator}${kWildcard}) or test-level query (append ${kBigSeparator}${kWildcard})?`); + + return new TestQueryMultiFile(suite, file); + } + assert(!filePathHasWildcard, `Wildcard ${kWildcard} must be at the end of the query string`); + + const { parts: test, wildcard: testPathHasWildcard } = parseBigPart(testString, kPathSeparator); + + if (paramsString === undefined) { + // Query is test-level + assert( + testPathHasWildcard, + `Test-level query without wildcard ${kWildcard}; did you want a test-level query \ +(append ${kPathSeparator}${kWildcard}) or case-level query (append ${kBigSeparator}${kWildcard})?`); + + assert(file.length > 0, 'File part of test-level query was empty (::)'); + return new TestQueryMultiTest(suite, file, test); + } + + // Query is case-level + assert(!testPathHasWildcard, `Wildcard ${kWildcard} must be at the end of the query string`); + + const { parts: paramsParts, wildcard: paramsHasWildcard } = parseBigPart( + paramsString, + kParamSeparator); + + + assert(test.length > 0, 'Test part of case-level query was empty (::)'); + + const params = {}; + for (const paramPart of paramsParts) { + const [k, v] = parseSingleParam(paramPart); + assert(validQueryPart.test(k), `param key names must match ${validQueryPart}`); + params[k] = v; + } + if (paramsHasWildcard) { + return new TestQueryMultiCase(suite, file, test, params); + } else { + return new TestQuerySingleCase(suite, file, test, params); + } +} + +// webgpu:a,b,* or webgpu:a,b,c:* +const kExampleQueries = `\ +webgpu${kBigSeparator}a${kPathSeparator}b${kPathSeparator}${kWildcard} or \ +webgpu${kBigSeparator}a${kPathSeparator}b${kPathSeparator}c${kBigSeparator}${kWildcard}`; + +function parseBigPart( +s, +separator) +{ + if (s === '') { + return { parts: [], wildcard: false }; + } + const parts = s.split(separator); + + let endsWithWildcard = false; + for (const [i, part] of parts.entries()) { + if (i === parts.length - 1) { + endsWithWildcard = part === kWildcard; + } + assert( + part.indexOf(kWildcard) === -1 || endsWithWildcard, + `Wildcard ${kWildcard} must be complete last part of a path (e.g. ${kExampleQueries})`); + + } + if (endsWithWildcard) { + // Remove the last element of the array (which is just the wildcard). + parts.length = parts.length - 1; + } + return { parts, wildcard: endsWithWildcard }; +} + +function parseSingleParam(paramSubstring) { + assert(paramSubstring !== '', 'Param in a query must not be blank (is there a trailing comma?)'); + const i = paramSubstring.indexOf('='); + assert(i !== -1, 'Param in a query must be of form key=value'); + const k = paramSubstring.substring(0, i); + assert(paramKeyIsPublic(k), 'Param in a query must not be private (start with _)'); + const v = paramSubstring.substring(i + 1); + return [k, parseSingleParamValue(v)]; +} + +function parseSingleParamValue(s) { + assert( + !badParamValueChars.test(s), + `param value must not match ${badParamValueChars} - was ${s}`); + + return parseParamValue(s); +} +//# sourceMappingURL=parseQuery.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/parseQuery.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/parseQuery.js.map new file mode 100644 index 0000000000..4580b15bf4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/parseQuery.js.map @@ -0,0 +1 @@ +{"version":3,"file":"parseQuery.js","names":["assert","badParamValueChars","paramKeyIsPublic","parseParamValue","TestQueryMultiFile","TestQueryMultiTest","TestQueryMultiCase","TestQuerySingleCase","kBigSeparator","kWildcard","kPathSeparator","kParamSeparator","validQueryPart","parseQuery","s","parseQueryImpl","ex","Error","message","decodeURIComponent","suite","fileString","testString","paramsString","i1","indexOf","substring","i2","i3","parts","file","wildcard","filePathHasWildcard","parseBigPart","undefined","test","testPathHasWildcard","length","paramsParts","paramsHasWildcard","params","paramPart","k","v","parseSingleParam","kExampleQueries","separator","split","endsWithWildcard","i","part","entries","paramSubstring","parseSingleParamValue"],"sources":["../../../../src/common/internal/query/parseQuery.ts"],"sourcesContent":["import { assert } from '../../util/util.js';\nimport {\n TestParamsRW,\n JSONWithUndefined,\n badParamValueChars,\n paramKeyIsPublic,\n} from '../params_utils.js';\n\nimport { parseParamValue } from './json_param_value.js';\nimport {\n TestQuery,\n TestQueryMultiFile,\n TestQueryMultiTest,\n TestQueryMultiCase,\n TestQuerySingleCase,\n} from './query.js';\nimport { kBigSeparator, kWildcard, kPathSeparator, kParamSeparator } from './separators.js';\nimport { validQueryPart } from './validQueryPart.js';\n\nexport function parseQuery(s: string): TestQuery {\n try {\n return parseQueryImpl(s);\n } catch (ex) {\n if (ex instanceof Error) {\n ex.message += '\\n on: ' + s;\n }\n throw ex;\n }\n}\n\nfunction parseQueryImpl(s: string): TestQuery {\n // Undo encodeURIComponentSelectively\n s = decodeURIComponent(s);\n\n // bigParts are: suite, file, test, params (note kBigSeparator could appear in params)\n let suite: string;\n let fileString: string | undefined;\n let testString: string | undefined;\n let paramsString: string | undefined;\n {\n const i1 = s.indexOf(kBigSeparator);\n assert(i1 !== -1, `query string must have at least one ${kBigSeparator}`);\n suite = s.substring(0, i1);\n const i2 = s.indexOf(kBigSeparator, i1 + 1);\n if (i2 === -1) {\n fileString = s.substring(i1 + 1);\n } else {\n fileString = s.substring(i1 + 1, i2);\n const i3 = s.indexOf(kBigSeparator, i2 + 1);\n if (i3 === -1) {\n testString = s.substring(i2 + 1);\n } else {\n testString = s.substring(i2 + 1, i3);\n paramsString = s.substring(i3 + 1);\n }\n }\n }\n\n const { parts: file, wildcard: filePathHasWildcard } = parseBigPart(fileString, kPathSeparator);\n\n if (testString === undefined) {\n // Query is file-level\n assert(\n filePathHasWildcard,\n `File-level query without wildcard ${kWildcard}. Did you want a file-level query \\\n(append ${kPathSeparator}${kWildcard}) or test-level query (append ${kBigSeparator}${kWildcard})?`\n );\n return new TestQueryMultiFile(suite, file);\n }\n assert(!filePathHasWildcard, `Wildcard ${kWildcard} must be at the end of the query string`);\n\n const { parts: test, wildcard: testPathHasWildcard } = parseBigPart(testString, kPathSeparator);\n\n if (paramsString === undefined) {\n // Query is test-level\n assert(\n testPathHasWildcard,\n `Test-level query without wildcard ${kWildcard}; did you want a test-level query \\\n(append ${kPathSeparator}${kWildcard}) or case-level query (append ${kBigSeparator}${kWildcard})?`\n );\n assert(file.length > 0, 'File part of test-level query was empty (::)');\n return new TestQueryMultiTest(suite, file, test);\n }\n\n // Query is case-level\n assert(!testPathHasWildcard, `Wildcard ${kWildcard} must be at the end of the query string`);\n\n const { parts: paramsParts, wildcard: paramsHasWildcard } = parseBigPart(\n paramsString,\n kParamSeparator\n );\n\n assert(test.length > 0, 'Test part of case-level query was empty (::)');\n\n const params: TestParamsRW = {};\n for (const paramPart of paramsParts) {\n const [k, v] = parseSingleParam(paramPart);\n assert(validQueryPart.test(k), `param key names must match ${validQueryPart}`);\n params[k] = v;\n }\n if (paramsHasWildcard) {\n return new TestQueryMultiCase(suite, file, test, params);\n } else {\n return new TestQuerySingleCase(suite, file, test, params);\n }\n}\n\n// webgpu:a,b,* or webgpu:a,b,c:*\nconst kExampleQueries = `\\\nwebgpu${kBigSeparator}a${kPathSeparator}b${kPathSeparator}${kWildcard} or \\\nwebgpu${kBigSeparator}a${kPathSeparator}b${kPathSeparator}c${kBigSeparator}${kWildcard}`;\n\nfunction parseBigPart(\n s: string,\n separator: typeof kParamSeparator | typeof kPathSeparator\n): { parts: string[]; wildcard: boolean } {\n if (s === '') {\n return { parts: [], wildcard: false };\n }\n const parts = s.split(separator);\n\n let endsWithWildcard = false;\n for (const [i, part] of parts.entries()) {\n if (i === parts.length - 1) {\n endsWithWildcard = part === kWildcard;\n }\n assert(\n part.indexOf(kWildcard) === -1 || endsWithWildcard,\n `Wildcard ${kWildcard} must be complete last part of a path (e.g. ${kExampleQueries})`\n );\n }\n if (endsWithWildcard) {\n // Remove the last element of the array (which is just the wildcard).\n parts.length = parts.length - 1;\n }\n return { parts, wildcard: endsWithWildcard };\n}\n\nfunction parseSingleParam(paramSubstring: string): [string, JSONWithUndefined] {\n assert(paramSubstring !== '', 'Param in a query must not be blank (is there a trailing comma?)');\n const i = paramSubstring.indexOf('=');\n assert(i !== -1, 'Param in a query must be of form key=value');\n const k = paramSubstring.substring(0, i);\n assert(paramKeyIsPublic(k), 'Param in a query must not be private (start with _)');\n const v = paramSubstring.substring(i + 1);\n return [k, parseSingleParamValue(v)];\n}\n\nfunction parseSingleParamValue(s: string): JSONWithUndefined {\n assert(\n !badParamValueChars.test(s),\n `param value must not match ${badParamValueChars} - was ${s}`\n );\n return parseParamValue(s);\n}\n"],"mappings":"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"}
\ No newline at end of file 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 new file mode 100644 index 0000000000..cb09f6ea8a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/query.js @@ -0,0 +1,263 @@ +/** +* 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 { compareQueries, Ordering } from './compare.js'; +import { encodeURIComponentSelectively } from './encode_selectively.js'; +import { parseQuery } from './parseQuery.js'; +import { kBigSeparator, kPathSeparator, kWildcard } from './separators.js'; +import { stringifyPublicParams } from './stringify_params.js'; + +/** + * Represents a test query of some level. + * + * TestQuery types are immutable. + */ + + + + + + + + + + + + + + + + + + + +/** + * A multi-file test query, like `s:*` or `s:a,b,*`. + * + * Immutable (makes copies of constructor args). + */ +export class TestQueryMultiFile { + level = 1; + isMultiFile = true; + + + + constructor(suite, file) { + this.suite = suite; + this.filePathParts = [...file]; + } + + get depthInLevel() { + return this.filePathParts.length; + } + + toString() { + return encodeURIComponentSelectively(this.toStringHelper().join(kBigSeparator)); + } + + toStringHelper() { + return [this.suite, [...this.filePathParts, kWildcard].join(kPathSeparator)]; + } +} + +/** + * A multi-test test query, like `s:f:*` or `s:f:a,b,*`. + * + * Immutable (makes copies of constructor args). + */ +export class TestQueryMultiTest extends TestQueryMultiFile { + level = 2; + isMultiFile = false; + isMultiTest = true; + + + constructor(suite, file, test) { + super(suite, file); + assert(file.length > 0, 'multi-test (or finer) query must have file-path'); + this.testPathParts = [...test]; + } + + get depthInLevel() { + return this.testPathParts.length; + } + + toStringHelper() { + return [ + this.suite, + this.filePathParts.join(kPathSeparator), + [...this.testPathParts, kWildcard].join(kPathSeparator)]; + + } +} + +/** + * A multi-case test query, like `s:f:t:*` or `s:f:t:a,b,*`. + * + * Immutable (makes copies of constructor args), except for param values + * (which aren't normally supposed to change; they're marked readonly in TestParams). + */ +export class TestQueryMultiCase extends TestQueryMultiTest { + level = 3; + isMultiTest = false; + isMultiCase = true; + + + constructor(suite, file, test, params) { + super(suite, file, test); + assert(test.length > 0, 'multi-case (or finer) query must have test-path'); + this.params = { ...params }; + } + + get depthInLevel() { + return Object.keys(this.params).length; + } + + toStringHelper() { + return [ + this.suite, + this.filePathParts.join(kPathSeparator), + this.testPathParts.join(kPathSeparator), + stringifyPublicParams(this.params, true)]; + + } +} + +/** + * A multi-case test query, like `s:f:t:` or `s:f:t:a=1,b=1`. + * + * Immutable (makes copies of constructor args). + */ +export class TestQuerySingleCase extends TestQueryMultiCase { + level = 4; + isMultiCase = false; + + get depthInLevel() { + return 0; + } + + toStringHelper() { + return [ + this.suite, + this.filePathParts.join(kPathSeparator), + this.testPathParts.join(kPathSeparator), + stringifyPublicParams(this.params)]; + + } +} + +/** + * Parse raw expectations input into TestQueryWithExpectation[], filtering so that only + * expectations that are relevant for the provided query and wptURL. + * + * `rawExpectations` should be @type {{ query: string, expectation: Expectation }[]} + * + * The `rawExpectations` are parsed and validated that they are in the correct format. + * If `wptURL` is passed, the query string should be of the full path format such + * as `path/to/cts.https.html?worker=0&q=suite:test_path:test_name:foo=1;bar=2;*`. + * If `wptURL` is `undefined`, the query string should be only the query + * `suite:test_path:test_name:foo=1;bar=2;*`. + */ +export function parseExpectationsForTestQuery( +rawExpectations, + + + + + +query, +wptURL) +{ + if (!Array.isArray(rawExpectations)) { + unreachable('Expectations should be an array'); + } + const expectations = []; + for (const entry of rawExpectations) { + assert(typeof entry === 'object'); + const rawExpectation = entry; + assert(rawExpectation.query !== undefined, 'Expectation missing query string'); + assert(rawExpectation.expectation !== undefined, 'Expectation missing expectation string'); + + let expectationQuery; + if (wptURL !== undefined) { + const expectationURL = new URL(`${wptURL.origin}/${entry.query}`); + if (expectationURL.pathname !== wptURL.pathname) { + continue; + } + 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;... + `); + + + const params = expectationURL.searchParams; + if (optionEnabled('worker', params) !== optionEnabled('worker', wptURL.searchParams)) { + continue; + } + + const qs = params.getAll('q'); + assert(qs.length === 1, 'currently, there must be exactly one ?q= in the expectation string'); + expectationQuery = parseQuery(qs[0]); + } else { + expectationQuery = parseQuery(entry.query); + } + + // Strip params from multicase expectations so that an expectation of foo=2;* + // is stored if the test query is bar=3;* + const queryForFilter = + expectationQuery instanceof TestQueryMultiCase ? + new TestQueryMultiCase( + expectationQuery.suite, + expectationQuery.filePathParts, + expectationQuery.testPathParts, + {}) : + + expectationQuery; + + if (compareQueries(query, queryForFilter) === Ordering.Unordered) { + continue; + } + + switch (entry.expectation) { + case 'pass': + case 'skip': + case 'fail': + break; + default: + unreachable(`Invalid expectation ${entry.expectation}`);} + + + expectations.push({ + query: expectationQuery, + expectation: entry.expectation + }); + } + return expectations; +} + +/** + * For display purposes only, produces a "relative" query string from parent to child. + * Used in the wpt runtime to reduce the verbosity of logs. + */ +export function relativeQueryString(parent, child) { + const ordering = compareQueries(parent, child); + if (ordering === Ordering.Equal) { + return ''; + } else if (ordering === Ordering.StrictSuperset) { + const parentString = parent.toString(); + assert(parentString.endsWith(kWildcard)); + const childString = child.toString(); + assert( + childString.startsWith(parentString.substring(0, parentString.length - 2)), + 'impossible?: childString does not start with parentString[:-2]'); + + return childString.substring(parentString.length - 2); + } else { + unreachable( + `relativeQueryString arguments have invalid ordering ${ordering}:\n${parent}\n${child}`); + + } +} +//# sourceMappingURL=query.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/query.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/query.js.map new file mode 100644 index 0000000000..09d712c589 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/query.js.map @@ -0,0 +1 @@ +{"version":3,"file":"query.js","names":["optionEnabled","assert","unreachable","compareQueries","Ordering","encodeURIComponentSelectively","parseQuery","kBigSeparator","kPathSeparator","kWildcard","stringifyPublicParams","TestQueryMultiFile","level","isMultiFile","constructor","suite","file","filePathParts","depthInLevel","length","toString","toStringHelper","join","TestQueryMultiTest","isMultiTest","test","testPathParts","TestQueryMultiCase","isMultiCase","params","Object","keys","TestQuerySingleCase","parseExpectationsForTestQuery","rawExpectations","query","wptURL","Array","isArray","expectations","entry","rawExpectation","undefined","expectation","expectationQuery","expectationURL","URL","origin","pathname","searchParams","qs","getAll","queryForFilter","Unordered","push","relativeQueryString","parent","child","ordering","Equal","StrictSuperset","parentString","endsWith","childString","startsWith","substring"],"sources":["../../../../src/common/internal/query/query.ts"],"sourcesContent":["import { TestParams } from '../../framework/fixture.js';\nimport { optionEnabled } from '../../runtime/helper/options.js';\nimport { assert, unreachable } from '../../util/util.js';\nimport { Expectation } from '../logging/result.js';\n\nimport { compareQueries, Ordering } from './compare.js';\nimport { encodeURIComponentSelectively } from './encode_selectively.js';\nimport { parseQuery } from './parseQuery.js';\nimport { kBigSeparator, kPathSeparator, kWildcard } from './separators.js';\nimport { stringifyPublicParams } from './stringify_params.js';\n\n/**\n * Represents a test query of some level.\n *\n * TestQuery types are immutable.\n */\nexport type TestQuery =\n | TestQuerySingleCase\n | TestQueryMultiCase\n | TestQueryMultiTest\n | TestQueryMultiFile;\n\n/**\n * - 1 = MultiFile.\n * - 2 = MultiTest.\n * - 3 = MultiCase.\n * - 4 = SingleCase.\n */\nexport type TestQueryLevel = 1 | 2 | 3 | 4;\n\nexport interface TestQueryWithExpectation {\n query: TestQuery;\n expectation: Expectation;\n}\n\n/**\n * A multi-file test query, like `s:*` or `s:a,b,*`.\n *\n * Immutable (makes copies of constructor args).\n */\nexport class TestQueryMultiFile {\n readonly level: TestQueryLevel = 1;\n readonly isMultiFile: boolean = true;\n readonly suite: string;\n readonly filePathParts: readonly string[];\n\n constructor(suite: string, file: readonly string[]) {\n this.suite = suite;\n this.filePathParts = [...file];\n }\n\n get depthInLevel() {\n return this.filePathParts.length;\n }\n\n toString(): string {\n return encodeURIComponentSelectively(this.toStringHelper().join(kBigSeparator));\n }\n\n protected toStringHelper(): string[] {\n return [this.suite, [...this.filePathParts, kWildcard].join(kPathSeparator)];\n }\n}\n\n/**\n * A multi-test test query, like `s:f:*` or `s:f:a,b,*`.\n *\n * Immutable (makes copies of constructor args).\n */\nexport class TestQueryMultiTest extends TestQueryMultiFile {\n readonly level: TestQueryLevel = 2;\n readonly isMultiFile: false = false;\n readonly isMultiTest: boolean = true;\n readonly testPathParts: readonly string[];\n\n constructor(suite: string, file: readonly string[], test: readonly string[]) {\n super(suite, file);\n assert(file.length > 0, 'multi-test (or finer) query must have file-path');\n this.testPathParts = [...test];\n }\n\n get depthInLevel() {\n return this.testPathParts.length;\n }\n\n protected toStringHelper(): string[] {\n return [\n this.suite,\n this.filePathParts.join(kPathSeparator),\n [...this.testPathParts, kWildcard].join(kPathSeparator),\n ];\n }\n}\n\n/**\n * A multi-case test query, like `s:f:t:*` or `s:f:t:a,b,*`.\n *\n * Immutable (makes copies of constructor args), except for param values\n * (which aren't normally supposed to change; they're marked readonly in TestParams).\n */\nexport class TestQueryMultiCase extends TestQueryMultiTest {\n readonly level: TestQueryLevel = 3;\n readonly isMultiTest: false = false;\n readonly isMultiCase: boolean = true;\n readonly params: TestParams;\n\n constructor(suite: string, file: readonly string[], test: readonly string[], params: TestParams) {\n super(suite, file, test);\n assert(test.length > 0, 'multi-case (or finer) query must have test-path');\n this.params = { ...params };\n }\n\n get depthInLevel() {\n return Object.keys(this.params).length;\n }\n\n protected toStringHelper(): string[] {\n return [\n this.suite,\n this.filePathParts.join(kPathSeparator),\n this.testPathParts.join(kPathSeparator),\n stringifyPublicParams(this.params, true),\n ];\n }\n}\n\n/**\n * A multi-case test query, like `s:f:t:` or `s:f:t:a=1,b=1`.\n *\n * Immutable (makes copies of constructor args).\n */\nexport class TestQuerySingleCase extends TestQueryMultiCase {\n readonly level: TestQueryLevel = 4;\n readonly isMultiCase: false = false;\n\n get depthInLevel() {\n return 0;\n }\n\n protected toStringHelper(): string[] {\n return [\n this.suite,\n this.filePathParts.join(kPathSeparator),\n this.testPathParts.join(kPathSeparator),\n stringifyPublicParams(this.params),\n ];\n }\n}\n\n/**\n * Parse raw expectations input into TestQueryWithExpectation[], filtering so that only\n * expectations that are relevant for the provided query and wptURL.\n *\n * `rawExpectations` should be @type {{ query: string, expectation: Expectation }[]}\n *\n * The `rawExpectations` are parsed and validated that they are in the correct format.\n * If `wptURL` is passed, the query string should be of the full path format such\n * as `path/to/cts.https.html?worker=0&q=suite:test_path:test_name:foo=1;bar=2;*`.\n * If `wptURL` is `undefined`, the query string should be only the query\n * `suite:test_path:test_name:foo=1;bar=2;*`.\n */\nexport function parseExpectationsForTestQuery(\n rawExpectations:\n | unknown\n | {\n query: string;\n expectation: Expectation;\n }[],\n query: TestQuery,\n wptURL?: URL\n) {\n if (!Array.isArray(rawExpectations)) {\n unreachable('Expectations should be an array');\n }\n const expectations: TestQueryWithExpectation[] = [];\n for (const entry of rawExpectations) {\n assert(typeof entry === 'object');\n const rawExpectation = entry as { query?: string; expectation?: string };\n assert(rawExpectation.query !== undefined, 'Expectation missing query string');\n assert(rawExpectation.expectation !== undefined, 'Expectation missing expectation string');\n\n let expectationQuery: TestQuery;\n if (wptURL !== undefined) {\n const expectationURL = new URL(`${wptURL.origin}/${entry.query}`);\n if (expectationURL.pathname !== wptURL.pathname) {\n continue;\n }\n assert(\n expectationURL.pathname === wptURL.pathname,\n `Invalid expectation path ${expectationURL.pathname}\nExpectation should be of the form path/to/cts.https.html?worker=0&q=suite:test_path:test_name:foo=1;bar=2;...\n `\n );\n\n const params = expectationURL.searchParams;\n if (optionEnabled('worker', params) !== optionEnabled('worker', wptURL.searchParams)) {\n continue;\n }\n\n const qs = params.getAll('q');\n assert(qs.length === 1, 'currently, there must be exactly one ?q= in the expectation string');\n expectationQuery = parseQuery(qs[0]);\n } else {\n expectationQuery = parseQuery(entry.query);\n }\n\n // Strip params from multicase expectations so that an expectation of foo=2;*\n // is stored if the test query is bar=3;*\n const queryForFilter =\n expectationQuery instanceof TestQueryMultiCase\n ? new TestQueryMultiCase(\n expectationQuery.suite,\n expectationQuery.filePathParts,\n expectationQuery.testPathParts,\n {}\n )\n : expectationQuery;\n\n if (compareQueries(query, queryForFilter) === Ordering.Unordered) {\n continue;\n }\n\n switch (entry.expectation) {\n case 'pass':\n case 'skip':\n case 'fail':\n break;\n default:\n unreachable(`Invalid expectation ${entry.expectation}`);\n }\n\n expectations.push({\n query: expectationQuery,\n expectation: entry.expectation,\n });\n }\n return expectations;\n}\n\n/**\n * For display purposes only, produces a \"relative\" query string from parent to child.\n * Used in the wpt runtime to reduce the verbosity of logs.\n */\nexport function relativeQueryString(parent: TestQuery, child: TestQuery): string {\n const ordering = compareQueries(parent, child);\n if (ordering === Ordering.Equal) {\n return '';\n } else if (ordering === Ordering.StrictSuperset) {\n const parentString = parent.toString();\n assert(parentString.endsWith(kWildcard));\n const childString = child.toString();\n assert(\n childString.startsWith(parentString.substring(0, parentString.length - 2)),\n 'impossible?: childString does not start with parentString[:-2]'\n );\n return childString.substring(parentString.length - 2);\n } else {\n unreachable(\n `relativeQueryString arguments have invalid ordering ${ordering}:\\n${parent}\\n${child}`\n );\n }\n}\n"],"mappings":"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"}
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/separators.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/separators.js new file mode 100644 index 0000000000..cf0c130583 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/separators.js @@ -0,0 +1,15 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ /** Separator between big parts: suite:file:test:case */export const kBigSeparator = ':'; +/** Separator between path,to,file or path,to,test */ +export const kPathSeparator = ','; + +/** Separator between k=v;k=v */ +export const kParamSeparator = ';'; + +/** Separator between key and value in k=v */ +export const kParamKVSeparator = '='; + +/** Final wildcard, if query is not single-case */ +export const kWildcard = '*'; +//# sourceMappingURL=separators.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/separators.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/separators.js.map new file mode 100644 index 0000000000..df7bd0c9ea --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/separators.js.map @@ -0,0 +1 @@ +{"version":3,"file":"separators.js","names":["kBigSeparator","kPathSeparator","kParamSeparator","kParamKVSeparator","kWildcard"],"sources":["../../../../src/common/internal/query/separators.ts"],"sourcesContent":["/** Separator between big parts: suite:file:test:case */\nexport const kBigSeparator = ':';\n\n/** Separator between path,to,file or path,to,test */\nexport const kPathSeparator = ',';\n\n/** Separator between k=v;k=v */\nexport const kParamSeparator = ';';\n\n/** Separator between key and value in k=v */\nexport const kParamKVSeparator = '=';\n\n/** Final wildcard, if query is not single-case */\nexport const kWildcard = '*';\n"],"mappings":";AAAA;AAAA,G,CAAA,wDACA,OAAO,MAAMA,aAAa,GAAG,GAAG;AAEhC;AACA,OAAO,MAAMC,cAAc,GAAG,GAAG;;AAEjC;AACA,OAAO,MAAMC,eAAe,GAAG,GAAG;;AAElC;AACA,OAAO,MAAMC,iBAAiB,GAAG,GAAG;;AAEpC;AACA,OAAO,MAAMC,SAAS,GAAG,GAAG"}
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/stringify_params.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/stringify_params.js new file mode 100644 index 0000000000..014f502cd4 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/stringify_params.js @@ -0,0 +1,45 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { assert } from '../../util/util.js';import { badParamValueChars, paramKeyIsPublic } from '../params_utils.js'; + +import { stringifyParamValue, stringifyParamValueUniquely } from './json_param_value.js'; +import { kParamKVSeparator, kParamSeparator, kWildcard } from './separators.js'; + +export function stringifyPublicParams(p, addWildcard = false) { + const parts = Object.keys(p). + filter((k) => paramKeyIsPublic(k)). + map((k) => stringifySingleParam(k, p[k])); + + if (addWildcard) parts.push(kWildcard); + + return parts.join(kParamSeparator); +} + +/** + * An _approximately_ unique string representing a CaseParams value. + */ +export function stringifyPublicParamsUniquely(p) { + const keys = Object.keys(p).sort(); + return keys. + filter((k) => paramKeyIsPublic(k)). + map((k) => stringifySingleParamUniquely(k, p[k])). + join(kParamSeparator); +} + +export function stringifySingleParam(k, v) { + return `${k}${kParamKVSeparator}${stringifySingleParamValue(v)}`; +} + +function stringifySingleParamUniquely(k, v) { + return `${k}${kParamKVSeparator}${stringifyParamValueUniquely(v)}`; +} + +function stringifySingleParamValue(v) { + const s = stringifyParamValue(v); + assert( + !badParamValueChars.test(s), + `JSON.stringified param value must not match ${badParamValueChars} - was ${s}`); + + return s; +} +//# sourceMappingURL=stringify_params.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/stringify_params.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/stringify_params.js.map new file mode 100644 index 0000000000..60e963e6cb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/stringify_params.js.map @@ -0,0 +1 @@ +{"version":3,"file":"stringify_params.js","names":["assert","badParamValueChars","paramKeyIsPublic","stringifyParamValue","stringifyParamValueUniquely","kParamKVSeparator","kParamSeparator","kWildcard","stringifyPublicParams","p","addWildcard","parts","Object","keys","filter","k","map","stringifySingleParam","push","join","stringifyPublicParamsUniquely","sort","stringifySingleParamUniquely","v","stringifySingleParamValue","s","test"],"sources":["../../../../src/common/internal/query/stringify_params.ts"],"sourcesContent":["import { TestParams } from '../../framework/fixture.js';\nimport { assert } from '../../util/util.js';\nimport { JSONWithUndefined, badParamValueChars, paramKeyIsPublic } from '../params_utils.js';\n\nimport { stringifyParamValue, stringifyParamValueUniquely } from './json_param_value.js';\nimport { kParamKVSeparator, kParamSeparator, kWildcard } from './separators.js';\n\nexport function stringifyPublicParams(p: TestParams, addWildcard = false): string {\n const parts = Object.keys(p)\n .filter(k => paramKeyIsPublic(k))\n .map(k => stringifySingleParam(k, p[k]));\n\n if (addWildcard) parts.push(kWildcard);\n\n return parts.join(kParamSeparator);\n}\n\n/**\n * An _approximately_ unique string representing a CaseParams value.\n */\nexport function stringifyPublicParamsUniquely(p: TestParams): string {\n const keys = Object.keys(p).sort();\n return keys\n .filter(k => paramKeyIsPublic(k))\n .map(k => stringifySingleParamUniquely(k, p[k]))\n .join(kParamSeparator);\n}\n\nexport function stringifySingleParam(k: string, v: JSONWithUndefined) {\n return `${k}${kParamKVSeparator}${stringifySingleParamValue(v)}`;\n}\n\nfunction stringifySingleParamUniquely(k: string, v: JSONWithUndefined) {\n return `${k}${kParamKVSeparator}${stringifyParamValueUniquely(v)}`;\n}\n\nfunction stringifySingleParamValue(v: JSONWithUndefined): string {\n const s = stringifyParamValue(v);\n assert(\n !badParamValueChars.test(s),\n `JSON.stringified param value must not match ${badParamValueChars} - was ${s}`\n );\n return s;\n}\n"],"mappings":";AAAA;AAAA,GACA,SAASA,MAAM,QAAQ,oBAAoB,CAC3C,SAA4BC,kBAAkB,EAAEC,gBAAgB,QAAQ,oBAAoB;;AAE5F,SAASC,mBAAmB,EAAEC,2BAA2B,QAAQ,uBAAuB;AACxF,SAASC,iBAAiB,EAAEC,eAAe,EAAEC,SAAS,QAAQ,iBAAiB;;AAE/E,OAAO,SAASC,qBAAqB,CAACC,CAAa,EAAEC,WAAW,GAAG,KAAK,EAAU;EAChF,MAAMC,KAAK,GAAGC,MAAM,CAACC,IAAI,CAACJ,CAAC,CAAC;EACzBK,MAAM,CAAC,CAAAC,CAAC,KAAIb,gBAAgB,CAACa,CAAC,CAAC,CAAC;EAChCC,GAAG,CAAC,CAAAD,CAAC,KAAIE,oBAAoB,CAACF,CAAC,EAAEN,CAAC,CAACM,CAAC,CAAC,CAAC,CAAC;;EAE1C,IAAIL,WAAW,EAAEC,KAAK,CAACO,IAAI,CAACX,SAAS,CAAC;;EAEtC,OAAOI,KAAK,CAACQ,IAAI,CAACb,eAAe,CAAC;AACpC;;AAEA;AACA;AACA;AACA,OAAO,SAASc,6BAA6B,CAACX,CAAa,EAAU;EACnE,MAAMI,IAAI,GAAGD,MAAM,CAACC,IAAI,CAACJ,CAAC,CAAC,CAACY,IAAI,EAAE;EAClC,OAAOR,IAAI;EACRC,MAAM,CAAC,CAAAC,CAAC,KAAIb,gBAAgB,CAACa,CAAC,CAAC,CAAC;EAChCC,GAAG,CAAC,CAAAD,CAAC,KAAIO,4BAA4B,CAACP,CAAC,EAAEN,CAAC,CAACM,CAAC,CAAC,CAAC,CAAC;EAC/CI,IAAI,CAACb,eAAe,CAAC;AAC1B;;AAEA,OAAO,SAASW,oBAAoB,CAACF,CAAS,EAAEQ,CAAoB,EAAE;EACpE,OAAQ,GAAER,CAAE,GAAEV,iBAAkB,GAAEmB,yBAAyB,CAACD,CAAC,CAAE,EAAC;AAClE;;AAEA,SAASD,4BAA4B,CAACP,CAAS,EAAEQ,CAAoB,EAAE;EACrE,OAAQ,GAAER,CAAE,GAAEV,iBAAkB,GAAED,2BAA2B,CAACmB,CAAC,CAAE,EAAC;AACpE;;AAEA,SAASC,yBAAyB,CAACD,CAAoB,EAAU;EAC/D,MAAME,CAAC,GAAGtB,mBAAmB,CAACoB,CAAC,CAAC;EAChCvB,MAAM;EACJ,CAACC,kBAAkB,CAACyB,IAAI,CAACD,CAAC,CAAC;EAC1B,+CAA8CxB,kBAAmB,UAASwB,CAAE,EAAC,CAC/E;;EACD,OAAOA,CAAC;AACV"}
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/validQueryPart.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/validQueryPart.js new file mode 100644 index 0000000000..9fa7135cc5 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/validQueryPart.js @@ -0,0 +1,4 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ /** Applies to group parts, test parts, params keys. */export const validQueryPart = /^[a-zA-Z0-9_]+$/; +//# sourceMappingURL=validQueryPart.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/query/validQueryPart.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/validQueryPart.js.map new file mode 100644 index 0000000000..3bd6e8e82b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/query/validQueryPart.js.map @@ -0,0 +1 @@ +{"version":3,"file":"validQueryPart.js","names":["validQueryPart"],"sources":["../../../../src/common/internal/query/validQueryPart.ts"],"sourcesContent":["/** Applies to group parts, test parts, params keys. */\nexport const validQueryPart = /^[a-zA-Z0-9_]+$/;\n"],"mappings":";AAAA;AAAA,G,CAAA,uDACA,OAAO,MAAMA,cAAc,GAAG,iBAAiB"}
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/stack.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/stack.js new file mode 100644 index 0000000000..bff671d204 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/stack.js @@ -0,0 +1,83 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ // Returns the stack trace of an Error, but without the extra boilerplate at the bottom +// (e.g. RunCaseSpecific, processTicksAndRejections, etc.), for logging. +export function extractImportantStackTrace(e) {let stack = e.stack;if (!stack) { + return ''; + } + const redundantMessage = 'Error: ' + e.message + '\n'; + if (stack.startsWith(redundantMessage)) { + stack = stack.substring(redundantMessage.length); + } + + const lines = stack.split('\n'); + for (let i = lines.length - 1; i >= 0; --i) { + const line = lines[i]; + if (line.indexOf('.spec.') !== -1) { + return lines.slice(0, i + 1).join('\n'); + } + } + return stack; +} + +// *** Examples *** +// +// Node fail() +// > Error: +// > at CaseRecorder.fail (/Users/kainino/src/cts/src/common/framework/logger.ts:99:30) +// > at RunCaseSpecific.exports.g.test.t [as fn] (/Users/kainino/src/cts/src/unittests/logger.spec.ts:80:7) +// x at RunCaseSpecific.run (/Users/kainino/src/cts/src/common/framework/test_group.ts:121:18) +// x at processTicksAndRejections (internal/process/task_queues.js:86:5) +// +// Node throw +// > Error: hello +// > at RunCaseSpecific.g.test.t [as fn] (/Users/kainino/src/cts/src/unittests/test_group.spec.ts:51:11) +// x at RunCaseSpecific.run (/Users/kainino/src/cts/src/common/framework/test_group.ts:121:18) +// x at processTicksAndRejections (internal/process/task_queues.js:86:5) +// +// Firefox fail() +// > fail@http://localhost:8080/out/framework/logger.js:104:30 +// > expect@http://localhost:8080/out/framework/default_fixture.js:59:16 +// > @http://localhost:8080/out/unittests/util.spec.js:35:5 +// x run@http://localhost:8080/out/framework/test_group.js:119:18 +// +// Firefox throw +// > @http://localhost:8080/out/unittests/test_group.spec.js:48:11 +// x run@http://localhost:8080/out/framework/test_group.js:119:18 +// +// Safari fail() +// > fail@http://localhost:8080/out/framework/logger.js:104:39 +// > expect@http://localhost:8080/out/framework/default_fixture.js:59:20 +// > http://localhost:8080/out/unittests/util.spec.js:35:11 +// x http://localhost:8080/out/framework/test_group.js:119:20 +// x asyncFunctionResume@[native code] +// x [native code] +// x promiseReactionJob@[native code] +// +// Safari throw +// > http://localhost:8080/out/unittests/test_group.spec.js:48:20 +// x http://localhost:8080/out/framework/test_group.js:119:20 +// x asyncFunctionResume@[native code] +// x [native code] +// x promiseReactionJob@[native code] +// +// Chrome fail() +// x Error +// x at CaseRecorder.fail (http://localhost:8080/out/framework/logger.js:104:30) +// x at DefaultFixture.expect (http://localhost:8080/out/framework/default_fixture.js:59:16) +// > at RunCaseSpecific.fn (http://localhost:8080/out/unittests/util.spec.js:35:5) +// x at RunCaseSpecific.run (http://localhost:8080/out/framework/test_group.js:119:18) +// x at async runCase (http://localhost:8080/out/runtime/standalone.js:37:17) +// x at async http://localhost:8080/out/runtime/standalone.js:102:7 +// +// Chrome throw +// x Error: hello +// > at RunCaseSpecific.fn (http://localhost:8080/out/unittests/test_group.spec.js:48:11) +// x at RunCaseSpecific.run (http://localhost:8080/out/framework/test_group.js:119:18)" +// x at async Promise.all (index 0) +// x at async TestGroupTest.run (http://localhost:8080/out/unittests/test_group_test.js:6:5) +// x at async RunCaseSpecific.fn (http://localhost:8080/out/unittests/test_group.spec.js:53:15) +// x at async RunCaseSpecific.run (http://localhost:8080/out/framework/test_group.js:119:7) +// x at async runCase (http://localhost:8080/out/runtime/standalone.js:37:17) +// x at async http://localhost:8080/out/runtime/standalone.js:102:7 +//# sourceMappingURL=stack.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/stack.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/stack.js.map new file mode 100644 index 0000000000..399d289119 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/stack.js.map @@ -0,0 +1 @@ +{"version":3,"file":"stack.js","names":["extractImportantStackTrace","e","stack","redundantMessage","message","startsWith","substring","length","lines","split","i","line","indexOf","slice","join"],"sources":["../../../src/common/internal/stack.ts"],"sourcesContent":["// Returns the stack trace of an Error, but without the extra boilerplate at the bottom\n// (e.g. RunCaseSpecific, processTicksAndRejections, etc.), for logging.\nexport function extractImportantStackTrace(e: Error): string {\n let stack = e.stack;\n if (!stack) {\n return '';\n }\n const redundantMessage = 'Error: ' + e.message + '\\n';\n if (stack.startsWith(redundantMessage)) {\n stack = stack.substring(redundantMessage.length);\n }\n\n const lines = stack.split('\\n');\n for (let i = lines.length - 1; i >= 0; --i) {\n const line = lines[i];\n if (line.indexOf('.spec.') !== -1) {\n return lines.slice(0, i + 1).join('\\n');\n }\n }\n return stack;\n}\n\n// *** Examples ***\n//\n// Node fail()\n// > Error:\n// > at CaseRecorder.fail (/Users/kainino/src/cts/src/common/framework/logger.ts:99:30)\n// > at RunCaseSpecific.exports.g.test.t [as fn] (/Users/kainino/src/cts/src/unittests/logger.spec.ts:80:7)\n// x at RunCaseSpecific.run (/Users/kainino/src/cts/src/common/framework/test_group.ts:121:18)\n// x at processTicksAndRejections (internal/process/task_queues.js:86:5)\n//\n// Node throw\n// > Error: hello\n// > at RunCaseSpecific.g.test.t [as fn] (/Users/kainino/src/cts/src/unittests/test_group.spec.ts:51:11)\n// x at RunCaseSpecific.run (/Users/kainino/src/cts/src/common/framework/test_group.ts:121:18)\n// x at processTicksAndRejections (internal/process/task_queues.js:86:5)\n//\n// Firefox fail()\n// > fail@http://localhost:8080/out/framework/logger.js:104:30\n// > expect@http://localhost:8080/out/framework/default_fixture.js:59:16\n// > @http://localhost:8080/out/unittests/util.spec.js:35:5\n// x run@http://localhost:8080/out/framework/test_group.js:119:18\n//\n// Firefox throw\n// > @http://localhost:8080/out/unittests/test_group.spec.js:48:11\n// x run@http://localhost:8080/out/framework/test_group.js:119:18\n//\n// Safari fail()\n// > fail@http://localhost:8080/out/framework/logger.js:104:39\n// > expect@http://localhost:8080/out/framework/default_fixture.js:59:20\n// > http://localhost:8080/out/unittests/util.spec.js:35:11\n// x http://localhost:8080/out/framework/test_group.js:119:20\n// x asyncFunctionResume@[native code]\n// x [native code]\n// x promiseReactionJob@[native code]\n//\n// Safari throw\n// > http://localhost:8080/out/unittests/test_group.spec.js:48:20\n// x http://localhost:8080/out/framework/test_group.js:119:20\n// x asyncFunctionResume@[native code]\n// x [native code]\n// x promiseReactionJob@[native code]\n//\n// Chrome fail()\n// x Error\n// x at CaseRecorder.fail (http://localhost:8080/out/framework/logger.js:104:30)\n// x at DefaultFixture.expect (http://localhost:8080/out/framework/default_fixture.js:59:16)\n// > at RunCaseSpecific.fn (http://localhost:8080/out/unittests/util.spec.js:35:5)\n// x at RunCaseSpecific.run (http://localhost:8080/out/framework/test_group.js:119:18)\n// x at async runCase (http://localhost:8080/out/runtime/standalone.js:37:17)\n// x at async http://localhost:8080/out/runtime/standalone.js:102:7\n//\n// Chrome throw\n// x Error: hello\n// > at RunCaseSpecific.fn (http://localhost:8080/out/unittests/test_group.spec.js:48:11)\n// x at RunCaseSpecific.run (http://localhost:8080/out/framework/test_group.js:119:18)\"\n// x at async Promise.all (index 0)\n// x at async TestGroupTest.run (http://localhost:8080/out/unittests/test_group_test.js:6:5)\n// x at async RunCaseSpecific.fn (http://localhost:8080/out/unittests/test_group.spec.js:53:15)\n// x at async RunCaseSpecific.run (http://localhost:8080/out/framework/test_group.js:119:7)\n// x at async runCase (http://localhost:8080/out/runtime/standalone.js:37:17)\n// x at async http://localhost:8080/out/runtime/standalone.js:102:7\n"],"mappings":";AAAA;AAAA,G,CAAA;AACA;AACA,OAAO,SAASA,0BAA0B,CAACC,CAAQ,EAAU,CAC3D,IAAIC,KAAK,GAAGD,CAAC,CAACC,KAAK,CACnB,IAAI,CAACA,KAAK,EAAE;IACV,OAAO,EAAE;EACX;EACA,MAAMC,gBAAgB,GAAG,SAAS,GAAGF,CAAC,CAACG,OAAO,GAAG,IAAI;EACrD,IAAIF,KAAK,CAACG,UAAU,CAACF,gBAAgB,CAAC,EAAE;IACtCD,KAAK,GAAGA,KAAK,CAACI,SAAS,CAACH,gBAAgB,CAACI,MAAM,CAAC;EAClD;;EAEA,MAAMC,KAAK,GAAGN,KAAK,CAACO,KAAK,CAAC,IAAI,CAAC;EAC/B,KAAK,IAAIC,CAAC,GAAGF,KAAK,CAACD,MAAM,GAAG,CAAC,EAAEG,CAAC,IAAI,CAAC,EAAE,EAAEA,CAAC,EAAE;IAC1C,MAAMC,IAAI,GAAGH,KAAK,CAACE,CAAC,CAAC;IACrB,IAAIC,IAAI,CAACC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE;MACjC,OAAOJ,KAAK,CAACK,KAAK,CAAC,CAAC,EAAEH,CAAC,GAAG,CAAC,CAAC,CAACI,IAAI,CAAC,IAAI,CAAC;IACzC;EACF;EACA,OAAOZ,KAAK;AACd;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
\ No newline at end of file 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 new file mode 100644 index 0000000000..74eb775c60 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_group.js @@ -0,0 +1,647 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { +SkipTestCase, + +UnexpectedPassError } from +'../framework/fixture.js'; +import { + +builderIterateCasesWithSubcases, +kUnitCaseParamsBuilder } from + + +'../framework/params_builder.js'; +import { globalTestConfig } from '../framework/test_config.js'; + +import { TestCaseRecorder } from '../internal/logging/test_case_recorder.js'; +import { extractPublicParams, mergeParams } from '../internal/params_utils.js'; +import { compareQueries, Ordering } from '../internal/query/compare.js'; +import { TestQuerySingleCase } from '../internal/query/query.js'; +import { kPathSeparator } from '../internal/query/separators.js'; +import { +stringifyPublicParams, +stringifyPublicParamsUniquely } from +'../internal/query/stringify_params.js'; +import { validQueryPart } from '../internal/query/validQueryPart.js'; +import { assert, unreachable } from '../util/util.js'; + + + + + + + + + + + + + + + + + + + + + + + + + +export function makeTestGroup( +fixture) +{ + return new TestGroup(fixture); +} + +// Interfaces for running tests + + + + + + + + + + + +export function makeTestGroupForUnitTesting( +fixture) +{ + return new TestGroup(fixture); +} + + + + + + + + + + + + + +export class TestGroup +{ + + seen = new Set(); + tests = []; + + constructor(fixture) { + this.fixture = fixture; + } + + iterate() { + return this.tests; + } + + checkName(name) { + assert( + // Shouldn't happen due to the rule above. Just makes sure that treating + // unencoded strings as encoded strings is OK. + name === decodeURIComponent(name), + `Not decodeURIComponent-idempotent: ${name} !== ${decodeURIComponent(name)}`); + + assert(!this.seen.has(name), `Duplicate test name: ${name}`); + + this.seen.add(name); + } + + test(name) { + const testCreationStack = new Error(`Test created: ${name}`); + + this.checkName(name); + + const parts = name.split(kPathSeparator); + for (const p of parts) { + assert(validQueryPart.test(p), `Invalid test name part ${p}; must match ${validQueryPart}`); + } + + const test = new TestBuilder(parts, this.fixture, testCreationStack); + this.tests.push(test); + return test; + } + + validate() { + for (const test of this.tests) { + test.validate(); + } + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +class TestBuilder { + + + + + + + + + testCases = undefined; + batchSize = 0; + + constructor(testPath, fixture, testCreationStack) { + this.testPath = testPath; + this.isUnimplemented = false; + this.fixture = fixture; + this.testCreationStack = testCreationStack; + } + + desc(description) { + this.description = description.trim(); + return this; + } + + specURL(url) { + return this; + } + + beforeAllSubcases(fn) { + assert(this.beforeFn === undefined); + this.beforeFn = fn; + return this; + } + + fn(fn) { + + // MAINTENANCE_TODO: add "TODO" if there's no description? (and make sure it only ends up on + // actual tests, not on test parents in the tree, which is what happens if you do it here, not + // sure why) + assert(this.testFn === undefined); + this.testFn = fn; + } + + batch(b) { + this.batchSize = b; + return this; + } + + unimplemented() { + assert(this.testFn === undefined); + + this.description = + (this.description ? this.description + '\n\n' : '') + 'TODO: .unimplemented()'; + this.isUnimplemented = true; + + this.testFn = () => { + throw new SkipTestCase('test unimplemented'); + }; + } + + validate() { + const testPathString = this.testPath.join(kPathSeparator); + assert(this.testFn !== undefined, () => { + let s = `Test is missing .fn(): ${testPathString}`; + if (this.testCreationStack.stack) { + s += `\n-> test created at:\n${this.testCreationStack.stack}`; + } + return s; + }); + + if (this.testCases === undefined) { + return; + } + + const seen = new Set(); + for (const [caseParams, subcases] of builderIterateCasesWithSubcases(this.testCases)) { + for (const subcaseParams of subcases ?? [{}]) { + const params = mergeParams(caseParams, subcaseParams); + assert(this.batchSize === 0 || !('batch__' in params)); + + // stringifyPublicParams also checks for invalid params values + const testcaseString = stringifyPublicParams(params); + + // A (hopefully) unique representation of a params value. + const testcaseStringUnique = stringifyPublicParamsUniquely(params); + assert( + !seen.has(testcaseStringUnique), + `Duplicate public test case params for test ${testPathString}: ${testcaseString}`); + + seen.add(testcaseStringUnique); + } + } + } + + params( + cases) + { + assert(this.testCases === undefined, 'test case is already parameterized'); + if (cases instanceof Function) { + this.testCases = cases(kUnitCaseParamsBuilder); + } else { + this.testCases = cases; + } + return this; + } + + paramsSimple(cases) { + assert(this.testCases === undefined, 'test case is already parameterized'); + this.testCases = kUnitCaseParamsBuilder.combineWithParams(cases); + return this; + } + + paramsSubcasesOnly( + subcases) + { + if (subcases instanceof Function) { + return this.params(subcases(kUnitCaseParamsBuilder.beginSubcases())); + } else { + return this.params(kUnitCaseParamsBuilder.beginSubcases().combineWithParams(subcases)); + } + } + + *iterate() { + assert(this.testFn !== undefined, 'No test function (.fn()) for test'); + this.testCases ??= kUnitCaseParamsBuilder; + for (const [caseParams, subcases] of builderIterateCasesWithSubcases(this.testCases)) { + if (this.batchSize === 0 || subcases === undefined) { + yield new RunCaseSpecific( + this.testPath, + caseParams, + this.isUnimplemented, + subcases, + this.fixture, + this.testFn, + this.beforeFn, + this.testCreationStack); + + } else { + const subcaseArray = Array.from(subcases); + if (subcaseArray.length <= this.batchSize) { + yield new RunCaseSpecific( + this.testPath, + caseParams, + this.isUnimplemented, + subcaseArray, + this.fixture, + this.testFn, + this.beforeFn, + this.testCreationStack); + + } else { + for (let i = 0; i < subcaseArray.length; i = i + this.batchSize) { + yield new RunCaseSpecific( + this.testPath, + { ...caseParams, batch__: i / this.batchSize }, + this.isUnimplemented, + subcaseArray.slice(i, Math.min(subcaseArray.length, i + this.batchSize)), + this.fixture, + this.testFn, + this.beforeFn, + this.testCreationStack); + + } + } + } + } + } +} + +class RunCaseSpecific { + + + + + + + + + + + constructor( + testPath, + params, + isUnimplemented, + subcases, + fixture, + fn, + beforeFn, + testCreationStack) + { + this.id = { test: testPath, params: extractPublicParams(params) }; + this.isUnimplemented = isUnimplemented; + this.params = params; + this.subcases = subcases; + this.fixture = fixture; + this.fn = fn; + this.beforeFn = beforeFn; + this.testCreationStack = testCreationStack; + } + + async runTest( + rec, + sharedState, + params, + throwSkip, + expectedStatus) + { + try { + rec.beginSubCase(); + if (expectedStatus === 'skip') { + throw new SkipTestCase('Skipped by expectations'); + } + + const inst = new this.fixture(sharedState, rec, params); + try { + await inst.init(); + await this.fn(inst); + } finally { + // Runs as long as constructor succeeded, even if initialization or the test failed. + await inst.finalize(); + } + } catch (ex) { + // There was an exception from constructor, init, test, or finalize. + // An error from init or test may have been a SkipTestCase. + // An error from finalize may have been an eventualAsyncExpectation failure + // or unexpected validation/OOM error from the GPUDevice. + if (throwSkip && ex instanceof SkipTestCase) { + throw ex; + } + rec.threw(ex); + } finally { + try { + rec.endSubCase(expectedStatus); + } catch (ex) { + assert(ex instanceof UnexpectedPassError); + ex.message = `Testcase passed unexpectedly.`; + ex.stack = this.testCreationStack.stack; + rec.warn(ex); + } + } + } + + async run( + rec, + selfQuery, + expectations) + { + const getExpectedStatus = (selfQueryWithSubParams) => { + let didSeeFail = false; + for (const exp of expectations) { + const ordering = compareQueries(exp.query, selfQueryWithSubParams); + if (ordering === Ordering.Unordered || ordering === Ordering.StrictSubset) { + continue; + } + + switch (exp.expectation) { + // Skip takes precedence. If there is any expectation indicating a skip, + // signal it immediately. + case 'skip': + return 'skip'; + case 'fail': + // Otherwise, indicate that we might expect a failure. + didSeeFail = true; + break; + default: + unreachable();} + + } + return didSeeFail ? 'fail' : 'pass'; + }; + + const { testHeartbeatCallback, maxSubcasesInFlight } = globalTestConfig; + try { + rec.start(); + const sharedState = this.fixture.MakeSharedState(this.params); + try { + await sharedState.init(); + if (this.beforeFn) { + await this.beforeFn(sharedState); + } + await sharedState.postInit(); + testHeartbeatCallback(); + + let allPreviousSubcasesFinalizedPromise = Promise.resolve(); + if (this.subcases) { + let totalCount = 0; + let skipCount = 0; + + // If there are too many subcases in flight, starting the next subcase will register + // `resolvePromiseBlockingSubcase` and wait until `subcaseFinishedCallback` is called. + let subcasesInFlight = 0; + let resolvePromiseBlockingSubcase = undefined; + const subcaseFinishedCallback = () => { + subcasesInFlight -= 1; + // If there is any subcase waiting on a previous subcase to finish, + // unblock it now, and clear the resolve callback. + if (resolvePromiseBlockingSubcase) { + resolvePromiseBlockingSubcase(); + resolvePromiseBlockingSubcase = undefined; + } + }; + + for (const subParams of this.subcases) { + // Make a recorder that will defer all calls until `allPreviousSubcasesFinalizedPromise` + // resolves. Waiting on `allPreviousSubcasesFinalizedPromise` ensures that + // logs from all the previous subcases have been flushed before flushing new logs. + const subcasePrefix = 'subcase: ' + stringifyPublicParams(subParams); + const subRec = new Proxy(rec, { + get: (target, k) => { + const prop = TestCaseRecorder.prototype[k]; + if (typeof prop === 'function') { + testHeartbeatCallback(); + return function (...args) { + void allPreviousSubcasesFinalizedPromise.then(() => { + // Prepend the subcase name to all error messages. + for (const arg of args) { + if (arg instanceof Error) { + try { + arg.message = subcasePrefix + '\n' + arg.message; + } catch { + // If that fails (e.g. on DOMException), try to put it in the stack: + let stack = subcasePrefix; + if (arg.stack) stack += '\n' + arg.stack; + try { + arg.stack = stack; + } catch { + + // If that fails too, just silence it. + }} + } + } + + + const rv = prop.apply(target, args); + // Because this proxy executes functions in a deferred manner, + // it should never be used for functions that need to return a value. + assert(rv === undefined); + }); + }; + } + return prop; + } + }); + + const params = mergeParams(this.params, subParams); + const subcaseQuery = new TestQuerySingleCase( + selfQuery.suite, + selfQuery.filePathParts, + selfQuery.testPathParts, + params); + + + // Limit the maximum number of subcases in flight. + if (subcasesInFlight >= maxSubcasesInFlight) { + await new Promise((resolve) => { + // There should only be one subcase waiting at a time. + assert(resolvePromiseBlockingSubcase === undefined); + resolvePromiseBlockingSubcase = resolve; + }); + } + + subcasesInFlight += 1; + // Runs async without waiting so that subsequent subcases can start. + // All finalization steps will be waited on at the end of the testcase. + const finalizePromise = this.runTest( + subRec, + sharedState, + params, + /* throwSkip */true, + getExpectedStatus(subcaseQuery)). + + then(() => { + subRec.info(new Error('OK')); + }). + catch((ex) => { + if (ex instanceof SkipTestCase) { + // Convert SkipTestCase to info messages + ex.message = 'subcase skipped: ' + ex.message; + subRec.info(ex); + ++skipCount; + } else { + // Since we are catching all error inside runTest(), this should never happen + subRec.threw(ex); + } + }). + finally(subcaseFinishedCallback); + + allPreviousSubcasesFinalizedPromise = allPreviousSubcasesFinalizedPromise.then( + () => finalizePromise); + + ++totalCount; + } + + // Wait for all subcases to finalize and report their results. + await allPreviousSubcasesFinalizedPromise; + + if (skipCount === totalCount) { + rec.skipped(new SkipTestCase('all subcases were skipped')); + } + } else { + await this.runTest( + rec, + sharedState, + this.params, + /* throwSkip */false, + getExpectedStatus(selfQuery)); + + } + } finally { + testHeartbeatCallback(); + // Runs as long as the shared state constructor succeeded, even if initialization or a test failed. + await sharedState.finalize(); + testHeartbeatCallback(); + } + } catch (ex) { + // There was an exception from sharedState/fixture constructor, init, beforeFn, or test. + // An error from beforeFn may have been SkipTestCase. + // An error from finalize may have been an eventualAsyncExpectation failure + // or unexpected validation/OOM error from the GPUDevice. + rec.threw(ex); + } finally { + rec.finish(); + } + } +} +//# sourceMappingURL=test_group.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/test_group.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_group.js.map new file mode 100644 index 0000000000..f45df9e09c --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_group.js.map @@ -0,0 +1 @@ +{"version":3,"file":"test_group.js","names":["SkipTestCase","UnexpectedPassError","builderIterateCasesWithSubcases","kUnitCaseParamsBuilder","globalTestConfig","TestCaseRecorder","extractPublicParams","mergeParams","compareQueries","Ordering","TestQuerySingleCase","kPathSeparator","stringifyPublicParams","stringifyPublicParamsUniquely","validQueryPart","assert","unreachable","makeTestGroup","fixture","TestGroup","makeTestGroupForUnitTesting","seen","Set","tests","constructor","iterate","checkName","name","decodeURIComponent","has","add","test","testCreationStack","Error","parts","split","p","TestBuilder","push","validate","testCases","undefined","batchSize","testPath","isUnimplemented","desc","description","trim","specURL","url","beforeAllSubcases","fn","beforeFn","testFn","batch","b","unimplemented","testPathString","join","s","stack","caseParams","subcases","subcaseParams","params","testcaseString","testcaseStringUnique","cases","Function","paramsSimple","combineWithParams","paramsSubcasesOnly","beginSubcases","RunCaseSpecific","subcaseArray","Array","from","length","i","batch__","slice","Math","min","id","runTest","rec","sharedState","throwSkip","expectedStatus","beginSubCase","inst","init","finalize","ex","threw","endSubCase","message","warn","run","selfQuery","expectations","getExpectedStatus","selfQueryWithSubParams","didSeeFail","exp","ordering","query","Unordered","StrictSubset","expectation","testHeartbeatCallback","maxSubcasesInFlight","start","MakeSharedState","postInit","allPreviousSubcasesFinalizedPromise","Promise","resolve","totalCount","skipCount","subcasesInFlight","resolvePromiseBlockingSubcase","subcaseFinishedCallback","subParams","subcasePrefix","subRec","Proxy","get","target","k","prop","prototype","args","then","arg","rv","apply","subcaseQuery","suite","filePathParts","testPathParts","finalizePromise","info","catch","finally","skipped","finish"],"sources":["../../../src/common/internal/test_group.ts"],"sourcesContent":["import {\n Fixture,\n SubcaseBatchState,\n SkipTestCase,\n TestParams,\n UnexpectedPassError,\n} from '../framework/fixture.js';\nimport {\n CaseParamsBuilder,\n builderIterateCasesWithSubcases,\n kUnitCaseParamsBuilder,\n ParamsBuilderBase,\n SubcaseParamsBuilder,\n} from '../framework/params_builder.js';\nimport { globalTestConfig } from '../framework/test_config.js';\nimport { Expectation } from '../internal/logging/result.js';\nimport { TestCaseRecorder } from '../internal/logging/test_case_recorder.js';\nimport { extractPublicParams, Merged, mergeParams } from '../internal/params_utils.js';\nimport { compareQueries, Ordering } from '../internal/query/compare.js';\nimport { TestQuerySingleCase, TestQueryWithExpectation } from '../internal/query/query.js';\nimport { kPathSeparator } from '../internal/query/separators.js';\nimport {\n stringifyPublicParams,\n stringifyPublicParamsUniquely,\n} from '../internal/query/stringify_params.js';\nimport { validQueryPart } from '../internal/query/validQueryPart.js';\nimport { assert, unreachable } from '../util/util.js';\n\nexport type RunFn = (\n rec: TestCaseRecorder,\n expectations?: TestQueryWithExpectation[]\n) => Promise<void>;\n\nexport interface TestCaseID {\n readonly test: readonly string[];\n readonly params: TestParams;\n}\n\nexport interface RunCase {\n readonly id: TestCaseID;\n readonly isUnimplemented: boolean;\n run(\n rec: TestCaseRecorder,\n selfQuery: TestQuerySingleCase,\n expectations: TestQueryWithExpectation[]\n ): Promise<void>;\n}\n\n// Interface for defining tests\nexport interface TestGroupBuilder<S extends SubcaseBatchState, F extends Fixture<S>> {\n test(name: string): TestBuilderWithName<S, F>;\n}\nexport function makeTestGroup<S extends SubcaseBatchState, F extends Fixture<S>>(\n fixture: FixtureClass<S, F>\n): TestGroupBuilder<S, F> {\n return new TestGroup((fixture as unknown) as FixtureClass);\n}\n\n// Interfaces for running tests\nexport interface IterableTestGroup {\n iterate(): Iterable<IterableTest>;\n validate(): void;\n}\nexport interface IterableTest {\n testPath: string[];\n description: string | undefined;\n readonly testCreationStack: Error;\n iterate(): Iterable<RunCase>;\n}\n\nexport function makeTestGroupForUnitTesting<F extends Fixture>(\n fixture: FixtureClass<SubcaseBatchState, F>\n): TestGroup<SubcaseBatchState, F> {\n return new TestGroup(fixture);\n}\n\nexport type FixtureClass<\n S extends SubcaseBatchState = SubcaseBatchState,\n F extends Fixture<S> = Fixture<S>\n> = {\n new (sharedState: S, log: TestCaseRecorder, params: TestParams): F;\n MakeSharedState(params: TestParams): S;\n};\ntype TestFn<F extends Fixture, P extends {}> = (t: F & { params: P }) => Promise<void> | void;\ntype BeforeAllSubcasesFn<S extends SubcaseBatchState, P extends {}> = (\n s: S & { params: P }\n) => Promise<void> | void;\n\nexport class TestGroup<S extends SubcaseBatchState, F extends Fixture<S>>\n implements TestGroupBuilder<S, F> {\n private fixture: FixtureClass;\n private seen: Set<string> = new Set();\n private tests: Array<TestBuilder<S, F>> = [];\n\n constructor(fixture: FixtureClass) {\n this.fixture = fixture;\n }\n\n iterate(): Iterable<IterableTest> {\n return this.tests;\n }\n\n private checkName(name: string): void {\n assert(\n // Shouldn't happen due to the rule above. Just makes sure that treating\n // unencoded strings as encoded strings is OK.\n name === decodeURIComponent(name),\n `Not decodeURIComponent-idempotent: ${name} !== ${decodeURIComponent(name)}`\n );\n assert(!this.seen.has(name), `Duplicate test name: ${name}`);\n\n this.seen.add(name);\n }\n\n test(name: string): TestBuilderWithName<S, F> {\n const testCreationStack = new Error(`Test created: ${name}`);\n\n this.checkName(name);\n\n const parts = name.split(kPathSeparator);\n for (const p of parts) {\n assert(validQueryPart.test(p), `Invalid test name part ${p}; must match ${validQueryPart}`);\n }\n\n const test = new TestBuilder(parts, this.fixture, testCreationStack);\n this.tests.push(test);\n return (test as unknown) as TestBuilderWithName<S, F>;\n }\n\n validate(): void {\n for (const test of this.tests) {\n test.validate();\n }\n }\n}\n\ninterface TestBuilderWithName<S extends SubcaseBatchState, F extends Fixture<S>>\n extends TestBuilderWithParams<S, F, {}, {}> {\n desc(description: string): this;\n /**\n * A noop function to associate a test with the relevant part of the specification.\n *\n * @param url a link to the spec where test is extracted from.\n */\n specURL(url: string): this;\n /**\n * Parameterize the test, generating multiple cases, each possibly having subcases.\n *\n * The `unit` value passed to the `cases` callback is an immutable constant\n * `CaseParamsBuilder<{}>` representing the \"unit\" builder `[ {} ]`,\n * provided for convenience. The non-callback overload can be used if `unit` is not needed.\n */\n params<CaseP extends {}, SubcaseP extends {}>(\n cases: (unit: CaseParamsBuilder<{}>) => ParamsBuilderBase<CaseP, SubcaseP>\n ): TestBuilderWithParams<S, F, CaseP, SubcaseP>;\n /**\n * Parameterize the test, generating multiple cases, each possibly having subcases.\n *\n * Use the callback overload of this method if a \"unit\" builder is needed.\n */\n params<CaseP extends {}, SubcaseP extends {}>(\n cases: ParamsBuilderBase<CaseP, SubcaseP>\n ): TestBuilderWithParams<S, F, CaseP, SubcaseP>;\n\n /**\n * Parameterize the test, generating multiple cases, without subcases.\n */\n paramsSimple<P extends {}>(cases: Iterable<P>): TestBuilderWithParams<S, F, P, {}>;\n\n /**\n * Parameterize the test, generating one case with multiple subcases.\n */\n paramsSubcasesOnly<P extends {}>(subcases: Iterable<P>): TestBuilderWithParams<S, F, {}, P>;\n /**\n * Parameterize the test, generating one case with multiple subcases.\n *\n * The `unit` value passed to the `subcases` callback is an immutable constant\n * `SubcaseParamsBuilder<{}>`, with one empty case `{}` and one empty subcase `{}`.\n */\n paramsSubcasesOnly<P extends {}>(\n subcases: (unit: SubcaseParamsBuilder<{}, {}>) => SubcaseParamsBuilder<{}, P>\n ): TestBuilderWithParams<S, F, {}, P>;\n}\n\ninterface TestBuilderWithParams<\n S extends SubcaseBatchState,\n F extends Fixture<S>,\n CaseP extends {},\n SubcaseP extends {}\n> {\n /**\n * Limit subcases to a maximum number of per testcase.\n * @param b the maximum number of subcases per testcase.\n *\n * If the number of subcases exceeds `b`, add an internal\n * numeric, incrementing `batch__` param to split subcases\n * into groups of at most `b` subcases.\n */\n batch(b: number): this;\n /**\n * Run a function on shared subcase batch state before each\n * batch of subcases.\n * @param fn the function to run. It is called with the test\n * fixture's shared subcase batch state.\n *\n * Generally, this function should be careful to avoid mutating\n * any state on the shared subcase batch state which could result\n * in unexpected order-dependent test behavior.\n */\n beforeAllSubcases(fn: BeforeAllSubcasesFn<S, CaseP>): this;\n /**\n * Set the test function.\n * @param fn the test function.\n */\n fn(fn: TestFn<F, Merged<CaseP, SubcaseP>>): void;\n /**\n * Mark the test as unimplemented.\n */\n unimplemented(): void;\n}\n\nclass TestBuilder<S extends SubcaseBatchState, F extends Fixture> {\n readonly testPath: string[];\n isUnimplemented: boolean;\n description: string | undefined;\n readonly testCreationStack: Error;\n\n private readonly fixture: FixtureClass;\n private testFn: TestFn<Fixture, {}> | undefined;\n private beforeFn: BeforeAllSubcasesFn<SubcaseBatchState, {}> | undefined;\n private testCases?: ParamsBuilderBase<{}, {}> = undefined;\n private batchSize: number = 0;\n\n constructor(testPath: string[], fixture: FixtureClass, testCreationStack: Error) {\n this.testPath = testPath;\n this.isUnimplemented = false;\n this.fixture = fixture;\n this.testCreationStack = testCreationStack;\n }\n\n desc(description: string): this {\n this.description = description.trim();\n return this;\n }\n\n specURL(url: string): this {\n return this;\n }\n\n beforeAllSubcases(fn: BeforeAllSubcasesFn<SubcaseBatchState, {}>): this {\n assert(this.beforeFn === undefined);\n this.beforeFn = fn;\n return this;\n }\n\n fn(fn: TestFn<Fixture, {}>): void {\n // eslint-disable-next-line no-warning-comments\n // MAINTENANCE_TODO: add \"TODO\" if there's no description? (and make sure it only ends up on\n // actual tests, not on test parents in the tree, which is what happens if you do it here, not\n // sure why)\n assert(this.testFn === undefined);\n this.testFn = fn;\n }\n\n batch(b: number): this {\n this.batchSize = b;\n return this;\n }\n\n unimplemented(): void {\n assert(this.testFn === undefined);\n\n this.description =\n (this.description ? this.description + '\\n\\n' : '') + 'TODO: .unimplemented()';\n this.isUnimplemented = true;\n\n this.testFn = () => {\n throw new SkipTestCase('test unimplemented');\n };\n }\n\n validate(): void {\n const testPathString = this.testPath.join(kPathSeparator);\n assert(this.testFn !== undefined, () => {\n let s = `Test is missing .fn(): ${testPathString}`;\n if (this.testCreationStack.stack) {\n s += `\\n-> test created at:\\n${this.testCreationStack.stack}`;\n }\n return s;\n });\n\n if (this.testCases === undefined) {\n return;\n }\n\n const seen = new Set<string>();\n for (const [caseParams, subcases] of builderIterateCasesWithSubcases(this.testCases)) {\n for (const subcaseParams of subcases ?? [{}]) {\n const params = mergeParams(caseParams, subcaseParams);\n assert(this.batchSize === 0 || !('batch__' in params));\n\n // stringifyPublicParams also checks for invalid params values\n const testcaseString = stringifyPublicParams(params);\n\n // A (hopefully) unique representation of a params value.\n const testcaseStringUnique = stringifyPublicParamsUniquely(params);\n assert(\n !seen.has(testcaseStringUnique),\n `Duplicate public test case params for test ${testPathString}: ${testcaseString}`\n );\n seen.add(testcaseStringUnique);\n }\n }\n }\n\n params(\n cases: ((unit: CaseParamsBuilder<{}>) => ParamsBuilderBase<{}, {}>) | ParamsBuilderBase<{}, {}>\n ): TestBuilder<S, F> {\n assert(this.testCases === undefined, 'test case is already parameterized');\n if (cases instanceof Function) {\n this.testCases = cases(kUnitCaseParamsBuilder);\n } else {\n this.testCases = cases;\n }\n return this;\n }\n\n paramsSimple(cases: Iterable<{}>): TestBuilder<S, F> {\n assert(this.testCases === undefined, 'test case is already parameterized');\n this.testCases = kUnitCaseParamsBuilder.combineWithParams(cases);\n return this;\n }\n\n paramsSubcasesOnly(\n subcases: Iterable<{}> | ((unit: SubcaseParamsBuilder<{}, {}>) => SubcaseParamsBuilder<{}, {}>)\n ): TestBuilder<S, F> {\n if (subcases instanceof Function) {\n return this.params(subcases(kUnitCaseParamsBuilder.beginSubcases()));\n } else {\n return this.params(kUnitCaseParamsBuilder.beginSubcases().combineWithParams(subcases));\n }\n }\n\n *iterate(): IterableIterator<RunCase> {\n assert(this.testFn !== undefined, 'No test function (.fn()) for test');\n this.testCases ??= kUnitCaseParamsBuilder;\n for (const [caseParams, subcases] of builderIterateCasesWithSubcases(this.testCases)) {\n if (this.batchSize === 0 || subcases === undefined) {\n yield new RunCaseSpecific(\n this.testPath,\n caseParams,\n this.isUnimplemented,\n subcases,\n this.fixture,\n this.testFn,\n this.beforeFn,\n this.testCreationStack\n );\n } else {\n const subcaseArray = Array.from(subcases);\n if (subcaseArray.length <= this.batchSize) {\n yield new RunCaseSpecific(\n this.testPath,\n caseParams,\n this.isUnimplemented,\n subcaseArray,\n this.fixture,\n this.testFn,\n this.beforeFn,\n this.testCreationStack\n );\n } else {\n for (let i = 0; i < subcaseArray.length; i = i + this.batchSize) {\n yield new RunCaseSpecific(\n this.testPath,\n { ...caseParams, batch__: i / this.batchSize },\n this.isUnimplemented,\n subcaseArray.slice(i, Math.min(subcaseArray.length, i + this.batchSize)),\n this.fixture,\n this.testFn,\n this.beforeFn,\n this.testCreationStack\n );\n }\n }\n }\n }\n }\n}\n\nclass RunCaseSpecific implements RunCase {\n readonly id: TestCaseID;\n readonly isUnimplemented: boolean;\n\n private readonly params: {};\n private readonly subcases: Iterable<{}> | undefined;\n private readonly fixture: FixtureClass;\n private readonly fn: TestFn<Fixture, {}>;\n private readonly beforeFn?: BeforeAllSubcasesFn<SubcaseBatchState, {}>;\n private readonly testCreationStack: Error;\n\n constructor(\n testPath: string[],\n params: {},\n isUnimplemented: boolean,\n subcases: Iterable<{}> | undefined,\n fixture: FixtureClass,\n fn: TestFn<Fixture, {}>,\n beforeFn: BeforeAllSubcasesFn<SubcaseBatchState, {}> | undefined,\n testCreationStack: Error\n ) {\n this.id = { test: testPath, params: extractPublicParams(params) };\n this.isUnimplemented = isUnimplemented;\n this.params = params;\n this.subcases = subcases;\n this.fixture = fixture;\n this.fn = fn;\n this.beforeFn = beforeFn;\n this.testCreationStack = testCreationStack;\n }\n\n async runTest(\n rec: TestCaseRecorder,\n sharedState: SubcaseBatchState,\n params: TestParams,\n throwSkip: boolean,\n expectedStatus: Expectation\n ): Promise<void> {\n try {\n rec.beginSubCase();\n if (expectedStatus === 'skip') {\n throw new SkipTestCase('Skipped by expectations');\n }\n\n const inst = new this.fixture(sharedState, rec, params);\n try {\n await inst.init();\n await this.fn(inst as Fixture & { params: {} });\n } finally {\n // Runs as long as constructor succeeded, even if initialization or the test failed.\n await inst.finalize();\n }\n } catch (ex) {\n // There was an exception from constructor, init, test, or finalize.\n // An error from init or test may have been a SkipTestCase.\n // An error from finalize may have been an eventualAsyncExpectation failure\n // or unexpected validation/OOM error from the GPUDevice.\n if (throwSkip && ex instanceof SkipTestCase) {\n throw ex;\n }\n rec.threw(ex);\n } finally {\n try {\n rec.endSubCase(expectedStatus);\n } catch (ex) {\n assert(ex instanceof UnexpectedPassError);\n ex.message = `Testcase passed unexpectedly.`;\n ex.stack = this.testCreationStack.stack;\n rec.warn(ex);\n }\n }\n }\n\n async run(\n rec: TestCaseRecorder,\n selfQuery: TestQuerySingleCase,\n expectations: TestQueryWithExpectation[]\n ): Promise<void> {\n const getExpectedStatus = (selfQueryWithSubParams: TestQuerySingleCase) => {\n let didSeeFail = false;\n for (const exp of expectations) {\n const ordering = compareQueries(exp.query, selfQueryWithSubParams);\n if (ordering === Ordering.Unordered || ordering === Ordering.StrictSubset) {\n continue;\n }\n\n switch (exp.expectation) {\n // Skip takes precedence. If there is any expectation indicating a skip,\n // signal it immediately.\n case 'skip':\n return 'skip';\n case 'fail':\n // Otherwise, indicate that we might expect a failure.\n didSeeFail = true;\n break;\n default:\n unreachable();\n }\n }\n return didSeeFail ? 'fail' : 'pass';\n };\n\n const { testHeartbeatCallback, maxSubcasesInFlight } = globalTestConfig;\n try {\n rec.start();\n const sharedState = this.fixture.MakeSharedState(this.params);\n try {\n await sharedState.init();\n if (this.beforeFn) {\n await this.beforeFn(sharedState);\n }\n await sharedState.postInit();\n testHeartbeatCallback();\n\n let allPreviousSubcasesFinalizedPromise: Promise<void> = Promise.resolve();\n if (this.subcases) {\n let totalCount = 0;\n let skipCount = 0;\n\n // If there are too many subcases in flight, starting the next subcase will register\n // `resolvePromiseBlockingSubcase` and wait until `subcaseFinishedCallback` is called.\n let subcasesInFlight = 0;\n let resolvePromiseBlockingSubcase: (() => void) | undefined = undefined;\n const subcaseFinishedCallback = () => {\n subcasesInFlight -= 1;\n // If there is any subcase waiting on a previous subcase to finish,\n // unblock it now, and clear the resolve callback.\n if (resolvePromiseBlockingSubcase) {\n resolvePromiseBlockingSubcase();\n resolvePromiseBlockingSubcase = undefined;\n }\n };\n\n for (const subParams of this.subcases) {\n // Make a recorder that will defer all calls until `allPreviousSubcasesFinalizedPromise`\n // resolves. Waiting on `allPreviousSubcasesFinalizedPromise` ensures that\n // logs from all the previous subcases have been flushed before flushing new logs.\n const subcasePrefix = 'subcase: ' + stringifyPublicParams(subParams);\n const subRec = new Proxy(rec, {\n get: (target, k: keyof TestCaseRecorder) => {\n const prop = TestCaseRecorder.prototype[k];\n if (typeof prop === 'function') {\n testHeartbeatCallback();\n return function (...args: Parameters<typeof prop>) {\n void allPreviousSubcasesFinalizedPromise.then(() => {\n // Prepend the subcase name to all error messages.\n for (const arg of args) {\n if (arg instanceof Error) {\n try {\n arg.message = subcasePrefix + '\\n' + arg.message;\n } catch {\n // If that fails (e.g. on DOMException), try to put it in the stack:\n let stack = subcasePrefix;\n if (arg.stack) stack += '\\n' + arg.stack;\n try {\n arg.stack = stack;\n } catch {\n // If that fails too, just silence it.\n }\n }\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const rv = (prop as any).apply(target, args);\n // Because this proxy executes functions in a deferred manner,\n // it should never be used for functions that need to return a value.\n assert(rv === undefined);\n });\n };\n }\n return prop;\n },\n });\n\n const params = mergeParams(this.params, subParams);\n const subcaseQuery = new TestQuerySingleCase(\n selfQuery.suite,\n selfQuery.filePathParts,\n selfQuery.testPathParts,\n params\n );\n\n // Limit the maximum number of subcases in flight.\n if (subcasesInFlight >= maxSubcasesInFlight) {\n await new Promise<void>(resolve => {\n // There should only be one subcase waiting at a time.\n assert(resolvePromiseBlockingSubcase === undefined);\n resolvePromiseBlockingSubcase = resolve;\n });\n }\n\n subcasesInFlight += 1;\n // Runs async without waiting so that subsequent subcases can start.\n // All finalization steps will be waited on at the end of the testcase.\n const finalizePromise = this.runTest(\n subRec,\n sharedState,\n params,\n /* throwSkip */ true,\n getExpectedStatus(subcaseQuery)\n )\n .then(() => {\n subRec.info(new Error('OK'));\n })\n .catch(ex => {\n if (ex instanceof SkipTestCase) {\n // Convert SkipTestCase to info messages\n ex.message = 'subcase skipped: ' + ex.message;\n subRec.info(ex);\n ++skipCount;\n } else {\n // Since we are catching all error inside runTest(), this should never happen\n subRec.threw(ex);\n }\n })\n .finally(subcaseFinishedCallback);\n\n allPreviousSubcasesFinalizedPromise = allPreviousSubcasesFinalizedPromise.then(\n () => finalizePromise\n );\n ++totalCount;\n }\n\n // Wait for all subcases to finalize and report their results.\n await allPreviousSubcasesFinalizedPromise;\n\n if (skipCount === totalCount) {\n rec.skipped(new SkipTestCase('all subcases were skipped'));\n }\n } else {\n await this.runTest(\n rec,\n sharedState,\n this.params,\n /* throwSkip */ false,\n getExpectedStatus(selfQuery)\n );\n }\n } finally {\n testHeartbeatCallback();\n // Runs as long as the shared state constructor succeeded, even if initialization or a test failed.\n await sharedState.finalize();\n testHeartbeatCallback();\n }\n } catch (ex) {\n // There was an exception from sharedState/fixture constructor, init, beforeFn, or test.\n // An error from beforeFn may have been SkipTestCase.\n // An error from finalize may have been an eventualAsyncExpectation failure\n // or unexpected validation/OOM error from the GPUDevice.\n rec.threw(ex);\n } finally {\n rec.finish();\n }\n }\n}\n"],"mappings":"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"}
\ 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 new file mode 100644 index 0000000000..fc2c8c4189 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_suite_listing.js @@ -0,0 +1,4 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/export {}; +//# sourceMappingURL=test_suite_listing.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/test_suite_listing.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_suite_listing.js.map new file mode 100644 index 0000000000..89ae3a6866 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/test_suite_listing.js.map @@ -0,0 +1 @@ +{"version":3,"file":"test_suite_listing.js","names":[],"sources":["../../../src/common/internal/test_suite_listing.ts"],"sourcesContent":["// A listing of all specs within a single suite. This is the (awaited) type of\n// `groups` in '{cts,unittests}/listing.ts' and `listing` in the auto-generated\n// 'out/{cts,unittests}/listing.js' files (see tools/gen_listings).\nexport type TestSuiteListing = TestSuiteListingEntry[];\n\nexport type TestSuiteListingEntry = TestSuiteListingEntrySpec | TestSuiteListingEntryReadme;\n\ninterface TestSuiteListingEntrySpec {\n readonly file: string[];\n}\n\ninterface TestSuiteListingEntryReadme {\n readonly file: string[];\n readonly readme: string;\n}\n"],"mappings":";AAAA;AAAA,G"}
\ 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 new file mode 100644 index 0000000000..5245079d5d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/tree.js @@ -0,0 +1,576 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { assert } from '../util/util.js'; + + +import { compareQueries, Ordering } from './query/compare.js'; +import { + +TestQueryMultiCase, +TestQuerySingleCase, +TestQueryMultiFile, +TestQueryMultiTest } from +'./query/query.js'; +import { kBigSeparator, kWildcard, kPathSeparator, kParamSeparator } from './query/separators.js'; +import { stringifySingleParam } from './query/stringify_params.js'; +import { StacklessError } from './util.js'; + +// `loadTreeForQuery()` loads a TestTree for a given queryToLoad. +// The resulting tree is a linked-list all the way from `suite:*` to queryToLoad, +// and under queryToLoad is a tree containing every case matched by queryToLoad. +// +// `subqueriesToExpand` influences the `collapsible` flag on nodes in the resulting tree. +// A node is considered "collapsible" if none of the subqueriesToExpand is a StrictSubset +// of that node. +// +// In WebKit/Blink-style web_tests, an expectation file marks individual cts.https.html "variants +// as "Failure", "Crash", etc. By passing in the list of expectations as the subqueriesToExpand, +// we can programmatically subdivide the cts.https.html "variants" list to be able to implement +// arbitrarily-fine suppressions (instead of having to suppress entire test files, which would +// lose a lot of coverage). +// +// `iterateCollapsedNodes()` produces the list of queries for the variants list. +// +// Though somewhat complicated, this system has important benefits: +// - Avoids having to suppress entire test files, which would cause large test coverage loss. +// - Minimizes the number of page loads needed for fine-grained suppressions. +// (In the naive case, we could do one page load per test case - but the test suite would +// take impossibly long to run.) +// - Enables developers to put any number of tests in one file as appropriate, without worrying +// about expectation granularity. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +export class TestTree { + /** + * The `queryToLoad` that this test tree was created for. + * Test trees are always rooted at `suite:*`, but they only contain nodes that fit + * within `forQuery`. + * + * This is used for `iterateCollapsedNodes` which only starts collapsing at the next + * `TestQueryLevel` after `forQuery`. + */ + + + + constructor(forQuery, root) { + this.forQuery = forQuery; + TestTree.propagateCounts(root); + this.root = root; + assert( + root.query.level === 1 && root.query.depthInLevel === 0, + 'TestTree root must be the root (suite:*)'); + + } + + /** + * Iterate through the leaves of a version of the tree which has been pruned to exclude + * subtrees which: + * - are at a deeper `TestQueryLevel` than `this.forQuery`, and + * - were not a `Ordering.StrictSubset` of any of the `subqueriesToExpand` during tree creation. + */ + iterateCollapsedNodes({ + includeIntermediateNodes = false, + includeEmptySubtrees = false, + alwaysExpandThroughLevel + + + + + + + + }) { + const expandThroughLevel = Math.max(this.forQuery.level, alwaysExpandThroughLevel); + return TestTree.iterateSubtreeNodes(this.root, { + includeIntermediateNodes, + includeEmptySubtrees, + expandThroughLevel + }); + } + + iterateLeaves() { + return TestTree.iterateSubtreeLeaves(this.root); + } + + /** + * Dissolve nodes which have only one child, e.g.: + * a,* { a,b,* { a,b:* { ... } } } + * collapses down into: + * a,* { a,b:* { ... } } + * which is less needlessly verbose when displaying the tree in the standalone runner. + */ + dissolveSingleChildTrees() { + const newRoot = dissolveSingleChildTrees(this.root); + assert(newRoot === this.root); + } + + toString() { + return TestTree.subtreeToString('(root)', this.root, ''); + } + + static *iterateSubtreeNodes( + subtree, + opts) + + + + + { + if (opts.includeIntermediateNodes) { + yield subtree; + } + + for (const [, child] of subtree.children) { + if ('children' in child) { + // Is a subtree + const collapsible = child.collapsible && child.query.level > opts.expandThroughLevel; + if (child.children.size > 0 && !collapsible) { + yield* TestTree.iterateSubtreeNodes(child, opts); + } else if (child.children.size > 0 || opts.includeEmptySubtrees) { + // Don't yield empty subtrees (e.g. files with no tests) unless includeEmptySubtrees + yield child; + } + } else { + // Is a leaf + yield child; + } + } + } + + static *iterateSubtreeLeaves(subtree) { + for (const [, child] of subtree.children) { + if ('children' in child) { + yield* TestTree.iterateSubtreeLeaves(child); + } else { + yield child; + } + } + } + + /** Propagate the subtreeTODOs/subtreeTests state upward from leaves to parent nodes. */ + static propagateCounts(subtree) { + subtree.subtreeCounts ??= { tests: 0, nodesWithTODO: 0 }; + for (const [, child] of subtree.children) { + if ('children' in child) { + const counts = TestTree.propagateCounts(child); + subtree.subtreeCounts.tests += counts.tests; + subtree.subtreeCounts.nodesWithTODO += counts.nodesWithTODO; + } + } + return subtree.subtreeCounts; + } + + /** Displays counts in the format `(Nodes with TODOs) / (Total test count)`. */ + static countsToString(tree) { + if (tree.subtreeCounts) { + return `${tree.subtreeCounts.nodesWithTODO} / ${tree.subtreeCounts.tests}`; + } else { + return ''; + } + } + + static subtreeToString(name, tree, indent) { + const collapsible = 'run' in tree ? '>' : tree.collapsible ? '+' : '-'; + let s = + indent + + `${collapsible} ${TestTree.countsToString(tree)} ${JSON.stringify(name)} => ${tree.query}`; + if ('children' in tree) { + if (tree.description !== undefined) { + s += `\n${indent} | ${JSON.stringify(tree.description)}`; + } + + for (const [name, child] of tree.children) { + s += '\n' + TestTree.subtreeToString(name, child, indent + ' '); + } + } + return s; + } +} + +// MAINTENANCE_TODO: Consider having subqueriesToExpand actually impact the depth-order of params +// in the tree. +export async function loadTreeForQuery( +loader, +queryToLoad, +subqueriesToExpand) +{ + const suite = queryToLoad.suite; + const specs = await loader.listing(suite); + + const subqueriesToExpandEntries = Array.from(subqueriesToExpand.entries()); + const seenSubqueriesToExpand = new Array(subqueriesToExpand.length); + seenSubqueriesToExpand.fill(false); + + const isCollapsible = (subquery) => + subqueriesToExpandEntries.every(([i, toExpand]) => { + const ordering = compareQueries(toExpand, subquery); + + // If toExpand == subquery, no expansion is needed (but it's still "seen"). + if (ordering === Ordering.Equal) seenSubqueriesToExpand[i] = true; + return ordering !== Ordering.StrictSubset; + }); + + // L0 = suite-level, e.g. suite:* + // L1 = file-level, e.g. suite:a,b:* + // L2 = test-level, e.g. suite:a,b:c,d:* + // L3 = case-level, e.g. suite:a,b:c,d: + let foundCase = false; + // L0 is suite:* + const subtreeL0 = makeTreeForSuite(suite, isCollapsible); + for (const entry of specs) { + if (entry.file.length === 0 && 'readme' in entry) { + // Suite-level readme. + setSubtreeDescriptionAndCountTODOs(subtreeL0, entry.readme); + continue; + } + + { + const queryL1 = new TestQueryMultiFile(suite, entry.file); + const orderingL1 = compareQueries(queryL1, queryToLoad); + if (orderingL1 === Ordering.Unordered) { + // File path is not matched by this query. + continue; + } + } + + if ('readme' in entry) { + // Entry is a README that is an ancestor or descendant of the query. + // (It's included for display in the standalone runner.) + + // readmeSubtree is suite:a,b,* + // (This is always going to dedup with a file path, if there are any test spec files under + // the directory that has the README). + const readmeSubtree = addSubtreeForDirPath( + subtreeL0, + entry.file, + isCollapsible); + + setSubtreeDescriptionAndCountTODOs(readmeSubtree, entry.readme); + continue; + } + // Entry is a spec file. + + const spec = await loader.importSpecFile(queryToLoad.suite, entry.file); + // subtreeL1 is suite:a,b:* + const subtreeL1 = addSubtreeForFilePath( + subtreeL0, + entry.file, + isCollapsible); + + setSubtreeDescriptionAndCountTODOs(subtreeL1, spec.description); + + let groupHasTests = false; + for (const t of spec.g.iterate()) { + groupHasTests = true; + { + const queryL2 = new TestQueryMultiCase(suite, entry.file, t.testPath, {}); + const orderingL2 = compareQueries(queryL2, queryToLoad); + if (orderingL2 === Ordering.Unordered) { + // Test path is not matched by this query. + continue; + } + } + + // subtreeL2 is suite:a,b:c,d:* + const subtreeL2 = addSubtreeForTestPath( + subtreeL1, + t.testPath, + t.testCreationStack, + isCollapsible); + + // This is 1 test. Set tests=1 then count TODOs. + subtreeL2.subtreeCounts ??= { tests: 1, nodesWithTODO: 0 }; + if (t.description) setSubtreeDescriptionAndCountTODOs(subtreeL2, t.description); + + // MAINTENANCE_TODO: If tree generation gets too slow, avoid actually iterating the cases in a + // file if there's no need to (based on the subqueriesToExpand). + for (const c of t.iterate()) { + { + const queryL3 = new TestQuerySingleCase(suite, entry.file, c.id.test, c.id.params); + const orderingL3 = compareQueries(queryL3, queryToLoad); + if (orderingL3 === Ordering.Unordered || orderingL3 === Ordering.StrictSuperset) { + // Case is not matched by this query. + continue; + } + } + + // Leaf for case is suite:a,b:c,d:x=1;y=2 + addLeafForCase(subtreeL2, c, isCollapsible); + + foundCase = true; + } + } + if (!groupHasTests && !subtreeL1.subtreeCounts) { + throw new StacklessError( + `${subtreeL1.query} has no tests - it must have "TODO" in its description`); + + } + } + + for (const [i, sq] of subqueriesToExpandEntries) { + const subquerySeen = seenSubqueriesToExpand[i]; + if (!subquerySeen) { + throw new StacklessError( + `subqueriesToExpand entry did not match anything \ +(could be wrong, or could be redundant with a previous subquery):\n ${sq.toString()}`); + + } + } + assert(foundCase, `Query \`${queryToLoad.toString()}\` does not match any cases`); + + return new TestTree(queryToLoad, subtreeL0); +} + +function setSubtreeDescriptionAndCountTODOs( +subtree, +description) +{ + assert(subtree.description === undefined); + subtree.description = description.trim(); + subtree.subtreeCounts ??= { tests: 0, nodesWithTODO: 0 }; + if (subtree.description.indexOf('TODO') !== -1) { + subtree.subtreeCounts.nodesWithTODO++; + } +} + +function makeTreeForSuite( +suite, +isCollapsible) +{ + const query = new TestQueryMultiFile(suite, []); + return { + readableRelativeName: suite + kBigSeparator, + query, + children: new Map(), + collapsible: isCollapsible(query) + }; +} + +function addSubtreeForDirPath( +tree, +file, +isCollapsible) +{ + const subqueryFile = []; + // To start, tree is suite:* + // This loop goes from that -> suite:a,* -> suite:a,b,* + for (const part of file) { + subqueryFile.push(part); + tree = getOrInsertSubtree(part, tree, () => { + const query = new TestQueryMultiFile(tree.query.suite, subqueryFile); + return { + readableRelativeName: part + kPathSeparator + kWildcard, + query, + collapsible: isCollapsible(query) + }; + }); + } + return tree; +} + +function addSubtreeForFilePath( +tree, +file, +isCollapsible) +{ + // To start, tree is suite:* + // This goes from that -> suite:a,* -> suite:a,b,* + tree = addSubtreeForDirPath(tree, file, isCollapsible); + // This goes from that -> suite:a,b:* + const subtree = getOrInsertSubtree('', tree, () => { + const query = new TestQueryMultiTest(tree.query.suite, tree.query.filePathParts, []); + assert(file.length > 0, 'file path is empty'); + return { + readableRelativeName: file[file.length - 1] + kBigSeparator + kWildcard, + query, + collapsible: isCollapsible(query) + }; + }); + return subtree; +} + +function addSubtreeForTestPath( +tree, +test, +testCreationStack, +isCollapsible) +{ + const subqueryTest = []; + // To start, tree is suite:a,b:* + // This loop goes from that -> suite:a,b:c,* -> suite:a,b:c,d,* + for (const part of test) { + subqueryTest.push(part); + tree = getOrInsertSubtree(part, tree, () => { + const query = new TestQueryMultiTest( + tree.query.suite, + tree.query.filePathParts, + subqueryTest); + + return { + readableRelativeName: part + kPathSeparator + kWildcard, + query, + collapsible: isCollapsible(query) + }; + }); + } + // This goes from that -> suite:a,b:c,d:* + return getOrInsertSubtree('', tree, () => { + const query = new TestQueryMultiCase( + tree.query.suite, + tree.query.filePathParts, + subqueryTest, + {}); + + assert(subqueryTest.length > 0, 'subqueryTest is empty'); + return { + readableRelativeName: subqueryTest[subqueryTest.length - 1] + kBigSeparator + kWildcard, + kWildcard, + query, + testCreationStack, + collapsible: isCollapsible(query) + }; + }); +} + +function addLeafForCase( +tree, +t, +checkCollapsible) +{ + const query = tree.query; + let name = ''; + const subqueryParams = {}; + + // To start, tree is suite:a,b:c,d:* + // This loop goes from that -> suite:a,b:c,d:x=1;* -> suite:a,b:c,d:x=1;y=2;* + for (const [k, v] of Object.entries(t.id.params)) { + name = stringifySingleParam(k, v); + subqueryParams[k] = v; + + tree = getOrInsertSubtree(name, tree, () => { + const subquery = new TestQueryMultiCase( + query.suite, + query.filePathParts, + query.testPathParts, + subqueryParams); + + return { + readableRelativeName: name + kParamSeparator + kWildcard, + query: subquery, + collapsible: checkCollapsible(subquery) + }; + }); + } + + // This goes from that -> suite:a,b:c,d:x=1;y=2 + const subquery = new TestQuerySingleCase( + query.suite, + query.filePathParts, + query.testPathParts, + subqueryParams); + + checkCollapsible(subquery); // mark seenSubqueriesToExpand + insertLeaf(tree, subquery, t); +} + +function getOrInsertSubtree( +key, +parent, +createSubtree) +{ + let v; + const child = parent.children.get(key); + if (child !== undefined) { + assert('children' in child); // Make sure cached subtree is not actually a leaf + v = child; + } else { + v = { ...createSubtree(), children: new Map() }; + parent.children.set(key, v); + } + return v; +} + +function insertLeaf(parent, query, t) { + const leaf = { + readableRelativeName: readableNameForCase(query), + query, + run: (rec, expectations) => t.run(rec, query, expectations || []), + isUnimplemented: t.isUnimplemented + }; + + // This is a leaf (e.g. s:f:t:x=1;* -> s:f:t:x=1). The key is always ''. + const key = ''; + assert(!parent.children.has(key), `Duplicate testcase: ${query}`); + parent.children.set(key, leaf); +} + +function dissolveSingleChildTrees(tree) { + if ('children' in tree) { + const shouldDissolveThisTree = + tree.children.size === 1 && tree.query.depthInLevel !== 0 && tree.description === undefined; + if (shouldDissolveThisTree) { + // Loops exactly once + for (const [, child] of tree.children) { + // Recurse on child + return dissolveSingleChildTrees(child); + } + } + + for (const [k, child] of tree.children) { + // Recurse on each child + const newChild = dissolveSingleChildTrees(child); + if (newChild !== child) { + tree.children.set(k, newChild); + } + } + } + return tree; +} + +/** Generate a readable relative name for a case (used in standalone). */ +function readableNameForCase(query) { + const paramsKeys = Object.keys(query.params); + if (paramsKeys.length === 0) { + return query.testPathParts[query.testPathParts.length - 1] + kBigSeparator; + } else { + const lastKey = paramsKeys[paramsKeys.length - 1]; + return stringifySingleParam(lastKey, query.params[lastKey]); + } +} +//# sourceMappingURL=tree.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/tree.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/tree.js.map new file mode 100644 index 0000000000..44a0c7c035 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/tree.js.map @@ -0,0 +1 @@ +{"version":3,"file":"tree.js","names":["assert","compareQueries","Ordering","TestQueryMultiCase","TestQuerySingleCase","TestQueryMultiFile","TestQueryMultiTest","kBigSeparator","kWildcard","kPathSeparator","kParamSeparator","stringifySingleParam","StacklessError","TestTree","constructor","forQuery","root","propagateCounts","query","level","depthInLevel","iterateCollapsedNodes","includeIntermediateNodes","includeEmptySubtrees","alwaysExpandThroughLevel","expandThroughLevel","Math","max","iterateSubtreeNodes","iterateLeaves","iterateSubtreeLeaves","dissolveSingleChildTrees","newRoot","toString","subtreeToString","subtree","opts","child","children","collapsible","size","subtreeCounts","tests","nodesWithTODO","counts","countsToString","tree","name","indent","s","JSON","stringify","description","undefined","loadTreeForQuery","loader","queryToLoad","subqueriesToExpand","suite","specs","listing","subqueriesToExpandEntries","Array","from","entries","seenSubqueriesToExpand","length","fill","isCollapsible","subquery","every","i","toExpand","ordering","Equal","StrictSubset","foundCase","subtreeL0","makeTreeForSuite","entry","file","setSubtreeDescriptionAndCountTODOs","readme","queryL1","orderingL1","Unordered","readmeSubtree","addSubtreeForDirPath","spec","importSpecFile","subtreeL1","addSubtreeForFilePath","groupHasTests","t","g","iterate","queryL2","testPath","orderingL2","subtreeL2","addSubtreeForTestPath","testCreationStack","c","queryL3","id","test","params","orderingL3","StrictSuperset","addLeafForCase","sq","subquerySeen","trim","indexOf","readableRelativeName","Map","subqueryFile","part","push","getOrInsertSubtree","filePathParts","subqueryTest","checkCollapsible","subqueryParams","k","v","Object","testPathParts","insertLeaf","key","parent","createSubtree","get","set","leaf","readableNameForCase","run","rec","expectations","isUnimplemented","has","shouldDissolveThisTree","newChild","paramsKeys","keys","lastKey"],"sources":["../../../src/common/internal/tree.ts"],"sourcesContent":["import { RunCase, RunFn } from '../internal/test_group.js';\nimport { assert } from '../util/util.js';\n\nimport { TestFileLoader } from './file_loader.js';\nimport { TestParamsRW } from './params_utils.js';\nimport { compareQueries, Ordering } from './query/compare.js';\nimport {\n TestQuery,\n TestQueryMultiCase,\n TestQuerySingleCase,\n TestQueryMultiFile,\n TestQueryMultiTest,\n} from './query/query.js';\nimport { kBigSeparator, kWildcard, kPathSeparator, kParamSeparator } from './query/separators.js';\nimport { stringifySingleParam } from './query/stringify_params.js';\nimport { StacklessError } from './util.js';\n\n// `loadTreeForQuery()` loads a TestTree for a given queryToLoad.\n// The resulting tree is a linked-list all the way from `suite:*` to queryToLoad,\n// and under queryToLoad is a tree containing every case matched by queryToLoad.\n//\n// `subqueriesToExpand` influences the `collapsible` flag on nodes in the resulting tree.\n// A node is considered \"collapsible\" if none of the subqueriesToExpand is a StrictSubset\n// of that node.\n//\n// In WebKit/Blink-style web_tests, an expectation file marks individual cts.https.html \"variants\n// as \"Failure\", \"Crash\", etc. By passing in the list of expectations as the subqueriesToExpand,\n// we can programmatically subdivide the cts.https.html \"variants\" list to be able to implement\n// arbitrarily-fine suppressions (instead of having to suppress entire test files, which would\n// lose a lot of coverage).\n//\n// `iterateCollapsedNodes()` produces the list of queries for the variants list.\n//\n// Though somewhat complicated, this system has important benefits:\n// - Avoids having to suppress entire test files, which would cause large test coverage loss.\n// - Minimizes the number of page loads needed for fine-grained suppressions.\n// (In the naive case, we could do one page load per test case - but the test suite would\n// take impossibly long to run.)\n// - Enables developers to put any number of tests in one file as appropriate, without worrying\n// about expectation granularity.\n\ninterface TestTreeNodeBase<T extends TestQuery> {\n readonly query: T;\n /**\n * Readable \"relative\" name for display in standalone runner.\n * Not always the exact relative name, because sometimes there isn't\n * one (e.g. s:f:* relative to s:f,*), but something that is readable.\n */\n readonly readableRelativeName: string;\n subtreeCounts?: { tests: number; nodesWithTODO: number };\n}\n\nexport interface TestSubtree<T extends TestQuery = TestQuery> extends TestTreeNodeBase<T> {\n readonly children: Map<string, TestTreeNode>;\n readonly collapsible: boolean;\n description?: string;\n readonly testCreationStack?: Error;\n}\n\nexport interface TestTreeLeaf extends TestTreeNodeBase<TestQuerySingleCase> {\n readonly run: RunFn;\n readonly isUnimplemented?: boolean;\n subtreeCounts?: undefined;\n}\n\nexport type TestTreeNode = TestSubtree | TestTreeLeaf;\n\n/**\n * When iterating through \"collapsed\" tree nodes, indicates how many \"query levels\" to traverse\n * through before starting to collapse nodes.\n *\n * Corresponds with TestQueryLevel, but excludes 4 (SingleCase):\n * - 1 = MultiFile. Expands so every file is in the collapsed tree.\n * - 2 = MultiTest. Expands so every test is in the collapsed tree.\n * - 3 = MultiCase. Expands so every case is in the collapsed tree (i.e. collapsing disabled).\n */\nexport type ExpandThroughLevel = 1 | 2 | 3;\n\nexport class TestTree {\n /**\n * The `queryToLoad` that this test tree was created for.\n * Test trees are always rooted at `suite:*`, but they only contain nodes that fit\n * within `forQuery`.\n *\n * This is used for `iterateCollapsedNodes` which only starts collapsing at the next\n * `TestQueryLevel` after `forQuery`.\n */\n readonly forQuery: TestQuery;\n readonly root: TestSubtree;\n\n constructor(forQuery: TestQuery, root: TestSubtree) {\n this.forQuery = forQuery;\n TestTree.propagateCounts(root);\n this.root = root;\n assert(\n root.query.level === 1 && root.query.depthInLevel === 0,\n 'TestTree root must be the root (suite:*)'\n );\n }\n\n /**\n * Iterate through the leaves of a version of the tree which has been pruned to exclude\n * subtrees which:\n * - are at a deeper `TestQueryLevel` than `this.forQuery`, and\n * - were not a `Ordering.StrictSubset` of any of the `subqueriesToExpand` during tree creation.\n */\n iterateCollapsedNodes({\n includeIntermediateNodes = false,\n includeEmptySubtrees = false,\n alwaysExpandThroughLevel,\n }: {\n /** Whether to include intermediate tree nodes or only collapsed-leaves. */\n includeIntermediateNodes?: boolean;\n /** Whether to include collapsed-leaves with no children. */\n includeEmptySubtrees?: boolean;\n /** Never collapse nodes up through this level. */\n alwaysExpandThroughLevel: ExpandThroughLevel;\n }): IterableIterator<Readonly<TestTreeNode>> {\n const expandThroughLevel = Math.max(this.forQuery.level, alwaysExpandThroughLevel);\n return TestTree.iterateSubtreeNodes(this.root, {\n includeIntermediateNodes,\n includeEmptySubtrees,\n expandThroughLevel,\n });\n }\n\n iterateLeaves(): IterableIterator<Readonly<TestTreeLeaf>> {\n return TestTree.iterateSubtreeLeaves(this.root);\n }\n\n /**\n * Dissolve nodes which have only one child, e.g.:\n * a,* { a,b,* { a,b:* { ... } } }\n * collapses down into:\n * a,* { a,b:* { ... } }\n * which is less needlessly verbose when displaying the tree in the standalone runner.\n */\n dissolveSingleChildTrees(): void {\n const newRoot = dissolveSingleChildTrees(this.root);\n assert(newRoot === this.root);\n }\n\n toString(): string {\n return TestTree.subtreeToString('(root)', this.root, '');\n }\n\n static *iterateSubtreeNodes(\n subtree: TestSubtree,\n opts: {\n includeIntermediateNodes: boolean;\n includeEmptySubtrees: boolean;\n expandThroughLevel: number;\n }\n ): IterableIterator<TestTreeNode> {\n if (opts.includeIntermediateNodes) {\n yield subtree;\n }\n\n for (const [, child] of subtree.children) {\n if ('children' in child) {\n // Is a subtree\n const collapsible = child.collapsible && child.query.level > opts.expandThroughLevel;\n if (child.children.size > 0 && !collapsible) {\n yield* TestTree.iterateSubtreeNodes(child, opts);\n } else if (child.children.size > 0 || opts.includeEmptySubtrees) {\n // Don't yield empty subtrees (e.g. files with no tests) unless includeEmptySubtrees\n yield child;\n }\n } else {\n // Is a leaf\n yield child;\n }\n }\n }\n\n static *iterateSubtreeLeaves(subtree: TestSubtree): IterableIterator<TestTreeLeaf> {\n for (const [, child] of subtree.children) {\n if ('children' in child) {\n yield* TestTree.iterateSubtreeLeaves(child);\n } else {\n yield child;\n }\n }\n }\n\n /** Propagate the subtreeTODOs/subtreeTests state upward from leaves to parent nodes. */\n static propagateCounts(subtree: TestSubtree): { tests: number; nodesWithTODO: number } {\n subtree.subtreeCounts ??= { tests: 0, nodesWithTODO: 0 };\n for (const [, child] of subtree.children) {\n if ('children' in child) {\n const counts = TestTree.propagateCounts(child);\n subtree.subtreeCounts.tests += counts.tests;\n subtree.subtreeCounts.nodesWithTODO += counts.nodesWithTODO;\n }\n }\n return subtree.subtreeCounts;\n }\n\n /** Displays counts in the format `(Nodes with TODOs) / (Total test count)`. */\n static countsToString(tree: TestTreeNode): string {\n if (tree.subtreeCounts) {\n return `${tree.subtreeCounts.nodesWithTODO} / ${tree.subtreeCounts.tests}`;\n } else {\n return '';\n }\n }\n\n static subtreeToString(name: string, tree: TestTreeNode, indent: string): string {\n const collapsible = 'run' in tree ? '>' : tree.collapsible ? '+' : '-';\n let s =\n indent +\n `${collapsible} ${TestTree.countsToString(tree)} ${JSON.stringify(name)} => ${tree.query}`;\n if ('children' in tree) {\n if (tree.description !== undefined) {\n s += `\\n${indent} | ${JSON.stringify(tree.description)}`;\n }\n\n for (const [name, child] of tree.children) {\n s += '\\n' + TestTree.subtreeToString(name, child, indent + ' ');\n }\n }\n return s;\n }\n}\n\n// MAINTENANCE_TODO: Consider having subqueriesToExpand actually impact the depth-order of params\n// in the tree.\nexport async function loadTreeForQuery(\n loader: TestFileLoader,\n queryToLoad: TestQuery,\n subqueriesToExpand: TestQuery[]\n): Promise<TestTree> {\n const suite = queryToLoad.suite;\n const specs = await loader.listing(suite);\n\n const subqueriesToExpandEntries = Array.from(subqueriesToExpand.entries());\n const seenSubqueriesToExpand: boolean[] = new Array(subqueriesToExpand.length);\n seenSubqueriesToExpand.fill(false);\n\n const isCollapsible = (subquery: TestQuery) =>\n subqueriesToExpandEntries.every(([i, toExpand]) => {\n const ordering = compareQueries(toExpand, subquery);\n\n // If toExpand == subquery, no expansion is needed (but it's still \"seen\").\n if (ordering === Ordering.Equal) seenSubqueriesToExpand[i] = true;\n return ordering !== Ordering.StrictSubset;\n });\n\n // L0 = suite-level, e.g. suite:*\n // L1 = file-level, e.g. suite:a,b:*\n // L2 = test-level, e.g. suite:a,b:c,d:*\n // L3 = case-level, e.g. suite:a,b:c,d:\n let foundCase = false;\n // L0 is suite:*\n const subtreeL0 = makeTreeForSuite(suite, isCollapsible);\n for (const entry of specs) {\n if (entry.file.length === 0 && 'readme' in entry) {\n // Suite-level readme.\n setSubtreeDescriptionAndCountTODOs(subtreeL0, entry.readme);\n continue;\n }\n\n {\n const queryL1 = new TestQueryMultiFile(suite, entry.file);\n const orderingL1 = compareQueries(queryL1, queryToLoad);\n if (orderingL1 === Ordering.Unordered) {\n // File path is not matched by this query.\n continue;\n }\n }\n\n if ('readme' in entry) {\n // Entry is a README that is an ancestor or descendant of the query.\n // (It's included for display in the standalone runner.)\n\n // readmeSubtree is suite:a,b,*\n // (This is always going to dedup with a file path, if there are any test spec files under\n // the directory that has the README).\n const readmeSubtree: TestSubtree<TestQueryMultiFile> = addSubtreeForDirPath(\n subtreeL0,\n entry.file,\n isCollapsible\n );\n setSubtreeDescriptionAndCountTODOs(readmeSubtree, entry.readme);\n continue;\n }\n // Entry is a spec file.\n\n const spec = await loader.importSpecFile(queryToLoad.suite, entry.file);\n // subtreeL1 is suite:a,b:*\n const subtreeL1: TestSubtree<TestQueryMultiTest> = addSubtreeForFilePath(\n subtreeL0,\n entry.file,\n isCollapsible\n );\n setSubtreeDescriptionAndCountTODOs(subtreeL1, spec.description);\n\n let groupHasTests = false;\n for (const t of spec.g.iterate()) {\n groupHasTests = true;\n {\n const queryL2 = new TestQueryMultiCase(suite, entry.file, t.testPath, {});\n const orderingL2 = compareQueries(queryL2, queryToLoad);\n if (orderingL2 === Ordering.Unordered) {\n // Test path is not matched by this query.\n continue;\n }\n }\n\n // subtreeL2 is suite:a,b:c,d:*\n const subtreeL2: TestSubtree<TestQueryMultiCase> = addSubtreeForTestPath(\n subtreeL1,\n t.testPath,\n t.testCreationStack,\n isCollapsible\n );\n // This is 1 test. Set tests=1 then count TODOs.\n subtreeL2.subtreeCounts ??= { tests: 1, nodesWithTODO: 0 };\n if (t.description) setSubtreeDescriptionAndCountTODOs(subtreeL2, t.description);\n\n // MAINTENANCE_TODO: If tree generation gets too slow, avoid actually iterating the cases in a\n // file if there's no need to (based on the subqueriesToExpand).\n for (const c of t.iterate()) {\n {\n const queryL3 = new TestQuerySingleCase(suite, entry.file, c.id.test, c.id.params);\n const orderingL3 = compareQueries(queryL3, queryToLoad);\n if (orderingL3 === Ordering.Unordered || orderingL3 === Ordering.StrictSuperset) {\n // Case is not matched by this query.\n continue;\n }\n }\n\n // Leaf for case is suite:a,b:c,d:x=1;y=2\n addLeafForCase(subtreeL2, c, isCollapsible);\n\n foundCase = true;\n }\n }\n if (!groupHasTests && !subtreeL1.subtreeCounts) {\n throw new StacklessError(\n `${subtreeL1.query} has no tests - it must have \"TODO\" in its description`\n );\n }\n }\n\n for (const [i, sq] of subqueriesToExpandEntries) {\n const subquerySeen = seenSubqueriesToExpand[i];\n if (!subquerySeen) {\n throw new StacklessError(\n `subqueriesToExpand entry did not match anything \\\n(could be wrong, or could be redundant with a previous subquery):\\n ${sq.toString()}`\n );\n }\n }\n assert(foundCase, `Query \\`${queryToLoad.toString()}\\` does not match any cases`);\n\n return new TestTree(queryToLoad, subtreeL0);\n}\n\nfunction setSubtreeDescriptionAndCountTODOs(\n subtree: TestSubtree<TestQueryMultiFile>,\n description: string\n) {\n assert(subtree.description === undefined);\n subtree.description = description.trim();\n subtree.subtreeCounts ??= { tests: 0, nodesWithTODO: 0 };\n if (subtree.description.indexOf('TODO') !== -1) {\n subtree.subtreeCounts.nodesWithTODO++;\n }\n}\n\nfunction makeTreeForSuite(\n suite: string,\n isCollapsible: (sq: TestQuery) => boolean\n): TestSubtree<TestQueryMultiFile> {\n const query = new TestQueryMultiFile(suite, []);\n return {\n readableRelativeName: suite + kBigSeparator,\n query,\n children: new Map(),\n collapsible: isCollapsible(query),\n };\n}\n\nfunction addSubtreeForDirPath(\n tree: TestSubtree<TestQueryMultiFile>,\n file: string[],\n isCollapsible: (sq: TestQuery) => boolean\n): TestSubtree<TestQueryMultiFile> {\n const subqueryFile: string[] = [];\n // To start, tree is suite:*\n // This loop goes from that -> suite:a,* -> suite:a,b,*\n for (const part of file) {\n subqueryFile.push(part);\n tree = getOrInsertSubtree(part, tree, () => {\n const query = new TestQueryMultiFile(tree.query.suite, subqueryFile);\n return {\n readableRelativeName: part + kPathSeparator + kWildcard,\n query,\n collapsible: isCollapsible(query),\n };\n });\n }\n return tree;\n}\n\nfunction addSubtreeForFilePath(\n tree: TestSubtree<TestQueryMultiFile>,\n file: string[],\n isCollapsible: (sq: TestQuery) => boolean\n): TestSubtree<TestQueryMultiTest> {\n // To start, tree is suite:*\n // This goes from that -> suite:a,* -> suite:a,b,*\n tree = addSubtreeForDirPath(tree, file, isCollapsible);\n // This goes from that -> suite:a,b:*\n const subtree = getOrInsertSubtree('', tree, () => {\n const query = new TestQueryMultiTest(tree.query.suite, tree.query.filePathParts, []);\n assert(file.length > 0, 'file path is empty');\n return {\n readableRelativeName: file[file.length - 1] + kBigSeparator + kWildcard,\n query,\n collapsible: isCollapsible(query),\n };\n });\n return subtree;\n}\n\nfunction addSubtreeForTestPath(\n tree: TestSubtree<TestQueryMultiTest>,\n test: readonly string[],\n testCreationStack: Error,\n isCollapsible: (sq: TestQuery) => boolean\n): TestSubtree<TestQueryMultiCase> {\n const subqueryTest: string[] = [];\n // To start, tree is suite:a,b:*\n // This loop goes from that -> suite:a,b:c,* -> suite:a,b:c,d,*\n for (const part of test) {\n subqueryTest.push(part);\n tree = getOrInsertSubtree(part, tree, () => {\n const query = new TestQueryMultiTest(\n tree.query.suite,\n tree.query.filePathParts,\n subqueryTest\n );\n return {\n readableRelativeName: part + kPathSeparator + kWildcard,\n query,\n collapsible: isCollapsible(query),\n };\n });\n }\n // This goes from that -> suite:a,b:c,d:*\n return getOrInsertSubtree('', tree, () => {\n const query = new TestQueryMultiCase(\n tree.query.suite,\n tree.query.filePathParts,\n subqueryTest,\n {}\n );\n assert(subqueryTest.length > 0, 'subqueryTest is empty');\n return {\n readableRelativeName: subqueryTest[subqueryTest.length - 1] + kBigSeparator + kWildcard,\n kWildcard,\n query,\n testCreationStack,\n collapsible: isCollapsible(query),\n };\n });\n}\n\nfunction addLeafForCase(\n tree: TestSubtree<TestQueryMultiTest>,\n t: RunCase,\n checkCollapsible: (sq: TestQuery) => boolean\n): void {\n const query = tree.query;\n let name: string = '';\n const subqueryParams: TestParamsRW = {};\n\n // To start, tree is suite:a,b:c,d:*\n // This loop goes from that -> suite:a,b:c,d:x=1;* -> suite:a,b:c,d:x=1;y=2;*\n for (const [k, v] of Object.entries(t.id.params)) {\n name = stringifySingleParam(k, v);\n subqueryParams[k] = v;\n\n tree = getOrInsertSubtree(name, tree, () => {\n const subquery = new TestQueryMultiCase(\n query.suite,\n query.filePathParts,\n query.testPathParts,\n subqueryParams\n );\n return {\n readableRelativeName: name + kParamSeparator + kWildcard,\n query: subquery,\n collapsible: checkCollapsible(subquery),\n };\n });\n }\n\n // This goes from that -> suite:a,b:c,d:x=1;y=2\n const subquery = new TestQuerySingleCase(\n query.suite,\n query.filePathParts,\n query.testPathParts,\n subqueryParams\n );\n checkCollapsible(subquery); // mark seenSubqueriesToExpand\n insertLeaf(tree, subquery, t);\n}\n\nfunction getOrInsertSubtree<T extends TestQuery>(\n key: string,\n parent: TestSubtree,\n createSubtree: () => Omit<TestSubtree<T>, 'children'>\n): TestSubtree<T> {\n let v: TestSubtree<T>;\n const child = parent.children.get(key);\n if (child !== undefined) {\n assert('children' in child); // Make sure cached subtree is not actually a leaf\n v = child as TestSubtree<T>;\n } else {\n v = { ...createSubtree(), children: new Map() };\n parent.children.set(key, v);\n }\n return v;\n}\n\nfunction insertLeaf(parent: TestSubtree, query: TestQuerySingleCase, t: RunCase) {\n const leaf: TestTreeLeaf = {\n readableRelativeName: readableNameForCase(query),\n query,\n run: (rec, expectations) => t.run(rec, query, expectations || []),\n isUnimplemented: t.isUnimplemented,\n };\n\n // This is a leaf (e.g. s:f:t:x=1;* -> s:f:t:x=1). The key is always ''.\n const key = '';\n assert(!parent.children.has(key), `Duplicate testcase: ${query}`);\n parent.children.set(key, leaf);\n}\n\nfunction dissolveSingleChildTrees(tree: TestTreeNode): TestTreeNode {\n if ('children' in tree) {\n const shouldDissolveThisTree =\n tree.children.size === 1 && tree.query.depthInLevel !== 0 && tree.description === undefined;\n if (shouldDissolveThisTree) {\n // Loops exactly once\n for (const [, child] of tree.children) {\n // Recurse on child\n return dissolveSingleChildTrees(child);\n }\n }\n\n for (const [k, child] of tree.children) {\n // Recurse on each child\n const newChild = dissolveSingleChildTrees(child);\n if (newChild !== child) {\n tree.children.set(k, newChild);\n }\n }\n }\n return tree;\n}\n\n/** Generate a readable relative name for a case (used in standalone). */\nfunction readableNameForCase(query: TestQuerySingleCase): string {\n const paramsKeys = Object.keys(query.params);\n if (paramsKeys.length === 0) {\n return query.testPathParts[query.testPathParts.length - 1] + kBigSeparator;\n } else {\n const lastKey = paramsKeys[paramsKeys.length - 1];\n return stringifySingleParam(lastKey, query.params[lastKey]);\n }\n}\n"],"mappings":"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"}
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/util.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/util.js new file mode 100644 index 0000000000..18935e074b --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/util.js @@ -0,0 +1,11 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ /** + * Error without a stack, which can be used to fatally exit from `tool/` scripts with a + * user-friendly message (and no confusing stack). + */export class StacklessError extends Error {constructor(message) { + super(message); + this.stack = undefined; + } +} +//# sourceMappingURL=util.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/util.js.map b/testing/web-platform/mozilla/tests/webgpu/common/internal/util.js.map new file mode 100644 index 0000000000..e29de27b3d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/util.js.map @@ -0,0 +1 @@ +{"version":3,"file":"util.js","names":["StacklessError","Error","constructor","message","stack","undefined"],"sources":["../../../src/common/internal/util.ts"],"sourcesContent":["/**\n * Error without a stack, which can be used to fatally exit from `tool/` scripts with a\n * user-friendly message (and no confusing stack).\n */\nexport class StacklessError extends Error {\n constructor(message: string) {\n super(message);\n this.stack = undefined;\n }\n}\n"],"mappings":";AAAA;AAAA,G,CAAA;AACA;AACA;AACA,GACA,OAAO,MAAMA,cAAc,SAASC,KAAK,CAAC,CACxCC,WAAW,CAACC,OAAe,EAAE;IAC3B,KAAK,CAACA,OAAO,CAAC;IACd,IAAI,CAACC,KAAK,GAAGC,SAAS;EACxB;AACF"}
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/internal/version.js b/testing/web-platform/mozilla/tests/webgpu/common/internal/version.js new file mode 100644 index 0000000000..3353fd94d7 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/internal/version.js @@ -0,0 +1,3 @@ +// AUTO-GENERATED - DO NOT EDIT. See tools/gen_version. + +export const version = 'b3ce8f38983dc445e66c35d83f1110ce89fba9ba'; 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 new file mode 100644 index 0000000000..946c0bdc11 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/options.js @@ -0,0 +1,18 @@ +/** + * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts + **/ let windowURL = undefined; +function getWindowURL() { + if (windowURL === undefined) { + windowURL = new URL(window.location.toString()); + } + return windowURL; +} + +export function optionEnabled(opt, searchParams = getWindowURL().searchParams) { + const val = searchParams.get(opt); + return val !== null && val !== '0'; +} + +export function optionString(opt, searchParams = getWindowURL().searchParams) { + return searchParams.get(opt) || ''; +} diff --git a/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/sys.js b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/sys.js new file mode 100644 index 0000000000..db7af47dab --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/sys.js @@ -0,0 +1,37 @@ +/** + * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts + **/ +function node() { + const { existsSync } = require('fs'); + + return { + type: 'node', + existsSync, + args: process.argv.slice(2), + cwd: () => process.cwd(), + exit: code => process.exit(code), + }; +} + +function deno() { + function existsSync(path) { + try { + Deno.readFileSync(path); + return true; + } catch (err) { + return false; + } + } + + return { + type: 'deno', + existsSync, + args: Deno.args, + cwd: Deno.cwd, + exit: Deno.exit, + }; +} + +const sys = typeof globalThis.process !== 'undefined' ? node() : deno(); + +export default sys; 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 new file mode 100644 index 0000000000..73eaff46b2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker-worker.js @@ -0,0 +1,32 @@ +/** + * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts + **/ import { setBaseResourcePath } from '../../framework/resources.js'; +import { DefaultTestFileLoader } from '../../internal/file_loader.js'; +import { Logger } from '../../internal/logging/logger.js'; +import { parseQuery } from '../../internal/query/parseQuery.js'; + +import { assert } from '../../util/util.js'; + +// Should be DedicatedWorkerGlobalScope, but importing lib "webworker" conflicts with lib "dom". + +const loader = new DefaultTestFileLoader(); + +setBaseResourcePath('../../../resources'); + +self.onmessage = async ev => { + const query = ev.data.query; + const expectations = ev.data.expectations; + const debug = ev.data.debug; + + Logger.globalDebugMode = debug; + const log = new Logger(); + + const testcases = Array.from(await loader.loadCases(parseQuery(query))); + assert(testcases.length === 1, 'worker query resulted in != 1 cases'); + + const testcase = testcases[0]; + const [rec, result] = log.record(testcase.query.toString()); + await testcase.run(rec, expectations); + + self.postMessage({ query, result }); +}; 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 new file mode 100644 index 0000000000..f3f9dc62e1 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/helper/test_worker.js @@ -0,0 +1,37 @@ +/** + * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts + **/ import { LogMessageWithStack } from '../../internal/logging/log_message.js'; + +export class TestWorker { + resolvers = new Map(); + + constructor(debug) { + this.debug = debug; + + 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); + + // 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, query, expectations = []) { + this.worker.postMessage({ query, expectations, debug: this.debug }); + const workerResult = await new Promise(resolve => { + this.resolvers.set(query, resolve); + }); + rec.injectResult(workerResult); + } +} diff --git a/testing/web-platform/mozilla/tests/webgpu/common/runtime/wpt.js b/testing/web-platform/mozilla/tests/webgpu/common/runtime/wpt.js new file mode 100644 index 0000000000..90294223c0 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/runtime/wpt.js @@ -0,0 +1,73 @@ +/** + * AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts + **/ // Implements the wpt-embedded test runner (see also: wpt/cts.https.html). +import { globalTestConfig } from '../framework/test_config.js'; +import { DefaultTestFileLoader } from '../internal/file_loader.js'; +import { prettyPrintLog } from '../internal/logging/log_message.js'; +import { Logger } from '../internal/logging/logger.js'; +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'; + +// testharness.js API (https://web-platform-tests.org/writing-tests/testharness-api.html) + +setup({ + // It's convenient for us to asynchronously add tests to the page. Prevent done() from being + // called implicitly when the page is finished loading. + explicit_done: true, +}); + +void (async () => { + const workerEnabled = optionEnabled('worker'); + const worker = workerEnabled ? new TestWorker(false) : undefined; + + globalTestConfig.unrollConstEvalLoops = optionEnabled('unroll_const_eval_loops'); + + const failOnWarnings = + typeof shouldWebGPUCTSFailOnWarnings !== 'undefined' && (await shouldWebGPUCTSFailOnWarnings); + + const loader = new DefaultTestFileLoader(); + const qs = new URLSearchParams(window.location.search).getAll('q'); + assert(qs.length === 1, 'currently, there must be exactly one ?q='); + const filterQuery = parseQuery(qs[0]); + const testcases = await loader.loadCases(filterQuery); + + const expectations = + typeof loadWebGPUExpectations !== 'undefined' + ? parseExpectationsForTestQuery( + await loadWebGPUExpectations, + filterQuery, + new URL(window.location.href) + ) + : []; + + const log = new Logger(); + + for (const testcase of testcases) { + const name = testcase.query.toString(); + // For brevity, display the case name "relative" to the ?q= path. + const shortName = relativeQueryString(filterQuery, testcase.query) || '(case)'; + + const wpt_fn = async () => { + const [rec, res] = log.record(name); + if (worker) { + await worker.run(rec, name, expectations); + } else { + await testcase.run(rec, expectations); + } + + // Unfortunately, it seems not possible to surface any logs for warn/skip. + if (res.status === 'fail' || (res.status === 'warn' && failOnWarnings)) { + const logs = (res.logs ?? []).map(prettyPrintLog); + assert_unreached('\n' + logs.join('\n') + '\n'); + } + }; + + promise_test(wpt_fn, shortName); + } + + done(); +})(); diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/collect_garbage.js b/testing/web-platform/mozilla/tests/webgpu/common/util/collect_garbage.js new file mode 100644 index 0000000000..0c078a11b9 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/util/collect_garbage.js @@ -0,0 +1,59 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { resolveOnTimeout } from './util.js'; + + +/** + * Attempts to trigger JavaScript garbage collection, either using explicit methods if exposed + * (may be available in testing environments with special browser runtime flags set), or using + * some weird tricks to incur GC pressure. Adopted from the WebGL CTS. + */ +export async function attemptGarbageCollection() { + + const w = globalThis; + if (w.GCController) { + w.GCController.collect(); + return; + } + + if (w.opera && w.opera.collect) { + w.opera.collect(); + return; + } + + try { + w.QueryInterface(Components.interfaces.nsIInterfaceRequestor). + getInterface(Components.interfaces.nsIDOMWindowUtils). + garbageCollect(); + return; + } catch (e) { + + // ignore any failure + } + if (w.gc) { + w.gc(); + return; + } + + if (w.CollectGarbage) { + w.CollectGarbage(); + return; + } + + let i; + function gcRec(n) { + if (n < 1) return; + + let temp = { i: 'ab' + i + i / 100000 }; + + temp = temp + 'foo'; + temp; // dummy use of unused variable + gcRec(n - 1); + } + for (i = 0; i < 1000; i++) { + gcRec(10); + } + + return resolveOnTimeout(35); // Let the event loop run a few frames in case it helps. +} +//# sourceMappingURL=collect_garbage.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/collect_garbage.js.map b/testing/web-platform/mozilla/tests/webgpu/common/util/collect_garbage.js.map new file mode 100644 index 0000000000..59020707d6 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/util/collect_garbage.js.map @@ -0,0 +1 @@ +{"version":3,"file":"collect_garbage.js","names":["resolveOnTimeout","attemptGarbageCollection","w","globalThis","GCController","collect","opera","QueryInterface","Components","interfaces","nsIInterfaceRequestor","getInterface","nsIDOMWindowUtils","garbageCollect","e","gc","CollectGarbage","i","gcRec","n","temp"],"sources":["../../../src/common/util/collect_garbage.ts"],"sourcesContent":["import { resolveOnTimeout } from './util.js';\n\n/* eslint-disable-next-line @typescript-eslint/no-explicit-any */\ndeclare const Components: any;\n\n/**\n * Attempts to trigger JavaScript garbage collection, either using explicit methods if exposed\n * (may be available in testing environments with special browser runtime flags set), or using\n * some weird tricks to incur GC pressure. Adopted from the WebGL CTS.\n */\nexport async function attemptGarbageCollection(): Promise<void> {\n /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n const w: any = globalThis;\n if (w.GCController) {\n w.GCController.collect();\n return;\n }\n\n if (w.opera && w.opera.collect) {\n w.opera.collect();\n return;\n }\n\n try {\n w.QueryInterface(Components.interfaces.nsIInterfaceRequestor)\n .getInterface(Components.interfaces.nsIDOMWindowUtils)\n .garbageCollect();\n return;\n } catch (e) {\n // ignore any failure\n }\n\n if (w.gc) {\n w.gc();\n return;\n }\n\n if (w.CollectGarbage) {\n w.CollectGarbage();\n return;\n }\n\n let i: number;\n function gcRec(n: number): void {\n if (n < 1) return;\n /* eslint-disable @typescript-eslint/restrict-plus-operands */\n let temp: object | string = { i: 'ab' + i + i / 100000 };\n /* eslint-disable @typescript-eslint/restrict-plus-operands */\n temp = temp + 'foo';\n temp; // dummy use of unused variable\n gcRec(n - 1);\n }\n for (i = 0; i < 1000; i++) {\n gcRec(10);\n }\n\n return resolveOnTimeout(35); // Let the event loop run a few frames in case it helps.\n}\n"],"mappings":";AAAA;AAAA,GAAA,SAASA,gBAAgB,QAAQ,WAAW;;;AAK5C;AACA;AACA;AACA;AACA;AACA,OAAO,eAAeC,wBAAwB,GAAkB;;EAE9D,MAAMC,CAAM,GAAGC,UAAU;EACzB,IAAID,CAAC,CAACE,YAAY,EAAE;IAClBF,CAAC,CAACE,YAAY,CAACC,OAAO,EAAE;IACxB;EACF;;EAEA,IAAIH,CAAC,CAACI,KAAK,IAAIJ,CAAC,CAACI,KAAK,CAACD,OAAO,EAAE;IAC9BH,CAAC,CAACI,KAAK,CAACD,OAAO,EAAE;IACjB;EACF;;EAEA,IAAI;IACFH,CAAC,CAACK,cAAc,CAACC,UAAU,CAACC,UAAU,CAACC,qBAAqB,CAAC;IAC1DC,YAAY,CAACH,UAAU,CAACC,UAAU,CAACG,iBAAiB,CAAC;IACrDC,cAAc,EAAE;IACnB;EACF,CAAC,CAAC,OAAOC,CAAC,EAAE;;IACV;EAAA;EAGF,IAAIZ,CAAC,CAACa,EAAE,EAAE;IACRb,CAAC,CAACa,EAAE,EAAE;IACN;EACF;;EAEA,IAAIb,CAAC,CAACc,cAAc,EAAE;IACpBd,CAAC,CAACc,cAAc,EAAE;IAClB;EACF;;EAEA,IAAIC,CAAS;EACb,SAASC,KAAK,CAACC,CAAS,EAAQ;IAC9B,IAAIA,CAAC,GAAG,CAAC,EAAE;;IAEX,IAAIC,IAAqB,GAAG,EAAEH,CAAC,EAAE,IAAI,GAAGA,CAAC,GAAGA,CAAC,GAAG,MAAM,CAAC,CAAC;;IAExDG,IAAI,GAAGA,IAAI,GAAG,KAAK;IACnBA,IAAI,CAAC,CAAC;IACNF,KAAK,CAACC,CAAC,GAAG,CAAC,CAAC;EACd;EACA,KAAKF,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAG,IAAI,EAAEA,CAAC,EAAE,EAAE;IACzBC,KAAK,CAAC,EAAE,CAAC;EACX;;EAEA,OAAOlB,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC;AAC/B"}
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/colors.js b/testing/web-platform/mozilla/tests/webgpu/common/util/colors.js new file mode 100644 index 0000000000..7f8f11eacb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/util/colors.js @@ -0,0 +1,128 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/** + * The interface used for formatting strings with color metadata. + * + * Currently Colors will use the 'ansi-colors' module if it can be loaded. + * If it cannot be loaded, then the Colors implementation is a straight pass-through. + * + * Colors may also be a no-op if the current environment does not support colors. + */ +export let Colors; + +try { + + Colors = require('ansi-colors'); +} catch { + const passthrough = (s) => s; + passthrough.enabled = false; + passthrough.reset = passthrough; + passthrough.bold = passthrough; + passthrough.dim = passthrough; + passthrough.italic = passthrough; + passthrough.underline = passthrough; + passthrough.inverse = passthrough; + passthrough.hidden = passthrough; + passthrough.strikethrough = passthrough; + passthrough.black = passthrough; + passthrough.red = passthrough; + passthrough.green = passthrough; + passthrough.yellow = passthrough; + passthrough.blue = passthrough; + passthrough.magenta = passthrough; + passthrough.cyan = passthrough; + passthrough.white = passthrough; + passthrough.gray = passthrough; + passthrough.grey = passthrough; + passthrough.blackBright = passthrough; + passthrough.redBright = passthrough; + passthrough.greenBright = passthrough; + passthrough.yellowBright = passthrough; + passthrough.blueBright = passthrough; + passthrough.magentaBright = passthrough; + passthrough.cyanBright = passthrough; + passthrough.whiteBright = passthrough; + passthrough.bgBlack = passthrough; + passthrough.bgRed = passthrough; + passthrough.bgGreen = passthrough; + passthrough.bgYellow = passthrough; + passthrough.bgBlue = passthrough; + passthrough.bgMagenta = passthrough; + passthrough.bgCyan = passthrough; + passthrough.bgWhite = passthrough; + passthrough.bgBlackBright = passthrough; + passthrough.bgRedBright = passthrough; + passthrough.bgGreenBright = passthrough; + passthrough.bgYellowBright = passthrough; + passthrough.bgBlueBright = passthrough; + passthrough.bgMagentaBright = passthrough; + passthrough.bgCyanBright = passthrough; + passthrough.bgWhiteBright = passthrough; + Colors = passthrough; +} +//# sourceMappingURL=colors.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/colors.js.map b/testing/web-platform/mozilla/tests/webgpu/common/util/colors.js.map new file mode 100644 index 0000000000..581265e20f --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/util/colors.js.map @@ -0,0 +1 @@ +{"version":3,"file":"colors.js","names":["Colors","require","passthrough","s","enabled","reset","bold","dim","italic","underline","inverse","hidden","strikethrough","black","red","green","yellow","blue","magenta","cyan","white","gray","grey","blackBright","redBright","greenBright","yellowBright","blueBright","magentaBright","cyanBright","whiteBright","bgBlack","bgRed","bgGreen","bgYellow","bgBlue","bgMagenta","bgCyan","bgWhite","bgBlackBright","bgRedBright","bgGreenBright","bgYellowBright","bgBlueBright","bgMagentaBright","bgCyanBright","bgWhiteBright"],"sources":["../../../src/common/util/colors.ts"],"sourcesContent":["/**\n * The interface used for formatting strings to contain color metadata.\n *\n * Use the interface properties to construct a style, then use the\n * `(s: string): string` function to format the provided string with the given\n * style.\n */\nexport interface Colors {\n // Are colors enabled?\n enabled: boolean;\n\n // Returns the string formatted to contain the specified color or style.\n (s: string): string;\n\n // modifiers\n reset: Colors;\n bold: Colors;\n dim: Colors;\n italic: Colors;\n underline: Colors;\n inverse: Colors;\n hidden: Colors;\n strikethrough: Colors;\n\n // colors\n black: Colors;\n red: Colors;\n green: Colors;\n yellow: Colors;\n blue: Colors;\n magenta: Colors;\n cyan: Colors;\n white: Colors;\n gray: Colors;\n grey: Colors;\n\n // bright colors\n blackBright: Colors;\n redBright: Colors;\n greenBright: Colors;\n yellowBright: Colors;\n blueBright: Colors;\n magentaBright: Colors;\n cyanBright: Colors;\n whiteBright: Colors;\n\n // background colors\n bgBlack: Colors;\n bgRed: Colors;\n bgGreen: Colors;\n bgYellow: Colors;\n bgBlue: Colors;\n bgMagenta: Colors;\n bgCyan: Colors;\n bgWhite: Colors;\n\n // bright background colors\n bgBlackBright: Colors;\n bgRedBright: Colors;\n bgGreenBright: Colors;\n bgYellowBright: Colors;\n bgBlueBright: Colors;\n bgMagentaBright: Colors;\n bgCyanBright: Colors;\n bgWhiteBright: Colors;\n}\n\n/**\n * The interface used for formatting strings with color metadata.\n *\n * Currently Colors will use the 'ansi-colors' module if it can be loaded.\n * If it cannot be loaded, then the Colors implementation is a straight pass-through.\n *\n * Colors may also be a no-op if the current environment does not support colors.\n */\nexport let Colors: Colors;\n\ntry {\n /* eslint-disable-next-line node/no-unpublished-require */\n Colors = require('ansi-colors') as Colors;\n} catch {\n const passthrough = ((s: string) => s) as Colors;\n passthrough.enabled = false;\n passthrough.reset = passthrough;\n passthrough.bold = passthrough;\n passthrough.dim = passthrough;\n passthrough.italic = passthrough;\n passthrough.underline = passthrough;\n passthrough.inverse = passthrough;\n passthrough.hidden = passthrough;\n passthrough.strikethrough = passthrough;\n passthrough.black = passthrough;\n passthrough.red = passthrough;\n passthrough.green = passthrough;\n passthrough.yellow = passthrough;\n passthrough.blue = passthrough;\n passthrough.magenta = passthrough;\n passthrough.cyan = passthrough;\n passthrough.white = passthrough;\n passthrough.gray = passthrough;\n passthrough.grey = passthrough;\n passthrough.blackBright = passthrough;\n passthrough.redBright = passthrough;\n passthrough.greenBright = passthrough;\n passthrough.yellowBright = passthrough;\n passthrough.blueBright = passthrough;\n passthrough.magentaBright = passthrough;\n passthrough.cyanBright = passthrough;\n passthrough.whiteBright = passthrough;\n passthrough.bgBlack = passthrough;\n passthrough.bgRed = passthrough;\n passthrough.bgGreen = passthrough;\n passthrough.bgYellow = passthrough;\n passthrough.bgBlue = passthrough;\n passthrough.bgMagenta = passthrough;\n passthrough.bgCyan = passthrough;\n passthrough.bgWhite = passthrough;\n passthrough.bgBlackBright = passthrough;\n passthrough.bgRedBright = passthrough;\n passthrough.bgGreenBright = passthrough;\n passthrough.bgYellowBright = passthrough;\n passthrough.bgBlueBright = passthrough;\n passthrough.bgMagentaBright = passthrough;\n passthrough.bgCyanBright = passthrough;\n passthrough.bgWhiteBright = passthrough;\n Colors = passthrough;\n}\n"],"mappings":";AAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,IAAIA,MAAc;;AAEzB,IAAI;;EAEFA,MAAM,GAAGC,OAAO,CAAC,aAAa,CAAW;AAC3C,CAAC,CAAC,MAAM;EACN,MAAMC,WAAW,GAAI,CAACC,CAAS,KAAKA,CAAY;EAChDD,WAAW,CAACE,OAAO,GAAG,KAAK;EAC3BF,WAAW,CAACG,KAAK,GAAGH,WAAW;EAC/BA,WAAW,CAACI,IAAI,GAAGJ,WAAW;EAC9BA,WAAW,CAACK,GAAG,GAAGL,WAAW;EAC7BA,WAAW,CAACM,MAAM,GAAGN,WAAW;EAChCA,WAAW,CAACO,SAAS,GAAGP,WAAW;EACnCA,WAAW,CAACQ,OAAO,GAAGR,WAAW;EACjCA,WAAW,CAACS,MAAM,GAAGT,WAAW;EAChCA,WAAW,CAACU,aAAa,GAAGV,WAAW;EACvCA,WAAW,CAACW,KAAK,GAAGX,WAAW;EAC/BA,WAAW,CAACY,GAAG,GAAGZ,WAAW;EAC7BA,WAAW,CAACa,KAAK,GAAGb,WAAW;EAC/BA,WAAW,CAACc,MAAM,GAAGd,WAAW;EAChCA,WAAW,CAACe,IAAI,GAAGf,WAAW;EAC9BA,WAAW,CAACgB,OAAO,GAAGhB,WAAW;EACjCA,WAAW,CAACiB,IAAI,GAAGjB,WAAW;EAC9BA,WAAW,CAACkB,KAAK,GAAGlB,WAAW;EAC/BA,WAAW,CAACmB,IAAI,GAAGnB,WAAW;EAC9BA,WAAW,CAACoB,IAAI,GAAGpB,WAAW;EAC9BA,WAAW,CAACqB,WAAW,GAAGrB,WAAW;EACrCA,WAAW,CAACsB,SAAS,GAAGtB,WAAW;EACnCA,WAAW,CAACuB,WAAW,GAAGvB,WAAW;EACrCA,WAAW,CAACwB,YAAY,GAAGxB,WAAW;EACtCA,WAAW,CAACyB,UAAU,GAAGzB,WAAW;EACpCA,WAAW,CAAC0B,aAAa,GAAG1B,WAAW;EACvCA,WAAW,CAAC2B,UAAU,GAAG3B,WAAW;EACpCA,WAAW,CAAC4B,WAAW,GAAG5B,WAAW;EACrCA,WAAW,CAAC6B,OAAO,GAAG7B,WAAW;EACjCA,WAAW,CAAC8B,KAAK,GAAG9B,WAAW;EAC/BA,WAAW,CAAC+B,OAAO,GAAG/B,WAAW;EACjCA,WAAW,CAACgC,QAAQ,GAAGhC,WAAW;EAClCA,WAAW,CAACiC,MAAM,GAAGjC,WAAW;EAChCA,WAAW,CAACkC,SAAS,GAAGlC,WAAW;EACnCA,WAAW,CAACmC,MAAM,GAAGnC,WAAW;EAChCA,WAAW,CAACoC,OAAO,GAAGpC,WAAW;EACjCA,WAAW,CAACqC,aAAa,GAAGrC,WAAW;EACvCA,WAAW,CAACsC,WAAW,GAAGtC,WAAW;EACrCA,WAAW,CAACuC,aAAa,GAAGvC,WAAW;EACvCA,WAAW,CAACwC,cAAc,GAAGxC,WAAW;EACxCA,WAAW,CAACyC,YAAY,GAAGzC,WAAW;EACtCA,WAAW,CAAC0C,eAAe,GAAG1C,WAAW;EACzCA,WAAW,CAAC2C,YAAY,GAAG3C,WAAW;EACtCA,WAAW,CAAC4C,aAAa,GAAG5C,WAAW;EACvCF,MAAM,GAAGE,WAAW;AACtB"}
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/data_tables.js b/testing/web-platform/mozilla/tests/webgpu/common/util/data_tables.js new file mode 100644 index 0000000000..845cebf1fc --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/util/data_tables.js @@ -0,0 +1,40 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + +export function keysOf(obj) { + return Object.keys(obj); +} + +export function numericKeysOf(obj) { + return Object.keys(obj).map((n) => Number(n)); +} + +/** + * Creates an info lookup object from a more nicely-formatted table. See below for examples. + * + * Note: Using `as const` on the arguments to this function is necessary to infer the correct type. + */ +export function makeTable( + + + + +members, +defaults, +table) + + +{ + const result = {}; + for (const [k, v] of Object.entries(table)) { + const item = {}; + for (let i = 0; i < members.length; ++i) { + item[members[i]] = v[i] ?? defaults[i]; + } + result[k] = item; + } + + return result; +} +//# sourceMappingURL=data_tables.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/data_tables.js.map b/testing/web-platform/mozilla/tests/webgpu/common/util/data_tables.js.map new file mode 100644 index 0000000000..512f535412 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/util/data_tables.js.map @@ -0,0 +1 @@ +{"version":3,"file":"data_tables.js","names":["keysOf","obj","Object","keys","numericKeysOf","map","n","Number","makeTable","members","defaults","table","result","k","v","entries","item","i","length"],"sources":["../../../src/common/util/data_tables.ts"],"sourcesContent":["import { ResolveType, ZipKeysWithValues } from './types.js';\n\nexport type valueof<K> = K[keyof K];\n\nexport function keysOf<T extends string>(obj: { [k in T]: unknown }): readonly T[] {\n return (Object.keys(obj) as unknown[]) as T[];\n}\n\nexport function numericKeysOf<T>(obj: object): readonly T[] {\n return (Object.keys(obj).map(n => Number(n)) as unknown[]) as T[];\n}\n\n/**\n * Creates an info lookup object from a more nicely-formatted table. See below for examples.\n *\n * Note: Using `as const` on the arguments to this function is necessary to infer the correct type.\n */\nexport function makeTable<\n Members extends readonly string[],\n Defaults extends readonly unknown[],\n Table extends { readonly [k: string]: readonly unknown[] }\n>(\n members: Members,\n defaults: Defaults,\n table: Table\n): {\n readonly [k in keyof Table]: ResolveType<ZipKeysWithValues<Members, Table[k], Defaults>>;\n} {\n const result: { [k: string]: { [m: string]: unknown } } = {};\n for (const [k, v] of Object.entries<readonly unknown[]>(table)) {\n const item: { [m: string]: unknown } = {};\n for (let i = 0; i < members.length; ++i) {\n item[members[i]] = v[i] ?? defaults[i];\n }\n result[k] = item;\n }\n /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n return result as any;\n}\n"],"mappings":";AAAA;AAAA;;AAIA,OAAO,SAASA,MAAM,CAAmBC,GAA0B,EAAgB;EACjF,OAAQC,MAAM,CAACC,IAAI,CAACF,GAAG,CAAC;AAC1B;;AAEA,OAAO,SAASG,aAAa,CAAIH,GAAW,EAAgB;EAC1D,OAAQC,MAAM,CAACC,IAAI,CAACF,GAAG,CAAC,CAACI,GAAG,CAAC,CAAAC,CAAC,KAAIC,MAAM,CAACD,CAAC,CAAC,CAAC;AAC9C;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASE,SAAS;;;;;AAKvBC,OAAgB;AAChBC,QAAkB;AAClBC,KAAY;;;AAGZ;EACA,MAAMC,MAAiD,GAAG,CAAC,CAAC;EAC5D,KAAK,MAAM,CAACC,CAAC,EAAEC,CAAC,CAAC,IAAIZ,MAAM,CAACa,OAAO,CAAqBJ,KAAK,CAAC,EAAE;IAC9D,MAAMK,IAA8B,GAAG,CAAC,CAAC;IACzC,KAAK,IAAIC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGR,OAAO,CAACS,MAAM,EAAE,EAAED,CAAC,EAAE;MACvCD,IAAI,CAACP,OAAO,CAACQ,CAAC,CAAC,CAAC,GAAGH,CAAC,CAACG,CAAC,CAAC,IAAIP,QAAQ,CAACO,CAAC,CAAC;IACxC;IACAL,MAAM,CAACC,CAAC,CAAC,GAAGG,IAAI;EAClB;;EAEA,OAAOJ,MAAM;AACf"}
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/navigator_gpu.js b/testing/web-platform/mozilla/tests/webgpu/common/util/navigator_gpu.js new file mode 100644 index 0000000000..75330edbd2 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/util/navigator_gpu.js @@ -0,0 +1,75 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ /// <reference types="@webgpu/types" /> +import { assert } from './util.js'; +/** + * Finds and returns the `navigator.gpu` object (or equivalent, for non-browser implementations). + * Throws an exception if not found. + */ +function defaultGPUProvider() { + assert( + typeof navigator !== 'undefined' && navigator.gpu !== undefined, + 'No WebGPU implementation found'); + + return navigator.gpu; +} + +/** + * GPUProvider is a function that creates and returns a new GPU instance. + * May throw an exception if a GPU cannot be created. + */ + + +let gpuProvider = defaultGPUProvider; + +/** + * Sets the function to create and return a new GPU instance. + */ +export function setGPUProvider(provider) { + assert(impl === undefined, 'setGPUProvider() should not be after getGPU()'); + gpuProvider = provider; +} + +let impl = undefined; + +let defaultRequestAdapterOptions; + +export function setDefaultRequestAdapterOptions(options) { + if (impl) { + throw new Error('must call setDefaultRequestAdapterOptions before getGPU'); + } + defaultRequestAdapterOptions = { ...options }; +} + +/** + * Finds and returns the `navigator.gpu` object (or equivalent, for non-browser implementations). + * Throws an exception if not found. + */ +export function getGPU() { + if (impl) { + return impl; + } + + impl = gpuProvider(); + + if (defaultRequestAdapterOptions) { + + const oldFn = impl.requestAdapter; + impl.requestAdapter = function ( + options) + { + const promise = oldFn.call(this, { ...defaultRequestAdapterOptions, ...(options || {}) }); + void promise.then(async (adapter) => { + if (adapter) { + const info = await adapter.requestAdapterInfo(); + + console.log(info); + } + }); + return promise; + }; + } + + return impl; +} +//# sourceMappingURL=navigator_gpu.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/navigator_gpu.js.map b/testing/web-platform/mozilla/tests/webgpu/common/util/navigator_gpu.js.map new file mode 100644 index 0000000000..cabc9ffd18 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/util/navigator_gpu.js.map @@ -0,0 +1 @@ +{"version":3,"file":"navigator_gpu.js","names":["assert","defaultGPUProvider","navigator","gpu","undefined","gpuProvider","setGPUProvider","provider","impl","defaultRequestAdapterOptions","setDefaultRequestAdapterOptions","options","Error","getGPU","oldFn","requestAdapter","promise","call","then","adapter","info","requestAdapterInfo","console","log"],"sources":["../../../src/common/util/navigator_gpu.ts"],"sourcesContent":["/// <reference types=\"@webgpu/types\" />\n\nimport { assert } from './util.js';\n\n/**\n * Finds and returns the `navigator.gpu` object (or equivalent, for non-browser implementations).\n * Throws an exception if not found.\n */\nfunction defaultGPUProvider(): GPU {\n assert(\n typeof navigator !== 'undefined' && navigator.gpu !== undefined,\n 'No WebGPU implementation found'\n );\n return navigator.gpu;\n}\n\n/**\n * GPUProvider is a function that creates and returns a new GPU instance.\n * May throw an exception if a GPU cannot be created.\n */\nexport type GPUProvider = () => GPU;\n\nlet gpuProvider: GPUProvider = defaultGPUProvider;\n\n/**\n * Sets the function to create and return a new GPU instance.\n */\nexport function setGPUProvider(provider: GPUProvider) {\n assert(impl === undefined, 'setGPUProvider() should not be after getGPU()');\n gpuProvider = provider;\n}\n\nlet impl: GPU | undefined = undefined;\n\nlet defaultRequestAdapterOptions: GPURequestAdapterOptions | undefined;\n\nexport function setDefaultRequestAdapterOptions(options: GPURequestAdapterOptions) {\n if (impl) {\n throw new Error('must call setDefaultRequestAdapterOptions before getGPU');\n }\n defaultRequestAdapterOptions = { ...options };\n}\n\n/**\n * Finds and returns the `navigator.gpu` object (or equivalent, for non-browser implementations).\n * Throws an exception if not found.\n */\nexport function getGPU(): GPU {\n if (impl) {\n return impl;\n }\n\n impl = gpuProvider();\n\n if (defaultRequestAdapterOptions) {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n const oldFn = impl.requestAdapter;\n impl.requestAdapter = function (\n options?: GPURequestAdapterOptions\n ): Promise<GPUAdapter | null> {\n const promise = oldFn.call(this, { ...defaultRequestAdapterOptions, ...(options || {}) });\n void promise.then(async adapter => {\n if (adapter) {\n const info = await adapter.requestAdapterInfo();\n // eslint-disable-next-line no-console\n console.log(info);\n }\n });\n return promise;\n };\n }\n\n return impl;\n}\n"],"mappings":";AAAA;AAAA,G,CAAA;AAEA,SAASA,MAAM,QAAQ,WAAW;AAElC;AACA;AACA;AACA;AACA,SAASC,kBAAkB,GAAQ;EACjCD,MAAM;EACJ,OAAOE,SAAS,KAAK,WAAW,IAAIA,SAAS,CAACC,GAAG,KAAKC,SAAS;EAC/D,gCAAgC,CACjC;;EACD,OAAOF,SAAS,CAACC,GAAG;AACtB;;AAEA;AACA;AACA;AACA;;;AAGA,IAAIE,WAAwB,GAAGJ,kBAAkB;;AAEjD;AACA;AACA;AACA,OAAO,SAASK,cAAc,CAACC,QAAqB,EAAE;EACpDP,MAAM,CAACQ,IAAI,KAAKJ,SAAS,EAAE,+CAA+C,CAAC;EAC3EC,WAAW,GAAGE,QAAQ;AACxB;;AAEA,IAAIC,IAAqB,GAAGJ,SAAS;;AAErC,IAAIK,4BAAkE;;AAEtE,OAAO,SAASC,+BAA+B,CAACC,OAAiC,EAAE;EACjF,IAAIH,IAAI,EAAE;IACR,MAAM,IAAII,KAAK,CAAC,yDAAyD,CAAC;EAC5E;EACAH,4BAA4B,GAAG,EAAE,GAAGE,OAAO,CAAC,CAAC;AAC/C;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASE,MAAM,GAAQ;EAC5B,IAAIL,IAAI,EAAE;IACR,OAAOA,IAAI;EACb;;EAEAA,IAAI,GAAGH,WAAW,EAAE;;EAEpB,IAAII,4BAA4B,EAAE;;IAEhC,MAAMK,KAAK,GAAGN,IAAI,CAACO,cAAc;IACjCP,IAAI,CAACO,cAAc,GAAG;IACpBJ,OAAkC;IACN;MAC5B,MAAMK,OAAO,GAAGF,KAAK,CAACG,IAAI,CAAC,IAAI,EAAE,EAAE,GAAGR,4BAA4B,EAAE,IAAIE,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;MACzF,KAAKK,OAAO,CAACE,IAAI,CAAC,OAAMC,OAAO,KAAI;QACjC,IAAIA,OAAO,EAAE;UACX,MAAMC,IAAI,GAAG,MAAMD,OAAO,CAACE,kBAAkB,EAAE;;UAE/CC,OAAO,CAACC,GAAG,CAACH,IAAI,CAAC;QACnB;MACF,CAAC,CAAC;MACF,OAAOJ,OAAO;IAChB,CAAC;EACH;;EAEA,OAAOR,IAAI;AACb"}
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/preprocessor.js b/testing/web-platform/mozilla/tests/webgpu/common/util/preprocessor.js new file mode 100644 index 0000000000..23ffe4c45a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/util/preprocessor.js @@ -0,0 +1,150 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { assert } from './util.js'; // The state of the preprocessor is a stack of States. +var +State; + + +// Have already seen a passing condition; now skipping the rest + + +// The transitions in the state space are the following preprocessor directives: +// - Sibling elif +// - Sibling else +// - Sibling endif +// - Child if +(function (State) {State[State["Seeking"] = 0] = "Seeking";State[State["Passing"] = 1] = "Passing";State[State["Skipping"] = 2] = "Skipping";})(State || (State = {}));class Directive { + + + constructor(depth) { + this.depth = depth; + } + + checkDepth(stack) { + assert( + stack.length === this.depth, + `Number of "$"s must match nesting depth, currently ${stack.length} (e.g. $if $$if $$endif $endif)`); + + } + + +} + +class If extends Directive { + + + constructor(depth, predicate) { + super(depth); + this.predicate = predicate; + } + + applyTo(stack) { + this.checkDepth(stack); + const parentState = stack[stack.length - 1].state; + stack.push({ + allowsFollowingElse: true, + state: + parentState !== State.Passing ? + State.Skipping : + this.predicate ? + State.Passing : + State.Seeking + }); + } +} + +class ElseIf extends If { + applyTo(stack) { + assert(stack.length >= 1); + const { allowsFollowingElse, state: siblingState } = stack.pop(); + this.checkDepth(stack); + assert(allowsFollowingElse, 'pp.elif after pp.else'); + if (siblingState !== State.Seeking) { + stack.push({ allowsFollowingElse: true, state: State.Skipping }); + } else { + super.applyTo(stack); + } + } +} + +class Else extends Directive { + applyTo(stack) { + assert(stack.length >= 1); + const { allowsFollowingElse, state: siblingState } = stack.pop(); + this.checkDepth(stack); + assert(allowsFollowingElse, 'pp.else after pp.else'); + stack.push({ + allowsFollowingElse: false, + state: siblingState === State.Seeking ? State.Passing : State.Skipping + }); + } +} + +class EndIf extends Directive { + applyTo(stack) { + stack.pop(); + this.checkDepth(stack); + } +} + +/** + * A simple template-based, non-line-based preprocessor implementing if/elif/else/endif. + * + * @example + * ``` + * const shader = pp` + * ${pp._if(expr)} + * const x: ${type} = ${value}; + * ${pp._elif(expr)} + * ${pp.__if(expr)} + * ... + * ${pp.__else} + * ... + * ${pp.__endif} + * ${pp._endif}`; + * ``` + * + * @param strings - The array of constant string chunks of the template string. + * @param ...values - The array of interpolated `${}` values within the template string. + */ +export function pp( +strings, +...values) +{ + let result = ''; + const stateStack = [{ allowsFollowingElse: false, state: State.Passing }]; + + for (let i = 0; i < values.length; ++i) { + const passing = stateStack[stateStack.length - 1].state === State.Passing; + if (passing) { + result += strings[i]; + } + + const value = values[i]; + if (value instanceof Directive) { + value.applyTo(stateStack); + } else { + if (passing) { + result += value; + } + } + } + assert(stateStack.length === 1, 'Unterminated preprocessor condition at end of file'); + result += strings[values.length]; + + return result; +} +pp._if = (predicate) => new If(1, predicate); +pp._elif = (predicate) => new ElseIf(1, predicate); +pp._else = new Else(1); +pp._endif = new EndIf(1); +pp.__if = (predicate) => new If(2, predicate); +pp.__elif = (predicate) => new ElseIf(2, predicate); +pp.__else = new Else(2); +pp.__endif = new EndIf(2); +pp.___if = (predicate) => new If(3, predicate); +pp.___elif = (predicate) => new ElseIf(3, predicate); +pp.___else = new Else(3); +pp.___endif = new EndIf(3); +// Add more if needed. +//# sourceMappingURL=preprocessor.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/preprocessor.js.map b/testing/web-platform/mozilla/tests/webgpu/common/util/preprocessor.js.map new file mode 100644 index 0000000000..b58f288efe --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/util/preprocessor.js.map @@ -0,0 +1 @@ +{"version":3,"file":"preprocessor.js","names":["assert","State","Directive","constructor","depth","checkDepth","stack","length","If","predicate","applyTo","parentState","state","push","allowsFollowingElse","Passing","Skipping","Seeking","ElseIf","siblingState","pop","Else","EndIf","pp","strings","values","result","stateStack","i","passing","value","_if","_elif","_else","_endif","__if","__elif","__else","__endif","___if","___elif","___else","___endif"],"sources":["../../../src/common/util/preprocessor.ts"],"sourcesContent":["import { assert } from './util.js';\n\n// The state of the preprocessor is a stack of States.\ntype StateStack = { allowsFollowingElse: boolean; state: State }[];\nconst enum State {\n Seeking, // Still looking for a passing condition\n Passing, // Currently inside a passing condition (the root is always in this state)\n Skipping, // Have already seen a passing condition; now skipping the rest\n}\n\n// The transitions in the state space are the following preprocessor directives:\n// - Sibling elif\n// - Sibling else\n// - Sibling endif\n// - Child if\nabstract class Directive {\n private readonly depth: number;\n\n constructor(depth: number) {\n this.depth = depth;\n }\n\n protected checkDepth(stack: StateStack): void {\n assert(\n stack.length === this.depth,\n `Number of \"$\"s must match nesting depth, currently ${stack.length} (e.g. $if $$if $$endif $endif)`\n );\n }\n\n abstract applyTo(stack: StateStack): void;\n}\n\nclass If extends Directive {\n private readonly predicate: boolean;\n\n constructor(depth: number, predicate: boolean) {\n super(depth);\n this.predicate = predicate;\n }\n\n applyTo(stack: StateStack) {\n this.checkDepth(stack);\n const parentState = stack[stack.length - 1].state;\n stack.push({\n allowsFollowingElse: true,\n state:\n parentState !== State.Passing\n ? State.Skipping\n : this.predicate\n ? State.Passing\n : State.Seeking,\n });\n }\n}\n\nclass ElseIf extends If {\n applyTo(stack: StateStack) {\n assert(stack.length >= 1);\n const { allowsFollowingElse, state: siblingState } = stack.pop()!;\n this.checkDepth(stack);\n assert(allowsFollowingElse, 'pp.elif after pp.else');\n if (siblingState !== State.Seeking) {\n stack.push({ allowsFollowingElse: true, state: State.Skipping });\n } else {\n super.applyTo(stack);\n }\n }\n}\n\nclass Else extends Directive {\n applyTo(stack: StateStack) {\n assert(stack.length >= 1);\n const { allowsFollowingElse, state: siblingState } = stack.pop()!;\n this.checkDepth(stack);\n assert(allowsFollowingElse, 'pp.else after pp.else');\n stack.push({\n allowsFollowingElse: false,\n state: siblingState === State.Seeking ? State.Passing : State.Skipping,\n });\n }\n}\n\nclass EndIf extends Directive {\n applyTo(stack: StateStack) {\n stack.pop();\n this.checkDepth(stack);\n }\n}\n\n/**\n * A simple template-based, non-line-based preprocessor implementing if/elif/else/endif.\n *\n * @example\n * ```\n * const shader = pp`\n * ${pp._if(expr)}\n * const x: ${type} = ${value};\n * ${pp._elif(expr)}\n * ${pp.__if(expr)}\n * ...\n * ${pp.__else}\n * ...\n * ${pp.__endif}\n * ${pp._endif}`;\n * ```\n *\n * @param strings - The array of constant string chunks of the template string.\n * @param ...values - The array of interpolated `${}` values within the template string.\n */\nexport function pp(\n strings: TemplateStringsArray,\n ...values: ReadonlyArray<Directive | string | number>\n): string {\n let result = '';\n const stateStack: StateStack = [{ allowsFollowingElse: false, state: State.Passing }];\n\n for (let i = 0; i < values.length; ++i) {\n const passing = stateStack[stateStack.length - 1].state === State.Passing;\n if (passing) {\n result += strings[i];\n }\n\n const value = values[i];\n if (value instanceof Directive) {\n value.applyTo(stateStack);\n } else {\n if (passing) {\n result += value;\n }\n }\n }\n assert(stateStack.length === 1, 'Unterminated preprocessor condition at end of file');\n result += strings[values.length];\n\n return result;\n}\npp._if = (predicate: boolean) => new If(1, predicate);\npp._elif = (predicate: boolean) => new ElseIf(1, predicate);\npp._else = new Else(1);\npp._endif = new EndIf(1);\npp.__if = (predicate: boolean) => new If(2, predicate);\npp.__elif = (predicate: boolean) => new ElseIf(2, predicate);\npp.__else = new Else(2);\npp.__endif = new EndIf(2);\npp.___if = (predicate: boolean) => new If(3, predicate);\npp.___elif = (predicate: boolean) => new ElseIf(3, predicate);\npp.___else = new Else(3);\npp.___endif = new EndIf(3);\n// Add more if needed.\n"],"mappings":";AAAA;AAAA,GAAA,SAASA,MAAM,QAAQ,WAAW,CAAC,CAEnC;AAAA;AAEWC,KAAK;;;AAGJ;;;AAGZ;AACA;AACA;AACA;AACA;AAAA,WAVWA,KAAK,GAALA,KAAK,CAALA,KAAK,6BAALA,KAAK,CAALA,KAAK,6BAALA,KAAK,CAALA,KAAK,kCAALA,KAAK,KAALA,KAAK,QAWhB,MAAeC,SAAS,CAAC;;;EAGvBC,WAAW,CAACC,KAAa,EAAE;IACzB,IAAI,CAACA,KAAK,GAAGA,KAAK;EACpB;;EAEUC,UAAU,CAACC,KAAiB,EAAQ;IAC5CN,MAAM;IACJM,KAAK,CAACC,MAAM,KAAK,IAAI,CAACH,KAAK;IAC1B,sDAAqDE,KAAK,CAACC,MAAO,iCAAgC,CACpG;;EACH;;;AAGF;;AAEA,MAAMC,EAAE,SAASN,SAAS,CAAC;;;EAGzBC,WAAW,CAACC,KAAa,EAAEK,SAAkB,EAAE;IAC7C,KAAK,CAACL,KAAK,CAAC;IACZ,IAAI,CAACK,SAAS,GAAGA,SAAS;EAC5B;;EAEAC,OAAO,CAACJ,KAAiB,EAAE;IACzB,IAAI,CAACD,UAAU,CAACC,KAAK,CAAC;IACtB,MAAMK,WAAW,GAAGL,KAAK,CAACA,KAAK,CAACC,MAAM,GAAG,CAAC,CAAC,CAACK,KAAK;IACjDN,KAAK,CAACO,IAAI,CAAC;MACTC,mBAAmB,EAAE,IAAI;MACzBF,KAAK;MACHD,WAAW,KAAKV,KAAK,CAACc,OAAO;MACzBd,KAAK,CAACe,QAAQ;MACd,IAAI,CAACP,SAAS;MACdR,KAAK,CAACc,OAAO;MACbd,KAAK,CAACgB;IACd,CAAC,CAAC;EACJ;AACF;;AAEA,MAAMC,MAAM,SAASV,EAAE,CAAC;EACtBE,OAAO,CAACJ,KAAiB,EAAE;IACzBN,MAAM,CAACM,KAAK,CAACC,MAAM,IAAI,CAAC,CAAC;IACzB,MAAM,EAAEO,mBAAmB,EAAEF,KAAK,EAAEO,YAAY,CAAC,CAAC,GAAGb,KAAK,CAACc,GAAG,EAAG;IACjE,IAAI,CAACf,UAAU,CAACC,KAAK,CAAC;IACtBN,MAAM,CAACc,mBAAmB,EAAE,uBAAuB,CAAC;IACpD,IAAIK,YAAY,KAAKlB,KAAK,CAACgB,OAAO,EAAE;MAClCX,KAAK,CAACO,IAAI,CAAC,EAAEC,mBAAmB,EAAE,IAAI,EAAEF,KAAK,EAAEX,KAAK,CAACe,QAAQ,CAAC,CAAC,CAAC;IAClE,CAAC,MAAM;MACL,KAAK,CAACN,OAAO,CAACJ,KAAK,CAAC;IACtB;EACF;AACF;;AAEA,MAAMe,IAAI,SAASnB,SAAS,CAAC;EAC3BQ,OAAO,CAACJ,KAAiB,EAAE;IACzBN,MAAM,CAACM,KAAK,CAACC,MAAM,IAAI,CAAC,CAAC;IACzB,MAAM,EAAEO,mBAAmB,EAAEF,KAAK,EAAEO,YAAY,CAAC,CAAC,GAAGb,KAAK,CAACc,GAAG,EAAG;IACjE,IAAI,CAACf,UAAU,CAACC,KAAK,CAAC;IACtBN,MAAM,CAACc,mBAAmB,EAAE,uBAAuB,CAAC;IACpDR,KAAK,CAACO,IAAI,CAAC;MACTC,mBAAmB,EAAE,KAAK;MAC1BF,KAAK,EAAEO,YAAY,KAAKlB,KAAK,CAACgB,OAAO,GAAGhB,KAAK,CAACc,OAAO,GAAGd,KAAK,CAACe;IAChE,CAAC,CAAC;EACJ;AACF;;AAEA,MAAMM,KAAK,SAASpB,SAAS,CAAC;EAC5BQ,OAAO,CAACJ,KAAiB,EAAE;IACzBA,KAAK,CAACc,GAAG,EAAE;IACX,IAAI,CAACf,UAAU,CAACC,KAAK,CAAC;EACxB;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASiB,EAAE;AAChBC,OAA6B;AAC7B,GAAGC,MAAkD;AAC7C;EACR,IAAIC,MAAM,GAAG,EAAE;EACf,MAAMC,UAAsB,GAAG,CAAC,EAAEb,mBAAmB,EAAE,KAAK,EAAEF,KAAK,EAAEX,KAAK,CAACc,OAAO,CAAC,CAAC,CAAC;;EAErF,KAAK,IAAIa,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGH,MAAM,CAAClB,MAAM,EAAE,EAAEqB,CAAC,EAAE;IACtC,MAAMC,OAAO,GAAGF,UAAU,CAACA,UAAU,CAACpB,MAAM,GAAG,CAAC,CAAC,CAACK,KAAK,KAAKX,KAAK,CAACc,OAAO;IACzE,IAAIc,OAAO,EAAE;MACXH,MAAM,IAAIF,OAAO,CAACI,CAAC,CAAC;IACtB;;IAEA,MAAME,KAAK,GAAGL,MAAM,CAACG,CAAC,CAAC;IACvB,IAAIE,KAAK,YAAY5B,SAAS,EAAE;MAC9B4B,KAAK,CAACpB,OAAO,CAACiB,UAAU,CAAC;IAC3B,CAAC,MAAM;MACL,IAAIE,OAAO,EAAE;QACXH,MAAM,IAAII,KAAK;MACjB;IACF;EACF;EACA9B,MAAM,CAAC2B,UAAU,CAACpB,MAAM,KAAK,CAAC,EAAE,oDAAoD,CAAC;EACrFmB,MAAM,IAAIF,OAAO,CAACC,MAAM,CAAClB,MAAM,CAAC;;EAEhC,OAAOmB,MAAM;AACf;AACAH,EAAE,CAACQ,GAAG,GAAG,CAACtB,SAAkB,KAAK,IAAID,EAAE,CAAC,CAAC,EAAEC,SAAS,CAAC;AACrDc,EAAE,CAACS,KAAK,GAAG,CAACvB,SAAkB,KAAK,IAAIS,MAAM,CAAC,CAAC,EAAET,SAAS,CAAC;AAC3Dc,EAAE,CAACU,KAAK,GAAG,IAAIZ,IAAI,CAAC,CAAC,CAAC;AACtBE,EAAE,CAACW,MAAM,GAAG,IAAIZ,KAAK,CAAC,CAAC,CAAC;AACxBC,EAAE,CAACY,IAAI,GAAG,CAAC1B,SAAkB,KAAK,IAAID,EAAE,CAAC,CAAC,EAAEC,SAAS,CAAC;AACtDc,EAAE,CAACa,MAAM,GAAG,CAAC3B,SAAkB,KAAK,IAAIS,MAAM,CAAC,CAAC,EAAET,SAAS,CAAC;AAC5Dc,EAAE,CAACc,MAAM,GAAG,IAAIhB,IAAI,CAAC,CAAC,CAAC;AACvBE,EAAE,CAACe,OAAO,GAAG,IAAIhB,KAAK,CAAC,CAAC,CAAC;AACzBC,EAAE,CAACgB,KAAK,GAAG,CAAC9B,SAAkB,KAAK,IAAID,EAAE,CAAC,CAAC,EAAEC,SAAS,CAAC;AACvDc,EAAE,CAACiB,OAAO,GAAG,CAAC/B,SAAkB,KAAK,IAAIS,MAAM,CAAC,CAAC,EAAET,SAAS,CAAC;AAC7Dc,EAAE,CAACkB,OAAO,GAAG,IAAIpB,IAAI,CAAC,CAAC,CAAC;AACxBE,EAAE,CAACmB,QAAQ,GAAG,IAAIpB,KAAK,CAAC,CAAC,CAAC;AAC1B"}
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/timeout.js b/testing/web-platform/mozilla/tests/webgpu/common/util/timeout.js new file mode 100644 index 0000000000..32b4660a59 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/util/timeout.js @@ -0,0 +1,8 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ +/** + * Equivalent of `setTimeout`, but redirects to WPT's `step_timeout` when it is defined. + */ +export const timeout = typeof step_timeout !== 'undefined' ? step_timeout : setTimeout; +//# sourceMappingURL=timeout.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/timeout.js.map b/testing/web-platform/mozilla/tests/webgpu/common/util/timeout.js.map new file mode 100644 index 0000000000..0e8fff6f67 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/util/timeout.js.map @@ -0,0 +1 @@ +{"version":3,"file":"timeout.js","names":["timeout","step_timeout","setTimeout"],"sources":["../../../src/common/util/timeout.ts"],"sourcesContent":["/** Defined by WPT. Like `setTimeout`, but applies a timeout multiplier for slow test systems. */\ndeclare const step_timeout: undefined | typeof setTimeout;\n\n/**\n * Equivalent of `setTimeout`, but redirects to WPT's `step_timeout` when it is defined.\n */\nexport const timeout = typeof step_timeout !== 'undefined' ? step_timeout : setTimeout;\n"],"mappings":";AAAA;AAAA;AAGA;AACA;AACA;AACA,OAAO,MAAMA,OAAO,GAAG,OAAOC,YAAY,KAAK,WAAW,GAAGA,YAAY,GAAGC,UAAU"}
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/types.js b/testing/web-platform/mozilla/tests/webgpu/common/util/types.js new file mode 100644 index 0000000000..2c224b6d3a --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/util/types.js @@ -0,0 +1,60 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/ + + + + + + + + + + +export function assertTypeTrue() {} + +/** + * Computes the intersection of a set of types, given the union of those types. + * + * From: https://stackoverflow.com/a/56375136 + */ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// K exhausted +//# sourceMappingURL=types.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/types.js.map b/testing/web-platform/mozilla/tests/webgpu/common/util/types.js.map new file mode 100644 index 0000000000..084ce36abb --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/util/types.js.map @@ -0,0 +1 @@ +{"version":3,"file":"types.js","names":["assertTypeTrue"],"sources":["../../../src/common/util/types.ts"],"sourcesContent":["/** Forces a type to resolve its type definitions, to make it readable/debuggable. */\nexport type ResolveType<T> = T extends object\n ? T extends infer O\n ? { [K in keyof O]: ResolveType<O[K]> }\n : never\n : T;\n\n/** Returns the type `true` iff X and Y are exactly equal */\nexport type TypeEqual<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2\n ? true\n : false;\n\n/* eslint-disable-next-line @typescript-eslint/no-unused-vars */\nexport function assertTypeTrue<T extends true>() {}\n\n/**\n * Computes the intersection of a set of types, given the union of those types.\n *\n * From: https://stackoverflow.com/a/56375136\n */\nexport type UnionToIntersection<U> =\n /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;\n\n/** \"Type asserts\" that `X` is a subtype of `Y`. */\ntype EnsureSubtype<X, Y> = X extends Y ? X : never;\n\ntype TupleHeadOr<T, Default> = T extends readonly [infer H, ...(readonly unknown[])] ? H : Default;\ntype TupleTailOr<T, Default> = T extends readonly [unknown, ...infer Tail] ? Tail : Default;\ntype TypeOr<T, Default> = T extends undefined ? Default : T;\n\n/**\n * Zips a key tuple type and a value tuple type together into an object.\n *\n * @template Keys Keys of the resulting object.\n * @template Values Values of the resulting object. If a key corresponds to a `Values` member that\n * is undefined or past the end, it defaults to the corresponding `Defaults` member.\n * @template Defaults Default values. If a key corresponds to a `Defaults` member that is past the\n * end, the default falls back to `undefined`.\n */\nexport type ZipKeysWithValues<\n Keys extends readonly string[],\n Values extends readonly unknown[],\n Defaults extends readonly unknown[]\n> =\n //\n Keys extends readonly [infer KHead, ...infer KTail]\n ? {\n readonly [k in EnsureSubtype<KHead, string>]: TypeOr<\n TupleHeadOr<Values, undefined>,\n TupleHeadOr<Defaults, undefined>\n >;\n } &\n ZipKeysWithValues<\n EnsureSubtype<KTail, readonly string[]>,\n TupleTailOr<Values, []>,\n TupleTailOr<Defaults, []>\n >\n : {}; // K exhausted\n"],"mappings":";AAAA;AAAA;;;;;;;;;;;AAaA,OAAO,SAASA,cAAc,GAAmB,CAAC;;AAElD;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCU"}
\ 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 new file mode 100644 index 0000000000..3dfd824b12 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/util/util.js @@ -0,0 +1,304 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { Float16Array } from '../../external/petamoriken/float16/float16.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'; + +/** + * Error with arbitrary `extra` data attached, for debugging. + * The extra data is omitted if not running the test in debug mode (`?debug=1`). + */ +export class ErrorWithExtra extends Error { + + + /** + * `extra` function is only called if in debug mode. + * If an `ErrorWithExtra` is passed, its message is used and its extras are passed through. + */ + + + constructor(baseOrMessage, newExtra) { + const message = typeof baseOrMessage === 'string' ? baseOrMessage : baseOrMessage.message; + super(message); + + const oldExtras = baseOrMessage instanceof ErrorWithExtra ? baseOrMessage.extra : {}; + this.extra = Logger.globalDebugMode ? + { ...oldExtras, ...newExtra() } : + { omitted: 'pass ?debug=1' }; + } +} + +/** + * Asserts `condition` is true. Otherwise, throws an `Error` with the provided message. + */ +export function assert(condition, msg) { + if (!condition) { + throw new Error(msg && (typeof msg === 'string' ? msg : msg())); + } +} + +/** If the argument is an Error, throw it. Otherwise, pass it back. */ +export function assertOK(value) { + if (value instanceof Error) { + throw value; + } + return value; +} + +/** + * Resolves if the provided promise rejects; rejects if it does not. + */ +export async function assertReject(p, msg) { + try { + await p; + unreachable(msg); + } catch (ex) { + + // Assertion OK + }} + +/** + * Assert this code is unreachable. Unconditionally throws an `Error`. + */ +export function unreachable(msg) { + throw new Error(msg); +} + +/** + * The `performance` interface. + * It is available in all browsers, but it is not in scope by default in Node. + */ +const perf = typeof performance !== 'undefined' ? performance : require('perf_hooks').performance; + +/** + * Calls the appropriate `performance.now()` depending on whether running in a browser or Node. + */ +export function now() { + return perf.now(); +} + +/** + * Returns a promise which resolves after the specified time. + */ +export function resolveOnTimeout(ms) { + return new Promise((resolve) => { + timeout(() => { + resolve(); + }, ms); + }); +} + +export class PromiseTimeoutError extends Error {} + +/** + * Returns a promise which rejects after the specified time. + */ +export function rejectOnTimeout(ms, msg) { + return new Promise((_resolve, reject) => { + timeout(() => { + reject(new PromiseTimeoutError(msg)); + }, ms); + }); +} + +/** + * Takes a promise `p`, and returns a new one which rejects if `p` takes too long, + * and otherwise passes the result through. + */ +export function raceWithRejectOnTimeout(p, ms, msg) { + if (globalTestConfig.noRaceWithRejectOnTimeout) { + return p; + } + // Setup a promise that will reject after `ms` milliseconds. We cancel this timeout when + // `p` is finalized, so the JavaScript VM doesn't hang around waiting for the timer to + // complete, once the test runner has finished executing the tests. + const timeoutPromise = new Promise((_resolve, reject) => { + const handle = timeout(() => { + reject(new PromiseTimeoutError(msg)); + }, ms); + p = p.finally(() => clearTimeout(handle)); + }); + return Promise.race([p, timeoutPromise]); +} + +/** + * Takes a promise `p` and returns a new one which rejects if `p` resolves or rejects, + * and otherwise resolves after the specified time. + */ +export function assertNotSettledWithinTime( +p, +ms, +msg) +{ + // Rejects regardless of whether p resolves or rejects. + const rejectWhenSettled = p.then(() => Promise.reject(new Error(msg))); + // Resolves after `ms` milliseconds. + const timeoutPromise = new Promise((resolve) => { + const handle = timeout(() => { + resolve(undefined); + }, ms); + p.finally(() => clearTimeout(handle)); + }); + return Promise.race([rejectWhenSettled, timeoutPromise]); +} + +/** + * Returns a `Promise.reject()`, but also registers a dummy `.catch()` handler so it doesn't count + * as an uncaught promise rejection in the runtime. + */ +export function rejectWithoutUncaught(err) { + const p = Promise.reject(err); + // Suppress uncaught promise rejection. + p.catch(() => {}); + return p; +} + +/** + * Makes a copy of a JS `object`, with the keys reordered into sorted order. + */ +export function sortObjectByKey(v) { + const sortedObject = {}; + for (const k of Object.keys(v).sort()) { + sortedObject[k] = v[k]; + } + return sortedObject; +} + +/** + * Determines whether two JS values are equal, recursing into objects and arrays. + * NaN is treated specially, such that `objectEquals(NaN, NaN)`. + */ +export function objectEquals(x, y) { + if (typeof x !== 'object' || typeof y !== 'object') { + if (typeof x === 'number' && typeof y === 'number' && Number.isNaN(x) && Number.isNaN(y)) { + return true; + } + return x === y; + } + if (x === null || y === null) return x === y; + if (x.constructor !== y.constructor) return false; + if (x instanceof Function) return x === y; + if (x instanceof RegExp) return x === y; + if (x === y || x.valueOf() === y.valueOf()) return true; + if (Array.isArray(x) && Array.isArray(y) && x.length !== y.length) return false; + if (x instanceof Date) return false; + if (!(x instanceof Object)) return false; + if (!(y instanceof Object)) return false; + + const x1 = x; + const y1 = y; + const p = Object.keys(x); + return Object.keys(y).every((i) => p.indexOf(i) !== -1) && p.every((i) => objectEquals(x1[i], y1[i])); +} + +/** + * Generates a range of values `fn(0)..fn(n-1)`. + */ +export function range(n, fn) { + return [...new Array(n)].map((_, i) => fn(i)); +} + +/** + * Generates a range of values `fn(0)..fn(n-1)`. + */ +export function* iterRange(n, fn) { + for (let i = 0; i < n; ++i) { + yield fn(i); + } +} + +/** Creates a (reusable) iterable object that maps `f` over `xs`, lazily. */ +export function mapLazy(xs, f) { + return { + *[Symbol.iterator]() { + for (const x of xs) { + yield f(x); + } + } + }; +} + +const TypedArrayBufferViewInstances = [ +new Uint8Array(), +new Uint8ClampedArray(), +new Uint16Array(), +new Uint32Array(), +new Int8Array(), +new Int16Array(), +new Int32Array(), +new Float16Array(), +new Float32Array(), +new Float64Array()]; + + + + + + + + + + + + + + + + + + + + + + + + + +export const kTypedArrayBufferViews = + +{ + ...(() => { + + const result = {}; + for (const v of TypedArrayBufferViewInstances) { + result[v.constructor.name] = v.constructor; + } + return result; + })() +}; +export const kTypedArrayBufferViewKeys = keysOf(kTypedArrayBufferViews); +export const kTypedArrayBufferViewConstructors = Object.values(kTypedArrayBufferViews); + +function subarrayAsU8( +buf, +{ start = 0, length }) +{ + if (buf instanceof ArrayBuffer) { + return new Uint8Array(buf, start, length); + } else if (buf instanceof Uint8Array || buf instanceof Uint8ClampedArray) { + // Don't wrap in new views if we don't need to. + if (start === 0 && (length === undefined || length === buf.byteLength)) { + return buf; + } + } + const byteOffset = buf.byteOffset + start * buf.BYTES_PER_ELEMENT; + const byteLength = + length !== undefined ? + length * buf.BYTES_PER_ELEMENT : + buf.byteLength - (byteOffset - buf.byteOffset); + return new Uint8Array(buf.buffer, byteOffset, byteLength); +} + +/** + * Copy a range of bytes from one ArrayBuffer or TypedArray to another. + * + * `start`/`length` are in elements (or in bytes, if ArrayBuffer). + */ +export function memcpy( +src, +dst) +{ + subarrayAsU8(dst.dst, dst).set(subarrayAsU8(src.src, src)); +} +//# sourceMappingURL=util.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/util.js.map b/testing/web-platform/mozilla/tests/webgpu/common/util/util.js.map new file mode 100644 index 0000000000..4a8ad3bd50 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/util/util.js.map @@ -0,0 +1 @@ +{"version":3,"file":"util.js","names":["Float16Array","globalTestConfig","Logger","keysOf","timeout","ErrorWithExtra","Error","constructor","baseOrMessage","newExtra","message","oldExtras","extra","globalDebugMode","omitted","assert","condition","msg","assertOK","value","assertReject","p","unreachable","ex","perf","performance","require","now","resolveOnTimeout","ms","Promise","resolve","PromiseTimeoutError","rejectOnTimeout","_resolve","reject","raceWithRejectOnTimeout","noRaceWithRejectOnTimeout","timeoutPromise","handle","finally","clearTimeout","race","assertNotSettledWithinTime","rejectWhenSettled","then","undefined","rejectWithoutUncaught","err","catch","sortObjectByKey","v","sortedObject","k","Object","keys","sort","objectEquals","x","y","Number","isNaN","Function","RegExp","valueOf","Array","isArray","length","Date","x1","y1","every","i","indexOf","range","n","fn","map","_","iterRange","mapLazy","xs","f","Symbol","iterator","TypedArrayBufferViewInstances","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","Int8Array","Int16Array","Int32Array","Float32Array","Float64Array","kTypedArrayBufferViews","result","name","kTypedArrayBufferViewKeys","kTypedArrayBufferViewConstructors","values","subarrayAsU8","buf","start","ArrayBuffer","byteLength","byteOffset","BYTES_PER_ELEMENT","buffer","memcpy","src","dst","set"],"sources":["../../../src/common/util/util.ts"],"sourcesContent":["import { Float16Array } from '../../external/petamoriken/float16/float16.js';\nimport { globalTestConfig } from '../framework/test_config.js';\nimport { Logger } from '../internal/logging/logger.js';\n\nimport { keysOf } from './data_tables.js';\nimport { timeout } from './timeout.js';\n\n/**\n * Error with arbitrary `extra` data attached, for debugging.\n * The extra data is omitted if not running the test in debug mode (`?debug=1`).\n */\nexport class ErrorWithExtra extends Error {\n readonly extra: { [k: string]: unknown };\n\n /**\n * `extra` function is only called if in debug mode.\n * If an `ErrorWithExtra` is passed, its message is used and its extras are passed through.\n */\n constructor(message: string, extra: () => {});\n constructor(base: ErrorWithExtra, newExtra: () => {});\n constructor(baseOrMessage: string | ErrorWithExtra, newExtra: () => {}) {\n const message = typeof baseOrMessage === 'string' ? baseOrMessage : baseOrMessage.message;\n super(message);\n\n const oldExtras = baseOrMessage instanceof ErrorWithExtra ? baseOrMessage.extra : {};\n this.extra = Logger.globalDebugMode\n ? { ...oldExtras, ...newExtra() }\n : { omitted: 'pass ?debug=1' };\n }\n}\n\n/**\n * Asserts `condition` is true. Otherwise, throws an `Error` with the provided message.\n */\nexport function assert(condition: boolean, msg?: string | (() => string)): asserts condition {\n if (!condition) {\n throw new Error(msg && (typeof msg === 'string' ? msg : msg()));\n }\n}\n\n/** If the argument is an Error, throw it. Otherwise, pass it back. */\nexport function assertOK<T>(value: Error | T): T {\n if (value instanceof Error) {\n throw value;\n }\n return value;\n}\n\n/**\n * Resolves if the provided promise rejects; rejects if it does not.\n */\nexport async function assertReject(p: Promise<unknown>, msg?: string): Promise<void> {\n try {\n await p;\n unreachable(msg);\n } catch (ex) {\n // Assertion OK\n }\n}\n\n/**\n * Assert this code is unreachable. Unconditionally throws an `Error`.\n */\nexport function unreachable(msg?: string): never {\n throw new Error(msg);\n}\n\n/**\n * The `performance` interface.\n * It is available in all browsers, but it is not in scope by default in Node.\n */\nconst perf = typeof performance !== 'undefined' ? performance : require('perf_hooks').performance;\n\n/**\n * Calls the appropriate `performance.now()` depending on whether running in a browser or Node.\n */\nexport function now(): number {\n return perf.now();\n}\n\n/**\n * Returns a promise which resolves after the specified time.\n */\nexport function resolveOnTimeout(ms: number): Promise<void> {\n return new Promise(resolve => {\n timeout(() => {\n resolve();\n }, ms);\n });\n}\n\nexport class PromiseTimeoutError extends Error {}\n\n/**\n * Returns a promise which rejects after the specified time.\n */\nexport function rejectOnTimeout(ms: number, msg: string): Promise<never> {\n return new Promise((_resolve, reject) => {\n timeout(() => {\n reject(new PromiseTimeoutError(msg));\n }, ms);\n });\n}\n\n/**\n * Takes a promise `p`, and returns a new one which rejects if `p` takes too long,\n * and otherwise passes the result through.\n */\nexport function raceWithRejectOnTimeout<T>(p: Promise<T>, ms: number, msg: string): Promise<T> {\n if (globalTestConfig.noRaceWithRejectOnTimeout) {\n return p;\n }\n // Setup a promise that will reject after `ms` milliseconds. We cancel this timeout when\n // `p` is finalized, so the JavaScript VM doesn't hang around waiting for the timer to\n // complete, once the test runner has finished executing the tests.\n const timeoutPromise = new Promise((_resolve, reject) => {\n const handle = timeout(() => {\n reject(new PromiseTimeoutError(msg));\n }, ms);\n p = p.finally(() => clearTimeout(handle));\n });\n return Promise.race([p, timeoutPromise]) as Promise<T>;\n}\n\n/**\n * Takes a promise `p` and returns a new one which rejects if `p` resolves or rejects,\n * and otherwise resolves after the specified time.\n */\nexport function assertNotSettledWithinTime(\n p: Promise<unknown>,\n ms: number,\n msg: string\n): Promise<undefined> {\n // Rejects regardless of whether p resolves or rejects.\n const rejectWhenSettled = p.then(() => Promise.reject(new Error(msg)));\n // Resolves after `ms` milliseconds.\n const timeoutPromise = new Promise<undefined>(resolve => {\n const handle = timeout(() => {\n resolve(undefined);\n }, ms);\n p.finally(() => clearTimeout(handle));\n });\n return Promise.race([rejectWhenSettled, timeoutPromise]);\n}\n\n/**\n * Returns a `Promise.reject()`, but also registers a dummy `.catch()` handler so it doesn't count\n * as an uncaught promise rejection in the runtime.\n */\nexport function rejectWithoutUncaught<T>(err: unknown): Promise<T> {\n const p = Promise.reject(err);\n // Suppress uncaught promise rejection.\n p.catch(() => {});\n return p;\n}\n\n/**\n * Makes a copy of a JS `object`, with the keys reordered into sorted order.\n */\nexport function sortObjectByKey(v: { [k: string]: unknown }): { [k: string]: unknown } {\n const sortedObject: { [k: string]: unknown } = {};\n for (const k of Object.keys(v).sort()) {\n sortedObject[k] = v[k];\n }\n return sortedObject;\n}\n\n/**\n * Determines whether two JS values are equal, recursing into objects and arrays.\n * NaN is treated specially, such that `objectEquals(NaN, NaN)`.\n */\nexport function objectEquals(x: unknown, y: unknown): boolean {\n if (typeof x !== 'object' || typeof y !== 'object') {\n if (typeof x === 'number' && typeof y === 'number' && Number.isNaN(x) && Number.isNaN(y)) {\n return true;\n }\n return x === y;\n }\n if (x === null || y === null) return x === y;\n if (x.constructor !== y.constructor) return false;\n if (x instanceof Function) return x === y;\n if (x instanceof RegExp) return x === y;\n if (x === y || x.valueOf() === y.valueOf()) return true;\n if (Array.isArray(x) && Array.isArray(y) && x.length !== y.length) return false;\n if (x instanceof Date) return false;\n if (!(x instanceof Object)) return false;\n if (!(y instanceof Object)) return false;\n\n const x1 = x as { [k: string]: unknown };\n const y1 = y as { [k: string]: unknown };\n const p = Object.keys(x);\n return Object.keys(y).every(i => p.indexOf(i) !== -1) && p.every(i => objectEquals(x1[i], y1[i]));\n}\n\n/**\n * Generates a range of values `fn(0)..fn(n-1)`.\n */\nexport function range<T>(n: number, fn: (i: number) => T): T[] {\n return [...new Array(n)].map((_, i) => fn(i));\n}\n\n/**\n * Generates a range of values `fn(0)..fn(n-1)`.\n */\nexport function* iterRange<T>(n: number, fn: (i: number) => T): Iterable<T> {\n for (let i = 0; i < n; ++i) {\n yield fn(i);\n }\n}\n\n/** Creates a (reusable) iterable object that maps `f` over `xs`, lazily. */\nexport function mapLazy<T, R>(xs: Iterable<T>, f: (x: T) => R): Iterable<R> {\n return {\n *[Symbol.iterator]() {\n for (const x of xs) {\n yield f(x);\n }\n },\n };\n}\n\nconst TypedArrayBufferViewInstances = [\n new Uint8Array(),\n new Uint8ClampedArray(),\n new Uint16Array(),\n new Uint32Array(),\n new Int8Array(),\n new Int16Array(),\n new Int32Array(),\n new Float16Array(),\n new Float32Array(),\n new Float64Array(),\n] as const;\n\nexport type TypedArrayBufferView = typeof TypedArrayBufferViewInstances[number];\n\nexport type TypedArrayBufferViewConstructor<\n A extends TypedArrayBufferView = TypedArrayBufferView\n> = {\n // Interface copied from Uint8Array, and made generic.\n readonly prototype: A;\n readonly BYTES_PER_ELEMENT: number;\n\n new (): A;\n new (elements: Iterable<number>): A;\n new (array: ArrayLike<number> | ArrayBufferLike): A;\n new (buffer: ArrayBufferLike, byteOffset?: number, length?: number): A;\n new (length: number): A;\n\n from(arrayLike: ArrayLike<number>): A;\n /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): A;\n /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n from<T>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => number, thisArg?: any): A;\n of(...items: number[]): A;\n};\n\nexport const kTypedArrayBufferViews: {\n readonly [k: string]: TypedArrayBufferViewConstructor;\n} = {\n ...(() => {\n /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n const result: { [k: string]: any } = {};\n for (const v of TypedArrayBufferViewInstances) {\n result[v.constructor.name] = v.constructor;\n }\n return result;\n })(),\n};\nexport const kTypedArrayBufferViewKeys = keysOf(kTypedArrayBufferViews);\nexport const kTypedArrayBufferViewConstructors = Object.values(kTypedArrayBufferViews);\n\nfunction subarrayAsU8(\n buf: ArrayBuffer | TypedArrayBufferView,\n { start = 0, length }: { start?: number; length?: number }\n): Uint8Array | Uint8ClampedArray {\n if (buf instanceof ArrayBuffer) {\n return new Uint8Array(buf, start, length);\n } else if (buf instanceof Uint8Array || buf instanceof Uint8ClampedArray) {\n // Don't wrap in new views if we don't need to.\n if (start === 0 && (length === undefined || length === buf.byteLength)) {\n return buf;\n }\n }\n const byteOffset = buf.byteOffset + start * buf.BYTES_PER_ELEMENT;\n const byteLength =\n length !== undefined\n ? length * buf.BYTES_PER_ELEMENT\n : buf.byteLength - (byteOffset - buf.byteOffset);\n return new Uint8Array(buf.buffer, byteOffset, byteLength);\n}\n\n/**\n * Copy a range of bytes from one ArrayBuffer or TypedArray to another.\n *\n * `start`/`length` are in elements (or in bytes, if ArrayBuffer).\n */\nexport function memcpy(\n src: { src: ArrayBuffer | TypedArrayBufferView; start?: number; length?: number },\n dst: { dst: ArrayBuffer | TypedArrayBufferView; start?: number }\n): void {\n subarrayAsU8(dst.dst, dst).set(subarrayAsU8(src.src, src));\n}\n"],"mappings":"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"}
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/wpt_reftest_wait.js b/testing/web-platform/mozilla/tests/webgpu/common/util/wpt_reftest_wait.js new file mode 100644 index 0000000000..c2fc1f596d --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/util/wpt_reftest_wait.js @@ -0,0 +1,25 @@ +/** +* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts +**/import { timeout } from './timeout.js'; // Copied from https://github.com/web-platform-tests/wpt/blob/master/common/reftest-wait.js + +/** + * Remove the `reftest-wait` class on the document element. + * The reftest runner will wait with taking a screenshot while + * this class is present. + * + * See https://web-platform-tests.org/writing-tests/reftests.html#controlling-when-comparison-occurs + */ +export function takeScreenshot() { + document.documentElement.classList.remove('reftest-wait'); +} + +/** + * Call `takeScreenshot()` after a delay of at least `ms` milliseconds. + * @param {number} ms - milliseconds + */ +export function takeScreenshotDelayed(ms) { + timeout(() => { + takeScreenshot(); + }, ms); +} +//# sourceMappingURL=wpt_reftest_wait.js.map
\ No newline at end of file diff --git a/testing/web-platform/mozilla/tests/webgpu/common/util/wpt_reftest_wait.js.map b/testing/web-platform/mozilla/tests/webgpu/common/util/wpt_reftest_wait.js.map new file mode 100644 index 0000000000..a231c5f611 --- /dev/null +++ b/testing/web-platform/mozilla/tests/webgpu/common/util/wpt_reftest_wait.js.map @@ -0,0 +1 @@ +{"version":3,"file":"wpt_reftest_wait.js","names":["timeout","takeScreenshot","document","documentElement","classList","remove","takeScreenshotDelayed","ms"],"sources":["../../../src/common/util/wpt_reftest_wait.ts"],"sourcesContent":["import { timeout } from './timeout.js';\n\n// Copied from https://github.com/web-platform-tests/wpt/blob/master/common/reftest-wait.js\n\n/**\n * Remove the `reftest-wait` class on the document element.\n * The reftest runner will wait with taking a screenshot while\n * this class is present.\n *\n * See https://web-platform-tests.org/writing-tests/reftests.html#controlling-when-comparison-occurs\n */\nexport function takeScreenshot() {\n document.documentElement.classList.remove('reftest-wait');\n}\n\n/**\n * Call `takeScreenshot()` after a delay of at least `ms` milliseconds.\n * @param {number} ms - milliseconds\n */\nexport function takeScreenshotDelayed(ms: number) {\n timeout(() => {\n takeScreenshot();\n }, ms);\n}\n"],"mappings":";AAAA;AAAA,GAAA,SAASA,OAAO,QAAQ,cAAc,CAAC,CAEvC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,cAAc,GAAG;EAC/BC,QAAQ,CAACC,eAAe,CAACC,SAAS,CAACC,MAAM,CAAC,cAAc,CAAC;AAC3D;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASC,qBAAqB,CAACC,EAAU,EAAE;EAChDP,OAAO,CAAC,MAAM;IACZC,cAAc,EAAE;EAClB,CAAC,EAAEM,EAAE,CAAC;AACR"}
\ No newline at end of file |