github.com/anchore/syft@v1.38.2/syft/pkg/cataloger/alpine/cataloger_test.go (about) 1 package alpine 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/google/go-cmp/cmp" 8 "github.com/google/go-cmp/cmp/cmpopts" 9 10 "github.com/anchore/syft/syft/artifact" 11 "github.com/anchore/syft/syft/file" 12 "github.com/anchore/syft/syft/pkg" 13 "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" 14 ) 15 16 func TestApkDBCataloger(t *testing.T) { 17 dbLocation := file.NewLocation("lib/apk/db/installed") 18 ctx := context.TODO() 19 bashPkg := pkg.Package{ 20 Name: "bash", 21 Version: "5.2.21-r0", 22 Type: pkg.ApkPkg, 23 FoundBy: "apk-db-cataloger", 24 Licenses: pkg.NewLicenseSet( 25 pkg.NewLicenseFromLocationsWithContext(ctx, "GPL-3.0-or-later", dbLocation), 26 ), 27 Locations: file.NewLocationSet(dbLocation), 28 Metadata: pkg.ApkDBEntry{ 29 Package: "bash", 30 OriginPackage: "bash", 31 Maintainer: "Natanael Copa <ncopa@alpinelinux.org>", 32 Version: "5.2.21-r0", 33 Architecture: "x86_64", 34 URL: "https://www.gnu.org/software/bash/bash.html", 35 Description: "The GNU Bourne Again shell", 36 Size: 448728, 37 InstalledSize: 1396736, 38 Dependencies: []string{ 39 "/bin/sh", "so:libc.musl-x86_64.so.1", "so:libreadline.so.8", 40 }, 41 Provides: []string{ 42 "cmd:bash=5.2.21-r0", 43 }, 44 // note: files not provided and not under test 45 }, 46 } 47 48 busyboxBinshPkg := pkg.Package{ 49 Name: "busybox-binsh", 50 Version: "1.36.1-r15", 51 Type: pkg.ApkPkg, 52 FoundBy: "apk-db-cataloger", 53 Licenses: pkg.NewLicenseSet( 54 pkg.NewLicenseFromLocationsWithContext(ctx, "GPL-2.0-only", dbLocation), 55 ), 56 Locations: file.NewLocationSet(dbLocation), 57 Metadata: pkg.ApkDBEntry{ 58 Package: "busybox-binsh", 59 OriginPackage: "busybox", 60 Maintainer: "Sören Tempel <soeren+alpine@soeren-tempel.net>", 61 Version: "1.36.1-r15", 62 Architecture: "x86_64", 63 URL: "https://busybox.net/", 64 Description: "busybox ash /bin/sh", 65 Size: 1543, 66 InstalledSize: 8192, 67 Dependencies: []string{ 68 "busybox=1.36.1-r15", 69 }, 70 Provides: []string{ 71 "/bin/sh", "cmd:sh=1.36.1-r15", 72 }, 73 // note: files not provided and not under test 74 }, 75 } 76 77 muslPkg := pkg.Package{ 78 Name: "musl", 79 Version: "1.2.4_git20230717-r4", 80 Type: pkg.ApkPkg, 81 FoundBy: "apk-db-cataloger", 82 Licenses: pkg.NewLicenseSet( 83 pkg.NewLicenseFromLocationsWithContext(ctx, "MIT", dbLocation), 84 ), 85 Locations: file.NewLocationSet(dbLocation), 86 Metadata: pkg.ApkDBEntry{ 87 Package: "musl", 88 OriginPackage: "musl", 89 Maintainer: "Timo Teräs <timo.teras@iki.fi>", 90 Version: "1.2.4_git20230717-r4", 91 Architecture: "x86_64", 92 URL: "https://musl.libc.org/", 93 Description: "the musl c library (libc) implementation", 94 Size: 407278, 95 InstalledSize: 667648, 96 Dependencies: []string{}, 97 Provides: []string{ 98 "so:libc.musl-x86_64.so.1=1", 99 }, 100 // note: files not provided and not under test 101 }, 102 } 103 104 readlinePkg := pkg.Package{ 105 Name: "readline", 106 Version: "8.2.1-r2", 107 Type: pkg.ApkPkg, 108 FoundBy: "apk-db-cataloger", 109 Licenses: pkg.NewLicenseSet( 110 pkg.NewLicenseFromLocationsWithContext(ctx, "GPL-2.0-or-later", dbLocation), 111 ), 112 Locations: file.NewLocationSet(dbLocation), 113 Metadata: pkg.ApkDBEntry{ 114 Package: "readline", 115 OriginPackage: "readline", 116 Maintainer: "Natanael Copa <ncopa@alpinelinux.org>", 117 Version: "8.2.1-r2", 118 Architecture: "x86_64", 119 URL: "https://tiswww.cwru.edu/php/chet/readline/rltop.html", 120 Description: "GNU readline library", 121 Size: 119878, 122 InstalledSize: 303104, 123 Dependencies: []string{ 124 "so:libc.musl-x86_64.so.1", "so:libncursesw.so.6", 125 }, 126 Provides: []string{ 127 "so:libreadline.so.8=8.2", 128 }, 129 // note: files not provided and not under test 130 }, 131 } 132 133 expectedPkgs := []pkg.Package{ 134 bashPkg, 135 busyboxBinshPkg, 136 muslPkg, 137 readlinePkg, 138 } 139 140 // # apk info --depends bash 141 // bash-5.2.21-r0 depends on: 142 // /bin/sh 143 // so:libc.musl-x86_64.so.1 144 // so:libreadline.so.8 145 // 146 // # apk info --who-owns /bin/sh 147 // /bin/sh is owned by busybox-binsh-1.36.1-r15 148 // 149 // # find / | grep musl 150 // /lib/ld-musl-x86_64.so.1 151 // /lib/libc.musl-x86_64.so.1 152 // 153 // # apk info --who-owns '/lib/libc.musl-x86_64.so.1' 154 // /lib/libc.musl-x86_64.so.1 is owned by musl-1.2.4_git20230717-r4 155 // 156 // # find / | grep libreadline 157 // /usr/lib/libreadline.so.8.2 158 // /usr/lib/libreadline.so.8 159 // 160 // # apk info --who-owns '/usr/lib/libreadline.so.8' 161 // /usr/lib/libreadline.so.8 is owned by readline-8.2.1-r2 162 163 expectedRelationships := []artifact.Relationship{ 164 { 165 From: busyboxBinshPkg, 166 To: bashPkg, 167 Type: artifact.DependencyOfRelationship, 168 }, 169 { 170 From: readlinePkg, 171 To: bashPkg, 172 Type: artifact.DependencyOfRelationship, 173 }, 174 { 175 From: muslPkg, 176 To: readlinePkg, 177 Type: artifact.DependencyOfRelationship, 178 }, 179 { 180 From: muslPkg, 181 To: bashPkg, 182 Type: artifact.DependencyOfRelationship, 183 }, 184 } 185 186 pkgtest.NewCatalogTester(). 187 FromDirectory(t, "test-fixtures/multiple-1"). 188 WithCompareOptions(cmpopts.IgnoreFields(pkg.ApkDBEntry{}, "Files", "GitCommit", "Checksum")). 189 Expects(expectedPkgs, expectedRelationships). 190 TestCataloger(t, NewDBCataloger()) 191 192 } 193 194 func Test_corruptDb(t *testing.T) { 195 pkgtest.NewCatalogTester(). 196 FromDirectory(t, "test-fixtures/corrupt"). 197 WithCompareOptions(cmpopts.IgnoreFields(pkg.ApkDBEntry{}, "Files", "GitCommit", "Checksum")). 198 WithError(). 199 TestCataloger(t, NewDBCataloger()) 200 } 201 202 func TestCatalogerDependencyTree(t *testing.T) { 203 assertion := func(t *testing.T, pkgs []pkg.Package, relationships []artifact.Relationship) { 204 expected := map[string][]string{ 205 "alpine-baselayout": {"busybox", "alpine-baselayout-data", "musl"}, 206 "apk-tools": {"ca-certificates-bundle", "musl", "libcrypto1.1", "libssl1.1", "zlib"}, 207 "busybox": {"musl"}, 208 "libc-utils": {"musl-utils"}, 209 "libcrypto1.1": {"musl"}, 210 "libssl1.1": {"musl", "libcrypto1.1"}, 211 "musl-utils": {"scanelf", "musl"}, 212 "scanelf": {"musl"}, 213 "ssl_client": {"musl", "libcrypto1.1", "libssl1.1"}, 214 "zlib": {"musl"}, 215 } 216 pkgsByID := make(map[artifact.ID]pkg.Package) 217 for _, p := range pkgs { 218 p.SetID() 219 pkgsByID[p.ID()] = p 220 } 221 222 actualDependencies := make(map[string][]string) 223 224 for _, r := range relationships { 225 switch r.Type { 226 case artifact.DependencyOfRelationship: 227 to := pkgsByID[r.To.ID()] 228 from := pkgsByID[r.From.ID()] 229 actualDependencies[to.Name] = append(actualDependencies[to.Name], from.Name) 230 default: 231 t.Fatalf("unexpected relationship type: %+v", r.Type) 232 } 233 } 234 235 if d := cmp.Diff(expected, actualDependencies); d != "" { 236 t.Fail() 237 t.Log(d) 238 } 239 } 240 241 pkgtest.NewCatalogTester(). 242 FromDirectory(t, "test-fixtures/multiple-2"). 243 ExpectsAssertion(assertion). 244 TestCataloger(t, NewDBCataloger()) 245 246 } 247 248 func TestCataloger_Globs(t *testing.T) { 249 tests := []struct { 250 name string 251 fixture string 252 expected []string 253 }{ 254 { 255 name: "obtain DB files", 256 fixture: "test-fixtures/glob-paths", 257 expected: []string{"lib/apk/db/installed"}, 258 }, 259 } 260 261 for _, test := range tests { 262 t.Run(test.name, func(t *testing.T) { 263 pkgtest.NewCatalogTester(). 264 FromDirectory(t, test.fixture). 265 ExpectsResolverContentQueries(test.expected). 266 IgnoreUnfulfilledPathResponses("etc/apk/repositories"). 267 TestCataloger(t, NewDBCataloger()) 268 }) 269 } 270 }