Advance M8-M11 parity workflows
This commit is contained in:
197
web/tests/e2e/nanovdb-page-feedback.spec.ts
Normal file
197
web/tests/e2e/nanovdb-page-feedback.spec.ts
Normal file
@@ -0,0 +1,197 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("M8-02 through M8-10 gates, pins and bounded redraws manifest-backed page faults", async ({ page }) => {
|
||||
test.setTimeout(90_000);
|
||||
await page.goto("/");
|
||||
const result = await page.evaluate(() => new Promise<any>((resolve, reject) => {
|
||||
const worker = new Worker("/src/workers/nanovdb-page-feedback-test.worker.ts", { type: "module" });
|
||||
worker.onmessage = (event) => {
|
||||
worker.terminate();
|
||||
event.data.error ? reject(new Error(event.data.error)) : resolve(event.data);
|
||||
};
|
||||
worker.onerror = (event) => { worker.terminate(); reject(new Error(event.message)); };
|
||||
worker.postMessage({});
|
||||
}));
|
||||
|
||||
expect(result.leafByteOffset).toBeGreaterThan(0);
|
||||
expect(result.leafPageId).toBeGreaterThan(0);
|
||||
expect(result.leafPageId).toBeLessThan(result.pageCount);
|
||||
expect(result.manifestPageBytes).toBe(4 * 1024 * 1024);
|
||||
expect(result.leafSampleCount).toBe(256);
|
||||
expect(result.leafSamplesFallback).toBe(true);
|
||||
expect(result.leafResult).toEqual({
|
||||
schemaVersion: 1,
|
||||
renderRevision: 17,
|
||||
attemptedCount: 1,
|
||||
gpuStoredCount: 1,
|
||||
uniqueCount: 1,
|
||||
pageIds: [result.leafPageId],
|
||||
status: "READY",
|
||||
errorCode: null,
|
||||
});
|
||||
expect(result.leafGuard).toEqual(result.guardWords);
|
||||
expect(result.staleDispatch).toEqual({
|
||||
schemaVersion: 1,
|
||||
renderRevision: 17,
|
||||
currentRenderRevision: 18,
|
||||
status: "STALE",
|
||||
requestedPageIds: [],
|
||||
requestedCount: 0,
|
||||
errorCode: "REVISION_CONFLICT",
|
||||
});
|
||||
expect(result.stalePageIoCount).toBe(0);
|
||||
expect(result.currentDispatch).toEqual({
|
||||
schemaVersion: 1,
|
||||
renderRevision: 17,
|
||||
currentRenderRevision: 17,
|
||||
status: "ACCEPTED",
|
||||
requestedPageIds: [result.leafPageId],
|
||||
requestedCount: 1,
|
||||
errorCode: null,
|
||||
});
|
||||
expect(result.pageIoRequests).toEqual([{ pageId: result.leafPageId, renderRevision: 17 }]);
|
||||
expect(result.manifestFeedbackResult).toEqual({
|
||||
schemaVersion: 1,
|
||||
renderRevision: 19,
|
||||
attemptedCount: 1,
|
||||
gpuStoredCount: 1,
|
||||
uniqueCount: 1,
|
||||
pageIds: [0],
|
||||
status: "READY",
|
||||
errorCode: null,
|
||||
});
|
||||
expect(result.manifestWordsZero).toBe(true);
|
||||
expect(result.manifestStaleDispatch).toEqual({
|
||||
schemaVersion: 1,
|
||||
renderRevision: 19,
|
||||
currentRenderRevision: 20,
|
||||
status: "STALE",
|
||||
requestedPageIds: [],
|
||||
requestedCount: 0,
|
||||
errorCode: "REVISION_CONFLICT",
|
||||
});
|
||||
expect(result.staleManifestRangeCount).toBe(0);
|
||||
expect(result.manifestDispatch).toEqual({
|
||||
schemaVersion: 1,
|
||||
renderRevision: 19,
|
||||
currentRenderRevision: 19,
|
||||
status: "ACCEPTED",
|
||||
requestedPageIds: [0],
|
||||
requestedCount: 1,
|
||||
errorCode: null,
|
||||
});
|
||||
expect(result.manifestPageIoRequests).toEqual([{ pageId: 0, renderRevision: 19 }]);
|
||||
expect(result.manifestRanges.length).toBeGreaterThan(0);
|
||||
expect(result.manifestRanges).toEqual(result.declaredManifestRanges);
|
||||
expect(result.manifestRanges.every((range: { sha256: string }) => /^[a-f0-9]{64}$/.test(range.sha256))).toBe(true);
|
||||
expect(result.manifestPageMatchesPayload).toBe(true);
|
||||
expect(result.coalesced.rangeCalls).toBe(1);
|
||||
expect(result.coalesced.underlyingAborts).toBe(0);
|
||||
expect(result.coalesced.beforeCancel).toEqual({ pendingPages: 1, subscribers: 2, pageIds: [0] });
|
||||
expect(result.coalesced.afterFirstCancel).toEqual({ pendingPages: 1, subscribers: 1, pageIds: [0] });
|
||||
expect(result.coalesced.afterResolve).toEqual({ pendingPages: 0, subscribers: 0, pageIds: [] });
|
||||
expect(result.coalesced.outcomes[0]).toEqual({ status: "REJECTED", name: "AbortError" });
|
||||
expect(result.coalesced.outcomes[1].status).toBe("RESOLVED");
|
||||
expect(result.coalesced.consumers).toEqual(["second:0"]);
|
||||
expect(result.lastCancel.rangeCalls).toBe(1);
|
||||
expect(result.lastCancel.underlyingAborts).toBe(1);
|
||||
expect(result.lastCancel.afterFirst).toEqual({
|
||||
stats: { pendingPages: 1, subscribers: 1, pageIds: [0] },
|
||||
underlyingAborts: 0,
|
||||
});
|
||||
expect(result.lastCancel.afterLast).toEqual({ pendingPages: 0, subscribers: 0, pageIds: [] });
|
||||
expect(result.lastCancel.outcomes).toEqual([
|
||||
{ status: "REJECTED", name: "AbortError" },
|
||||
{ status: "REJECTED", name: "AbortError" },
|
||||
]);
|
||||
expect(result.tamperedPage).toEqual({
|
||||
rangeCalls: 1,
|
||||
residentWrites: 0,
|
||||
errorCode: "NANOVDB_HASH_MISMATCH",
|
||||
errorMessage: expect.stringContaining("NANOVDB_HASH_MISMATCH"),
|
||||
cache: {
|
||||
residentPageCount: 0,
|
||||
residentBytes: 0,
|
||||
residentVirtualPages: [],
|
||||
coordinator: { pendingPages: 0, subscribers: 0, pageIds: [] },
|
||||
},
|
||||
});
|
||||
expect(result.framePin).toEqual({
|
||||
pinnedPage0: true,
|
||||
pinnedMissingPage: false,
|
||||
afterPinnedEviction: {
|
||||
residentVirtualPages: [0, 2],
|
||||
evictionCount: 1,
|
||||
page0: true,
|
||||
page1: false,
|
||||
page2: true,
|
||||
},
|
||||
allPinnedError: expect.stringContaining("NANOVDB_GPU_BUDGET_EXCEEDED: all resident NanoVDB pages are pinned"),
|
||||
afterAllPinned: {
|
||||
residentVirtualPages: [0, 2],
|
||||
evictionCount: 1,
|
||||
page3: false,
|
||||
},
|
||||
afterNextFrame: {
|
||||
residentVirtualPages: [2, 3],
|
||||
evictionCount: 2,
|
||||
page0: false,
|
||||
page2: true,
|
||||
page3: true,
|
||||
},
|
||||
pageTable: [0xffffffff, 0xffffffff, 1, 0],
|
||||
});
|
||||
expect(result.progressiveRedraw).toEqual({
|
||||
firstUpload: { pageId: 0, redrawScheduled: true },
|
||||
secondUpload: { pageId: 1, redrawScheduled: false },
|
||||
failedUpload: expect.stringContaining("NANOVDB_STREAM_INCOMPLETE"),
|
||||
beforeFirst: {
|
||||
queuedFrames: 1,
|
||||
callbacks: 0,
|
||||
stats: { pending: true, scheduledCount: 1, redrawCount: 0, maxRedraws: 32, capped: false, errorCode: null },
|
||||
},
|
||||
afterFirst: {
|
||||
queuedFrames: 0,
|
||||
callbacks: 1,
|
||||
stats: { pending: false, scheduledCount: 1, redrawCount: 1, maxRedraws: 32, capped: false, errorCode: null },
|
||||
},
|
||||
thirdUpload: { pageId: 2, redrawScheduled: true },
|
||||
beforeSecond: {
|
||||
queuedFrames: 1,
|
||||
callbacks: 1,
|
||||
stats: { pending: true, scheduledCount: 2, redrawCount: 1, maxRedraws: 32, capped: false, errorCode: null },
|
||||
},
|
||||
afterSecond: {
|
||||
queuedFrames: 0,
|
||||
callbacks: 2,
|
||||
stats: { pending: false, scheduledCount: 2, redrawCount: 2, maxRedraws: 32, capped: false, errorCode: null },
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.progressiveRedrawCap).toEqual({
|
||||
cappedRedraw: {
|
||||
uploads: [
|
||||
{ pageId: 0, redrawScheduled: true },
|
||||
{ pageId: 0, redrawScheduled: true },
|
||||
{ pageId: 0, redrawScheduled: false },
|
||||
{ pageId: 0, redrawScheduled: false },
|
||||
],
|
||||
callbacks: 2,
|
||||
queuedFrames: 0,
|
||||
stats: { pending: false, scheduledCount: 2, redrawCount: 2, maxRedraws: 2, capped: true, errorCode: "NANOVDB_PROGRESSIVE_REDRAW_LIMIT" },
|
||||
},
|
||||
afterCappedReset: { pending: false, scheduledCount: 0, redrawCount: 0, maxRedraws: 2, capped: false, errorCode: null },
|
||||
});
|
||||
|
||||
expect(result.missingWordsZero).toBe(true);
|
||||
expect(result.overflowResult.status).toBe("OVERFLOW");
|
||||
expect(result.overflowResult.renderRevision).toBe(18);
|
||||
expect(result.overflowResult.errorCode).toBe("NANOVDB_PAGE_FEEDBACK_OVERFLOW");
|
||||
expect(result.overflowResult.attemptedCount).toBeGreaterThan(2);
|
||||
expect(result.overflowResult.gpuStoredCount).toBe(2);
|
||||
expect(result.overflowResult.uniqueCount).toBe(2);
|
||||
expect(new Set(result.overflowResult.pageIds).size).toBe(2);
|
||||
expect(result.overflowResult.pageIds).toEqual([...result.overflowResult.pageIds].sort((left, right) => left - right));
|
||||
expect(result.overflowResult.pageIds.every((pageId: number) => result.missingPageIds.includes(pageId))).toBe(true);
|
||||
expect(result.overflowGuard).toEqual(result.guardWords);
|
||||
});
|
||||
Reference in New Issue
Block a user