@sdeverywhere/check-core 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1227 -439
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +499 -105
- package/dist/index.d.ts +499 -105
- package/dist/index.js +1218 -437
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -68,51 +68,203 @@ var src_exports = {};
|
|
|
68
68
|
__export(src_exports, {
|
|
69
69
|
CheckDataCoordinator: () => CheckDataCoordinator,
|
|
70
70
|
ComparisonDataCoordinator: () => ComparisonDataCoordinator,
|
|
71
|
-
PerfRunner: () => PerfRunner,
|
|
72
71
|
PerfStats: () => PerfStats,
|
|
73
72
|
categorizeComparisonTestSummaries: () => categorizeComparisonTestSummaries,
|
|
74
73
|
checkReportFromSummary: () => checkReportFromSummary,
|
|
75
74
|
checkSummaryFromReport: () => checkSummaryFromReport,
|
|
76
75
|
comparisonSummaryFromReport: () => comparisonSummaryFromReport,
|
|
76
|
+
createCheckDataCoordinator: () => createCheckDataCoordinator,
|
|
77
|
+
createCheckDataCoordinatorForTests: () => createCheckDataCoordinatorForTests,
|
|
78
|
+
createComparisonDataCoordinator: () => createComparisonDataCoordinator,
|
|
77
79
|
createConfig: () => createConfig,
|
|
78
80
|
datasetMessage: () => datasetMessage,
|
|
81
|
+
decodeImplVars: () => decodeImplVars,
|
|
79
82
|
diffDatasets: () => diffDatasets,
|
|
80
83
|
diffGraphs: () => diffGraphs,
|
|
84
|
+
encodeImplVars: () => encodeImplVars,
|
|
81
85
|
getScoresForTestSummaries: () => getScoresForTestSummaries,
|
|
82
86
|
predicateMessage: () => predicateMessage,
|
|
87
|
+
runPerf: () => runPerf,
|
|
83
88
|
runSuite: () => runSuite,
|
|
89
|
+
runTrace: () => runTrace,
|
|
84
90
|
scenarioMessage: () => scenarioMessage,
|
|
85
|
-
suiteSummaryFromReport: () => suiteSummaryFromReport
|
|
91
|
+
suiteSummaryFromReport: () => suiteSummaryFromReport,
|
|
92
|
+
testSummaryFromReport: () => testSummaryFromReport
|
|
86
93
|
});
|
|
87
94
|
module.exports = __toCommonJS(src_exports);
|
|
88
95
|
|
|
96
|
+
// src/bundle/impl-vars-codec.ts
|
|
97
|
+
function encodeImplVars(input) {
|
|
98
|
+
const subscripts = [];
|
|
99
|
+
const variables = [];
|
|
100
|
+
const varTypes = [];
|
|
101
|
+
const varInstances = {};
|
|
102
|
+
const subscriptMap = /* @__PURE__ */ new Map();
|
|
103
|
+
const variableMap = /* @__PURE__ */ new Map();
|
|
104
|
+
const varTypeMap = /* @__PURE__ */ new Map();
|
|
105
|
+
for (const [groupKey, implVars] of Object.entries(input)) {
|
|
106
|
+
const instances = [];
|
|
107
|
+
for (const implVar of implVars) {
|
|
108
|
+
const varIdInfo = parseSubscripts(implVar.varId);
|
|
109
|
+
const varNameInfo = parseSubscripts(implVar.varName);
|
|
110
|
+
let varTypeIndex = varTypeMap.get(implVar.varType);
|
|
111
|
+
if (varTypeIndex === void 0) {
|
|
112
|
+
varTypeIndex = varTypes.length;
|
|
113
|
+
varTypes.push(implVar.varType);
|
|
114
|
+
varTypeMap.set(implVar.varType, varTypeIndex);
|
|
115
|
+
}
|
|
116
|
+
let variableIndex = variableMap.get(implVar.varIndex);
|
|
117
|
+
if (variableIndex === void 0) {
|
|
118
|
+
variableIndex = variables.length;
|
|
119
|
+
variables.push({
|
|
120
|
+
n: varNameInfo.base,
|
|
121
|
+
i: varIdInfo.base,
|
|
122
|
+
x: implVar.varIndex
|
|
123
|
+
});
|
|
124
|
+
variableMap.set(implVar.varIndex, variableIndex);
|
|
125
|
+
}
|
|
126
|
+
let subscriptIndices;
|
|
127
|
+
let subscriptValues;
|
|
128
|
+
if (varIdInfo.subscripts.length > 0) {
|
|
129
|
+
subscriptIndices = [];
|
|
130
|
+
subscriptValues = implVar.subscriptIndices || [];
|
|
131
|
+
for (let i = 0; i < varIdInfo.subscripts.length; i++) {
|
|
132
|
+
const subscriptId = varIdInfo.subscripts[i];
|
|
133
|
+
const subscriptName = varNameInfo.subscripts[i];
|
|
134
|
+
let subscriptIndex = subscriptMap.get(subscriptId);
|
|
135
|
+
if (subscriptIndex === void 0) {
|
|
136
|
+
subscriptIndex = subscripts.length;
|
|
137
|
+
subscripts.push({
|
|
138
|
+
n: subscriptName,
|
|
139
|
+
i: subscriptId
|
|
140
|
+
});
|
|
141
|
+
subscriptMap.set(subscriptId, subscriptIndex);
|
|
142
|
+
}
|
|
143
|
+
subscriptIndices.push(subscriptIndex);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const instance = [varTypeIndex, variableIndex];
|
|
147
|
+
if (subscriptIndices) {
|
|
148
|
+
instance.push(...subscriptIndices, ...subscriptValues);
|
|
149
|
+
}
|
|
150
|
+
instances.push(instance);
|
|
151
|
+
}
|
|
152
|
+
varInstances[groupKey] = instances;
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
subscripts,
|
|
156
|
+
variables,
|
|
157
|
+
varTypes,
|
|
158
|
+
varInstances
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function decodeImplVars(encoded) {
|
|
162
|
+
const result = {};
|
|
163
|
+
for (const [groupKey, instances] of Object.entries(encoded.varInstances)) {
|
|
164
|
+
const implVars = [];
|
|
165
|
+
for (const instance of instances) {
|
|
166
|
+
const varType = encoded.varTypes[instance[0]];
|
|
167
|
+
const variable = encoded.variables[instance[1]];
|
|
168
|
+
let varId = variable.i;
|
|
169
|
+
let varName = variable.n;
|
|
170
|
+
if (instance.length > 2) {
|
|
171
|
+
const subscriptIds = [];
|
|
172
|
+
const subscriptNames = [];
|
|
173
|
+
const subscriptCount = (instance.length - 2) / 2;
|
|
174
|
+
const subscriptIndices = instance.slice(2, 2 + subscriptCount);
|
|
175
|
+
for (const subscriptIndex of subscriptIndices) {
|
|
176
|
+
const subscript = encoded.subscripts[subscriptIndex];
|
|
177
|
+
subscriptIds.push(subscript.i);
|
|
178
|
+
subscriptNames.push(subscript.n);
|
|
179
|
+
}
|
|
180
|
+
varId += `[${subscriptIds.join(",")}]`;
|
|
181
|
+
varName += `[${subscriptNames.join(",")}]`;
|
|
182
|
+
}
|
|
183
|
+
const implVar = {
|
|
184
|
+
varId,
|
|
185
|
+
varName,
|
|
186
|
+
varType,
|
|
187
|
+
varIndex: variable.x,
|
|
188
|
+
subscriptIndices: instance.length > 2 ? instance.slice(2 + (instance.length - 2) / 2) : void 0
|
|
189
|
+
};
|
|
190
|
+
implVars.push(implVar);
|
|
191
|
+
}
|
|
192
|
+
result[groupKey] = implVars;
|
|
193
|
+
}
|
|
194
|
+
return result;
|
|
195
|
+
}
|
|
196
|
+
function parseSubscripts(text) {
|
|
197
|
+
const bracketIndex = text.indexOf("[");
|
|
198
|
+
if (bracketIndex === -1) {
|
|
199
|
+
return { base: text, subscripts: [] };
|
|
200
|
+
}
|
|
201
|
+
const base = text.substring(0, bracketIndex);
|
|
202
|
+
const subscriptText = text.substring(bracketIndex + 1, text.lastIndexOf("]"));
|
|
203
|
+
const subscripts = subscriptText.split(",").map((s) => s.trim());
|
|
204
|
+
return { base, subscripts };
|
|
205
|
+
}
|
|
206
|
+
|
|
89
207
|
// src/_shared/task-queue.ts
|
|
90
|
-
var TaskQueue = class {
|
|
91
|
-
|
|
92
|
-
|
|
208
|
+
var TaskQueue = class _TaskQueue {
|
|
209
|
+
/**
|
|
210
|
+
* @param executors The map of available task executors.
|
|
211
|
+
*/
|
|
212
|
+
constructor(executors) {
|
|
213
|
+
this.executors = executors;
|
|
93
214
|
/** The queue of task keys, most recent at front. */
|
|
94
215
|
this.taskKeyQueue = [];
|
|
95
216
|
/** The map of tasks. */
|
|
96
217
|
this.taskMap = /* @__PURE__ */ new Map();
|
|
218
|
+
// /** The set of keys for the executors that are currently processing tasks. */
|
|
219
|
+
// private readonly activeExecutorKeys: Set<TaskExecutorKey> = new Set()
|
|
220
|
+
/** The idle event listeners. */
|
|
221
|
+
this.idleListeners = [];
|
|
97
222
|
/** Whether tasks are being processed. */
|
|
98
223
|
this.processing = false;
|
|
99
224
|
/** Whether `shutdown` has been called. */
|
|
100
225
|
this.stopped = false;
|
|
101
226
|
}
|
|
102
|
-
|
|
227
|
+
/**
|
|
228
|
+
* Initialize the shared `TaskQueue` instance.
|
|
229
|
+
*
|
|
230
|
+
* @param executors The map of available task executors.
|
|
231
|
+
*/
|
|
232
|
+
static initialize(executors) {
|
|
233
|
+
if (executors.size === 0) {
|
|
234
|
+
throw new Error("Must provide at least one executor");
|
|
235
|
+
}
|
|
236
|
+
this.instance = new _TaskQueue(executors);
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Get the shared `TaskQueue` instance.
|
|
240
|
+
*/
|
|
241
|
+
static getInstance() {
|
|
242
|
+
if (!this.instance) {
|
|
243
|
+
throw new Error("TaskQueue not initialized; must call `initialize` first");
|
|
244
|
+
}
|
|
245
|
+
return this.instance;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Add a task to the queue.
|
|
249
|
+
*
|
|
250
|
+
* @param task The task to add.
|
|
251
|
+
*/
|
|
252
|
+
addTask(task) {
|
|
103
253
|
if (this.stopped) {
|
|
104
254
|
return;
|
|
105
255
|
}
|
|
106
|
-
if (this.taskMap.has(key)) {
|
|
107
|
-
throw new Error(`Task already added for key ${key}`);
|
|
256
|
+
if (this.taskMap.has(task.key)) {
|
|
257
|
+
throw new Error(`Task already added for key ${task.key}`);
|
|
108
258
|
}
|
|
109
|
-
this.taskKeyQueue.push(key);
|
|
110
|
-
this.taskMap.set(key,
|
|
111
|
-
input,
|
|
112
|
-
onComplete
|
|
113
|
-
});
|
|
259
|
+
this.taskKeyQueue.push(task.key);
|
|
260
|
+
this.taskMap.set(task.key, task);
|
|
114
261
|
this.processTasksIfNeeded();
|
|
115
262
|
}
|
|
263
|
+
/**
|
|
264
|
+
* Cancel a task.
|
|
265
|
+
*
|
|
266
|
+
* @param taskKey The key of the task to cancel.
|
|
267
|
+
*/
|
|
116
268
|
cancelTask(taskKey) {
|
|
117
269
|
const index = this.taskKeyQueue.indexOf(taskKey);
|
|
118
270
|
if (index >= 0) {
|
|
@@ -120,9 +272,37 @@ var TaskQueue = class {
|
|
|
120
272
|
}
|
|
121
273
|
this.taskMap.delete(taskKey);
|
|
122
274
|
}
|
|
275
|
+
/**
|
|
276
|
+
* Add an idle listener.
|
|
277
|
+
*
|
|
278
|
+
* @param listener The listener to add.
|
|
279
|
+
*/
|
|
280
|
+
onIdle(listener) {
|
|
281
|
+
this.idleListeners.push(listener);
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Remove an idle listener.
|
|
285
|
+
*
|
|
286
|
+
* @param listener The listener to remove.
|
|
287
|
+
*/
|
|
288
|
+
removeIdleListener(listener) {
|
|
289
|
+
this.idleListeners.splice(this.idleListeners.indexOf(listener), 1);
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Notify the idle listeners.
|
|
293
|
+
*
|
|
294
|
+
* @param error The error to notify the listeners with.
|
|
295
|
+
*/
|
|
296
|
+
notifyIdle(error) {
|
|
297
|
+
for (const listener of this.idleListeners) {
|
|
298
|
+
listener(error);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Shutdown the task queue, cancelling all pending tasks.
|
|
303
|
+
*/
|
|
123
304
|
shutdown() {
|
|
124
305
|
this.stopped = true;
|
|
125
|
-
this.processing = false;
|
|
126
306
|
this.taskKeyQueue.length = 0;
|
|
127
307
|
this.taskMap.clear();
|
|
128
308
|
}
|
|
@@ -130,75 +310,98 @@ var TaskQueue = class {
|
|
|
130
310
|
if (!this.stopped && !this.processing) {
|
|
131
311
|
this.processing = true;
|
|
132
312
|
setTimeout(() => {
|
|
133
|
-
this.
|
|
313
|
+
this.processNextTasks();
|
|
134
314
|
});
|
|
135
315
|
}
|
|
136
316
|
}
|
|
137
|
-
|
|
317
|
+
processNextTasks() {
|
|
138
318
|
return __async(this, null, function* () {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
319
|
+
const taskKeys = this.taskKeyQueue.splice(0, this.executors.size);
|
|
320
|
+
if (taskKeys.length === 0) {
|
|
321
|
+
this.processing = false;
|
|
322
|
+
if (!this.stopped) {
|
|
323
|
+
this.notifyIdle();
|
|
324
|
+
}
|
|
142
325
|
return;
|
|
143
326
|
}
|
|
144
|
-
const
|
|
145
|
-
|
|
327
|
+
const executeCalls = [];
|
|
328
|
+
const availableExecutorKeys = Array.from(this.executors.keys());
|
|
329
|
+
for (const taskKey of taskKeys) {
|
|
330
|
+
const task = this.taskMap.get(taskKey);
|
|
331
|
+
if (!task) {
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
146
334
|
this.taskMap.delete(taskKey);
|
|
147
|
-
|
|
148
|
-
|
|
335
|
+
const executorKey = availableExecutorKeys.shift();
|
|
336
|
+
const executor = this.executors.get(executorKey);
|
|
337
|
+
if (!executor) {
|
|
338
|
+
throw new Error(`No executor found for key ${executorKey}`);
|
|
339
|
+
}
|
|
340
|
+
executeCalls.push(executor.execute(task));
|
|
149
341
|
}
|
|
150
|
-
let output;
|
|
151
342
|
try {
|
|
152
|
-
|
|
343
|
+
yield Promise.all(executeCalls);
|
|
153
344
|
} catch (e) {
|
|
154
345
|
if (!this.stopped) {
|
|
155
346
|
this.shutdown();
|
|
156
|
-
|
|
347
|
+
this.notifyIdle(e);
|
|
157
348
|
}
|
|
158
349
|
return;
|
|
159
350
|
}
|
|
160
|
-
task.onComplete(output);
|
|
161
351
|
if (this.taskKeyQueue.length > 0) {
|
|
162
352
|
setTimeout(() => {
|
|
163
|
-
this.
|
|
353
|
+
this.processNextTasks();
|
|
164
354
|
});
|
|
165
355
|
} else {
|
|
166
356
|
this.processing = false;
|
|
167
357
|
if (!this.stopped) {
|
|
168
|
-
|
|
358
|
+
this.notifyIdle();
|
|
169
359
|
}
|
|
170
360
|
}
|
|
171
361
|
});
|
|
172
362
|
}
|
|
173
363
|
};
|
|
364
|
+
function createExecutor(bundleModelL, bundleModelR) {
|
|
365
|
+
return {
|
|
366
|
+
execute: (task) => __async(this, null, function* () {
|
|
367
|
+
return task.process({
|
|
368
|
+
L: bundleModelL,
|
|
369
|
+
R: bundleModelR
|
|
370
|
+
});
|
|
371
|
+
})
|
|
372
|
+
};
|
|
373
|
+
}
|
|
174
374
|
|
|
175
375
|
// src/check/check-data-coordinator.ts
|
|
176
376
|
var CheckDataCoordinator = class {
|
|
177
|
-
constructor(
|
|
178
|
-
this.
|
|
179
|
-
this.taskQueue = new TaskQueue({
|
|
180
|
-
process: (request) => __async(this, null, function* () {
|
|
181
|
-
const result = yield this.bundleModel.getDatasetsForScenario(request.scenarioSpec, [request.datasetKey]);
|
|
182
|
-
const dataset = result.datasetMap.get(request.datasetKey);
|
|
183
|
-
return {
|
|
184
|
-
dataset
|
|
185
|
-
};
|
|
186
|
-
})
|
|
187
|
-
});
|
|
377
|
+
constructor(taskQueue) {
|
|
378
|
+
this.taskQueue = taskQueue;
|
|
188
379
|
}
|
|
189
380
|
requestDataset(requestKey, scenarioSpec, datasetKey, onResponse) {
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
381
|
+
const task = {
|
|
382
|
+
key: requestKey,
|
|
383
|
+
kind: "check-data-coordinator",
|
|
384
|
+
process: (bundleModels) => __async(this, null, function* () {
|
|
385
|
+
const bundleModelR = bundleModels.R;
|
|
386
|
+
const result = yield bundleModelR.getDatasetsForScenario(scenarioSpec, [datasetKey]);
|
|
387
|
+
const dataset = result.datasetMap.get(datasetKey);
|
|
388
|
+
onResponse(dataset);
|
|
389
|
+
})
|
|
193
390
|
};
|
|
194
|
-
this.taskQueue.addTask(
|
|
195
|
-
onResponse(response.dataset);
|
|
196
|
-
});
|
|
391
|
+
this.taskQueue.addTask(task);
|
|
197
392
|
}
|
|
198
393
|
cancelRequest(key) {
|
|
199
394
|
this.taskQueue.cancelTask(key);
|
|
200
395
|
}
|
|
201
396
|
};
|
|
397
|
+
function createCheckDataCoordinator() {
|
|
398
|
+
return new CheckDataCoordinator(TaskQueue.getInstance());
|
|
399
|
+
}
|
|
400
|
+
function createCheckDataCoordinatorForTests(bundleModel) {
|
|
401
|
+
const executor = createExecutor(void 0, bundleModel);
|
|
402
|
+
const taskQueue = new TaskQueue(/* @__PURE__ */ new Map([["test-executor-0", executor]]));
|
|
403
|
+
return new CheckDataCoordinator(taskQueue);
|
|
404
|
+
}
|
|
202
405
|
|
|
203
406
|
// src/check/check-report.ts
|
|
204
407
|
var import_assert_never2 = __toESM(require("assert-never"), 1);
|
|
@@ -260,6 +463,10 @@ function buildCheckReport(checkPlan, checkResults) {
|
|
|
260
463
|
testStatus = "failed";
|
|
261
464
|
scenarioStatus = "failed";
|
|
262
465
|
datasetStatus = "failed";
|
|
466
|
+
} else if (checkResult.status === "skipped" && testStatus === "passed") {
|
|
467
|
+
testStatus = "skipped";
|
|
468
|
+
scenarioStatus = "skipped";
|
|
469
|
+
datasetStatus = "skipped";
|
|
263
470
|
}
|
|
264
471
|
}
|
|
265
472
|
predicateReports.push(predicateReport(predicatePlan, checkKey, checkResult));
|
|
@@ -1195,16 +1402,6 @@ function actionForPredicate(predicateSpec) {
|
|
|
1195
1402
|
};
|
|
1196
1403
|
}
|
|
1197
1404
|
|
|
1198
|
-
// src/_shared/combo.ts
|
|
1199
|
-
function cartesianProductOf(arr) {
|
|
1200
|
-
return arr.reduce(
|
|
1201
|
-
(a, b) => {
|
|
1202
|
-
return a.map((x) => b.map((y) => x.concat([y]))).reduce((v, w) => v.concat(w), []);
|
|
1203
|
-
},
|
|
1204
|
-
[[]]
|
|
1205
|
-
);
|
|
1206
|
-
}
|
|
1207
|
-
|
|
1208
1405
|
// src/check/check-dataset.ts
|
|
1209
1406
|
function expandDatasets(modelSpec, datasetSpec) {
|
|
1210
1407
|
var _a;
|
|
@@ -1233,25 +1430,10 @@ function expandDatasets(modelSpec, datasetSpec) {
|
|
|
1233
1430
|
name: match.outputVar.varName
|
|
1234
1431
|
});
|
|
1235
1432
|
} else if (match.implVar) {
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
const subscriptCombos = cartesianProductOf(subscripts);
|
|
1241
|
-
for (const subscriptCombo of subscriptCombos) {
|
|
1242
|
-
const subIdParts = subscriptCombo.map((sub) => `[${sub.id}]`).join("");
|
|
1243
|
-
const subNameParts = subscriptCombo.map((sub) => sub.name).join(",");
|
|
1244
|
-
checkDatasets.push({
|
|
1245
|
-
datasetKey: `${baseDatasetKey}${subIdParts}`,
|
|
1246
|
-
name: `${implVar.varName}[${subNameParts}]`
|
|
1247
|
-
});
|
|
1248
|
-
}
|
|
1249
|
-
} else {
|
|
1250
|
-
checkDatasets.push({
|
|
1251
|
-
datasetKey: match.datasetKey,
|
|
1252
|
-
name: implVar.varName
|
|
1253
|
-
});
|
|
1254
|
-
}
|
|
1433
|
+
checkDatasets.push({
|
|
1434
|
+
datasetKey: match.datasetKey,
|
|
1435
|
+
name: match.implVar.varName
|
|
1436
|
+
});
|
|
1255
1437
|
}
|
|
1256
1438
|
}
|
|
1257
1439
|
return checkDatasets;
|
|
@@ -1659,12 +1841,18 @@ var CheckPlanner = class {
|
|
|
1659
1841
|
this.dataRefs = /* @__PURE__ */ new Map();
|
|
1660
1842
|
this.checkKey = 1;
|
|
1661
1843
|
}
|
|
1662
|
-
addAllChecks(checkSpec,
|
|
1844
|
+
addAllChecks(checkSpec, skipChecks) {
|
|
1845
|
+
function skipCheckKey(groupName, testName) {
|
|
1846
|
+
return `${groupName.toLowerCase()} :: ${testName.toLowerCase()}`;
|
|
1847
|
+
}
|
|
1848
|
+
const skipChecksSet = new Set(skipChecks.map((check) => skipCheckKey(check.groupName, check.testName)));
|
|
1663
1849
|
for (const groupSpec of checkSpec.groups) {
|
|
1664
1850
|
const groupName = groupSpec.describe;
|
|
1665
1851
|
const planTests = [];
|
|
1666
1852
|
for (const testSpec of groupSpec.tests) {
|
|
1667
1853
|
const testName = testSpec.it;
|
|
1854
|
+
const shouldSkip = skipChecksSet.has(skipCheckKey(groupName, testName));
|
|
1855
|
+
const simplifyScenarios = false;
|
|
1668
1856
|
const checkScenarios = expandScenarios(this.modelSpec, testSpec.scenarios || [], simplifyScenarios);
|
|
1669
1857
|
const checkDatasets = [];
|
|
1670
1858
|
for (const datasetSpec of testSpec.datasets) {
|
|
@@ -1705,7 +1893,8 @@ var CheckPlanner = class {
|
|
|
1705
1893
|
scenario: checkScenario,
|
|
1706
1894
|
dataset: checkDataset,
|
|
1707
1895
|
action: checkAction,
|
|
1708
|
-
dataRefs
|
|
1896
|
+
dataRefs,
|
|
1897
|
+
skip: shouldSkip
|
|
1709
1898
|
});
|
|
1710
1899
|
}
|
|
1711
1900
|
planDatasets.push({
|
|
@@ -1842,6 +2031,7 @@ function checkSummaryFromReport(checkReport) {
|
|
|
1842
2031
|
break;
|
|
1843
2032
|
case "failed":
|
|
1844
2033
|
case "error":
|
|
2034
|
+
case "skipped":
|
|
1845
2035
|
predicateSummaries.push({
|
|
1846
2036
|
checkKey: predicate.checkKey,
|
|
1847
2037
|
result: predicate.result
|
|
@@ -1859,14 +2049,14 @@ function checkSummaryFromReport(checkReport) {
|
|
|
1859
2049
|
predicateSummaries
|
|
1860
2050
|
};
|
|
1861
2051
|
}
|
|
1862
|
-
function checkReportFromSummary(checkConfig, checkSummary) {
|
|
2052
|
+
function checkReportFromSummary(checkConfig, checkSummary, skipChecks = []) {
|
|
1863
2053
|
const checkSpecResult = parseTestYaml(checkConfig.tests);
|
|
1864
2054
|
if (checkSpecResult.isErr()) {
|
|
1865
2055
|
return void 0;
|
|
1866
2056
|
}
|
|
1867
2057
|
const checkSpec = checkSpecResult.value;
|
|
1868
|
-
const checkPlanner = new CheckPlanner(checkConfig.bundle.
|
|
1869
|
-
checkPlanner.addAllChecks(checkSpec,
|
|
2058
|
+
const checkPlanner = new CheckPlanner(checkConfig.bundle.modelSpec);
|
|
2059
|
+
checkPlanner.addAllChecks(checkSpec, skipChecks);
|
|
1870
2060
|
const checkPlan = checkPlanner.buildPlan();
|
|
1871
2061
|
const checkResults = /* @__PURE__ */ new Map();
|
|
1872
2062
|
for (const predicateSummary of checkSummary.predicateSummaries) {
|
|
@@ -1876,98 +2066,115 @@ function checkReportFromSummary(checkConfig, checkSummary) {
|
|
|
1876
2066
|
}
|
|
1877
2067
|
|
|
1878
2068
|
// src/comparison/run/comparison-data-coordinator.ts
|
|
1879
|
-
var import_assert_never7 = require("assert-never");
|
|
1880
2069
|
var ComparisonDataCoordinator = class {
|
|
1881
|
-
constructor(
|
|
1882
|
-
this.
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
2070
|
+
constructor(taskQueue) {
|
|
2071
|
+
this.taskQueue = taskQueue;
|
|
2072
|
+
}
|
|
2073
|
+
/**
|
|
2074
|
+
* Request datasets from the two models.
|
|
2075
|
+
*
|
|
2076
|
+
* @param requestKey The unique key for the request.
|
|
2077
|
+
* @param sourceL The source of the first ("left") dataset. If "left", the datasets will
|
|
2078
|
+
* be fetched from the "left" bundle's model, otherwise they will be fetched from the
|
|
2079
|
+
* "right" bundle's model.
|
|
2080
|
+
* @param scenarioSpecL The scenario used for the first ("left") model of the comparison.
|
|
2081
|
+
* @param sourceR The source of the second ("right") dataset. If "left", the datasets
|
|
2082
|
+
* will be fetched from the "left" bundle's model, otherwise they will be fetched from
|
|
2083
|
+
* the "right" bundle's model.
|
|
2084
|
+
* @param scenarioSpecR The scenario used for the second ("right") model of the comparison.
|
|
2085
|
+
* @param graphId The keys of the datasets to be fetched.
|
|
2086
|
+
* @param onResponse The callback that will be called with the dataset maps.
|
|
2087
|
+
*/
|
|
2088
|
+
requestDatasetMaps(requestKey, sourceL, scenarioSpecL, sourceR, scenarioSpecR, datasetKeys, onResponse) {
|
|
2089
|
+
function fetchDatasets(bundleModel, scenarioSpec) {
|
|
2090
|
+
return __async(this, null, function* () {
|
|
2091
|
+
if (scenarioSpec) {
|
|
2092
|
+
return bundleModel.getDatasetsForScenario(scenarioSpec, datasetKeys);
|
|
2093
|
+
} else {
|
|
2094
|
+
return void 0;
|
|
1893
2095
|
}
|
|
2096
|
+
});
|
|
2097
|
+
}
|
|
2098
|
+
const task = {
|
|
2099
|
+
key: requestKey,
|
|
2100
|
+
kind: "comparison-data-coordinator",
|
|
2101
|
+
process: (bundleModels) => __async(this, null, function* () {
|
|
2102
|
+
const modelL = sourceL === "left" ? bundleModels.L : bundleModels.R;
|
|
2103
|
+
const modelR = sourceR === "left" ? bundleModels.L : bundleModels.R;
|
|
2104
|
+
let resultL;
|
|
2105
|
+
let resultR;
|
|
2106
|
+
if (modelL === modelR) {
|
|
2107
|
+
resultL = yield fetchDatasets(modelL, scenarioSpecL);
|
|
2108
|
+
resultR = yield fetchDatasets(modelR, scenarioSpecR);
|
|
2109
|
+
} else {
|
|
2110
|
+
const results = yield Promise.all([
|
|
2111
|
+
fetchDatasets(modelL, scenarioSpecL),
|
|
2112
|
+
fetchDatasets(modelR, scenarioSpecR)
|
|
2113
|
+
]);
|
|
2114
|
+
resultL = results[0];
|
|
2115
|
+
resultR = results[1];
|
|
2116
|
+
}
|
|
2117
|
+
onResponse(resultL == null ? void 0 : resultL.datasetMap, resultR == null ? void 0 : resultR.datasetMap);
|
|
1894
2118
|
})
|
|
1895
|
-
});
|
|
1896
|
-
}
|
|
1897
|
-
processDatasetRequest(request) {
|
|
1898
|
-
return __async(this, null, function* () {
|
|
1899
|
-
function fetchDatasets(bundleModel, scenarioSpec) {
|
|
1900
|
-
return __async(this, null, function* () {
|
|
1901
|
-
if (scenarioSpec) {
|
|
1902
|
-
return bundleModel.getDatasetsForScenario(scenarioSpec, request.datasetKeys);
|
|
1903
|
-
} else {
|
|
1904
|
-
return void 0;
|
|
1905
|
-
}
|
|
1906
|
-
});
|
|
1907
|
-
}
|
|
1908
|
-
const [resultL, resultR] = yield Promise.all([
|
|
1909
|
-
fetchDatasets(this.bundleModelL, request.scenarioSpecL),
|
|
1910
|
-
fetchDatasets(this.bundleModelR, request.scenarioSpecR)
|
|
1911
|
-
]);
|
|
1912
|
-
return {
|
|
1913
|
-
kind: "dataset",
|
|
1914
|
-
datasetMapL: resultL == null ? void 0 : resultL.datasetMap,
|
|
1915
|
-
datasetMapR: resultR == null ? void 0 : resultR.datasetMap
|
|
1916
|
-
};
|
|
1917
|
-
});
|
|
1918
|
-
}
|
|
1919
|
-
processGraphDataRequest(request) {
|
|
1920
|
-
return __async(this, null, function* () {
|
|
1921
|
-
function fetchGraphData(bundleModel, scenarioSpec) {
|
|
1922
|
-
return __async(this, null, function* () {
|
|
1923
|
-
if (scenarioSpec) {
|
|
1924
|
-
return bundleModel.getGraphDataForScenario(scenarioSpec, request.graphId);
|
|
1925
|
-
} else {
|
|
1926
|
-
return void 0;
|
|
1927
|
-
}
|
|
1928
|
-
});
|
|
1929
|
-
}
|
|
1930
|
-
const [graphDataL, graphDataR] = yield Promise.all([
|
|
1931
|
-
fetchGraphData(this.bundleModelL, request.scenarioSpecL),
|
|
1932
|
-
fetchGraphData(this.bundleModelR, request.scenarioSpecR)
|
|
1933
|
-
]);
|
|
1934
|
-
return {
|
|
1935
|
-
kind: "graph-data",
|
|
1936
|
-
graphDataL,
|
|
1937
|
-
graphDataR
|
|
1938
|
-
};
|
|
1939
|
-
});
|
|
1940
|
-
}
|
|
1941
|
-
requestDatasetMaps(requestKey, scenarioSpecL, scenarioSpecR, datasetKeys, onResponse) {
|
|
1942
|
-
const request = {
|
|
1943
|
-
kind: "dataset",
|
|
1944
|
-
scenarioSpecL,
|
|
1945
|
-
scenarioSpecR,
|
|
1946
|
-
datasetKeys
|
|
1947
2119
|
};
|
|
1948
|
-
this.taskQueue.addTask(
|
|
1949
|
-
if (response.kind === "dataset") {
|
|
1950
|
-
onResponse(response.datasetMapL, response.datasetMapR);
|
|
1951
|
-
}
|
|
1952
|
-
});
|
|
2120
|
+
this.taskQueue.addTask(task);
|
|
1953
2121
|
}
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
2122
|
+
/**
|
|
2123
|
+
* Request graph data from the two models.
|
|
2124
|
+
*
|
|
2125
|
+
* @param requestKey The unique key for the request.
|
|
2126
|
+
* @param sourceL The source of the first ("left") dataset. If "left", the datasets will
|
|
2127
|
+
* be fetched from the "left" bundle's model, otherwise they will be fetched from the
|
|
2128
|
+
* "right" bundle's model.
|
|
2129
|
+
* @param scenarioSpecL The scenario used for the first ("left") model of the comparison.
|
|
2130
|
+
* @param sourceR The source of the second ("right") dataset. If "left", the datasets
|
|
2131
|
+
* will be fetched from the "left" bundle's model, otherwise they will be fetched from
|
|
2132
|
+
* the "right" bundle's model.
|
|
2133
|
+
* @param scenarioSpecR The scenario used for the second ("right") model of the comparison.
|
|
2134
|
+
* @param graphId The ID of the graph for which data will be fetched.
|
|
2135
|
+
* @param onResponse The callback that will be called with the graph data.
|
|
2136
|
+
*/
|
|
2137
|
+
requestGraphData(requestKey, sourceL, scenarioSpecL, sourceR, scenarioSpecR, graphId, onResponse) {
|
|
2138
|
+
function fetchGraphData(bundleModel, scenarioSpec) {
|
|
2139
|
+
return __async(this, null, function* () {
|
|
2140
|
+
if (scenarioSpec) {
|
|
2141
|
+
return bundleModel.getGraphDataForScenario(scenarioSpec, graphId);
|
|
2142
|
+
} else {
|
|
2143
|
+
return void 0;
|
|
2144
|
+
}
|
|
2145
|
+
});
|
|
2146
|
+
}
|
|
2147
|
+
const task = {
|
|
2148
|
+
key: requestKey,
|
|
2149
|
+
kind: "comparison-data-coordinator",
|
|
2150
|
+
process: (bundleModels) => __async(this, null, function* () {
|
|
2151
|
+
const modelL = sourceL === "left" ? bundleModels.L : bundleModels.R;
|
|
2152
|
+
const modelR = sourceR === "left" ? bundleModels.L : bundleModels.R;
|
|
2153
|
+
let graphDataL;
|
|
2154
|
+
let graphDataR;
|
|
2155
|
+
if (modelL === modelR) {
|
|
2156
|
+
graphDataL = yield fetchGraphData(modelL, scenarioSpecL);
|
|
2157
|
+
graphDataR = yield fetchGraphData(modelR, scenarioSpecR);
|
|
2158
|
+
} else {
|
|
2159
|
+
const results = yield Promise.all([
|
|
2160
|
+
fetchGraphData(modelL, scenarioSpecL),
|
|
2161
|
+
fetchGraphData(modelR, scenarioSpecR)
|
|
2162
|
+
]);
|
|
2163
|
+
graphDataL = results[0];
|
|
2164
|
+
graphDataR = results[1];
|
|
2165
|
+
}
|
|
2166
|
+
onResponse(graphDataL, graphDataR);
|
|
2167
|
+
})
|
|
1960
2168
|
};
|
|
1961
|
-
this.taskQueue.addTask(
|
|
1962
|
-
if (response.kind === "graph-data") {
|
|
1963
|
-
onResponse(response.graphDataL, response.graphDataR);
|
|
1964
|
-
}
|
|
1965
|
-
});
|
|
2169
|
+
this.taskQueue.addTask(task);
|
|
1966
2170
|
}
|
|
1967
2171
|
cancelRequest(key) {
|
|
1968
2172
|
this.taskQueue.cancelTask(key);
|
|
1969
2173
|
}
|
|
1970
2174
|
};
|
|
2175
|
+
function createComparisonDataCoordinator() {
|
|
2176
|
+
return new ComparisonDataCoordinator(TaskQueue.getInstance());
|
|
2177
|
+
}
|
|
1971
2178
|
|
|
1972
2179
|
// src/comparison/diff-datasets/diff-datasets.ts
|
|
1973
2180
|
function diffDatasets(datasetL, datasetR) {
|
|
@@ -2117,14 +2324,14 @@ function diffGraphs(graphL, graphR, scenarioKey, testSummaries) {
|
|
|
2117
2324
|
|
|
2118
2325
|
// src/comparison/report/comparison-reporting.ts
|
|
2119
2326
|
function comparisonSummaryFromReport(comparisonReport) {
|
|
2327
|
+
var _a, _b;
|
|
2120
2328
|
const terseSummaries = [];
|
|
2121
2329
|
for (const r of comparisonReport.testReports) {
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
});
|
|
2330
|
+
const baselineMaxDiff = (_a = r.baselineDiffReport) == null ? void 0 : _a.maxDiff;
|
|
2331
|
+
const baselineAvgDiff = (_b = r.baselineDiffReport) == null ? void 0 : _b.avgDiff;
|
|
2332
|
+
const summary = testSummaryFromReport(r, baselineMaxDiff, baselineAvgDiff);
|
|
2333
|
+
if (summary) {
|
|
2334
|
+
terseSummaries.push(summary);
|
|
2128
2335
|
}
|
|
2129
2336
|
}
|
|
2130
2337
|
return {
|
|
@@ -2133,6 +2340,43 @@ function comparisonSummaryFromReport(comparisonReport) {
|
|
|
2133
2340
|
perfReportR: comparisonReport.perfReportR
|
|
2134
2341
|
};
|
|
2135
2342
|
}
|
|
2343
|
+
function testSummaryFromReport(r, baselineMaxDiff, baselineAvgDiff) {
|
|
2344
|
+
var _a;
|
|
2345
|
+
function baselineRelativeDiff(diffValue, baselineDiffValue) {
|
|
2346
|
+
if (baselineDiffValue !== void 0) {
|
|
2347
|
+
const epsilon = 1e-6;
|
|
2348
|
+
if (baselineDiffValue === 0) {
|
|
2349
|
+
baselineDiffValue = epsilon;
|
|
2350
|
+
}
|
|
2351
|
+
return diffValue / baselineDiffValue;
|
|
2352
|
+
} else {
|
|
2353
|
+
if (diffValue === 0) {
|
|
2354
|
+
return 0;
|
|
2355
|
+
} else {
|
|
2356
|
+
return 1;
|
|
2357
|
+
}
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
if (r.diffReport === void 0) {
|
|
2361
|
+
return {
|
|
2362
|
+
s: r.scenarioKey,
|
|
2363
|
+
d: r.datasetKey
|
|
2364
|
+
};
|
|
2365
|
+
} else if (((_a = r.diffReport) == null ? void 0 : _a.validity) === "both" && r.diffReport.maxDiff > 0) {
|
|
2366
|
+
const maxDiffRelativeToBaseline = baselineRelativeDiff(r.diffReport.maxDiff, baselineMaxDiff);
|
|
2367
|
+
const avgDiffRelativeToBaseline = baselineRelativeDiff(r.diffReport.avgDiff, baselineAvgDiff);
|
|
2368
|
+
return {
|
|
2369
|
+
s: r.scenarioKey,
|
|
2370
|
+
d: r.datasetKey,
|
|
2371
|
+
md: r.diffReport.maxDiff,
|
|
2372
|
+
ad: r.diffReport.avgDiff,
|
|
2373
|
+
mdb: maxDiffRelativeToBaseline,
|
|
2374
|
+
adb: avgDiffRelativeToBaseline
|
|
2375
|
+
};
|
|
2376
|
+
} else {
|
|
2377
|
+
return void 0;
|
|
2378
|
+
}
|
|
2379
|
+
}
|
|
2136
2380
|
function restoreFromTerseSummaries(comparisonConfig, terseSummaries) {
|
|
2137
2381
|
const existingSummaries = /* @__PURE__ */ new Map();
|
|
2138
2382
|
for (const summary of terseSummaries) {
|
|
@@ -2145,24 +2389,33 @@ function restoreFromTerseSummaries(comparisonConfig, terseSummaries) {
|
|
|
2145
2389
|
for (const datasetKey of datasetKeys) {
|
|
2146
2390
|
const key = `${scenario.key}::${datasetKey}`;
|
|
2147
2391
|
const existingSummary = existingSummaries.get(key);
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2392
|
+
if (existingSummary) {
|
|
2393
|
+
allTestSummaries.push(existingSummary);
|
|
2394
|
+
} else {
|
|
2395
|
+
allTestSummaries.push({
|
|
2396
|
+
s: scenario.key,
|
|
2397
|
+
d: datasetKey,
|
|
2398
|
+
md: 0,
|
|
2399
|
+
ad: 0,
|
|
2400
|
+
mdb: 0,
|
|
2401
|
+
adb: 0
|
|
2402
|
+
});
|
|
2403
|
+
}
|
|
2154
2404
|
}
|
|
2155
2405
|
}
|
|
2156
2406
|
return allTestSummaries;
|
|
2157
2407
|
}
|
|
2158
2408
|
|
|
2159
2409
|
// src/comparison/report/buckets.ts
|
|
2160
|
-
function getBucketIndex(
|
|
2161
|
-
if (
|
|
2410
|
+
function getBucketIndex(diff, thresholds) {
|
|
2411
|
+
if (diff === void 0) {
|
|
2412
|
+
return thresholds.length + 2;
|
|
2413
|
+
}
|
|
2414
|
+
if (diff === 0) {
|
|
2162
2415
|
return 0;
|
|
2163
2416
|
}
|
|
2164
2417
|
for (let i = 0; i < thresholds.length; i++) {
|
|
2165
|
-
if (
|
|
2418
|
+
if (diff < thresholds[i]) {
|
|
2166
2419
|
return i + 1;
|
|
2167
2420
|
}
|
|
2168
2421
|
}
|
|
@@ -2170,14 +2423,32 @@ function getBucketIndex(diffPct, thresholds) {
|
|
|
2170
2423
|
}
|
|
2171
2424
|
|
|
2172
2425
|
// src/comparison/report/comparison-group-scores.ts
|
|
2173
|
-
function getScoresForTestSummaries(testSummaries, thresholds) {
|
|
2174
|
-
const diffCountByBucket = Array(thresholds.length +
|
|
2175
|
-
const
|
|
2426
|
+
function getScoresForTestSummaries(testSummaries, thresholds, sortMode) {
|
|
2427
|
+
const diffCountByBucket = Array(thresholds.length + 3).fill(0);
|
|
2428
|
+
const totalDiffByBucket = Array(thresholds.length + 3).fill(0);
|
|
2176
2429
|
let totalDiffCount = 0;
|
|
2430
|
+
let valueKey;
|
|
2431
|
+
switch (sortMode) {
|
|
2432
|
+
case "max-diff":
|
|
2433
|
+
valueKey = "md";
|
|
2434
|
+
break;
|
|
2435
|
+
case "avg-diff":
|
|
2436
|
+
valueKey = "ad";
|
|
2437
|
+
break;
|
|
2438
|
+
case "max-diff-relative":
|
|
2439
|
+
valueKey = "mdb";
|
|
2440
|
+
break;
|
|
2441
|
+
case "avg-diff-relative":
|
|
2442
|
+
valueKey = "adb";
|
|
2443
|
+
break;
|
|
2444
|
+
}
|
|
2177
2445
|
for (const testSummary of testSummaries) {
|
|
2178
|
-
const
|
|
2446
|
+
const value = testSummary[valueKey];
|
|
2447
|
+
const bucketIndex = getBucketIndex(value, thresholds);
|
|
2179
2448
|
diffCountByBucket[bucketIndex]++;
|
|
2180
|
-
|
|
2449
|
+
if (value !== void 0) {
|
|
2450
|
+
totalDiffByBucket[bucketIndex] += value;
|
|
2451
|
+
}
|
|
2181
2452
|
totalDiffCount++;
|
|
2182
2453
|
}
|
|
2183
2454
|
let diffPercentByBucket;
|
|
@@ -2188,20 +2459,20 @@ function getScoresForTestSummaries(testSummaries, thresholds) {
|
|
|
2188
2459
|
}
|
|
2189
2460
|
return {
|
|
2190
2461
|
totalDiffCount,
|
|
2191
|
-
|
|
2462
|
+
totalDiffByBucket,
|
|
2192
2463
|
diffCountByBucket,
|
|
2193
2464
|
diffPercentByBucket
|
|
2194
2465
|
};
|
|
2195
2466
|
}
|
|
2196
2467
|
|
|
2197
2468
|
// src/comparison/report/comparison-grouping.ts
|
|
2198
|
-
var
|
|
2199
|
-
function categorizeComparisonTestSummaries(comparisonConfig, terseSummaries) {
|
|
2469
|
+
var import_assert_never7 = require("assert-never");
|
|
2470
|
+
function categorizeComparisonTestSummaries(comparisonConfig, terseSummaries, sortMode) {
|
|
2200
2471
|
const allTestSummaries = restoreFromTerseSummaries(comparisonConfig, terseSummaries);
|
|
2201
2472
|
const groupsByScenario = groupComparisonTestSummaries(allTestSummaries, "by-scenario");
|
|
2202
|
-
const byScenario = categorizeComparisonGroups(comparisonConfig, [...groupsByScenario.values()]);
|
|
2473
|
+
const byScenario = categorizeComparisonGroups(comparisonConfig, [...groupsByScenario.values()], sortMode);
|
|
2203
2474
|
const groupsByDataset = groupComparisonTestSummaries(allTestSummaries, "by-dataset");
|
|
2204
|
-
const byDataset = categorizeComparisonGroups(comparisonConfig, [...groupsByDataset.values()]);
|
|
2475
|
+
const byDataset = categorizeComparisonGroups(comparisonConfig, [...groupsByDataset.values()], sortMode);
|
|
2205
2476
|
return {
|
|
2206
2477
|
allTestSummaries,
|
|
2207
2478
|
byScenario,
|
|
@@ -2220,7 +2491,7 @@ function groupComparisonTestSummaries(testSummaries, groupKind) {
|
|
|
2220
2491
|
groupKey = testSummary.s;
|
|
2221
2492
|
break;
|
|
2222
2493
|
default:
|
|
2223
|
-
(0,
|
|
2494
|
+
(0, import_assert_never7.assertNever)(groupKind);
|
|
2224
2495
|
}
|
|
2225
2496
|
const group = groups.get(groupKey);
|
|
2226
2497
|
if (group) {
|
|
@@ -2235,7 +2506,7 @@ function groupComparisonTestSummaries(testSummaries, groupKind) {
|
|
|
2235
2506
|
}
|
|
2236
2507
|
return groups;
|
|
2237
2508
|
}
|
|
2238
|
-
function categorizeComparisonGroups(comparisonConfig, allGroups) {
|
|
2509
|
+
function categorizeComparisonGroups(comparisonConfig, allGroups, sortMode) {
|
|
2239
2510
|
const allGroupSummaries = /* @__PURE__ */ new Map();
|
|
2240
2511
|
const withErrors = [];
|
|
2241
2512
|
const onlyInLeft = [];
|
|
@@ -2245,7 +2516,9 @@ function categorizeComparisonGroups(comparisonConfig, allGroups) {
|
|
|
2245
2516
|
function addSummaryForGroup(group, root, validInL, validInR) {
|
|
2246
2517
|
let scores;
|
|
2247
2518
|
if (validInL && validInR) {
|
|
2248
|
-
|
|
2519
|
+
const isRelativeMode = sortMode === "max-diff-relative" || sortMode === "avg-diff-relative";
|
|
2520
|
+
const thresholds = isRelativeMode ? comparisonConfig.ratioThresholds : comparisonConfig.thresholds;
|
|
2521
|
+
scores = getScoresForTestSummaries(group.testSummaries, thresholds, sortMode);
|
|
2249
2522
|
}
|
|
2250
2523
|
const groupSummary = {
|
|
2251
2524
|
root,
|
|
@@ -2254,7 +2527,9 @@ function categorizeComparisonGroups(comparisonConfig, allGroups) {
|
|
|
2254
2527
|
};
|
|
2255
2528
|
allGroupSummaries.set(group.key, groupSummary);
|
|
2256
2529
|
if (validInL && validInR) {
|
|
2257
|
-
|
|
2530
|
+
const noDiffCount = scores.diffCountByBucket[0];
|
|
2531
|
+
const skippedCount = scores.diffCountByBucket[5];
|
|
2532
|
+
if (scores.totalDiffCount !== noDiffCount + skippedCount) {
|
|
2258
2533
|
withDiffs.push(groupSummary);
|
|
2259
2534
|
} else {
|
|
2260
2535
|
withoutDiffs.push(groupSummary);
|
|
@@ -2284,7 +2559,7 @@ function categorizeComparisonGroups(comparisonConfig, allGroups) {
|
|
|
2284
2559
|
break;
|
|
2285
2560
|
}
|
|
2286
2561
|
default:
|
|
2287
|
-
(0,
|
|
2562
|
+
(0, import_assert_never7.assertNever)(group.kind);
|
|
2288
2563
|
}
|
|
2289
2564
|
}
|
|
2290
2565
|
if (withDiffs.length > 1) {
|
|
@@ -2346,13 +2621,13 @@ function sortScenarioGroupSummaries(summaries) {
|
|
|
2346
2621
|
});
|
|
2347
2622
|
}
|
|
2348
2623
|
function compareScores(a, b) {
|
|
2349
|
-
if (a.
|
|
2624
|
+
if (a.totalDiffByBucket.length !== b.totalDiffByBucket.length) {
|
|
2350
2625
|
return 0;
|
|
2351
2626
|
}
|
|
2352
|
-
const len = a.
|
|
2627
|
+
const len = a.totalDiffByBucket.length;
|
|
2353
2628
|
for (let i = len - 1; i >= 0; i--) {
|
|
2354
|
-
const aTotal = a.
|
|
2355
|
-
const bTotal = b.
|
|
2629
|
+
const aTotal = a.totalDiffByBucket[i];
|
|
2630
|
+
const bTotal = b.totalDiffByBucket[i];
|
|
2356
2631
|
if (aTotal > bTotal) {
|
|
2357
2632
|
return 1;
|
|
2358
2633
|
} else if (aTotal < bTotal) {
|
|
@@ -2364,7 +2639,7 @@ function compareScores(a, b) {
|
|
|
2364
2639
|
|
|
2365
2640
|
// src/comparison/config/parse/comparison-parser.ts
|
|
2366
2641
|
var import_ajv2 = __toESM(require("ajv"), 1);
|
|
2367
|
-
var
|
|
2642
|
+
var import_assert_never8 = __toESM(require("assert-never"), 1);
|
|
2368
2643
|
var import_neverthrow2 = require("neverthrow");
|
|
2369
2644
|
var import_yaml2 = __toESM(require("yaml"), 1);
|
|
2370
2645
|
|
|
@@ -2900,7 +3175,7 @@ function parseComparisonSpecs(specSource) {
|
|
|
2900
3175
|
parsed = import_yaml2.default.parse(specSource.content);
|
|
2901
3176
|
break;
|
|
2902
3177
|
default:
|
|
2903
|
-
(0,
|
|
3178
|
+
(0, import_assert_never8.default)(specSource.kind);
|
|
2904
3179
|
}
|
|
2905
3180
|
if (validate(parsed)) {
|
|
2906
3181
|
for (const specItem of parsed) {
|
|
@@ -3127,11 +3402,12 @@ function viewGroupSpecFromParsed(parsedViewGroup) {
|
|
|
3127
3402
|
}
|
|
3128
3403
|
|
|
3129
3404
|
// src/comparison/config/resolve/comparison-resolver.ts
|
|
3130
|
-
var
|
|
3405
|
+
var import_assert_never10 = require("assert-never");
|
|
3131
3406
|
|
|
3132
3407
|
// src/bundle/model-inputs.ts
|
|
3133
3408
|
var ModelInputs = class {
|
|
3134
3409
|
constructor(modelSpec) {
|
|
3410
|
+
this.modelSpec = modelSpec;
|
|
3135
3411
|
/** All inputs keyed by lookup name (lowercase variable name or alias). */
|
|
3136
3412
|
this.inputsByLookupName = /* @__PURE__ */ new Map();
|
|
3137
3413
|
/** All input ID aliases. */
|
|
@@ -3178,10 +3454,18 @@ var ModelInputs = class {
|
|
|
3178
3454
|
getInputVarForName(name) {
|
|
3179
3455
|
return this.inputsByLookupName.get(name.toLowerCase());
|
|
3180
3456
|
}
|
|
3457
|
+
/**
|
|
3458
|
+
* Return the `InputVar` that matches the requested variable ID.
|
|
3459
|
+
*
|
|
3460
|
+
* @param varId The variable identifier to match.
|
|
3461
|
+
*/
|
|
3462
|
+
getInputVarForVarId(varId) {
|
|
3463
|
+
return this.modelSpec.inputVars.get(varId);
|
|
3464
|
+
}
|
|
3181
3465
|
};
|
|
3182
3466
|
|
|
3183
3467
|
// src/comparison/config/resolve/comparison-scenario-specs.ts
|
|
3184
|
-
var
|
|
3468
|
+
var import_assert_never9 = require("assert-never");
|
|
3185
3469
|
function scenarioSpecsFromSettings(settings) {
|
|
3186
3470
|
switch (settings.kind) {
|
|
3187
3471
|
case "all-inputs-settings": {
|
|
@@ -3194,7 +3478,7 @@ function scenarioSpecsFromSettings(settings) {
|
|
|
3194
3478
|
return [specL, specR];
|
|
3195
3479
|
}
|
|
3196
3480
|
default:
|
|
3197
|
-
(0,
|
|
3481
|
+
(0, import_assert_never9.assertNever)(settings);
|
|
3198
3482
|
}
|
|
3199
3483
|
}
|
|
3200
3484
|
function scenarioSpecFromInputs(inputs, side) {
|
|
@@ -3399,8 +3683,21 @@ function resolveScenariosFromSpec(modelInputsL, modelInputsR, scenarioSpec, genK
|
|
|
3399
3683
|
)
|
|
3400
3684
|
];
|
|
3401
3685
|
}
|
|
3686
|
+
case "scenario-with-setting-group": {
|
|
3687
|
+
return [
|
|
3688
|
+
resolveScenarioForSettingGroup(
|
|
3689
|
+
modelInputsL,
|
|
3690
|
+
modelInputsR,
|
|
3691
|
+
genKey(),
|
|
3692
|
+
scenarioSpec.id,
|
|
3693
|
+
scenarioSpec.title,
|
|
3694
|
+
scenarioSpec.subtitle,
|
|
3695
|
+
scenarioSpec.settingGroupId
|
|
3696
|
+
)
|
|
3697
|
+
];
|
|
3698
|
+
}
|
|
3402
3699
|
default:
|
|
3403
|
-
(0,
|
|
3700
|
+
(0, import_assert_never10.assertNever)(scenarioSpec);
|
|
3404
3701
|
}
|
|
3405
3702
|
}
|
|
3406
3703
|
function resolveScenarioMatrix(modelInputsL, modelInputsR, genKey) {
|
|
@@ -3456,7 +3753,7 @@ function resolveScenarioForInputSpecs(modelInputsL, modelInputsR, key, id, title
|
|
|
3456
3753
|
case "input-at-value":
|
|
3457
3754
|
return resolveInputForName(modelInputsL, modelInputsR, inputSpec.inputName, inputSpec.value);
|
|
3458
3755
|
default:
|
|
3459
|
-
(0,
|
|
3756
|
+
(0, import_assert_never10.assertNever)(inputSpec);
|
|
3460
3757
|
}
|
|
3461
3758
|
});
|
|
3462
3759
|
const settings = {
|
|
@@ -3489,7 +3786,7 @@ function resolveScenarioForDistinctInputSpecs(modelInputsL, modelInputsR, key, i
|
|
|
3489
3786
|
inputState = resolveInputForNameInModel(modelInputs, inputSpec.inputName, inputSpec.value);
|
|
3490
3787
|
break;
|
|
3491
3788
|
default:
|
|
3492
|
-
(0,
|
|
3789
|
+
(0, import_assert_never10.assertNever)(inputSpec);
|
|
3493
3790
|
}
|
|
3494
3791
|
if (inputState.error !== void 0) {
|
|
3495
3792
|
inputsWithErrors.push({
|
|
@@ -3528,6 +3825,113 @@ function resolveScenarioForDistinctInputSpecs(modelInputsL, modelInputsR, key, i
|
|
|
3528
3825
|
specR
|
|
3529
3826
|
};
|
|
3530
3827
|
}
|
|
3828
|
+
function resolveScenarioForSettingGroup(modelInputsL, modelInputsR, key, id, title, subtitle, settingGroupId) {
|
|
3829
|
+
var _a, _b;
|
|
3830
|
+
function inputVarNameForVarId(modelInputs, varId) {
|
|
3831
|
+
const inputVar = modelInputs.getInputVarForVarId(varId);
|
|
3832
|
+
if (inputVar !== void 0) {
|
|
3833
|
+
return inputVar.varName;
|
|
3834
|
+
} else {
|
|
3835
|
+
return varId;
|
|
3836
|
+
}
|
|
3837
|
+
}
|
|
3838
|
+
function inputPositionForPosition(position) {
|
|
3839
|
+
switch (position) {
|
|
3840
|
+
case "at-minimum":
|
|
3841
|
+
return "min";
|
|
3842
|
+
case "at-maximum":
|
|
3843
|
+
return "max";
|
|
3844
|
+
case "at-default":
|
|
3845
|
+
return "default";
|
|
3846
|
+
default:
|
|
3847
|
+
throw new Error(`Unknown input position: ${position}`);
|
|
3848
|
+
}
|
|
3849
|
+
}
|
|
3850
|
+
function inputSpecForSetting(modelInputs, inputSetting) {
|
|
3851
|
+
switch (inputSetting.kind) {
|
|
3852
|
+
case "position":
|
|
3853
|
+
return {
|
|
3854
|
+
kind: "input-at-position",
|
|
3855
|
+
inputName: inputVarNameForVarId(modelInputs, inputSetting.inputVarId),
|
|
3856
|
+
position: inputPositionForPosition(inputSetting.position)
|
|
3857
|
+
};
|
|
3858
|
+
case "value":
|
|
3859
|
+
return {
|
|
3860
|
+
kind: "input-at-value",
|
|
3861
|
+
inputName: inputVarNameForVarId(modelInputs, inputSetting.inputVarId),
|
|
3862
|
+
value: inputSetting.value
|
|
3863
|
+
};
|
|
3864
|
+
default:
|
|
3865
|
+
throw new Error(`Unknown input setting kind: ${inputSetting}`);
|
|
3866
|
+
}
|
|
3867
|
+
}
|
|
3868
|
+
function inputSpecsForSettingGroup(modelInputs, inputSettings) {
|
|
3869
|
+
return inputSettings.map((inputSetting) => inputSpecForSetting(modelInputs, inputSetting));
|
|
3870
|
+
}
|
|
3871
|
+
const inputSettingsL = ((_a = modelInputsL.modelSpec.inputSettingGroups) == null ? void 0 : _a.get(settingGroupId)) || [];
|
|
3872
|
+
const inputSettingsR = ((_b = modelInputsR.modelSpec.inputSettingGroups) == null ? void 0 : _b.get(settingGroupId)) || [];
|
|
3873
|
+
const inputsL = inputSpecsForSettingGroup(modelInputsL, inputSettingsL);
|
|
3874
|
+
const inputsR = inputSpecsForSettingGroup(modelInputsR, inputSettingsR);
|
|
3875
|
+
const scenario = resolveScenarioForDistinctInputSpecs(
|
|
3876
|
+
modelInputsL,
|
|
3877
|
+
modelInputsR,
|
|
3878
|
+
key,
|
|
3879
|
+
id,
|
|
3880
|
+
title,
|
|
3881
|
+
subtitle,
|
|
3882
|
+
inputsL,
|
|
3883
|
+
inputsR
|
|
3884
|
+
);
|
|
3885
|
+
function scenarioString(scenario2) {
|
|
3886
|
+
if (scenario2.kind === "input-settings") {
|
|
3887
|
+
const settings = scenario2.settings.map((setting) => {
|
|
3888
|
+
switch (setting.kind) {
|
|
3889
|
+
case "position":
|
|
3890
|
+
return `${setting.inputVarId}=${setting.position}`;
|
|
3891
|
+
case "value":
|
|
3892
|
+
return `${setting.inputVarId}=${setting.value}`;
|
|
3893
|
+
default:
|
|
3894
|
+
throw new Error(`Unexpected input setting kind: ${setting}`);
|
|
3895
|
+
}
|
|
3896
|
+
});
|
|
3897
|
+
return settings.sort().join("__");
|
|
3898
|
+
} else {
|
|
3899
|
+
throw new Error(`Unexpected scenario spec kind: ${scenario2.kind}`);
|
|
3900
|
+
}
|
|
3901
|
+
}
|
|
3902
|
+
function scenariosAreEqual(scenarioL, scenarioR) {
|
|
3903
|
+
return scenarioString(scenarioL) === scenarioString(scenarioR);
|
|
3904
|
+
}
|
|
3905
|
+
function errorState(inputSettings) {
|
|
3906
|
+
if (inputSettings.length === 0) {
|
|
3907
|
+
return { error: { kind: "unknown-input-setting-group" } };
|
|
3908
|
+
} else {
|
|
3909
|
+
return {};
|
|
3910
|
+
}
|
|
3911
|
+
}
|
|
3912
|
+
if (inputSettingsL.length === 0 || inputSettingsR.length === 0) {
|
|
3913
|
+
if (scenario.settings.kind === "input-settings") {
|
|
3914
|
+
const errorSetting = {
|
|
3915
|
+
requestedName: settingGroupId,
|
|
3916
|
+
stateL: errorState(inputSettingsL),
|
|
3917
|
+
stateR: errorState(inputSettingsR)
|
|
3918
|
+
};
|
|
3919
|
+
scenario.settings.inputs.unshift(errorSetting);
|
|
3920
|
+
}
|
|
3921
|
+
if (inputSettingsL.length === 0) {
|
|
3922
|
+
scenario.specL = void 0;
|
|
3923
|
+
}
|
|
3924
|
+
if (inputSettingsR.length === 0) {
|
|
3925
|
+
scenario.specR = void 0;
|
|
3926
|
+
}
|
|
3927
|
+
}
|
|
3928
|
+
if (scenario.settings.kind === "input-settings") {
|
|
3929
|
+
if (scenario.specL && scenario.specR && !scenariosAreEqual(scenario.specL, scenario.specR)) {
|
|
3930
|
+
scenario.settings.settingsDiffer = true;
|
|
3931
|
+
}
|
|
3932
|
+
}
|
|
3933
|
+
return scenario;
|
|
3934
|
+
}
|
|
3531
3935
|
function resolveInputForName(modelInputsL, modelInputsR, inputName, at) {
|
|
3532
3936
|
return {
|
|
3533
3937
|
requestedName: inputName,
|
|
@@ -3598,7 +4002,7 @@ function inputValueAtPosition2(inputVar, position) {
|
|
|
3598
4002
|
case "at-maximum":
|
|
3599
4003
|
return inputVar.maxValue;
|
|
3600
4004
|
default:
|
|
3601
|
-
(0,
|
|
4005
|
+
(0, import_assert_never10.assertNever)(position);
|
|
3602
4006
|
}
|
|
3603
4007
|
}
|
|
3604
4008
|
var ResolvedScenarioGroups = class {
|
|
@@ -3657,7 +4061,7 @@ function resolveGraphsFromSpec(modelSpecL, modelSpecR, resolvedGraphGroups, grap
|
|
|
3657
4061
|
return [...graphIds];
|
|
3658
4062
|
}
|
|
3659
4063
|
default:
|
|
3660
|
-
(0,
|
|
4064
|
+
(0, import_assert_never10.assertNever)(graphsSpec.preset);
|
|
3661
4065
|
}
|
|
3662
4066
|
}
|
|
3663
4067
|
// eslint-disable-next-line no-fallthrough
|
|
@@ -3671,7 +4075,7 @@ function resolveGraphsFromSpec(modelSpecL, modelSpecR, resolvedGraphGroups, grap
|
|
|
3671
4075
|
return groupSpec.graphIds;
|
|
3672
4076
|
}
|
|
3673
4077
|
default:
|
|
3674
|
-
(0,
|
|
4078
|
+
(0, import_assert_never10.assertNever)(graphsSpec);
|
|
3675
4079
|
}
|
|
3676
4080
|
}
|
|
3677
4081
|
function resolveViewForScenarioId(resolvedScenarios, viewTitle, viewSubtitle, scenarioId, graphIds, graphOrder) {
|
|
@@ -3845,7 +4249,7 @@ function resolveViewGroupFromSpec(modelSpecL, modelSpecR, modelOutputs, resolved
|
|
|
3845
4249
|
views.push(resolveViewForScenario(void 0, void 0, scenario, graphIds, graphOrder));
|
|
3846
4250
|
break;
|
|
3847
4251
|
default:
|
|
3848
|
-
(0,
|
|
4252
|
+
(0, import_assert_never10.assertNever)(scenario);
|
|
3849
4253
|
}
|
|
3850
4254
|
}
|
|
3851
4255
|
} else {
|
|
@@ -3854,13 +4258,13 @@ function resolveViewGroupFromSpec(modelSpecL, modelSpecR, modelOutputs, resolved
|
|
|
3854
4258
|
break;
|
|
3855
4259
|
}
|
|
3856
4260
|
default:
|
|
3857
|
-
(0,
|
|
4261
|
+
(0, import_assert_never10.assertNever)(refSpec);
|
|
3858
4262
|
}
|
|
3859
4263
|
}
|
|
3860
4264
|
break;
|
|
3861
4265
|
}
|
|
3862
4266
|
default:
|
|
3863
|
-
(0,
|
|
4267
|
+
(0, import_assert_never10.assertNever)(viewGroupSpec);
|
|
3864
4268
|
}
|
|
3865
4269
|
return {
|
|
3866
4270
|
kind: "view-group",
|
|
@@ -3923,9 +4327,9 @@ var ComparisonDatasetsImpl = class {
|
|
|
3923
4327
|
}
|
|
3924
4328
|
const allOutputVarKeysSet = /* @__PURE__ */ new Set();
|
|
3925
4329
|
const modelOutputVarKeysSet = /* @__PURE__ */ new Set();
|
|
3926
|
-
function addOutputVars(outputVars,
|
|
4330
|
+
function addOutputVars(outputVars, handleRenames2) {
|
|
3927
4331
|
outputVars.forEach((outputVar, key) => {
|
|
3928
|
-
const remappedKey =
|
|
4332
|
+
const remappedKey = handleRenames2 ? leftKeyForRightKey(key) : key;
|
|
3929
4333
|
allOutputVarKeysSet.add(remappedKey);
|
|
3930
4334
|
if (outputVar.sourceName === void 0) {
|
|
3931
4335
|
modelOutputVarKeysSet.add(remappedKey);
|
|
@@ -4039,109 +4443,41 @@ var ComparisonScenariosImpl = class {
|
|
|
4039
4443
|
}
|
|
4040
4444
|
};
|
|
4041
4445
|
|
|
4042
|
-
// src/config/synchronized-model.ts
|
|
4043
|
-
function synchronizedBundleModel(sourceModel) {
|
|
4044
|
-
const promiseQueue = new PromiseQueue();
|
|
4045
|
-
return {
|
|
4046
|
-
modelSpec: sourceModel.modelSpec,
|
|
4047
|
-
getDatasetsForScenario: (scenarioSpec, datasetKeys) => {
|
|
4048
|
-
return promiseQueue.add(() => sourceModel.getDatasetsForScenario(scenarioSpec, datasetKeys));
|
|
4049
|
-
},
|
|
4050
|
-
getGraphDataForScenario: (scenarioSpec, graphId) => {
|
|
4051
|
-
return promiseQueue.add(() => sourceModel.getGraphDataForScenario(scenarioSpec, graphId));
|
|
4052
|
-
},
|
|
4053
|
-
getGraphLinksForScenario: sourceModel.getGraphLinksForScenario.bind(sourceModel)
|
|
4054
|
-
};
|
|
4055
|
-
}
|
|
4056
|
-
var PromiseQueue = class {
|
|
4057
|
-
constructor() {
|
|
4058
|
-
this.tasks = [];
|
|
4059
|
-
this.runningCount = 0;
|
|
4060
|
-
}
|
|
4061
|
-
add(f) {
|
|
4062
|
-
return new Promise((resolve, reject) => {
|
|
4063
|
-
const run = () => __async(this, null, function* () {
|
|
4064
|
-
this.runningCount++;
|
|
4065
|
-
const promise = f();
|
|
4066
|
-
try {
|
|
4067
|
-
const result = yield promise;
|
|
4068
|
-
resolve(result);
|
|
4069
|
-
} catch (e) {
|
|
4070
|
-
reject(e);
|
|
4071
|
-
} finally {
|
|
4072
|
-
this.runningCount--;
|
|
4073
|
-
this.runNext();
|
|
4074
|
-
}
|
|
4075
|
-
});
|
|
4076
|
-
if (this.runningCount < 1) {
|
|
4077
|
-
run();
|
|
4078
|
-
} else {
|
|
4079
|
-
this.tasks.push(run);
|
|
4080
|
-
}
|
|
4081
|
-
});
|
|
4082
|
-
}
|
|
4083
|
-
runNext() {
|
|
4084
|
-
if (this.tasks.length > 0) {
|
|
4085
|
-
const task = this.tasks.shift();
|
|
4086
|
-
if (task) {
|
|
4087
|
-
task();
|
|
4088
|
-
}
|
|
4089
|
-
}
|
|
4090
|
-
}
|
|
4091
|
-
};
|
|
4092
|
-
|
|
4093
4446
|
// src/config/config.ts
|
|
4094
4447
|
function createConfig(options) {
|
|
4095
4448
|
return __async(this, null, function* () {
|
|
4096
|
-
var _a;
|
|
4097
|
-
|
|
4449
|
+
var _a, _b, _c, _d, _e;
|
|
4450
|
+
let concurrentModels;
|
|
4451
|
+
if (options.concurrency === void 0) {
|
|
4452
|
+
concurrentModels = 1;
|
|
4453
|
+
} else if (options.concurrency === 0) {
|
|
4454
|
+
let coreCount;
|
|
4455
|
+
if (typeof navigator !== "undefined") {
|
|
4456
|
+
coreCount = navigator.hardwareConcurrency;
|
|
4457
|
+
}
|
|
4458
|
+
if (coreCount === void 0 || coreCount < 1) {
|
|
4459
|
+
coreCount = 1;
|
|
4460
|
+
}
|
|
4461
|
+
concurrentModels = Math.max(1, Math.floor(coreCount / 2));
|
|
4462
|
+
} else {
|
|
4463
|
+
concurrentModels = Math.max(1, options.concurrency);
|
|
4464
|
+
}
|
|
4465
|
+
const origCurrentBundle = yield loadBundle(options.current, concurrentModels);
|
|
4098
4466
|
let currentBundle;
|
|
4099
4467
|
let comparisonConfig;
|
|
4100
4468
|
if (options.comparison === void 0) {
|
|
4101
4469
|
currentBundle = origCurrentBundle;
|
|
4102
4470
|
} else {
|
|
4103
|
-
const baselineBundle = yield
|
|
4104
|
-
|
|
4105
|
-
const
|
|
4106
|
-
|
|
4107
|
-
invertedRenamedKeys.set(newKey, oldKey);
|
|
4108
|
-
});
|
|
4109
|
-
const rightKeyForLeftKey = (leftKey) => {
|
|
4110
|
-
return (renamedDatasetKeys == null ? void 0 : renamedDatasetKeys.get(leftKey)) || leftKey;
|
|
4111
|
-
};
|
|
4112
|
-
const leftKeyForRightKey = (rightKey) => {
|
|
4113
|
-
return invertedRenamedKeys.get(rightKey) || rightKey;
|
|
4114
|
-
};
|
|
4115
|
-
const origBundleModelR = origCurrentBundle.model;
|
|
4116
|
-
const adjBundleModelR = {
|
|
4117
|
-
modelSpec: origBundleModelR.modelSpec,
|
|
4118
|
-
getDatasetsForScenario: (scenarioSpec, datasetKeys) => __async(this, null, function* () {
|
|
4119
|
-
const rightKeys = datasetKeys.map(rightKeyForLeftKey);
|
|
4120
|
-
const result = yield origBundleModelR.getDatasetsForScenario(scenarioSpec, rightKeys);
|
|
4121
|
-
const mapWithRightKeys = result.datasetMap;
|
|
4122
|
-
const mapWithLeftKeys = /* @__PURE__ */ new Map();
|
|
4123
|
-
for (const [rightKey, dataset] of mapWithRightKeys.entries()) {
|
|
4124
|
-
const leftKey = leftKeyForRightKey(rightKey);
|
|
4125
|
-
mapWithLeftKeys.set(leftKey, dataset);
|
|
4126
|
-
}
|
|
4127
|
-
return {
|
|
4128
|
-
datasetMap: mapWithLeftKeys,
|
|
4129
|
-
modelRunTime: result.modelRunTime
|
|
4130
|
-
};
|
|
4131
|
-
}),
|
|
4132
|
-
getGraphDataForScenario: origBundleModelR.getGraphDataForScenario.bind(origBundleModelR),
|
|
4133
|
-
getGraphLinksForScenario: origBundleModelR.getGraphLinksForScenario.bind(origBundleModelR)
|
|
4134
|
-
};
|
|
4135
|
-
currentBundle = __spreadProps(__spreadValues({}, origCurrentBundle), {
|
|
4136
|
-
model: adjBundleModelR
|
|
4137
|
-
});
|
|
4138
|
-
const modelSpecL = baselineBundle.model.modelSpec;
|
|
4139
|
-
const modelSpecR = currentBundle.model.modelSpec;
|
|
4471
|
+
const baselineBundle = yield loadBundle(options.comparison.baseline, concurrentModels);
|
|
4472
|
+
currentBundle = handleRenames(origCurrentBundle, (_a = options.comparison.datasets) == null ? void 0 : _a.renamedDatasetKeys);
|
|
4473
|
+
const modelSpecL = baselineBundle.modelSpec;
|
|
4474
|
+
const modelSpecR = currentBundle.modelSpec;
|
|
4140
4475
|
const comparisonDefs = resolveComparisonSpecsFromSources(modelSpecL, modelSpecR, options.comparison.specs);
|
|
4141
4476
|
comparisonConfig = {
|
|
4142
4477
|
bundleL: baselineBundle,
|
|
4143
4478
|
bundleR: currentBundle,
|
|
4144
|
-
thresholds: options.comparison.thresholds,
|
|
4479
|
+
thresholds: (_b = options.comparison.thresholds) != null ? _b : [1, 5, 10],
|
|
4480
|
+
ratioThresholds: (_c = options.comparison.ratioThresholds) != null ? _c : [1, 2, 3],
|
|
4145
4481
|
scenarios: getComparisonScenarios(comparisonDefs.scenarios),
|
|
4146
4482
|
datasets: getComparisonDatasets(modelSpecL, modelSpecR, options.comparison.datasets),
|
|
4147
4483
|
viewGroups: comparisonDefs.viewGroups,
|
|
@@ -4152,26 +4488,75 @@ function createConfig(options) {
|
|
|
4152
4488
|
bundle: currentBundle,
|
|
4153
4489
|
tests: options.check.tests
|
|
4154
4490
|
};
|
|
4491
|
+
const executors = /* @__PURE__ */ new Map();
|
|
4492
|
+
for (let i = 0; i < checkConfig.bundle.models.length; i++) {
|
|
4493
|
+
const bundleModelL = (_d = comparisonConfig == null ? void 0 : comparisonConfig.bundleL.models) == null ? void 0 : _d[i];
|
|
4494
|
+
const bundleModelR = ((_e = comparisonConfig == null ? void 0 : comparisonConfig.bundleR.models) == null ? void 0 : _e[i]) || checkConfig.bundle.models[i];
|
|
4495
|
+
const executor = createExecutor(bundleModelL, bundleModelR);
|
|
4496
|
+
executors.set(`executor-${i}`, executor);
|
|
4497
|
+
}
|
|
4498
|
+
TaskQueue.initialize(executors);
|
|
4155
4499
|
return {
|
|
4156
4500
|
check: checkConfig,
|
|
4157
4501
|
comparison: comparisonConfig
|
|
4158
4502
|
};
|
|
4159
4503
|
});
|
|
4160
4504
|
}
|
|
4161
|
-
function
|
|
4505
|
+
function loadBundle(bundle, concurrentModels) {
|
|
4162
4506
|
return __async(this, null, function* () {
|
|
4163
|
-
const
|
|
4164
|
-
const
|
|
4507
|
+
const initCalls = Array.from({ length: concurrentModels }, () => bundle.bundle.initModel());
|
|
4508
|
+
const models = yield Promise.all(initCalls);
|
|
4165
4509
|
return {
|
|
4166
|
-
name:
|
|
4167
|
-
version:
|
|
4168
|
-
|
|
4510
|
+
name: bundle.name,
|
|
4511
|
+
version: bundle.bundle.version,
|
|
4512
|
+
modelSpec: bundle.bundle.modelSpec,
|
|
4513
|
+
models
|
|
4169
4514
|
};
|
|
4170
4515
|
});
|
|
4171
4516
|
}
|
|
4517
|
+
function handleRenames(origCurrentBundle, renamedDatasetKeys) {
|
|
4518
|
+
if (renamedDatasetKeys === void 0 || renamedDatasetKeys.size === 0) {
|
|
4519
|
+
return origCurrentBundle;
|
|
4520
|
+
}
|
|
4521
|
+
const invertedRenamedKeys = /* @__PURE__ */ new Map();
|
|
4522
|
+
renamedDatasetKeys.forEach((newKey, oldKey) => {
|
|
4523
|
+
invertedRenamedKeys.set(newKey, oldKey);
|
|
4524
|
+
});
|
|
4525
|
+
const rightKeyForLeftKey = (leftKey) => {
|
|
4526
|
+
return (renamedDatasetKeys == null ? void 0 : renamedDatasetKeys.get(leftKey)) || leftKey;
|
|
4527
|
+
};
|
|
4528
|
+
const leftKeyForRightKey = (rightKey) => {
|
|
4529
|
+
return invertedRenamedKeys.get(rightKey) || rightKey;
|
|
4530
|
+
};
|
|
4531
|
+
function wrapModel(origBundleModelR) {
|
|
4532
|
+
return {
|
|
4533
|
+
modelSpec: origBundleModelR.modelSpec,
|
|
4534
|
+
getDatasetsForScenario: (scenarioSpec, datasetKeys) => __async(this, null, function* () {
|
|
4535
|
+
const rightKeys = datasetKeys.map(rightKeyForLeftKey);
|
|
4536
|
+
const result = yield origBundleModelR.getDatasetsForScenario(scenarioSpec, rightKeys);
|
|
4537
|
+
const mapWithRightKeys = result.datasetMap;
|
|
4538
|
+
const mapWithLeftKeys = /* @__PURE__ */ new Map();
|
|
4539
|
+
for (const [rightKey, dataset] of mapWithRightKeys.entries()) {
|
|
4540
|
+
const leftKey = leftKeyForRightKey(rightKey);
|
|
4541
|
+
mapWithLeftKeys.set(leftKey, dataset);
|
|
4542
|
+
}
|
|
4543
|
+
return {
|
|
4544
|
+
datasetMap: mapWithLeftKeys,
|
|
4545
|
+
modelRunTime: result.modelRunTime
|
|
4546
|
+
};
|
|
4547
|
+
}),
|
|
4548
|
+
getGraphDataForScenario: origBundleModelR.getGraphDataForScenario.bind(origBundleModelR),
|
|
4549
|
+
getGraphLinksForScenario: origBundleModelR.getGraphLinksForScenario.bind(origBundleModelR)
|
|
4550
|
+
};
|
|
4551
|
+
}
|
|
4552
|
+
const wrappedModels = origCurrentBundle.models.map(wrapModel);
|
|
4553
|
+
return __spreadProps(__spreadValues({}, origCurrentBundle), {
|
|
4554
|
+
models: wrappedModels
|
|
4555
|
+
});
|
|
4556
|
+
}
|
|
4172
4557
|
|
|
4173
4558
|
// src/perf/perf-runner.ts
|
|
4174
|
-
var
|
|
4559
|
+
var import_assert_never11 = require("assert-never");
|
|
4175
4560
|
|
|
4176
4561
|
// src/perf/perf-stats.ts
|
|
4177
4562
|
var PerfStats = class {
|
|
@@ -4208,80 +4593,110 @@ var PerfStats = class {
|
|
|
4208
4593
|
};
|
|
4209
4594
|
|
|
4210
4595
|
// src/perf/perf-runner.ts
|
|
4211
|
-
|
|
4212
|
-
|
|
4596
|
+
function runPerfWithTaskQueue(taskQueue, callbacks, options) {
|
|
4597
|
+
const perfRunner = new PerfRunner(taskQueue, callbacks, options);
|
|
4598
|
+
perfRunner.start();
|
|
4599
|
+
return () => {
|
|
4600
|
+
perfRunner.cancel();
|
|
4601
|
+
};
|
|
4602
|
+
}
|
|
4603
|
+
function runPerf(callbacks, options) {
|
|
4604
|
+
const taskQueue = TaskQueue.getInstance();
|
|
4605
|
+
return runPerfWithTaskQueue(taskQueue, callbacks, options);
|
|
4606
|
+
}
|
|
4213
4607
|
var PerfRunner = class {
|
|
4214
|
-
constructor(
|
|
4215
|
-
this.
|
|
4216
|
-
this.
|
|
4217
|
-
this.
|
|
4218
|
-
|
|
4219
|
-
this.
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
case "right": {
|
|
4229
|
-
const result = yield bundleModelR.getDatasetsForScenario(scenarioSpec, []);
|
|
4230
|
-
return {
|
|
4231
|
-
runTimeR: result.modelRunTime
|
|
4232
|
-
};
|
|
4233
|
-
}
|
|
4234
|
-
case "both": {
|
|
4235
|
-
const [resultL, resultR] = yield Promise.all([
|
|
4236
|
-
bundleModelL.getDatasetsForScenario(scenarioSpec, []),
|
|
4237
|
-
bundleModelR.getDatasetsForScenario(scenarioSpec, [])
|
|
4238
|
-
]);
|
|
4239
|
-
return {
|
|
4240
|
-
runTimeL: resultL.modelRunTime,
|
|
4241
|
-
runTimeR: resultR.modelRunTime
|
|
4242
|
-
};
|
|
4243
|
-
}
|
|
4244
|
-
default:
|
|
4245
|
-
(0, import_assert_never12.assertNever)(request.kind);
|
|
4246
|
-
}
|
|
4247
|
-
})
|
|
4248
|
-
});
|
|
4608
|
+
constructor(taskQueue, callbacks, options) {
|
|
4609
|
+
this.taskQueue = taskQueue;
|
|
4610
|
+
this.callbacks = callbacks;
|
|
4611
|
+
this.options = options;
|
|
4612
|
+
this.pendingTaskKeys = /* @__PURE__ */ new Set();
|
|
4613
|
+
this.stopped = false;
|
|
4614
|
+
}
|
|
4615
|
+
cancel() {
|
|
4616
|
+
if (!this.stopped) {
|
|
4617
|
+
for (const taskKey of this.pendingTaskKeys) {
|
|
4618
|
+
this.taskQueue.cancelTask(taskKey);
|
|
4619
|
+
}
|
|
4620
|
+
this.stopped = true;
|
|
4621
|
+
}
|
|
4249
4622
|
}
|
|
4250
4623
|
start() {
|
|
4624
|
+
var _a, _b, _c, _d, _e, _f;
|
|
4251
4625
|
const statsL = new PerfStats();
|
|
4252
4626
|
const statsR = new PerfStats();
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
const taskQueue = this.taskQueue;
|
|
4262
|
-
function addTask(index, warmup, kind) {
|
|
4263
|
-
const key = `${warmup ? "warmup-" : ""}${kind}-${index}`;
|
|
4264
|
-
const request = {
|
|
4265
|
-
kind
|
|
4266
|
-
};
|
|
4267
|
-
taskQueue.addTask(key, request, (response) => {
|
|
4268
|
-
if (!warmup && response.runTimeL !== void 0) {
|
|
4269
|
-
statsL.addRun(response.runTimeL);
|
|
4270
|
-
}
|
|
4271
|
-
if (!warmup && response.runTimeR !== void 0) {
|
|
4272
|
-
statsR.addRun(response.runTimeR);
|
|
4273
|
-
}
|
|
4274
|
-
});
|
|
4627
|
+
const scenarioSpec = allInputsAtPositionSpec("at-default");
|
|
4628
|
+
const warmupCount = (_b = (_a = this.options) == null ? void 0 : _a.warmupCount) != null ? _b : 5;
|
|
4629
|
+
const runCount = (_d = (_c = this.options) == null ? void 0 : _c.runCount) != null ? _d : 100;
|
|
4630
|
+
let totalTasks = 0;
|
|
4631
|
+
if (((_e = this.options) == null ? void 0 : _e.mode) === "parallel") {
|
|
4632
|
+
totalTasks = warmupCount + runCount;
|
|
4633
|
+
} else {
|
|
4634
|
+
totalTasks = (warmupCount + runCount) * 2;
|
|
4275
4635
|
}
|
|
4636
|
+
let tasksCompleted = 0;
|
|
4637
|
+
let perfTaskId = 1;
|
|
4638
|
+
const addTask = (warmup, kind) => {
|
|
4639
|
+
const task = {
|
|
4640
|
+
key: `perf-runner-${perfTaskId++}`,
|
|
4641
|
+
kind: "perf-runner",
|
|
4642
|
+
process: (bundleModels) => __async(this, null, function* () {
|
|
4643
|
+
var _a2, _b2, _c2, _d2;
|
|
4644
|
+
this.pendingTaskKeys.delete(task.key);
|
|
4645
|
+
try {
|
|
4646
|
+
let runTimeL;
|
|
4647
|
+
let runTimeR;
|
|
4648
|
+
switch (kind) {
|
|
4649
|
+
case "left": {
|
|
4650
|
+
const result = yield bundleModels.L.getDatasetsForScenario(scenarioSpec, []);
|
|
4651
|
+
runTimeL = result.modelRunTime;
|
|
4652
|
+
break;
|
|
4653
|
+
}
|
|
4654
|
+
case "right": {
|
|
4655
|
+
const result = yield bundleModels.R.getDatasetsForScenario(scenarioSpec, []);
|
|
4656
|
+
runTimeR = result.modelRunTime;
|
|
4657
|
+
break;
|
|
4658
|
+
}
|
|
4659
|
+
case "both": {
|
|
4660
|
+
const [resultL, resultR] = yield Promise.all([
|
|
4661
|
+
bundleModels.L.getDatasetsForScenario(scenarioSpec, []),
|
|
4662
|
+
bundleModels.R.getDatasetsForScenario(scenarioSpec, [])
|
|
4663
|
+
]);
|
|
4664
|
+
runTimeL = resultL.modelRunTime;
|
|
4665
|
+
runTimeR = resultR.modelRunTime;
|
|
4666
|
+
break;
|
|
4667
|
+
}
|
|
4668
|
+
default:
|
|
4669
|
+
(0, import_assert_never11.assertNever)(kind);
|
|
4670
|
+
}
|
|
4671
|
+
if (!warmup) {
|
|
4672
|
+
if (runTimeL !== void 0) {
|
|
4673
|
+
statsL.addRun(runTimeL);
|
|
4674
|
+
}
|
|
4675
|
+
if (runTimeR !== void 0) {
|
|
4676
|
+
statsR.addRun(runTimeR);
|
|
4677
|
+
}
|
|
4678
|
+
}
|
|
4679
|
+
tasksCompleted++;
|
|
4680
|
+
if (tasksCompleted === totalTasks) {
|
|
4681
|
+
(_b2 = (_a2 = this.callbacks).onComplete) == null ? void 0 : _b2.call(_a2, statsL.toReport(), statsR.toReport());
|
|
4682
|
+
}
|
|
4683
|
+
} catch (error) {
|
|
4684
|
+
(_d2 = (_c2 = this.callbacks).onError) == null ? void 0 : _d2.call(_c2, error);
|
|
4685
|
+
}
|
|
4686
|
+
})
|
|
4687
|
+
};
|
|
4688
|
+
this.taskQueue.addTask(task);
|
|
4689
|
+
this.pendingTaskKeys.add(task.key);
|
|
4690
|
+
};
|
|
4276
4691
|
function addTasks(kind) {
|
|
4277
4692
|
for (let i = 0; i < warmupCount; i++) {
|
|
4278
|
-
addTask(
|
|
4693
|
+
addTask(true, kind);
|
|
4279
4694
|
}
|
|
4280
4695
|
for (let i = 0; i < runCount; i++) {
|
|
4281
|
-
addTask(
|
|
4696
|
+
addTask(false, kind);
|
|
4282
4697
|
}
|
|
4283
4698
|
}
|
|
4284
|
-
if (this.mode === "parallel") {
|
|
4699
|
+
if (((_f = this.options) == null ? void 0 : _f.mode) === "parallel") {
|
|
4285
4700
|
addTasks("both");
|
|
4286
4701
|
} else {
|
|
4287
4702
|
addTasks("left");
|
|
@@ -4290,6 +4705,303 @@ var PerfRunner = class {
|
|
|
4290
4705
|
}
|
|
4291
4706
|
};
|
|
4292
4707
|
|
|
4708
|
+
// src/trace/trace-runner.ts
|
|
4709
|
+
var import_assert_never12 = require("assert-never");
|
|
4710
|
+
function runTraceWithTaskQueue(modelSpec, taskQueue, callbacks, options) {
|
|
4711
|
+
const traceRunner = new TraceRunner(taskQueue, callbacks);
|
|
4712
|
+
traceRunner.start(modelSpec, options);
|
|
4713
|
+
return () => {
|
|
4714
|
+
traceRunner.cancel();
|
|
4715
|
+
};
|
|
4716
|
+
}
|
|
4717
|
+
function runTrace(modelSpec, callbacks, options) {
|
|
4718
|
+
const taskQueue = TaskQueue.getInstance();
|
|
4719
|
+
return runTraceWithTaskQueue(modelSpec, taskQueue, callbacks, options);
|
|
4720
|
+
}
|
|
4721
|
+
var TraceRunner = class {
|
|
4722
|
+
constructor(taskQueue, callbacks) {
|
|
4723
|
+
this.taskQueue = taskQueue;
|
|
4724
|
+
this.callbacks = callbacks;
|
|
4725
|
+
this.pendingTaskKeys = /* @__PURE__ */ new Set();
|
|
4726
|
+
this.stopped = false;
|
|
4727
|
+
}
|
|
4728
|
+
cancel() {
|
|
4729
|
+
if (!this.stopped) {
|
|
4730
|
+
for (const taskKey of this.pendingTaskKeys) {
|
|
4731
|
+
this.taskQueue.cancelTask(taskKey);
|
|
4732
|
+
}
|
|
4733
|
+
this.stopped = true;
|
|
4734
|
+
}
|
|
4735
|
+
}
|
|
4736
|
+
start(modelSpec, options) {
|
|
4737
|
+
const allDatasetKeys = [...modelSpec.implVars.keys()];
|
|
4738
|
+
const traceRequests = [];
|
|
4739
|
+
const batchSize = 2e3;
|
|
4740
|
+
for (let i = 0; i < allDatasetKeys.length; i += batchSize) {
|
|
4741
|
+
const datasetKeysForBatch = allDatasetKeys.slice(i, i + batchSize);
|
|
4742
|
+
switch (options.kind) {
|
|
4743
|
+
case "compare-to-bundle":
|
|
4744
|
+
traceRequests.push({
|
|
4745
|
+
kind: "compare-to-bundle",
|
|
4746
|
+
datasetKeys: datasetKeysForBatch,
|
|
4747
|
+
bundleSide0: options.bundleSide0,
|
|
4748
|
+
scenarioSpec0: options.scenarioSpec0,
|
|
4749
|
+
bundleSide1: options.bundleSide1,
|
|
4750
|
+
scenarioSpec1: options.scenarioSpec1
|
|
4751
|
+
});
|
|
4752
|
+
break;
|
|
4753
|
+
case "compare-to-ext-data":
|
|
4754
|
+
traceRequests.push({
|
|
4755
|
+
kind: "compare-to-ext-data",
|
|
4756
|
+
datasetKeys: datasetKeysForBatch,
|
|
4757
|
+
extData: options.extData,
|
|
4758
|
+
bundleSide: options.bundleSide,
|
|
4759
|
+
scenarioSpec: options.scenarioSpec
|
|
4760
|
+
});
|
|
4761
|
+
break;
|
|
4762
|
+
default:
|
|
4763
|
+
(0, import_assert_never12.assertNever)(options);
|
|
4764
|
+
}
|
|
4765
|
+
}
|
|
4766
|
+
const allDatasetReports = /* @__PURE__ */ new Map();
|
|
4767
|
+
const taskCount = traceRequests.length;
|
|
4768
|
+
let tasksCompleted = 0;
|
|
4769
|
+
let traceTaskId = 1;
|
|
4770
|
+
for (const traceRequest of traceRequests) {
|
|
4771
|
+
const task = {
|
|
4772
|
+
key: `trace-runner-${traceTaskId++}`,
|
|
4773
|
+
kind: "trace-runner",
|
|
4774
|
+
process: (bundleModels) => __async(this, null, function* () {
|
|
4775
|
+
var _a, _b;
|
|
4776
|
+
this.pendingTaskKeys.delete(task.key);
|
|
4777
|
+
let datasetReports;
|
|
4778
|
+
switch (traceRequest.kind) {
|
|
4779
|
+
case "compare-to-bundle":
|
|
4780
|
+
datasetReports = yield processCompareToBundleRequest(traceRequest, bundleModels);
|
|
4781
|
+
break;
|
|
4782
|
+
case "compare-to-ext-data":
|
|
4783
|
+
datasetReports = yield processCompareToExtDataRequest(traceRequest, bundleModels);
|
|
4784
|
+
break;
|
|
4785
|
+
default:
|
|
4786
|
+
(0, import_assert_never12.assertNever)(traceRequest);
|
|
4787
|
+
}
|
|
4788
|
+
for (const datasetReport of datasetReports) {
|
|
4789
|
+
allDatasetReports.set(datasetReport.datasetKey, datasetReport);
|
|
4790
|
+
}
|
|
4791
|
+
tasksCompleted++;
|
|
4792
|
+
if (tasksCompleted === taskCount) {
|
|
4793
|
+
const traceReport = {
|
|
4794
|
+
datasetReports: allDatasetReports
|
|
4795
|
+
};
|
|
4796
|
+
(_b = (_a = this.callbacks).onComplete) == null ? void 0 : _b.call(_a, traceReport);
|
|
4797
|
+
}
|
|
4798
|
+
})
|
|
4799
|
+
};
|
|
4800
|
+
this.taskQueue.addTask(task);
|
|
4801
|
+
this.pendingTaskKeys.add(task.key);
|
|
4802
|
+
}
|
|
4803
|
+
}
|
|
4804
|
+
};
|
|
4805
|
+
function processCompareToBundleRequest(request, bundleModels) {
|
|
4806
|
+
return __async(this, null, function* () {
|
|
4807
|
+
const bundleModel0 = request.bundleSide0 === "left" ? bundleModels.L : bundleModels.R;
|
|
4808
|
+
const bundleModel1 = request.bundleSide1 === "left" ? bundleModels.L : bundleModels.R;
|
|
4809
|
+
let result0;
|
|
4810
|
+
let result1;
|
|
4811
|
+
if (bundleModel1 === bundleModel0) {
|
|
4812
|
+
result0 = yield bundleModel0.getDatasetsForScenario(request.scenarioSpec0, request.datasetKeys);
|
|
4813
|
+
result1 = yield bundleModel1.getDatasetsForScenario(request.scenarioSpec1, request.datasetKeys);
|
|
4814
|
+
} else {
|
|
4815
|
+
;
|
|
4816
|
+
[result0, result1] = yield Promise.all([
|
|
4817
|
+
bundleModel0.getDatasetsForScenario(request.scenarioSpec0, request.datasetKeys),
|
|
4818
|
+
bundleModel1.getDatasetsForScenario(request.scenarioSpec1, request.datasetKeys)
|
|
4819
|
+
]);
|
|
4820
|
+
}
|
|
4821
|
+
const datasetReports = [];
|
|
4822
|
+
for (const datasetKey of request.datasetKeys) {
|
|
4823
|
+
const dataset0 = result0.datasetMap.get(datasetKey);
|
|
4824
|
+
const dataset1 = result1.datasetMap.get(datasetKey);
|
|
4825
|
+
const datasetReport = diffDatasets2(
|
|
4826
|
+
datasetKey,
|
|
4827
|
+
dataset0,
|
|
4828
|
+
dataset1,
|
|
4829
|
+
/*matchPrecisionOfLeft=*/
|
|
4830
|
+
false
|
|
4831
|
+
);
|
|
4832
|
+
datasetReports.push(datasetReport);
|
|
4833
|
+
}
|
|
4834
|
+
return datasetReports;
|
|
4835
|
+
});
|
|
4836
|
+
}
|
|
4837
|
+
function processCompareToExtDataRequest(request, bundleModels) {
|
|
4838
|
+
return __async(this, null, function* () {
|
|
4839
|
+
const bundleModel = request.bundleSide === "left" ? bundleModels.L : bundleModels.R;
|
|
4840
|
+
const resultR = yield bundleModel.getDatasetsForScenario(request.scenarioSpec, request.datasetKeys);
|
|
4841
|
+
const datasetReports = [];
|
|
4842
|
+
for (const datasetKey of request.datasetKeys) {
|
|
4843
|
+
let datasetL = request.extData.get(datasetKey);
|
|
4844
|
+
if (datasetL === void 0) {
|
|
4845
|
+
const datasetKeyParts = datasetKey.split("[");
|
|
4846
|
+
if (datasetKeyParts.length === 2) {
|
|
4847
|
+
const baseKey = datasetKeyParts[0];
|
|
4848
|
+
const keySubParts = datasetKeyParts[1].replace("]", "");
|
|
4849
|
+
const keySubIds = keySubParts.split(",");
|
|
4850
|
+
const subIdPermutations = permutationsOf(keySubIds);
|
|
4851
|
+
for (const subIds of subIdPermutations) {
|
|
4852
|
+
const datDatasetKey = `${baseKey}[${subIds.join(",")}]`;
|
|
4853
|
+
datasetL = request.extData.get(datDatasetKey);
|
|
4854
|
+
if (datasetL !== void 0) {
|
|
4855
|
+
break;
|
|
4856
|
+
}
|
|
4857
|
+
}
|
|
4858
|
+
}
|
|
4859
|
+
if (datasetL === void 0) {
|
|
4860
|
+
console.warn(`WARNING: Failed to find data in dat file for key=${datasetKey}`);
|
|
4861
|
+
}
|
|
4862
|
+
}
|
|
4863
|
+
const datasetR = resultR.datasetMap.get(datasetKey);
|
|
4864
|
+
const datasetReport = diffDatasets2(
|
|
4865
|
+
datasetKey,
|
|
4866
|
+
datasetL,
|
|
4867
|
+
datasetR,
|
|
4868
|
+
/*matchPrecisionOfLeft=*/
|
|
4869
|
+
true
|
|
4870
|
+
);
|
|
4871
|
+
datasetReports.push(datasetReport);
|
|
4872
|
+
}
|
|
4873
|
+
return datasetReports;
|
|
4874
|
+
});
|
|
4875
|
+
}
|
|
4876
|
+
function diffDatasets2(datasetKey, datasetL, datasetR, matchPrecisionOfLeft) {
|
|
4877
|
+
const points = /* @__PURE__ */ new Map();
|
|
4878
|
+
let minValueL = Number.MAX_VALUE;
|
|
4879
|
+
let maxValueL = Number.MIN_VALUE;
|
|
4880
|
+
let minValueR = Number.MAX_VALUE;
|
|
4881
|
+
let maxValueR = Number.MIN_VALUE;
|
|
4882
|
+
let minValue = Number.MAX_VALUE;
|
|
4883
|
+
let maxValue = Number.MIN_VALUE;
|
|
4884
|
+
let minRawDiff = Number.MAX_VALUE;
|
|
4885
|
+
let maxRawDiff = -1;
|
|
4886
|
+
let maxDiffPoint;
|
|
4887
|
+
let diffCount = 0;
|
|
4888
|
+
let totalRawDiff = 0;
|
|
4889
|
+
if (datasetL && datasetR) {
|
|
4890
|
+
const times = /* @__PURE__ */ new Set([...datasetL.keys(), ...datasetR.keys()]);
|
|
4891
|
+
for (const t of times) {
|
|
4892
|
+
const valueL = datasetL.get(t);
|
|
4893
|
+
if (valueL !== void 0) {
|
|
4894
|
+
if (valueL < minValueL) minValueL = valueL;
|
|
4895
|
+
if (valueL > maxValueL) maxValueL = valueL;
|
|
4896
|
+
if (valueL < minValue) minValue = valueL;
|
|
4897
|
+
if (valueL > maxValue) maxValue = valueL;
|
|
4898
|
+
}
|
|
4899
|
+
let valueR;
|
|
4900
|
+
const rawValueR = datasetR.get(t);
|
|
4901
|
+
if (rawValueR !== void 0) {
|
|
4902
|
+
if (matchPrecisionOfLeft && valueL !== void 0) {
|
|
4903
|
+
valueR = matchPrecision(rawValueR, valueL);
|
|
4904
|
+
} else {
|
|
4905
|
+
valueR = rawValueR;
|
|
4906
|
+
}
|
|
4907
|
+
if (valueR < minValueR) minValueR = valueR;
|
|
4908
|
+
if (valueR > maxValueR) maxValueR = valueR;
|
|
4909
|
+
if (valueR < minValue) minValue = valueR;
|
|
4910
|
+
if (valueR > maxValue) maxValue = valueR;
|
|
4911
|
+
}
|
|
4912
|
+
if (valueL === void 0 || valueR === void 0) {
|
|
4913
|
+
continue;
|
|
4914
|
+
}
|
|
4915
|
+
const point = {
|
|
4916
|
+
time: t,
|
|
4917
|
+
valueL,
|
|
4918
|
+
valueR
|
|
4919
|
+
};
|
|
4920
|
+
points.set(t, point);
|
|
4921
|
+
const rawDiff = Math.abs(valueR - valueL);
|
|
4922
|
+
if (rawDiff < minRawDiff) {
|
|
4923
|
+
minRawDiff = rawDiff;
|
|
4924
|
+
}
|
|
4925
|
+
if (rawDiff > maxRawDiff) {
|
|
4926
|
+
maxRawDiff = rawDiff;
|
|
4927
|
+
maxDiffPoint = point;
|
|
4928
|
+
}
|
|
4929
|
+
diffCount++;
|
|
4930
|
+
totalRawDiff += rawDiff;
|
|
4931
|
+
}
|
|
4932
|
+
}
|
|
4933
|
+
function pct(x) {
|
|
4934
|
+
return x * 100;
|
|
4935
|
+
}
|
|
4936
|
+
let minDiff;
|
|
4937
|
+
let maxDiff;
|
|
4938
|
+
let avgDiff;
|
|
4939
|
+
if (minValueL === maxValueL && minValueR === maxValueR) {
|
|
4940
|
+
const diff = pct(maxValueL !== 0 ? Math.abs((maxValueR - maxValueL) / maxValueL) : 1);
|
|
4941
|
+
minDiff = diff;
|
|
4942
|
+
maxDiff = diff;
|
|
4943
|
+
avgDiff = diff;
|
|
4944
|
+
} else {
|
|
4945
|
+
const spread = maxValue - minValue;
|
|
4946
|
+
minDiff = pct(spread > 0 ? minRawDiff / spread : 0);
|
|
4947
|
+
maxDiff = pct(spread > 0 ? maxRawDiff / spread : 0);
|
|
4948
|
+
const avgRawDiff = totalRawDiff / diffCount;
|
|
4949
|
+
avgDiff = pct(spread > 0 ? avgRawDiff / spread : 0);
|
|
4950
|
+
}
|
|
4951
|
+
let validity;
|
|
4952
|
+
if (datasetL && datasetR) {
|
|
4953
|
+
validity = "both";
|
|
4954
|
+
} else if (datasetL) {
|
|
4955
|
+
validity = "left-only";
|
|
4956
|
+
} else if (datasetR) {
|
|
4957
|
+
validity = "right-only";
|
|
4958
|
+
} else {
|
|
4959
|
+
validity = "neither";
|
|
4960
|
+
}
|
|
4961
|
+
return {
|
|
4962
|
+
datasetKey,
|
|
4963
|
+
validity,
|
|
4964
|
+
points,
|
|
4965
|
+
minValue,
|
|
4966
|
+
maxValue,
|
|
4967
|
+
avgDiff,
|
|
4968
|
+
minDiff,
|
|
4969
|
+
maxDiff,
|
|
4970
|
+
maxDiffPoint
|
|
4971
|
+
};
|
|
4972
|
+
}
|
|
4973
|
+
function matchPrecision(x, baseline) {
|
|
4974
|
+
const s = baseline.toString();
|
|
4975
|
+
if (s.includes("e")) {
|
|
4976
|
+
return x;
|
|
4977
|
+
}
|
|
4978
|
+
const parts = s.split(".");
|
|
4979
|
+
if (parts.length < 2) {
|
|
4980
|
+
return x;
|
|
4981
|
+
}
|
|
4982
|
+
const sigDigits = parts[1].replace(/0+$/, "").length;
|
|
4983
|
+
if (sigDigits > 21) {
|
|
4984
|
+
return x;
|
|
4985
|
+
}
|
|
4986
|
+
return parseFloat(x.toFixed(sigDigits));
|
|
4987
|
+
}
|
|
4988
|
+
function permutationsOf(inputArr) {
|
|
4989
|
+
const result = [];
|
|
4990
|
+
const permute = (arr, m = []) => {
|
|
4991
|
+
if (arr.length === 0) {
|
|
4992
|
+
result.push(m);
|
|
4993
|
+
} else {
|
|
4994
|
+
for (let i = 0; i < arr.length; i++) {
|
|
4995
|
+
const curr = arr.slice();
|
|
4996
|
+
const next = curr.splice(i, 1);
|
|
4997
|
+
permute(curr.slice(), m.concat(next));
|
|
4998
|
+
}
|
|
4999
|
+
}
|
|
5000
|
+
};
|
|
5001
|
+
permute(inputArr);
|
|
5002
|
+
return result;
|
|
5003
|
+
}
|
|
5004
|
+
|
|
4293
5005
|
// src/data/data-planner.ts
|
|
4294
5006
|
var DataPlanner = class {
|
|
4295
5007
|
/**
|
|
@@ -4476,10 +5188,10 @@ function scenarioPairUid(scenarioSpecL, scenarioSpecR) {
|
|
|
4476
5188
|
}
|
|
4477
5189
|
|
|
4478
5190
|
// src/check/check-runner.ts
|
|
4479
|
-
function runChecks(checkConfig, checkSpec, dataPlanner, refDataPlanner,
|
|
4480
|
-
const modelSpec = checkConfig.bundle.
|
|
5191
|
+
function runChecks(checkConfig, checkSpec, dataPlanner, refDataPlanner, skipChecks) {
|
|
5192
|
+
const modelSpec = checkConfig.bundle.modelSpec;
|
|
4481
5193
|
const checkPlanner = new CheckPlanner(modelSpec);
|
|
4482
|
-
checkPlanner.addAllChecks(checkSpec,
|
|
5194
|
+
checkPlanner.addAllChecks(checkSpec, skipChecks);
|
|
4483
5195
|
const checkPlan = checkPlanner.buildPlan();
|
|
4484
5196
|
const refDatasets = /* @__PURE__ */ new Map();
|
|
4485
5197
|
for (const [dataRefKey, dataRef] of checkPlan.dataRefs.entries()) {
|
|
@@ -4492,11 +5204,15 @@ function runChecks(checkConfig, checkSpec, dataPlanner, refDataPlanner, simplify
|
|
|
4492
5204
|
}
|
|
4493
5205
|
const checkResults = /* @__PURE__ */ new Map();
|
|
4494
5206
|
for (const [checkKey, checkTask] of checkPlan.tasks.entries()) {
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
5207
|
+
if (checkTask.skip === true) {
|
|
5208
|
+
checkResults.set(checkKey, { status: "skipped" });
|
|
5209
|
+
} else {
|
|
5210
|
+
dataPlanner.addRequest(void 0, checkTask.scenario.spec, checkTask.dataset.datasetKey, (datasets) => {
|
|
5211
|
+
const dataset = datasets.datasetR;
|
|
5212
|
+
const checkResult = runCheck(checkTask, dataset, refDatasets);
|
|
5213
|
+
checkResults.set(checkKey, checkResult);
|
|
5214
|
+
});
|
|
5215
|
+
}
|
|
4500
5216
|
}
|
|
4501
5217
|
return () => {
|
|
4502
5218
|
return buildCheckReport(checkPlan, checkResults);
|
|
@@ -4561,21 +5277,73 @@ function runCheck(checkTask, dataset, refDatasets) {
|
|
|
4561
5277
|
}
|
|
4562
5278
|
|
|
4563
5279
|
// src/comparison/run/comparison-runner.ts
|
|
4564
|
-
function runComparisons(comparisonConfig, dataPlanner) {
|
|
5280
|
+
function runComparisons(comparisonConfig, dataPlanner, skipScenarios) {
|
|
5281
|
+
function skipScenarioKey(title, subtitle) {
|
|
5282
|
+
let key = title.toLowerCase();
|
|
5283
|
+
if (subtitle) {
|
|
5284
|
+
key += ` :: ${subtitle.toLowerCase()}`;
|
|
5285
|
+
}
|
|
5286
|
+
return key;
|
|
5287
|
+
}
|
|
5288
|
+
const skipScenariosSet = new Set(skipScenarios.map((scenario) => skipScenarioKey(scenario.title, scenario.subtitle)));
|
|
5289
|
+
const allScenarios = [...comparisonConfig.scenarios.getAllScenarios()];
|
|
5290
|
+
let baselineScenario;
|
|
5291
|
+
const baselineScenarioIndex = allScenarios.findIndex((scenario) => {
|
|
5292
|
+
const settings = scenario.settings;
|
|
5293
|
+
return settings.kind === "all-inputs-settings" && settings.position === "at-default";
|
|
5294
|
+
});
|
|
5295
|
+
if (baselineScenarioIndex !== -1) {
|
|
5296
|
+
baselineScenario = allScenarios.splice(baselineScenarioIndex, 1)[0];
|
|
5297
|
+
}
|
|
4565
5298
|
const testReports = [];
|
|
4566
|
-
|
|
5299
|
+
const baselineDiffReports = /* @__PURE__ */ new Map();
|
|
5300
|
+
function runComparisonsForScenario(scenario, isBaseline) {
|
|
4567
5301
|
const datasetKeys = comparisonConfig.datasets.getDatasetKeysForScenario(scenario);
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
5302
|
+
const shouldSkip = skipScenariosSet.has(skipScenarioKey(scenario.title, scenario.subtitle));
|
|
5303
|
+
if (shouldSkip) {
|
|
5304
|
+
for (const datasetKey of datasetKeys) {
|
|
4571
5305
|
testReports.push({
|
|
4572
5306
|
scenarioKey: scenario.key,
|
|
4573
5307
|
datasetKey,
|
|
4574
|
-
diffReport
|
|
5308
|
+
diffReport: void 0
|
|
4575
5309
|
});
|
|
5310
|
+
}
|
|
5311
|
+
return;
|
|
5312
|
+
}
|
|
5313
|
+
for (const datasetKey of datasetKeys) {
|
|
5314
|
+
dataPlanner.addRequest(scenario.specL, scenario.specR, datasetKey, (datasets) => {
|
|
5315
|
+
const diffReport = diffDatasets(datasets.datasetL, datasets.datasetR);
|
|
5316
|
+
if (isBaseline) {
|
|
5317
|
+
baselineDiffReports.set(datasetKey, diffReport);
|
|
5318
|
+
testReports.push({
|
|
5319
|
+
scenarioKey: scenario.key,
|
|
5320
|
+
datasetKey,
|
|
5321
|
+
diffReport
|
|
5322
|
+
});
|
|
5323
|
+
} else {
|
|
5324
|
+
const baselineDiffReport = baselineDiffReports.get(datasetKey);
|
|
5325
|
+
testReports.push({
|
|
5326
|
+
scenarioKey: scenario.key,
|
|
5327
|
+
datasetKey,
|
|
5328
|
+
diffReport,
|
|
5329
|
+
baselineDiffReport
|
|
5330
|
+
});
|
|
5331
|
+
}
|
|
4576
5332
|
});
|
|
4577
5333
|
}
|
|
4578
5334
|
}
|
|
5335
|
+
runComparisonsForScenario(
|
|
5336
|
+
baselineScenario,
|
|
5337
|
+
/*isBaseline=*/
|
|
5338
|
+
true
|
|
5339
|
+
);
|
|
5340
|
+
for (const scenario of allScenarios) {
|
|
5341
|
+
runComparisonsForScenario(
|
|
5342
|
+
scenario,
|
|
5343
|
+
/*isBaseline=*/
|
|
5344
|
+
false
|
|
5345
|
+
);
|
|
5346
|
+
}
|
|
4579
5347
|
return () => {
|
|
4580
5348
|
return testReports;
|
|
4581
5349
|
};
|
|
@@ -4583,74 +5351,52 @@ function runComparisons(comparisonConfig, dataPlanner) {
|
|
|
4583
5351
|
|
|
4584
5352
|
// src/suite/suite-runner.ts
|
|
4585
5353
|
var SuiteRunner = class {
|
|
4586
|
-
constructor(config, callbacks) {
|
|
5354
|
+
constructor(config, taskQueue, callbacks) {
|
|
4587
5355
|
this.config = config;
|
|
5356
|
+
this.taskQueue = taskQueue;
|
|
4588
5357
|
this.callbacks = callbacks;
|
|
4589
5358
|
this.perfStatsL = new PerfStats();
|
|
4590
5359
|
this.perfStatsR = new PerfStats();
|
|
5360
|
+
this.pendingTaskKeys = /* @__PURE__ */ new Set();
|
|
4591
5361
|
this.stopped = false;
|
|
4592
|
-
this.taskQueue = new TaskQueue({
|
|
4593
|
-
process: (request) => {
|
|
4594
|
-
return this.processRequest(request);
|
|
4595
|
-
}
|
|
4596
|
-
});
|
|
4597
5362
|
}
|
|
4598
5363
|
cancel() {
|
|
4599
5364
|
if (!this.stopped) {
|
|
5365
|
+
for (const taskKey of this.pendingTaskKeys) {
|
|
5366
|
+
this.taskQueue.cancelTask(taskKey);
|
|
5367
|
+
}
|
|
4600
5368
|
this.stopped = true;
|
|
4601
|
-
this.taskQueue.shutdown();
|
|
4602
5369
|
}
|
|
4603
5370
|
}
|
|
4604
5371
|
start(options) {
|
|
4605
5372
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
4606
5373
|
(_b = (_a = this.callbacks).onProgress) == null ? void 0 : _b.call(_a, 0);
|
|
4607
|
-
const
|
|
4608
|
-
const dataPlanner = new DataPlanner(
|
|
4609
|
-
const refDataPlanner = new DataPlanner(
|
|
5374
|
+
const modelSpecR = this.config.check.bundle.modelSpec;
|
|
5375
|
+
const dataPlanner = new DataPlanner(modelSpecR.outputVars.size);
|
|
5376
|
+
const refDataPlanner = new DataPlanner(modelSpecR.outputVars.size);
|
|
4610
5377
|
const checkSpecResult = parseTestYaml(this.config.check.tests);
|
|
4611
5378
|
if (checkSpecResult.isErr()) {
|
|
4612
5379
|
(_d = (_c = this.callbacks).onError) == null ? void 0 : _d.call(_c, checkSpecResult.error);
|
|
4613
5380
|
return;
|
|
4614
5381
|
}
|
|
4615
5382
|
const checkSpec = checkSpecResult.value;
|
|
4616
|
-
const
|
|
4617
|
-
const buildCheckReport2 = runChecks(this.config.check, checkSpec, dataPlanner, refDataPlanner,
|
|
5383
|
+
const skipChecks = (options == null ? void 0 : options.skipChecks) || [];
|
|
5384
|
+
const buildCheckReport2 = runChecks(this.config.check, checkSpec, dataPlanner, refDataPlanner, skipChecks);
|
|
4618
5385
|
let buildComparisonTestReports;
|
|
4619
5386
|
if (this.config.comparison) {
|
|
4620
|
-
|
|
5387
|
+
const skipScenarios = (options == null ? void 0 : options.skipComparisonScenarios) || [];
|
|
5388
|
+
buildComparisonTestReports = runComparisons(this.config.comparison, dataPlanner, skipScenarios);
|
|
4621
5389
|
}
|
|
4622
|
-
this.taskQueue.onIdle = (error) => {
|
|
4623
|
-
var _a2, _b2, _c2, _d2;
|
|
4624
|
-
if (this.stopped) {
|
|
4625
|
-
return;
|
|
4626
|
-
}
|
|
4627
|
-
if (error) {
|
|
4628
|
-
(_b2 = (_a2 = this.callbacks).onError) == null ? void 0 : _b2.call(_a2, error);
|
|
4629
|
-
} else {
|
|
4630
|
-
const checkReport = buildCheckReport2();
|
|
4631
|
-
let comparisonReport;
|
|
4632
|
-
if (this.config.comparison) {
|
|
4633
|
-
comparisonReport = {
|
|
4634
|
-
testReports: buildComparisonTestReports(),
|
|
4635
|
-
perfReportL: this.perfStatsL.toReport(),
|
|
4636
|
-
perfReportR: this.perfStatsR.toReport()
|
|
4637
|
-
};
|
|
4638
|
-
}
|
|
4639
|
-
(_d2 = (_c2 = this.callbacks).onComplete) == null ? void 0 : _d2.call(_c2, {
|
|
4640
|
-
checkReport,
|
|
4641
|
-
comparisonReport
|
|
4642
|
-
});
|
|
4643
|
-
}
|
|
4644
|
-
};
|
|
4645
5390
|
const refDataPlan = refDataPlanner.buildPlan();
|
|
4646
5391
|
const dataPlan = dataPlanner.buildPlan();
|
|
4647
5392
|
const dataRequests = [...refDataPlan.requests, ...dataPlan.requests];
|
|
4648
5393
|
const taskCount = dataRequests.length;
|
|
4649
5394
|
if (taskCount === 0) {
|
|
5395
|
+
const checkReport = buildCheckReport2();
|
|
4650
5396
|
let comparisonReport;
|
|
4651
5397
|
if (this.config.comparison) {
|
|
4652
5398
|
comparisonReport = {
|
|
4653
|
-
testReports:
|
|
5399
|
+
testReports: buildComparisonTestReports(),
|
|
4654
5400
|
perfReportL: this.perfStatsL.toReport(),
|
|
4655
5401
|
perfReportR: this.perfStatsR.toReport()
|
|
4656
5402
|
};
|
|
@@ -4658,26 +5404,54 @@ var SuiteRunner = class {
|
|
|
4658
5404
|
this.cancel();
|
|
4659
5405
|
(_f = (_e = this.callbacks).onProgress) == null ? void 0 : _f.call(_e, 1);
|
|
4660
5406
|
(_h = (_g = this.callbacks).onComplete) == null ? void 0 : _h.call(_g, {
|
|
4661
|
-
checkReport
|
|
4662
|
-
groups: []
|
|
4663
|
-
},
|
|
5407
|
+
checkReport,
|
|
4664
5408
|
comparisonReport
|
|
4665
5409
|
});
|
|
4666
5410
|
return;
|
|
4667
5411
|
}
|
|
5412
|
+
const buildReport = (error) => {
|
|
5413
|
+
var _a2, _b2, _c2, _d2;
|
|
5414
|
+
if (error) {
|
|
5415
|
+
(_b2 = (_a2 = this.callbacks).onError) == null ? void 0 : _b2.call(_a2, error);
|
|
5416
|
+
} else {
|
|
5417
|
+
const checkReport = buildCheckReport2();
|
|
5418
|
+
let comparisonReport;
|
|
5419
|
+
if (this.config.comparison) {
|
|
5420
|
+
comparisonReport = {
|
|
5421
|
+
testReports: buildComparisonTestReports(),
|
|
5422
|
+
perfReportL: this.perfStatsL.toReport(),
|
|
5423
|
+
perfReportR: this.perfStatsR.toReport()
|
|
5424
|
+
};
|
|
5425
|
+
}
|
|
5426
|
+
(_d2 = (_c2 = this.callbacks).onComplete) == null ? void 0 : _d2.call(_c2, {
|
|
5427
|
+
checkReport,
|
|
5428
|
+
comparisonReport
|
|
5429
|
+
});
|
|
5430
|
+
}
|
|
5431
|
+
};
|
|
4668
5432
|
let tasksCompleted = 0;
|
|
4669
5433
|
let dataTaskId = 1;
|
|
4670
5434
|
for (const dataRequest of dataRequests) {
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
(
|
|
4675
|
-
|
|
5435
|
+
const task = {
|
|
5436
|
+
key: `suite-runner-${dataTaskId++}`,
|
|
5437
|
+
kind: "suite-runner",
|
|
5438
|
+
process: (bundleModels) => __async(this, null, function* () {
|
|
5439
|
+
var _a2, _b2;
|
|
5440
|
+
this.pendingTaskKeys.delete(task.key);
|
|
5441
|
+
yield this.processRequest(dataRequest, bundleModels);
|
|
5442
|
+
tasksCompleted++;
|
|
5443
|
+
(_b2 = (_a2 = this.callbacks).onProgress) == null ? void 0 : _b2.call(_a2, tasksCompleted / taskCount);
|
|
5444
|
+
if (tasksCompleted === taskCount) {
|
|
5445
|
+
buildReport();
|
|
5446
|
+
}
|
|
5447
|
+
})
|
|
5448
|
+
};
|
|
5449
|
+
this.taskQueue.addTask(task);
|
|
5450
|
+
this.pendingTaskKeys.add(task.key);
|
|
4676
5451
|
}
|
|
4677
5452
|
}
|
|
4678
|
-
processRequest(request) {
|
|
5453
|
+
processRequest(request, bundleModels) {
|
|
4679
5454
|
return __async(this, null, function* () {
|
|
4680
|
-
var _a, _b;
|
|
4681
5455
|
const datasetKeySet = /* @__PURE__ */ new Set();
|
|
4682
5456
|
for (const dataTask of request.dataTasks) {
|
|
4683
5457
|
datasetKeySet.add(dataTask.datasetKey);
|
|
@@ -4692,8 +5466,8 @@ var SuiteRunner = class {
|
|
|
4692
5466
|
}
|
|
4693
5467
|
});
|
|
4694
5468
|
}
|
|
4695
|
-
const bundleModelL =
|
|
4696
|
-
const bundleModelR =
|
|
5469
|
+
const bundleModelL = bundleModels.L;
|
|
5470
|
+
const bundleModelR = bundleModels.R;
|
|
4697
5471
|
const [datasetsResultL, datasetsResultR] = yield Promise.all([
|
|
4698
5472
|
getDatasets(bundleModelL, request.scenarioSpecL),
|
|
4699
5473
|
getDatasets(bundleModelR, request.scenarioSpecR)
|
|
@@ -4717,22 +5491,29 @@ var SuiteRunner = class {
|
|
|
4717
5491
|
});
|
|
4718
5492
|
}
|
|
4719
5493
|
};
|
|
4720
|
-
function
|
|
4721
|
-
const suiteRunner = new SuiteRunner(config, callbacks);
|
|
5494
|
+
function runSuiteWithTaskQueue(config, taskQueue, callbacks, options) {
|
|
5495
|
+
const suiteRunner = new SuiteRunner(config, taskQueue, callbacks);
|
|
4722
5496
|
suiteRunner.start(options);
|
|
4723
5497
|
return () => {
|
|
4724
5498
|
suiteRunner.cancel();
|
|
4725
5499
|
};
|
|
4726
5500
|
}
|
|
5501
|
+
function runSuite(config, callbacks, options) {
|
|
5502
|
+
const taskQueue = TaskQueue.getInstance();
|
|
5503
|
+
return runSuiteWithTaskQueue(config, taskQueue, callbacks, options);
|
|
5504
|
+
}
|
|
4727
5505
|
|
|
4728
5506
|
// src/suite/suite-reporting.ts
|
|
4729
|
-
function suiteSummaryFromReport(suiteReport) {
|
|
5507
|
+
function suiteSummaryFromReport(suiteReport, elapsedMillis) {
|
|
4730
5508
|
const checkSummary = checkSummaryFromReport(suiteReport.checkReport);
|
|
4731
5509
|
let comparisonSummary;
|
|
4732
5510
|
if (suiteReport.comparisonReport) {
|
|
4733
5511
|
comparisonSummary = comparisonSummaryFromReport(suiteReport.comparisonReport);
|
|
4734
5512
|
}
|
|
5513
|
+
const date = (/* @__PURE__ */ new Date()).toISOString();
|
|
4735
5514
|
return {
|
|
5515
|
+
date,
|
|
5516
|
+
elapsed: elapsedMillis,
|
|
4736
5517
|
checkSummary,
|
|
4737
5518
|
comparisonSummary
|
|
4738
5519
|
};
|
|
@@ -4741,20 +5522,27 @@ function suiteSummaryFromReport(suiteReport) {
|
|
|
4741
5522
|
0 && (module.exports = {
|
|
4742
5523
|
CheckDataCoordinator,
|
|
4743
5524
|
ComparisonDataCoordinator,
|
|
4744
|
-
PerfRunner,
|
|
4745
5525
|
PerfStats,
|
|
4746
5526
|
categorizeComparisonTestSummaries,
|
|
4747
5527
|
checkReportFromSummary,
|
|
4748
5528
|
checkSummaryFromReport,
|
|
4749
5529
|
comparisonSummaryFromReport,
|
|
5530
|
+
createCheckDataCoordinator,
|
|
5531
|
+
createCheckDataCoordinatorForTests,
|
|
5532
|
+
createComparisonDataCoordinator,
|
|
4750
5533
|
createConfig,
|
|
4751
5534
|
datasetMessage,
|
|
5535
|
+
decodeImplVars,
|
|
4752
5536
|
diffDatasets,
|
|
4753
5537
|
diffGraphs,
|
|
5538
|
+
encodeImplVars,
|
|
4754
5539
|
getScoresForTestSummaries,
|
|
4755
5540
|
predicateMessage,
|
|
5541
|
+
runPerf,
|
|
4756
5542
|
runSuite,
|
|
5543
|
+
runTrace,
|
|
4757
5544
|
scenarioMessage,
|
|
4758
|
-
suiteSummaryFromReport
|
|
5545
|
+
suiteSummaryFromReport,
|
|
5546
|
+
testSummaryFromReport
|
|
4759
5547
|
});
|
|
4760
5548
|
//# sourceMappingURL=index.cjs.map
|