From 3bce5db6d10337777020b07a688ea484bde7359a Mon Sep 17 00:00:00 2001 From: Krishnan Parthasarathi Date: Thu, 14 Jul 2016 18:37:43 -0700 Subject: [PATCH] tests: Add tests to treeWalk for sortedness, recursive listing and isEnd behaviour (#2209) --- tree-walk_test.go | 278 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 266 insertions(+), 12 deletions(-) diff --git a/tree-walk_test.go b/tree-walk_test.go index 1a7baef5a..01a38f385 100644 --- a/tree-walk_test.go +++ b/tree-walk_test.go @@ -19,20 +19,14 @@ package main import ( "fmt" "io/ioutil" + "sort" "strings" "testing" "time" ) -// Sample entries for the namespace. -var volume = "testvolume" -var files = []string{ - "d/e", - "d/f", - "d/g/h", - "i/j/k", - "lmn", -} +// Fixed volume name that could be used across tests +const volume = "testvolume" // Helper function that creates a volume and files in it. func createNamespace(disk StorageAPI, volume string, files []string) error { @@ -97,6 +91,13 @@ func TestTreeWalk(t *testing.T) { t.Errorf("Unable to create StorageAPI: %s", err) } + var files = []string{ + "d/e", + "d/f", + "d/g/h", + "i/j/k", + "lmn", + } err = createNamespace(disk, volume, files) if err != nil { t.Fatal(err) @@ -125,12 +126,12 @@ func TestTreeWalkTimeout(t *testing.T) { if err != nil { t.Errorf("Unable to create StorageAPI: %s", err) } - var files []string + var myfiles []string // Create maxObjectsList+1 number of entries. for i := 0; i < maxObjectList+1; i++ { - files = append(files, fmt.Sprintf("file.%d", i)) + myfiles = append(myfiles, fmt.Sprintf("file.%d", i)) } - err = createNamespace(disk, volume, files) + err = createNamespace(disk, volume, myfiles) if err != nil { t.Fatal(err) } @@ -259,3 +260,256 @@ func TestListDir(t *testing.T) { t.Error("expected errDiskNotFound error.") } } + +// TestRecursiveWalk - tests if treeWalk returns entries correctly with and +// without recursively traversing prefixes. +func TestRecursiveTreeWalk(t *testing.T) { + // Create a backend directories fsDir1. + fsDir1, err := ioutil.TempDir("", "minio-") + if err != nil { + t.Errorf("Unable to create tmp directory: %s", err) + } + + // Create two StorageAPIs disk1. + disk1, err := newStorageAPI(fsDir1) + if err != nil { + t.Errorf("Unable to create StorageAPI: %s", err) + } + + // Create listDir function. + listDir := listDirFactory(func(volume, prefix string) bool { + return !strings.HasSuffix(prefix, slashSeparator) + }, disk1) + + // Create the namespace. + var files = []string{ + "d/e", + "d/f", + "d/g/h", + "i/j/k", + "lmn", + } + err = createNamespace(disk1, volume, files) + if err != nil { + t.Fatal(err) + } + + endWalkCh := make(chan struct{}) + testCases := []struct { + prefix string + marker string + recursive bool + expected map[string]struct{} + }{ + // with no prefix, no marker and no recursive traversal + {"", "", false, map[string]struct{}{ + "d/": {}, + "i/": {}, + "lmn": {}, + }}, + // with no prefix, no marker and recursive traversal + {"", "", true, map[string]struct{}{ + "d/f": {}, + "d/g/h": {}, + "d/e": {}, + "i/j/k": {}, + "lmn": {}, + }}, + // with no prefix, marker and no recursive traversal + {"", "d/e", false, map[string]struct{}{ + "d/f": {}, + "d/g/": {}, + "i/": {}, + "lmn": {}, + }}, + // with no prefix, marker and recursive traversal + {"", "d/e", true, map[string]struct{}{ + "d/f": {}, + "d/g/h": {}, + "i/j/k": {}, + "lmn": {}, + }}, + // with prefix, no marker and no recursive traversal + {"d/", "", false, map[string]struct{}{ + "d/e": {}, + "d/f": {}, + "d/g/": {}, + }}, + // with prefix, no marker and no recursive traversal + {"d/", "", true, map[string]struct{}{ + "d/e": {}, + "d/f": {}, + "d/g/h": {}, + }}, + // with prefix, marker and no recursive traversal + {"d/", "d/e", false, map[string]struct{}{ + "d/f": {}, + "d/g/": {}, + }}, + // with prefix, marker and recursive traversal + {"d/", "d/e", true, map[string]struct{}{ + "d/f": {}, + "d/g/h": {}, + }}, + } + for i, testCase := range testCases { + for entry := range startTreeWalk(volume, + testCase.prefix, testCase.marker, testCase.recursive, + listDir, endWalkCh) { + if _, found := testCase.expected[entry.entry]; !found { + t.Errorf("Test %d: Expected %s, but couldn't find", i+1, entry.entry) + } + } + } + err = removeAll(fsDir1) + if err != nil { + t.Error(err) + } +} + +func TestSortedness(t *testing.T) { + // Create a backend directories fsDir1. + fsDir1, err := ioutil.TempDir("", "minio-") + if err != nil { + t.Errorf("Unable to create tmp directory: %s", err) + } + + // Create two StorageAPIs disk1. + disk1, err := newStorageAPI(fsDir1) + if err != nil { + t.Errorf("Unable to create StorageAPI: %s", err) + } + + // Create listDir function. + listDir := listDirFactory(func(volume, prefix string) bool { + return !strings.HasSuffix(prefix, slashSeparator) + }, disk1) + + // Create the namespace. + var files = []string{ + "d/e", + "d/f", + "d/g/h", + "i/j/k", + "lmn", + } + err = createNamespace(disk1, volume, files) + if err != nil { + t.Fatal(err) + } + + endWalkCh := make(chan struct{}) + testCases := []struct { + prefix string + marker string + recursive bool + }{ + // with no prefix, no marker and no recursive traversal + {"", "", false}, + // with no prefix, no marker and recursive traversal + {"", "", true}, + // with no prefix, marker and no recursive traversal + {"", "d/e", false}, + // with no prefix, marker and recursive traversal + {"", "d/e", true}, + // with prefix, no marker and no recursive traversal + {"d/", "", false}, + // with prefix, no marker and no recursive traversal + {"d/", "", true}, + // with prefix, marker and no recursive traversal + {"d/", "d/e", false}, + // with prefix, marker and recursive traversal + {"d/", "d/e", true}, + } + for i, test := range testCases { + var actualEntries []string + for entry := range startTreeWalk(volume, + test.prefix, test.marker, test.recursive, + listDir, endWalkCh) { + actualEntries = append(actualEntries, entry.entry) + } + if !sort.IsSorted(sort.StringSlice(actualEntries)) { + t.Error(i+1, "Expected entries to be sort, but it wasn't") + } + } + + // Remove directory created for testing + err = removeAll(fsDir1) + if err != nil { + t.Error(err) + } +} + +func TestTreeWalkIsEnd(t *testing.T) { + // Create a backend directories fsDir1. + fsDir1, err := ioutil.TempDir("", "minio-") + if err != nil { + t.Errorf("Unable to create tmp directory: %s", err) + } + + // Create two StorageAPIs disk1. + disk1, err := newStorageAPI(fsDir1) + if err != nil { + t.Errorf("Unable to create StorageAPI: %s", err) + } + + // Create listDir function. + listDir := listDirFactory(func(volume, prefix string) bool { + return !strings.HasSuffix(prefix, slashSeparator) + }, disk1) + + // Create the namespace. + var files = []string{ + "d/e", + "d/f", + "d/g/h", + "i/j/k", + "lmn", + } + err = createNamespace(disk1, volume, files) + if err != nil { + t.Fatal(err) + } + + endWalkCh := make(chan struct{}) + testCases := []struct { + prefix string + marker string + recursive bool + expectedEntry string + }{ + // with no prefix, no marker and no recursive traversal + {"", "", false, "lmn"}, + // with no prefix, no marker and recursive traversal + {"", "", true, "lmn"}, + // with no prefix, marker and no recursive traversal + {"", "d/e", false, "lmn"}, + // with no prefix, marker and recursive traversal + {"", "d/e", true, "lmn"}, + // with prefix, no marker and no recursive traversal + {"d/", "", false, "d/g/"}, + // with prefix, no marker and no recursive traversal + {"d/", "", true, "d/g/h"}, + // with prefix, marker and no recursive traversal + {"d/", "d/e", false, "d/g/"}, + // with prefix, marker and recursive traversal + {"d/", "d/e", true, "d/g/h"}, + } + for i, test := range testCases { + var entry treeWalkResult + for entry = range startTreeWalk(volume, test.prefix, test.marker, test.recursive, listDir, endWalkCh) { + } + if entry.entry != test.expectedEntry { + t.Errorf("Test %d: Expected entry %s, but received %s with the EOF marker", i, test.expectedEntry, entry.entry) + } + if !entry.end { + t.Errorf("Test %d: Last entry %s, doesn't have EOF marker set", i, entry.entry) + } + } + + // Remove directory created for testing + err = removeAll(fsDir1) + if err != nil { + t.Error(err) + } +}