mongo/jstests/concurrency/fsm_libs/parse_config.js

99 lines
3.8 KiB
JavaScript

// Validate the config object and return a normalized copy of it.
// Normalized means all optional parameters are set to their default values,
// and any parameters that need to be coerced have been coerced.
export function parseConfig(config) {
config = Object.extend({}, config, true); // defensive deep copy
let allowedKeys = [
"data",
"iterations",
"passConnectionCache",
"setup",
"startState",
"states",
"teardown",
"threadCount",
"transitions",
];
Object.keys(config).forEach(function (key) {
assert.contains(
key,
allowedKeys,
"invalid config parameter: " + key + "; valid parameters are: " + tojson(allowedKeys),
);
});
assert(Number.isInteger(config.threadCount), "expected number of threads to be an integer");
assert.gt(config.threadCount, 0, "expected number of threads to be positive");
assert(Number.isInteger(config.iterations), "expected number of iterations to be an integer");
config.startState = config.startState || "init";
assert.eq("string", typeof config.startState);
assert.eq("object", typeof config.states);
assert.gt(Object.keys(config.states).length, 0);
Object.keys(config.states).forEach(function (k) {
assert.eq("function", typeof config.states[k], "config.states." + k + " is not a function");
if (config.passConnectionCache) {
assert.eq(
3,
config.states[k].length,
"if passConnectionCache is true, state functions should " +
"accept 3 parameters: db, collName, and connCache",
);
} else {
assert.eq(
2,
config.states[k].length,
"if passConnectionCache is false, state functions should " + "accept 2 parameters: db and collName",
);
}
});
// assert all states mentioned in config.transitions are present in config.states
assert.eq("object", typeof config.transitions);
assert.gt(Object.keys(config.transitions).length, 0);
Object.keys(config.transitions).forEach(function (fromState) {
assert(
config.states.hasOwnProperty(fromState),
"config.transitions contains a state not in config.states: " + fromState,
);
assert.gt(Object.keys(config.transitions[fromState]).length, 0);
Object.keys(config.transitions[fromState]).forEach(function (toState) {
assert(
config.states.hasOwnProperty(toState),
"config.transitions." + fromState + " contains a state not in config.states: " + toState,
);
assert.eq(
"number",
typeof config.transitions[fromState][toState],
"transitions." + fromState + "." + toState + " should be a number",
);
assert(
!isNaN(config.transitions[fromState][toState]),
"transitions." + fromState + "." + toState + " cannot be NaN",
);
});
});
config.setup = config.setup || function () {};
assert.eq("function", typeof config.setup);
config.teardown = config.teardown || function () {};
assert.eq("function", typeof config.teardown);
config.data = config.data || {};
assert.eq("object", typeof config.data);
assert.eq(false, config.data.hasOwnProperty("tid"), 'data object cannot redefine "tid"');
assert.eq(false, config.data.hasOwnProperty("iterations"), 'data object cannot redefine "iterations"');
assert.eq(false, config.data.hasOwnProperty("threadCount"), 'data object cannot redefine "threadCount"');
config.passConnectionCache = config.passConnectionCache || false;
assert.eq("boolean", typeof config.passConnectionCache);
return config;
}