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  }