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  }