Skip to content

Commit 0278e91

Browse files
add test diff + Diff.init() (#5)
1 parent bf502b7 commit 0278e91

1 file changed

Lines changed: 128 additions & 0 deletions

File tree

DiffMatchPatch.zig

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ pub const Diff = struct {
2828
});
2929
}
3030

31+
pub fn init(operation: Operation, text: []const u8) Diff {
32+
return .{ .operation = operation, .text = text };
33+
}
3134
pub fn eql(a: Diff, b: Diff) bool {
3235
return a.operation == b.operation and std.mem.eql(u8, a.text, b.text);
3336
}
@@ -1420,3 +1423,128 @@ test diffCharsToLines {
14201423

14211424
// TODO: Implement exhaustive tests
14221425
}
1426+
1427+
fn rebuildtexts(allocator: std.mem.Allocator, diffs: std.ArrayListUnmanaged(Diff)) ![2][]const u8 {
1428+
var text = [2]std.ArrayList(u8){
1429+
std.ArrayList(u8).init(allocator),
1430+
std.ArrayList(u8).init(allocator),
1431+
};
1432+
1433+
for (diffs.items) |myDiff| {
1434+
if (myDiff.operation != .insert) {
1435+
try text[0].appendSlice(myDiff.text);
1436+
}
1437+
if (myDiff.operation != .delete) {
1438+
try text[1].appendSlice(myDiff.text);
1439+
}
1440+
}
1441+
return .{
1442+
try text[0].toOwnedSlice(),
1443+
try text[1].toOwnedSlice(),
1444+
};
1445+
}
1446+
1447+
const talloc = std.testing.allocator;
1448+
test diff {
1449+
// Perform a trivial diff.
1450+
var diffs = std.ArrayListUnmanaged(Diff){};
1451+
defer diffs.deinit(talloc);
1452+
var this = DiffMatchPatch{};
1453+
try std.testing.expectEqualDeep(diffs, try this.diff(talloc, "", "", false)); // diff: Null case.
1454+
1455+
diffs.items.len = 0;
1456+
try diffs.appendSlice(talloc, &.{Diff.init(.equal, "abc")});
1457+
try std.testing.expectEqualDeep(diffs, try this.diff(talloc, "abc", "abc", false)); // diff: Equality.
1458+
1459+
diffs.items.len = 0;
1460+
try diffs.appendSlice(talloc, &.{ Diff.init(.equal, "ab"), Diff.init(.insert, "123"), Diff.init(.equal, "c") });
1461+
try std.testing.expectEqualDeep(diffs, try this.diff(talloc, "abc", "ab123c", false)); // diff: Simple insertion.
1462+
1463+
diffs.items.len = 0;
1464+
try diffs.appendSlice(talloc, &.{ Diff.init(.equal, "a"), Diff.init(.delete, "123"), Diff.init(.equal, "bc") });
1465+
try std.testing.expectEqualDeep(diffs, try this.diff(talloc, "a123bc", "abc", false)); // diff: Simple deletion.
1466+
1467+
diffs.items.len = 0;
1468+
try diffs.appendSlice(talloc, &.{ Diff.init(.equal, "a"), Diff.init(.insert, "123"), Diff.init(.equal, "b"), Diff.init(.insert, "456"), Diff.init(.equal, "c") });
1469+
try std.testing.expectEqualDeep(diffs, try this.diff(talloc, "abc", "a123b456c", false)); // diff: Two insertions.
1470+
1471+
diffs.items.len = 0;
1472+
try diffs.appendSlice(talloc, &.{ Diff.init(.equal, "a"), Diff.init(.delete, "123"), Diff.init(.equal, "b"), Diff.init(.delete, "456"), Diff.init(.equal, "c") });
1473+
try std.testing.expectEqualDeep(diffs, try this.diff(talloc, "a123b456c", "abc", false)); // diff: Two deletions.
1474+
1475+
// Perform a real diff.
1476+
// Switch off the timeout.
1477+
this.diff_timeout = 0;
1478+
diffs.items.len = 0;
1479+
try diffs.appendSlice(talloc, &.{ Diff.init(.delete, "a"), Diff.init(.insert, "b") });
1480+
try std.testing.expectEqualDeep(diffs, try this.diff(talloc, "a", "b", false)); // diff: Simple case #1.
1481+
1482+
diffs.items.len = 0;
1483+
try diffs.appendSlice(talloc, &.{ Diff.init(.delete, "Apple"), Diff.init(.insert, "Banana"), Diff.init(.equal, "s are a"), Diff.init(.insert, "lso"), Diff.init(.equal, " fruit.") });
1484+
try std.testing.expectEqualDeep(diffs, try this.diff(talloc, "Apples are a fruit.", "Bananas are also fruit.", false)); // diff: Simple case #2.
1485+
1486+
diffs.items.len = 0;
1487+
try diffs.appendSlice(talloc, &.{ Diff.init(.delete, "a"), Diff.init(.insert, "\u{0680}"), Diff.init(.equal, "x"), Diff.init(.delete, "\t"), Diff.init(.insert, "\x00") });
1488+
try std.testing.expectEqualDeep(diffs, try this.diff(talloc, "ax\t", "\u{0680}x\x00", false)); // diff: Simple case #3.
1489+
1490+
diffs.items.len = 0;
1491+
try diffs.appendSlice(talloc, &.{ Diff.init(.delete, "1"), Diff.init(.equal, "a"), Diff.init(.delete, "y"), Diff.init(.equal, "b"), Diff.init(.delete, "2"), Diff.init(.insert, "xab") });
1492+
try std.testing.expectEqualDeep(diffs, try this.diff(talloc, "1ayb2", "abxab", false)); // diff: Overlap #1.
1493+
1494+
diffs.items.len = 0;
1495+
try diffs.appendSlice(talloc, &.{ Diff.init(.insert, "xaxcx"), Diff.init(.equal, "abc"), Diff.init(.delete, "y") });
1496+
try std.testing.expectEqualDeep(diffs, try this.diff(talloc, "abcy", "xaxcxabc", false)); // diff: Overlap #2.
1497+
1498+
diffs.items.len = 0;
1499+
try diffs.appendSlice(talloc, &.{ Diff.init(.delete, "ABCD"), Diff.init(.equal, "a"), Diff.init(.delete, "="), Diff.init(.insert, "-"), Diff.init(.equal, "bcd"), Diff.init(.delete, "="), Diff.init(.insert, "-"), Diff.init(.equal, "efghijklmnopqrs"), Diff.init(.delete, "EFGHIJKLMNOefg") });
1500+
try std.testing.expectEqualDeep(diffs, try this.diff(talloc, "ABCDa=bcd=efghijklmnopqrsEFGHIJKLMNOefg", "a-bcd-efghijklmnopqrs", false)); // diff: Overlap #3.
1501+
1502+
diffs.items.len = 0;
1503+
try diffs.appendSlice(talloc, &.{ Diff.init(.insert, " "), Diff.init(.equal, "a"), Diff.init(.insert, "nd"), Diff.init(.equal, " [[Pennsylvania]]"), Diff.init(.delete, " and [[New") });
1504+
try std.testing.expectEqualDeep(diffs, try this.diff(talloc, "a [[Pennsylvania]] and [[New", " and [[Pennsylvania]]", false)); // diff: Large equality.
1505+
1506+
this.diff_timeout = 100 * std.time.ms_per_s; // 100ms
1507+
// Increase the text lengths by 1024 times to ensure a timeout.
1508+
{
1509+
const a = "`Twas brillig, and the slithy toves\nDid gyre and gimble in the wabe:\nAll mimsy were the borogoves,\nAnd the mome raths outgrabe.\n" ** 10;
1510+
const b = "I am the very model of a modern major general,\nI've information vegetable, animal, and mineral,\nI know the kings of England, and I quote the fights historical,\nFrom Marathon to Waterloo, in order categorical.\n" ** 10;
1511+
const start_time = std.time.milliTimestamp();
1512+
_ = try this.diff(talloc, a, b, false); // Travis - TODO not sure what the third arg should be
1513+
const end_time = std.time.milliTimestamp();
1514+
// Test that we took at least the timeout period.
1515+
try std.testing.expect((this.diff_timeout * 1000) * 10000 <= end_time - start_time); // diff: Timeout min.
1516+
// Test that we didn't take forever (be forgiving).
1517+
// Theoretically this test could fail very occasionally if the
1518+
// OS task swaps or locks up for a second at the wrong moment.
1519+
try std.testing.expect((this.diff_timeout * 1000) * 10000 * 2 > end_time - start_time); // diff: Timeout max.
1520+
this.diff_timeout = 0;
1521+
}
1522+
{
1523+
// Test the linemode speedup.
1524+
// Must be long to pass the 100 char cutoff.
1525+
const a = "1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n";
1526+
const b = "abcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\nabcdefghij\n";
1527+
try std.testing.expectEqualDeep(try this.diff(talloc, a, b, true), try this.diff(talloc, a, b, false)); // diff: Simple line-mode.
1528+
}
1529+
{
1530+
const a = "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";
1531+
const b = "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij";
1532+
try std.testing.expectEqualDeep(try this.diff(talloc, a, b, true), try this.diff(talloc, a, b, false)); // diff: Single line-mode.
1533+
}
1534+
1535+
const a = "1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n1234567890\n";
1536+
const b = "abcdefghij\n1234567890\n1234567890\n1234567890\nabcdefghij\n1234567890\n1234567890\n1234567890\nabcdefghij\n1234567890\n1234567890\n1234567890\nabcdefghij\n";
1537+
const texts_linemode = try rebuildtexts(talloc, try this.diff(talloc, a, b, true));
1538+
defer {
1539+
talloc.free(texts_linemode[0]);
1540+
talloc.free(texts_linemode[1]);
1541+
}
1542+
const texts_textmode = try rebuildtexts(talloc, try this.diff(talloc, a, b, false));
1543+
defer {
1544+
talloc.free(texts_textmode[0]);
1545+
talloc.free(texts_textmode[1]);
1546+
}
1547+
try std.testing.expectEqualDeep(texts_textmode, texts_linemode); // diff: Overlap line-mode.
1548+
1549+
// Test null inputs -- not needed because nulls can't be passed in C#.
1550+
}

0 commit comments

Comments
 (0)