github.com/bradleyfalzon/revgrep@v0.0.0-20170920092642-c04006dc3307/revgrep_test.go (about) 1 package revgrep 2 3 import ( 4 "bufio" 5 "bytes" 6 "io/ioutil" 7 "os" 8 "os/exec" 9 "path/filepath" 10 "reflect" 11 "strings" 12 "testing" 13 ) 14 15 func setup(t *testing.T, stage, subdir string) (prevwd string, sample []byte) { 16 wd, err := os.Getwd() 17 if err != nil { 18 t.Fatalf("could not get working dir: %s", err) 19 } 20 21 // Execute make 22 cmd := exec.Command("./make.sh", stage) 23 cmd.Dir = filepath.Join(wd, "testdata") 24 sample, err = cmd.CombinedOutput() 25 if err != nil { 26 t.Fatalf("could not run make.sh: %v, output:\n%s", err, sample) 27 } 28 29 // chdir so the vcs exec commands read the correct testdata 30 err = os.Chdir(filepath.Join(wd, "testdata", "git", subdir)) 31 if err != nil { 32 t.Fatalf("could not chdir: %v", err) 33 } 34 return wd, sample 35 } 36 37 func teardown(t *testing.T, wd string) { 38 err := os.Chdir(wd) 39 if err != nil { 40 t.Fatalf("could not chdir: %v", err) 41 } 42 } 43 44 // TestCheckerRegexp tests line matching and extraction of issue 45 func TestCheckerRegexp(t *testing.T) { 46 tests := []struct { 47 regexp string 48 line string 49 want Issue 50 }{ 51 {"", "file.go:1:issue", Issue{"file.go", 1, 0, 2, "file.go:1:issue", "issue"}}, 52 {"", "file.go:1:5:issue", Issue{"file.go", 1, 5, 2, "file.go:1:5:issue", "issue"}}, 53 {"", "file.go:1: issue", Issue{"file.go", 1, 0, 2, "file.go:1: issue", "issue"}}, 54 {`.*?:(.*?\.go):([0-9]+):()(.*)`, "prefix:file.go:1:issue", Issue{"file.go", 1, 0, 2, "prefix:file.go:1:issue", "issue"}}, 55 } 56 57 diff := []byte(`--- a/file.go 58 +++ b/file.go 59 @@ -1,1 +1,1 @@ 60 -func Line() {} 61 +func NewLine() {}`) 62 63 for _, test := range tests { 64 checker := Checker{ 65 Patch: bytes.NewReader(diff), 66 Regexp: test.regexp, 67 } 68 69 issues, err := checker.Check(bytes.NewReader([]byte(test.line)), ioutil.Discard) 70 if err != nil { 71 t.Errorf("unexpected error: %v", err) 72 } 73 74 want := []Issue{test.want} 75 if !reflect.DeepEqual(issues, want) { 76 t.Errorf("unexpected issues for line: %q\nhave: %#v\nwant: %#v", test.line, issues, want) 77 } 78 } 79 } 80 81 // TestChangesReturn tests the writer in the argument to the Changes function 82 // and generally tests the entire programs functionality. 83 func TestChangesWriter(t *testing.T) { 84 tests := map[string]struct { 85 subdir string 86 exp []string // file:linenumber including trailing colon 87 revFrom string 88 revTo string 89 }{ 90 "2-untracked": {"", []string{"main.go:3:"}, "", ""}, 91 "3-untracked-subdir": {"", []string{"main.go:3:", "subdir/main.go:3:"}, "", ""}, 92 "3-untracked-subdir-cwd": {"subdir", []string{"main.go:3:"}, "", ""}, 93 "4-commit": {"", []string{"main.go:3:", "subdir/main.go:3:"}, "", ""}, 94 "5-unstaged-no-warning": {"", nil, "", ""}, 95 "6-unstaged": {"", []string{"main.go:6:"}, "", ""}, 96 // From a commit, all changes should be shown 97 "7-commit": {"", []string{"main.go:6:"}, "HEAD~1", ""}, 98 // From a commit+unstaged, all changes should be shown 99 "8-unstaged": {"", []string{"main.go:6:", "main.go:7:"}, "HEAD~1", ""}, 100 // From a commit+unstaged+untracked, all changes should be shown 101 "9-untracked": {"", []string{"main.go:6:", "main.go:7:", "main2.go:2:"}, "HEAD~1", ""}, 102 // From a commit to last commit, all changes should be shown except recent unstaged, untracked 103 "10-committed": {"", []string{"main.go:6:"}, "HEAD~1", "HEAD~0"}, 104 // static analysis tools with absolute paths should be handled 105 "11-abs-path": {"", []string{"main.go:6:"}, "HEAD~1", "HEAD~0"}, 106 // Removing a single line shouldn't raise any issues. 107 "12-removed-lines": {"", nil, "", ""}, 108 } 109 110 for stage, test := range tests { 111 prevwd, sample := setup(t, stage, test.subdir) 112 113 reader := bytes.NewBuffer(sample) 114 var out bytes.Buffer 115 116 c := Checker{ 117 RevisionFrom: test.revFrom, 118 RevisionTo: test.revTo, 119 } 120 _, err := c.Check(reader, &out) 121 if err != nil { 122 t.Errorf("%v: unexpected error: %v", stage, err) 123 } 124 125 scanner := bufio.NewScanner(&out) 126 var i int 127 for i = 0; scanner.Scan(); i++ { 128 // Rewrite abs paths to for simpler matching 129 line := rewriteAbs(scanner.Text()) 130 131 if i > len(test.exp)-1 { 132 t.Errorf("%v: unexpected line: %q", stage, line) 133 } else { 134 if !strings.HasPrefix(line, test.exp[i]) { 135 t.Errorf("%v: line does not have prefix: %q line: %q", stage, test.exp[i], line) 136 } 137 } 138 } 139 if i != len(test.exp) { 140 t.Errorf("%v: i %v, expected %v", stage, i, len(test.exp)) 141 } 142 teardown(t, prevwd) 143 } 144 } 145 146 func rewriteAbs(line string) string { 147 cwd, err := os.Getwd() 148 if err != nil { 149 panic(err) 150 } 151 return strings.TrimPrefix(line, cwd+"/") 152 } 153 154 func TestGitPatchNonGitDir(t *testing.T) { 155 // Change to non-git dir 156 err := os.Chdir("/") 157 if err != nil { 158 t.Fatalf("could not chdir: %v", err) 159 } 160 161 patch, newfiles, err := GitPatch("", "") 162 if err != nil { 163 t.Errorf("error expected nil, got: %v", err) 164 } 165 if patch != nil { 166 t.Errorf("patch expected nil, got: %v", patch) 167 } 168 if newfiles != nil { 169 t.Errorf("newFiles expected nil, got: %v", newfiles) 170 } 171 } 172 173 func TestLinesChanged(t *testing.T) { 174 diff := []byte(`--- a/file.go 175 +++ b/file.go 176 @@ -1,1 +1,1 @@ 177 // comment 178 -func Line() {} 179 +func NewLine() {} 180 @@ -20,1 +20,1 @@ 181 // comment 182 -func Line() {} 183 +func NewLine() {} 184 // comment 185 @@ -3,1 +30,1 @@ 186 -func Line() {} 187 +func NewLine() {} 188 // comment`) 189 190 checker := Checker{ 191 Patch: bytes.NewReader(diff), 192 } 193 194 have := checker.linesChanged() 195 196 want := map[string][]pos{ 197 "file.go": []pos{ 198 {lineNo: 2, hunkPos: 3}, 199 {lineNo: 21, hunkPos: 7}, 200 {lineNo: 30, hunkPos: 11}, 201 }, 202 } 203 204 if !reflect.DeepEqual(have, want) { 205 t.Errorf("unexpected pos:\nhave: %#v\nwant: %#v", have, want) 206 } 207 }