blob: 11923ca0fa98fdd00b1e813bbcfb87502dc2d323 [file] [log] [blame] [edit]
"use strict";
/*
* Copyright (C) 2025 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
const defaultEmptyMap = Object.freeze({});
class Params {
// Enable a detailed developer menu to change the current Params.
developerMode = false;
startAutomatically = false;
report = false;
startDelay = undefined;
testList = [];
testIterationCount = undefined;
testWorstCaseCount = undefined;
prefetchResources = true;
// Display group details.
groupDetails = false
RAMification = false;
dumpJSONResults = false;
dumpTestList = false;
// Override iteration and worst-case counts per workload.
// Example:
// testIterationCountMap = { "acorn-wtb": 5 };
testIterationCountMap = defaultEmptyMap;
testWorstCaseCountMap = defaultEmptyMap;
customPreIterationCode = undefined;
customPostIterationCode = undefined;
constructor(sourceParams = undefined) {
if (sourceParams)
this._copyFromSearchParams(sourceParams);
if (!this.developerMode)
Object.freeze(this);
}
_copyFromSearchParams(sourceParams) {
this.startAutomatically = this._parseBooleanParam(sourceParams, "startAutomatically");
this.developerMode = this._parseBooleanParam(sourceParams, "developerMode");
this.report = this._parseBooleanParam(sourceParams, "report");
this.prefetchResources = this._parseBooleanParam(sourceParams, "prefetchResources");
this.RAMification = this._parseBooleanParam(sourceParams, "RAMification");
this.dumpJSONResults = this._parseBooleanParam(sourceParams, "dumpJSONResults");
this.groupDetails = this._parseBooleanParam(sourceParams, "groupDetails");
this.dumpTestList = this._parseBooleanParam(sourceParams, "dumpTestList");
this.customPreIterationCode = this._parseStringParam(sourceParams, "customPreIterationCode");
this.customPostIterationCode = this._parseStringParam(sourceParams, "customPostIterationCode");
this.startDelay = this._parseIntParam(sourceParams, "startDelay", 0);
if (!this.startDelay) {
if (this.report)
this.startDelay = 4000;
if (this.startAutomatically)
this.startDelay = 100;
}
this.testList = this._parseOneOf(sourceParams, ["testList", "tag", "tags", "test", "tests"], this._parseTestListParam);
this.testIterationCount = this._parseOneOf(sourceParams, ["testIterationCount", "iterationCount", "iterations" ], this._parseIntParam, 1);
this.testWorstCaseCount = this._parseOneOf(sourceParams, ["testWorstCaseCount", "worstCaseCount", "worst"], this._parseIntParam, 1);
const unused = Array.from(sourceParams.keys());
if (unused.length > 0)
console.error("Got unused source params", unused);
}
_parseOneOf(sourceParams, paramKeys, parseFunction, ...args) {
const defaultParamKey = paramKeys[0]
let result = undefined;
let parsedParamKey = undefined;
for (const paramKey of paramKeys) {
if (!sourceParams.has(paramKey)) {
continue;
}
const parseResult = parseFunction.call(this, sourceParams, paramKey, ...args);
if (parsedParamKey) {
throw new Error(`Cannot parse ${paramKey}, overriding previous "${parsedParamKey}" value ${JSON.stringify(result)} with ${JSON.stringify(parseResult)}`)
}
parsedParamKey = paramKey;
result = parseResult;
}
if (!parsedParamKey) {
return DefaultJetStreamParams[defaultParamKey];
}
return result;
}
_parseTestListParam(sourceParams, key) {
if (!sourceParams.has(key))
return this.testList;
let testList = [];
if (sourceParams?.getAll) {
for (const param of sourceParams?.getAll(key)) {
testList.push(...param.split(","));
}
} else {
// fallback for cli sourceParams which is just a Map;
testList = sourceParams.get(key).split(",");
}
testList = testList.map(each => each.trim());
sourceParams.delete(key);
return testList;
}
_parseStringParam(sourceParams, paramKey) {
if (!sourceParams.has(paramKey))
return DefaultJetStreamParams[paramKey];
const value = sourceParams.get(paramKey);
sourceParams.delete(paramKey);
return value;
}
_parseBooleanParam(sourceParams, paramKey) {
if (!sourceParams.has(paramKey))
return DefaultJetStreamParams[paramKey];
const rawValue = sourceParams.get(paramKey);;
sourceParams.delete(paramKey);
const value = rawValue.toLowerCase();
return !(value === "false" || value === "0");
}
_parseIntParam(sourceParams, paramKey, minValue) {
if (!sourceParams.has(paramKey))
return DefaultJetStreamParams[paramKey];
const parsedValue = this._parseInt(sourceParams.get(paramKey), paramKey);
if (parsedValue < minValue)
throw new Error(`Invalid ${paramKey} param: '${parsedValue}', value must be >= ${minValue}.`);
sourceParams.delete(paramKey);
return parsedValue;
}
_parseInt(value, errorMessage) {
const number = Number(value);
if (!Number.isInteger(number) && errorMessage)
throw new Error(`Invalid ${errorMessage} param: '${value}', expected int.`);
return parseInt(number);
}
get isDefault() {
return this === DefaultJetStreamParams;
}
get nonDefaultParams() {
const diff = Object.create(null);
for (const [key, value] of Object.entries(this)) {
const defaultValue = DefaultJetStreamParams[key]
if (value == defaultValue) continue;
if (value?.length == 0 && defaultValue?.length == 0) continue;
diff[key] = value;
}
return diff;
}
}
const DefaultJetStreamParams = new Params();
let maybeCustomParams = DefaultJetStreamParams;
if (globalThis?.JetStreamParamsSource) {
try {
maybeCustomParams = new Params(globalThis?.JetStreamParamsSource);
// We might have parsed the same values again, do a poor-mans deep-equals:
if (JSON.stringify(maybeCustomParams) === JSON.stringify(DefaultJetStreamParams)) {
maybeCustomParams = DefaultJetStreamParams
}
} catch (e) {
console.error("Invalid Params", e, "\nUsing defaults as fallback:", maybeCustomParams);
}
}
const JetStreamParams = maybeCustomParams;