github.com/anchore/syft@v1.4.2-0.20240516191711-1bec1fc5d397/syft/file/cataloger/filemetadata/cataloger_test.go (about) 1 package filemetadata 2 3 import ( 4 "context" 5 "os" 6 "testing" 7 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10 11 stereoscopeFile "github.com/anchore/stereoscope/pkg/file" 12 "github.com/anchore/stereoscope/pkg/imagetest" 13 "github.com/anchore/syft/syft/file" 14 "github.com/anchore/syft/syft/source" 15 "github.com/anchore/syft/syft/source/stereoscopesource" 16 ) 17 18 func TestFileMetadataCataloger(t *testing.T) { 19 testImage := "image-file-type-mix" 20 21 img := imagetest.GetFixtureImage(t, "docker-archive", testImage) 22 23 c := NewCataloger() 24 25 src := stereoscopesource.New(img, stereoscopesource.ImageConfig{ 26 Reference: testImage, 27 }) 28 29 resolver, err := src.FileResolver(source.SquashedScope) 30 require.NoError(t, err) 31 32 actual, err := c.Catalog(context.Background(), resolver) 33 require.NoError(t, err) 34 35 tests := []struct { 36 path string 37 exists bool 38 expected file.Metadata 39 err bool 40 }{ 41 // note: it is difficult to add a hardlink-based test in a cross-platform way and is already covered well in stereoscope 42 { 43 path: "/file-1.txt", 44 exists: true, 45 expected: file.Metadata{ 46 FileInfo: stereoscopeFile.ManualInfo{ 47 NameValue: "file-1.txt", 48 ModeValue: 0644, 49 SizeValue: 7, 50 }, 51 Path: "/file-1.txt", 52 Type: stereoscopeFile.TypeRegular, 53 UserID: 1, 54 GroupID: 2, 55 MIMEType: "text/plain", 56 }, 57 }, 58 { 59 path: "/symlink-1", 60 exists: true, 61 expected: file.Metadata{ 62 Path: "/symlink-1", 63 FileInfo: stereoscopeFile.ManualInfo{ 64 NameValue: "symlink-1", 65 ModeValue: 0777 | os.ModeSymlink, 66 }, 67 Type: stereoscopeFile.TypeSymLink, 68 LinkDestination: "file-1.txt", 69 UserID: 0, 70 GroupID: 0, 71 MIMEType: "", 72 }, 73 }, 74 { 75 path: "/char-device-1", 76 exists: true, 77 expected: file.Metadata{ 78 Path: "/char-device-1", 79 FileInfo: stereoscopeFile.ManualInfo{ 80 NameValue: "char-device-1", 81 ModeValue: 0644 | os.ModeDevice | os.ModeCharDevice, 82 }, 83 Type: stereoscopeFile.TypeCharacterDevice, 84 UserID: 0, 85 GroupID: 0, 86 MIMEType: "", 87 }, 88 }, 89 { 90 path: "/block-device-1", 91 exists: true, 92 expected: file.Metadata{ 93 Path: "/block-device-1", 94 FileInfo: stereoscopeFile.ManualInfo{ 95 NameValue: "block-device-1", 96 ModeValue: 0644 | os.ModeDevice, 97 }, 98 Type: stereoscopeFile.TypeBlockDevice, 99 UserID: 0, 100 GroupID: 0, 101 MIMEType: "", 102 }, 103 }, 104 { 105 path: "/fifo-1", 106 exists: true, 107 expected: file.Metadata{ 108 Path: "/fifo-1", 109 FileInfo: stereoscopeFile.ManualInfo{ 110 NameValue: "fifo-1", 111 ModeValue: 0644 | os.ModeNamedPipe, 112 }, 113 Type: stereoscopeFile.TypeFIFO, 114 UserID: 0, 115 GroupID: 0, 116 MIMEType: "", 117 }, 118 }, 119 { 120 path: "/bin", 121 exists: true, 122 expected: file.Metadata{ 123 Path: "/bin", 124 FileInfo: stereoscopeFile.ManualInfo{ 125 NameValue: "bin", 126 ModeValue: 0755 | os.ModeDir, 127 }, 128 Type: stereoscopeFile.TypeDirectory, 129 UserID: 0, 130 GroupID: 0, 131 MIMEType: "", 132 }, 133 }, 134 } 135 136 for _, test := range tests { 137 t.Run(test.path, func(t *testing.T) { 138 _, ref, err := img.SquashedTree().File(stereoscopeFile.Path(test.path)) 139 require.NoError(t, err) 140 141 l := file.NewLocationFromImage(test.path, *ref.Reference, img) 142 143 if _, ok := actual[l.Coordinates]; ok { 144 // we're not interested in keeping the test fixtures up to date with the latest file modification times 145 // thus ModTime is not under test 146 fi := test.expected.FileInfo.(stereoscopeFile.ManualInfo) 147 fi.ModTimeValue = actual[l.Coordinates].ModTime() 148 test.expected.FileInfo = fi 149 } 150 151 assert.True(t, test.expected.Equal(actual[l.Coordinates])) 152 }) 153 } 154 155 } 156 157 func TestFileMetadataCataloger_GivenCoordinates(t *testing.T) { 158 testImage := "image-file-type-mix" 159 160 img := imagetest.GetFixtureImage(t, "docker-archive", testImage) 161 162 c := NewCataloger() 163 164 src := stereoscopesource.New(img, stereoscopesource.ImageConfig{ 165 Reference: testImage, 166 }) 167 168 resolver, err := src.FileResolver(source.SquashedScope) 169 require.NoError(t, err) 170 171 tests := []struct { 172 path string 173 exists bool 174 expected file.Metadata 175 }{ 176 { 177 path: "/file-1.txt", 178 exists: true, 179 expected: file.Metadata{ 180 FileInfo: stereoscopeFile.ManualInfo{ 181 NameValue: "file-1.txt", 182 ModeValue: 0644, 183 SizeValue: 7, 184 }, 185 Path: "/file-1.txt", 186 Type: stereoscopeFile.TypeRegular, 187 UserID: 1, 188 GroupID: 2, 189 MIMEType: "text/plain", 190 }, 191 }, 192 } 193 194 for _, test := range tests { 195 t.Run(test.path, func(t *testing.T) { 196 _, ref, err := img.SquashedTree().File(stereoscopeFile.Path(test.path)) 197 require.NoError(t, err) 198 199 l := file.NewLocationFromImage(test.path, *ref.Reference, img) 200 201 // note: an important difference between this test and the previous is that this test is using a list 202 // of specific coordinates to catalog 203 actual, err := c.Catalog(context.Background(), resolver, l.Coordinates) 204 require.NoError(t, err) 205 require.Len(t, actual, 1) 206 207 if _, ok := actual[l.Coordinates]; ok { 208 // we're not interested in keeping the test fixtures up to date with the latest file modification times 209 // thus ModTime is not under test 210 fi := test.expected.FileInfo.(stereoscopeFile.ManualInfo) 211 fi.ModTimeValue = actual[l.Coordinates].ModTime() 212 test.expected.FileInfo = fi 213 } 214 215 assert.True(t, test.expected.Equal(actual[l.Coordinates])) 216 }) 217 } 218 219 }