@sdeverywhere/check-core 0.1.5 → 0.1.7
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 +1104 -442
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +536 -108
- package/dist/index.d.ts +536 -108
- package/dist/index.js +1092 -437
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -64,55 +64,207 @@ var __async = (__this, __arguments, generator) => {
|
|
|
64
64
|
};
|
|
65
65
|
|
|
66
66
|
// src/index.ts
|
|
67
|
-
var
|
|
68
|
-
__export(
|
|
67
|
+
var index_exports = {};
|
|
68
|
+
__export(index_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
|
-
module.exports = __toCommonJS(
|
|
94
|
+
module.exports = __toCommonJS(index_exports);
|
|
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
|
+
}
|
|
88
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(null, 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(null, 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,116 @@ 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(null, 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
|
+
var _a;
|
|
2141
|
+
if (scenarioSpec) {
|
|
2142
|
+
return (_a = bundleModel.getGraphDataForScenario) == null ? void 0 : _a.call(bundleModel, scenarioSpec, graphId);
|
|
2143
|
+
} else {
|
|
2144
|
+
return void 0;
|
|
2145
|
+
}
|
|
2146
|
+
});
|
|
2147
|
+
}
|
|
2148
|
+
const task = {
|
|
2149
|
+
key: requestKey,
|
|
2150
|
+
kind: "comparison-data-coordinator",
|
|
2151
|
+
process: (bundleModels) => __async(null, null, function* () {
|
|
2152
|
+
const modelL = sourceL === "left" ? bundleModels.L : bundleModels.R;
|
|
2153
|
+
const modelR = sourceR === "left" ? bundleModels.L : bundleModels.R;
|
|
2154
|
+
let graphDataL;
|
|
2155
|
+
let graphDataR;
|
|
2156
|
+
if (modelL === modelR) {
|
|
2157
|
+
graphDataL = yield fetchGraphData(modelL, scenarioSpecL);
|
|
2158
|
+
graphDataR = yield fetchGraphData(modelR, scenarioSpecR);
|
|
2159
|
+
} else {
|
|
2160
|
+
const results = yield Promise.all([
|
|
2161
|
+
fetchGraphData(modelL, scenarioSpecL),
|
|
2162
|
+
fetchGraphData(modelR, scenarioSpecR)
|
|
2163
|
+
]);
|
|
2164
|
+
graphDataL = results[0];
|
|
2165
|
+
graphDataR = results[1];
|
|
2166
|
+
}
|
|
2167
|
+
onResponse(graphDataL, graphDataR);
|
|
2168
|
+
})
|
|
1960
2169
|
};
|
|
1961
|
-
this.taskQueue.addTask(
|
|
1962
|
-
if (response.kind === "graph-data") {
|
|
1963
|
-
onResponse(response.graphDataL, response.graphDataR);
|
|
1964
|
-
}
|
|
1965
|
-
});
|
|
2170
|
+
this.taskQueue.addTask(task);
|
|
1966
2171
|
}
|
|
1967
2172
|
cancelRequest(key) {
|
|
1968
2173
|
this.taskQueue.cancelTask(key);
|
|
1969
2174
|
}
|
|
1970
2175
|
};
|
|
2176
|
+
function createComparisonDataCoordinator() {
|
|
2177
|
+
return new ComparisonDataCoordinator(TaskQueue.getInstance());
|
|
2178
|
+
}
|
|
1971
2179
|
|
|
1972
2180
|
// src/comparison/diff-datasets/diff-datasets.ts
|
|
1973
2181
|
function diffDatasets(datasetL, datasetR) {
|
|
@@ -2117,14 +2325,14 @@ function diffGraphs(graphL, graphR, scenarioKey, testSummaries) {
|
|
|
2117
2325
|
|
|
2118
2326
|
// src/comparison/report/comparison-reporting.ts
|
|
2119
2327
|
function comparisonSummaryFromReport(comparisonReport) {
|
|
2328
|
+
var _a, _b;
|
|
2120
2329
|
const terseSummaries = [];
|
|
2121
2330
|
for (const r of comparisonReport.testReports) {
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
});
|
|
2331
|
+
const baselineMaxDiff = (_a = r.baselineDiffReport) == null ? void 0 : _a.maxDiff;
|
|
2332
|
+
const baselineAvgDiff = (_b = r.baselineDiffReport) == null ? void 0 : _b.avgDiff;
|
|
2333
|
+
const summary = testSummaryFromReport(r, baselineMaxDiff, baselineAvgDiff);
|
|
2334
|
+
if (summary) {
|
|
2335
|
+
terseSummaries.push(summary);
|
|
2128
2336
|
}
|
|
2129
2337
|
}
|
|
2130
2338
|
return {
|
|
@@ -2133,6 +2341,43 @@ function comparisonSummaryFromReport(comparisonReport) {
|
|
|
2133
2341
|
perfReportR: comparisonReport.perfReportR
|
|
2134
2342
|
};
|
|
2135
2343
|
}
|
|
2344
|
+
function testSummaryFromReport(r, baselineMaxDiff, baselineAvgDiff) {
|
|
2345
|
+
var _a;
|
|
2346
|
+
function baselineRelativeDiff(diffValue, baselineDiffValue) {
|
|
2347
|
+
if (baselineDiffValue !== void 0) {
|
|
2348
|
+
const epsilon = 1e-6;
|
|
2349
|
+
if (baselineDiffValue === 0) {
|
|
2350
|
+
baselineDiffValue = epsilon;
|
|
2351
|
+
}
|
|
2352
|
+
return diffValue / baselineDiffValue;
|
|
2353
|
+
} else {
|
|
2354
|
+
if (diffValue === 0) {
|
|
2355
|
+
return 0;
|
|
2356
|
+
} else {
|
|
2357
|
+
return 1;
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2361
|
+
if (r.diffReport === void 0) {
|
|
2362
|
+
return {
|
|
2363
|
+
s: r.scenarioKey,
|
|
2364
|
+
d: r.datasetKey
|
|
2365
|
+
};
|
|
2366
|
+
} else if (((_a = r.diffReport) == null ? void 0 : _a.validity) === "both" && r.diffReport.maxDiff > 0) {
|
|
2367
|
+
const maxDiffRelativeToBaseline = baselineRelativeDiff(r.diffReport.maxDiff, baselineMaxDiff);
|
|
2368
|
+
const avgDiffRelativeToBaseline = baselineRelativeDiff(r.diffReport.avgDiff, baselineAvgDiff);
|
|
2369
|
+
return {
|
|
2370
|
+
s: r.scenarioKey,
|
|
2371
|
+
d: r.datasetKey,
|
|
2372
|
+
md: r.diffReport.maxDiff,
|
|
2373
|
+
ad: r.diffReport.avgDiff,
|
|
2374
|
+
mdb: maxDiffRelativeToBaseline,
|
|
2375
|
+
adb: avgDiffRelativeToBaseline
|
|
2376
|
+
};
|
|
2377
|
+
} else {
|
|
2378
|
+
return void 0;
|
|
2379
|
+
}
|
|
2380
|
+
}
|
|
2136
2381
|
function restoreFromTerseSummaries(comparisonConfig, terseSummaries) {
|
|
2137
2382
|
const existingSummaries = /* @__PURE__ */ new Map();
|
|
2138
2383
|
for (const summary of terseSummaries) {
|
|
@@ -2145,24 +2390,33 @@ function restoreFromTerseSummaries(comparisonConfig, terseSummaries) {
|
|
|
2145
2390
|
for (const datasetKey of datasetKeys) {
|
|
2146
2391
|
const key = `${scenario.key}::${datasetKey}`;
|
|
2147
2392
|
const existingSummary = existingSummaries.get(key);
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2393
|
+
if (existingSummary) {
|
|
2394
|
+
allTestSummaries.push(existingSummary);
|
|
2395
|
+
} else {
|
|
2396
|
+
allTestSummaries.push({
|
|
2397
|
+
s: scenario.key,
|
|
2398
|
+
d: datasetKey,
|
|
2399
|
+
md: 0,
|
|
2400
|
+
ad: 0,
|
|
2401
|
+
mdb: 0,
|
|
2402
|
+
adb: 0
|
|
2403
|
+
});
|
|
2404
|
+
}
|
|
2154
2405
|
}
|
|
2155
2406
|
}
|
|
2156
2407
|
return allTestSummaries;
|
|
2157
2408
|
}
|
|
2158
2409
|
|
|
2159
2410
|
// src/comparison/report/buckets.ts
|
|
2160
|
-
function getBucketIndex(
|
|
2161
|
-
if (
|
|
2411
|
+
function getBucketIndex(diff, thresholds) {
|
|
2412
|
+
if (diff === void 0) {
|
|
2413
|
+
return thresholds.length + 2;
|
|
2414
|
+
}
|
|
2415
|
+
if (diff === 0) {
|
|
2162
2416
|
return 0;
|
|
2163
2417
|
}
|
|
2164
2418
|
for (let i = 0; i < thresholds.length; i++) {
|
|
2165
|
-
if (
|
|
2419
|
+
if (diff < thresholds[i]) {
|
|
2166
2420
|
return i + 1;
|
|
2167
2421
|
}
|
|
2168
2422
|
}
|
|
@@ -2170,14 +2424,32 @@ function getBucketIndex(diffPct, thresholds) {
|
|
|
2170
2424
|
}
|
|
2171
2425
|
|
|
2172
2426
|
// src/comparison/report/comparison-group-scores.ts
|
|
2173
|
-
function getScoresForTestSummaries(testSummaries, thresholds) {
|
|
2174
|
-
const diffCountByBucket = Array(thresholds.length +
|
|
2175
|
-
const
|
|
2427
|
+
function getScoresForTestSummaries(testSummaries, thresholds, sortMode) {
|
|
2428
|
+
const diffCountByBucket = Array(thresholds.length + 3).fill(0);
|
|
2429
|
+
const totalDiffByBucket = Array(thresholds.length + 3).fill(0);
|
|
2176
2430
|
let totalDiffCount = 0;
|
|
2431
|
+
let valueKey;
|
|
2432
|
+
switch (sortMode) {
|
|
2433
|
+
case "max-diff":
|
|
2434
|
+
valueKey = "md";
|
|
2435
|
+
break;
|
|
2436
|
+
case "avg-diff":
|
|
2437
|
+
valueKey = "ad";
|
|
2438
|
+
break;
|
|
2439
|
+
case "max-diff-relative":
|
|
2440
|
+
valueKey = "mdb";
|
|
2441
|
+
break;
|
|
2442
|
+
case "avg-diff-relative":
|
|
2443
|
+
valueKey = "adb";
|
|
2444
|
+
break;
|
|
2445
|
+
}
|
|
2177
2446
|
for (const testSummary of testSummaries) {
|
|
2178
|
-
const
|
|
2447
|
+
const value = testSummary[valueKey];
|
|
2448
|
+
const bucketIndex = getBucketIndex(value, thresholds);
|
|
2179
2449
|
diffCountByBucket[bucketIndex]++;
|
|
2180
|
-
|
|
2450
|
+
if (value !== void 0) {
|
|
2451
|
+
totalDiffByBucket[bucketIndex] += value;
|
|
2452
|
+
}
|
|
2181
2453
|
totalDiffCount++;
|
|
2182
2454
|
}
|
|
2183
2455
|
let diffPercentByBucket;
|
|
@@ -2188,20 +2460,20 @@ function getScoresForTestSummaries(testSummaries, thresholds) {
|
|
|
2188
2460
|
}
|
|
2189
2461
|
return {
|
|
2190
2462
|
totalDiffCount,
|
|
2191
|
-
|
|
2463
|
+
totalDiffByBucket,
|
|
2192
2464
|
diffCountByBucket,
|
|
2193
2465
|
diffPercentByBucket
|
|
2194
2466
|
};
|
|
2195
2467
|
}
|
|
2196
2468
|
|
|
2197
2469
|
// src/comparison/report/comparison-grouping.ts
|
|
2198
|
-
var
|
|
2199
|
-
function categorizeComparisonTestSummaries(comparisonConfig, terseSummaries) {
|
|
2470
|
+
var import_assert_never7 = require("assert-never");
|
|
2471
|
+
function categorizeComparisonTestSummaries(comparisonConfig, terseSummaries, sortMode) {
|
|
2200
2472
|
const allTestSummaries = restoreFromTerseSummaries(comparisonConfig, terseSummaries);
|
|
2201
2473
|
const groupsByScenario = groupComparisonTestSummaries(allTestSummaries, "by-scenario");
|
|
2202
|
-
const byScenario = categorizeComparisonGroups(comparisonConfig, [...groupsByScenario.values()]);
|
|
2474
|
+
const byScenario = categorizeComparisonGroups(comparisonConfig, [...groupsByScenario.values()], sortMode);
|
|
2203
2475
|
const groupsByDataset = groupComparisonTestSummaries(allTestSummaries, "by-dataset");
|
|
2204
|
-
const byDataset = categorizeComparisonGroups(comparisonConfig, [...groupsByDataset.values()]);
|
|
2476
|
+
const byDataset = categorizeComparisonGroups(comparisonConfig, [...groupsByDataset.values()], sortMode);
|
|
2205
2477
|
return {
|
|
2206
2478
|
allTestSummaries,
|
|
2207
2479
|
byScenario,
|
|
@@ -2220,7 +2492,7 @@ function groupComparisonTestSummaries(testSummaries, groupKind) {
|
|
|
2220
2492
|
groupKey = testSummary.s;
|
|
2221
2493
|
break;
|
|
2222
2494
|
default:
|
|
2223
|
-
(0,
|
|
2495
|
+
(0, import_assert_never7.assertNever)(groupKind);
|
|
2224
2496
|
}
|
|
2225
2497
|
const group = groups.get(groupKey);
|
|
2226
2498
|
if (group) {
|
|
@@ -2235,7 +2507,7 @@ function groupComparisonTestSummaries(testSummaries, groupKind) {
|
|
|
2235
2507
|
}
|
|
2236
2508
|
return groups;
|
|
2237
2509
|
}
|
|
2238
|
-
function categorizeComparisonGroups(comparisonConfig, allGroups) {
|
|
2510
|
+
function categorizeComparisonGroups(comparisonConfig, allGroups, sortMode) {
|
|
2239
2511
|
const allGroupSummaries = /* @__PURE__ */ new Map();
|
|
2240
2512
|
const withErrors = [];
|
|
2241
2513
|
const onlyInLeft = [];
|
|
@@ -2245,7 +2517,9 @@ function categorizeComparisonGroups(comparisonConfig, allGroups) {
|
|
|
2245
2517
|
function addSummaryForGroup(group, root, validInL, validInR) {
|
|
2246
2518
|
let scores;
|
|
2247
2519
|
if (validInL && validInR) {
|
|
2248
|
-
|
|
2520
|
+
const isRelativeMode = sortMode === "max-diff-relative" || sortMode === "avg-diff-relative";
|
|
2521
|
+
const thresholds = isRelativeMode ? comparisonConfig.ratioThresholds : comparisonConfig.thresholds;
|
|
2522
|
+
scores = getScoresForTestSummaries(group.testSummaries, thresholds, sortMode);
|
|
2249
2523
|
}
|
|
2250
2524
|
const groupSummary = {
|
|
2251
2525
|
root,
|
|
@@ -2254,7 +2528,9 @@ function categorizeComparisonGroups(comparisonConfig, allGroups) {
|
|
|
2254
2528
|
};
|
|
2255
2529
|
allGroupSummaries.set(group.key, groupSummary);
|
|
2256
2530
|
if (validInL && validInR) {
|
|
2257
|
-
|
|
2531
|
+
const noDiffCount = scores.diffCountByBucket[0];
|
|
2532
|
+
const skippedCount = scores.diffCountByBucket[5];
|
|
2533
|
+
if (scores.totalDiffCount !== noDiffCount + skippedCount) {
|
|
2258
2534
|
withDiffs.push(groupSummary);
|
|
2259
2535
|
} else {
|
|
2260
2536
|
withoutDiffs.push(groupSummary);
|
|
@@ -2284,7 +2560,7 @@ function categorizeComparisonGroups(comparisonConfig, allGroups) {
|
|
|
2284
2560
|
break;
|
|
2285
2561
|
}
|
|
2286
2562
|
default:
|
|
2287
|
-
(0,
|
|
2563
|
+
(0, import_assert_never7.assertNever)(group.kind);
|
|
2288
2564
|
}
|
|
2289
2565
|
}
|
|
2290
2566
|
if (withDiffs.length > 1) {
|
|
@@ -2346,13 +2622,13 @@ function sortScenarioGroupSummaries(summaries) {
|
|
|
2346
2622
|
});
|
|
2347
2623
|
}
|
|
2348
2624
|
function compareScores(a, b) {
|
|
2349
|
-
if (a.
|
|
2625
|
+
if (a.totalDiffByBucket.length !== b.totalDiffByBucket.length) {
|
|
2350
2626
|
return 0;
|
|
2351
2627
|
}
|
|
2352
|
-
const len = a.
|
|
2628
|
+
const len = a.totalDiffByBucket.length;
|
|
2353
2629
|
for (let i = len - 1; i >= 0; i--) {
|
|
2354
|
-
const aTotal = a.
|
|
2355
|
-
const bTotal = b.
|
|
2630
|
+
const aTotal = a.totalDiffByBucket[i];
|
|
2631
|
+
const bTotal = b.totalDiffByBucket[i];
|
|
2356
2632
|
if (aTotal > bTotal) {
|
|
2357
2633
|
return 1;
|
|
2358
2634
|
} else if (aTotal < bTotal) {
|
|
@@ -2364,7 +2640,7 @@ function compareScores(a, b) {
|
|
|
2364
2640
|
|
|
2365
2641
|
// src/comparison/config/parse/comparison-parser.ts
|
|
2366
2642
|
var import_ajv2 = __toESM(require("ajv"), 1);
|
|
2367
|
-
var
|
|
2643
|
+
var import_assert_never8 = __toESM(require("assert-never"), 1);
|
|
2368
2644
|
var import_neverthrow2 = require("neverthrow");
|
|
2369
2645
|
var import_yaml2 = __toESM(require("yaml"), 1);
|
|
2370
2646
|
|
|
@@ -2900,7 +3176,7 @@ function parseComparisonSpecs(specSource) {
|
|
|
2900
3176
|
parsed = import_yaml2.default.parse(specSource.content);
|
|
2901
3177
|
break;
|
|
2902
3178
|
default:
|
|
2903
|
-
(0,
|
|
3179
|
+
(0, import_assert_never8.default)(specSource.kind);
|
|
2904
3180
|
}
|
|
2905
3181
|
if (validate(parsed)) {
|
|
2906
3182
|
for (const specItem of parsed) {
|
|
@@ -3127,7 +3403,7 @@ function viewGroupSpecFromParsed(parsedViewGroup) {
|
|
|
3127
3403
|
}
|
|
3128
3404
|
|
|
3129
3405
|
// src/comparison/config/resolve/comparison-resolver.ts
|
|
3130
|
-
var
|
|
3406
|
+
var import_assert_never10 = require("assert-never");
|
|
3131
3407
|
|
|
3132
3408
|
// src/bundle/model-inputs.ts
|
|
3133
3409
|
var ModelInputs = class {
|
|
@@ -3190,7 +3466,7 @@ var ModelInputs = class {
|
|
|
3190
3466
|
};
|
|
3191
3467
|
|
|
3192
3468
|
// src/comparison/config/resolve/comparison-scenario-specs.ts
|
|
3193
|
-
var
|
|
3469
|
+
var import_assert_never9 = require("assert-never");
|
|
3194
3470
|
function scenarioSpecsFromSettings(settings) {
|
|
3195
3471
|
switch (settings.kind) {
|
|
3196
3472
|
case "all-inputs-settings": {
|
|
@@ -3203,7 +3479,7 @@ function scenarioSpecsFromSettings(settings) {
|
|
|
3203
3479
|
return [specL, specR];
|
|
3204
3480
|
}
|
|
3205
3481
|
default:
|
|
3206
|
-
(0,
|
|
3482
|
+
(0, import_assert_never9.assertNever)(settings);
|
|
3207
3483
|
}
|
|
3208
3484
|
}
|
|
3209
3485
|
function scenarioSpecFromInputs(inputs, side) {
|
|
@@ -3422,7 +3698,7 @@ function resolveScenariosFromSpec(modelInputsL, modelInputsR, scenarioSpec, genK
|
|
|
3422
3698
|
];
|
|
3423
3699
|
}
|
|
3424
3700
|
default:
|
|
3425
|
-
(0,
|
|
3701
|
+
(0, import_assert_never10.assertNever)(scenarioSpec);
|
|
3426
3702
|
}
|
|
3427
3703
|
}
|
|
3428
3704
|
function resolveScenarioMatrix(modelInputsL, modelInputsR, genKey) {
|
|
@@ -3478,7 +3754,7 @@ function resolveScenarioForInputSpecs(modelInputsL, modelInputsR, key, id, title
|
|
|
3478
3754
|
case "input-at-value":
|
|
3479
3755
|
return resolveInputForName(modelInputsL, modelInputsR, inputSpec.inputName, inputSpec.value);
|
|
3480
3756
|
default:
|
|
3481
|
-
(0,
|
|
3757
|
+
(0, import_assert_never10.assertNever)(inputSpec);
|
|
3482
3758
|
}
|
|
3483
3759
|
});
|
|
3484
3760
|
const settings = {
|
|
@@ -3511,7 +3787,7 @@ function resolveScenarioForDistinctInputSpecs(modelInputsL, modelInputsR, key, i
|
|
|
3511
3787
|
inputState = resolveInputForNameInModel(modelInputs, inputSpec.inputName, inputSpec.value);
|
|
3512
3788
|
break;
|
|
3513
3789
|
default:
|
|
3514
|
-
(0,
|
|
3790
|
+
(0, import_assert_never10.assertNever)(inputSpec);
|
|
3515
3791
|
}
|
|
3516
3792
|
if (inputState.error !== void 0) {
|
|
3517
3793
|
inputsWithErrors.push({
|
|
@@ -3727,7 +4003,7 @@ function inputValueAtPosition2(inputVar, position) {
|
|
|
3727
4003
|
case "at-maximum":
|
|
3728
4004
|
return inputVar.maxValue;
|
|
3729
4005
|
default:
|
|
3730
|
-
(0,
|
|
4006
|
+
(0, import_assert_never10.assertNever)(position);
|
|
3731
4007
|
}
|
|
3732
4008
|
}
|
|
3733
4009
|
var ResolvedScenarioGroups = class {
|
|
@@ -3786,7 +4062,7 @@ function resolveGraphsFromSpec(modelSpecL, modelSpecR, resolvedGraphGroups, grap
|
|
|
3786
4062
|
return [...graphIds];
|
|
3787
4063
|
}
|
|
3788
4064
|
default:
|
|
3789
|
-
(0,
|
|
4065
|
+
(0, import_assert_never10.assertNever)(graphsSpec.preset);
|
|
3790
4066
|
}
|
|
3791
4067
|
}
|
|
3792
4068
|
// eslint-disable-next-line no-fallthrough
|
|
@@ -3800,7 +4076,7 @@ function resolveGraphsFromSpec(modelSpecL, modelSpecR, resolvedGraphGroups, grap
|
|
|
3800
4076
|
return groupSpec.graphIds;
|
|
3801
4077
|
}
|
|
3802
4078
|
default:
|
|
3803
|
-
(0,
|
|
4079
|
+
(0, import_assert_never10.assertNever)(graphsSpec);
|
|
3804
4080
|
}
|
|
3805
4081
|
}
|
|
3806
4082
|
function resolveViewForScenarioId(resolvedScenarios, viewTitle, viewSubtitle, scenarioId, graphIds, graphOrder) {
|
|
@@ -3974,7 +4250,7 @@ function resolveViewGroupFromSpec(modelSpecL, modelSpecR, modelOutputs, resolved
|
|
|
3974
4250
|
views.push(resolveViewForScenario(void 0, void 0, scenario, graphIds, graphOrder));
|
|
3975
4251
|
break;
|
|
3976
4252
|
default:
|
|
3977
|
-
(0,
|
|
4253
|
+
(0, import_assert_never10.assertNever)(scenario);
|
|
3978
4254
|
}
|
|
3979
4255
|
}
|
|
3980
4256
|
} else {
|
|
@@ -3983,13 +4259,13 @@ function resolveViewGroupFromSpec(modelSpecL, modelSpecR, modelOutputs, resolved
|
|
|
3983
4259
|
break;
|
|
3984
4260
|
}
|
|
3985
4261
|
default:
|
|
3986
|
-
(0,
|
|
4262
|
+
(0, import_assert_never10.assertNever)(refSpec);
|
|
3987
4263
|
}
|
|
3988
4264
|
}
|
|
3989
4265
|
break;
|
|
3990
4266
|
}
|
|
3991
4267
|
default:
|
|
3992
|
-
(0,
|
|
4268
|
+
(0, import_assert_never10.assertNever)(viewGroupSpec);
|
|
3993
4269
|
}
|
|
3994
4270
|
return {
|
|
3995
4271
|
kind: "view-group",
|
|
@@ -4052,9 +4328,9 @@ var ComparisonDatasetsImpl = class {
|
|
|
4052
4328
|
}
|
|
4053
4329
|
const allOutputVarKeysSet = /* @__PURE__ */ new Set();
|
|
4054
4330
|
const modelOutputVarKeysSet = /* @__PURE__ */ new Set();
|
|
4055
|
-
function addOutputVars(outputVars,
|
|
4331
|
+
function addOutputVars(outputVars, handleRenames2) {
|
|
4056
4332
|
outputVars.forEach((outputVar, key) => {
|
|
4057
|
-
const remappedKey =
|
|
4333
|
+
const remappedKey = handleRenames2 ? leftKeyForRightKey(key) : key;
|
|
4058
4334
|
allOutputVarKeysSet.add(remappedKey);
|
|
4059
4335
|
if (outputVar.sourceName === void 0) {
|
|
4060
4336
|
modelOutputVarKeysSet.add(remappedKey);
|
|
@@ -4168,109 +4444,41 @@ var ComparisonScenariosImpl = class {
|
|
|
4168
4444
|
}
|
|
4169
4445
|
};
|
|
4170
4446
|
|
|
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
4447
|
// src/config/config.ts
|
|
4223
4448
|
function createConfig(options) {
|
|
4224
4449
|
return __async(this, null, function* () {
|
|
4225
|
-
var _a;
|
|
4226
|
-
|
|
4450
|
+
var _a, _b, _c, _d, _e;
|
|
4451
|
+
let concurrentModels;
|
|
4452
|
+
if (options.concurrency === void 0) {
|
|
4453
|
+
concurrentModels = 1;
|
|
4454
|
+
} else if (options.concurrency === 0) {
|
|
4455
|
+
let coreCount;
|
|
4456
|
+
if (typeof navigator !== "undefined") {
|
|
4457
|
+
coreCount = navigator.hardwareConcurrency;
|
|
4458
|
+
}
|
|
4459
|
+
if (coreCount === void 0 || coreCount < 1) {
|
|
4460
|
+
coreCount = 1;
|
|
4461
|
+
}
|
|
4462
|
+
concurrentModels = Math.max(1, Math.floor(coreCount / 2));
|
|
4463
|
+
} else {
|
|
4464
|
+
concurrentModels = Math.max(1, options.concurrency);
|
|
4465
|
+
}
|
|
4466
|
+
const origCurrentBundle = yield loadBundle(options.current, concurrentModels);
|
|
4227
4467
|
let currentBundle;
|
|
4228
4468
|
let comparisonConfig;
|
|
4229
4469
|
if (options.comparison === void 0) {
|
|
4230
4470
|
currentBundle = origCurrentBundle;
|
|
4231
4471
|
} 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;
|
|
4472
|
+
const baselineBundle = yield loadBundle(options.comparison.baseline, concurrentModels);
|
|
4473
|
+
currentBundle = handleRenames(origCurrentBundle, (_a = options.comparison.datasets) == null ? void 0 : _a.renamedDatasetKeys);
|
|
4474
|
+
const modelSpecL = baselineBundle.modelSpec;
|
|
4475
|
+
const modelSpecR = currentBundle.modelSpec;
|
|
4269
4476
|
const comparisonDefs = resolveComparisonSpecsFromSources(modelSpecL, modelSpecR, options.comparison.specs);
|
|
4270
4477
|
comparisonConfig = {
|
|
4271
4478
|
bundleL: baselineBundle,
|
|
4272
4479
|
bundleR: currentBundle,
|
|
4273
|
-
thresholds: options.comparison.thresholds,
|
|
4480
|
+
thresholds: (_b = options.comparison.thresholds) != null ? _b : [1, 5, 10],
|
|
4481
|
+
ratioThresholds: (_c = options.comparison.ratioThresholds) != null ? _c : [1, 2, 3],
|
|
4274
4482
|
scenarios: getComparisonScenarios(comparisonDefs.scenarios),
|
|
4275
4483
|
datasets: getComparisonDatasets(modelSpecL, modelSpecR, options.comparison.datasets),
|
|
4276
4484
|
viewGroups: comparisonDefs.viewGroups,
|
|
@@ -4281,26 +4489,77 @@ function createConfig(options) {
|
|
|
4281
4489
|
bundle: currentBundle,
|
|
4282
4490
|
tests: options.check.tests
|
|
4283
4491
|
};
|
|
4492
|
+
const executors = /* @__PURE__ */ new Map();
|
|
4493
|
+
for (let i = 0; i < checkConfig.bundle.models.length; i++) {
|
|
4494
|
+
const bundleModelL = (_d = comparisonConfig == null ? void 0 : comparisonConfig.bundleL.models) == null ? void 0 : _d[i];
|
|
4495
|
+
const bundleModelR = ((_e = comparisonConfig == null ? void 0 : comparisonConfig.bundleR.models) == null ? void 0 : _e[i]) || checkConfig.bundle.models[i];
|
|
4496
|
+
const executor = createExecutor(bundleModelL, bundleModelR);
|
|
4497
|
+
executors.set(`executor-${i}`, executor);
|
|
4498
|
+
}
|
|
4499
|
+
TaskQueue.initialize(executors);
|
|
4284
4500
|
return {
|
|
4285
4501
|
check: checkConfig,
|
|
4286
4502
|
comparison: comparisonConfig
|
|
4287
4503
|
};
|
|
4288
4504
|
});
|
|
4289
4505
|
}
|
|
4290
|
-
function
|
|
4506
|
+
function loadBundle(bundle, concurrentModels) {
|
|
4291
4507
|
return __async(this, null, function* () {
|
|
4292
|
-
const
|
|
4293
|
-
const
|
|
4508
|
+
const initCalls = Array.from({ length: concurrentModels }, () => bundle.bundle.initModel());
|
|
4509
|
+
const models = yield Promise.all(initCalls);
|
|
4294
4510
|
return {
|
|
4295
|
-
name:
|
|
4296
|
-
version:
|
|
4297
|
-
|
|
4511
|
+
name: bundle.name,
|
|
4512
|
+
version: bundle.bundle.version,
|
|
4513
|
+
modelSpec: bundle.bundle.modelSpec,
|
|
4514
|
+
models
|
|
4515
|
+
};
|
|
4516
|
+
});
|
|
4517
|
+
}
|
|
4518
|
+
function handleRenames(origCurrentBundle, renamedDatasetKeys) {
|
|
4519
|
+
if (renamedDatasetKeys === void 0 || renamedDatasetKeys.size === 0) {
|
|
4520
|
+
return origCurrentBundle;
|
|
4521
|
+
}
|
|
4522
|
+
const invertedRenamedKeys = /* @__PURE__ */ new Map();
|
|
4523
|
+
renamedDatasetKeys.forEach((newKey, oldKey) => {
|
|
4524
|
+
invertedRenamedKeys.set(newKey, oldKey);
|
|
4525
|
+
});
|
|
4526
|
+
const rightKeyForLeftKey = (leftKey) => {
|
|
4527
|
+
return (renamedDatasetKeys == null ? void 0 : renamedDatasetKeys.get(leftKey)) || leftKey;
|
|
4528
|
+
};
|
|
4529
|
+
const leftKeyForRightKey = (rightKey) => {
|
|
4530
|
+
return invertedRenamedKeys.get(rightKey) || rightKey;
|
|
4531
|
+
};
|
|
4532
|
+
function wrapModel(origBundleModelR) {
|
|
4533
|
+
var _a, _b, _c;
|
|
4534
|
+
return {
|
|
4535
|
+
modelSpec: origBundleModelR.modelSpec,
|
|
4536
|
+
getDatasetsForScenario: (scenarioSpec, datasetKeys) => __async(null, null, function* () {
|
|
4537
|
+
const rightKeys = datasetKeys.map(rightKeyForLeftKey);
|
|
4538
|
+
const result = yield origBundleModelR.getDatasetsForScenario(scenarioSpec, rightKeys);
|
|
4539
|
+
const mapWithRightKeys = result.datasetMap;
|
|
4540
|
+
const mapWithLeftKeys = /* @__PURE__ */ new Map();
|
|
4541
|
+
for (const [rightKey, dataset] of mapWithRightKeys.entries()) {
|
|
4542
|
+
const leftKey = leftKeyForRightKey(rightKey);
|
|
4543
|
+
mapWithLeftKeys.set(leftKey, dataset);
|
|
4544
|
+
}
|
|
4545
|
+
return {
|
|
4546
|
+
datasetMap: mapWithLeftKeys,
|
|
4547
|
+
modelRunTime: result.modelRunTime
|
|
4548
|
+
};
|
|
4549
|
+
}),
|
|
4550
|
+
getGraphDataForScenario: (_a = origBundleModelR.getGraphDataForScenario) == null ? void 0 : _a.bind(origBundleModelR),
|
|
4551
|
+
getGraphLinksForScenario: (_b = origBundleModelR.getGraphLinksForScenario) == null ? void 0 : _b.bind(origBundleModelR),
|
|
4552
|
+
createGraphView: (_c = origBundleModelR.createGraphView) == null ? void 0 : _c.bind(origBundleModelR)
|
|
4298
4553
|
};
|
|
4554
|
+
}
|
|
4555
|
+
const wrappedModels = origCurrentBundle.models.map(wrapModel);
|
|
4556
|
+
return __spreadProps(__spreadValues({}, origCurrentBundle), {
|
|
4557
|
+
models: wrappedModels
|
|
4299
4558
|
});
|
|
4300
4559
|
}
|
|
4301
4560
|
|
|
4302
4561
|
// src/perf/perf-runner.ts
|
|
4303
|
-
var
|
|
4562
|
+
var import_assert_never11 = require("assert-never");
|
|
4304
4563
|
|
|
4305
4564
|
// src/perf/perf-stats.ts
|
|
4306
4565
|
var PerfStats = class {
|
|
@@ -4337,80 +4596,110 @@ var PerfStats = class {
|
|
|
4337
4596
|
};
|
|
4338
4597
|
|
|
4339
4598
|
// src/perf/perf-runner.ts
|
|
4340
|
-
|
|
4341
|
-
|
|
4599
|
+
function runPerfWithTaskQueue(taskQueue, callbacks, options) {
|
|
4600
|
+
const perfRunner = new PerfRunner(taskQueue, callbacks, options);
|
|
4601
|
+
perfRunner.start();
|
|
4602
|
+
return () => {
|
|
4603
|
+
perfRunner.cancel();
|
|
4604
|
+
};
|
|
4605
|
+
}
|
|
4606
|
+
function runPerf(callbacks, options) {
|
|
4607
|
+
const taskQueue = TaskQueue.getInstance();
|
|
4608
|
+
return runPerfWithTaskQueue(taskQueue, callbacks, options);
|
|
4609
|
+
}
|
|
4342
4610
|
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
|
-
});
|
|
4611
|
+
constructor(taskQueue, callbacks, options) {
|
|
4612
|
+
this.taskQueue = taskQueue;
|
|
4613
|
+
this.callbacks = callbacks;
|
|
4614
|
+
this.options = options;
|
|
4615
|
+
this.pendingTaskKeys = /* @__PURE__ */ new Set();
|
|
4616
|
+
this.stopped = false;
|
|
4617
|
+
}
|
|
4618
|
+
cancel() {
|
|
4619
|
+
if (!this.stopped) {
|
|
4620
|
+
for (const taskKey of this.pendingTaskKeys) {
|
|
4621
|
+
this.taskQueue.cancelTask(taskKey);
|
|
4622
|
+
}
|
|
4623
|
+
this.stopped = true;
|
|
4624
|
+
}
|
|
4378
4625
|
}
|
|
4379
4626
|
start() {
|
|
4627
|
+
var _a, _b, _c, _d, _e, _f;
|
|
4380
4628
|
const statsL = new PerfStats();
|
|
4381
4629
|
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
|
-
});
|
|
4630
|
+
const scenarioSpec = allInputsAtPositionSpec("at-default");
|
|
4631
|
+
const warmupCount = (_b = (_a = this.options) == null ? void 0 : _a.warmupCount) != null ? _b : 5;
|
|
4632
|
+
const runCount = (_d = (_c = this.options) == null ? void 0 : _c.runCount) != null ? _d : 100;
|
|
4633
|
+
let totalTasks = 0;
|
|
4634
|
+
if (((_e = this.options) == null ? void 0 : _e.mode) === "parallel") {
|
|
4635
|
+
totalTasks = warmupCount + runCount;
|
|
4636
|
+
} else {
|
|
4637
|
+
totalTasks = (warmupCount + runCount) * 2;
|
|
4404
4638
|
}
|
|
4639
|
+
let tasksCompleted = 0;
|
|
4640
|
+
let perfTaskId = 1;
|
|
4641
|
+
const addTask = (warmup, kind) => {
|
|
4642
|
+
const task = {
|
|
4643
|
+
key: `perf-runner-${perfTaskId++}`,
|
|
4644
|
+
kind: "perf-runner",
|
|
4645
|
+
process: (bundleModels) => __async(this, null, function* () {
|
|
4646
|
+
var _a2, _b2, _c2, _d2;
|
|
4647
|
+
this.pendingTaskKeys.delete(task.key);
|
|
4648
|
+
try {
|
|
4649
|
+
let runTimeL;
|
|
4650
|
+
let runTimeR;
|
|
4651
|
+
switch (kind) {
|
|
4652
|
+
case "left": {
|
|
4653
|
+
const result = yield bundleModels.L.getDatasetsForScenario(scenarioSpec, []);
|
|
4654
|
+
runTimeL = result.modelRunTime;
|
|
4655
|
+
break;
|
|
4656
|
+
}
|
|
4657
|
+
case "right": {
|
|
4658
|
+
const result = yield bundleModels.R.getDatasetsForScenario(scenarioSpec, []);
|
|
4659
|
+
runTimeR = result.modelRunTime;
|
|
4660
|
+
break;
|
|
4661
|
+
}
|
|
4662
|
+
case "both": {
|
|
4663
|
+
const [resultL, resultR] = yield Promise.all([
|
|
4664
|
+
bundleModels.L.getDatasetsForScenario(scenarioSpec, []),
|
|
4665
|
+
bundleModels.R.getDatasetsForScenario(scenarioSpec, [])
|
|
4666
|
+
]);
|
|
4667
|
+
runTimeL = resultL.modelRunTime;
|
|
4668
|
+
runTimeR = resultR.modelRunTime;
|
|
4669
|
+
break;
|
|
4670
|
+
}
|
|
4671
|
+
default:
|
|
4672
|
+
(0, import_assert_never11.assertNever)(kind);
|
|
4673
|
+
}
|
|
4674
|
+
if (!warmup) {
|
|
4675
|
+
if (runTimeL !== void 0) {
|
|
4676
|
+
statsL.addRun(runTimeL);
|
|
4677
|
+
}
|
|
4678
|
+
if (runTimeR !== void 0) {
|
|
4679
|
+
statsR.addRun(runTimeR);
|
|
4680
|
+
}
|
|
4681
|
+
}
|
|
4682
|
+
tasksCompleted++;
|
|
4683
|
+
if (tasksCompleted === totalTasks) {
|
|
4684
|
+
(_b2 = (_a2 = this.callbacks).onComplete) == null ? void 0 : _b2.call(_a2, statsL.toReport(), statsR.toReport());
|
|
4685
|
+
}
|
|
4686
|
+
} catch (error) {
|
|
4687
|
+
(_d2 = (_c2 = this.callbacks).onError) == null ? void 0 : _d2.call(_c2, error);
|
|
4688
|
+
}
|
|
4689
|
+
})
|
|
4690
|
+
};
|
|
4691
|
+
this.taskQueue.addTask(task);
|
|
4692
|
+
this.pendingTaskKeys.add(task.key);
|
|
4693
|
+
};
|
|
4405
4694
|
function addTasks(kind) {
|
|
4406
4695
|
for (let i = 0; i < warmupCount; i++) {
|
|
4407
|
-
addTask(
|
|
4696
|
+
addTask(true, kind);
|
|
4408
4697
|
}
|
|
4409
4698
|
for (let i = 0; i < runCount; i++) {
|
|
4410
|
-
addTask(
|
|
4699
|
+
addTask(false, kind);
|
|
4411
4700
|
}
|
|
4412
4701
|
}
|
|
4413
|
-
if (this.mode === "parallel") {
|
|
4702
|
+
if (((_f = this.options) == null ? void 0 : _f.mode) === "parallel") {
|
|
4414
4703
|
addTasks("both");
|
|
4415
4704
|
} else {
|
|
4416
4705
|
addTasks("left");
|
|
@@ -4419,6 +4708,303 @@ var PerfRunner = class {
|
|
|
4419
4708
|
}
|
|
4420
4709
|
};
|
|
4421
4710
|
|
|
4711
|
+
// src/trace/trace-runner.ts
|
|
4712
|
+
var import_assert_never12 = require("assert-never");
|
|
4713
|
+
function runTraceWithTaskQueue(modelSpec, taskQueue, callbacks, options) {
|
|
4714
|
+
const traceRunner = new TraceRunner(taskQueue, callbacks);
|
|
4715
|
+
traceRunner.start(modelSpec, options);
|
|
4716
|
+
return () => {
|
|
4717
|
+
traceRunner.cancel();
|
|
4718
|
+
};
|
|
4719
|
+
}
|
|
4720
|
+
function runTrace(modelSpec, callbacks, options) {
|
|
4721
|
+
const taskQueue = TaskQueue.getInstance();
|
|
4722
|
+
return runTraceWithTaskQueue(modelSpec, taskQueue, callbacks, options);
|
|
4723
|
+
}
|
|
4724
|
+
var TraceRunner = class {
|
|
4725
|
+
constructor(taskQueue, callbacks) {
|
|
4726
|
+
this.taskQueue = taskQueue;
|
|
4727
|
+
this.callbacks = callbacks;
|
|
4728
|
+
this.pendingTaskKeys = /* @__PURE__ */ new Set();
|
|
4729
|
+
this.stopped = false;
|
|
4730
|
+
}
|
|
4731
|
+
cancel() {
|
|
4732
|
+
if (!this.stopped) {
|
|
4733
|
+
for (const taskKey of this.pendingTaskKeys) {
|
|
4734
|
+
this.taskQueue.cancelTask(taskKey);
|
|
4735
|
+
}
|
|
4736
|
+
this.stopped = true;
|
|
4737
|
+
}
|
|
4738
|
+
}
|
|
4739
|
+
start(modelSpec, options) {
|
|
4740
|
+
const allDatasetKeys = [...modelSpec.implVars.keys()];
|
|
4741
|
+
const traceRequests = [];
|
|
4742
|
+
const batchSize = 2e3;
|
|
4743
|
+
for (let i = 0; i < allDatasetKeys.length; i += batchSize) {
|
|
4744
|
+
const datasetKeysForBatch = allDatasetKeys.slice(i, i + batchSize);
|
|
4745
|
+
switch (options.kind) {
|
|
4746
|
+
case "compare-to-bundle":
|
|
4747
|
+
traceRequests.push({
|
|
4748
|
+
kind: "compare-to-bundle",
|
|
4749
|
+
datasetKeys: datasetKeysForBatch,
|
|
4750
|
+
bundleSide0: options.bundleSide0,
|
|
4751
|
+
scenarioSpec0: options.scenarioSpec0,
|
|
4752
|
+
bundleSide1: options.bundleSide1,
|
|
4753
|
+
scenarioSpec1: options.scenarioSpec1
|
|
4754
|
+
});
|
|
4755
|
+
break;
|
|
4756
|
+
case "compare-to-ext-data":
|
|
4757
|
+
traceRequests.push({
|
|
4758
|
+
kind: "compare-to-ext-data",
|
|
4759
|
+
datasetKeys: datasetKeysForBatch,
|
|
4760
|
+
extData: options.extData,
|
|
4761
|
+
bundleSide: options.bundleSide,
|
|
4762
|
+
scenarioSpec: options.scenarioSpec
|
|
4763
|
+
});
|
|
4764
|
+
break;
|
|
4765
|
+
default:
|
|
4766
|
+
(0, import_assert_never12.assertNever)(options);
|
|
4767
|
+
}
|
|
4768
|
+
}
|
|
4769
|
+
const allDatasetReports = /* @__PURE__ */ new Map();
|
|
4770
|
+
const taskCount = traceRequests.length;
|
|
4771
|
+
let tasksCompleted = 0;
|
|
4772
|
+
let traceTaskId = 1;
|
|
4773
|
+
for (const traceRequest of traceRequests) {
|
|
4774
|
+
const task = {
|
|
4775
|
+
key: `trace-runner-${traceTaskId++}`,
|
|
4776
|
+
kind: "trace-runner",
|
|
4777
|
+
process: (bundleModels) => __async(this, null, function* () {
|
|
4778
|
+
var _a, _b;
|
|
4779
|
+
this.pendingTaskKeys.delete(task.key);
|
|
4780
|
+
let datasetReports;
|
|
4781
|
+
switch (traceRequest.kind) {
|
|
4782
|
+
case "compare-to-bundle":
|
|
4783
|
+
datasetReports = yield processCompareToBundleRequest(traceRequest, bundleModels);
|
|
4784
|
+
break;
|
|
4785
|
+
case "compare-to-ext-data":
|
|
4786
|
+
datasetReports = yield processCompareToExtDataRequest(traceRequest, bundleModels);
|
|
4787
|
+
break;
|
|
4788
|
+
default:
|
|
4789
|
+
(0, import_assert_never12.assertNever)(traceRequest);
|
|
4790
|
+
}
|
|
4791
|
+
for (const datasetReport of datasetReports) {
|
|
4792
|
+
allDatasetReports.set(datasetReport.datasetKey, datasetReport);
|
|
4793
|
+
}
|
|
4794
|
+
tasksCompleted++;
|
|
4795
|
+
if (tasksCompleted === taskCount) {
|
|
4796
|
+
const traceReport = {
|
|
4797
|
+
datasetReports: allDatasetReports
|
|
4798
|
+
};
|
|
4799
|
+
(_b = (_a = this.callbacks).onComplete) == null ? void 0 : _b.call(_a, traceReport);
|
|
4800
|
+
}
|
|
4801
|
+
})
|
|
4802
|
+
};
|
|
4803
|
+
this.taskQueue.addTask(task);
|
|
4804
|
+
this.pendingTaskKeys.add(task.key);
|
|
4805
|
+
}
|
|
4806
|
+
}
|
|
4807
|
+
};
|
|
4808
|
+
function processCompareToBundleRequest(request, bundleModels) {
|
|
4809
|
+
return __async(this, null, function* () {
|
|
4810
|
+
const bundleModel0 = request.bundleSide0 === "left" ? bundleModels.L : bundleModels.R;
|
|
4811
|
+
const bundleModel1 = request.bundleSide1 === "left" ? bundleModels.L : bundleModels.R;
|
|
4812
|
+
let result0;
|
|
4813
|
+
let result1;
|
|
4814
|
+
if (bundleModel1 === bundleModel0) {
|
|
4815
|
+
result0 = yield bundleModel0.getDatasetsForScenario(request.scenarioSpec0, request.datasetKeys);
|
|
4816
|
+
result1 = yield bundleModel1.getDatasetsForScenario(request.scenarioSpec1, request.datasetKeys);
|
|
4817
|
+
} else {
|
|
4818
|
+
;
|
|
4819
|
+
[result0, result1] = yield Promise.all([
|
|
4820
|
+
bundleModel0.getDatasetsForScenario(request.scenarioSpec0, request.datasetKeys),
|
|
4821
|
+
bundleModel1.getDatasetsForScenario(request.scenarioSpec1, request.datasetKeys)
|
|
4822
|
+
]);
|
|
4823
|
+
}
|
|
4824
|
+
const datasetReports = [];
|
|
4825
|
+
for (const datasetKey of request.datasetKeys) {
|
|
4826
|
+
const dataset0 = result0.datasetMap.get(datasetKey);
|
|
4827
|
+
const dataset1 = result1.datasetMap.get(datasetKey);
|
|
4828
|
+
const datasetReport = diffDatasets2(
|
|
4829
|
+
datasetKey,
|
|
4830
|
+
dataset0,
|
|
4831
|
+
dataset1,
|
|
4832
|
+
/*matchPrecisionOfLeft=*/
|
|
4833
|
+
false
|
|
4834
|
+
);
|
|
4835
|
+
datasetReports.push(datasetReport);
|
|
4836
|
+
}
|
|
4837
|
+
return datasetReports;
|
|
4838
|
+
});
|
|
4839
|
+
}
|
|
4840
|
+
function processCompareToExtDataRequest(request, bundleModels) {
|
|
4841
|
+
return __async(this, null, function* () {
|
|
4842
|
+
const bundleModel = request.bundleSide === "left" ? bundleModels.L : bundleModels.R;
|
|
4843
|
+
const resultR = yield bundleModel.getDatasetsForScenario(request.scenarioSpec, request.datasetKeys);
|
|
4844
|
+
const datasetReports = [];
|
|
4845
|
+
for (const datasetKey of request.datasetKeys) {
|
|
4846
|
+
let datasetL = request.extData.get(datasetKey);
|
|
4847
|
+
if (datasetL === void 0) {
|
|
4848
|
+
const datasetKeyParts = datasetKey.split("[");
|
|
4849
|
+
if (datasetKeyParts.length === 2) {
|
|
4850
|
+
const baseKey = datasetKeyParts[0];
|
|
4851
|
+
const keySubParts = datasetKeyParts[1].replace("]", "");
|
|
4852
|
+
const keySubIds = keySubParts.split(",");
|
|
4853
|
+
const subIdPermutations = permutationsOf(keySubIds);
|
|
4854
|
+
for (const subIds of subIdPermutations) {
|
|
4855
|
+
const datDatasetKey = `${baseKey}[${subIds.join(",")}]`;
|
|
4856
|
+
datasetL = request.extData.get(datDatasetKey);
|
|
4857
|
+
if (datasetL !== void 0) {
|
|
4858
|
+
break;
|
|
4859
|
+
}
|
|
4860
|
+
}
|
|
4861
|
+
}
|
|
4862
|
+
if (datasetL === void 0) {
|
|
4863
|
+
console.warn(`WARNING: Failed to find data in dat file for key=${datasetKey}`);
|
|
4864
|
+
}
|
|
4865
|
+
}
|
|
4866
|
+
const datasetR = resultR.datasetMap.get(datasetKey);
|
|
4867
|
+
const datasetReport = diffDatasets2(
|
|
4868
|
+
datasetKey,
|
|
4869
|
+
datasetL,
|
|
4870
|
+
datasetR,
|
|
4871
|
+
/*matchPrecisionOfLeft=*/
|
|
4872
|
+
true
|
|
4873
|
+
);
|
|
4874
|
+
datasetReports.push(datasetReport);
|
|
4875
|
+
}
|
|
4876
|
+
return datasetReports;
|
|
4877
|
+
});
|
|
4878
|
+
}
|
|
4879
|
+
function diffDatasets2(datasetKey, datasetL, datasetR, matchPrecisionOfLeft) {
|
|
4880
|
+
const points = /* @__PURE__ */ new Map();
|
|
4881
|
+
let minValueL = Number.MAX_VALUE;
|
|
4882
|
+
let maxValueL = Number.MIN_VALUE;
|
|
4883
|
+
let minValueR = Number.MAX_VALUE;
|
|
4884
|
+
let maxValueR = Number.MIN_VALUE;
|
|
4885
|
+
let minValue = Number.MAX_VALUE;
|
|
4886
|
+
let maxValue = Number.MIN_VALUE;
|
|
4887
|
+
let minRawDiff = Number.MAX_VALUE;
|
|
4888
|
+
let maxRawDiff = -1;
|
|
4889
|
+
let maxDiffPoint;
|
|
4890
|
+
let diffCount = 0;
|
|
4891
|
+
let totalRawDiff = 0;
|
|
4892
|
+
if (datasetL && datasetR) {
|
|
4893
|
+
const times = /* @__PURE__ */ new Set([...datasetL.keys(), ...datasetR.keys()]);
|
|
4894
|
+
for (const t of times) {
|
|
4895
|
+
const valueL = datasetL.get(t);
|
|
4896
|
+
if (valueL !== void 0) {
|
|
4897
|
+
if (valueL < minValueL) minValueL = valueL;
|
|
4898
|
+
if (valueL > maxValueL) maxValueL = valueL;
|
|
4899
|
+
if (valueL < minValue) minValue = valueL;
|
|
4900
|
+
if (valueL > maxValue) maxValue = valueL;
|
|
4901
|
+
}
|
|
4902
|
+
let valueR;
|
|
4903
|
+
const rawValueR = datasetR.get(t);
|
|
4904
|
+
if (rawValueR !== void 0) {
|
|
4905
|
+
if (matchPrecisionOfLeft && valueL !== void 0) {
|
|
4906
|
+
valueR = matchPrecision(rawValueR, valueL);
|
|
4907
|
+
} else {
|
|
4908
|
+
valueR = rawValueR;
|
|
4909
|
+
}
|
|
4910
|
+
if (valueR < minValueR) minValueR = valueR;
|
|
4911
|
+
if (valueR > maxValueR) maxValueR = valueR;
|
|
4912
|
+
if (valueR < minValue) minValue = valueR;
|
|
4913
|
+
if (valueR > maxValue) maxValue = valueR;
|
|
4914
|
+
}
|
|
4915
|
+
if (valueL === void 0 || valueR === void 0) {
|
|
4916
|
+
continue;
|
|
4917
|
+
}
|
|
4918
|
+
const point = {
|
|
4919
|
+
time: t,
|
|
4920
|
+
valueL,
|
|
4921
|
+
valueR
|
|
4922
|
+
};
|
|
4923
|
+
points.set(t, point);
|
|
4924
|
+
const rawDiff = Math.abs(valueR - valueL);
|
|
4925
|
+
if (rawDiff < minRawDiff) {
|
|
4926
|
+
minRawDiff = rawDiff;
|
|
4927
|
+
}
|
|
4928
|
+
if (rawDiff > maxRawDiff) {
|
|
4929
|
+
maxRawDiff = rawDiff;
|
|
4930
|
+
maxDiffPoint = point;
|
|
4931
|
+
}
|
|
4932
|
+
diffCount++;
|
|
4933
|
+
totalRawDiff += rawDiff;
|
|
4934
|
+
}
|
|
4935
|
+
}
|
|
4936
|
+
function pct(x) {
|
|
4937
|
+
return x * 100;
|
|
4938
|
+
}
|
|
4939
|
+
let minDiff;
|
|
4940
|
+
let maxDiff;
|
|
4941
|
+
let avgDiff;
|
|
4942
|
+
if (minValueL === maxValueL && minValueR === maxValueR) {
|
|
4943
|
+
const diff = pct(maxValueL !== 0 ? Math.abs((maxValueR - maxValueL) / maxValueL) : 1);
|
|
4944
|
+
minDiff = diff;
|
|
4945
|
+
maxDiff = diff;
|
|
4946
|
+
avgDiff = diff;
|
|
4947
|
+
} else {
|
|
4948
|
+
const spread = maxValue - minValue;
|
|
4949
|
+
minDiff = pct(spread > 0 ? minRawDiff / spread : 0);
|
|
4950
|
+
maxDiff = pct(spread > 0 ? maxRawDiff / spread : 0);
|
|
4951
|
+
const avgRawDiff = totalRawDiff / diffCount;
|
|
4952
|
+
avgDiff = pct(spread > 0 ? avgRawDiff / spread : 0);
|
|
4953
|
+
}
|
|
4954
|
+
let validity;
|
|
4955
|
+
if (datasetL && datasetR) {
|
|
4956
|
+
validity = "both";
|
|
4957
|
+
} else if (datasetL) {
|
|
4958
|
+
validity = "left-only";
|
|
4959
|
+
} else if (datasetR) {
|
|
4960
|
+
validity = "right-only";
|
|
4961
|
+
} else {
|
|
4962
|
+
validity = "neither";
|
|
4963
|
+
}
|
|
4964
|
+
return {
|
|
4965
|
+
datasetKey,
|
|
4966
|
+
validity,
|
|
4967
|
+
points,
|
|
4968
|
+
minValue,
|
|
4969
|
+
maxValue,
|
|
4970
|
+
avgDiff,
|
|
4971
|
+
minDiff,
|
|
4972
|
+
maxDiff,
|
|
4973
|
+
maxDiffPoint
|
|
4974
|
+
};
|
|
4975
|
+
}
|
|
4976
|
+
function matchPrecision(x, baseline) {
|
|
4977
|
+
const s = baseline.toString();
|
|
4978
|
+
if (s.includes("e")) {
|
|
4979
|
+
return x;
|
|
4980
|
+
}
|
|
4981
|
+
const parts = s.split(".");
|
|
4982
|
+
if (parts.length < 2) {
|
|
4983
|
+
return x;
|
|
4984
|
+
}
|
|
4985
|
+
const sigDigits = parts[1].replace(/0+$/, "").length;
|
|
4986
|
+
if (sigDigits > 21) {
|
|
4987
|
+
return x;
|
|
4988
|
+
}
|
|
4989
|
+
return parseFloat(x.toFixed(sigDigits));
|
|
4990
|
+
}
|
|
4991
|
+
function permutationsOf(inputArr) {
|
|
4992
|
+
const result = [];
|
|
4993
|
+
const permute = (arr, m = []) => {
|
|
4994
|
+
if (arr.length === 0) {
|
|
4995
|
+
result.push(m);
|
|
4996
|
+
} else {
|
|
4997
|
+
for (let i = 0; i < arr.length; i++) {
|
|
4998
|
+
const curr = arr.slice();
|
|
4999
|
+
const next = curr.splice(i, 1);
|
|
5000
|
+
permute(curr.slice(), m.concat(next));
|
|
5001
|
+
}
|
|
5002
|
+
}
|
|
5003
|
+
};
|
|
5004
|
+
permute(inputArr);
|
|
5005
|
+
return result;
|
|
5006
|
+
}
|
|
5007
|
+
|
|
4422
5008
|
// src/data/data-planner.ts
|
|
4423
5009
|
var DataPlanner = class {
|
|
4424
5010
|
/**
|
|
@@ -4605,10 +5191,10 @@ function scenarioPairUid(scenarioSpecL, scenarioSpecR) {
|
|
|
4605
5191
|
}
|
|
4606
5192
|
|
|
4607
5193
|
// src/check/check-runner.ts
|
|
4608
|
-
function runChecks(checkConfig, checkSpec, dataPlanner, refDataPlanner,
|
|
4609
|
-
const modelSpec = checkConfig.bundle.
|
|
5194
|
+
function runChecks(checkConfig, checkSpec, dataPlanner, refDataPlanner, skipChecks) {
|
|
5195
|
+
const modelSpec = checkConfig.bundle.modelSpec;
|
|
4610
5196
|
const checkPlanner = new CheckPlanner(modelSpec);
|
|
4611
|
-
checkPlanner.addAllChecks(checkSpec,
|
|
5197
|
+
checkPlanner.addAllChecks(checkSpec, skipChecks);
|
|
4612
5198
|
const checkPlan = checkPlanner.buildPlan();
|
|
4613
5199
|
const refDatasets = /* @__PURE__ */ new Map();
|
|
4614
5200
|
for (const [dataRefKey, dataRef] of checkPlan.dataRefs.entries()) {
|
|
@@ -4621,11 +5207,15 @@ function runChecks(checkConfig, checkSpec, dataPlanner, refDataPlanner, simplify
|
|
|
4621
5207
|
}
|
|
4622
5208
|
const checkResults = /* @__PURE__ */ new Map();
|
|
4623
5209
|
for (const [checkKey, checkTask] of checkPlan.tasks.entries()) {
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
5210
|
+
if (checkTask.skip === true) {
|
|
5211
|
+
checkResults.set(checkKey, { status: "skipped" });
|
|
5212
|
+
} else {
|
|
5213
|
+
dataPlanner.addRequest(void 0, checkTask.scenario.spec, checkTask.dataset.datasetKey, (datasets) => {
|
|
5214
|
+
const dataset = datasets.datasetR;
|
|
5215
|
+
const checkResult = runCheck(checkTask, dataset, refDatasets);
|
|
5216
|
+
checkResults.set(checkKey, checkResult);
|
|
5217
|
+
});
|
|
5218
|
+
}
|
|
4629
5219
|
}
|
|
4630
5220
|
return () => {
|
|
4631
5221
|
return buildCheckReport(checkPlan, checkResults);
|
|
@@ -4690,21 +5280,73 @@ function runCheck(checkTask, dataset, refDatasets) {
|
|
|
4690
5280
|
}
|
|
4691
5281
|
|
|
4692
5282
|
// src/comparison/run/comparison-runner.ts
|
|
4693
|
-
function runComparisons(comparisonConfig, dataPlanner) {
|
|
5283
|
+
function runComparisons(comparisonConfig, dataPlanner, skipScenarios) {
|
|
5284
|
+
function skipScenarioKey(title, subtitle) {
|
|
5285
|
+
let key = title.toLowerCase();
|
|
5286
|
+
if (subtitle) {
|
|
5287
|
+
key += ` :: ${subtitle.toLowerCase()}`;
|
|
5288
|
+
}
|
|
5289
|
+
return key;
|
|
5290
|
+
}
|
|
5291
|
+
const skipScenariosSet = new Set(skipScenarios.map((scenario) => skipScenarioKey(scenario.title, scenario.subtitle)));
|
|
5292
|
+
const allScenarios = [...comparisonConfig.scenarios.getAllScenarios()];
|
|
5293
|
+
let baselineScenario;
|
|
5294
|
+
const baselineScenarioIndex = allScenarios.findIndex((scenario) => {
|
|
5295
|
+
const settings = scenario.settings;
|
|
5296
|
+
return settings.kind === "all-inputs-settings" && settings.position === "at-default";
|
|
5297
|
+
});
|
|
5298
|
+
if (baselineScenarioIndex !== -1) {
|
|
5299
|
+
baselineScenario = allScenarios.splice(baselineScenarioIndex, 1)[0];
|
|
5300
|
+
}
|
|
4694
5301
|
const testReports = [];
|
|
4695
|
-
|
|
5302
|
+
const baselineDiffReports = /* @__PURE__ */ new Map();
|
|
5303
|
+
function runComparisonsForScenario(scenario, isBaseline) {
|
|
4696
5304
|
const datasetKeys = comparisonConfig.datasets.getDatasetKeysForScenario(scenario);
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
5305
|
+
const shouldSkip = skipScenariosSet.has(skipScenarioKey(scenario.title, scenario.subtitle));
|
|
5306
|
+
if (shouldSkip) {
|
|
5307
|
+
for (const datasetKey of datasetKeys) {
|
|
4700
5308
|
testReports.push({
|
|
4701
5309
|
scenarioKey: scenario.key,
|
|
4702
5310
|
datasetKey,
|
|
4703
|
-
diffReport
|
|
5311
|
+
diffReport: void 0
|
|
4704
5312
|
});
|
|
5313
|
+
}
|
|
5314
|
+
return;
|
|
5315
|
+
}
|
|
5316
|
+
for (const datasetKey of datasetKeys) {
|
|
5317
|
+
dataPlanner.addRequest(scenario.specL, scenario.specR, datasetKey, (datasets) => {
|
|
5318
|
+
const diffReport = diffDatasets(datasets.datasetL, datasets.datasetR);
|
|
5319
|
+
if (isBaseline) {
|
|
5320
|
+
baselineDiffReports.set(datasetKey, diffReport);
|
|
5321
|
+
testReports.push({
|
|
5322
|
+
scenarioKey: scenario.key,
|
|
5323
|
+
datasetKey,
|
|
5324
|
+
diffReport
|
|
5325
|
+
});
|
|
5326
|
+
} else {
|
|
5327
|
+
const baselineDiffReport = baselineDiffReports.get(datasetKey);
|
|
5328
|
+
testReports.push({
|
|
5329
|
+
scenarioKey: scenario.key,
|
|
5330
|
+
datasetKey,
|
|
5331
|
+
diffReport,
|
|
5332
|
+
baselineDiffReport
|
|
5333
|
+
});
|
|
5334
|
+
}
|
|
4705
5335
|
});
|
|
4706
5336
|
}
|
|
4707
5337
|
}
|
|
5338
|
+
runComparisonsForScenario(
|
|
5339
|
+
baselineScenario,
|
|
5340
|
+
/*isBaseline=*/
|
|
5341
|
+
true
|
|
5342
|
+
);
|
|
5343
|
+
for (const scenario of allScenarios) {
|
|
5344
|
+
runComparisonsForScenario(
|
|
5345
|
+
scenario,
|
|
5346
|
+
/*isBaseline=*/
|
|
5347
|
+
false
|
|
5348
|
+
);
|
|
5349
|
+
}
|
|
4708
5350
|
return () => {
|
|
4709
5351
|
return testReports;
|
|
4710
5352
|
};
|
|
@@ -4712,74 +5354,52 @@ function runComparisons(comparisonConfig, dataPlanner) {
|
|
|
4712
5354
|
|
|
4713
5355
|
// src/suite/suite-runner.ts
|
|
4714
5356
|
var SuiteRunner = class {
|
|
4715
|
-
constructor(config, callbacks) {
|
|
5357
|
+
constructor(config, taskQueue, callbacks) {
|
|
4716
5358
|
this.config = config;
|
|
5359
|
+
this.taskQueue = taskQueue;
|
|
4717
5360
|
this.callbacks = callbacks;
|
|
4718
5361
|
this.perfStatsL = new PerfStats();
|
|
4719
5362
|
this.perfStatsR = new PerfStats();
|
|
5363
|
+
this.pendingTaskKeys = /* @__PURE__ */ new Set();
|
|
4720
5364
|
this.stopped = false;
|
|
4721
|
-
this.taskQueue = new TaskQueue({
|
|
4722
|
-
process: (request) => {
|
|
4723
|
-
return this.processRequest(request);
|
|
4724
|
-
}
|
|
4725
|
-
});
|
|
4726
5365
|
}
|
|
4727
5366
|
cancel() {
|
|
4728
5367
|
if (!this.stopped) {
|
|
5368
|
+
for (const taskKey of this.pendingTaskKeys) {
|
|
5369
|
+
this.taskQueue.cancelTask(taskKey);
|
|
5370
|
+
}
|
|
4729
5371
|
this.stopped = true;
|
|
4730
|
-
this.taskQueue.shutdown();
|
|
4731
5372
|
}
|
|
4732
5373
|
}
|
|
4733
5374
|
start(options) {
|
|
4734
5375
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
4735
5376
|
(_b = (_a = this.callbacks).onProgress) == null ? void 0 : _b.call(_a, 0);
|
|
4736
|
-
const
|
|
4737
|
-
const dataPlanner = new DataPlanner(
|
|
4738
|
-
const refDataPlanner = new DataPlanner(
|
|
5377
|
+
const modelSpecR = this.config.check.bundle.modelSpec;
|
|
5378
|
+
const dataPlanner = new DataPlanner(modelSpecR.outputVars.size);
|
|
5379
|
+
const refDataPlanner = new DataPlanner(modelSpecR.outputVars.size);
|
|
4739
5380
|
const checkSpecResult = parseTestYaml(this.config.check.tests);
|
|
4740
5381
|
if (checkSpecResult.isErr()) {
|
|
4741
5382
|
(_d = (_c = this.callbacks).onError) == null ? void 0 : _d.call(_c, checkSpecResult.error);
|
|
4742
5383
|
return;
|
|
4743
5384
|
}
|
|
4744
5385
|
const checkSpec = checkSpecResult.value;
|
|
4745
|
-
const
|
|
4746
|
-
const buildCheckReport2 = runChecks(this.config.check, checkSpec, dataPlanner, refDataPlanner,
|
|
5386
|
+
const skipChecks = (options == null ? void 0 : options.skipChecks) || [];
|
|
5387
|
+
const buildCheckReport2 = runChecks(this.config.check, checkSpec, dataPlanner, refDataPlanner, skipChecks);
|
|
4747
5388
|
let buildComparisonTestReports;
|
|
4748
5389
|
if (this.config.comparison) {
|
|
4749
|
-
|
|
5390
|
+
const skipScenarios = (options == null ? void 0 : options.skipComparisonScenarios) || [];
|
|
5391
|
+
buildComparisonTestReports = runComparisons(this.config.comparison, dataPlanner, skipScenarios);
|
|
4750
5392
|
}
|
|
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
5393
|
const refDataPlan = refDataPlanner.buildPlan();
|
|
4775
5394
|
const dataPlan = dataPlanner.buildPlan();
|
|
4776
5395
|
const dataRequests = [...refDataPlan.requests, ...dataPlan.requests];
|
|
4777
5396
|
const taskCount = dataRequests.length;
|
|
4778
5397
|
if (taskCount === 0) {
|
|
5398
|
+
const checkReport = buildCheckReport2();
|
|
4779
5399
|
let comparisonReport;
|
|
4780
5400
|
if (this.config.comparison) {
|
|
4781
5401
|
comparisonReport = {
|
|
4782
|
-
testReports:
|
|
5402
|
+
testReports: buildComparisonTestReports(),
|
|
4783
5403
|
perfReportL: this.perfStatsL.toReport(),
|
|
4784
5404
|
perfReportR: this.perfStatsR.toReport()
|
|
4785
5405
|
};
|
|
@@ -4787,26 +5407,54 @@ var SuiteRunner = class {
|
|
|
4787
5407
|
this.cancel();
|
|
4788
5408
|
(_f = (_e = this.callbacks).onProgress) == null ? void 0 : _f.call(_e, 1);
|
|
4789
5409
|
(_h = (_g = this.callbacks).onComplete) == null ? void 0 : _h.call(_g, {
|
|
4790
|
-
checkReport
|
|
4791
|
-
groups: []
|
|
4792
|
-
},
|
|
5410
|
+
checkReport,
|
|
4793
5411
|
comparisonReport
|
|
4794
5412
|
});
|
|
4795
5413
|
return;
|
|
4796
5414
|
}
|
|
5415
|
+
const buildReport = (error) => {
|
|
5416
|
+
var _a2, _b2, _c2, _d2;
|
|
5417
|
+
if (error) {
|
|
5418
|
+
(_b2 = (_a2 = this.callbacks).onError) == null ? void 0 : _b2.call(_a2, error);
|
|
5419
|
+
} else {
|
|
5420
|
+
const checkReport = buildCheckReport2();
|
|
5421
|
+
let comparisonReport;
|
|
5422
|
+
if (this.config.comparison) {
|
|
5423
|
+
comparisonReport = {
|
|
5424
|
+
testReports: buildComparisonTestReports(),
|
|
5425
|
+
perfReportL: this.perfStatsL.toReport(),
|
|
5426
|
+
perfReportR: this.perfStatsR.toReport()
|
|
5427
|
+
};
|
|
5428
|
+
}
|
|
5429
|
+
(_d2 = (_c2 = this.callbacks).onComplete) == null ? void 0 : _d2.call(_c2, {
|
|
5430
|
+
checkReport,
|
|
5431
|
+
comparisonReport
|
|
5432
|
+
});
|
|
5433
|
+
}
|
|
5434
|
+
};
|
|
4797
5435
|
let tasksCompleted = 0;
|
|
4798
5436
|
let dataTaskId = 1;
|
|
4799
5437
|
for (const dataRequest of dataRequests) {
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
(
|
|
4804
|
-
|
|
5438
|
+
const task = {
|
|
5439
|
+
key: `suite-runner-${dataTaskId++}`,
|
|
5440
|
+
kind: "suite-runner",
|
|
5441
|
+
process: (bundleModels) => __async(this, null, function* () {
|
|
5442
|
+
var _a2, _b2;
|
|
5443
|
+
this.pendingTaskKeys.delete(task.key);
|
|
5444
|
+
yield this.processRequest(dataRequest, bundleModels);
|
|
5445
|
+
tasksCompleted++;
|
|
5446
|
+
(_b2 = (_a2 = this.callbacks).onProgress) == null ? void 0 : _b2.call(_a2, tasksCompleted / taskCount);
|
|
5447
|
+
if (tasksCompleted === taskCount) {
|
|
5448
|
+
buildReport();
|
|
5449
|
+
}
|
|
5450
|
+
})
|
|
5451
|
+
};
|
|
5452
|
+
this.taskQueue.addTask(task);
|
|
5453
|
+
this.pendingTaskKeys.add(task.key);
|
|
4805
5454
|
}
|
|
4806
5455
|
}
|
|
4807
|
-
processRequest(request) {
|
|
5456
|
+
processRequest(request, bundleModels) {
|
|
4808
5457
|
return __async(this, null, function* () {
|
|
4809
|
-
var _a, _b;
|
|
4810
5458
|
const datasetKeySet = /* @__PURE__ */ new Set();
|
|
4811
5459
|
for (const dataTask of request.dataTasks) {
|
|
4812
5460
|
datasetKeySet.add(dataTask.datasetKey);
|
|
@@ -4821,8 +5469,8 @@ var SuiteRunner = class {
|
|
|
4821
5469
|
}
|
|
4822
5470
|
});
|
|
4823
5471
|
}
|
|
4824
|
-
const bundleModelL =
|
|
4825
|
-
const bundleModelR =
|
|
5472
|
+
const bundleModelL = bundleModels.L;
|
|
5473
|
+
const bundleModelR = bundleModels.R;
|
|
4826
5474
|
const [datasetsResultL, datasetsResultR] = yield Promise.all([
|
|
4827
5475
|
getDatasets(bundleModelL, request.scenarioSpecL),
|
|
4828
5476
|
getDatasets(bundleModelR, request.scenarioSpecR)
|
|
@@ -4846,22 +5494,29 @@ var SuiteRunner = class {
|
|
|
4846
5494
|
});
|
|
4847
5495
|
}
|
|
4848
5496
|
};
|
|
4849
|
-
function
|
|
4850
|
-
const suiteRunner = new SuiteRunner(config, callbacks);
|
|
5497
|
+
function runSuiteWithTaskQueue(config, taskQueue, callbacks, options) {
|
|
5498
|
+
const suiteRunner = new SuiteRunner(config, taskQueue, callbacks);
|
|
4851
5499
|
suiteRunner.start(options);
|
|
4852
5500
|
return () => {
|
|
4853
5501
|
suiteRunner.cancel();
|
|
4854
5502
|
};
|
|
4855
5503
|
}
|
|
5504
|
+
function runSuite(config, callbacks, options) {
|
|
5505
|
+
const taskQueue = TaskQueue.getInstance();
|
|
5506
|
+
return runSuiteWithTaskQueue(config, taskQueue, callbacks, options);
|
|
5507
|
+
}
|
|
4856
5508
|
|
|
4857
5509
|
// src/suite/suite-reporting.ts
|
|
4858
|
-
function suiteSummaryFromReport(suiteReport) {
|
|
5510
|
+
function suiteSummaryFromReport(suiteReport, elapsedMillis) {
|
|
4859
5511
|
const checkSummary = checkSummaryFromReport(suiteReport.checkReport);
|
|
4860
5512
|
let comparisonSummary;
|
|
4861
5513
|
if (suiteReport.comparisonReport) {
|
|
4862
5514
|
comparisonSummary = comparisonSummaryFromReport(suiteReport.comparisonReport);
|
|
4863
5515
|
}
|
|
5516
|
+
const date = (/* @__PURE__ */ new Date()).toISOString();
|
|
4864
5517
|
return {
|
|
5518
|
+
date,
|
|
5519
|
+
elapsed: elapsedMillis,
|
|
4865
5520
|
checkSummary,
|
|
4866
5521
|
comparisonSummary
|
|
4867
5522
|
};
|
|
@@ -4870,20 +5525,27 @@ function suiteSummaryFromReport(suiteReport) {
|
|
|
4870
5525
|
0 && (module.exports = {
|
|
4871
5526
|
CheckDataCoordinator,
|
|
4872
5527
|
ComparisonDataCoordinator,
|
|
4873
|
-
PerfRunner,
|
|
4874
5528
|
PerfStats,
|
|
4875
5529
|
categorizeComparisonTestSummaries,
|
|
4876
5530
|
checkReportFromSummary,
|
|
4877
5531
|
checkSummaryFromReport,
|
|
4878
5532
|
comparisonSummaryFromReport,
|
|
5533
|
+
createCheckDataCoordinator,
|
|
5534
|
+
createCheckDataCoordinatorForTests,
|
|
5535
|
+
createComparisonDataCoordinator,
|
|
4879
5536
|
createConfig,
|
|
4880
5537
|
datasetMessage,
|
|
5538
|
+
decodeImplVars,
|
|
4881
5539
|
diffDatasets,
|
|
4882
5540
|
diffGraphs,
|
|
5541
|
+
encodeImplVars,
|
|
4883
5542
|
getScoresForTestSummaries,
|
|
4884
5543
|
predicateMessage,
|
|
5544
|
+
runPerf,
|
|
4885
5545
|
runSuite,
|
|
5546
|
+
runTrace,
|
|
4886
5547
|
scenarioMessage,
|
|
4887
|
-
suiteSummaryFromReport
|
|
5548
|
+
suiteSummaryFromReport,
|
|
5549
|
+
testSummaryFromReport
|
|
4888
5550
|
});
|
|
4889
5551
|
//# sourceMappingURL=index.cjs.map
|