|
/** |
|
* @effectionx/k6 Conformance Test Bundle |
|
* |
|
* This file is auto-generated by build.js |
|
* Do not edit directly. |
|
* |
|
* Run with: k6 run conformance-bundle.js |
|
*/ |
|
|
|
|
|
// conformance/k6-runner.ts |
|
import { check } from "k6"; |
|
|
|
// conformance/01-symbols.ts |
|
function testSymbols() { |
|
const checks = []; |
|
try { |
|
if (typeof Symbol !== "function") { |
|
return { |
|
pass: false, |
|
message: "Symbol constructor does not exist" |
|
}; |
|
} |
|
checks.push("Symbol constructor exists"); |
|
if (typeof Symbol.iterator !== "symbol") { |
|
return { |
|
pass: false, |
|
message: "Symbol.iterator is not a symbol", |
|
details: `typeof Symbol.iterator = ${typeof Symbol.iterator}` |
|
}; |
|
} |
|
checks.push("Symbol.iterator is a symbol"); |
|
if (typeof Symbol.toStringTag !== "symbol") { |
|
return { |
|
pass: false, |
|
message: "Symbol.toStringTag is not a symbol", |
|
details: `typeof Symbol.toStringTag = ${typeof Symbol.toStringTag}` |
|
}; |
|
} |
|
checks.push("Symbol.toStringTag is a symbol"); |
|
const customSymbol = Symbol("test"); |
|
if (typeof customSymbol !== "symbol") { |
|
return { |
|
pass: false, |
|
message: "Cannot create custom symbols" |
|
}; |
|
} |
|
checks.push("Custom symbol creation works"); |
|
const obj = {}; |
|
obj[customSymbol] = "value"; |
|
if (obj[customSymbol] !== "value") { |
|
return { |
|
pass: false, |
|
message: "Symbols do not work as object keys" |
|
}; |
|
} |
|
checks.push("Symbols work as object keys"); |
|
const globalSym1 = Symbol.for("global.test"); |
|
const globalSym2 = Symbol.for("global.test"); |
|
if (!Object.is(globalSym1, globalSym2)) { |
|
return { |
|
pass: false, |
|
message: "Symbol.for does not return same symbol for same key" |
|
}; |
|
} |
|
checks.push("Symbol.for works correctly"); |
|
return { |
|
pass: true, |
|
message: "Full Symbol support confirmed", |
|
details: checks.join("; ") |
|
}; |
|
} catch (error) { |
|
return { |
|
pass: false, |
|
message: `Symbol test threw error: ${error instanceof Error ? error.message : String(error)}` |
|
}; |
|
} |
|
} |
|
|
|
// conformance/02-generators.ts |
|
function testGenerators() { |
|
const checks = []; |
|
try { |
|
function* basicGenerator() { |
|
yield 1; |
|
yield 2; |
|
yield 3; |
|
return "done"; |
|
} |
|
const gen = basicGenerator(); |
|
checks.push("Generator function syntax works"); |
|
let result = gen.next(); |
|
if (result.value !== 1 || result.done !== false) { |
|
return { |
|
pass: false, |
|
message: "First yield did not return expected value", |
|
details: `Expected {value: 1, done: false}, got ${JSON.stringify(result)}` |
|
}; |
|
} |
|
result = gen.next(); |
|
if (result.value !== 2) { |
|
return { |
|
pass: false, |
|
message: "Second yield did not return expected value" |
|
}; |
|
} |
|
result = gen.next(); |
|
if (result.value !== 3) { |
|
return { |
|
pass: false, |
|
message: "Third yield did not return expected value" |
|
}; |
|
} |
|
checks.push("yield returns values correctly"); |
|
result = gen.next(); |
|
if (result.done !== true || result.value !== "done") { |
|
return { |
|
pass: false, |
|
message: "Generator return value not received", |
|
details: `Expected {value: "done", done: true}, got ${JSON.stringify(result)}` |
|
}; |
|
} |
|
checks.push("Generator return value works"); |
|
function* returnableGen() { |
|
yield 1; |
|
yield 2; |
|
yield 3; |
|
return "completed"; |
|
} |
|
const gen2 = returnableGen(); |
|
gen2.next(); |
|
const returnResult = gen2.return("early"); |
|
if (returnResult.done !== true || returnResult.value !== "early") { |
|
return { |
|
pass: false, |
|
message: "Generator return() method did not work correctly", |
|
details: `Expected {value: "early", done: true}, got ${JSON.stringify(returnResult)}` |
|
}; |
|
} |
|
checks.push("Generator return() method works"); |
|
function* throwableGen() { |
|
try { |
|
yield 1; |
|
yield 2; |
|
} catch (_e) { |
|
yield 99; |
|
} |
|
} |
|
const gen3 = throwableGen(); |
|
gen3.next(); |
|
const throwResult = gen3.throw(new Error("test error")); |
|
if (throwResult.value !== 99) { |
|
return { |
|
pass: false, |
|
message: "Generator throw() method did not trigger catch block", |
|
details: `Expected yield 99, got ${JSON.stringify(throwResult)}` |
|
}; |
|
} |
|
checks.push("Generator throw() method works"); |
|
function* iterableGen() { |
|
yield 1; |
|
yield 2; |
|
yield 3; |
|
} |
|
const values = []; |
|
for (const v of iterableGen()) { |
|
values.push(v); |
|
} |
|
if (values.length !== 3 || values[0] !== 1 || values[2] !== 3) { |
|
return { |
|
pass: false, |
|
message: "for...of iteration did not work", |
|
details: `Expected [1,2,3], got ${JSON.stringify(values)}` |
|
}; |
|
} |
|
checks.push("for...of iteration works"); |
|
return { |
|
pass: true, |
|
message: "Full generator support confirmed", |
|
details: checks.join("; ") |
|
}; |
|
} catch (error) { |
|
return { |
|
pass: false, |
|
message: `Generator test threw error: ${error instanceof Error ? error.message : String(error)}` |
|
}; |
|
} |
|
} |
|
|
|
// conformance/03-yield-delegation.ts |
|
function testYieldDelegation() { |
|
const checks = []; |
|
try { |
|
let createOperation2 = function(value) { |
|
return { |
|
*[Symbol.iterator]() { |
|
yield 10; |
|
yield 20; |
|
return value; |
|
} |
|
}; |
|
}; |
|
var createOperation = createOperation2; |
|
function* inner() { |
|
yield 1; |
|
yield 2; |
|
return "inner-done"; |
|
} |
|
function* outer() { |
|
const result2 = yield* inner(); |
|
yield 3; |
|
return result2; |
|
} |
|
const gen = outer(); |
|
const values = []; |
|
let result = gen.next(); |
|
while (!result.done) { |
|
values.push(result.value); |
|
result = gen.next(); |
|
} |
|
if (values.length !== 3 || values[0] !== 1 || values[1] !== 2 || values[2] !== 3) { |
|
return { |
|
pass: false, |
|
message: "yield* did not delegate values correctly", |
|
details: `Expected [1,2,3], got ${JSON.stringify(values)}` |
|
}; |
|
} |
|
if (result.value !== "inner-done") { |
|
return { |
|
pass: false, |
|
message: "yield* did not propagate return value", |
|
details: `Expected "inner-done", got ${JSON.stringify(result.value)}` |
|
}; |
|
} |
|
checks.push("yield* delegates to generators and propagates return value"); |
|
function* useOperation() { |
|
const result2 = yield* createOperation2("operation-result"); |
|
yield 30; |
|
return result2; |
|
} |
|
const opGen = useOperation(); |
|
const opValues = []; |
|
let opResult = opGen.next(); |
|
while (!opResult.done) { |
|
opValues.push(opResult.value); |
|
opResult = opGen.next(); |
|
} |
|
if (opValues.length !== 3 || opValues[0] !== 10 || opValues[1] !== 20 || opValues[2] !== 30) { |
|
return { |
|
pass: false, |
|
message: "yield* did not delegate to custom iterable", |
|
details: `Expected [10,20,30], got ${JSON.stringify(opValues)}` |
|
}; |
|
} |
|
if (opResult.value !== "operation-result") { |
|
return { |
|
pass: false, |
|
message: "yield* did not propagate return value from custom iterable", |
|
details: `Expected "operation-result", got ${JSON.stringify(opResult.value)}` |
|
}; |
|
} |
|
checks.push("yield* works with custom [Symbol.iterator] objects"); |
|
function* level3() { |
|
yield "L3"; |
|
return 3; |
|
} |
|
function* level2() { |
|
yield "L2-before"; |
|
const result2 = yield* level3(); |
|
yield "L2-after"; |
|
return result2 + 2; |
|
} |
|
function* level1() { |
|
yield "L1-before"; |
|
const result2 = yield* level2(); |
|
yield "L1-after"; |
|
return result2 + 1; |
|
} |
|
const nestedGen = level1(); |
|
const nestedValues = []; |
|
let nestedResult = nestedGen.next(); |
|
while (!nestedResult.done) { |
|
nestedValues.push(nestedResult.value); |
|
nestedResult = nestedGen.next(); |
|
} |
|
const expectedNested = [ |
|
"L1-before", |
|
"L2-before", |
|
"L3", |
|
"L2-after", |
|
"L1-after" |
|
]; |
|
if (JSON.stringify(nestedValues) !== JSON.stringify(expectedNested)) { |
|
return { |
|
pass: false, |
|
message: "Nested yield* delegation order incorrect", |
|
details: `Expected ${JSON.stringify(expectedNested)}, got ${JSON.stringify(nestedValues)}` |
|
}; |
|
} |
|
if (nestedResult.value !== 6) { |
|
return { |
|
pass: false, |
|
message: "Nested yield* return value propagation failed", |
|
details: `Expected 6 (3+2+1), got ${nestedResult.value}` |
|
}; |
|
} |
|
checks.push("Nested yield* delegation works correctly"); |
|
return { |
|
pass: true, |
|
message: "yield* delegation fully supported", |
|
details: checks.join("; ") |
|
}; |
|
} catch (error) { |
|
return { |
|
pass: false, |
|
message: `yield* delegation test threw error: ${error instanceof Error ? error.message : String(error)}` |
|
}; |
|
} |
|
} |
|
|
|
// conformance/04-yield-throw.ts |
|
function testYieldThrow() { |
|
const checks = []; |
|
try { |
|
let innerCaughtError = false; |
|
function* innerWithCatch() { |
|
try { |
|
yield "inner-1"; |
|
yield "inner-2"; |
|
return "inner-done"; |
|
} catch (_e) { |
|
innerCaughtError = true; |
|
return "inner-caught"; |
|
} |
|
} |
|
function* outerDelegating() { |
|
const result = yield* innerWithCatch(); |
|
return result; |
|
} |
|
const gen1 = outerDelegating(); |
|
gen1.next(); |
|
const throwResult = gen1.throw(new Error("test error")); |
|
if (!innerCaughtError) { |
|
return { |
|
pass: false, |
|
message: "Error was not forwarded to delegated generator" |
|
}; |
|
} |
|
if (throwResult.value !== "inner-caught" || throwResult.done !== true) { |
|
return { |
|
pass: false, |
|
message: "Delegated generator catch block return value not propagated", |
|
details: `Expected {value: "inner-caught", done: true}, got ${JSON.stringify(throwResult)}` |
|
}; |
|
} |
|
checks.push("Error forwarding to delegated generator works"); |
|
function* innerNoCatch() { |
|
yield "will-throw"; |
|
return "never-reached"; |
|
} |
|
function* outerCatching() { |
|
try { |
|
const result = yield* innerNoCatch(); |
|
return result; |
|
} catch (_e) { |
|
return "outer-caught"; |
|
} |
|
} |
|
const gen2 = outerCatching(); |
|
gen2.next(); |
|
const bubbleResult = gen2.throw(new Error("bubble error")); |
|
if (bubbleResult.value !== "outer-caught" || bubbleResult.done !== true) { |
|
return { |
|
pass: false, |
|
message: "Uncaught error did not bubble to outer generator", |
|
details: `Expected {value: "outer-caught", done: true}, got ${JSON.stringify(bubbleResult)}` |
|
}; |
|
} |
|
checks.push("Uncaught errors bubble up through yield*"); |
|
const errorPath = []; |
|
function* level3Throw() { |
|
try { |
|
yield "L3"; |
|
return "L3-done"; |
|
} catch (_e) { |
|
errorPath.push("L3-catch"); |
|
throw _e; |
|
} |
|
} |
|
function* level2Throw() { |
|
try { |
|
const result = yield* level3Throw(); |
|
return result; |
|
} catch (_e) { |
|
errorPath.push("L2-catch"); |
|
throw _e; |
|
} |
|
} |
|
function* level1Throw() { |
|
try { |
|
const result = yield* level2Throw(); |
|
return result; |
|
} catch (_e) { |
|
errorPath.push("L1-catch"); |
|
return "L1-recovered"; |
|
} |
|
} |
|
const gen3 = level1Throw(); |
|
gen3.next(); |
|
const multiLevelResult = gen3.throw(new Error("multi-level error")); |
|
if (errorPath.length !== 3) { |
|
return { |
|
pass: false, |
|
message: "Error did not propagate through all levels", |
|
details: `Expected 3 catches, got: ${JSON.stringify(errorPath)}` |
|
}; |
|
} |
|
if (errorPath[0] !== "L3-catch" || errorPath[1] !== "L2-catch" || errorPath[2] !== "L1-catch") { |
|
return { |
|
pass: false, |
|
message: "Error propagation order incorrect", |
|
details: `Expected [L3-catch, L2-catch, L1-catch], got ${JSON.stringify(errorPath)}` |
|
}; |
|
} |
|
if (multiLevelResult.value !== "L1-recovered" || multiLevelResult.done !== true) { |
|
return { |
|
pass: false, |
|
message: "Final recovery value not correct", |
|
details: `Expected {value: "L1-recovered", done: true}, got ${JSON.stringify(multiLevelResult)}` |
|
}; |
|
} |
|
checks.push("Error propagation works across multiple delegation levels"); |
|
return { |
|
pass: true, |
|
message: "yield* throw() forwarding fully supported", |
|
details: checks.join("; ") |
|
}; |
|
} catch (error) { |
|
return { |
|
pass: false, |
|
message: `yield* throw test threw unexpected error: ${error instanceof Error ? error.message : String(error)}` |
|
}; |
|
} |
|
} |
|
|
|
// conformance/05-yield-return.ts |
|
function testYieldReturn() { |
|
const checks = []; |
|
try { |
|
let innerFinallyRan = false; |
|
function* innerWithFinally() { |
|
try { |
|
yield "inner-1"; |
|
yield "inner-2"; |
|
return "inner-done"; |
|
} finally { |
|
innerFinallyRan = true; |
|
} |
|
} |
|
function* outerDelegating() { |
|
const result = yield* innerWithFinally(); |
|
return result; |
|
} |
|
const gen1 = outerDelegating(); |
|
gen1.next(); |
|
const returnResult = gen1.return("early-return"); |
|
if (!innerFinallyRan) { |
|
return { |
|
pass: false, |
|
message: "return() did not trigger finally in delegated generator", |
|
details: "This is CRITICAL for Effection cleanup semantics" |
|
}; |
|
} |
|
if (returnResult.done !== true) { |
|
return { |
|
pass: false, |
|
message: "return() did not complete the generator" |
|
}; |
|
} |
|
checks.push("return() triggers finally in delegated generator"); |
|
const finallyOrder = []; |
|
function* level3Finally() { |
|
try { |
|
yield "L3"; |
|
return "L3-done"; |
|
} finally { |
|
finallyOrder.push("L3-finally"); |
|
} |
|
} |
|
function* level2Finally() { |
|
try { |
|
const result = yield* level3Finally(); |
|
yield "L2-after"; |
|
return result; |
|
} finally { |
|
finallyOrder.push("L2-finally"); |
|
} |
|
} |
|
function* level1Finally() { |
|
try { |
|
const result = yield* level2Finally(); |
|
yield "L1-after"; |
|
return result; |
|
} finally { |
|
finallyOrder.push("L1-finally"); |
|
} |
|
} |
|
const gen2 = level1Finally(); |
|
gen2.next(); |
|
gen2.return("cancelled"); |
|
if (finallyOrder.length !== 3) { |
|
return { |
|
pass: false, |
|
message: "Not all finally blocks executed", |
|
details: `Expected 3, got ${finallyOrder.length}: ${JSON.stringify(finallyOrder)}` |
|
}; |
|
} |
|
if (finallyOrder[0] !== "L3-finally") { |
|
return { |
|
pass: false, |
|
message: "Innermost finally did not run first", |
|
details: `Expected L3-finally first, got: ${JSON.stringify(finallyOrder)}` |
|
}; |
|
} |
|
if (finallyOrder[2] !== "L1-finally") { |
|
return { |
|
pass: false, |
|
message: "Outermost finally did not run last", |
|
details: `Expected L1-finally last, got: ${JSON.stringify(finallyOrder)}` |
|
}; |
|
} |
|
checks.push("Nested finally blocks execute in LIFO order"); |
|
let cleanupYielded = false; |
|
function* withCleanupYield() { |
|
try { |
|
yield "working"; |
|
return "done"; |
|
} finally { |
|
yield "cleanup"; |
|
cleanupYielded = true; |
|
} |
|
} |
|
function* useCleanupYield() { |
|
const result = yield* withCleanupYield(); |
|
return result; |
|
} |
|
const gen3 = useCleanupYield(); |
|
gen3.next(); |
|
const cleanupResult1 = gen3.return("cancel"); |
|
if (cleanupResult1.value !== "cleanup" || cleanupResult1.done !== false) { |
|
return { |
|
pass: false, |
|
message: "finally block yield not executed during return()", |
|
details: `Expected {value: "cleanup", done: false}, got ${JSON.stringify(cleanupResult1)}` |
|
}; |
|
} |
|
const cleanupResult2 = gen3.next(); |
|
if (!cleanupYielded) { |
|
return { |
|
pass: false, |
|
message: "finally block did not complete after yield" |
|
}; |
|
} |
|
if (cleanupResult2.done !== true) { |
|
return { |
|
pass: false, |
|
message: "Generator did not complete after finally yield" |
|
}; |
|
} |
|
checks.push("finally blocks can yield during cleanup"); |
|
return { |
|
pass: true, |
|
message: "yield* return() forwarding fully supported (cancellation semantics OK)", |
|
details: checks.join("; ") |
|
}; |
|
} catch (error) { |
|
return { |
|
pass: false, |
|
message: `yield* return test threw error: ${error instanceof Error ? error.message : String(error)}` |
|
}; |
|
} |
|
} |
|
|
|
// conformance/06-promises.ts |
|
function testPromises() { |
|
const checks = []; |
|
try { |
|
if (typeof Promise !== "function") { |
|
return { |
|
pass: false, |
|
message: "Promise constructor does not exist" |
|
}; |
|
} |
|
checks.push("Promise constructor exists"); |
|
const resolved = Promise.resolve(42); |
|
if (!(resolved instanceof Promise)) { |
|
return { |
|
pass: false, |
|
message: "Promise.resolve did not return a Promise" |
|
}; |
|
} |
|
checks.push("Promise.resolve works"); |
|
const rejected = Promise.reject(new Error("test")); |
|
if (!(rejected instanceof Promise)) { |
|
return { |
|
pass: false, |
|
message: "Promise.reject did not return a Promise" |
|
}; |
|
} |
|
rejected.catch(() => { |
|
}); |
|
checks.push("Promise.reject works"); |
|
let executorRan = false; |
|
const _constructed = new Promise((resolve) => { |
|
executorRan = true; |
|
resolve(); |
|
}); |
|
if (!executorRan) { |
|
return { |
|
pass: false, |
|
message: "Promise executor did not run synchronously" |
|
}; |
|
} |
|
checks.push("Promise executor runs synchronously"); |
|
if (typeof Promise.all !== "function") { |
|
return { |
|
pass: false, |
|
message: "Promise.all does not exist" |
|
}; |
|
} |
|
checks.push("Promise.all exists"); |
|
if (typeof Promise.race !== "function") { |
|
return { |
|
pass: false, |
|
message: "Promise.race does not exist" |
|
}; |
|
} |
|
checks.push("Promise.race exists"); |
|
if (typeof Promise.allSettled !== "function") { |
|
checks.push("Promise.allSettled not available (ES2020)"); |
|
} else { |
|
checks.push("Promise.allSettled exists"); |
|
} |
|
const asyncFn = async () => 42; |
|
if (typeof asyncFn !== "function") { |
|
return { |
|
pass: false, |
|
message: "async function syntax not supported" |
|
}; |
|
} |
|
checks.push("async function syntax works"); |
|
const asyncResult = asyncFn(); |
|
if (!(asyncResult instanceof Promise)) { |
|
return { |
|
pass: false, |
|
message: "async function did not return Promise" |
|
}; |
|
} |
|
checks.push("async functions return Promises"); |
|
return { |
|
pass: true, |
|
message: "Promise support confirmed", |
|
details: checks.join("; ") |
|
}; |
|
} catch (error) { |
|
return { |
|
pass: false, |
|
message: `Promise test threw error: ${error instanceof Error ? error.message : String(error)}` |
|
}; |
|
} |
|
} |
|
async function testPromisesAsync() { |
|
const checks = []; |
|
try { |
|
const value = await Promise.resolve(42); |
|
if (value !== 42) { |
|
return { |
|
pass: false, |
|
message: "Promise.resolve did not resolve to correct value" |
|
}; |
|
} |
|
checks.push("await Promise.resolve works"); |
|
const chained = await Promise.resolve(1).then((x) => x + 1).then((x) => x + 1); |
|
if (chained !== 3) { |
|
return { |
|
pass: false, |
|
message: "Promise.then chaining did not work", |
|
details: `Expected 3, got ${chained}` |
|
}; |
|
} |
|
checks.push("Promise.then chaining works"); |
|
const allResults = await Promise.all([ |
|
Promise.resolve(1), |
|
Promise.resolve(2), |
|
Promise.resolve(3) |
|
]); |
|
if (allResults.length !== 3 || allResults[0] !== 1 || allResults[2] !== 3) { |
|
return { |
|
pass: false, |
|
message: "Promise.all did not collect all values", |
|
details: `Expected [1,2,3], got ${JSON.stringify(allResults)}` |
|
}; |
|
} |
|
checks.push("Promise.all works"); |
|
const raceResult = await Promise.race([ |
|
Promise.resolve("first"), |
|
new Promise((resolve) => setTimeout(() => resolve("second"), 100)) |
|
]); |
|
if (raceResult !== "first") { |
|
return { |
|
pass: false, |
|
message: "Promise.race did not return first resolved value" |
|
}; |
|
} |
|
checks.push("Promise.race works"); |
|
let caughtError = false; |
|
try { |
|
await Promise.reject(new Error("test error")); |
|
} catch (_e) { |
|
caughtError = true; |
|
} |
|
if (!caughtError) { |
|
return { |
|
pass: false, |
|
message: "async/await try/catch did not catch rejection" |
|
}; |
|
} |
|
checks.push("async/await try/catch works"); |
|
return { |
|
pass: true, |
|
message: "Full async Promise support confirmed", |
|
details: checks.join("; ") |
|
}; |
|
} catch (error) { |
|
return { |
|
pass: false, |
|
message: `Async Promise test threw error: ${error instanceof Error ? error.message : String(error)}` |
|
}; |
|
} |
|
} |
|
|
|
// conformance/07-timers.ts |
|
function testTimers() { |
|
const checks = []; |
|
try { |
|
if (typeof setTimeout !== "function") { |
|
return { |
|
pass: false, |
|
message: "setTimeout does not exist", |
|
details: "setTimeout is required for Effection's sleep() operation" |
|
}; |
|
} |
|
checks.push("setTimeout exists"); |
|
if (typeof clearTimeout !== "function") { |
|
return { |
|
pass: false, |
|
message: "clearTimeout does not exist", |
|
details: "clearTimeout is required for cancelling sleep operations" |
|
}; |
|
} |
|
checks.push("clearTimeout exists"); |
|
const timerId = setTimeout(() => { |
|
}, 1e3); |
|
if (timerId === void 0 || timerId === null) { |
|
return { |
|
pass: false, |
|
message: "setTimeout did not return a timer ID" |
|
}; |
|
} |
|
clearTimeout(timerId); |
|
checks.push("setTimeout returns timer ID"); |
|
try { |
|
const id = setTimeout(() => { |
|
throw new Error("This should not run"); |
|
}, 10); |
|
clearTimeout(id); |
|
checks.push("clearTimeout can cancel timers"); |
|
} catch (e) { |
|
return { |
|
pass: false, |
|
message: `clearTimeout threw error: ${e instanceof Error ? e.message : String(e)}` |
|
}; |
|
} |
|
if (typeof setInterval !== "function") { |
|
checks.push("setInterval not available (not critical)"); |
|
} else { |
|
checks.push("setInterval exists"); |
|
if (typeof clearInterval !== "function") { |
|
checks.push("clearInterval not available (not critical)"); |
|
} else { |
|
const intervalId = setInterval(() => { |
|
}, 1e3); |
|
clearInterval(intervalId); |
|
checks.push("clearInterval exists and works"); |
|
} |
|
} |
|
return { |
|
pass: true, |
|
message: "Timer support confirmed", |
|
details: checks.join("; ") |
|
}; |
|
} catch (error) { |
|
return { |
|
pass: false, |
|
message: `Timer test threw error: ${error instanceof Error ? error.message : String(error)}` |
|
}; |
|
} |
|
} |
|
async function testTimersAsync() { |
|
const checks = []; |
|
try { |
|
const startTime = Date.now(); |
|
await new Promise((resolve) => { |
|
setTimeout(() => { |
|
resolve(); |
|
}, 50); |
|
}); |
|
const elapsed = Date.now() - startTime; |
|
if (elapsed < 40) { |
|
return { |
|
pass: false, |
|
message: "setTimeout fired too quickly", |
|
details: `Expected ~50ms delay, got ${elapsed}ms` |
|
}; |
|
} |
|
checks.push(`setTimeout fires correctly (${elapsed}ms for 50ms timeout)`); |
|
const sequence = []; |
|
await new Promise((resolve) => { |
|
setTimeout(() => sequence.push(1), 10); |
|
setTimeout(() => sequence.push(2), 20); |
|
setTimeout(() => { |
|
sequence.push(3); |
|
resolve(); |
|
}, 30); |
|
}); |
|
if (sequence.length !== 3 || sequence[0] !== 1 || sequence[1] !== 2 || sequence[2] !== 3) { |
|
return { |
|
pass: false, |
|
message: "setTimeout sequence order incorrect", |
|
details: `Expected [1,2,3], got ${JSON.stringify(sequence)}` |
|
}; |
|
} |
|
checks.push("setTimeout ordering works correctly"); |
|
let shouldNotRun = false; |
|
const cancelId = setTimeout(() => { |
|
shouldNotRun = true; |
|
}, 20); |
|
clearTimeout(cancelId); |
|
await new Promise((resolve) => setTimeout(resolve, 50)); |
|
if (shouldNotRun) { |
|
return { |
|
pass: false, |
|
message: "clearTimeout did not prevent callback execution" |
|
}; |
|
} |
|
checks.push("clearTimeout prevents callback execution"); |
|
return { |
|
pass: true, |
|
message: "Full timer support confirmed", |
|
details: checks.join("; ") |
|
}; |
|
} catch (error) { |
|
return { |
|
pass: false, |
|
message: `Async timer test threw error: ${error instanceof Error ? error.message : String(error)}` |
|
}; |
|
} |
|
} |
|
|
|
// conformance/08-abort-controller.ts |
|
function testAbortController() { |
|
const checks = []; |
|
try { |
|
if (typeof AbortController !== "function") { |
|
return { |
|
pass: false, |
|
message: "AbortController does not exist", |
|
details: "useAbortSignal() will not be available, but Effection core will work" |
|
}; |
|
} |
|
checks.push("AbortController constructor exists"); |
|
let controller; |
|
try { |
|
controller = new AbortController(); |
|
} catch (e) { |
|
return { |
|
pass: false, |
|
message: `AbortController instantiation failed: ${e instanceof Error ? e.message : String(e)}` |
|
}; |
|
} |
|
checks.push("AbortController can be instantiated"); |
|
const signal = controller.signal; |
|
if (!signal) { |
|
return { |
|
pass: false, |
|
message: "AbortController.signal is not defined" |
|
}; |
|
} |
|
checks.push("AbortController.signal exists"); |
|
if (signal.aborted !== false) { |
|
return { |
|
pass: false, |
|
message: "AbortSignal.aborted should initially be false", |
|
details: `Got: ${signal.aborted}` |
|
}; |
|
} |
|
checks.push("AbortSignal.aborted initially false"); |
|
if (typeof controller.abort !== "function") { |
|
return { |
|
pass: false, |
|
message: "AbortController.abort() method does not exist" |
|
}; |
|
} |
|
checks.push("AbortController.abort() method exists"); |
|
controller.abort(); |
|
const abortedAfter = controller.signal.aborted; |
|
if (!abortedAfter) { |
|
return { |
|
pass: false, |
|
message: "AbortController.abort() did not set signal.aborted to true", |
|
details: `Got: ${abortedAfter}` |
|
}; |
|
} |
|
checks.push("abort() sets signal.aborted to true"); |
|
const controller2 = new AbortController(); |
|
const customReason = new Error("custom abort reason"); |
|
controller2.abort(customReason); |
|
if (controller2.signal.reason === customReason) { |
|
checks.push("AbortSignal.reason captures abort reason"); |
|
} else { |
|
checks.push("AbortSignal.reason not supported (ES2022 feature)"); |
|
} |
|
if (typeof AbortSignal.abort === "function") { |
|
const abortedSignal = AbortSignal.abort(); |
|
if (abortedSignal.aborted) { |
|
checks.push("AbortSignal.abort() static method works"); |
|
} |
|
} else { |
|
checks.push("AbortSignal.abort() not available"); |
|
} |
|
if (typeof AbortSignal.timeout === "function") { |
|
checks.push("AbortSignal.timeout() available"); |
|
} else { |
|
checks.push("AbortSignal.timeout() not available"); |
|
} |
|
return { |
|
pass: true, |
|
message: "AbortController support confirmed", |
|
details: checks.join("; ") |
|
}; |
|
} catch (error) { |
|
return { |
|
pass: false, |
|
message: `AbortController test threw error: ${error instanceof Error ? error.message : String(error)}` |
|
}; |
|
} |
|
} |
|
async function testAbortControllerAsync() { |
|
const checks = []; |
|
try { |
|
const controller = new AbortController(); |
|
let eventFired = false; |
|
let eventType = ""; |
|
controller.signal.addEventListener("abort", (event) => { |
|
eventFired = true; |
|
eventType = event.type; |
|
}); |
|
controller.abort(); |
|
await Promise.resolve(); |
|
if (!eventFired) { |
|
return { |
|
pass: false, |
|
message: "abort event listener did not fire", |
|
details: "Event-based abort handling may not work" |
|
}; |
|
} |
|
if (eventType !== "abort") { |
|
return { |
|
pass: false, |
|
message: "abort event type incorrect", |
|
details: `Expected "abort", got "${eventType}"` |
|
}; |
|
} |
|
checks.push("abort event listener works"); |
|
const controller2 = new AbortController(); |
|
let onabortFired = false; |
|
if ("onabort" in controller2.signal) { |
|
controller2.signal.onabort = () => { |
|
onabortFired = true; |
|
}; |
|
controller2.abort(); |
|
await Promise.resolve(); |
|
if (onabortFired) { |
|
checks.push("signal.onabort handler works"); |
|
} else { |
|
checks.push("signal.onabort exists but did not fire"); |
|
} |
|
} else { |
|
checks.push("signal.onabort not supported"); |
|
} |
|
return { |
|
pass: true, |
|
message: "AbortController async features confirmed", |
|
details: checks.join("; ") |
|
}; |
|
} catch (error) { |
|
return { |
|
pass: false, |
|
message: `Async AbortController test threw error: ${error instanceof Error ? error.message : String(error)}` |
|
}; |
|
} |
|
} |
|
|
|
// conformance/mod.ts |
|
var syncTests = { |
|
"01-symbols": testSymbols, |
|
"02-generators": testGenerators, |
|
"03-yield-delegation": testYieldDelegation, |
|
"04-yield-throw": testYieldThrow, |
|
"05-yield-return": testYieldReturn, |
|
"06-promises-sync": testPromises, |
|
"07-timers-sync": testTimers, |
|
"08-abort-controller-sync": testAbortController |
|
}; |
|
var asyncTests = { |
|
"06-promises-async": testPromisesAsync, |
|
"07-timers-async": testTimersAsync, |
|
"08-abort-controller-async": testAbortControllerAsync |
|
}; |
|
function runSyncTests() { |
|
const results = {}; |
|
for (const [name, test] of Object.entries(syncTests)) { |
|
try { |
|
results[name] = test(); |
|
} catch (error) { |
|
results[name] = { |
|
pass: false, |
|
message: `Test threw unexpected error: ${error instanceof Error ? error.message : String(error)}` |
|
}; |
|
} |
|
} |
|
return results; |
|
} |
|
async function runAsyncTests() { |
|
const results = {}; |
|
for (const [name, test] of Object.entries(asyncTests)) { |
|
try { |
|
results[name] = await test(); |
|
} catch (error) { |
|
results[name] = { |
|
pass: false, |
|
message: `Test threw unexpected error: ${error instanceof Error ? error.message : String(error)}` |
|
}; |
|
} |
|
} |
|
return results; |
|
} |
|
function printResults(results) { |
|
console.log("\n=== Effection K6 Conformance Test Results ===\n"); |
|
let passed = 0; |
|
let failed = 0; |
|
for (const [name, result] of Object.entries(results)) { |
|
const status = result.pass ? "PASS" : "FAIL"; |
|
const icon = result.pass ? "+" : "x"; |
|
console.log(`[${icon}] ${name}: ${status}`); |
|
console.log(` ${result.message}`); |
|
if (result.details) { |
|
console.log(` Details: ${result.details}`); |
|
} |
|
console.log(""); |
|
if (result.pass) { |
|
passed++; |
|
} else { |
|
failed++; |
|
} |
|
} |
|
console.log("=== Summary ==="); |
|
console.log(`Passed: ${passed}`); |
|
console.log(`Failed: ${failed}`); |
|
console.log(`Total: ${passed + failed}`); |
|
if (failed > 0) { |
|
console.log("\nWARNING: Some conformance tests failed."); |
|
console.log("Effection may not work correctly in this runtime."); |
|
} else { |
|
console.log("\nAll conformance tests passed!"); |
|
console.log("Effection should work correctly in this runtime."); |
|
} |
|
} |
|
function allCriticalTestsPassed(results) { |
|
const criticalTests = [ |
|
"01-symbols", |
|
"02-generators", |
|
"03-yield-delegation", |
|
"04-yield-throw", |
|
"05-yield-return" |
|
]; |
|
for (const name of criticalTests) { |
|
if (!results[name]?.pass) { |
|
return false; |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
// conformance/k6-runner.ts |
|
var options = { |
|
vus: 1, |
|
iterations: 1, |
|
thresholds: { |
|
checks: ["rate==1"] |
|
// All checks must pass |
|
} |
|
}; |
|
function setup() { |
|
console.log("Running synchronous conformance tests...\n"); |
|
const syncResults = runSyncTests(); |
|
return { syncResults }; |
|
} |
|
async function k6_runner_default(data) { |
|
const { syncResults } = data; |
|
console.log("Running asynchronous conformance tests...\n"); |
|
const asyncResults = await runAsyncTests(); |
|
const allResults = { |
|
...syncResults, |
|
...asyncResults |
|
}; |
|
printResults(allResults); |
|
for (const [name, result] of Object.entries(allResults)) { |
|
check(result, { |
|
[`${name}`]: (r) => r.pass |
|
}); |
|
} |
|
const criticalPassed = allCriticalTestsPassed(allResults); |
|
check(criticalPassed, { |
|
"All critical tests passed (Effection can work)": (v) => v === true |
|
}); |
|
if (!criticalPassed) { |
|
console.error("\n!!! CRITICAL: Effection cannot work in this runtime !!!"); |
|
console.error("One or more critical conformance tests failed."); |
|
console.error("Please check the results above for details."); |
|
} |
|
} |
|
function teardown(data) { |
|
const criticalPassed = allCriticalTestsPassed(data.syncResults); |
|
if (criticalPassed) { |
|
console.log("\n=== Conformance testing complete ==="); |
|
console.log("The K6/Sobek runtime appears to support Effection."); |
|
console.log("You can proceed with using @effectionx/k6 in your tests."); |
|
} |
|
} |
|
export { |
|
k6_runner_default as default, |
|
options, |
|
setup, |
|
teardown |
|
}; |
|
//# sourceMappingURL=conformance-bundle.js.map |