github.com/mmirolim/gtr@v0.3.0/parser_test.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "io" 8 "io/ioutil" 9 "os" 10 "path/filepath" 11 "reflect" 12 "testing" 13 14 "github.com/kr/pretty" 15 ) 16 17 func TestChangesFromGitDiff(t *testing.T) { 18 cases := []struct { 19 data string 20 output []Change 21 err error 22 }{ 23 {data: `diff --git a/parser.go b/parser.go 24 index 6452f09..de4ce2a 100644 25 --- a/parser.go 26 +++ b/parser.go 27 @@ -32,0 +33,2 @@ func changesFromGitDiff(diff string) ([]Change, error) { 28 // comment 29 // comment 30 + fmt.Printf("All matches %+v\n", matches) // output for debug 31 + 32 } 33 // comment 34 diff --git a/parser_test.go b/parser_test.go 35 index 7268a75..31a1203 100644 36 --- a/parser_test.go 37 +++ b/parser_test.go 38 @@ -341 +341 @@ func TestGetDiff(t *testing.T) { 39 // 40 - desc: "Update file math.go, change package level const and add comment", 41 + desc: "Multiple updates to file math.go", 42 @@ -343 +343,2 @@ func TestGetDiff(t *testing.T) { 43 - return ioutil.WriteFile(filePath("math.go"), mathgo_update_pkg_lvl_var_add_comment_change_func, 0600) 44 + return ioutil.WriteFile(filePath("math.go"), 45 + mathgo_update_pkg_lvl_var_add_comment_change_func, 0600) 46 @@ -349 +350 @@ func TestGetDiff(t *testing.T) { 47 - output: []Change{{"math.go", 1, 9}}, 48 + output: []Change{{"math.go", 0, 0}, {"math.go", 1, 9}}, 49 diff --git a/process_go_file.go b/process_go_file.go 50 index 95a1cdd..d32a8ba 100644 51 --- a/process_go_file.go 52 +++ b/process_go_file.go 53 @@ -58 +57,0 @@ func parseTestFile(fname string) error { 54 - fmt.Printf("parseTestFile %+v\n", fname) // output for debug 55 @@ -69,0 +69 @@ func parseTestFile(fname string) error { 56 + // testFiles LOCK 57 @@ -72,0 +73 @@ func parseTestFile(fname string) error { 58 + // testFiles UNLOCK 59 @@ -118,0 +120 @@ func indexFuncsInTestFile(fname string) { 60 +// TODO handle other types of entities like Types, Interfaces 61 @@ -166 +168 @@ func processFileChanges() (map[string]FileInfo, error) { 62 - //fmt.Printf("Process changes\n%+v\n", changes) // output for debug 63 + fmt.Printf("Process changes\n%+v\n", changes) // output for debug 64 diff --git a/process_go_file_test.go b/process_go_file_test.go 65 index d1f20de..c0bcbcd 100644 66 --- a/process_go_file_test.go 67 +++ b/process_go_file_test.go 68 @@ -5,0 +6,2 @@ import ( 69 + 70 + "github.com/kr/pretty" 71 @@ -69,0 +72,22 @@ func Test_fnNameFromCallExpr(t *testing.T) { 72 + } 73 +} 74 `, output: []Change{ 75 {fpathOld: "parser.go", fpath: "parser.go", start: 33, count: 2}, 76 {fpathOld: "parser_test.go", fpath: "parser_test.go", start: 341, count: 0}, 77 {fpathOld: "parser_test.go", fpath: "parser_test.go", start: 343, count: 2}, 78 {fpathOld: "parser_test.go", fpath: "parser_test.go", start: 350, count: 0}, 79 {fpathOld: "process_go_file.go", fpath: "process_go_file.go", start: 57, count: 0}, 80 {fpathOld: "process_go_file.go", fpath: "process_go_file.go", start: 69, count: 0}, 81 {fpathOld: "process_go_file.go", fpath: "process_go_file.go", start: 73, count: 0}, 82 {fpathOld: "process_go_file.go", fpath: "process_go_file.go", start: 120, count: 0}, 83 {fpathOld: "process_go_file.go", fpath: "process_go_file.go", start: 168, count: 0}, 84 {fpathOld: "process_go_file_test.go", fpath: "process_go_file_test.go", start: 6, count: 2}, 85 {fpathOld: "process_go_file_test.go", fpath: "process_go_file_test.go", start: 72, count: 22}}}, 86 // deleted file 87 {data: `diff --git a/main.go b/main.go 88 deleted file mode 100644 89 index 6e2c328..0000000 90 --- a/main.go 91 +++ /dev/null 92 @@ -1,12 +0,0 @@ 93 - 94 -package main 95 - 96 -var a, b int = 10, 20 97 - 98 -func main() { 99 - fmt.Printf("%+v\n", add(a, b)) 100 -} 101 - 102 -func add(a, b int) { 103 - return a + b 104 -} 105 `, output: nil}, 106 } 107 var buffer bytes.Buffer 108 for i, tc := range cases { 109 buffer.Reset() 110 buffer.WriteString(tc.data) 111 112 changes, err := changesFromGitDiff(buffer) 113 if isUnexpectedErr(t, i, "", tc.err, err) { 114 continue 115 } 116 117 diffs := pretty.Diff(tc.output, changes) 118 if len(diffs) > 0 { 119 t.Errorf("%# v", pretty.Formatter(diffs)) 120 } 121 122 } 123 } 124 125 var gofile = []byte(` 126 package main 127 128 import "github.com/pkg" 129 130 type T1 struct{ 131 a int 132 } 133 134 func (t *T1) M1(a, b int) int { 135 z := a + b 136 a += b 137 return z + a + b 138 } 139 140 func (t T1) M2(a, b int) int { 141 return b - a 142 } 143 144 func F2() int { 145 return pkg.F() 146 } 147 148 func Perimeter(d, h int) int { 149 return 2*d + 2*h 150 } 151 152 func Area(d, h int) int { 153 return d * h 154 } 155 `) 156 157 func TestGetFileBlocks(t *testing.T) { 158 cases := []struct { 159 fileName string 160 fileData []byte 161 output FileInfo 162 err error 163 }{ 164 { 165 fileName: "gofile.go", fileData: gofile, output: FileInfo{ 166 fname: "gofile.go", 167 pkgName: "main", endLine: 30, 168 blocks: []FileBlock{ 169 {typ: BlockType, name: "T1", start: 6, end: 8}, 170 {typ: BlockMethod, name: "T1.M1", start: 10, end: 14}, 171 {typ: BlockMethod, name: "T1.M2", start: 16, end: 18}, 172 {typ: BlockFunc, name: "F2", start: 20, end: 22}, 173 {typ: BlockFunc, name: "Perimeter", start: 24, end: 26}, 174 {typ: BlockFunc, name: "Area", start: 28, end: 30}, 175 }, 176 }, 177 }, 178 } 179 for i, tc := range cases { 180 fileInfo, err := getFileInfo("gofile.go", gofile) 181 if isUnexpectedErr(t, i, "", tc.err, err) { 182 continue 183 } 184 185 diffs := pretty.Diff(tc.output, fileInfo) 186 if len(diffs) > 0 { 187 fmt.Printf("%# v\n", pretty.Formatter(fileInfo)) // output for debug 188 t.Errorf("%# v", pretty.Formatter(diffs)) 189 } 190 } 191 } 192 193 func TestParseFlag(t *testing.T) { 194 cases := []struct { 195 desc string 196 osArgs []string 197 out config 198 err error 199 }{ 200 { 201 desc: "no flags are defined", 202 osArgs: []string{"./binary"}, 203 out: newConfig(), 204 err: nil, 205 }, 206 { 207 desc: "All flags are correctly defined", 208 osArgs: []string{ 209 "./binary", "-C", "/home/user/go", "-strategy", "coverage", 210 "-analysis", "cha", "-delay", "10", "-exclude-file-prefix", "h,v,#", 211 "-exclude-dirs", "vendor,node_modules", "-auto-commit", "t", "-run-init", "false", "-args", 212 "-tf1", "10", "-tf2", "20,30"}, 213 out: config{ 214 workDir: "/home/user/go", 215 strategy: "coverage", 216 analysis: "cha", 217 runInit: false, 218 delay: 10, 219 excludeFilePrefix: []string{"h", "v", "#"}, 220 excludeDirs: []string{"vendor", "node_modules"}, 221 autoCommit: true, 222 argsToTestBinary: "-tf1 10 -tf2 20,30", 223 }, 224 err: nil, 225 }, 226 { 227 desc: "Delay flag invalid", 228 osArgs: []string{"./binary", "-delay", "10.1", "-args", 229 "-tf1", "10", "-tf2", "20,30"}, 230 out: config{}, 231 err: errors.New("-delay invalid value 10.1"), 232 }, 233 { 234 desc: "Flag value missing", 235 osArgs: []string{"./binary", "-auto-commit", "t", "-exclude-dirs"}, 236 out: config{}, 237 err: errors.New("-exclude-dirs value missing"), 238 }, 239 { 240 desc: "on help return usage", 241 osArgs: []string{"./binary", "help"}, 242 out: config{}, 243 err: errors.New(flagUsage()), 244 }, 245 { 246 desc: "test flag setting", 247 osArgs: []string{"./binary", "-strategy=\"coverage\"", "-analysis=cha"}, 248 out: config{ 249 workDir: ".", 250 delay: 1000, 251 strategy: "coverage", 252 runInit: true, 253 analysis: "cha", 254 excludeFilePrefix: []string{"#"}, 255 excludeDirs: []string{"vendor", "node_modules"}, 256 autoCommit: false, 257 argsToTestBinary: "", 258 }, 259 err: nil, 260 }, 261 { 262 desc: "invalid option", 263 osArgs: []string{"./binary", "-no-a-flag", "value"}, 264 out: config{}, 265 err: errors.New("invalid option -- -no-a-flag"), 266 }, 267 } 268 for i, tc := range cases { 269 cfg, err := parseFlags(tc.osArgs) 270 if isUnexpectedErr(t, i, tc.desc, tc.err, err) { 271 continue 272 } 273 if err != nil { 274 continue // skip on valid errors 275 } 276 diffs := pretty.Diff(tc.out, cfg) 277 if len(diffs) > 0 { 278 t.Errorf("case [%d] %s\nunexpected result %# v", i, tc.desc, pretty.Formatter(diffs)) 279 } 280 } 281 282 } 283 284 func TestGetModuleName(t *testing.T) { 285 gomod := []byte(`module rock.com/solid 286 287 go 1.13 288 289 require ( 290 golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a 291 )`) 292 // setup 293 testDir := filepath.Join(os.TempDir(), "test-get-module-name") 294 workDir := filepath.Join(testDir, "src", "rockcom", "solid") 295 err := os.MkdirAll(workDir, 0700) 296 if err != nil { 297 t.Fatal(err) 298 } 299 dir, err := os.Getwd() 300 if err != nil { 301 t.Fatal(err) 302 } 303 // change dir 304 err = os.Chdir(workDir) 305 if err != nil { 306 t.Fatal(err) 307 } 308 // teardown 309 defer func() { 310 // go back 311 os.Chdir(dir) 312 if !t.Failed() { 313 // clean tmp dir on test success 314 _ = os.RemoveAll(testDir) 315 } 316 }() 317 318 cases := []struct { 319 desc string 320 gofile []byte 321 module string 322 err error 323 setup, teardown func() error 324 }{ 325 { 326 desc: "Not a go module", 327 module: "rockcom/solid", 328 setup: func() error { 329 return os.Setenv("GOPATH", testDir) 330 }, 331 }, 332 { 333 desc: "Go module", 334 gofile: gomod, 335 module: "rock.com/solid", 336 setup: func() error { 337 return ioutil.WriteFile(filepath.Join(workDir, "go.mod"), gomod, 0600) 338 }, 339 teardown: func() error { 340 return os.Remove(filepath.Join(workDir, "go.mod")) 341 }, 342 }, 343 } 344 345 for i, tc := range cases { 346 // setup 347 execTestHelper(t, i, tc.desc, tc.setup) 348 349 module, err := getModuleName(workDir) 350 351 // teardown 352 execTestHelper(t, i, tc.desc, tc.teardown) 353 if isUnexpectedErr(t, i, tc.desc, tc.err, err) { 354 continue 355 } 356 357 if !reflect.DeepEqual(tc.module, module) { 358 t.Errorf("case [%d] %s\nexpected %s, got %s", i, tc.desc, tc.module, module) 359 } 360 } 361 } 362 363 func TestParseCoverProfile(t *testing.T) { 364 testRunnerFile := []byte(`mode: set 365 mmirolim/gtr/strategy.go:329.38,331.15 1 0 366 mmirolim/gtr/strategy.go:333.28,335.7 1 0 367 mmirolim/gtr/testrunner.go:39.17,46.2 1 1 368 mmirolim/gtr/testrunner.go:49.37,51.2 1 0 369 mmirolim/gtr/testrunner.go:100.77,102.18 2 1 370 mmirolim/gtr/testrunner.go:105.2,105.24 1 1 371 mmirolim/gtr/testrunner.go:108.2,108.12 1 1 372 mmirolim/gtr/testrunner.go:102.18,104.3 1 1 373 mmirolim/gtr/testrunner.go:105.24,107.3 1 1 374 mmirolim/gtr/testrunner.go:111.77,113.12 2 1 375 mmirolim/gtr/testrunner.go:121.2,123.21 3 1 376 mmirolim/gtr/testrunner.go:126.2,126.30 1 1 377 mmirolim/gtr/testrunner.go:113.12,117.3 3 1 378 mmirolim/gtr/testrunner.go:117.8,119.3 1 0 379 mmirolim/gtr/testrunner.go:123.21,125.3 1 1 380 mmirolim/gtr/watcher.go:51.21,64.2 2 0 381 mmirolim/gtr/watcher.go:67.31,71.16 3 1 382 `) 383 cases := []struct { 384 desc string 385 data []byte 386 infoMap map[string]*FileCoverInfo 387 err error 388 }{ 389 { 390 desc: "No data", 391 data: nil, 392 err: io.EOF, 393 }, 394 { 395 desc: "Cover profile data for multiple files", 396 data: testRunnerFile, 397 infoMap: map[string]*FileCoverInfo{ 398 "mmirolim/gtr/watcher.go": &FileCoverInfo{ 399 "mmirolim/gtr/watcher.go", [][2]int{{67, 71}}, 400 }, 401 "mmirolim/gtr/strategy.go": &FileCoverInfo{ 402 File: "mmirolim/gtr/strategy.go", 403 }, 404 "mmirolim/gtr/testrunner.go": &FileCoverInfo{ 405 "mmirolim/gtr/testrunner.go", 406 [][2]int{{39, 46}, {100, 104}, {105, 107}, {108, 108}, 407 {111, 117}, {121, 125}, {126, 126}}, 408 }, 409 }, 410 }, 411 } 412 413 for i, tc := range cases { 414 infos, err := ParseCoverProfile(tc.data) 415 if isUnexpectedErr(t, i, tc.desc, tc.err, err) { 416 continue 417 } 418 if err != nil { 419 continue 420 } 421 422 diffs := pretty.Diff(tc.infoMap, infos) 423 if len(diffs) > 0 { 424 t.Errorf("case [%d] %s\nexpected %+v, got %+v", i, tc.desc, tc.infoMap, infos) 425 fmt.Printf("Diffs %# v\n", pretty.Formatter(diffs)) // output for debug 426 427 } 428 } 429 }