github.com/jaypipes/ghw@v0.21.1/pkg/snapshot/clonetree_linux_test.go (about) 1 // 2 // Use and distribution licensed under the Apache license version 2. 3 // 4 // See the COPYING file in the root project directory for full text. 5 // 6 7 package snapshot_test 8 9 import ( 10 "os" 11 "path/filepath" 12 "reflect" 13 "sort" 14 "strings" 15 "testing" 16 17 "github.com/jaypipes/ghw/pkg/snapshot" 18 ) 19 20 // NOTE: we intentionally use `os.RemoveAll` - not `snapshot.Cleanup` because we 21 // want to make sure we never leak directories. `snapshot.Cleanup` is used and 22 // tested explicitly in `unpack_test.go`. 23 24 // nolint: gocyclo 25 func TestCloneTree(t *testing.T) { 26 root, err := snapshot.Unpack(testDataSnapshot) 27 if err != nil { 28 t.Fatalf("Expected nil err, but got %v", err) 29 } 30 defer os.RemoveAll(root) 31 32 cloneRoot, err := os.MkdirTemp("", "ghw-test-clonetree-*") 33 if err != nil { 34 t.Fatalf("Expected nil err, but got %v", err) 35 } 36 defer os.RemoveAll(cloneRoot) 37 38 fileSpecs := []string{ 39 filepath.Join(root, "ghw-test-*"), 40 filepath.Join(root, "different/subtree/ghw*"), 41 filepath.Join(root, "nested/ghw-test*"), 42 filepath.Join(root, "nested/tree/of/subdirectories/forming/deep/unbalanced/tree/ghw-test-3"), 43 } 44 err = snapshot.CopyFilesInto(fileSpecs, cloneRoot, nil) 45 if err != nil { 46 t.Fatalf("Expected nil err, but got %v", err) 47 } 48 49 origContent, err := scanTree(root, "", []string{""}) 50 if err != nil { 51 t.Fatalf("Expected nil err, but got %v", err) 52 } 53 sort.Strings(origContent) 54 55 cloneContent, err := scanTree(cloneRoot, cloneRoot, []string{"", "/tmp"}) 56 if err != nil { 57 t.Fatalf("Expected nil err, but got %v", err) 58 } 59 sort.Strings(cloneContent) 60 61 if len(origContent) != len(cloneContent) { 62 t.Fatalf("Expected tree size %d got %d", len(origContent), len(cloneContent)) 63 } 64 if !reflect.DeepEqual(origContent, cloneContent) { 65 t.Fatalf("subtree content different expected %#v got %#v", origContent, cloneContent) 66 } 67 } 68 69 // nolint: gocyclo 70 func TestCloneSystemTree(t *testing.T) { 71 // ok, this is tricky. Validating a cloned tree is a complex business. 72 // We do the bare minimum here to check that both the CloneTree and the ValidateClonedTree did something 73 // sensible. To really do a meaningful test we need a more advanced functional test, starting with from 74 // a ghw snapshot. 75 76 cloneRoot, err := os.MkdirTemp("", "ghw-test-clonetree-*") 77 if err != nil { 78 t.Fatalf("Expected nil err, but got %v", err) 79 } 80 defer os.RemoveAll(cloneRoot) 81 82 err = snapshot.CloneTreeInto(cloneRoot) 83 if err != nil { 84 t.Fatalf("Expected nil err, but got %v", err) 85 } 86 87 missing, err := snapshot.ValidateClonedTree(snapshot.ExpectedCloneContent(), cloneRoot) 88 if err != nil { 89 t.Fatalf("Expected nil err, but got %v", err) 90 } 91 92 if len(missing) > 0 && areEntriesOnSysfs(missing) { 93 t.Fatalf("Expected content %#v missing into the cloned tree %q", missing, cloneRoot) 94 } 95 } 96 97 func areEntriesOnSysfs(sysfsEntries []string) bool { 98 // turns out some ISA bridges do not actually expose the driver entry. The reason is not clear. 99 // So let's check if we actually have the entry we were looking for on sysfs. If so, we 100 // actually failed to clone an entry, and we must fail the test. Otherwise we carry on. 101 for _, sysfsEntry := range sysfsEntries { 102 if _, err := os.Lstat(sysfsEntry); err == nil { 103 return true 104 } 105 } 106 return false 107 } 108 109 func scanTree(root, prefix string, excludeList []string) ([]string, error) { 110 var contents []string 111 return contents, filepath.Walk(root, func(path string, info os.FileInfo, err error) error { 112 if err != nil { 113 return err 114 } 115 if fp := strings.TrimPrefix(path, prefix); !includedInto(fp, excludeList) { 116 contents = append(contents, fp) 117 } 118 return nil 119 }) 120 } 121 122 func includedInto(s string, items []string) bool { 123 if items == nil { 124 return false 125 } 126 for _, item := range items { 127 if s == item { 128 return true 129 } 130 } 131 return false 132 }