mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
WIP
This commit is contained in:
parent
e6c455c613
commit
777c935603
11 changed files with 339 additions and 225 deletions
|
@ -1,5 +1,7 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
import { core, primordials } from "ext:core/mod.js";
|
import { core, primordials } from "ext:core/mod.js";
|
||||||
import { escapeName, withPermissions } from "ext:cli/40_test_common.js";
|
import { escapeName, withPermissions } from "ext:cli/40_test_common.js";
|
||||||
|
|
||||||
|
@ -7,14 +9,18 @@ import { escapeName, withPermissions } from "ext:cli/40_test_common.js";
|
||||||
const {
|
const {
|
||||||
op_register_test_step,
|
op_register_test_step,
|
||||||
op_register_test,
|
op_register_test,
|
||||||
op_register_test_group,
|
op_test_group_register,
|
||||||
op_test_group_pop,
|
op_test_group_event_start,
|
||||||
op_register_test_group_lifecycle,
|
op_test_group_event_end,
|
||||||
op_register_test_run_fn,
|
op_register_test_run_fn,
|
||||||
op_test_event_step_result_failed,
|
op_test_event_step_result_failed,
|
||||||
op_test_event_step_result_ignored,
|
op_test_event_step_result_ignored,
|
||||||
op_test_event_step_result_ok,
|
op_test_event_step_result_ok,
|
||||||
op_test_event_step_wait,
|
op_test_event_step_wait,
|
||||||
|
op_test_event_start,
|
||||||
|
op_test_event_result_ok,
|
||||||
|
op_test_event_result_ignored,
|
||||||
|
op_test_event_result_failed,
|
||||||
op_test_get_origin,
|
op_test_get_origin,
|
||||||
} = core.ops;
|
} = core.ops;
|
||||||
const {
|
const {
|
||||||
|
@ -44,11 +50,11 @@ const DenoNs = globalThis.Deno;
|
||||||
* origin: string,
|
* origin: string,
|
||||||
* location: TestLocation,
|
* location: TestLocation,
|
||||||
* ignore: boolean,
|
* ignore: boolean,
|
||||||
* only: boolean.
|
* only: boolean,
|
||||||
* sanitizeOps: boolean,
|
* sanitizeOps: boolean,
|
||||||
* sanitizeResources: boolean,
|
* sanitizeResources: boolean,
|
||||||
* sanitizeExit: boolean,
|
* sanitizeExit: boolean,
|
||||||
* permissions: PermissionOptions,
|
* permissions: Deno.PermissionOptions,
|
||||||
* }} TestDescription
|
* }} TestDescription
|
||||||
*
|
*
|
||||||
* @typedef {{
|
* @typedef {{
|
||||||
|
@ -86,9 +92,9 @@ const DenoNs = globalThis.Deno;
|
||||||
* fn: BenchFunction
|
* fn: BenchFunction
|
||||||
* origin: string,
|
* origin: string,
|
||||||
* ignore: boolean,
|
* ignore: boolean,
|
||||||
* only: boolean.
|
* only: boolean,
|
||||||
* sanitizeExit: boolean,
|
* sanitizeExit: boolean,
|
||||||
* permissions: PermissionOptions,
|
* permissions: Deno.PermissionOptions,
|
||||||
* }} BenchDescription
|
* }} BenchDescription
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -149,7 +155,7 @@ function wrapOuter(fn, desc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function wrapInner(fn) {
|
function wrapInner(fn) {
|
||||||
/** @param desc {TestDescription | TestStepDescription} */
|
/** @param {TestDescription | TestStepDescription} desc */
|
||||||
return async function innerWrapped(desc) {
|
return async function innerWrapped(desc) {
|
||||||
function getRunningStepDescs() {
|
function getRunningStepDescs() {
|
||||||
const results = [];
|
const results = [];
|
||||||
|
@ -210,7 +216,16 @@ function wrapInner(fn) {
|
||||||
const registerTestIdRetBuf = new Uint32Array(1);
|
const registerTestIdRetBuf = new Uint32Array(1);
|
||||||
const registerTestIdRetBufU8 = new Uint8Array(registerTestIdRetBuf.buffer);
|
const registerTestIdRetBufU8 = new Uint8Array(registerTestIdRetBuf.buffer);
|
||||||
|
|
||||||
// As long as we're using one isolate per test, we can cache the origin since it won't change
|
const registerTestGroupIdRetBuf = new Uint32Array(1);
|
||||||
|
const registerTestGroupIdRetBufU8 = new Uint8Array(
|
||||||
|
registerTestGroupIdRetBuf.buffer,
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* As long as we're using one isolate per test, we can cache the origin
|
||||||
|
* since it won't change.
|
||||||
|
* @type {string | undefined}
|
||||||
|
*/
|
||||||
let cachedOrigin = undefined;
|
let cachedOrigin = undefined;
|
||||||
|
|
||||||
function testInner(
|
function testInner(
|
||||||
|
@ -384,7 +399,7 @@ function stepReportResult(desc, result, elapsed) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param desc {TestDescription | TestStepDescription} */
|
/** @param {TestDescription | TestStepDescription} desc */
|
||||||
function createTestContext(desc) {
|
function createTestContext(desc) {
|
||||||
let parent;
|
let parent;
|
||||||
let level;
|
let level;
|
||||||
|
@ -416,8 +431,8 @@ function createTestContext(desc) {
|
||||||
*/
|
*/
|
||||||
origin: desc.origin,
|
origin: desc.origin,
|
||||||
/**
|
/**
|
||||||
* @param nameOrFnOrOptions {string | TestStepDefinition | ((t: TestContext) => void | Promise<void>)}
|
* @param {string | TestStepDescription | ((t: TestContext) => void | Promise<void>)} nameOrFnOrOptions
|
||||||
* @param maybeFn {((t: TestContext) => void | Promise<void>) | undefined}
|
* @param {((t: TestContext) => void | Promise<void>) | undefined} maybeFn
|
||||||
*/
|
*/
|
||||||
async step(nameOrFnOrOptions, maybeFn) {
|
async step(nameOrFnOrOptions, maybeFn) {
|
||||||
if (MapPrototypeGet(testStates, desc.id).completed) {
|
if (MapPrototypeGet(testStates, desc.id).completed) {
|
||||||
|
@ -504,9 +519,8 @@ function createTestContext(desc) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap a user test function in one which returns a structured result.
|
* Wrap a user test function in one which returns a structured result.
|
||||||
* @template T {Function}
|
* @template {Function} T
|
||||||
* @param testFn {T}
|
* @param {TestDescription | TestStepDescription} desc
|
||||||
* @param desc {TestDescription | TestStepDescription}
|
|
||||||
* @returns {T}
|
* @returns {T}
|
||||||
*/
|
*/
|
||||||
function wrapTest(desc) {
|
function wrapTest(desc) {
|
||||||
|
@ -522,14 +536,34 @@ function wrapTest(desc) {
|
||||||
|
|
||||||
globalThis.Deno.test = test;
|
globalThis.Deno.test = test;
|
||||||
|
|
||||||
/** @typedef {{ name: string, fn: () => any, only: boolean, ignore: boolean }} BddTest */
|
/**
|
||||||
|
* @typedef {{
|
||||||
/** @typedef {() => unknown | Promise<unknown>} TestLifecycleFn */
|
* id: number,
|
||||||
|
* name: string,
|
||||||
/** @typedef {{ name: string, ignore: boolean, only: boolean, children: Array<TestGroup | BddTest>, beforeAll: TestLifecycleFn | null, afterAll: TestLifecycleFn | null, beforeEach: TestLifecycleFn | null, afterEach: TestLifecycleFn | null}} TestGroup */
|
* fn: () => any,
|
||||||
|
* only: boolean,
|
||||||
|
* ignore: boolean
|
||||||
|
* }} BddTest
|
||||||
|
*
|
||||||
|
* @typedef {() => unknown | Promise<unknown>} TestLifecycleFn
|
||||||
|
*
|
||||||
|
* @typedef {{
|
||||||
|
* id: number,
|
||||||
|
* name: string,
|
||||||
|
* ignore: boolean,
|
||||||
|
* only: boolean,
|
||||||
|
* children: Array<TestGroup | BddTest>,
|
||||||
|
* beforeAll: TestLifecycleFn | null,
|
||||||
|
* afterAll: TestLifecycleFn | null,
|
||||||
|
* beforeEach: TestLifecycleFn | null,
|
||||||
|
* afterEach: TestLifecycleFn | null
|
||||||
|
* }} TestGroup
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @type {TestGroup} */
|
||||||
const ROOT_TEST_GROUP = {
|
const ROOT_TEST_GROUP = {
|
||||||
name: "__<root>__",
|
id: 0,
|
||||||
|
name: "__DENO_TEST_ROOT__",
|
||||||
ignore: false,
|
ignore: false,
|
||||||
only: false,
|
only: false,
|
||||||
children: [],
|
children: [],
|
||||||
|
@ -538,6 +572,16 @@ const ROOT_TEST_GROUP = {
|
||||||
afterAll: null,
|
afterAll: null,
|
||||||
afterEach: null,
|
afterEach: null,
|
||||||
};
|
};
|
||||||
|
// No-op if we're not running in `deno test` subcommand.
|
||||||
|
if (typeof op_register_test === "function") {
|
||||||
|
op_test_group_register(
|
||||||
|
registerTestGroupIdRetBufU8,
|
||||||
|
ROOT_TEST_GROUP.name,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
ROOT_TEST_GROUP.id = registerTestGroupIdRetBuf[0];
|
||||||
|
}
|
||||||
|
|
||||||
/** @type {{ hasOnly: boolean, stack: TestGroup[], total: number }} */
|
/** @type {{ hasOnly: boolean, stack: TestGroup[], total: number }} */
|
||||||
const BDD_CONTEXT = {
|
const BDD_CONTEXT = {
|
||||||
hasOnly: false,
|
hasOnly: false,
|
||||||
|
@ -547,14 +591,16 @@ const BDD_CONTEXT = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} name
|
* @param {string} name
|
||||||
* @param {fn: () => any} fn
|
* @param {() => any} fn
|
||||||
* @param {boolean} ignore
|
* @param {boolean} ignore
|
||||||
* @param {boolean} only
|
* @param {boolean} only
|
||||||
*/
|
*/
|
||||||
function itInner(name, fn, ignore, only) {
|
function itInner(name, fn, ignore, only) {
|
||||||
// No-op if we're not running in `deno test` subcommand.
|
if (
|
||||||
if (typeof op_register_test !== "function") {
|
!ignore && BDD_CONTEXT.stack.length > 1 &&
|
||||||
return;
|
BDD_CONTEXT.stack.some((x) => x.ignore)
|
||||||
|
) {
|
||||||
|
ignore = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cachedOrigin == undefined) {
|
if (cachedOrigin == undefined) {
|
||||||
|
@ -577,12 +623,13 @@ function itInner(name, fn, ignore, only) {
|
||||||
|
|
||||||
/** @type {BddTest} */
|
/** @type {BddTest} */
|
||||||
const testDef = {
|
const testDef = {
|
||||||
|
id: 0,
|
||||||
name,
|
name,
|
||||||
fn: testFn,
|
fn: testFn,
|
||||||
ignore,
|
ignore,
|
||||||
only,
|
only,
|
||||||
};
|
};
|
||||||
BDD_CONTEXT.stack.at(-1).children.push(testDef);
|
getGroupParent().children.push(testDef);
|
||||||
BDD_CONTEXT.total++;
|
BDD_CONTEXT.total++;
|
||||||
|
|
||||||
op_register_test(
|
op_register_test(
|
||||||
|
@ -597,6 +644,8 @@ function itInner(name, fn, ignore, only) {
|
||||||
location.columnNumber,
|
location.columnNumber,
|
||||||
registerTestIdRetBufU8,
|
registerTestIdRetBufU8,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
testDef.id = registerTestIdRetBuf[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -623,6 +672,18 @@ it.ignore = (name, fn) => {
|
||||||
};
|
};
|
||||||
it.skip = it.ignore;
|
it.skip = it.ignore;
|
||||||
|
|
||||||
|
/** @type {(x: TestGroup | BddTest) => x is TestGroup} */
|
||||||
|
function isTestGroup(x) {
|
||||||
|
return "beforeAll" in x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {TestGroup}
|
||||||
|
*/
|
||||||
|
function getGroupParent() {
|
||||||
|
return /** @type {TestGroup} */ (BDD_CONTEXT.stack.at(-1));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} name
|
* @param {string} name
|
||||||
* @param {() => void} fn
|
* @param {() => void} fn
|
||||||
|
@ -635,9 +696,13 @@ function describeInner(name, fn, ignore, only) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const parent = BDD_CONTEXT.stack.at(-1);
|
op_test_group_register(registerTestGroupIdRetBufU8, name, false);
|
||||||
|
const id = registerTestGroupIdRetBuf[0];
|
||||||
|
|
||||||
|
const parent = getGroupParent();
|
||||||
/** @type {TestGroup} */
|
/** @type {TestGroup} */
|
||||||
const group = {
|
const group = {
|
||||||
|
id,
|
||||||
name,
|
name,
|
||||||
ignore,
|
ignore,
|
||||||
only,
|
only,
|
||||||
|
@ -653,6 +718,43 @@ function describeInner(name, fn, ignore, only) {
|
||||||
try {
|
try {
|
||||||
fn();
|
fn();
|
||||||
} finally {
|
} finally {
|
||||||
|
let allIgnore = true;
|
||||||
|
let onlyChildCount = 0;
|
||||||
|
|
||||||
|
for (let i = 0; i < group.children.length; i++) {
|
||||||
|
const child = group.children[i];
|
||||||
|
|
||||||
|
if (!child.ignore) allIgnore = false;
|
||||||
|
if (!isTestGroup(child) && child.only) {
|
||||||
|
onlyChildCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!group.ignore) {
|
||||||
|
group.ignore = allIgnore;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!group.ignore) {
|
||||||
|
if (onlyChildCount > 0) {
|
||||||
|
group.only = true;
|
||||||
|
|
||||||
|
if (onlyChildCount < group.children.length - 1) {
|
||||||
|
for (let i = 0; i < group.children.length; i++) {
|
||||||
|
const child = group.children[i];
|
||||||
|
|
||||||
|
if (!isTestGroup(child) && !child.only) {
|
||||||
|
child.ignore = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (group.only) {
|
||||||
|
for (let i = 0; i < group.children.length; i++) {
|
||||||
|
const child = group.children[i];
|
||||||
|
child.only = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BDD_CONTEXT.stack.pop();
|
BDD_CONTEXT.stack.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -685,27 +787,27 @@ describe.skip = describe.ignore;
|
||||||
* @param {() => any} fn
|
* @param {() => any} fn
|
||||||
*/
|
*/
|
||||||
function beforeAll(fn) {
|
function beforeAll(fn) {
|
||||||
BDD_CONTEXT.stack.at(-1).beforeAll = fn;
|
getGroupParent().beforeAll = fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {() => any} fn
|
* @param {() => any} fn
|
||||||
*/
|
*/
|
||||||
function afterAll(fn) {
|
function afterAll(fn) {
|
||||||
BDD_CONTEXT.stack.at(-1).afterAll = fn;
|
getGroupParent().afterAll = fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {() => any} fn
|
* @param {() => any} fn
|
||||||
*/
|
*/
|
||||||
function beforeEach(fn) {
|
function beforeEach(fn) {
|
||||||
BDD_CONTEXT.stack.at(-1).beforeEach = fn;
|
getGroupParent().beforeEach = fn;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @param {() => any} fn
|
* @param {() => any} fn
|
||||||
*/
|
*/
|
||||||
function afterEach(fn) {
|
function afterEach(fn) {
|
||||||
BDD_CONTEXT.stack.at(-1).afterEach = fn;
|
getGroupParent().afterEach = fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
globalThis.before = beforeAll;
|
globalThis.before = beforeAll;
|
||||||
|
@ -719,68 +821,109 @@ globalThis.describe = describe;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is called from Rust.
|
* This function is called from Rust.
|
||||||
* @param {bigint} seed
|
* @param {number} seed
|
||||||
* @param {...any} rest
|
* @param {...any} rest
|
||||||
*/
|
*/
|
||||||
async function runTests(seed, ...rest) {
|
async function runTests(seed, ...rest) {
|
||||||
|
if (BDD_CONTEXT.hasOnly) {
|
||||||
|
ROOT_TEST_GROUP.only = ROOT_TEST_GROUP.children.some((child) => child.only);
|
||||||
|
}
|
||||||
|
|
||||||
console.log("RUN TESTS", seed, rest, ROOT_TEST_GROUP);
|
console.log("RUN TESTS", seed, rest, ROOT_TEST_GROUP);
|
||||||
|
try {
|
||||||
// Filter tests
|
await runGroup(seed, ROOT_TEST_GROUP);
|
||||||
|
} finally {
|
||||||
await runGroup(seed, ROOT_TEST_GROUP);
|
//
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {bigint} seed
|
* @param {number} seed
|
||||||
* @param {TestGroup} group
|
* @param {TestGroup} group
|
||||||
*/
|
*/
|
||||||
async function runGroup(seed, group) {
|
async function runGroup(seed, group) {
|
||||||
// Bail out if group has no tests or sub groups
|
op_test_group_event_start(group.id);
|
||||||
|
|
||||||
/** @type {BddTest[]} */
|
if (seed > 0 && group.children.length > 1) {
|
||||||
const tests = [];
|
shuffle(group.children, seed);
|
||||||
/** @type {TestGroup[]} */
|
}
|
||||||
const groups = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < group.children[i]; i++) {
|
// Sort tests:
|
||||||
const child = group.children[i];
|
// - non-ignored tests first (might be shuffled earlier)
|
||||||
if ("beforeAll" in child) {
|
// - ignored tests second
|
||||||
groups.push(child);
|
// - groups last
|
||||||
} else {
|
group.children.sort(sortTestItems);
|
||||||
tests.push(child);
|
|
||||||
|
// Short circuit if the whole group is ignored
|
||||||
|
if (group.ignore) {
|
||||||
|
// FIXME
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (group.beforeAll !== null) {
|
||||||
|
await group.beforeAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < group.children.length; i++) {
|
||||||
|
const child = group.children[i];
|
||||||
|
|
||||||
|
if (group.beforeEach !== null) {
|
||||||
|
await group.beforeEach();
|
||||||
|
}
|
||||||
|
if (isTestGroup(child)) {
|
||||||
|
await runGroup(seed, child);
|
||||||
|
} else if (child.ignore) {
|
||||||
|
op_test_event_result_ignored(child.id);
|
||||||
|
} else {
|
||||||
|
op_test_event_start(child.id);
|
||||||
|
|
||||||
|
const start = DateNow();
|
||||||
|
try {
|
||||||
|
await child.fn();
|
||||||
|
const elapsed = DateNow() - start;
|
||||||
|
op_test_event_result_ok(child.id, elapsed);
|
||||||
|
} catch (err) {
|
||||||
|
const elapsed = DateNow() - start;
|
||||||
|
op_test_event_result_failed(child.id, elapsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (group.afterEach !== null) {
|
||||||
|
await group.afterEach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (group.afterAll !== null) {
|
||||||
|
await group.afterAll();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
op_test_group_event_end(group.id);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (seed > 0) {
|
/**
|
||||||
shuffle(tests, seed);
|
* @param {TestGroup | BddTest} a
|
||||||
shuffle(groups, seed);
|
* @param {TestGroup | BddTest} b
|
||||||
}
|
*/
|
||||||
|
function sortTestItems(a, b) {
|
||||||
|
const isAGroup = isTestGroup(a);
|
||||||
|
const isBGroup = isTestGroup(b);
|
||||||
|
if (isAGroup && isBGroup) return 0;
|
||||||
|
if (isAGroup && !isBGroup) return -1;
|
||||||
|
if (!isAGroup && isBGroup) return 1;
|
||||||
|
|
||||||
await group.beforeAll?.();
|
if (a.ignore && b.ignore) return 0;
|
||||||
|
if (a.ignore && !b.ignore) return -1;
|
||||||
|
if (!a.ignore && b.ignore) return 1;
|
||||||
|
|
||||||
for (let i = 0; i < tests.length; i++) {
|
return 0;
|
||||||
const test = tests[i];
|
|
||||||
|
|
||||||
await group.beforeEach?.();
|
|
||||||
await test.fn();
|
|
||||||
await group.afterEach?.();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < groups.length; i++) {
|
|
||||||
const childGroup = groups[i];
|
|
||||||
|
|
||||||
await group.beforeEach?.();
|
|
||||||
await runGroup(seed, childGroup);
|
|
||||||
await group.afterEach?.();
|
|
||||||
}
|
|
||||||
|
|
||||||
await group.afterAll?.();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @template T
|
* @template T
|
||||||
* @param {T[]} arr
|
* @param {T[]} arr
|
||||||
* @param {bigint} seed
|
* @param {number} seed
|
||||||
*/
|
*/
|
||||||
function shuffle(arr, seed) {
|
function shuffle(arr, seed) {
|
||||||
let m = arr.length;
|
let m = arr.length;
|
||||||
|
@ -788,13 +931,22 @@ function shuffle(arr, seed) {
|
||||||
let i;
|
let i;
|
||||||
|
|
||||||
while (m) {
|
while (m) {
|
||||||
i = Math.floor(seed * m--);
|
i = Math.floor(randomize(seed) * m--);
|
||||||
t = arr[m];
|
t = arr[m];
|
||||||
arr[m] = arr[i];
|
arr[m] = arr[i];
|
||||||
arr[i] = t;
|
arr[i] = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} seed
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
function randomize(seed) {
|
||||||
|
const x = Math.sin(seed++) * 10000;
|
||||||
|
return x - Math.floor(x);
|
||||||
|
}
|
||||||
|
|
||||||
// No-op if we're not running in `deno test` subcommand.
|
// No-op if we're not running in `deno test` subcommand.
|
||||||
if (typeof op_register_test === "function") {
|
if (typeof op_register_test === "function") {
|
||||||
op_register_test_run_fn(runTests);
|
op_register_test_run_fn(runTests);
|
||||||
|
|
|
@ -421,6 +421,7 @@ impl TestRun {
|
||||||
}
|
}
|
||||||
test::TestEvent::ForceEndReport => {}
|
test::TestEvent::ForceEndReport => {}
|
||||||
test::TestEvent::Sigint => {}
|
test::TestEvent::Sigint => {}
|
||||||
|
_ => {} // FIXME
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,9 @@ use crate::tools::test::TestDescription;
|
||||||
use crate::tools::test::TestEvent;
|
use crate::tools::test::TestEvent;
|
||||||
use crate::tools::test::TestEventSender;
|
use crate::tools::test::TestEventSender;
|
||||||
use crate::tools::test::TestFailure;
|
use crate::tools::test::TestFailure;
|
||||||
use crate::tools::test::TestGroup;
|
use crate::tools::test::TestGroupDescription;
|
||||||
use crate::tools::test::TestGroupLifecycleFn;
|
|
||||||
use crate::tools::test::TestLocation;
|
use crate::tools::test::TestLocation;
|
||||||
|
use crate::tools::test::TestResult;
|
||||||
use crate::tools::test::TestStepDescription;
|
use crate::tools::test::TestStepDescription;
|
||||||
use crate::tools::test::TestStepResult;
|
use crate::tools::test::TestStepResult;
|
||||||
|
|
||||||
|
@ -30,10 +30,14 @@ deno_core::extension!(deno_test,
|
||||||
op_restore_test_permissions,
|
op_restore_test_permissions,
|
||||||
op_register_test,
|
op_register_test,
|
||||||
op_register_test_step,
|
op_register_test_step,
|
||||||
op_register_test_group,
|
|
||||||
op_test_group_pop,
|
|
||||||
op_register_test_group_lifecycle,
|
|
||||||
op_register_test_run_fn,
|
op_register_test_run_fn,
|
||||||
|
op_test_group_register,
|
||||||
|
op_test_group_event_start,
|
||||||
|
op_test_group_event_end,
|
||||||
|
op_test_event_start,
|
||||||
|
op_test_event_result_ignored,
|
||||||
|
op_test_event_result_ok,
|
||||||
|
op_test_event_result_failed,
|
||||||
op_test_get_origin,
|
op_test_get_origin,
|
||||||
op_test_event_step_wait,
|
op_test_event_step_wait,
|
||||||
op_test_event_step_result_ok,
|
op_test_event_step_result_ok,
|
||||||
|
@ -93,7 +97,7 @@ pub fn op_restore_test_permissions(
|
||||||
}
|
}
|
||||||
|
|
||||||
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
|
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
|
||||||
static NEXT_GROUP_ID: AtomicUsize = AtomicUsize::new(1);
|
static NEXT_GROUP_ID: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
#[op2]
|
#[op2]
|
||||||
|
@ -120,7 +124,6 @@ fn op_register_test(
|
||||||
let origin = state.borrow::<ModuleSpecifier>().to_string();
|
let origin = state.borrow::<ModuleSpecifier>().to_string();
|
||||||
let description = TestDescription {
|
let description = TestDescription {
|
||||||
id,
|
id,
|
||||||
parent_id: 0,
|
|
||||||
name,
|
name,
|
||||||
ignore,
|
ignore,
|
||||||
only,
|
only,
|
||||||
|
@ -140,35 +143,37 @@ fn op_register_test(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
fn op_register_test_group(
|
fn op_test_group_register(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
|
#[buffer] ret_buf: &mut [u8],
|
||||||
#[string] name: String,
|
#[string] name: String,
|
||||||
ignore: bool,
|
is_root: bool,
|
||||||
only: bool,
|
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
let id = NEXT_GROUP_ID.fetch_add(1, Ordering::SeqCst);
|
let id = NEXT_GROUP_ID.fetch_add(1, Ordering::SeqCst);
|
||||||
let container = state.borrow_mut::<TestContainer>();
|
let sender = state.borrow_mut::<TestEventSender>();
|
||||||
|
let description = TestGroupDescription { id, name, is_root };
|
||||||
let group = TestGroup {
|
sender.send(TestEvent::GroupRegister(description)).ok();
|
||||||
id,
|
ret_buf.copy_from_slice(&(id as u32).to_le_bytes());
|
||||||
parent_id: 0,
|
|
||||||
name,
|
|
||||||
ignore,
|
|
||||||
only,
|
|
||||||
children: vec![],
|
|
||||||
after_all: None,
|
|
||||||
after_each: None,
|
|
||||||
before_all: None,
|
|
||||||
before_each: None,
|
|
||||||
};
|
|
||||||
container.register_group(group);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
fn op_test_group_pop(state: &mut OpState) -> Result<(), AnyError> {
|
fn op_test_group_event_start(
|
||||||
let container = state.borrow_mut::<TestContainer>();
|
state: &mut OpState,
|
||||||
container.group_pop();
|
#[smi] id: usize,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
let sender = state.borrow_mut::<TestEventSender>();
|
||||||
|
sender.send(TestEvent::GroupWait(id)).ok();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
fn op_test_group_event_end(
|
||||||
|
state: &mut OpState,
|
||||||
|
#[smi] id: usize,
|
||||||
|
) -> Result<(), AnyError> {
|
||||||
|
let sender = state.borrow_mut::<TestEventSender>();
|
||||||
|
sender.send(TestEvent::GroupResult(id)).ok();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,43 +187,6 @@ fn op_register_test_run_fn(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
|
||||||
#[op2]
|
|
||||||
fn op_register_test_group_lifecycle(
|
|
||||||
state: &mut OpState,
|
|
||||||
#[smi] kind: u32,
|
|
||||||
#[global] function: v8::Global<v8::Function>,
|
|
||||||
#[string] file_name: String,
|
|
||||||
#[smi] line_number: u32,
|
|
||||||
#[smi] column_number: u32,
|
|
||||||
) -> Result<(), AnyError> {
|
|
||||||
let container = state.borrow_mut::<TestContainer>();
|
|
||||||
|
|
||||||
let lifecycle = TestGroupLifecycleFn {
|
|
||||||
function,
|
|
||||||
location: TestLocation {
|
|
||||||
column_number,
|
|
||||||
line_number,
|
|
||||||
file_name,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Keep in sync with the JS side
|
|
||||||
if let Some(last_id) = container.stack.last() {
|
|
||||||
let last: &mut TestGroup =
|
|
||||||
container.groups.get_mut::<usize>(*last_id).unwrap();
|
|
||||||
match kind {
|
|
||||||
1 => last.before_all = Some(lifecycle),
|
|
||||||
2 => last.before_each = Some(lifecycle),
|
|
||||||
3 => last.after_all = Some(lifecycle),
|
|
||||||
4 => last.after_each = Some(lifecycle),
|
|
||||||
_ => panic!("Unknown test group lifecycle kind"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[string]
|
#[string]
|
||||||
fn op_test_get_origin(state: &mut OpState) -> String {
|
fn op_test_get_origin(state: &mut OpState) -> String {
|
||||||
|
@ -260,6 +228,46 @@ fn op_register_test_step(
|
||||||
Ok(id)
|
Ok(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
fn op_test_event_start(state: &mut OpState, #[smi] id: usize) {
|
||||||
|
let sender = state.borrow_mut::<TestEventSender>();
|
||||||
|
sender.send(TestEvent::Wait(id)).ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
fn op_test_event_result_ignored(state: &mut OpState, #[smi] id: usize) {
|
||||||
|
let sender = state.borrow_mut::<TestEventSender>();
|
||||||
|
sender
|
||||||
|
.send(TestEvent::Result(id, TestResult::Ignored, 0))
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
fn op_test_event_result_ok(
|
||||||
|
state: &mut OpState,
|
||||||
|
#[smi] id: usize,
|
||||||
|
#[smi] duration: u64,
|
||||||
|
) {
|
||||||
|
let sender = state.borrow_mut::<TestEventSender>();
|
||||||
|
sender
|
||||||
|
.send(TestEvent::Result(id, TestResult::Ok, duration))
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
fn op_test_event_result_failed(
|
||||||
|
state: &mut OpState,
|
||||||
|
#[smi] id: usize,
|
||||||
|
#[smi] duration: u64,
|
||||||
|
) {
|
||||||
|
// FIXME: Placeholder
|
||||||
|
let failure = TestFailure::IncompleteSteps;
|
||||||
|
let sender = state.borrow_mut::<TestEventSender>();
|
||||||
|
sender
|
||||||
|
.send(TestEvent::Result(id, TestResult::Failed(failure), duration))
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
fn op_test_event_step_wait(state: &mut OpState, #[smi] id: usize) {
|
fn op_test_event_step_wait(state: &mut OpState, #[smi] id: usize) {
|
||||||
let sender = state.borrow_mut::<TestEventSender>();
|
let sender = state.borrow_mut::<TestEventSender>();
|
||||||
|
|
|
@ -226,34 +226,15 @@ pub(crate) struct TestContainer {
|
||||||
has_tests: bool,
|
has_tests: bool,
|
||||||
pub run_fn: Option<v8::Global<v8::Function>>,
|
pub run_fn: Option<v8::Global<v8::Function>>,
|
||||||
pub has_only: bool,
|
pub has_only: bool,
|
||||||
pub groups: Vec<TestGroup>,
|
|
||||||
pub stack: Vec<usize>,
|
|
||||||
pub tests: (TestDescriptions, Vec<v8::Global<v8::Function>>),
|
pub tests: (TestDescriptions, Vec<v8::Global<v8::Function>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestContainer {
|
impl TestContainer {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let root = TestGroup {
|
|
||||||
id: 0,
|
|
||||||
parent_id: 0,
|
|
||||||
children: vec![],
|
|
||||||
ignore: false,
|
|
||||||
name: "<root>".to_string(),
|
|
||||||
only: false,
|
|
||||||
after_all: None,
|
|
||||||
after_each: None,
|
|
||||||
before_all: None,
|
|
||||||
before_each: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let stack = vec![root.id];
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
has_tests: false,
|
has_tests: false,
|
||||||
run_fn: None,
|
run_fn: None,
|
||||||
groups: vec![root],
|
|
||||||
has_only: false,
|
has_only: false,
|
||||||
stack,
|
|
||||||
tests: (
|
tests: (
|
||||||
TestDescriptions {
|
TestDescriptions {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -265,7 +246,7 @@ impl TestContainer {
|
||||||
|
|
||||||
pub fn register(
|
pub fn register(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut description: TestDescription,
|
description: TestDescription,
|
||||||
function: v8::Global<v8::Function>,
|
function: v8::Global<v8::Function>,
|
||||||
) {
|
) {
|
||||||
self.has_tests = true;
|
self.has_tests = true;
|
||||||
|
@ -274,35 +255,10 @@ impl TestContainer {
|
||||||
self.has_only = true
|
self.has_only = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(last_id) = self.stack.last() {
|
|
||||||
description.parent_id = *last_id;
|
|
||||||
|
|
||||||
let last: &mut TestGroup =
|
|
||||||
self.groups.get_mut::<usize>(*last_id).unwrap();
|
|
||||||
last.children.push(TestGroupChild::Test(description.id));
|
|
||||||
}
|
|
||||||
|
|
||||||
self.tests.0.tests.insert(description.id, description);
|
self.tests.0.tests.insert(description.id, description);
|
||||||
self.tests.1.push(function);
|
self.tests.1.push(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_group(&mut self, mut group: TestGroup) {
|
|
||||||
if let Some(last_id) = self.stack.last() {
|
|
||||||
group.parent_id = *last_id;
|
|
||||||
|
|
||||||
let last: &mut TestGroup =
|
|
||||||
self.groups.get_mut::<usize>(*last_id).unwrap();
|
|
||||||
last.children.push(TestGroupChild::Group(group.id));
|
|
||||||
}
|
|
||||||
|
|
||||||
self.stack.push(group.id);
|
|
||||||
self.groups.push(group);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn group_pop(&mut self) {
|
|
||||||
self.stack.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.has_tests
|
self.has_tests
|
||||||
}
|
}
|
||||||
|
@ -336,7 +292,6 @@ impl<'a> IntoIterator for &'a TestDescriptions {
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct TestDescription {
|
pub struct TestDescription {
|
||||||
pub id: usize,
|
pub id: usize,
|
||||||
pub parent_id: usize,
|
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub ignore: bool,
|
pub ignore: bool,
|
||||||
pub only: bool,
|
pub only: bool,
|
||||||
|
@ -346,6 +301,14 @@ pub struct TestDescription {
|
||||||
pub sanitize_resources: bool,
|
pub sanitize_resources: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Deserialize, Eq, Hash)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct TestGroupDescription {
|
||||||
|
pub id: usize,
|
||||||
|
pub name: String,
|
||||||
|
pub is_root: bool,
|
||||||
|
}
|
||||||
|
|
||||||
/// May represent a failure of a test or test step.
|
/// May represent a failure of a test or test step.
|
||||||
#[derive(Debug, Clone, PartialEq, Deserialize, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Deserialize, Eq, Hash)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
@ -367,32 +330,6 @@ impl From<&TestDescription> for TestFailureDescription {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct TestGroupLifecycleFn {
|
|
||||||
pub function: v8::Global<v8::Function>,
|
|
||||||
pub location: TestLocation,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
|
||||||
pub struct TestGroup {
|
|
||||||
pub id: usize,
|
|
||||||
pub parent_id: usize,
|
|
||||||
pub name: String,
|
|
||||||
pub ignore: bool,
|
|
||||||
pub only: bool,
|
|
||||||
pub children: Vec<TestGroupChild>,
|
|
||||||
pub before_all: Option<TestGroupLifecycleFn>,
|
|
||||||
pub before_each: Option<TestGroupLifecycleFn>,
|
|
||||||
pub after_all: Option<TestGroupLifecycleFn>,
|
|
||||||
pub after_each: Option<TestGroupLifecycleFn>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum TestGroupChild {
|
|
||||||
Group(usize),
|
|
||||||
Test(usize),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, PartialEq)]
|
#[derive(Debug, Default, Clone, PartialEq)]
|
||||||
pub struct TestFailureFormatOptions {
|
pub struct TestFailureFormatOptions {
|
||||||
pub hide_stacktraces: bool,
|
pub hide_stacktraces: bool,
|
||||||
|
@ -561,6 +498,9 @@ pub enum TestStdioStream {
|
||||||
pub enum TestEvent {
|
pub enum TestEvent {
|
||||||
Register(Arc<TestDescriptions>),
|
Register(Arc<TestDescriptions>),
|
||||||
Plan(TestPlan),
|
Plan(TestPlan),
|
||||||
|
GroupRegister(TestGroupDescription),
|
||||||
|
GroupWait(usize),
|
||||||
|
GroupResult(usize),
|
||||||
Wait(usize),
|
Wait(usize),
|
||||||
Output(Vec<u8>),
|
Output(Vec<u8>),
|
||||||
Slow(usize, u64),
|
Slow(usize, u64),
|
||||||
|
@ -881,12 +821,6 @@ pub fn send_test_event(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum TestRunItem {
|
|
||||||
Lifecycle(usize),
|
|
||||||
Group(usize),
|
|
||||||
Test(usize),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn run_tests_for_worker(
|
pub async fn run_tests_for_worker(
|
||||||
worker: &mut MainWorker,
|
worker: &mut MainWorker,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
|
@ -898,9 +832,9 @@ pub async fn run_tests_for_worker(
|
||||||
let tc =
|
let tc =
|
||||||
std::mem::take(&mut *state_rc.borrow_mut().borrow_mut::<TestContainer>());
|
std::mem::take(&mut *state_rc.borrow_mut().borrow_mut::<TestContainer>());
|
||||||
|
|
||||||
eprintln!("{:#?}", tc.stack);
|
let tests: Arc<TestDescriptions> = tc.tests.0.into();
|
||||||
|
send_test_event(&state_rc, TestEvent::Register(tests.clone()))?;
|
||||||
|
|
||||||
let to_run: Vec<TestRunItem> = vec![];
|
|
||||||
if let Some(function) = &tc.run_fn {
|
if let Some(function) = &tc.run_fn {
|
||||||
let seed = if let Some(seed) = options.shuffle {
|
let seed = if let Some(seed) = options.shuffle {
|
||||||
seed
|
seed
|
||||||
|
@ -911,14 +845,16 @@ pub async fn run_tests_for_worker(
|
||||||
let args = {
|
let args = {
|
||||||
let scope = &mut worker.js_runtime.handle_scope();
|
let scope = &mut worker.js_runtime.handle_scope();
|
||||||
let seed_value: v8::Local<v8::Value> =
|
let seed_value: v8::Local<v8::Value> =
|
||||||
v8::BigInt::new_from_u64(scope, seed as u64).into();
|
v8::Number::new(scope, seed as f64).into();
|
||||||
[v8::Global::new(scope, seed_value)]
|
[v8::Global::new(scope, seed_value)]
|
||||||
};
|
};
|
||||||
let call = worker.js_runtime.call_with_args(&function, &args);
|
let call = worker.js_runtime.call_with_args(&function, &args);
|
||||||
|
// FIXME: result
|
||||||
let result = worker
|
let result = worker
|
||||||
.js_runtime
|
.js_runtime
|
||||||
.with_event_loop_promise(call, PollEventLoopOptions::default())
|
.with_event_loop_promise(call, PollEventLoopOptions::default())
|
||||||
.await;
|
.await;
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(seed) = options.shuffle {
|
if let Some(seed) = options.shuffle {
|
||||||
|
@ -926,11 +862,7 @@ pub async fn run_tests_for_worker(
|
||||||
}
|
}
|
||||||
// FILTER
|
// FILTER
|
||||||
|
|
||||||
eprintln!("sorted, {:#?}", tc.stack);
|
|
||||||
|
|
||||||
let test_functions = tc.tests.1;
|
let test_functions = tc.tests.1;
|
||||||
let tests: Arc<TestDescriptions> = tc.tests.0.into();
|
|
||||||
send_test_event(&state_rc, TestEvent::Register(tests.clone()))?;
|
|
||||||
let res = run_tests_for_worker_inner(
|
let res = run_tests_for_worker_inner(
|
||||||
worker,
|
worker,
|
||||||
specifier,
|
specifier,
|
||||||
|
@ -1401,6 +1333,9 @@ pub async fn report_tests(
|
||||||
|
|
||||||
while let Some((_, event)) = receiver.recv().await {
|
while let Some((_, event)) = receiver.recv().await {
|
||||||
match event {
|
match event {
|
||||||
|
TestEvent::GroupRegister(description) => {
|
||||||
|
reporter.report_register_group(&description);
|
||||||
|
}
|
||||||
TestEvent::Register(description) => {
|
TestEvent::Register(description) => {
|
||||||
for (_, description) in description.into_iter() {
|
for (_, description) in description.into_iter() {
|
||||||
reporter.report_register(description);
|
reporter.report_register(description);
|
||||||
|
@ -1489,6 +1424,7 @@ pub async fn report_tests(
|
||||||
}
|
}
|
||||||
std::process::exit(130);
|
std::process::exit(130);
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,12 @@ impl CompoundTestReporter {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestReporter for CompoundTestReporter {
|
impl TestReporter for CompoundTestReporter {
|
||||||
|
fn report_register_group(&mut self, description: &TestGroupDescription) {
|
||||||
|
for reporter in &mut self.test_reporters {
|
||||||
|
reporter.report_register_group(description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn report_register(&mut self, description: &TestDescription) {
|
fn report_register(&mut self, description: &TestDescription) {
|
||||||
for reporter in &mut self.test_reporters {
|
for reporter in &mut self.test_reporters {
|
||||||
reporter.report_register(description);
|
reporter.report_register(description);
|
||||||
|
|
|
@ -88,6 +88,7 @@ fn fmt_cancelled() -> String {
|
||||||
|
|
||||||
#[allow(clippy::print_stdout)]
|
#[allow(clippy::print_stdout)]
|
||||||
impl TestReporter for DotTestReporter {
|
impl TestReporter for DotTestReporter {
|
||||||
|
fn report_register_group(&mut self, _description: &TestGroupDescription) {}
|
||||||
fn report_register(&mut self, _description: &TestDescription) {}
|
fn report_register(&mut self, _description: &TestDescription) {}
|
||||||
|
|
||||||
fn report_plan(&mut self, plan: &TestPlan) {
|
fn report_plan(&mut self, plan: &TestPlan) {
|
||||||
|
|
|
@ -80,6 +80,8 @@ impl JunitTestReporter {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestReporter for JunitTestReporter {
|
impl TestReporter for JunitTestReporter {
|
||||||
|
fn report_register_group(&mut self, _description: &TestGroupDescription) {}
|
||||||
|
|
||||||
fn report_register(&mut self, description: &TestDescription) {
|
fn report_register(&mut self, description: &TestDescription) {
|
||||||
let mut case = quick_junit::TestCase::new(
|
let mut case = quick_junit::TestCase::new(
|
||||||
description.name.clone(),
|
description.name.clone(),
|
||||||
|
|
|
@ -17,6 +17,7 @@ pub use tap::TapTestReporter;
|
||||||
|
|
||||||
pub trait TestReporter {
|
pub trait TestReporter {
|
||||||
fn report_register(&mut self, description: &TestDescription);
|
fn report_register(&mut self, description: &TestDescription);
|
||||||
|
fn report_register_group(&mut self, description: &TestGroupDescription);
|
||||||
fn report_plan(&mut self, plan: &TestPlan);
|
fn report_plan(&mut self, plan: &TestPlan);
|
||||||
fn report_wait(&mut self, description: &TestDescription);
|
fn report_wait(&mut self, description: &TestDescription);
|
||||||
fn report_slow(&mut self, description: &TestDescription, elapsed: u64);
|
fn report_slow(&mut self, description: &TestDescription, elapsed: u64);
|
||||||
|
|
|
@ -167,6 +167,8 @@ impl PrettyTestReporter {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestReporter for PrettyTestReporter {
|
impl TestReporter for PrettyTestReporter {
|
||||||
|
fn report_register_group(&mut self, _description: &TestGroupDescription) {}
|
||||||
|
|
||||||
fn report_register(&mut self, _description: &TestDescription) {}
|
fn report_register(&mut self, _description: &TestDescription) {}
|
||||||
fn report_plan(&mut self, plan: &TestPlan) {
|
fn report_plan(&mut self, plan: &TestPlan) {
|
||||||
self.write_output_end();
|
self.write_output_end();
|
||||||
|
|
|
@ -123,6 +123,7 @@ impl TapTestReporter {
|
||||||
|
|
||||||
#[allow(clippy::print_stdout)]
|
#[allow(clippy::print_stdout)]
|
||||||
impl TestReporter for TapTestReporter {
|
impl TestReporter for TapTestReporter {
|
||||||
|
fn report_register_group(&mut self, _description: &TestGroupDescription) {}
|
||||||
fn report_register(&mut self, _description: &TestDescription) {}
|
fn report_register(&mut self, _description: &TestDescription) {}
|
||||||
|
|
||||||
fn report_plan(&mut self, plan: &TestPlan) {
|
fn report_plan(&mut self, plan: &TestPlan) {
|
||||||
|
|
|
@ -476,6 +476,10 @@ const NOT_IMPORTED_OPS = [
|
||||||
"op_test_event_step_result_ignored",
|
"op_test_event_step_result_ignored",
|
||||||
"op_test_event_step_result_ok",
|
"op_test_event_step_result_ok",
|
||||||
"op_test_event_step_wait",
|
"op_test_event_step_wait",
|
||||||
|
"op_test_event_start",
|
||||||
|
"op_test_event_result_ignored",
|
||||||
|
"op_test_event_result_ok",
|
||||||
|
"op_test_event_result_failed",
|
||||||
"op_test_op_sanitizer_collect",
|
"op_test_op_sanitizer_collect",
|
||||||
"op_test_op_sanitizer_finish",
|
"op_test_op_sanitizer_finish",
|
||||||
"op_test_op_sanitizer_get_async_message",
|
"op_test_op_sanitizer_get_async_message",
|
||||||
|
@ -483,9 +487,9 @@ const NOT_IMPORTED_OPS = [
|
||||||
"op_restore_test_permissions",
|
"op_restore_test_permissions",
|
||||||
"op_register_test_step",
|
"op_register_test_step",
|
||||||
"op_register_test",
|
"op_register_test",
|
||||||
"op_register_test_group",
|
"op_test_group_register",
|
||||||
"op_test_group_pop",
|
"op_test_group_event_start",
|
||||||
"op_register_test_group_lifecycle",
|
"op_test_group_event_end",
|
||||||
"op_register_test_run_fn",
|
"op_register_test_run_fn",
|
||||||
"op_test_get_origin",
|
"op_test_get_origin",
|
||||||
"op_pledge_test_permissions",
|
"op_pledge_test_permissions",
|
||||||
|
|
Loading…
Reference in a new issue