Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ class AsyncRAFTestInvoker extends TestInvoker {
}
}

export const TEST_INVOKER_LOOKUP = {
export const TEST_INVOKER_LOOKUP = Object.freeze({
__proto__: null,
raf: RAFTestInvoker,
async: AsyncRAFTestInvoker,
};
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ export class TestRunner {
#callback;
#type;

constructor(frame, page, params, suite, test, callback, type) {
constructor(frame, page, params, suite, test, callback, type = "default") {
this.#suite = suite;
this.#test = test;
this.#params = params;
this.#callback = callback;
this.#page = page;
this.#frame = frame;
this.#type = type;
console.assert(type in TEST_RUNNER_LOOKUP, "Invalid type", type);
}

get page() {
Expand Down Expand Up @@ -99,18 +100,18 @@ export class TestRunner {
}

export class AsyncTestRunner extends TestRunner {
constructor(frame, page, params, suite, test, callback, type) {
super(frame, page, params, suite, test, callback, type);
constructor(frame, page, params, suite, test, callback) {
super(frame, page, params, suite, test, callback, "async");
}

async _runSyncStep(test, page) {
await test.run(page);
}
}

export const TEST_RUNNER_LOOKUP = {
export const TEST_RUNNER_LOOKUP = Object.freeze({
__proto__: null,
default: TestRunner,
async: AsyncTestRunner,
remote: TestRunner,
};
});

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
self.__SSG_MANIFEST=new Set,self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB();

Large diffs are not rendered by default.

74 changes: 61 additions & 13 deletions resources/shared/benchmark.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable no-case-declarations */
import { StepRunner } from "./step-runner.mjs";
import { StepRunner, AsyncStepRunner } from "./step-runner.mjs";
import { Params } from "./params.mjs";

/**
Expand All @@ -20,15 +20,31 @@ export class BenchmarkStep {
}
}

export class AsyncBenchmarkStep extends BenchmarkStep {
async runAndRecord(params, suite, test, callback) {
const testRunner = new AsyncStepRunner(null, null, params, suite, test, callback);
const result = await testRunner.runTest();
return result;
}
}

export const BENCHMARK_SUITE_TYPE = Object.freeze({
__proto__: null,
sync: "sync",
async: "async",
});

/**
* BenchmarkSuite
*
* A single test suite that contains one or more test steps.
*/
export class BenchmarkSuite {
constructor(name, steps) {
constructor(name, steps, type = BENCHMARK_SUITE_TYPE.sync) {
this.name = name;
this.steps = steps;
this.type = type;
console.assert(this.type in BENCHMARK_SUITE_TYPE, "Invalid Type", this.type);
}

record(_step, syncTime, asyncTime) {
Expand All @@ -54,6 +70,7 @@ export class BenchmarkSuite {

for (const step of this.steps) {
const result = await step.runAndRecordStep(params, this, step, this.record);
console.assert(result, "Missing test return value", step);
measuredValues.tests[step.name] = result;
measuredValues.total += result.total;
onProgress?.(step.name);
Expand All @@ -66,11 +83,31 @@ export class BenchmarkSuite {
type: "suite-tests-complete",
status: "success",
result: measuredValues,
suitename: this.name,
suiteName: this.name,
};
}
}

export class AsyncBenchmarkSuite extends BenchmarkSuite {
constructor(name, steps) {
super(name, steps, BENCHMARK_SUITE_TYPE.async);
}
}

export const MESSAGE_TYPE = Object.freeze({
__proto__: null,
appReady: "app-ready",
suiteStart: "suite-start",
stepComplete: "step-complete",
suiteComplete: "suite-complete",
});

export const MESSAGE_STATUS = Object.freeze({
__proto__: null,
success: "success",
error: "error",
});

/** **********************************************************************
* BenchmarkConnector
*
Expand All @@ -95,31 +132,42 @@ export class BenchmarkConnector {
}

async onMessage(event) {
if (event.data.id !== this.appId || event.data.key !== "benchmark-connector")
const message = event.data;
if (message.appId !== this.appId || message.key !== "benchmark-connector") {
console.warning("Invalid message", message);
return;
}

switch (event.data.type) {
case "benchmark-suite":
switch (message.type) {
case MESSAGE_TYPE.suiteStart:
const params = new Params(new URLSearchParams(window.location.search));
const suite = this.suites[event.data.name];
const { name } = message.payload;
const suite = this.suites[name];
if (!suite)
console.error(`Suite with the name of "${event.data.name}" not found!`);
const { result } = await suite.runAndRecordSuite(params, (test) => this.sendMessage({ type: "step-complete", status: "success", appId: this.appId, name: this.name, test }));
this.sendMessage({ type: "suite-complete", status: "success", appId: this.appId, result });
console.error(`Suite with the name of "${name}" not found!`);
const onProgress = (step) => this._sendMessage(MESSAGE_TYPE.stepComplete, { name: this.name, step });
const { result } = await suite.runAndRecordSuite(params, onProgress);
this._sendMessage(MESSAGE_TYPE.suiteComplete, { result });
this.disconnect();
break;
default:
console.error(`Message data type not supported: ${event.data.type}`);
console.error(`Message data type not supported: ${message.type}`);
}
}

sendMessage(message) {
_sendMessage(type, payload, status = MESSAGE_STATUS.success) {
const message = {
appId: this.appId,
type: type,
payload: payload,
status: status,
};
window.top.postMessage(message, "*");
}

connect() {
window.addEventListener("message", this.onMessage);
this.sendMessage({ type: "app-ready", status: "success", appId: this.appId });
this._sendMessage(MESSAGE_TYPE.appReady, { appId: this.appId });
}

disconnect() {
Expand Down
41 changes: 30 additions & 11 deletions resources/suite-runner.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { STEP_RUNNER_LOOKUP } from "./shared/step-runner.mjs";
import { MESSAGE_TYPE } from "./shared/benchmark.mjs";
import { WarmupSuite } from "./benchmark-runner.mjs";

export class SuiteRunner {
Expand Down Expand Up @@ -160,43 +161,52 @@ export class RemoteSuiteRunner extends SuiteRunner {
const suiteName = this.suite.name;
const suitePrepareStartLabel = `suite-${suiteName}-prepare-start`;
const suitePrepareEndLabel = `suite-${suiteName}-prepare-end`;

performance.mark(suitePrepareStartLabel);

// Wait for the app-ready message from the workload.
const appReadyPromise = this._subscribeOnce("app-ready");
const appReadyPromise = this._subscribeOnce(MESSAGE_TYPE.appReady);
await this._loadFrame(this.suite);
// The suite will send out the app-ready message.
const response = await appReadyPromise;
this._initializeAppId(response.appId);
await this.suite.prepare?.(this.page);
// Capture appId to pass along with messages.
this.appId = response?.appId;

performance.mark(suitePrepareEndLabel);

const entry = performance.measure(`suite-${suiteName}-prepare`, suitePrepareStartLabel, suitePrepareEndLabel);
this.#prepareTime = entry.duration;
}

async _runSuite() {
// Ask workload to run its own tests.
this.frame.contentWindow.postMessage({ id: this.appId, key: "benchmark-connector", type: "benchmark-suite", name: this.suite.config?.name || "default" }, "*");
this._sendMessage(MESSAGE_TYPE.suiteStart, { name: this.suite.config?.name || "default" });
// Capture metrics from the completed tests.
const response = await this._subscribeOnce("suite-complete");
const { result } = await this._subscribeOnce(MESSAGE_TYPE.suiteComplete);

this.suiteResults.tests = {
...this.suiteResults.tests,
...response.result.tests,
...result.tests,
};

this.suiteResults.prepare = this.#prepareTime;
this.suiteResults.total = response.result.total;
this.suiteResults.total = result.total;

this._validateSuiteResults();
await this._updateClient();
}

_sendMessage(type, payload) {
const message = {
appId: this.appId,
key: "benchmark-connector",
type: type,
payload: payload,
};
this.frame.contentWindow.postMessage(message, "*");
}

_handlePostMessage(event) {
const callback = this.postMessageCallbacks.get(event.data.type);
const message = event.data;
const callback = this.postMessageCallbacks.get(message.type);
if (callback)
callback(event);
}
Expand All @@ -218,11 +228,20 @@ export class RemoteSuiteRunner extends SuiteRunner {
_subscribeOnce(type) {
return new Promise((resolve) => {
this._startSubscription(type, (e) => {
const message = e.data;
if (type !== MESSAGE_TYPE.appReady && message.appId !== this.appId)
throw new Error(`Got message for invalid app: ${message.appId} instead of ${this.appId}`);
this._stopSubscription(type);
resolve(e.data);
resolve(message.payload);
});
});
}

_initializeAppId(appId) {
console.assert(!this.appId, `Cannot receive ${MESSAGE_TYPE.appReady} twice`);
console.assert(appId, `${MESSAGE_TYPE.appReady} sent no appId`);
this.appId = appId;
}
}

export const SUITE_RUNNER_LOOKUP = {
Expand Down
Loading