open-standards/wai/quantum-studio/test/hardware.test.mjs
Transaction Science 80528577db wai-quantum-qpu: cloud-tasks reads a job through the qubits it was sent on, and refuses what it could not read
A job's record keeps the device's own names for its program's qubits, and
collection reads through those without asking the device again. Logical qubits
are read from a row by label, so a qubit past the sixty-fourth can be read, and
one the program ended on that was not measured is an error. Region and bucket
are checked before they go into a host; a dotted bucket is read by path, from
the bucket the task names. An endpoint this kind would not use is refused. A
named credential that gives nothing is an error on every built-in kind, and
every part of the keys comes out of a message, whole or cut short. wai-qpu asks
for --yes wherever a job spends. A simulator's estimate says it is the minimum.
The client now has a fake that follows the service's contract, temporary keys
among what it checks.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-05 17:40:53 -05:00

167 lines
9.9 KiB
JavaScript

// The "Your hardware" logic, without a browser: a run that is not free asks
// the person first, a free one does not, a "no" sends nothing, and the
// dialog's words carry the estimate. A job in the provider's queue is asked
// after by its id; Cancel cancels it there, "Wait in the background" leaves
// it, and a job left waiting, by this window or an earlier one, gives its
// result when it finishes.
//
// node test/hardware.test.mjs
import { HardwareEngine, NOTE, confirmText, costText, jobLine, needsConfirmation } from '../src/hardware.js';
let fails = 0;
const check = (ok, what) => { console.log(`${ok ? 'PASS' : 'FAIL'} ${what}`); if (!ok) fails += 1; };
const plan = (free, estimate) => ({ free, estimate, provider: { name: 'lab', device: 'reference:line-5', provenance: 'simulator:x' }, plan: { shots: 100, compile: { native_gates: 12, basis: 'rzsxxcz', swaps: 0 } } });
const priced = plan(false, { free: false, amount: '0.3', currency: 'USD', unit: 'shot', seconds: 4 });
check(needsConfirmation(priced) && !needsConfirmation(plan(true, { free: true })), 'a run not stated free needs a confirmation, a free one does not');
check(needsConfirmation(plan(undefined, { unknown: 'no estimate' })), 'an unknown cost needs a confirmation');
check(costText(priced) === '0.3 USD (billed by the shot), about 4 s', `the cost in words (${costText(priced)})`);
check(costText(plan(false, { free: false, amount: '0.003750', currency: 'USD', unit: 'minute', at_least: true })) === 'at least 0.003750 USD (billed by the minute)', 'a minimum says it is one');
check(costText(plan(false, { unknown: 'the provider gives no estimate' })) === 'cost unknown: the provider gives no estimate', 'an unknown cost says so');
const words = confirmText(priced).join(' ');
check(/Run on lab \(reference:line-5/.test(words) && /not free: 0\.3 USD/.test(words) && /12 native gates in rzsxxcz/.test(words) && /spends your account/.test(words), `the dialog's words (${words})`);
check(/desktop app or the command line/.test(NOTE) && /must not hold the credentials/.test(NOTE), 'the browser note');
// The engine against fake desktop commands.
function fake(p) {
const calls = [];
const invoke = async (cmd, args) => {
calls.push([cmd, args]);
if (cmd === 'providers_list') return JSON.stringify({ providers: [{ name: 'lab', kind: 'process' }] });
if (cmd === 'provider_estimate') return JSON.stringify(p);
if (cmd === 'run_on_provider') return JSON.stringify({ status: 'done', method: 'provider', request: JSON.parse(args.request), result: { counts: { '00': 50, '11': 50 } } });
return JSON.stringify({ error: `no command ${cmd}` });
};
return { calls, invoke };
}
{
const f = fake(plan(true, { free: true }));
let asked = 0;
const e = new HardwareEngine(f.invoke, async () => { asked += 1; return true; });
check((await e.providers()).length === 1, 'the providers are listed');
e.select('lab');
const body = await e.run({ qasm: 'OPENQASM 3.0; qubit[2] q;', shots: 100 });
const run = f.calls.find((c) => c[0] === 'run_on_provider');
check(asked === 0 && run[1].confirmCost === false && body.request.provider === 'lab', 'a free run is not asked about, and names its provider');
}
{
const f = fake(priced);
const e = new HardwareEngine(f.invoke, async () => false);
e.select('lab');
let err = '';
try { await e.run({ qasm: 'q', shots: 100 }); } catch (x) { err = x.message; }
check(err === 'cancelled' && !f.calls.some((c) => c[0] === 'run_on_provider'), 'a run not free, declined, sends nothing');
}
{
const f = fake(priced);
let shown = null;
const e = new HardwareEngine(f.invoke, async (p) => { shown = p; return true; });
e.select('lab');
await e.run({ qasm: 'q', shots: 100 });
const run = f.calls.find((c) => c[0] === 'run_on_provider');
check(shown === null ? false : shown.estimate.amount === '0.3', 'the dialog is shown the estimate');
check(run && run[1].confirmCost === true, 'a run not free, accepted, is sent confirmed');
}
{
const e = new HardwareEngine(fake(priced).invoke, async () => true);
let err = '';
try { await e.run({ qasm: 'q' }); } catch (x) { err = x.message; }
check(/choose one of your providers/.test(err), 'no provider chosen, no run');
}
// A job that waits in the provider's queue: the run asks after it by its id
// until it finishes, and the person can cancel it or leave it waiting.
function queue({ polls = 2, done = { '00': 50, '11': 50 }, failOnce = false } = {}) {
const calls = [];
const jobs = new Map(); // id -> {left, cancelled}
let failed = !failOnce;
let n = 0;
const request = { qasm: 'q', shots: 100, provider: 'lab' };
const body = (id) => ({ id, status: 'done', method: 'provider', request, result: { counts: done } });
const invoke = async (cmd, args) => {
calls.push([cmd, args]);
if (cmd === 'provider_estimate') return JSON.stringify(plan(true, { free: true }));
if (cmd === 'run_on_provider') {
const id = `pj-${String(++n).padStart(16, '0')}`;
jobs.set(id, { left: polls, cancelled: false });
return JSON.stringify({ id, status: 'running', method: 'provider', request });
}
if (cmd === 'provider_jobs') return JSON.stringify({ jobs: [...jobs].map(([id, j]) => ({ id, provider: 'lab', shots: 100, status: j.cancelled ? 'cancelled' : j.left > 0 ? 'running' : 'done', submitted_ms: 0 })) });
if (cmd === 'provider_job') {
const j = jobs.get(args.id);
if (!j) return JSON.stringify({ error: `no job ${args.id}` });
if (!failed) { failed = true; return JSON.stringify({ error: `could not ask after ${args.id}, and nothing about the job has changed; asking again is safe: the network is down` }); }
if (j.cancelled) return JSON.stringify({ id: args.id, status: 'cancelled', error: 'cancelled at lab', request });
if (j.left > 0 && args.cancel) { j.cancelled = true; return JSON.stringify({ id: args.id, status: 'cancelled', error: 'cancelled at lab', request }); }
if (j.left > 0) { j.left -= 1; return JSON.stringify({ id: args.id, status: 'running', method: 'provider', request }); }
return JSON.stringify(body(args.id));
}
return JSON.stringify({ error: `no command ${cmd}` });
};
return { calls, invoke, jobs };
}
const fast = { first: 0, most: 0 };
const asks = (calls) => calls.filter((c) => c[0] === 'provider_job');
{
const q = queue({ polls: 2 });
const e = new HardwareEngine(q.invoke, async () => true, fast);
e.select('lab');
const seen = [];
const body = await e.run({ qasm: 'q', shots: 100 }, (j, asked) => seen.push([j.status, asked, e.progressText(j, asked)]));
check(body.status === 'done' && body.result.counts['00'] === 50 && asks(q.calls).length === 3 && asks(q.calls).every((c) => c[1].cancel === false && c[1].id === body.id),
`a queued job is asked after by its id until it finishes (${asks(q.calls).length} asks)`);
check(seen.length === 3 && /^At lab, queued or running, as pj-0+1; asked 0 times\. Closing the app leaves it there\.$/.test(seen[0][2]), `the status line while it waits (${seen[0]?.[2]})`);
}
{
const q = queue({ polls: 5 });
const e = new HardwareEngine(q.invoke, async () => true, fast);
e.select('lab');
let err = '';
try { await e.run({ qasm: 'q', shots: 100 }, (j, asked) => { if (asked === 1) e.cancel(); }); } catch (x) { err = x.message; }
const last = asks(q.calls).at(-1);
check(err === 'cancelled' && last[1].cancel === true && [...q.jobs.values()][0].cancelled, 'Cancel while a job waits cancels it at the provider');
}
{
const q = queue({ polls: 0 });
const e = new HardwareEngine(q.invoke, async () => true, fast);
e.select('lab');
const body = await e.run({ qasm: 'q', shots: 100 }, () => e.cancel());
check(body.status === 'done', 'a job that finished before the cancel reached it gives its result: it has been paid for');
}
{
const q = queue({ polls: 2, failOnce: true });
const e = new HardwareEngine(q.invoke, async () => true, fast);
e.select('lab');
const seen = [];
const body = await e.run({ qasm: 'q', shots: 100 }, (j, asked, failed) => seen.push(e.progressText(j, asked, failed)));
check(body.status === 'done' && seen.some((s) => /The last check failed, and nothing about the job changed: could not ask after/.test(s)), 'a check that fails does not end the wait, and says so');
}
{
const q = queue({ polls: 4 });
const e = new HardwareEngine(q.invoke, async () => true, fast);
e.select('lab');
const finished = new Promise((resolve) => { e.onFinished = resolve; });
let err = null;
try { await e.run({ qasm: 'q', shots: 100 }, (j, asked) => { if (asked === 1) e.later(); }); } catch (x) { err = x; }
check(err?.later === true && /^pj-0+1 is still at lab\. It is followed from here/.test(err.message) && ![...q.jobs.values()][0].cancelled, `"Wait in the background" leaves the job at the provider, not cancelled (${err?.message})`);
const body = await finished;
check(body.status === 'done' && body.id === 'pj-0000000000000001' && asks(q.calls).every((c) => c[1].cancel === false), 'and the job, followed in the background, gives its result when it finishes');
}
{
const q = queue({ polls: 3 });
const first = new HardwareEngine(q.invoke, async () => true, fast);
first.select('lab');
try { await first.run({ qasm: 'q', shots: 100 }, () => first.later()); } catch (x) {}
// The app opened again: a new engine, the records kept.
const again = new HardwareEngine(q.invoke, async () => true, fast);
const finished = new Promise((resolve) => { again.onFinished = resolve; });
await again.resume();
check(again.watched.size === 1 && (await finished).status === 'done', 'a job left waiting by an earlier window is followed when the app opens again');
const listed = await again.jobs();
check(listed.length === 1 && jobLine(listed[0], () => 'then') === 'pj-0000000000000001 · lab · 100 shots · finished · sent then', `the jobs sent, in words (${jobLine(listed[0], () => 'then')})`);
}
if (fails) { console.error(`${fails} failed`); process.exit(1); }
console.log('hardware: every check held');
process.exit(0);