github.com/quay/claircore@v1.5.28/whiteout/resolver_test.go (about) 1 package whiteout 2 3 import ( 4 "context" 5 "crypto/sha256" 6 "io" 7 "testing" 8 9 "github.com/quay/claircore" 10 11 "github.com/quay/zlog" 12 ) 13 14 func Digest(name string) claircore.Digest { 15 h := sha256.New() 16 io.WriteString(h, name) 17 d, err := claircore.NewDigest("sha256", h.Sum(nil)) 18 if err != nil { 19 panic(err) 20 } 21 return d 22 } 23 24 func TestResolver(t *testing.T) { 25 firstLayerHash := Digest("first layer") 26 secondLayerHash := Digest("second layer") 27 thirdLayerHash := Digest("third layer") 28 29 type testcase struct { 30 Name string 31 Report *claircore.IndexReport 32 Layers []*claircore.Layer 33 LenPackage, LenEnvs int 34 } 35 36 tests := []testcase{ 37 { 38 Name: "Simple", 39 Report: &claircore.IndexReport{ 40 Packages: map[string]*claircore.Package{ 41 "1": { 42 Name: "something interesting", 43 Filepath: "a/path/to/some/file/site-packages/a_package/METADATA", 44 }, 45 "2": { 46 Name: "something uninteresting", 47 Filepath: "a/path/to/some/file/site-packages/b_package/METADATA", 48 }, 49 }, 50 Environments: map[string][]*claircore.Environment{ 51 "1": {{IntroducedIn: firstLayerHash}}, 52 "2": {{IntroducedIn: firstLayerHash}}, 53 }, 54 Files: map[string]claircore.File{ 55 secondLayerHash.String(): { 56 Path: "a/path/to/some/file/site-packages/.wh.a_package", 57 Kind: claircore.FileKindWhiteout, 58 }, 59 }, 60 }, 61 Layers: []*claircore.Layer{ 62 {Hash: firstLayerHash}, 63 {Hash: secondLayerHash}, 64 }, 65 LenPackage: 1, 66 LenEnvs: 1, 67 }, 68 { 69 Name: "SimpleNoDelete", 70 Report: &claircore.IndexReport{ 71 Packages: map[string]*claircore.Package{ 72 "1": { 73 Name: "something interesting", 74 Filepath: "a/path/to/some/file/site-packages/a_package/METADATA", 75 }, 76 "2": { 77 Name: "something uninteresting", 78 Filepath: "a/path/to/some/file/site-packages/b_package/METADATA", 79 }, 80 }, 81 Environments: map[string][]*claircore.Environment{ 82 "1": {{IntroducedIn: firstLayerHash}}, 83 "2": {{IntroducedIn: firstLayerHash}}, 84 }, 85 Files: map[string]claircore.File{ 86 secondLayerHash.String(): { 87 Path: "a/path/to/some/different_file/site-packages/.wh.a_package", 88 Kind: claircore.FileKindWhiteout, 89 }, 90 secondLayerHash.String(): { 91 Path: "a/path/to/some/different_file/.wh.site-packages", 92 Kind: claircore.FileKindWhiteout, 93 }, 94 secondLayerHash.String(): { 95 Path: "a/path/to/some/.wh.different_file", 96 Kind: claircore.FileKindWhiteout, 97 }, 98 }, 99 }, 100 Layers: []*claircore.Layer{ 101 {Hash: firstLayerHash}, 102 {Hash: secondLayerHash}, 103 }, 104 LenPackage: 2, 105 LenEnvs: 2, 106 }, 107 { 108 Name: "FatFinger", 109 Report: &claircore.IndexReport{ 110 Packages: map[string]*claircore.Package{ 111 "1": { 112 Name: "something interesting", 113 Filepath: "a/path/to/some/file/site-packages/a_package/METADATA", 114 }, 115 "2": { 116 Name: "something uninteresting", 117 Filepath: "a/path/to/some/file/site-packages/b_package/METADATA", 118 }, 119 }, 120 Environments: map[string][]*claircore.Environment{ 121 "1": {{IntroducedIn: firstLayerHash}}, 122 "2": {{IntroducedIn: firstLayerHash}}, 123 }, 124 Files: map[string]claircore.File{ 125 secondLayerHash.String(): { 126 Path: "a/path/to/some/file/.wh.site-packages", 127 Kind: claircore.FileKindWhiteout, 128 }, 129 }, 130 }, 131 Layers: []*claircore.Layer{ 132 {Hash: firstLayerHash}, 133 {Hash: secondLayerHash}, 134 }, 135 LenPackage: 0, 136 LenEnvs: 0, 137 }, 138 { 139 Name: "MaskedDirectory", 140 Report: &claircore.IndexReport{ 141 Packages: map[string]*claircore.Package{ 142 "1": { 143 Name: "something interesting", 144 Filepath: "a/path/to/some/file/site-packages/a_package/METADATA", 145 }, 146 "2": { 147 Name: "something uninteresting", 148 Filepath: "a/path/to/some/file/site-packages/b_package/METADATA", 149 }, 150 }, 151 Environments: map[string][]*claircore.Environment{ 152 "1": {{IntroducedIn: firstLayerHash}}, 153 "2": {{IntroducedIn: firstLayerHash}}, 154 }, 155 Files: map[string]claircore.File{ 156 firstLayerHash.String(): { // whiteout is in the same layer as packages 157 Path: "a/path/to/some/file/site-packages/.wh.b_package", 158 Kind: claircore.FileKindWhiteout, 159 }, 160 }, 161 }, 162 Layers: []*claircore.Layer{ 163 {Hash: firstLayerHash}, 164 {Hash: secondLayerHash}, 165 }, 166 LenPackage: 2, 167 LenEnvs: 2, 168 }, 169 { 170 Name: "CommonPrefixDistinctDirs", 171 Report: &claircore.IndexReport{ 172 Packages: map[string]*claircore.Package{ 173 "1": { 174 Name: "something interesting", 175 Filepath: "a/path/to/some/file/site-packages/a_package/METADATA", 176 }, 177 "2": { 178 Name: "something uninteresting", 179 Filepath: "a/path/to/some/file/site-packages/b_package/METADATA", 180 }, 181 }, 182 Environments: map[string][]*claircore.Environment{ 183 "1": {{IntroducedIn: firstLayerHash}}, 184 "2": {{IntroducedIn: firstLayerHash}}, 185 }, 186 Files: map[string]claircore.File{ 187 secondLayerHash.String(): { 188 Path: "a/path/to/some/file/site/.wh..wh..opq", 189 Kind: claircore.FileKindWhiteout, 190 }, 191 }, 192 }, 193 Layers: []*claircore.Layer{ 194 {Hash: firstLayerHash}, 195 {Hash: secondLayerHash}, 196 }, 197 LenPackage: 2, 198 LenEnvs: 2, 199 }, 200 { 201 Name: "Opaque", 202 Report: &claircore.IndexReport{ 203 Packages: map[string]*claircore.Package{ 204 "1": { 205 Name: "something interesting", 206 Filepath: "a/path/to/some/file/site-packages/a_package/METADATA", 207 }, 208 "2": { 209 Name: "something uninteresting", 210 Filepath: "a/path/to/some/file/site-packages/b_package/METADATA", 211 }, 212 }, 213 Environments: map[string][]*claircore.Environment{ 214 "1": {{IntroducedIn: firstLayerHash}}, 215 "2": {{IntroducedIn: firstLayerHash}}, 216 }, 217 Files: map[string]claircore.File{ 218 secondLayerHash.String(): { 219 Path: "a/path/to/some/file/site-packages/.wh..wh..opq", 220 Kind: claircore.FileKindWhiteout, 221 }, 222 }, 223 }, 224 Layers: []*claircore.Layer{ 225 {Hash: firstLayerHash}, 226 {Hash: secondLayerHash}, 227 }, 228 LenPackage: 0, 229 LenEnvs: 0, 230 }, 231 { 232 Name: "AddDeleteAdd", 233 Report: &claircore.IndexReport{ 234 Packages: map[string]*claircore.Package{ 235 "1": { 236 Name: "something interesting", 237 Filepath: "a/path/to/some/file/site-packages/a_package/METADATA", 238 }, 239 }, 240 Environments: map[string][]*claircore.Environment{ 241 "1": {{IntroducedIn: firstLayerHash}, {IntroducedIn: thirdLayerHash}}, 242 }, 243 Files: map[string]claircore.File{ 244 secondLayerHash.String(): { // whiteout is sandwiched 245 Path: "a/path/to/some/file/site-packages/.wh.a_package", 246 Kind: claircore.FileKindWhiteout, 247 }, 248 }, 249 }, 250 Layers: []*claircore.Layer{ 251 {Hash: firstLayerHash}, 252 {Hash: secondLayerHash}, 253 {Hash: thirdLayerHash}, 254 }, 255 LenPackage: 1, 256 LenEnvs: 1, 257 }, 258 } 259 260 r := &Resolver{} 261 for _, tc := range tests { 262 t.Run(tc.Name, func(t *testing.T) { 263 ctx := zlog.Test(context.Background(), t) 264 report := r.Resolve(ctx, tc.Report, tc.Layers) 265 if tc.LenPackage != len(report.Packages) { 266 t.Fatalf("wrong number of packages: expected: %d got: %d", tc.LenPackage, len(report.Packages)) 267 } 268 if tc.LenEnvs != len(report.Environments) { 269 t.Fatalf("wrong number of environments: expected: %d got: %d", tc.LenEnvs, len(report.Environments)) 270 } 271 }) 272 273 } 274 } 275 276 func TestIsDeleted(t *testing.T) { 277 type testcase struct { 278 Path string 279 Whiteout string 280 Deleted bool 281 } 282 283 for _, tc := range []testcase{ 284 { 285 Path: "a/b", 286 Whiteout: "a/.wh.b", 287 Deleted: true, 288 }, 289 { 290 Path: "a/c", 291 Whiteout: "a/.wh.b", 292 Deleted: false, 293 }, 294 { 295 Path: "a/b/c/foo", 296 Whiteout: "a/.wh..wh..opq", 297 Deleted: true, 298 }, 299 { 300 Path: "c/foo", 301 Whiteout: "a/.wh..wh..opq", 302 Deleted: false, 303 }, 304 { 305 Path: "a/file.wh.txt", 306 Whiteout: "a/.wh.file.wh.txt", 307 Deleted: true, 308 }, 309 { 310 Path: "file.wh.d/file.conf", 311 Whiteout: "file.wh.d/.wh.file.conf", 312 Deleted: true, 313 }, 314 { 315 Path: "some/file", 316 Whiteout: "not/a/white/out", 317 Deleted: false, 318 }, 319 { 320 Path: "a", 321 Whiteout: "a/b/.wh..wh..opq", 322 Deleted: false, 323 }, 324 { 325 Path: "a", 326 Whiteout: "a/.wh..wh..opq", 327 Deleted: false, 328 }, 329 } { 330 got, want := fileIsDeleted(tc.Path, tc.Whiteout), tc.Deleted 331 if got != want { 332 t.Fail() 333 } 334 t.Logf("%s, %s\tgot: %v, want: %v", tc.Whiteout, tc.Path, got, want) 335 } 336 }