summaryrefslogtreecommitdiff
path: root/pkg/gitdiff/file_header_test.go
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2026-01-30 17:18:31 -0700
committermo khan <mo@mokhan.ca>2026-01-30 17:18:31 -0700
commite4ed0342932b0aa741ee78d9e4fe135eba6e9ca7 (patch)
treef1e7f602cb86e78aedf04185b2c2e1428fc5b8f2 /pkg/gitdiff/file_header_test.go
parent83be9ddcf82e8a90ea50a9d54c1ebfc3e22ace16 (diff)
initial commit
Diffstat (limited to 'pkg/gitdiff/file_header_test.go')
-rw-r--r--pkg/gitdiff/file_header_test.go766
1 files changed, 0 insertions, 766 deletions
diff --git a/pkg/gitdiff/file_header_test.go b/pkg/gitdiff/file_header_test.go
deleted file mode 100644
index ef29833..0000000
--- a/pkg/gitdiff/file_header_test.go
+++ /dev/null
@@ -1,766 +0,0 @@
-package gitdiff
-
-import (
- "io"
- "os"
- "reflect"
- "testing"
-)
-
-func TestParseGitFileHeader(t *testing.T) {
- tests := map[string]struct {
- Input string
- Output *File
- Err bool
- }{
- "fileContentChange": {
- Input: `diff --git a/dir/file.txt b/dir/file.txt
-index 1c23fcc..40a1b33 100644
---- a/dir/file.txt
-+++ b/dir/file.txt
-@@ -2,3 +4,5 @@
-`,
- Output: &File{
- OldName: "dir/file.txt",
- NewName: "dir/file.txt",
- OldMode: os.FileMode(0100644),
- OldOIDPrefix: "1c23fcc",
- NewOIDPrefix: "40a1b33",
- },
- },
- "newFile": {
- Input: `diff --git a/dir/file.txt b/dir/file.txt
-new file mode 100644
-index 0000000..f5711e4
---- /dev/null
-+++ b/dir/file.txt
-`,
- Output: &File{
- NewName: "dir/file.txt",
- NewMode: os.FileMode(0100644),
- OldOIDPrefix: "0000000",
- NewOIDPrefix: "f5711e4",
- IsNew: true,
- },
- },
- "newEmptyFile": {
- Input: `diff --git a/empty.txt b/empty.txt
-new file mode 100644
-index 0000000..e69de29
-`,
- Output: &File{
- NewName: "empty.txt",
- NewMode: os.FileMode(0100644),
- OldOIDPrefix: "0000000",
- NewOIDPrefix: "e69de29",
- IsNew: true,
- },
- },
- "deleteFile": {
- Input: `diff --git a/dir/file.txt b/dir/file.txt
-deleted file mode 100644
-index 44cc321..0000000
---- a/dir/file.txt
-+++ /dev/null
-`,
- Output: &File{
- OldName: "dir/file.txt",
- OldMode: os.FileMode(0100644),
- OldOIDPrefix: "44cc321",
- NewOIDPrefix: "0000000",
- IsDelete: true,
- },
- },
- "changeMode": {
- Input: `diff --git a/file.sh b/file.sh
-old mode 100644
-new mode 100755
-`,
- Output: &File{
- OldName: "file.sh",
- NewName: "file.sh",
- OldMode: os.FileMode(0100644),
- NewMode: os.FileMode(0100755),
- },
- },
- "rename": {
- Input: `diff --git a/foo.txt b/bar.txt
-similarity index 100%
-rename from foo.txt
-rename to bar.txt
-`,
- Output: &File{
- OldName: "foo.txt",
- NewName: "bar.txt",
- Score: 100,
- IsRename: true,
- },
- },
- "copy": {
- Input: `diff --git a/file.txt b/copy.txt
-similarity index 100%
-copy from file.txt
-copy to copy.txt
-`,
- Output: &File{
- OldName: "file.txt",
- NewName: "copy.txt",
- Score: 100,
- IsCopy: true,
- },
- },
- "missingDefaultFilename": {
- Input: `diff --git a/foo.sh b/bar.sh
-old mode 100644
-new mode 100755
-`,
- Err: true,
- },
- "missingNewFilename": {
- Input: `diff --git a/file.txt b/file.txt
-index 1c23fcc..40a1b33 100644
---- a/file.txt
-`,
- Err: true,
- },
- "missingOldFilename": {
- Input: `diff --git a/file.txt b/file.txt
-index 1c23fcc..40a1b33 100644
-+++ b/file.txt
-`,
- Err: true,
- },
- "invalidHeaderLine": {
- Input: `diff --git a/file.txt b/file.txt
-index deadbeef
---- a/file.txt
-+++ b/file.txt
-`,
- Err: true,
- },
- "notGitHeader": {
- Input: `--- file.txt
-+++ file.txt
-@@ -0,0 +1 @@
-`,
- Output: nil,
- },
- }
-
- for name, test := range tests {
- t.Run(name, func(t *testing.T) {
- p := newTestParser(test.Input, true)
-
- f, err := p.ParseGitFileHeader()
- if test.Err {
- if err == nil || err == io.EOF {
- t.Fatalf("expected error parsing git file header, got %v", err)
- }
- return
- }
- if err != nil {
- t.Fatalf("unexpected error parsing git file header: %v", err)
- }
-
- if !reflect.DeepEqual(test.Output, f) {
- t.Errorf("incorrect file\nexpected: %+v\n actual: %+v", test.Output, f)
- }
- })
- }
-}
-
-func TestParseTraditionalFileHeader(t *testing.T) {
- tests := map[string]struct {
- Input string
- Output *File
- Err bool
- }{
- "fileContentChange": {
- Input: `--- dir/file_old.txt 2019-03-21 23:00:00.0 -0700
-+++ dir/file_new.txt 2019-03-21 23:30:00.0 -0700
-@@ -0,0 +1 @@
-`,
- Output: &File{
- OldName: "dir/file_new.txt",
- NewName: "dir/file_new.txt",
- },
- },
- "newFile": {
- Input: `--- /dev/null 1969-12-31 17:00:00.0 -0700
-+++ dir/file.txt 2019-03-21 23:30:00.0 -0700
-@@ -0,0 +1 @@
-`,
- Output: &File{
- NewName: "dir/file.txt",
- IsNew: true,
- },
- },
- "newFileTimestamp": {
- Input: `--- dir/file.txt 1969-12-31 17:00:00.0 -0700
-+++ dir/file.txt 2019-03-21 23:30:00.0 -0700
-@@ -0,0 +1 @@
-`,
- Output: &File{
- NewName: "dir/file.txt",
- IsNew: true,
- },
- },
- "deleteFile": {
- Input: `--- dir/file.txt 2019-03-21 23:30:00.0 -0700
-+++ /dev/null 1969-12-31 17:00:00.0 -0700
-@@ -0,0 +1 @@
-`,
- Output: &File{
- OldName: "dir/file.txt",
- IsDelete: true,
- },
- },
- "deleteFileTimestamp": {
- Input: `--- dir/file.txt 2019-03-21 23:30:00.0 -0700
-+++ dir/file.txt 1969-12-31 17:00:00.0 -0700
-@@ -0,0 +1 @@
-`,
- Output: &File{
- OldName: "dir/file.txt",
- IsDelete: true,
- },
- },
- "useShortestPrefixName": {
- Input: `--- dir/file.txt 2019-03-21 23:00:00.0 -0700
-+++ dir/file.txt~ 2019-03-21 23:30:00.0 -0700
-@@ -0,0 +1 @@
-`,
- Output: &File{
- OldName: "dir/file.txt",
- NewName: "dir/file.txt",
- },
- },
- "notTraditionalHeader": {
- Input: `diff --git a/dir/file.txt b/dir/file.txt
---- a/dir/file.txt
-+++ b/dir/file.txt
-`,
- Output: nil,
- },
- "noUnifiedFragment": {
- Input: `--- dir/file_old.txt 2019-03-21 23:00:00.0 -0700
-+++ dir/file_new.txt 2019-03-21 23:30:00.0 -0700
-context line
-+added line
-`,
- Output: nil,
- },
- }
-
- for name, test := range tests {
- t.Run(name, func(t *testing.T) {
- p := newTestParser(test.Input, true)
-
- f, err := p.ParseTraditionalFileHeader()
- if test.Err {
- if err == nil || err == io.EOF {
- t.Fatalf("expected error parsing traditional file header, got %v", err)
- }
- return
- }
- if err != nil {
- t.Fatalf("unexpected error parsing traditional file header: %v", err)
- }
-
- if !reflect.DeepEqual(test.Output, f) {
- t.Errorf("incorrect file\nexpected: %+v\n actual: %+v", test.Output, f)
- }
- })
- }
-}
-
-func TestCleanName(t *testing.T) {
- tests := map[string]struct {
- Input string
- Drop int
- Output string
- }{
- "alreadyClean": {
- Input: "a/b/c.txt", Output: "a/b/c.txt",
- },
- "doubleSlashes": {
- Input: "a//b/c.txt", Output: "a/b/c.txt",
- },
- "tripleSlashes": {
- Input: "a///b/c.txt", Output: "a/b/c.txt",
- },
- "dropPrefix": {
- Input: "a/b/c.txt", Drop: 2, Output: "c.txt",
- },
- "removeDoublesBeforeDrop": {
- Input: "a//b/c.txt", Drop: 1, Output: "b/c.txt",
- },
- }
-
- for name, test := range tests {
- t.Run(name, func(t *testing.T) {
- output := cleanName(test.Input, test.Drop)
- if output != test.Output {
- t.Fatalf("incorrect output: expected %q, actual %q", test.Output, output)
- }
- })
- }
-}
-
-func TestParseName(t *testing.T) {
- tests := map[string]struct {
- Input string
- Term byte
- Drop int
- Output string
- N int
- Err bool
- }{
- "singleUnquoted": {
- Input: "dir/file.txt", Output: "dir/file.txt", N: 12,
- },
- "singleQuoted": {
- Input: `"dir/file.txt"`, Output: "dir/file.txt", N: 14,
- },
- "quotedWithEscape": {
- Input: `"dir/\"quotes\".txt"`, Output: `dir/"quotes".txt`, N: 20,
- },
- "quotedWithSpaces": {
- Input: `"dir/space file.txt"`, Output: "dir/space file.txt", N: 20,
- },
- "tabTerminator": {
- Input: "dir/space file.txt\tfile2.txt", Term: '\t', Output: "dir/space file.txt", N: 18,
- },
- "dropPrefix": {
- Input: "a/dir/file.txt", Drop: 1, Output: "dir/file.txt", N: 14,
- },
- "unquotedWithSpaces": {
- Input: "dir/with spaces.txt", Output: "dir/with spaces.txt", N: 19,
- },
- "unquotedWithTrailingSpaces": {
- Input: "dir/with spaces.space ", Output: "dir/with spaces.space ", N: 23,
- },
- "devNull": {
- Input: "/dev/null", Term: '\t', Drop: 1, Output: "/dev/null", N: 9,
- },
- "newlineSeparates": {
- Input: "dir/file.txt\n", Output: "dir/file.txt", N: 12,
- },
- "emptyString": {
- Input: "", Err: true,
- },
- "emptyQuotedString": {
- Input: `""`, Err: true,
- },
- "unterminatedQuotes": {
- Input: `"dir/file.txt`, Err: true,
- },
- }
-
- for name, test := range tests {
- t.Run(name, func(t *testing.T) {
- output, n, err := parseName(test.Input, test.Term, test.Drop)
- if test.Err {
- if err == nil || err == io.EOF {
- t.Fatalf("expected error parsing name, but got %v", err)
- }
- return
- }
- if err != nil {
- t.Fatalf("unexpected error parsing name: %v", err)
- }
-
- if output != test.Output {
- t.Errorf("incorrect output: expected %q, actual: %q", test.Output, output)
- }
- if n != test.N {
- t.Errorf("incorrect next position: expected %d, actual %d", test.N, n)
- }
- })
- }
-}
-
-func TestParseGitHeaderData(t *testing.T) {
- tests := map[string]struct {
- InputFile *File
- Line string
- DefaultName string
-
- OutputFile *File
- End bool
- Err bool
- }{
- "fragementEndsParsing": {
- Line: "@@ -12,3 +12,2 @@\n",
- End: true,
- },
- "unknownEndsParsing": {
- Line: "GIT binary file\n",
- End: true,
- },
- "oldFileName": {
- Line: "--- a/dir/file.txt\n",
- OutputFile: &File{
- OldName: "dir/file.txt",
- },
- },
- "oldFileNameDevNull": {
- InputFile: &File{
- IsNew: true,
- },
- Line: "--- /dev/null\n",
- OutputFile: &File{
- IsNew: true,
- },
- },
- "oldFileNameInconsistent": {
- InputFile: &File{
- OldName: "dir/foo.txt",
- },
- Line: "--- a/dir/bar.txt\n",
- Err: true,
- },
- "oldFileNameExistingCreateMismatch": {
- InputFile: &File{
- OldName: "dir/foo.txt",
- IsNew: true,
- },
- Line: "--- /dev/null\n",
- Err: true,
- },
- "oldFileNameParsedCreateMismatch": {
- InputFile: &File{
- IsNew: true,
- },
- Line: "--- a/dir/file.txt\n",
- Err: true,
- },
- "oldFileNameMissing": {
- Line: "--- \n",
- Err: true,
- },
- "newFileName": {
- Line: "+++ b/dir/file.txt\n",
- OutputFile: &File{
- NewName: "dir/file.txt",
- },
- },
- "newFileNameDevNull": {
- InputFile: &File{
- IsDelete: true,
- },
- Line: "+++ /dev/null\n",
- OutputFile: &File{
- IsDelete: true,
- },
- },
- "newFileNameInconsistent": {
- InputFile: &File{
- NewName: "dir/foo.txt",
- },
- Line: "+++ b/dir/bar.txt\n",
- Err: true,
- },
- "newFileNameExistingDeleteMismatch": {
- InputFile: &File{
- NewName: "dir/foo.txt",
- IsDelete: true,
- },
- Line: "+++ /dev/null\n",
- Err: true,
- },
- "newFileNameParsedDeleteMismatch": {
- InputFile: &File{
- IsDelete: true,
- },
- Line: "+++ b/dir/file.txt\n",
- Err: true,
- },
- "newFileNameMissing": {
- Line: "+++ \n",
- Err: true,
- },
- "oldMode": {
- Line: "old mode 100644\n",
- OutputFile: &File{
- OldMode: os.FileMode(0100644),
- },
- },
- "oldModeWithTrailingSpace": {
- Line: "old mode 100644\r\n",
- OutputFile: &File{
- OldMode: os.FileMode(0100644),
- },
- },
- "invalidOldMode": {
- Line: "old mode rw\n",
- Err: true,
- },
- "newMode": {
- Line: "new mode 100755\n",
- OutputFile: &File{
- NewMode: os.FileMode(0100755),
- },
- },
- "newModeWithTrailingSpace": {
- Line: "new mode 100755\r\n",
- OutputFile: &File{
- NewMode: os.FileMode(0100755),
- },
- },
- "invalidNewMode": {
- Line: "new mode rwx\n",
- Err: true,
- },
- "deletedFileMode": {
- Line: "deleted file mode 100644\n",
- DefaultName: "dir/file.txt",
- OutputFile: &File{
- OldName: "dir/file.txt",
- OldMode: os.FileMode(0100644),
- IsDelete: true,
- },
- },
- "newFileMode": {
- Line: "new file mode 100755\n",
- DefaultName: "dir/file.txt",
- OutputFile: &File{
- NewName: "dir/file.txt",
- NewMode: os.FileMode(0100755),
- IsNew: true,
- },
- },
- "newFileModeWithTrailingSpace": {
- Line: "new file mode 100755\r\n",
- DefaultName: "dir/file.txt",
- OutputFile: &File{
- NewName: "dir/file.txt",
- NewMode: os.FileMode(0100755),
- IsNew: true,
- },
- },
- "copyFrom": {
- Line: "copy from dir/file.txt\n",
- OutputFile: &File{
- OldName: "dir/file.txt",
- IsCopy: true,
- },
- },
- "copyTo": {
- Line: "copy to dir/file.txt\n",
- OutputFile: &File{
- NewName: "dir/file.txt",
- IsCopy: true,
- },
- },
- "renameFrom": {
- Line: "rename from dir/file.txt\n",
- OutputFile: &File{
- OldName: "dir/file.txt",
- IsRename: true,
- },
- },
- "renameTo": {
- Line: "rename to dir/file.txt\n",
- OutputFile: &File{
- NewName: "dir/file.txt",
- IsRename: true,
- },
- },
- "similarityIndex": {
- Line: "similarity index 88%\n",
- OutputFile: &File{
- Score: 88,
- },
- },
- "similarityIndexTooBig": {
- Line: "similarity index 9001%\n",
- OutputFile: &File{
- Score: 0,
- },
- },
- "similarityIndexInvalid": {
- Line: "similarity index 12ab%\n",
- Err: true,
- },
- "indexFullSHA1AndMode": {
- Line: "index 79c6d7f7b7e76c75b3d238f12fb1323f2333ba14..04fab916d8f938173cbb8b93469855f0e838f098 100644\n",
- OutputFile: &File{
- OldOIDPrefix: "79c6d7f7b7e76c75b3d238f12fb1323f2333ba14",
- NewOIDPrefix: "04fab916d8f938173cbb8b93469855f0e838f098",
- OldMode: os.FileMode(0100644),
- },
- },
- "indexFullSHA1NoMode": {
- Line: "index 79c6d7f7b7e76c75b3d238f12fb1323f2333ba14..04fab916d8f938173cbb8b93469855f0e838f098\n",
- OutputFile: &File{
- OldOIDPrefix: "79c6d7f7b7e76c75b3d238f12fb1323f2333ba14",
- NewOIDPrefix: "04fab916d8f938173cbb8b93469855f0e838f098",
- },
- },
- "indexAbbrevSHA1AndMode": {
- Line: "index 79c6d7..04fab9 100644\n",
- OutputFile: &File{
- OldOIDPrefix: "79c6d7",
- NewOIDPrefix: "04fab9",
- OldMode: os.FileMode(0100644),
- },
- },
- "indexInvalid": {
- Line: "index 79c6d7f7b7e76c75b3d238f12fb1323f2333ba14\n",
- Err: true,
- },
- }
-
- for name, test := range tests {
- t.Run(name, func(t *testing.T) {
- var f File
- if test.InputFile != nil {
- f = *test.InputFile
- }
-
- end, err := parseGitHeaderData(&f, test.Line, test.DefaultName)
- if test.Err {
- if err == nil || err == io.EOF {
- t.Fatalf("expected error parsing header data, but got %v", err)
- }
- return
- }
- if err != nil {
- t.Fatalf("unexpected error parsing header data: %v", err)
- }
-
- if test.OutputFile != nil && !reflect.DeepEqual(test.OutputFile, &f) {
- t.Errorf("incorrect output:\nexpected: %+v\nactual: %+v", test.OutputFile, &f)
- }
- if end != test.End {
- t.Errorf("incorrect end state, expected %t, actual %t", test.End, end)
- }
- })
- }
-}
-
-func TestParseGitHeaderName(t *testing.T) {
- tests := map[string]struct {
- Input string
- Output string
- Err bool
- }{
- "twoMatchingNames": {
- Input: "a/dir/file.txt b/dir/file.txt",
- Output: "dir/file.txt",
- },
- "twoDifferentNames": {
- Input: "a/dir/foo.txt b/dir/bar.txt",
- Output: "",
- },
- "matchingNamesWithSpaces": {
- Input: "a/dir/file with spaces.txt b/dir/file with spaces.txt",
- Output: "dir/file with spaces.txt",
- },
- "matchingNamesWithTrailingSpaces": {
- Input: "a/dir/spaces b/dir/spaces ",
- Output: "dir/spaces ",
- },
- "matchingNamesQuoted": {
- Input: `"a/dir/\"quotes\".txt" "b/dir/\"quotes\".txt"`,
- Output: `dir/"quotes".txt`,
- },
- "matchingNamesFirstQuoted": {
- Input: `"a/dir/file.txt" b/dir/file.txt`,
- Output: "dir/file.txt",
- },
- "matchingNamesSecondQuoted": {
- Input: `a/dir/file.txt "b/dir/file.txt"`,
- Output: "dir/file.txt",
- },
- "noSecondName": {
- Input: "a/dir/foo.txt",
- Output: "",
- },
- "noSecondNameQuoted": {
- Input: `"a/dir/foo.txt"`,
- Output: "",
- },
- "invalidName": {
- Input: `"a/dir/file.txt b/dir/file.txt`,
- Err: true,
- },
- }
-
- for name, test := range tests {
- t.Run(name, func(t *testing.T) {
- output, err := parseGitHeaderName(test.Input)
- if test.Err {
- if err == nil {
- t.Fatalf("expected error parsing header name, but got nil")
- }
- return
- }
- if err != nil {
- t.Fatalf("unexpected error parsing header name: %v", err)
- }
-
- if output != test.Output {
- t.Errorf("incorrect output: expected %q, actual %q", test.Output, output)
- }
- })
- }
-}
-
-func TestHasEpochTimestamp(t *testing.T) {
- tests := map[string]struct {
- Input string
- Output bool
- }{
- "utcTimestamp": {
- Input: "+++ file.txt\t1970-01-01 00:00:00 +0000\n",
- Output: true,
- },
- "utcZoneWithColon": {
- Input: "+++ file.txt\t1970-01-01 00:00:00 +00:00\n",
- Output: true,
- },
- "utcZoneWithMilliseconds": {
- Input: "+++ file.txt\t1970-01-01 00:00:00.000000 +00:00\n",
- Output: true,
- },
- "westTimestamp": {
- Input: "+++ file.txt\t1969-12-31 16:00:00 -0800\n",
- Output: true,
- },
- "eastTimestamp": {
- Input: "+++ file.txt\t1970-01-01 04:00:00 +0400\n",
- Output: true,
- },
- "noTab": {
- Input: "+++ file.txt 1970-01-01 00:00:00 +0000\n",
- Output: false,
- },
- "invalidFormat": {
- Input: "+++ file.txt\t1970-01-01T00:00:00Z\n",
- Output: false,
- },
- "notEpoch": {
- Input: "+++ file.txt\t2019-03-21 12:34:56.789 -0700\n",
- Output: false,
- },
- "notTimestamp": {
- Input: "+++ file.txt\trandom text\n",
- Output: false,
- },
- "notTimestampShort": {
- Input: "+++ file.txt\t0\n",
- Output: false,
- },
- }
-
- for name, test := range tests {
- t.Run(name, func(t *testing.T) {
- output := hasEpochTimestamp(test.Input)
- if output != test.Output {
- t.Errorf("incorrect output: expected %t, actual %t", test.Output, output)
- }
- })
- }
-}