github.com/anishathalye/periscope@v0.3.5/internal/periscope/refresh_test.go (about)

     1  package periscope
     2  
     3  import (
     4  	"github.com/anishathalye/periscope/internal/db"
     5  	"github.com/anishathalye/periscope/internal/testfs"
     6  
     7  	"bytes"
     8  	"io/ioutil"
     9  	"os"
    10  	"path/filepath"
    11  	"testing"
    12  
    13  	"github.com/spf13/afero"
    14  )
    15  
    16  func TestRefreshBasic(t *testing.T) {
    17  	fs := testfs.Read(`
    18  /a [10000 1]
    19  /b [10000 1]
    20  /c/d/e [10000 1]
    21  	`).Mkfs()
    22  	ps, _, _ := newTest(fs)
    23  	ps.Scan([]string{"/"}, &ScanOptions{})
    24  	fs.Remove("/b")
    25  	err := ps.Refresh(&RefreshOptions{})
    26  	check(t, err)
    27  	got, _ := ps.db.AllDuplicates("")
    28  	expected := []db.DuplicateSet{{
    29  		{Path: "/a", Size: 10000, ShortHash: nil, FullHash: nil},
    30  		{Path: "/c/d/e", Size: 10000, ShortHash: nil, FullHash: nil},
    31  	}}
    32  	checkEquivalentDuplicateSet(t, expected, got)
    33  }
    34  
    35  func TestRefreshNoChange(t *testing.T) {
    36  	fs := testfs.Read(`
    37  /a [10000 1]
    38  /b [10000 1]
    39  /c/d/e [10000 1]
    40  	`).Mkfs()
    41  	ps, _, _ := newTest(fs)
    42  	ps.Scan([]string{"/"}, &ScanOptions{})
    43  	err := ps.Refresh(&RefreshOptions{})
    44  	check(t, err)
    45  	got, _ := ps.db.AllDuplicates("")
    46  	expected := []db.DuplicateSet{{
    47  		{Path: "/a", Size: 10000, ShortHash: nil, FullHash: nil},
    48  		{Path: "/b", Size: 10000, ShortHash: nil, FullHash: nil},
    49  		{Path: "/c/d/e", Size: 10000, ShortHash: nil, FullHash: nil},
    50  	}}
    51  	checkEquivalentDuplicateSet(t, expected, got)
    52  }
    53  
    54  func TestRefreshModifyFile(t *testing.T) {
    55  	fs := testfs.Read(`
    56  /a [10000 1]
    57  /b [10000 1]
    58  /c/d/e [10000 1]
    59  	`).Mkfs()
    60  	ps, _, _ := newTest(fs)
    61  	ps.Scan([]string{"/"}, &ScanOptions{})
    62  	afero.WriteFile(fs, "/a", []byte{'a', 'b', 'c'}, 0o644)
    63  	// double check that they're different
    64  	hashA, _ := ps.hashFile("/a")
    65  	hashB, _ := ps.hashFile("/b")
    66  	if bytes.Equal(hashA, hashB) {
    67  		t.Fatal("files are still equal")
    68  	}
    69  	err := ps.Refresh(&RefreshOptions{})
    70  	check(t, err)
    71  	got, _ := ps.db.AllDuplicates("")
    72  	// refresh only checks that the files are still there, so we should
    73  	// still see it as a duplicate
    74  	expected := []db.DuplicateSet{{
    75  		{Path: "/a", Size: 10000, ShortHash: nil, FullHash: nil},
    76  		{Path: "/b", Size: 10000, ShortHash: nil, FullHash: nil},
    77  		{Path: "/c/d/e", Size: 10000, ShortHash: nil, FullHash: nil},
    78  	}}
    79  	checkEquivalentDuplicateSet(t, expected, got)
    80  }
    81  
    82  func TestRefreshMove(t *testing.T) {
    83  	fs := testfs.Read(`
    84  /a [10000 1]
    85  /b [10000 1]
    86  /c/d/e [10000 1]
    87  	`).Mkfs()
    88  	ps, _, _ := newTest(fs)
    89  	ps.Scan([]string{"/"}, &ScanOptions{})
    90  	fs.Rename("/a", "/f")
    91  	err := ps.Refresh(&RefreshOptions{})
    92  	check(t, err)
    93  	got, _ := ps.db.AllDuplicates("")
    94  	expected := []db.DuplicateSet{{
    95  		{Path: "/b", Size: 10000, ShortHash: nil, FullHash: nil},
    96  		{Path: "/c/d/e", Size: 10000, ShortHash: nil, FullHash: nil},
    97  	}}
    98  	checkEquivalentDuplicateSet(t, expected, got)
    99  
   100  	ps.Scan([]string{"/"}, &ScanOptions{})
   101  	got, _ = ps.db.AllDuplicates("")
   102  	expected = []db.DuplicateSet{{
   103  		{Path: "/b", Size: 10000, ShortHash: nil, FullHash: nil},
   104  		{Path: "/c/d/e", Size: 10000, ShortHash: nil, FullHash: nil},
   105  		{Path: "/f", Size: 10000, ShortHash: nil, FullHash: nil},
   106  	}}
   107  	checkEquivalentDuplicateSet(t, expected, got)
   108  }
   109  
   110  func TestRefreshReplaceFileWithDirectory(t *testing.T) {
   111  	fs := testfs.Read(`
   112  /a [10000 1]
   113  /b [10000 1]
   114  /c/d/e [10000 1]
   115  	`).Mkfs()
   116  	ps, _, _ := newTest(fs)
   117  	ps.Scan([]string{"/"}, &ScanOptions{})
   118  	fs.Remove("/a")
   119  	fs.Mkdir("/a", 0o755)
   120  	afero.WriteFile(fs, "/a/x", []byte{'x'}, 0o644)
   121  	err := ps.Refresh(&RefreshOptions{})
   122  	check(t, err)
   123  	got, _ := ps.db.AllDuplicates("")
   124  	expected := []db.DuplicateSet{{
   125  		{Path: "/b", Size: 10000, ShortHash: nil, FullHash: nil},
   126  		{Path: "/c/d/e", Size: 10000, ShortHash: nil, FullHash: nil},
   127  	}}
   128  	checkEquivalentDuplicateSet(t, expected, got)
   129  }
   130  
   131  func TestRefreshRemoveSingletons(t *testing.T) {
   132  	fs := testfs.Read(`
   133  /a/x/1 [10000 1]
   134  /b/2 [10000 1]
   135  	`).Mkfs()
   136  	ps, _, _ := newTest(fs)
   137  	ps.Scan([]string{"/"}, &ScanOptions{})
   138  	fs.Remove("/a/x/1")
   139  	err := ps.Refresh(&RefreshOptions{})
   140  	check(t, err)
   141  	got, _ := ps.db.AllDuplicates("")
   142  	if len(got) != 0 {
   143  		t.Fatalf("expected no duplicate sets, got %d", len(got))
   144  	}
   145  }
   146  
   147  func TestRefreshPreserveNonSingletons(t *testing.T) {
   148  	fs := testfs.Read(`
   149  /a [10000 1]
   150  /b [10000 1]
   151  /c/d/e [10000 1]
   152  /f [1337 2]
   153  /g [1337 2]
   154  	`).Mkfs()
   155  	ps, _, _ := newTest(fs)
   156  	ps.Scan([]string{"/"}, &ScanOptions{})
   157  	fs.Remove("/a")
   158  	fs.Remove("/f")
   159  	err := ps.Refresh(&RefreshOptions{})
   160  	check(t, err)
   161  	got, _ := ps.db.AllDuplicates("")
   162  	expected := []db.DuplicateSet{{
   163  		{Path: "/b", Size: 10000, ShortHash: nil, FullHash: nil},
   164  		{Path: "/c/d/e", Size: 10000, ShortHash: nil, FullHash: nil},
   165  	}}
   166  	checkEquivalentDuplicateSet(t, expected, got)
   167  }
   168  
   169  func TestRefreshPermissionError(t *testing.T) {
   170  	fs := afero.NewOsFs()
   171  	dir := tempDir()
   172  	defer os.RemoveAll(dir)
   173  	os.Mkdir(filepath.Join(dir, "d1"), 0o755)
   174  	os.Mkdir(filepath.Join(dir, "d2"), 0o755)
   175  	ioutil.WriteFile(filepath.Join(dir, "d1", "w"), []byte{'a'}, 0o644)
   176  	ioutil.WriteFile(filepath.Join(dir, "d1", "x"), []byte{'a'}, 0o644)
   177  	ioutil.WriteFile(filepath.Join(dir, "d2", "y"), []byte{'b'}, 0o644)
   178  	ioutil.WriteFile(filepath.Join(dir, "d2", "z"), []byte{'b'}, 0o644)
   179  	ps, _, _ := newTest(fs)
   180  	ps.Scan([]string{dir}, &ScanOptions{})
   181  	os.Chmod(filepath.Join(dir, "d1"), 0o000)
   182  	ps.Refresh(&RefreshOptions{})
   183  	got, _ := ps.db.AllDuplicates("")
   184  	expected := []db.DuplicateSet{{
   185  		{Path: filepath.Join(dir, "d2", "y"), Size: 1, ShortHash: nil, FullHash: nil},
   186  		{Path: filepath.Join(dir, "d2", "z"), Size: 1, ShortHash: nil, FullHash: nil},
   187  	}}
   188  	checkEquivalentDuplicateSet(t, expected, got)
   189  }
   190  
   191  func TestRefreshNonRegularFile(t *testing.T) {
   192  	fs := afero.NewOsFs()
   193  	dir := tempDir()
   194  	defer os.RemoveAll(dir)
   195  	ioutil.WriteFile(filepath.Join(dir, "w"), []byte{'a'}, 0o644)
   196  	ioutil.WriteFile(filepath.Join(dir, "x"), []byte{'a'}, 0o644)
   197  	ioutil.WriteFile(filepath.Join(dir, "y"), []byte{'b'}, 0o644)
   198  	ioutil.WriteFile(filepath.Join(dir, "z"), []byte{'b'}, 0o644)
   199  	ps, _, _ := newTest(fs)
   200  	ps.Scan([]string{dir}, &ScanOptions{})
   201  	os.Remove(filepath.Join(dir, "w"))
   202  	os.Symlink(filepath.Join(dir, "x"), filepath.Join(dir, "w"))
   203  	ps.Refresh(&RefreshOptions{})
   204  	got, _ := ps.db.AllDuplicates("")
   205  	expected := []db.DuplicateSet{{
   206  		{Path: filepath.Join(dir, "y"), Size: 1, ShortHash: nil, FullHash: nil},
   207  		{Path: filepath.Join(dir, "z"), Size: 1, ShortHash: nil, FullHash: nil},
   208  	}}
   209  	checkEquivalentDuplicateSet(t, expected, got)
   210  }
   211  
   212  func TestRefreshSymlinkDir(t *testing.T) {
   213  	fs := afero.NewOsFs()
   214  	dir := tempDir()
   215  	defer os.RemoveAll(dir)
   216  	os.Mkdir(filepath.Join(dir, "d"), 0o755)
   217  	os.Mkdir(filepath.Join(dir, "d2"), 0o755)
   218  	ioutil.WriteFile(filepath.Join(dir, "d", "x"), []byte{'b'}, 0o644)
   219  	ioutil.WriteFile(filepath.Join(dir, "d2", "y"), []byte{'b'}, 0o644)
   220  	ps, _, _ := newTest(fs)
   221  	ps.Scan([]string{dir}, &ScanOptions{})
   222  	os.RemoveAll(filepath.Join(dir, "d2"))
   223  	os.Symlink(filepath.Join(dir, "d"), filepath.Join(dir, "d2"))
   224  	ps.Refresh(&RefreshOptions{})
   225  	got, _ := ps.db.AllDuplicates("")
   226  	if len(got) != 0 {
   227  		t.Fatalf("expected no duplicates, got %d", len(got))
   228  	}
   229  }