assertthat
Version:
assertthat provides fluent TDD.
161 lines (160 loc) • 6.65 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.compareArrays = void 0;
const compare_1 = require("../typeAware/compare");
const typedescriptor_1 = require("typedescriptor");
const maximumDiffTableSize_1 = require("../../constants/maximumDiffTableSize");
const simplifyDiff_1 = require("../../diffs/forArrays/simplifyDiff");
const size_1 = require("../../size/typeAware/size");
const ArrayDiff_1 = require("../../diffs/forArrays/ArrayDiff");
const EqualDiff_1 = require("../../diffs/EqualDiff");
const compareArraysLinearly = function (actual, expected) {
const diff = (0, ArrayDiff_1.arrayDiff)({
segments: [],
cost: 0
});
for (let i = 0; i < Math.max(actual.length, expected.length); i++) {
const actualItem = actual[i];
const expectedItem = expected[i];
if ((0, typedescriptor_1.isUndefined)(actualItem)) {
diff.segments.push({
omission: [expectedItem],
cost: (0, size_1.size)(expectedItem)
});
continue;
}
if ((0, typedescriptor_1.isUndefined)(expectedItem)) {
diff.segments.push({
addition: [actualItem],
cost: (0, size_1.size)(actualItem)
});
continue;
}
const subDiff = (0, compare_1.compare)(actualItem, expectedItem);
if ((0, EqualDiff_1.isEqualDiff)(subDiff)) {
diff.segments.push({
equal: [actualItem],
cost: 0
});
}
else {
diff.segments.push({
change: [subDiff],
cost: subDiff.cost
});
}
}
if (diff.cost === 0) {
return (0, EqualDiff_1.equalDiff)({ value: actual });
}
return (0, simplifyDiff_1.simplifyDiff)(diff);
};
const compareArraysBestMatch = function (actual, expected) {
const results = new Map();
results.set('-1|-1', (0, ArrayDiff_1.arrayDiff)({
segments: [],
cost: 0
}));
for (let indexActual = 0; indexActual < actual.length; indexActual++) {
const segment = {
addition: [],
cost: 0
};
for (let index = 0; index <= indexActual; index++) {
segment.addition.push(actual[index]);
segment.cost += (0, size_1.size)(actual[index]);
}
results.set(`${indexActual}|-1`, (0, ArrayDiff_1.arrayDiff)({
segments: [segment],
cost: segment.cost
}));
}
for (let indexExpected = 0; indexExpected < expected.length; indexExpected++) {
const segment = {
omission: [],
cost: 0
};
for (let index = 0; index <= indexExpected; index++) {
segment.omission.push(expected[index]);
segment.cost += (0, size_1.size)(expected[index]);
}
results.set(`-1|${indexExpected}`, (0, ArrayDiff_1.arrayDiff)({
segments: [segment],
cost: segment.cost
}));
}
for (const [indexActual, elementActual] of actual.entries()) {
for (const [indexExpected, elementExpected] of expected.entries()) {
const maybeEqualPreviousDiff = results.get(`${indexActual - 1}|${indexExpected - 1}`);
const maybeEqualCurrentDiff = (0, compare_1.compare)(elementActual, elementExpected);
const maybeEqualCost = maybeEqualPreviousDiff.cost + maybeEqualCurrentDiff.cost;
const omissionPreviousDiff = results.get(`${indexActual}|${indexExpected - 1}`);
const omissionCost = omissionPreviousDiff.cost + (0, size_1.size)(elementExpected);
const additionPreviousDiff = results.get(`${indexActual - 1}|${indexExpected}`);
const additionCost = additionPreviousDiff.cost + (0, size_1.size)(elementActual);
if (maybeEqualCost <= omissionCost && maybeEqualCost <= additionCost) {
if (maybeEqualCurrentDiff.cost === 0) {
results.set(`${indexActual}|${indexExpected}`, (0, ArrayDiff_1.arrayDiff)({
segments: [
...maybeEqualPreviousDiff.segments,
{
equal: [elementActual],
cost: 0
}
],
cost: maybeEqualCost
}));
}
else {
results.set(`${indexActual}|${indexExpected}`, (0, ArrayDiff_1.arrayDiff)({
segments: [
...maybeEqualPreviousDiff.segments,
{
change: [maybeEqualCurrentDiff],
cost: maybeEqualCurrentDiff.cost
}
],
cost: maybeEqualCost
}));
}
}
else if (omissionCost <= additionCost) {
results.set(`${indexActual}|${indexExpected}`, (0, ArrayDiff_1.arrayDiff)({
segments: [
...omissionPreviousDiff.segments,
{
omission: [elementExpected],
cost: (0, size_1.size)(elementExpected)
}
],
cost: omissionCost
}));
}
else {
results.set(`${indexActual}|${indexExpected}`, (0, ArrayDiff_1.arrayDiff)({
segments: [
...additionPreviousDiff.segments,
{
addition: [elementActual],
cost: (0, size_1.size)(elementActual)
}
],
cost: additionCost
}));
}
results.delete(`${indexActual - 1}|${indexExpected - 1}`);
}
}
const diff = results.get(`${actual.length - 1}|${expected.length - 1}`);
if (diff.cost === 0) {
return (0, EqualDiff_1.equalDiff)({ value: actual });
}
return (0, simplifyDiff_1.simplifyDiff)(results.get(`${actual.length - 1}|${expected.length - 1}`));
};
const compareArrays = function (actual, expected) {
if (actual.length * expected.length > maximumDiffTableSize_1.maximumDiffTableSize) {
return compareArraysLinearly(actual, expected);
}
return compareArraysBestMatch(actual, expected);
};
exports.compareArrays = compareArrays;