github.com/nextlinux/gosbom@v0.81.1-0.20230627115839-1ff50c281391/gosbom/file/cataloger/filedigest/cataloger_test.go (about) 1 package filedigest 2 3 import ( 4 "crypto" 5 "fmt" 6 "io" 7 "os" 8 "path/filepath" 9 "testing" 10 11 "github.com/nextlinux/gosbom/gosbom/file" 12 "github.com/nextlinux/gosbom/gosbom/source" 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/require" 15 16 stereoscopeFile "github.com/anchore/stereoscope/pkg/file" 17 "github.com/anchore/stereoscope/pkg/imagetest" 18 ) 19 20 func testDigests(t testing.TB, root string, files []string, hashes ...crypto.Hash) map[file.Coordinates][]file.Digest { 21 digests := make(map[file.Coordinates][]file.Digest) 22 23 for _, f := range files { 24 fh, err := os.Open(filepath.Join(root, f)) 25 if err != nil { 26 t.Fatalf("could not open %q : %+v", f, err) 27 } 28 b, err := io.ReadAll(fh) 29 if err != nil { 30 t.Fatalf("could not read %q : %+v", f, err) 31 } 32 33 if len(b) == 0 { 34 // we don't keep digests for empty files 35 digests[file.NewLocation(f).Coordinates] = []file.Digest{} 36 continue 37 } 38 39 for _, hash := range hashes { 40 h := hash.New() 41 h.Write(b) 42 digests[file.NewLocation(f).Coordinates] = append(digests[file.NewLocation(f).Coordinates], file.Digest{ 43 Algorithm: file.CleanDigestAlgorithmName(hash.String()), 44 Value: fmt.Sprintf("%x", h.Sum(nil)), 45 }) 46 } 47 } 48 49 return digests 50 } 51 52 func TestDigestsCataloger(t *testing.T) { 53 54 tests := []struct { 55 name string 56 digests []crypto.Hash 57 files []string 58 expected map[file.Coordinates][]file.Digest 59 }{ 60 { 61 name: "md5", 62 digests: []crypto.Hash{crypto.MD5}, 63 files: []string{"test-fixtures/last/empty/empty", "test-fixtures/last/path.txt"}, 64 expected: testDigests(t, "test-fixtures/last", []string{"empty/empty", "path.txt"}, crypto.MD5), 65 }, 66 { 67 name: "md5-sha1-sha256", 68 digests: []crypto.Hash{crypto.MD5, crypto.SHA1, crypto.SHA256}, 69 files: []string{"test-fixtures/last/empty/empty", "test-fixtures/last/path.txt"}, 70 expected: testDigests(t, "test-fixtures/last", []string{"empty/empty", "path.txt"}, crypto.MD5, crypto.SHA1, crypto.SHA256), 71 }, 72 } 73 74 for _, test := range tests { 75 t.Run(test.name, func(t *testing.T) { 76 c := NewCataloger(test.digests) 77 78 src, err := source.NewFromDirectory("test-fixtures/last/") 79 require.NoError(t, err) 80 81 resolver, err := src.FileResolver(source.SquashedScope) 82 require.NoError(t, err) 83 84 actual, err := c.Catalog(resolver) 85 require.NoError(t, err) 86 87 assert.Equal(t, test.expected, actual, "mismatched digests") 88 }) 89 } 90 } 91 92 func TestDigestsCataloger_MixFileTypes(t *testing.T) { 93 testImage := "image-file-type-mix" 94 95 img := imagetest.GetFixtureImage(t, "docker-archive", testImage) 96 97 src, err := source.NewFromImage(img, "---") 98 if err != nil { 99 t.Fatalf("could not create source: %+v", err) 100 } 101 102 resolver, err := src.FileResolver(source.SquashedScope) 103 if err != nil { 104 t.Fatalf("could not create resolver: %+v", err) 105 } 106 107 tests := []struct { 108 path string 109 expected string 110 }{ 111 { 112 path: "/file-1.txt", 113 expected: "888c139e550867814eb7c33b84d76e4d", 114 }, 115 // this is difficult to reproduce in a cross-platform way 116 //{ 117 // path: "/hardlink-1", 118 //}, 119 { 120 path: "/symlink-1", 121 }, 122 { 123 path: "/char-device-1", 124 }, 125 { 126 path: "/block-device-1", 127 }, 128 { 129 path: "/fifo-1", 130 }, 131 { 132 path: "/bin", 133 }, 134 } 135 136 for _, test := range tests { 137 t.Run(test.path, func(t *testing.T) { 138 c := NewCataloger([]crypto.Hash{crypto.MD5}) 139 140 actual, err := c.Catalog(resolver) 141 if err != nil { 142 t.Fatalf("could not catalog: %+v", err) 143 } 144 145 _, ref, err := img.SquashedTree().File(stereoscopeFile.Path(test.path)) 146 if err != nil { 147 t.Fatalf("unable to get file=%q : %+v", test.path, err) 148 } 149 l := file.NewLocationFromImage(test.path, *ref.Reference, img) 150 151 if len(actual[l.Coordinates]) == 0 { 152 if test.expected != "" { 153 t.Fatalf("no digest found, but expected one") 154 } 155 156 } else { 157 assert.Equal(t, actual[l.Coordinates][0].Value, test.expected, "mismatched digests") 158 } 159 }) 160 } 161 }