@sdeverywhere/check-core 0.1.5 → 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 +1098 -439
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +469 -103
- package/dist/index.d.ts +469 -103
- package/dist/index.js +1089 -437
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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;
|
|
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];
|
|
1893
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,7 +3402,7 @@ 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 {
|
|
@@ -3190,7 +3465,7 @@ var ModelInputs = class {
|
|
|
3190
3465
|
};
|
|
3191
3466
|
|
|
3192
3467
|
// src/comparison/config/resolve/comparison-scenario-specs.ts
|
|
3193
|
-
var
|
|
3468
|
+
var import_assert_never9 = require("assert-never");
|
|
3194
3469
|
function scenarioSpecsFromSettings(settings) {
|
|
3195
3470
|
switch (settings.kind) {
|
|
3196
3471
|
case "all-inputs-settings": {
|
|
@@ -3203,7 +3478,7 @@ function scenarioSpecsFromSettings(settings) {
|
|
|
3203
3478
|
return [specL, specR];
|
|
3204
3479
|
}
|
|
3205
3480
|
default:
|
|
3206
|
-
(0,
|
|
3481
|
+
(0, import_assert_never9.assertNever)(settings);
|
|
3207
3482
|
}
|
|
3208
3483
|
}
|
|
3209
3484
|
function scenarioSpecFromInputs(inputs, side) {
|
|
@@ -3422,7 +3697,7 @@ function resolveScenariosFromSpec(modelInputsL, modelInputsR, scenarioSpec, genK
|
|
|
3422
3697
|
];
|
|
3423
3698
|
}
|
|
3424
3699
|
default:
|
|
3425
|
-
(0,
|
|
3700
|
+
(0, import_assert_never10.assertNever)(scenarioSpec);
|
|
3426
3701
|
}
|
|
3427
3702
|
}
|
|
3428
3703
|
function resolveScenarioMatrix(modelInputsL, modelInputsR, genKey) {
|
|
@@ -3478,7 +3753,7 @@ function resolveScenarioForInputSpecs(modelInputsL, modelInputsR, key, id, title
|
|
|
3478
3753
|
case "input-at-value":
|
|
3479
3754
|
return resolveInputForName(modelInputsL, modelInputsR, inputSpec.inputName, inputSpec.value);
|
|
3480
3755
|
default:
|
|
3481
|
-
(0,
|
|
3756
|
+
(0, import_assert_never10.assertNever)(inputSpec);
|
|
3482
3757
|
}
|
|
3483
3758
|
});
|
|
3484
3759
|
const settings = {
|
|
@@ -3511,7 +3786,7 @@ function resolveScenarioForDistinctInputSpecs(modelInputsL, modelInputsR, key, i
|
|
|
3511
3786
|
inputState = resolveInputForNameInModel(modelInputs, inputSpec.inputName, inputSpec.value);
|
|
3512
3787
|
break;
|
|
3513
3788
|
default:
|
|
3514
|
-
(0,
|
|
3789
|
+
(0, import_assert_never10.assertNever)(inputSpec);
|
|
3515
3790
|
}
|
|
3516
3791
|
if (inputState.error !== void 0) {
|
|
3517
3792
|
inputsWithErrors.push({
|
|
@@ -3727,7 +4002,7 @@ function inputValueAtPosition2(inputVar, position) {
|
|
|
3727
4002
|
case "at-maximum":
|
|
3728
4003
|
return inputVar.maxValue;
|
|
3729
4004
|
default:
|
|
3730
|
-
(0,
|
|
4005
|
+
(0, import_assert_never10.assertNever)(position);
|
|
3731
4006
|
}
|
|
3732
4007
|
}
|
|
3733
4008
|
var ResolvedScenarioGroups = class {
|
|
@@ -3786,7 +4061,7 @@ function resolveGraphsFromSpec(modelSpecL, modelSpecR, resolvedGraphGroups, grap
|
|
|
3786
4061
|
return [...graphIds];
|
|
3787
4062
|
}
|
|
3788
4063
|
default:
|
|
3789
|
-
(0,
|
|
4064
|
+
(0, import_assert_never10.assertNever)(graphsSpec.preset);
|
|
3790
4065
|
}
|
|
3791
4066
|
}
|
|
3792
4067
|
// eslint-disable-next-line no-fallthrough
|
|
@@ -3800,7 +4075,7 @@ function resolveGraphsFromSpec(modelSpecL, modelSpecR, resolvedGraphGroups, grap
|
|
|
3800
4075
|
return groupSpec.graphIds;
|
|
3801
4076
|
}
|
|
3802
4077
|
default:
|
|
3803
|
-
(0,
|
|
4078
|
+
(0, import_assert_never10.assertNever)(graphsSpec);
|
|
3804
4079
|
}
|
|
3805
4080
|
}
|
|
3806
4081
|
function resolveViewForScenarioId(resolvedScenarios, viewTitle, viewSubtitle, scenarioId, graphIds, graphOrder) {
|
|
@@ -3974,7 +4249,7 @@ function resolveViewGroupFromSpec(modelSpecL, modelSpecR, modelOutputs, resolved
|
|
|
3974
4249
|
views.push(resolveViewForScenario(void 0, void 0, scenario, graphIds, graphOrder));
|
|
3975
4250
|
break;
|
|
3976
4251
|
default:
|
|
3977
|
-
(0,
|
|
4252
|
+
(0, import_assert_never10.assertNever)(scenario);
|
|
3978
4253
|
}
|
|
3979
4254
|
}
|
|
3980
4255
|
} else {
|
|
@@ -3983,13 +4258,13 @@ function resolveViewGroupFromSpec(modelSpecL, modelSpecR, modelOutputs, resolved
|
|
|
3983
4258
|
break;
|
|
3984
4259
|
}
|
|
3985
4260
|
default:
|
|
3986
|
-
(0,
|
|
4261
|
+
(0, import_assert_never10.assertNever)(refSpec);
|
|
3987
4262
|
}
|
|
3988
4263
|
}
|
|
3989
4264
|
break;
|
|
3990
4265
|
}
|
|
3991
4266
|
default:
|
|
3992
|
-
(0,
|
|
4267
|
+
(0, import_assert_never10.assertNever)(viewGroupSpec);
|
|
3993
4268
|
}
|
|
3994
4269
|
return {
|
|
3995
4270
|
kind: "view-group",
|
|
@@ -4052,9 +4327,9 @@ var ComparisonDatasetsImpl = class {
|
|
|
4052
4327
|
}
|
|
4053
4328
|
const allOutputVarKeysSet = /* @__PURE__ */ new Set();
|
|
4054
4329
|
const modelOutputVarKeysSet = /* @__PURE__ */ new Set();
|
|
4055
|
-
function addOutputVars(outputVars,
|
|
4330
|
+
function addOutputVars(outputVars, handleRenames2) {
|
|
4056
4331
|
outputVars.forEach((outputVar, key) => {
|
|
4057
|
-
const remappedKey =
|
|
4332
|
+
const remappedKey = handleRenames2 ? leftKeyForRightKey(key) : key;
|
|
4058
4333
|
allOutputVarKeysSet.add(remappedKey);
|
|
4059
4334
|
if (outputVar.sourceName === void 0) {
|
|
4060
4335
|
modelOutputVarKeysSet.add(remappedKey);
|
|
@@ -4168,109 +4443,41 @@ var ComparisonScenariosImpl = class {
|
|
|
4168
4443
|
}
|
|
4169
4444
|
};
|
|
4170
4445
|
|
|
4171
|
-
// src/config/synchronized-model.ts
|
|
4172
|
-
function synchronizedBundleModel(sourceModel) {
|
|
4173
|
-
const promiseQueue = new PromiseQueue();
|
|
4174
|
-
return {
|
|
4175
|
-
modelSpec: sourceModel.modelSpec,
|
|
4176
|
-
getDatasetsForScenario: (scenarioSpec, datasetKeys) => {
|
|
4177
|
-
return promiseQueue.add(() => sourceModel.getDatasetsForScenario(scenarioSpec, datasetKeys));
|
|
4178
|
-
},
|
|
4179
|
-
getGraphDataForScenario: (scenarioSpec, graphId) => {
|
|
4180
|
-
return promiseQueue.add(() => sourceModel.getGraphDataForScenario(scenarioSpec, graphId));
|
|
4181
|
-
},
|
|
4182
|
-
getGraphLinksForScenario: sourceModel.getGraphLinksForScenario.bind(sourceModel)
|
|
4183
|
-
};
|
|
4184
|
-
}
|
|
4185
|
-
var PromiseQueue = class {
|
|
4186
|
-
constructor() {
|
|
4187
|
-
this.tasks = [];
|
|
4188
|
-
this.runningCount = 0;
|
|
4189
|
-
}
|
|
4190
|
-
add(f) {
|
|
4191
|
-
return new Promise((resolve, reject) => {
|
|
4192
|
-
const run = () => __async(this, null, function* () {
|
|
4193
|
-
this.runningCount++;
|
|
4194
|
-
const promise = f();
|
|
4195
|
-
try {
|
|
4196
|
-
const result = yield promise;
|
|
4197
|
-
resolve(result);
|
|
4198
|
-
} catch (e) {
|
|
4199
|
-
reject(e);
|
|
4200
|
-
} finally {
|
|
4201
|
-
this.runningCount--;
|
|
4202
|
-
this.runNext();
|
|
4203
|
-
}
|
|
4204
|
-
});
|
|
4205
|
-
if (this.runningCount < 1) {
|
|
4206
|
-
run();
|
|
4207
|
-
} else {
|
|
4208
|
-
this.tasks.push(run);
|
|
4209
|
-
}
|
|
4210
|
-
});
|
|
4211
|
-
}
|
|
4212
|
-
runNext() {
|
|
4213
|
-
if (this.tasks.length > 0) {
|
|
4214
|
-
const task = this.tasks.shift();
|
|
4215
|
-
if (task) {
|
|
4216
|
-
task();
|
|
4217
|
-
}
|
|
4218
|
-
}
|
|
4219
|
-
}
|
|
4220
|
-
};
|
|
4221
|
-
|
|
4222
4446
|
// src/config/config.ts
|
|
4223
4447
|
function createConfig(options) {
|
|
4224
4448
|
return __async(this, null, function* () {
|
|
4225
|
-
var _a;
|
|
4226
|
-
|
|
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);
|
|
4227
4466
|
let currentBundle;
|
|
4228
4467
|
let comparisonConfig;
|
|
4229
4468
|
if (options.comparison === void 0) {
|
|
4230
4469
|
currentBundle = origCurrentBundle;
|
|
4231
4470
|
} else {
|
|
4232
|
-
const baselineBundle = yield
|
|
4233
|
-
|
|
4234
|
-
const
|
|
4235
|
-
|
|
4236
|
-
invertedRenamedKeys.set(newKey, oldKey);
|
|
4237
|
-
});
|
|
4238
|
-
const rightKeyForLeftKey = (leftKey) => {
|
|
4239
|
-
return (renamedDatasetKeys == null ? void 0 : renamedDatasetKeys.get(leftKey)) || leftKey;
|
|
4240
|
-
};
|
|
4241
|
-
const leftKeyForRightKey = (rightKey) => {
|
|
4242
|
-
return invertedRenamedKeys.get(rightKey) || rightKey;
|
|
4243
|
-
};
|
|
4244
|
-
const origBundleModelR = origCurrentBundle.model;
|
|
4245
|
-
const adjBundleModelR = {
|
|
4246
|
-
modelSpec: origBundleModelR.modelSpec,
|
|
4247
|
-
getDatasetsForScenario: (scenarioSpec, datasetKeys) => __async(this, null, function* () {
|
|
4248
|
-
const rightKeys = datasetKeys.map(rightKeyForLeftKey);
|
|
4249
|
-
const result = yield origBundleModelR.getDatasetsForScenario(scenarioSpec, rightKeys);
|
|
4250
|
-
const mapWithRightKeys = result.datasetMap;
|
|
4251
|
-
const mapWithLeftKeys = /* @__PURE__ */ new Map();
|
|
4252
|
-
for (const [rightKey, dataset] of mapWithRightKeys.entries()) {
|
|
4253
|
-
const leftKey = leftKeyForRightKey(rightKey);
|
|
4254
|
-
mapWithLeftKeys.set(leftKey, dataset);
|
|
4255
|
-
}
|
|
4256
|
-
return {
|
|
4257
|
-
datasetMap: mapWithLeftKeys,
|
|
4258
|
-
modelRunTime: result.modelRunTime
|
|
4259
|
-
};
|
|
4260
|
-
}),
|
|
4261
|
-
getGraphDataForScenario: origBundleModelR.getGraphDataForScenario.bind(origBundleModelR),
|
|
4262
|
-
getGraphLinksForScenario: origBundleModelR.getGraphLinksForScenario.bind(origBundleModelR)
|
|
4263
|
-
};
|
|
4264
|
-
currentBundle = __spreadProps(__spreadValues({}, origCurrentBundle), {
|
|
4265
|
-
model: adjBundleModelR
|
|
4266
|
-
});
|
|
4267
|
-
const modelSpecL = baselineBundle.model.modelSpec;
|
|
4268
|
-
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;
|
|
4269
4475
|
const comparisonDefs = resolveComparisonSpecsFromSources(modelSpecL, modelSpecR, options.comparison.specs);
|
|
4270
4476
|
comparisonConfig = {
|
|
4271
4477
|
bundleL: baselineBundle,
|
|
4272
4478
|
bundleR: currentBundle,
|
|
4273
|
-
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],
|
|
4274
4481
|
scenarios: getComparisonScenarios(comparisonDefs.scenarios),
|
|
4275
4482
|
datasets: getComparisonDatasets(modelSpecL, modelSpecR, options.comparison.datasets),
|
|
4276
4483
|
viewGroups: comparisonDefs.viewGroups,
|
|
@@ -4281,26 +4488,75 @@ function createConfig(options) {
|
|
|
4281
4488
|
bundle: currentBundle,
|
|
4282
4489
|
tests: options.check.tests
|
|
4283
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);
|
|
4284
4499
|
return {
|
|
4285
4500
|
check: checkConfig,
|
|
4286
4501
|
comparison: comparisonConfig
|
|
4287
4502
|
};
|
|
4288
4503
|
});
|
|
4289
4504
|
}
|
|
4290
|
-
function
|
|
4505
|
+
function loadBundle(bundle, concurrentModels) {
|
|
4291
4506
|
return __async(this, null, function* () {
|
|
4292
|
-
const
|
|
4293
|
-
const
|
|
4507
|
+
const initCalls = Array.from({ length: concurrentModels }, () => bundle.bundle.initModel());
|
|
4508
|
+
const models = yield Promise.all(initCalls);
|
|
4294
4509
|
return {
|
|
4295
|
-
name:
|
|
4296
|
-
version:
|
|
4297
|
-
|
|
4510
|
+
name: bundle.name,
|
|
4511
|
+
version: bundle.bundle.version,
|
|
4512
|
+
modelSpec: bundle.bundle.modelSpec,
|
|
4513
|
+
models
|
|
4514
|
+
};
|
|
4515
|
+
});
|
|
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)
|
|
4298
4550
|
};
|
|
4551
|
+
}
|
|
4552
|
+
const wrappedModels = origCurrentBundle.models.map(wrapModel);
|
|
4553
|
+
return __spreadProps(__spreadValues({}, origCurrentBundle), {
|
|
4554
|
+
models: wrappedModels
|
|
4299
4555
|
});
|
|
4300
4556
|
}
|
|
4301
4557
|
|
|
4302
4558
|
// src/perf/perf-runner.ts
|
|
4303
|
-
var
|
|
4559
|
+
var import_assert_never11 = require("assert-never");
|
|
4304
4560
|
|
|
4305
4561
|
// src/perf/perf-stats.ts
|
|
4306
4562
|
var PerfStats = class {
|
|
@@ -4337,80 +4593,110 @@ var PerfStats = class {
|
|
|
4337
4593
|
};
|
|
4338
4594
|
|
|
4339
4595
|
// src/perf/perf-runner.ts
|
|
4340
|
-
|
|
4341
|
-
|
|
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
|
+
}
|
|
4342
4607
|
var PerfRunner = class {
|
|
4343
|
-
constructor(
|
|
4344
|
-
this.
|
|
4345
|
-
this.
|
|
4346
|
-
this.
|
|
4347
|
-
|
|
4348
|
-
this.
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
case "right": {
|
|
4358
|
-
const result = yield bundleModelR.getDatasetsForScenario(scenarioSpec, []);
|
|
4359
|
-
return {
|
|
4360
|
-
runTimeR: result.modelRunTime
|
|
4361
|
-
};
|
|
4362
|
-
}
|
|
4363
|
-
case "both": {
|
|
4364
|
-
const [resultL, resultR] = yield Promise.all([
|
|
4365
|
-
bundleModelL.getDatasetsForScenario(scenarioSpec, []),
|
|
4366
|
-
bundleModelR.getDatasetsForScenario(scenarioSpec, [])
|
|
4367
|
-
]);
|
|
4368
|
-
return {
|
|
4369
|
-
runTimeL: resultL.modelRunTime,
|
|
4370
|
-
runTimeR: resultR.modelRunTime
|
|
4371
|
-
};
|
|
4372
|
-
}
|
|
4373
|
-
default:
|
|
4374
|
-
(0, import_assert_never12.assertNever)(request.kind);
|
|
4375
|
-
}
|
|
4376
|
-
})
|
|
4377
|
-
});
|
|
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
|
+
}
|
|
4378
4622
|
}
|
|
4379
4623
|
start() {
|
|
4624
|
+
var _a, _b, _c, _d, _e, _f;
|
|
4380
4625
|
const statsL = new PerfStats();
|
|
4381
4626
|
const statsR = new PerfStats();
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
const taskQueue = this.taskQueue;
|
|
4391
|
-
function addTask(index, warmup, kind) {
|
|
4392
|
-
const key = `${warmup ? "warmup-" : ""}${kind}-${index}`;
|
|
4393
|
-
const request = {
|
|
4394
|
-
kind
|
|
4395
|
-
};
|
|
4396
|
-
taskQueue.addTask(key, request, (response) => {
|
|
4397
|
-
if (!warmup && response.runTimeL !== void 0) {
|
|
4398
|
-
statsL.addRun(response.runTimeL);
|
|
4399
|
-
}
|
|
4400
|
-
if (!warmup && response.runTimeR !== void 0) {
|
|
4401
|
-
statsR.addRun(response.runTimeR);
|
|
4402
|
-
}
|
|
4403
|
-
});
|
|
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;
|
|
4404
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
|
+
};
|
|
4405
4691
|
function addTasks(kind) {
|
|
4406
4692
|
for (let i = 0; i < warmupCount; i++) {
|
|
4407
|
-
addTask(
|
|
4693
|
+
addTask(true, kind);
|
|
4408
4694
|
}
|
|
4409
4695
|
for (let i = 0; i < runCount; i++) {
|
|
4410
|
-
addTask(
|
|
4696
|
+
addTask(false, kind);
|
|
4411
4697
|
}
|
|
4412
4698
|
}
|
|
4413
|
-
if (this.mode === "parallel") {
|
|
4699
|
+
if (((_f = this.options) == null ? void 0 : _f.mode) === "parallel") {
|
|
4414
4700
|
addTasks("both");
|
|
4415
4701
|
} else {
|
|
4416
4702
|
addTasks("left");
|
|
@@ -4419,6 +4705,303 @@ var PerfRunner = class {
|
|
|
4419
4705
|
}
|
|
4420
4706
|
};
|
|
4421
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
|
+
|
|
4422
5005
|
// src/data/data-planner.ts
|
|
4423
5006
|
var DataPlanner = class {
|
|
4424
5007
|
/**
|
|
@@ -4605,10 +5188,10 @@ function scenarioPairUid(scenarioSpecL, scenarioSpecR) {
|
|
|
4605
5188
|
}
|
|
4606
5189
|
|
|
4607
5190
|
// src/check/check-runner.ts
|
|
4608
|
-
function runChecks(checkConfig, checkSpec, dataPlanner, refDataPlanner,
|
|
4609
|
-
const modelSpec = checkConfig.bundle.
|
|
5191
|
+
function runChecks(checkConfig, checkSpec, dataPlanner, refDataPlanner, skipChecks) {
|
|
5192
|
+
const modelSpec = checkConfig.bundle.modelSpec;
|
|
4610
5193
|
const checkPlanner = new CheckPlanner(modelSpec);
|
|
4611
|
-
checkPlanner.addAllChecks(checkSpec,
|
|
5194
|
+
checkPlanner.addAllChecks(checkSpec, skipChecks);
|
|
4612
5195
|
const checkPlan = checkPlanner.buildPlan();
|
|
4613
5196
|
const refDatasets = /* @__PURE__ */ new Map();
|
|
4614
5197
|
for (const [dataRefKey, dataRef] of checkPlan.dataRefs.entries()) {
|
|
@@ -4621,11 +5204,15 @@ function runChecks(checkConfig, checkSpec, dataPlanner, refDataPlanner, simplify
|
|
|
4621
5204
|
}
|
|
4622
5205
|
const checkResults = /* @__PURE__ */ new Map();
|
|
4623
5206
|
for (const [checkKey, checkTask] of checkPlan.tasks.entries()) {
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
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
|
+
}
|
|
4629
5216
|
}
|
|
4630
5217
|
return () => {
|
|
4631
5218
|
return buildCheckReport(checkPlan, checkResults);
|
|
@@ -4690,21 +5277,73 @@ function runCheck(checkTask, dataset, refDatasets) {
|
|
|
4690
5277
|
}
|
|
4691
5278
|
|
|
4692
5279
|
// src/comparison/run/comparison-runner.ts
|
|
4693
|
-
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
|
+
}
|
|
4694
5298
|
const testReports = [];
|
|
4695
|
-
|
|
5299
|
+
const baselineDiffReports = /* @__PURE__ */ new Map();
|
|
5300
|
+
function runComparisonsForScenario(scenario, isBaseline) {
|
|
4696
5301
|
const datasetKeys = comparisonConfig.datasets.getDatasetKeysForScenario(scenario);
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
5302
|
+
const shouldSkip = skipScenariosSet.has(skipScenarioKey(scenario.title, scenario.subtitle));
|
|
5303
|
+
if (shouldSkip) {
|
|
5304
|
+
for (const datasetKey of datasetKeys) {
|
|
4700
5305
|
testReports.push({
|
|
4701
5306
|
scenarioKey: scenario.key,
|
|
4702
5307
|
datasetKey,
|
|
4703
|
-
diffReport
|
|
5308
|
+
diffReport: void 0
|
|
4704
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
|
+
}
|
|
4705
5332
|
});
|
|
4706
5333
|
}
|
|
4707
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
|
+
}
|
|
4708
5347
|
return () => {
|
|
4709
5348
|
return testReports;
|
|
4710
5349
|
};
|
|
@@ -4712,74 +5351,52 @@ function runComparisons(comparisonConfig, dataPlanner) {
|
|
|
4712
5351
|
|
|
4713
5352
|
// src/suite/suite-runner.ts
|
|
4714
5353
|
var SuiteRunner = class {
|
|
4715
|
-
constructor(config, callbacks) {
|
|
5354
|
+
constructor(config, taskQueue, callbacks) {
|
|
4716
5355
|
this.config = config;
|
|
5356
|
+
this.taskQueue = taskQueue;
|
|
4717
5357
|
this.callbacks = callbacks;
|
|
4718
5358
|
this.perfStatsL = new PerfStats();
|
|
4719
5359
|
this.perfStatsR = new PerfStats();
|
|
5360
|
+
this.pendingTaskKeys = /* @__PURE__ */ new Set();
|
|
4720
5361
|
this.stopped = false;
|
|
4721
|
-
this.taskQueue = new TaskQueue({
|
|
4722
|
-
process: (request) => {
|
|
4723
|
-
return this.processRequest(request);
|
|
4724
|
-
}
|
|
4725
|
-
});
|
|
4726
5362
|
}
|
|
4727
5363
|
cancel() {
|
|
4728
5364
|
if (!this.stopped) {
|
|
5365
|
+
for (const taskKey of this.pendingTaskKeys) {
|
|
5366
|
+
this.taskQueue.cancelTask(taskKey);
|
|
5367
|
+
}
|
|
4729
5368
|
this.stopped = true;
|
|
4730
|
-
this.taskQueue.shutdown();
|
|
4731
5369
|
}
|
|
4732
5370
|
}
|
|
4733
5371
|
start(options) {
|
|
4734
5372
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
4735
5373
|
(_b = (_a = this.callbacks).onProgress) == null ? void 0 : _b.call(_a, 0);
|
|
4736
|
-
const
|
|
4737
|
-
const dataPlanner = new DataPlanner(
|
|
4738
|
-
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);
|
|
4739
5377
|
const checkSpecResult = parseTestYaml(this.config.check.tests);
|
|
4740
5378
|
if (checkSpecResult.isErr()) {
|
|
4741
5379
|
(_d = (_c = this.callbacks).onError) == null ? void 0 : _d.call(_c, checkSpecResult.error);
|
|
4742
5380
|
return;
|
|
4743
5381
|
}
|
|
4744
5382
|
const checkSpec = checkSpecResult.value;
|
|
4745
|
-
const
|
|
4746
|
-
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);
|
|
4747
5385
|
let buildComparisonTestReports;
|
|
4748
5386
|
if (this.config.comparison) {
|
|
4749
|
-
|
|
5387
|
+
const skipScenarios = (options == null ? void 0 : options.skipComparisonScenarios) || [];
|
|
5388
|
+
buildComparisonTestReports = runComparisons(this.config.comparison, dataPlanner, skipScenarios);
|
|
4750
5389
|
}
|
|
4751
|
-
this.taskQueue.onIdle = (error) => {
|
|
4752
|
-
var _a2, _b2, _c2, _d2;
|
|
4753
|
-
if (this.stopped) {
|
|
4754
|
-
return;
|
|
4755
|
-
}
|
|
4756
|
-
if (error) {
|
|
4757
|
-
(_b2 = (_a2 = this.callbacks).onError) == null ? void 0 : _b2.call(_a2, error);
|
|
4758
|
-
} else {
|
|
4759
|
-
const checkReport = buildCheckReport2();
|
|
4760
|
-
let comparisonReport;
|
|
4761
|
-
if (this.config.comparison) {
|
|
4762
|
-
comparisonReport = {
|
|
4763
|
-
testReports: buildComparisonTestReports(),
|
|
4764
|
-
perfReportL: this.perfStatsL.toReport(),
|
|
4765
|
-
perfReportR: this.perfStatsR.toReport()
|
|
4766
|
-
};
|
|
4767
|
-
}
|
|
4768
|
-
(_d2 = (_c2 = this.callbacks).onComplete) == null ? void 0 : _d2.call(_c2, {
|
|
4769
|
-
checkReport,
|
|
4770
|
-
comparisonReport
|
|
4771
|
-
});
|
|
4772
|
-
}
|
|
4773
|
-
};
|
|
4774
5390
|
const refDataPlan = refDataPlanner.buildPlan();
|
|
4775
5391
|
const dataPlan = dataPlanner.buildPlan();
|
|
4776
5392
|
const dataRequests = [...refDataPlan.requests, ...dataPlan.requests];
|
|
4777
5393
|
const taskCount = dataRequests.length;
|
|
4778
5394
|
if (taskCount === 0) {
|
|
5395
|
+
const checkReport = buildCheckReport2();
|
|
4779
5396
|
let comparisonReport;
|
|
4780
5397
|
if (this.config.comparison) {
|
|
4781
5398
|
comparisonReport = {
|
|
4782
|
-
testReports:
|
|
5399
|
+
testReports: buildComparisonTestReports(),
|
|
4783
5400
|
perfReportL: this.perfStatsL.toReport(),
|
|
4784
5401
|
perfReportR: this.perfStatsR.toReport()
|
|
4785
5402
|
};
|
|
@@ -4787,26 +5404,54 @@ var SuiteRunner = class {
|
|
|
4787
5404
|
this.cancel();
|
|
4788
5405
|
(_f = (_e = this.callbacks).onProgress) == null ? void 0 : _f.call(_e, 1);
|
|
4789
5406
|
(_h = (_g = this.callbacks).onComplete) == null ? void 0 : _h.call(_g, {
|
|
4790
|
-
checkReport
|
|
4791
|
-
groups: []
|
|
4792
|
-
},
|
|
5407
|
+
checkReport,
|
|
4793
5408
|
comparisonReport
|
|
4794
5409
|
});
|
|
4795
5410
|
return;
|
|
4796
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
|
+
};
|
|
4797
5432
|
let tasksCompleted = 0;
|
|
4798
5433
|
let dataTaskId = 1;
|
|
4799
5434
|
for (const dataRequest of dataRequests) {
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
(
|
|
4804
|
-
|
|
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);
|
|
4805
5451
|
}
|
|
4806
5452
|
}
|
|
4807
|
-
processRequest(request) {
|
|
5453
|
+
processRequest(request, bundleModels) {
|
|
4808
5454
|
return __async(this, null, function* () {
|
|
4809
|
-
var _a, _b;
|
|
4810
5455
|
const datasetKeySet = /* @__PURE__ */ new Set();
|
|
4811
5456
|
for (const dataTask of request.dataTasks) {
|
|
4812
5457
|
datasetKeySet.add(dataTask.datasetKey);
|
|
@@ -4821,8 +5466,8 @@ var SuiteRunner = class {
|
|
|
4821
5466
|
}
|
|
4822
5467
|
});
|
|
4823
5468
|
}
|
|
4824
|
-
const bundleModelL =
|
|
4825
|
-
const bundleModelR =
|
|
5469
|
+
const bundleModelL = bundleModels.L;
|
|
5470
|
+
const bundleModelR = bundleModels.R;
|
|
4826
5471
|
const [datasetsResultL, datasetsResultR] = yield Promise.all([
|
|
4827
5472
|
getDatasets(bundleModelL, request.scenarioSpecL),
|
|
4828
5473
|
getDatasets(bundleModelR, request.scenarioSpecR)
|
|
@@ -4846,22 +5491,29 @@ var SuiteRunner = class {
|
|
|
4846
5491
|
});
|
|
4847
5492
|
}
|
|
4848
5493
|
};
|
|
4849
|
-
function
|
|
4850
|
-
const suiteRunner = new SuiteRunner(config, callbacks);
|
|
5494
|
+
function runSuiteWithTaskQueue(config, taskQueue, callbacks, options) {
|
|
5495
|
+
const suiteRunner = new SuiteRunner(config, taskQueue, callbacks);
|
|
4851
5496
|
suiteRunner.start(options);
|
|
4852
5497
|
return () => {
|
|
4853
5498
|
suiteRunner.cancel();
|
|
4854
5499
|
};
|
|
4855
5500
|
}
|
|
5501
|
+
function runSuite(config, callbacks, options) {
|
|
5502
|
+
const taskQueue = TaskQueue.getInstance();
|
|
5503
|
+
return runSuiteWithTaskQueue(config, taskQueue, callbacks, options);
|
|
5504
|
+
}
|
|
4856
5505
|
|
|
4857
5506
|
// src/suite/suite-reporting.ts
|
|
4858
|
-
function suiteSummaryFromReport(suiteReport) {
|
|
5507
|
+
function suiteSummaryFromReport(suiteReport, elapsedMillis) {
|
|
4859
5508
|
const checkSummary = checkSummaryFromReport(suiteReport.checkReport);
|
|
4860
5509
|
let comparisonSummary;
|
|
4861
5510
|
if (suiteReport.comparisonReport) {
|
|
4862
5511
|
comparisonSummary = comparisonSummaryFromReport(suiteReport.comparisonReport);
|
|
4863
5512
|
}
|
|
5513
|
+
const date = (/* @__PURE__ */ new Date()).toISOString();
|
|
4864
5514
|
return {
|
|
5515
|
+
date,
|
|
5516
|
+
elapsed: elapsedMillis,
|
|
4865
5517
|
checkSummary,
|
|
4866
5518
|
comparisonSummary
|
|
4867
5519
|
};
|
|
@@ -4870,20 +5522,27 @@ function suiteSummaryFromReport(suiteReport) {
|
|
|
4870
5522
|
0 && (module.exports = {
|
|
4871
5523
|
CheckDataCoordinator,
|
|
4872
5524
|
ComparisonDataCoordinator,
|
|
4873
|
-
PerfRunner,
|
|
4874
5525
|
PerfStats,
|
|
4875
5526
|
categorizeComparisonTestSummaries,
|
|
4876
5527
|
checkReportFromSummary,
|
|
4877
5528
|
checkSummaryFromReport,
|
|
4878
5529
|
comparisonSummaryFromReport,
|
|
5530
|
+
createCheckDataCoordinator,
|
|
5531
|
+
createCheckDataCoordinatorForTests,
|
|
5532
|
+
createComparisonDataCoordinator,
|
|
4879
5533
|
createConfig,
|
|
4880
5534
|
datasetMessage,
|
|
5535
|
+
decodeImplVars,
|
|
4881
5536
|
diffDatasets,
|
|
4882
5537
|
diffGraphs,
|
|
5538
|
+
encodeImplVars,
|
|
4883
5539
|
getScoresForTestSummaries,
|
|
4884
5540
|
predicateMessage,
|
|
5541
|
+
runPerf,
|
|
4885
5542
|
runSuite,
|
|
5543
|
+
runTrace,
|
|
4886
5544
|
scenarioMessage,
|
|
4887
|
-
suiteSummaryFromReport
|
|
5545
|
+
suiteSummaryFromReport,
|
|
5546
|
+
testSummaryFromReport
|
|
4888
5547
|
});
|
|
4889
5548
|
//# sourceMappingURL=index.cjs.map
|