From b8c233b1bbc0b097d28fbe20233d6d86a41e1a9c Mon Sep 17 00:00:00 2001 From: Boming Zhang Date: Sat, 16 Nov 2024 03:07:12 -0500 Subject: [PATCH] test(parser/diff): add myers diff test --- internal/parser/diff/diff_test.go | 69 +++++++++++++++++++++++++++++++ internal/parser/diff/parser.go | 23 ++++++----- 2 files changed, 82 insertions(+), 10 deletions(-) create mode 100644 internal/parser/diff/diff_test.go diff --git a/internal/parser/diff/diff_test.go b/internal/parser/diff/diff_test.go new file mode 100644 index 0000000..09ba6fe --- /dev/null +++ b/internal/parser/diff/diff_test.go @@ -0,0 +1,69 @@ +package diff + +import ( + "reflect" + "testing" +) + +func TestMyersDiff(t *testing.T) { + tests := []struct { + name string + src []string + dst []string + compareSpace bool + expected []operation + }{ + { + name: "Insert operation", + src: []string{"a", "b"}, + dst: []string{"a", "b", "c"}, + compareSpace: true, + expected: []operation{MOVE, MOVE, INSERT}, + }, + { + name: "Delete operation", + src: []string{"a", "b", "c"}, + dst: []string{"a", "b"}, + compareSpace: true, + expected: []operation{MOVE, MOVE, DELETE}, + }, + { + name: "No changes", + src: []string{"a", "b", "c"}, + dst: []string{"a", "b", "c"}, + compareSpace: true, + expected: []operation{MOVE, MOVE, MOVE}, + }, + { + name: "Move operation", + src: []string{"a", "b", "c"}, + dst: []string{"c", "a", "b"}, + compareSpace: true, + expected: []operation{INSERT, MOVE, MOVE, DELETE}, + }, + { + name: "Ignore whitespace differences", + src: []string{"a ", "b"}, + dst: []string{"a", "b"}, + compareSpace: false, + expected: []operation{MOVE, MOVE}, + }, + { + name: "Consider whitespace differences", + src: []string{"a ", "b"}, + dst: []string{"a", "b"}, + compareSpace: true, + expected: []operation{DELETE, INSERT, MOVE}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + result := myersDiff(test.src, test.dst, test.compareSpace) + if !reflect.DeepEqual(result, test.expected) { + t.Errorf("myersDiff(%v, %v, %v) = %v; want %v", + test.src, test.dst, test.compareSpace, result, test.expected) + } + }) + } +} diff --git a/internal/parser/diff/parser.go b/internal/parser/diff/parser.go index 14230c4..89a5780 100644 --- a/internal/parser/diff/parser.go +++ b/internal/parser/diff/parser.go @@ -64,7 +64,7 @@ func (*Diff) Run(results []stage.ExecutorResult, confAny any) ( "actual length", len(result.Files[output.FileName]), "answer length", len(string(answer))) // If no difference, assign score - if compareChars(string(answer), result.Files[output.FileName], + if compareStrings(string(answer), result.Files[output.FileName], output.CompareSpace) { score += output.Score comment += conf.PassComment @@ -82,7 +82,8 @@ func (*Diff) Run(results []stage.ExecutorResult, confAny any) ( result.Files[output.FileName], "\n") // Generate Myers diff - diffOps := myersDiff(stdoutLines, resultLines) + diffOps := myersDiff(stdoutLines, resultLines, + output.CompareSpace) if output.MaxDiffLength == 0 { // real default value output.MaxDiffLength = 2048 } @@ -108,13 +109,13 @@ func (*Diff) Run(results []stage.ExecutorResult, confAny any) ( return res, forceQuit, nil } -// compareChars compares two strings character by character, optionally ignoring whitespace. -func compareChars(stdout, result string, compareSpace bool) bool { +// compareStrings compares two strings character by character, optionally ignoring whitespace. +func compareStrings(str1, str2 string, compareSpace bool) bool { if !compareSpace { - stdout = removeSpace(stdout) - result = removeSpace(result) + str1 = removeSpace(str1) + str2 = removeSpace(str2) } - return stdout == result + return str1 == str2 } // removeSpace removes all whitespace characters from the string. @@ -130,7 +131,7 @@ func removeSpace(s string) string { // myersDiff computes the Myers' diff between two slices of strings. // src: https://github.com/cj1128/myers-diff/blob/master/main.go -func myersDiff(src, dst []string) []operation { +func myersDiff(src, dst []string, compareSpace bool) []operation { n := len(src) m := len(dst) max := n + m @@ -144,7 +145,9 @@ loop: if d == 0 { t := 0 - for len(src) > t && len(dst) > t && src[t] == dst[t] { + for len(src) > t && + len(dst) > t && + compareStrings(src[t], dst[t], compareSpace) { t += 1 } v[0] = t @@ -165,7 +168,7 @@ loop: y = x - k - for x < n && y < m && src[x] == dst[y] { + for x < n && y < m && compareStrings(src[x], dst[y], compareSpace) { x, y = x+1, y+1 }