package dirtree import ( "fmt" "testing" "github.com/rclone/rclone/fstest/mockdir" "github.com/rclone/rclone/fstest/mockobject" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestNew(t *testing.T) { dt := New() assert.Equal(t, "", dt.String()) } func TestParentDir(t *testing.T) { assert.Equal(t, "root/parent", parentDir("root/parent/file")) assert.Equal(t, "parent", parentDir("parent/file")) assert.Equal(t, "", parentDir("parent")) assert.Equal(t, "", parentDir("")) } func TestDirTreeAdd(t *testing.T) { dt := New() o := mockobject.New("potato") dt.Add(o) assert.Equal(t, `/ potato `, dt.String()) o = mockobject.New("dir/subdir/sausage") dt.Add(o) assert.Equal(t, `/ potato dir/subdir/ sausage `, dt.String()) } func TestDirTreeAddDir(t *testing.T) { dt := New() d := mockdir.New("potato") dt.Add(d) assert.Equal(t, `/ potato/ `, dt.String()) d = mockdir.New("dir/subdir/sausage") dt.AddDir(d) assert.Equal(t, `/ potato/ dir/subdir/ sausage/ dir/subdir/sausage/ `, dt.String()) d = mockdir.New("") dt.AddDir(d) assert.Equal(t, `/ potato/ dir/subdir/ sausage/ dir/subdir/sausage/ `, dt.String()) } func TestDirTreeAddEntry(t *testing.T) { dt := New() d := mockdir.New("dir/subdir/sausagedir") dt.AddEntry(d) o := mockobject.New("dir/subdir2/sausage2") dt.AddEntry(o) assert.Equal(t, `/ dir/ dir/ subdir/ subdir2/ dir/subdir/ sausagedir/ dir/subdir/sausagedir/ dir/subdir2/ sausage2 `, dt.String()) } func TestDirTreeFind(t *testing.T) { dt := New() parent, foundObj := dt.Find("dir/subdir/sausage") assert.Equal(t, "dir/subdir", parent) assert.Nil(t, foundObj) o := mockobject.New("dir/subdir/sausage") dt.Add(o) parent, foundObj = dt.Find("dir/subdir/sausage") assert.Equal(t, "dir/subdir", parent) assert.Equal(t, o, foundObj) } func TestDirTreeCheckParent(t *testing.T) { dt := New() o := mockobject.New("dir/subdir/sausage") dt.Add(o) assert.Equal(t, `dir/subdir/ sausage `, dt.String()) dt.checkParent("", "dir/subdir", nil) assert.Equal(t, `/ dir/ dir/ subdir/ dir/subdir/ sausage `, dt.String()) } func TestDirTreeCheckParents(t *testing.T) { dt := New() dt.Add(mockobject.New("dir/subdir/sausage")) dt.Add(mockobject.New("dir/subdir2/sausage2")) dt.CheckParents("") dt.Sort() // sort since the exact order of adding parents is not defined assert.Equal(t, `/ dir/ dir/ subdir/ subdir2/ dir/subdir/ sausage dir/subdir2/ sausage2 `, dt.String()) } func TestDirTreeSort(t *testing.T) { dt := New() dt.Add(mockobject.New("dir/subdir/B")) dt.Add(mockobject.New("dir/subdir/A")) assert.Equal(t, `dir/subdir/ B A `, dt.String()) dt.Sort() assert.Equal(t, `dir/subdir/ A B `, dt.String()) } func TestDirTreeDirs(t *testing.T) { dt := New() dt.Add(mockobject.New("dir/subdir/sausage")) dt.Add(mockobject.New("dir/subdir2/sausage2")) dt.CheckParents("") assert.Equal(t, []string{ "", "dir", "dir/subdir", "dir/subdir2", }, dt.Dirs()) } func TestDirTreePrune(t *testing.T) { dt := New() dt.Add(mockobject.New("file")) dt.Add(mockobject.New("dir/subdir/sausage")) dt.Add(mockobject.New("dir/subdir2/sausage2")) dt.Add(mockobject.New("dir/file")) dt.Add(mockobject.New("dir2/file")) dt.CheckParents("") err := dt.Prune(map[string]bool{ "dir": true, }) require.NoError(t, err) assert.Equal(t, `/ file dir2/ dir2/ file `, dt.String()) } func BenchmarkCheckParents(b *testing.B) { for _, N := range []int{1e2, 1e3, 1e4, 1e5, 1e6} { b.Run(fmt.Sprintf("%d", N), func(b *testing.B) { b.StopTimer() dt := New() for i := 0; i < N; i++ { remote := fmt.Sprintf("dir%09d/file%09d.txt", i, 1) o := mockobject.New(remote) dt.Add(o) } b.StartTimer() for n := 0; n < b.N; n++ { dt.CheckParents("") } }) } }