@jawis/jatec
Version:
Common for jate view and server.
406 lines (405 loc) • 11.8 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.mergeTestLogsAndRogue_helper_by_ref = exports.mergeTestLogsAndRogue_map_testlog = exports.mergeTestLogsAndRogue = exports.flatToTestExpLogs_compat = exports.getClientTestReport = exports.getJatesTestReport = exports.getTestData = exports.zipObjects = exports.zipTestLogs = exports.getTestStatus = exports.testErrorLogsEqual = exports.testLogsEqual = exports.addErrMsgToTestLog = exports.addReturnToTestLogs = exports.errMsgAndReturnToTestLog = exports.errorToTestLog = exports.errorToTestResult = exports.testLogStatus = exports.testLogOrder = void 0;
const deep_equal_1 = __importDefault(require("deep-equal"));
const _jab_1 = require("@jawis/jab");
const testCurLogSystemKeys = ["err", "return", "chk", "user"];
exports.testLogOrder = [
"chk",
"err",
"stderr",
"console.error",
"child.stderr",
"stdout",
"console.log",
"child.stdout",
"imp",
];
exports.testLogStatus = {
rogue: 0,
chk: 1,
err: 2,
stderr: 2,
"console.error": 2,
"child.stderr": 2,
stdout: 3,
"console.log": 3,
"child.stdout": 3,
imp: 4,
return: 5,
unknown: 6,
};
/**
*
*/
const errorToTestResult = (error, extraInfo = [], extraErrorMsg) => ({ cur: (0, exports.errorToTestLog)(error, extraInfo, extraErrorMsg) });
exports.errorToTestResult = errorToTestResult;
/**
* - Extra error message is shown first.
*/
const errorToTestLog = (error, extraInfo = [], extraErrorMsg) => {
const data = (0, _jab_1.unknownToErrorData)(error, extraInfo);
if (extraErrorMsg === undefined) {
return { err: [data], user: {} };
}
else {
return {
err: [
{
msg: extraErrorMsg,
info: [],
stack: { type: "node", stack: "dummy" },
},
data,
],
user: {},
};
}
};
exports.errorToTestLog = errorToTestLog;
/**
* - testReturn must be cloned, already.
*/
const errMsgAndReturnToTestLog = (msg, testReturn) => (0, exports.addReturnToTestLogs)({
err: [{ msg, info: [], stack: { type: "node", stack: "dummy" } }],
user: {},
}, testReturn);
exports.errMsgAndReturnToTestLog = errMsgAndReturnToTestLog;
/**
* for the return result of the test case.
*
* - testReturn must be already cloned.
* - prefix can be used to make it a rogue log.
*/
const addReturnToTestLogs = (logs, testReturn) => {
if (testReturn !== undefined) {
return Object.assign(Object.assign({}, logs), { return: testReturn });
}
else {
return logs;
}
};
exports.addReturnToTestLogs = addReturnToTestLogs;
/**
*
*/
const addErrMsgToTestLog = (testLog, msg, info = []) => (Object.assign(Object.assign({}, testLog), { err: [
...(testLog.err || []),
{
msg,
info: (0, _jab_1.captureArrayEntries)(info),
stack: { type: "node", stack: "dummy" },
},
] }));
exports.addErrMsgToTestLog = addErrMsgToTestLog;
/**
*
*/
const testLogsEqual = (testLog) => {
switch (testLog.type) {
case "err":
return (0, exports.testErrorLogsEqual)(testLog);
case "return":
case "user":
return (0, deep_equal_1.default)(testLog.exp, testLog.cur, { strict: true });
case "chk":
//this is false, by 'definition'.
return false;
default:
return (0, _jab_1.assertNever)(testLog);
}
};
exports.testLogsEqual = testLogsEqual;
/**
*
*/
const testErrorLogsEqual = (testLog) => {
if (testLog.exp.length !== testLog.cur.length) {
return false;
}
for (let i = 0; i < testLog.exp.length; i++) {
if (testLog.exp[i] !== testLog.cur[i].msg) {
return false;
}
}
return true;
};
exports.testErrorLogsEqual = testErrorLogsEqual;
/**
*
*/
const getTestStatus = (testLogs) => {
let statusNo = Number.MAX_VALUE;
testLogs.forEach((log) => {
if (!(0, exports.testLogsEqual)(log)) {
const val = exports.testLogStatus[log.name] === undefined
? exports.testLogStatus["unknown"]
: exports.testLogStatus[log.name];
statusNo = Math.min(statusNo, val, 9);
}
});
return statusNo === Number.MAX_VALUE ? "." : statusNo;
};
exports.getTestStatus = getTestStatus;
/**
*
*/
const zipTestLogs = (exp, cur) => {
//
// assert root level (non-user) logs are known system logs.
//
Object.keys(exp).forEach((key) => {
if (!testCurLogSystemKeys.includes(key)) {
(0, _jab_1.err)("unknown key in exp log: ", key, exp);
}
});
Object.keys(cur).forEach((key) => {
if (!testCurLogSystemKeys.includes(key)) {
(0, _jab_1.err)("unknown key in cur log: ", key, cur);
}
});
//
// user logs
//
const testLogs = (0, exports.zipObjects)(exp.user, cur.user);
//
// system logs
//
if (exp.err || cur.err) {
testLogs.push({
type: "err",
name: "err",
exp: exp.err || [],
cur: cur.err || [],
});
}
if (exp.return || cur.return) {
testLogs.push({
type: "return",
name: "return",
exp: exp.return,
cur: cur.return,
});
}
if (cur.chk) {
testLogs.push(Object.assign({ type: "chk", name: "chk" }, cur.chk));
}
return testLogs;
};
exports.zipTestLogs = zipTestLogs;
/**
*
*/
const zipObjects = (exp, cur) => {
const res = [];
Object.keys(exp).forEach((name) => {
if (exp[name] === undefined) {
return;
}
res.push({
type: "user",
name,
exp: (0, _jab_1.def)(exp[name]),
cur: cur[name] || [],
});
});
Object.keys(cur).forEach((name) => {
if (cur[name] === undefined) {
return;
}
if (!(name in exp)) {
res.push({
type: "user",
name,
exp: [],
cur: (0, _jab_1.def)(cur[name]), //typescript can't see we check for undefined above.
});
}
});
return res;
};
exports.zipObjects = zipObjects;
/**
* - doesn't sort test logs. The client must do that itself.
*/
const getTestData = (exp, cur) => {
const testLogs = (0, exports.zipTestLogs)(exp, cur);
const status = (0, exports.getTestStatus)(testLogs);
return { testLogs, status };
};
exports.getTestData = getTestData;
/**
*
*/
const getJatesTestReport = (id, exp, result) => {
const data = (0, exports.getTestData)(exp, result.cur);
return {
id,
status: data.status,
zippedTestLogs: data.testLogs,
result: result,
};
};
exports.getJatesTestReport = getJatesTestReport;
/**
*
*/
const getClientTestReport = (id, exp, cur) => {
const data = (0, exports.getTestData)(exp, cur);
return {
id,
testLogs: data.testLogs,
status: data.status,
};
};
exports.getClientTestReport = getClientTestReport;
//
// old
//
/**
* compat for converting from old test log format.
*/
const flatToTestExpLogs_compat = (logs, isExp = true) => {
const copy = Object.assign({}, logs);
const res = { user: {} };
if (logs.err) {
res.err = logs.err.map((elm) => {
if (isExp) {
//compat for error logs, that have been saved in full.
return typeof elm === "string" ? elm : elm.msg;
}
else {
return elm;
}
});
delete copy.err;
}
if (logs.chk) {
if (isExp) {
throw new Error("chk log not allowed in exp logs");
}
else {
res.chk = logs.chk[0];
delete copy.chk;
}
}
if (logs.return) {
res.return = logs.return[0];
delete copy.return;
}
//add the rest, they are user logs.
res.user = copy;
return res;
};
exports.flatToTestExpLogs_compat = flatToTestExpLogs_compat;
/**
* note
* - very cumbersome.
* - actually no need to handle chk log, because Jarun never sends that.
*/
const mergeTestLogsAndRogue = (curZipped, tmp) => {
const rogue = testLogsToFlat(tmp);
const ordinaryCopy = Object.assign({}, rogue); //for ordinary logs
const rogueCopy = Object.assign({}, rogue); //for the extra rogue logs
//
// add to existing logs
//
const newZipped = curZipped.map((elm) => {
//ordinary entry
if (elm.name in ordinaryCopy) {
delete ordinaryCopy[elm.name];
return (0, exports.mergeTestLogsAndRogue_map_testlog)(rogue, elm, elm.name);
}
//entry previously stored with rogue
const logName = elm.name.replace(/rogue\./, "");
if (logName in rogueCopy) {
delete rogueCopy[logName];
return (0, exports.mergeTestLogsAndRogue_map_testlog)(rogue, elm, logName);
}
//nothing to do
return elm;
});
// create new ordinary entries.
(0, exports.mergeTestLogsAndRogue_helper_by_ref)(ordinaryCopy, newZipped);
// create new rogue entries.
(0, exports.mergeTestLogsAndRogue_helper_by_ref)(rogueCopy, newZipped, "rogue.");
// done
return newZipped;
};
exports.mergeTestLogsAndRogue = mergeTestLogsAndRogue;
/**
*
*/
const mergeTestLogsAndRogue_map_testlog = (flatRogue, elm, logName) => {
if (elm.type === "err") {
return Object.assign(Object.assign({}, elm), { cur: elm.cur.concat(flatRogue[logName]) });
}
if (elm.type === "return") {
return Object.assign(Object.assign({}, elm), { cur: flatRogue[logName] });
}
if (elm.type === "chk") {
console.log("not impl: mulitple rogue chk logs, silently dropped.");
return elm;
}
if (elm.type === "user") {
return Object.assign(Object.assign({}, elm), { cur: elm.cur.concat(flatRogue[logName]) });
}
throw (0, _jab_1.assertNever)(elm);
};
exports.mergeTestLogsAndRogue_map_testlog = mergeTestLogsAndRogue_map_testlog;
/**
*
*/
const mergeTestLogsAndRogue_helper_by_ref = (flatRogue, output, prefix = "") => {
Object.entries(flatRogue).forEach(([key, value]) => {
if (value === undefined) {
//we have to regard undefined as no value
return;
}
//add rogue log to ordinary logs (because there isn't an entry for the log type)
if (key === "err") {
output.push({
type: "err",
name: prefix + "err",
exp: [],
cur: value,
});
return;
}
if (key === "return") {
output.push({
type: "return",
name: prefix + "return",
cur: value,
});
return;
}
if (key === "chk") {
output.push(Object.assign({ type: "chk", name: prefix + "chk" }, value));
return;
}
//it must be a user log
output.push({
type: "user",
name: prefix + key,
exp: [],
cur: value,
});
});
};
exports.mergeTestLogsAndRogue_helper_by_ref = mergeTestLogsAndRogue_helper_by_ref;
/**
*
*/
const testLogsToFlat = (logs) => {
const res = Object.assign({}, logs);
const user = logs.user;
delete res.user;
Object.entries(user).forEach(([key, value]) => {
res[key] = value;
});
return res;
};