github.com/xxr3376/massren@v1.3.1-0.20140919090154-4316ec86540d/main_test.go (about) 1 package main 2 3 import ( 4 "errors" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 "strings" 10 "testing" 11 "time" 12 ) 13 14 func setup(t *testing.T) { 15 minLogLevel_ = 10 16 17 pwd, err := os.Getwd() 18 if err != nil { 19 t.Fatal(err) 20 } 21 homeDir_ = filepath.Join(pwd, "homedirtest") 22 err = os.MkdirAll(homeDir_, 0700) 23 if err != nil { 24 t.Fatal(err) 25 } 26 27 deleteTempFiles() 28 profileOpen() 29 clearHistory() 30 } 31 32 func teardown(t *testing.T) { 33 profileDelete() 34 } 35 36 func touch(filePath string) { 37 ioutil.WriteFile(filePath, []byte("testing"), 0700) 38 } 39 40 func fileExists(filePath string) bool { 41 _, err := os.Stat(filePath) 42 return err == nil 43 } 44 45 func createRandomTempFiles() []string { 46 var output []string 47 for i := 0; i < 10; i++ { 48 filePath := filepath.Join(tempFolder(), fmt.Sprintf("testfile%d", i)) 49 ioutil.WriteFile(filePath, []byte("testing"), 0700) 50 output = append(output, filePath) 51 } 52 return output 53 } 54 55 func fileGetContent(path string) string { 56 o, err := ioutil.ReadFile(path) 57 if err != nil { 58 return "" 59 } 60 return string(o) 61 } 62 63 func filePutContent(path string, content string) { 64 err := ioutil.WriteFile(path, []byte(content), 0700) 65 if err != nil { 66 panic(err) 67 } 68 } 69 70 func Test_fileActions(t *testing.T) { 71 var err error 72 73 type TestCase struct { 74 paths []string 75 content string 76 result []*FileAction 77 } 78 79 var testCases []TestCase 80 81 testCases = append(testCases, TestCase{ 82 paths: []string{ 83 "abcd", 84 "efgh", 85 "ijkl", 86 }, 87 content: ` 88 // some header 89 // some header 90 // some header 91 92 abcd 93 newname 94 // should skip this 95 ijkl 96 // ignore 97 `, 98 result: []*FileAction{ 99 &FileAction{ 100 kind: KIND_RENAME, 101 oldPath: "efgh", 102 newPath: "newname", 103 }, 104 }, 105 }) 106 107 testCases = append(testCases, TestCase{ 108 paths: []string{ 109 "abcd", 110 "efgh", 111 "ijkl", 112 }, 113 content: ` 114 // some header 115 // some header 116 // some header 117 118 //abcd 119 120 efgh 121 ijklmnop 122 `, 123 result: []*FileAction{ 124 &FileAction{ 125 kind: KIND_DELETE, 126 oldPath: "abcd", 127 newPath: "", 128 }, 129 &FileAction{ 130 kind: KIND_RENAME, 131 oldPath: "ijkl", 132 newPath: "ijklmnop", 133 }, 134 }, 135 }) 136 137 testCases = append(testCases, TestCase{ 138 paths: []string{ 139 "abcd", 140 "efgh", 141 "ijkl", 142 }, 143 content: ` 144 // some header 145 // some header 146 abcd 147 efgh 148 ijkl 149 `, 150 result: []*FileAction{}, 151 }) 152 153 testCases = append(testCases, TestCase{ 154 paths: []string{ 155 " abcd", 156 "\t efgh\t\t ", 157 }, 158 content: ` 159 abcd 160 efgh 161 `, 162 result: []*FileAction{}, 163 }) 164 165 testCases = append(testCases, TestCase{ 166 paths: []string{ 167 "abcd", 168 " efgh", 169 " ijkl\t ", 170 }, 171 content: ` 172 // abcd 173 //efgh 174 // ijkl 175 `, 176 result: []*FileAction{ 177 &FileAction{ 178 kind: KIND_DELETE, 179 oldPath: "abcd", 180 newPath: "", 181 }, 182 &FileAction{ 183 kind: KIND_DELETE, 184 oldPath: " efgh", 185 newPath: "", 186 }, 187 &FileAction{ 188 kind: KIND_DELETE, 189 oldPath: " ijkl\t ", 190 newPath: "", 191 }, 192 }, 193 }) 194 195 testCases = append(testCases, TestCase{ 196 paths: []string{ 197 " abcd", 198 "\t efgh\t\t ", 199 }, 200 content: ` 201 abcd 202 efgh 203 `, 204 result: []*FileAction{}, 205 }) 206 207 // Force \n as newline to simplify testing 208 // across platforms. 209 newline_ = "\n" 210 211 for _, testCase := range testCases { 212 // Note: Run tests with -v in case of error 213 214 r, _ := fileActions(testCase.paths, testCase.content) 215 if len(testCase.result) != len(r) { 216 t.Errorf("Expected %d, got %d", len(testCase.result), len(r)) 217 t.Log(testCase.result) 218 t.Log(r) 219 continue 220 } 221 for i, r1 := range r { 222 r2 := testCase.result[i] 223 if r1.kind != r2.kind { 224 t.Errorf("Expected kind %d, got %d", r2.kind, r1.kind) 225 } 226 if r1.oldPath != r2.oldPath { 227 t.Errorf("Expected path %s, got %s", r2.oldPath, r1.oldPath) 228 } 229 if r1.newPath != r2.newPath { 230 t.Error("Expected path %s, got %s", r2.newPath, r1.newPath) 231 } 232 } 233 } 234 235 _, err = fileActions([]string{"abcd", "efgh"}, "") 236 if err == nil { 237 t.Error("Expected error, got nil") 238 } 239 240 _, err = fileActions([]string{"abcd", "efgh"}, "abcd") 241 if err == nil { 242 t.Error("Expected error, got nil") 243 } 244 } 245 246 func Test_processFileActions(t *testing.T) { 247 setup(t) 248 defer teardown(t) 249 250 touch(filepath.Join(tempFolder(), "one")) 251 touch(filepath.Join(tempFolder(), "two")) 252 touch(filepath.Join(tempFolder(), "three")) 253 254 fileActions := []*FileAction{} 255 256 fileAction := NewFileAction() 257 fileAction.oldPath = filepath.Join(tempFolder(), "one") 258 fileAction.newPath = "one123" 259 fileActions = append(fileActions, fileAction) 260 261 fileAction = NewFileAction() 262 fileAction.oldPath = filepath.Join(tempFolder(), "two") 263 fileAction.newPath = "two456" 264 fileActions = append(fileActions, fileAction) 265 266 processFileActions(fileActions, false) 267 268 if !fileExists(filepath.Join(tempFolder(), "one123")) { 269 t.Error("File not found") 270 } 271 272 if !fileExists(filepath.Join(tempFolder(), "two456")) { 273 t.Error("File not found") 274 } 275 276 if !fileExists(filepath.Join(tempFolder(), "three")) { 277 t.Error("File not found") 278 } 279 280 fileActions = []*FileAction{} 281 282 fileAction = NewFileAction() 283 fileAction.oldPath = filepath.Join(tempFolder(), "two456") 284 fileAction.kind = KIND_DELETE 285 fileActions = append(fileActions, fileAction) 286 287 processFileActions(fileActions, true) 288 289 if !fileExists(filepath.Join(tempFolder(), "two456")) { 290 t.Error("File should not have been deleted") 291 } 292 293 processFileActions(fileActions, false) 294 295 if fileExists(filepath.Join(tempFolder(), "two456")) { 296 t.Error("File should have been deleted") 297 } 298 299 fileActions = []*FileAction{} 300 301 fileAction = NewFileAction() 302 fileAction.oldPath = filepath.Join(tempFolder(), "three") 303 fileAction.newPath = "nochange" 304 fileActions = append(fileActions, fileAction) 305 306 processFileActions(fileActions, true) 307 308 if !fileExists(filepath.Join(tempFolder(), "three")) { 309 t.Error("File was renamed in dry-run mode") 310 } 311 } 312 313 func Test_processFileActions_noDestinationOverwrite(t *testing.T) { 314 setup(t) 315 defer teardown(t) 316 317 // Case where a sequence of files such as 0.jpg, 1.jpg is being 318 // renamed to 1.jpg, 2.jpg 319 320 p0 := filepath.Join(tempFolder(), "0") 321 p1 := filepath.Join(tempFolder(), "1") 322 p2 := filepath.Join(tempFolder(), "2") 323 324 filePutContent(p0, "0") 325 filePutContent(p1, "1") 326 327 fileActions := []*FileAction{} 328 329 fileAction := NewFileAction() 330 fileAction.oldPath = p0 331 fileAction.newPath = "1" 332 fileActions = append(fileActions, fileAction) 333 334 fileAction = NewFileAction() 335 fileAction.oldPath = p1 336 fileAction.newPath = "2" 337 fileActions = append(fileActions, fileAction) 338 339 err := processFileActions(fileActions, false) 340 341 if err != nil { 342 t.Errorf("Expected no error, but got an error.") 343 } 344 345 if fileExists(p0) { 346 t.Error("File 0 should have been renamed") 347 } 348 349 if !fileExists(p1) { 350 t.Error("File 1 should exist") 351 } 352 353 if !fileExists(p2) { 354 t.Error("File 2 should exist") 355 } 356 357 if fileGetContent(p1) != "0" { 358 t.Error("File 1 has wrong content") 359 } 360 361 if fileGetContent(p2) != "1" { 362 t.Error("File 2 has wrong content") 363 } 364 } 365 366 func Test_processFileActions_noDestinationOverwrite2(t *testing.T) { 367 setup(t) 368 defer teardown(t) 369 370 // Case where a file is renamed to the name of 371 // another existing file. 372 373 touch(filepath.Join(tempFolder(), "0")) 374 touch(filepath.Join(tempFolder(), "1")) 375 376 originalFilePaths := []string{ 377 filepath.Join(tempFolder(), "0"), 378 } 379 380 changes := ` 381 1 382 ` 383 _, err := fileActions(originalFilePaths, changes) 384 385 if err == nil { 386 t.Error("Expected an error, but got nil.") 387 } 388 } 389 390 func Test_processFileActions_swapFilenames(t *testing.T) { 391 setup(t) 392 defer teardown(t) 393 394 p0 := filepath.Join(tempFolder(), "0") 395 p1 := filepath.Join(tempFolder(), "1") 396 397 filePutContent(p0, "0") 398 filePutContent(p1, "1") 399 400 originalFilePaths := []string{ 401 p0, 402 p1, 403 } 404 405 changes := ` 406 1 407 0 408 ` 409 actions, _ := fileActions(originalFilePaths, changes) 410 err := processFileActions(actions, false) 411 412 if err != nil { 413 t.Error("Expected no error, but got one.") 414 } 415 416 if fileGetContent(p0) != "1" { 417 t.Error("File 1 has not been renamed correctly") 418 } 419 420 if fileGetContent(p1) != "0" { 421 t.Error("File 0 has not been renamed correctly") 422 } 423 } 424 425 func Test_processFileActions_renameToSameName(t *testing.T) { 426 setup(t) 427 defer teardown(t) 428 429 touch(filepath.Join(tempFolder(), "0")) 430 touch(filepath.Join(tempFolder(), "1")) 431 432 originalFilePaths := []string{ 433 filepath.Join(tempFolder(), "0"), 434 filepath.Join(tempFolder(), "1"), 435 } 436 437 changes := ` 438 9 439 9 440 ` 441 _, err := fileActions(originalFilePaths, changes) 442 443 if err == nil { 444 t.Error("Expected an error, but got nil.") 445 } 446 } 447 448 func Test_processFileActions_dontDeleteAfterRename(t *testing.T) { 449 setup(t) 450 defer teardown(t) 451 452 p0 := filepath.Join(tempFolder(), "0") 453 p1 := filepath.Join(tempFolder(), "1") 454 filePutContent(p0, "0") 455 filePutContent(p1, "1") 456 457 originalFilePaths := []string{ 458 p0, 459 p1, 460 } 461 462 changes := ` 463 1 464 //1 465 ` 466 actions, _ := fileActions(originalFilePaths, changes) 467 err := processFileActions(actions, false) 468 469 if err != nil { 470 t.Error("Expected no error, but got one.") 471 } 472 473 if fileExists(p0) { 474 t.Error("File 0 should have been renamed but still exists.") 475 } 476 477 if !fileExists(p1) { 478 t.Error("File 1 should exist.") 479 } 480 481 if fileGetContent(p1) != "0" { 482 t.Errorf("File 0 has not been renamed correctly - content should be \"%s\", but is \"%s\"", "0", fileGetContent(p1)) 483 } 484 } 485 486 func Test_stringHash(t *testing.T) { 487 if len(stringHash("aaaa")) != 32 { 488 t.Error("hash should be 32 characters long") 489 } 490 491 if stringHash("abcd") == stringHash("efgh") || stringHash("") == stringHash("ijkl") { 492 t.Error("hashes should be different") 493 } 494 } 495 496 func Test_watchFile(t *testing.T) { 497 setup(t) 498 defer teardown(t) 499 500 filePath := tempFolder() + "watchtest" 501 ioutil.WriteFile(filePath, []byte("testing"), 0700) 502 doneChan := make(chan bool) 503 504 go func(doneChan chan bool) { 505 defer func() { 506 doneChan <- true 507 }() 508 err := watchFile(filePath) 509 if err != nil { 510 t.Error(err) 511 } 512 }(doneChan) 513 514 time.Sleep(300 * time.Millisecond) 515 ioutil.WriteFile(filePath, []byte("testing change"), 0700) 516 517 <-doneChan 518 } 519 520 func fileListsAreEqual(files1 []string, files2 []string) error { 521 if len(files1) != len(files2) { 522 return errors.New("file count is different") 523 } 524 525 for _, f1 := range files1 { 526 found := false 527 for _, f2 := range files2 { 528 if filepath.Base(f1) == filepath.Base(f2) { 529 found = true 530 } 531 } 532 if !found { 533 return errors.New("file names do not match") 534 } 535 } 536 537 return nil 538 } 539 540 func Test_filePathsFromArgs(t *testing.T) { 541 setup(t) 542 defer teardown(t) 543 544 tempFiles := createRandomTempFiles() 545 args := []string{ 546 filepath.Join(tempFolder(), "*"), 547 } 548 549 filePaths, err := filePathsFromArgs(args, true) 550 if err != nil { 551 t.Fatal(err) 552 } 553 554 err = fileListsAreEqual(filePaths, tempFiles) 555 if err != nil { 556 t.Error(err) 557 } 558 559 // If no argument is provided, the function should default to "*" 560 // in the current dir. 561 562 currentDir, err := os.Getwd() 563 if err != nil { 564 panic(err) 565 } 566 567 err = os.Chdir(tempFolder()) 568 if err != nil { 569 panic(err) 570 } 571 572 args = []string{} 573 filePaths, err = filePathsFromArgs(args, true) 574 if err != nil { 575 t.Fatal(err) 576 } 577 578 err = fileListsAreEqual(filePaths, tempFiles) 579 if err != nil { 580 t.Error(err) 581 } 582 583 os.Chdir(currentDir) 584 } 585 586 func Test_filePathsFromArgs_noDirectories(t *testing.T) { 587 setup(t) 588 defer teardown(t) 589 590 f0 := filepath.Join(tempFolder(), "0") 591 f1 := filepath.Join(tempFolder(), "1") 592 d0 := filepath.Join(tempFolder(), "dir0") 593 d1 := filepath.Join(tempFolder(), "dir1") 594 595 touch(f0) 596 touch(f1) 597 os.Mkdir(d0, 0700) 598 os.Mkdir(d1, 0700) 599 600 args := []string{ 601 filepath.Join(tempFolder(), "*"), 602 } 603 604 filePaths, _ := filePathsFromArgs(args, true) 605 err := fileListsAreEqual(filePaths, []string{f0, f1, d0, d1}) 606 if err != nil { 607 t.Error(err) 608 } 609 610 filePaths, _ = filePathsFromArgs(args, false) 611 err = fileListsAreEqual(filePaths, []string{f0, f1}) 612 if err != nil { 613 t.Error(err) 614 } 615 } 616 617 func stringListsEqual(s1 []string, s2 []string) bool { 618 for i, s := range s1 { 619 if s != s2[i] { 620 return false 621 } 622 } 623 return true 624 } 625 626 func Test_filePathsFromString(t *testing.T) { 627 newline_ = "\n" 628 629 var data []string 630 var expected [][]string 631 632 data = append(data, "// comment\n\nfile1\nfile2\n//comment\n\n\n") 633 expected = append(expected, []string{"file1", "file2"}) 634 635 data = append(data, "\n// comment\n\n") 636 expected = append(expected, []string{}) 637 638 data = append(data, "") 639 expected = append(expected, []string{}) 640 641 data = append(data, "// comment\n\n file1 \n\tfile2\n\nanother file\t\n//comment\n\n\n") 642 expected = append(expected, []string{" file1 ", "\tfile2", "another file\t"}) 643 644 for i, d := range data { 645 e := expected[i] 646 r := filePathsFromString(d) 647 if !stringListsEqual(e, r) { 648 t.Error("Expected", e, "got", r) 649 } 650 } 651 } 652 653 func Test_filePathsFromListFile(t *testing.T) { 654 setup(t) 655 defer teardown(t) 656 657 ioutil.WriteFile(filepath.Join(tempFolder(), "list.txt"), []byte("one"+newline()+"two"), PROFILE_PERM) 658 filePaths, err := filePathsFromListFile(filepath.Join(tempFolder(), "list.txt")) 659 if err != nil { 660 t.Errorf("Expected no error, got %s", err) 661 } 662 663 if len(filePaths) != 2 { 664 t.Errorf("Expected 2 paths, got %d", len(filePaths)) 665 } else { 666 if filePaths[0] != "one" || filePaths[1] != "two" { 667 t.Error("Incorrect data") 668 } 669 } 670 671 os.Remove(filepath.Join(tempFolder(), "list.txt")) 672 _, err = filePathsFromListFile(filepath.Join(tempFolder(), "list.txt")) 673 if err == nil { 674 t.Error("Expected an error, got nil") 675 } 676 } 677 678 func Test_stripBom(t *testing.T) { 679 data := [][][]byte{ 680 {{239, 187, 191}, {}}, 681 {{239, 187, 191, 239, 187, 191}, {239, 187, 191}}, 682 {{239, 187, 191, 65, 66}, {65, 66}}, 683 {{239, 191, 65, 66}, {239, 191, 65, 66}}, 684 {{}, {}}, 685 {{65, 239, 187, 191}, {65, 239, 187, 191}}, 686 } 687 688 for _, d := range data { 689 if stripBom(string(d[0])) != string(d[1]) { 690 t.Errorf("Expected %x, got %x", d[0], d[1]) 691 } 692 } 693 } 694 695 func Test_deleteTempFiles(t *testing.T) { 696 setup(t) 697 defer teardown(t) 698 699 ioutil.WriteFile(filepath.Join(tempFolder(), "one"), []byte("test1"), PROFILE_PERM) 700 ioutil.WriteFile(filepath.Join(tempFolder(), "two"), []byte("test2"), PROFILE_PERM) 701 702 deleteTempFiles() 703 704 tempFiles, _ := filepath.Glob(filepath.Join(tempFolder(), "*")) 705 if len(tempFiles) > 0 { 706 t.Fail() 707 } 708 } 709 710 func Test_newline(t *testing.T) { 711 newline_ = "" 712 nl := newline() 713 if len(nl) < 1 || len(nl) > 2 { 714 t.Fail() 715 } 716 } 717 718 func Test_guessEditorCommand(t *testing.T) { 719 editor, err := guessEditorCommand() 720 if err != nil || len(editor) <= 0 { 721 t.Fail() 722 } 723 } 724 725 func Test_bufferHeader(t *testing.T) { 726 setup(t) 727 defer teardown(t) 728 729 f0 := filepath.Join(tempFolder(), "0") 730 f1 := filepath.Join(tempFolder(), "1") 731 732 touch(f0) 733 touch(f1) 734 735 newline_ = "\n" 736 737 content := createListFileContent([]string{f0, f1}, true) 738 if strings.Index(content, "//") != 0 { 739 t.Fatal("cannot find header") 740 } 741 742 content = createListFileContent([]string{f0, f1}, false) 743 if content != "0\n1\n" { 744 t.Fatal("file content is incorrect: " + content) 745 } 746 }