fork of go-gitdiff with jj support
at main 5.1 kB view raw
1package gitdiff 2 3import ( 4 "bytes" 5 "fmt" 6 "os" 7 "path/filepath" 8 "slices" 9 "testing" 10) 11 12func TestFormatRoundtrip(t *testing.T) { 13 patches := []struct { 14 File string 15 SkipTextCompare bool 16 }{ 17 {File: "copy.patch"}, 18 {File: "copy_modify.patch"}, 19 {File: "delete.patch"}, 20 {File: "mode.patch"}, 21 {File: "mode_modify.patch"}, 22 {File: "modify.patch"}, 23 {File: "new.patch"}, 24 {File: "new_empty.patch"}, 25 {File: "new_mode.patch"}, 26 {File: "rename.patch"}, 27 {File: "rename_modify.patch"}, 28 29 // Due to differences between Go's 'encoding/zlib' package and the zlib 30 // C library, binary patches cannot be compared directly as the patch 31 // data is slightly different when re-encoded by Go. 32 {File: "binary_modify.patch", SkipTextCompare: true}, 33 {File: "binary_new.patch", SkipTextCompare: true}, 34 {File: "binary_modify_nodata.patch"}, 35 } 36 37 for _, patch := range patches { 38 t.Run(patch.File, func(t *testing.T) { 39 b, err := os.ReadFile(filepath.Join("testdata", "string", patch.File)) 40 if err != nil { 41 t.Fatalf("failed to read patch: %v", err) 42 } 43 44 original := assertParseSingleFile(t, b, "patch") 45 str := original.String() 46 47 if !patch.SkipTextCompare { 48 if string(b) != str { 49 t.Errorf("incorrect patch text\nexpected: %q\n actual: %q\n", string(b), str) 50 } 51 } 52 53 reparsed := assertParseSingleFile(t, []byte(str), "formatted patch") 54 assertFilesEqual(t, original, reparsed) 55 }) 56 } 57} 58 59func assertParseSingleFile(t *testing.T, b []byte, kind string) *File { 60 files, _, err := Parse(bytes.NewReader(b)) 61 if err != nil { 62 t.Fatalf("failed to parse %s: %v", kind, err) 63 } 64 if len(files) != 1 { 65 t.Fatalf("expected %s to contain a single files, but found %d", kind, len(files)) 66 } 67 return files[0] 68} 69 70func assertFilesEqual(t *testing.T, expected, actual *File) { 71 assertEqual(t, expected.OldName, actual.OldName, "OldName") 72 assertEqual(t, expected.NewName, actual.NewName, "NewName") 73 74 assertEqual(t, expected.IsNew, actual.IsNew, "IsNew") 75 assertEqual(t, expected.IsDelete, actual.IsDelete, "IsDelete") 76 assertEqual(t, expected.IsCopy, actual.IsCopy, "IsCopy") 77 assertEqual(t, expected.IsRename, actual.IsRename, "IsRename") 78 79 assertEqual(t, expected.OldMode, actual.OldMode, "OldMode") 80 assertEqual(t, expected.NewMode, actual.NewMode, "NewMode") 81 82 assertEqual(t, expected.OldOIDPrefix, actual.OldOIDPrefix, "OldOIDPrefix") 83 assertEqual(t, expected.NewOIDPrefix, actual.NewOIDPrefix, "NewOIDPrefix") 84 assertEqual(t, expected.Score, actual.Score, "Score") 85 86 if len(expected.TextFragments) == len(actual.TextFragments) { 87 for i := range expected.TextFragments { 88 prefix := fmt.Sprintf("TextFragments[%d].", i) 89 ef := expected.TextFragments[i] 90 af := actual.TextFragments[i] 91 92 assertEqual(t, ef.Comment, af.Comment, prefix+"Comment") 93 94 assertEqual(t, ef.OldPosition, af.OldPosition, prefix+"OldPosition") 95 assertEqual(t, ef.OldLines, af.OldLines, prefix+"OldLines") 96 97 assertEqual(t, ef.NewPosition, af.NewPosition, prefix+"NewPosition") 98 assertEqual(t, ef.NewLines, af.NewLines, prefix+"NewLines") 99 100 assertEqual(t, ef.LinesAdded, af.LinesAdded, prefix+"LinesAdded") 101 assertEqual(t, ef.LinesDeleted, af.LinesDeleted, prefix+"LinesDeleted") 102 103 assertEqual(t, ef.LeadingContext, af.LeadingContext, prefix+"LeadingContext") 104 assertEqual(t, ef.TrailingContext, af.TrailingContext, prefix+"TrailingContext") 105 106 if !slices.Equal(ef.Lines, af.Lines) { 107 t.Errorf("%sLines: expected %#v, actual %#v", prefix, ef.Lines, af.Lines) 108 } 109 } 110 } else { 111 t.Errorf("TextFragments: expected length %d, actual length %d", len(expected.TextFragments), len(actual.TextFragments)) 112 } 113 114 assertEqual(t, expected.IsBinary, actual.IsBinary, "IsBinary") 115 116 if expected.BinaryFragment != nil { 117 if actual.BinaryFragment == nil { 118 t.Errorf("BinaryFragment: expected non-nil, actual is nil") 119 } else { 120 ef := expected.BinaryFragment 121 af := expected.BinaryFragment 122 123 assertEqual(t, ef.Method, af.Method, "BinaryFragment.Method") 124 assertEqual(t, ef.Size, af.Size, "BinaryFragment.Size") 125 126 if !slices.Equal(ef.Data, af.Data) { 127 t.Errorf("BinaryFragment.Data: expected %#v, actual %#v", ef.Data, af.Data) 128 } 129 } 130 } else if actual.BinaryFragment != nil { 131 t.Errorf("BinaryFragment: expected nil, actual is non-nil") 132 } 133 134 if expected.ReverseBinaryFragment != nil { 135 if actual.ReverseBinaryFragment == nil { 136 t.Errorf("ReverseBinaryFragment: expected non-nil, actual is nil") 137 } else { 138 ef := expected.ReverseBinaryFragment 139 af := expected.ReverseBinaryFragment 140 141 assertEqual(t, ef.Method, af.Method, "ReverseBinaryFragment.Method") 142 assertEqual(t, ef.Size, af.Size, "ReverseBinaryFragment.Size") 143 144 if !slices.Equal(ef.Data, af.Data) { 145 t.Errorf("ReverseBinaryFragment.Data: expected %#v, actual %#v", ef.Data, af.Data) 146 } 147 } 148 } else if actual.ReverseBinaryFragment != nil { 149 t.Errorf("ReverseBinaryFragment: expected nil, actual is non-nil") 150 } 151} 152 153func assertEqual[T comparable](t *testing.T, expected, actual T, name string) { 154 if expected != actual { 155 t.Errorf("%s: expected %#v, actual %#v", name, expected, actual) 156 } 157}