UNPKG

@jawis/jatec

Version:
406 lines (405 loc) 11.8 kB
"use strict"; 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; };