github.com/anchore/syft@v1.38.2/syft/pkg/cataloger/nix/cataloger_test.go (about)

     1  package nix
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/google/go-cmp/cmp"
     7  	"github.com/scylladb/go-set/strset"
     8  	"github.com/stretchr/testify/assert"
     9  	"github.com/stretchr/testify/require"
    10  	_ "modernc.org/sqlite"
    11  
    12  	"github.com/anchore/syft/syft/artifact"
    13  	"github.com/anchore/syft/syft/file"
    14  	"github.com/anchore/syft/syft/pkg"
    15  	"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
    16  )
    17  
    18  func TestCataloger_Image(t *testing.T) {
    19  	tests := []struct {
    20  		fixture  string
    21  		wantPkgs []string
    22  		wantRel  []string
    23  	}{
    24  		{
    25  			// $ nix-store -q --tree $(which jq)
    26  			//
    27  			// /nix/store/nzwfgsp28vgxv7n2gl5fxqkca9awh4dz-jq-1.6-bin3.4
    28  			// ├───/nix/store/02mqs1by2vab9yzw0qc4j7463w78p3ps-glibc-2.37-8
    29  			// │   ├───/nix/store/cw8fpl8r1x9rmaqj55fwbfnnrgw7b40k-libidn2-2.3.4
    30  			// │   │   ├───/nix/store/h1ysk4vvw48winwmh38rvnsj0dlsz7c1-libunistring-1.1
    31  			// │   │   │   └───/nix/store/h1ysk4vvw48winwmh38rvnsj0dlsz7c1-libunistring-1.1 [...]
    32  			// │   │   └───/nix/store/cw8fpl8r1x9rmaqj55fwbfnnrgw7b40k-libidn2-2.3.4 [...]
    33  			// │   ├───/nix/store/fmz62d844wf4blb11k21f4m0q6n6hdfp-xgcc-12.3.0-libgcc
    34  			// │   └───/nix/store/02mqs1by2vab9yzw0qc4j7463w78p3ps-glibc-2.37-8 [...]
    35  			// ├───/nix/store/mzj90j6m3c3a1vv8j9pl920f98i2yz9q-oniguruma-6.9.8-lib
    36  			// │   ├───/nix/store/02mqs1by2vab9yzw0qc4j7463w78p3ps-glibc-2.37-8 [...]
    37  			// │   └───/nix/store/mzj90j6m3c3a1vv8j9pl920f98i2yz9q-oniguruma-6.9.8-lib [...]
    38  			// └───/nix/store/1x3s2v9wc9m302cspfqcn2iwar0b5w99-jq-1.6-lib
    39  			//     ├───/nix/store/02mqs1by2vab9yzw0qc4j7463w78p3ps-glibc-2.37-8 [...]
    40  			//     ├───/nix/store/mzj90j6m3c3a1vv8j9pl920f98i2yz9q-oniguruma-6.9.8-lib [...]
    41  			//     └───/nix/store/1x3s2v9wc9m302cspfqcn2iwar0b5w99-jq-1.6-lib [...]
    42  			fixture: "image-nixos-jq-pkg-db",
    43  			wantPkgs: []string{
    44  				"glibc @ 2.37-8 (/nix/var/nix/db/db.sqlite)",
    45  				"jq @ 1.6 (/nix/var/nix/db/db.sqlite)", // lib output
    46  				"jq @ 1.6 (/nix/var/nix/db/db.sqlite)", // bin output
    47  				"libidn2 @ 2.3.4 (/nix/var/nix/db/db.sqlite)",
    48  				"libunistring @ 1.1 (/nix/var/nix/db/db.sqlite)",
    49  				"oniguruma @ 6.9.8 (/nix/var/nix/db/db.sqlite)",
    50  				"xgcc @ 12.3.0 (/nix/var/nix/db/db.sqlite)",
    51  			},
    52  			wantRel: []string{
    53  				// used the DB cataloger, thus has a complete dependency graph
    54  				"glibc @ 2.37-8 (/nix/var/nix/db/db.sqlite) [dependency-of] jq @ 1.6 (/nix/var/nix/db/db.sqlite)", // jq bin output
    55  				"glibc @ 2.37-8 (/nix/var/nix/db/db.sqlite) [dependency-of] jq @ 1.6 (/nix/var/nix/db/db.sqlite)", // jq lib output
    56  				"glibc @ 2.37-8 (/nix/var/nix/db/db.sqlite) [dependency-of] oniguruma @ 6.9.8 (/nix/var/nix/db/db.sqlite)",
    57  				"jq @ 1.6 (/nix/var/nix/db/db.sqlite) [dependency-of] jq @ 1.6 (/nix/var/nix/db/db.sqlite)", // jq bin to lib output dependency
    58  				"libidn2 @ 2.3.4 (/nix/var/nix/db/db.sqlite) [dependency-of] glibc @ 2.37-8 (/nix/var/nix/db/db.sqlite)",
    59  				"libunistring @ 1.1 (/nix/var/nix/db/db.sqlite) [dependency-of] libidn2 @ 2.3.4 (/nix/var/nix/db/db.sqlite)",
    60  				"oniguruma @ 6.9.8 (/nix/var/nix/db/db.sqlite) [dependency-of] jq @ 1.6 (/nix/var/nix/db/db.sqlite)", // jq bin output
    61  				"oniguruma @ 6.9.8 (/nix/var/nix/db/db.sqlite) [dependency-of] jq @ 1.6 (/nix/var/nix/db/db.sqlite)", // jq lib output
    62  				"xgcc @ 12.3.0 (/nix/var/nix/db/db.sqlite) [dependency-of] glibc @ 2.37-8 (/nix/var/nix/db/db.sqlite)",
    63  			},
    64  		},
    65  	}
    66  	for _, tt := range tests {
    67  		t.Run(tt.fixture, func(t *testing.T) {
    68  			pkgtest.NewCatalogTester().
    69  				WithImageResolver(t, tt.fixture).
    70  				ExpectsPackageStrings(tt.wantPkgs).
    71  				ExpectsRelationshipStrings(tt.wantRel).
    72  				TestCataloger(t, NewCataloger(DefaultConfig()))
    73  		})
    74  	}
    75  }
    76  
    77  func TestCataloger_Image_FilesListing(t *testing.T) {
    78  	tests := []struct {
    79  		fixture      string
    80  		wantPkgFiles map[string][]string
    81  	}{
    82  		{
    83  			fixture: "image-nixos-jq-pkg-db",
    84  			wantPkgFiles: map[string][]string{
    85  				"libidn2": {
    86  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/lib/libidn2.la",
    87  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/lib/libidn2.so.0.3.8",
    88  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/cs/LC_MESSAGES/libidn2.mo",
    89  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/da/LC_MESSAGES/libidn2.mo",
    90  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/de/LC_MESSAGES/libidn2.mo",
    91  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/eo/LC_MESSAGES/libidn2.mo",
    92  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/es/LC_MESSAGES/libidn2.mo",
    93  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/fi/LC_MESSAGES/libidn2.mo",
    94  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/fr/LC_MESSAGES/libidn2.mo",
    95  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/fur/LC_MESSAGES/libidn2.mo",
    96  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/hr/LC_MESSAGES/libidn2.mo",
    97  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/hu/LC_MESSAGES/libidn2.mo",
    98  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/id/LC_MESSAGES/libidn2.mo",
    99  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/it/LC_MESSAGES/libidn2.mo",
   100  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/ja/LC_MESSAGES/libidn2.mo",
   101  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/ka/LC_MESSAGES/libidn2.mo",
   102  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/ko/LC_MESSAGES/libidn2.mo",
   103  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/nl/LC_MESSAGES/libidn2.mo",
   104  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/pl/LC_MESSAGES/libidn2.mo",
   105  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/pt_BR/LC_MESSAGES/libidn2.mo",
   106  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/ro/LC_MESSAGES/libidn2.mo",
   107  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/ru/LC_MESSAGES/libidn2.mo",
   108  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/sr/LC_MESSAGES/libidn2.mo",
   109  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/sv/LC_MESSAGES/libidn2.mo",
   110  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/uk/LC_MESSAGES/libidn2.mo",
   111  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/vi/LC_MESSAGES/libidn2.mo",
   112  					"/nix/store/k8ivghpggjrq1n49xp8sj116i4sh8lia-libidn2-2.3.4/share/locale/zh_CN/LC_MESSAGES/libidn2.mo",
   113  				},
   114  			},
   115  		},
   116  	}
   117  	for _, tt := range tests {
   118  		t.Run(tt.fixture, func(t *testing.T) {
   119  			pkgtest.NewCatalogTester().
   120  				WithImageResolver(t, tt.fixture).
   121  				ExpectsAssertion(func(t *testing.T, pkgs []pkg.Package, relationships []artifact.Relationship) {
   122  					found := strset.New()
   123  					for _, p := range pkgs {
   124  						if files, ok := tt.wantPkgFiles[p.Name]; ok {
   125  							m, ok := p.Metadata.(pkg.NixStoreEntry)
   126  							require.True(t, ok)
   127  							if d := cmp.Diff(files, m.Files); d != "" {
   128  								t.Errorf("unexpected files for package %q: %s", p.Name, d)
   129  							}
   130  							found.Add(p.Name)
   131  						}
   132  					}
   133  					expected := strset.New()
   134  					for n := range tt.wantPkgFiles {
   135  						expected.Add(n)
   136  					}
   137  					assert.ElementsMatch(t, expected.List(), found.List())
   138  				}).
   139  				TestCataloger(t, NewCataloger(Config{CaptureOwnedFiles: true}))
   140  		})
   141  	}
   142  }
   143  
   144  func TestCataloger_Directory(t *testing.T) {
   145  
   146  	tests := []struct {
   147  		fixture  string
   148  		wantPkgs []pkg.Package
   149  		wantRel  []artifact.Relationship
   150  	}{
   151  		{
   152  			fixture: "test-fixtures/fixture-1",
   153  			wantPkgs: []pkg.Package{
   154  				{
   155  					Name:    "glibc",
   156  					Version: "2.34-210",
   157  					PURL:    "pkg:nix/glibc@2.34-210?drvpath=5av396z8xa13jg89g9jws145c0k26k2x-glibc-2.34-210.drv&output=bin&outputhash=h0cnbmfcn93xm5dg2x27ixhag1cwndga",
   158  					Locations: file.NewLocationSet(
   159  						file.NewLocation("nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
   160  						file.NewLocation("nix/store/5av396z8xa13jg89g9jws145c0k26k2x-glibc-2.34-210.drv").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation),
   161  					),
   162  					FoundBy: "nix-cataloger",
   163  					Type:    pkg.NixPkg,
   164  					Metadata: pkg.NixStoreEntry{
   165  						Path: "/nix/store/h0cnbmfcn93xm5dg2x27ixhag1cwndga-glibc-2.34-210-bin",
   166  						Derivation: pkg.NixDerivation{
   167  							Path:   "nix/store/5av396z8xa13jg89g9jws145c0k26k2x-glibc-2.34-210.drv",
   168  							System: "aarch64-linux",
   169  							InputDerivations: []pkg.NixDerivationReference{
   170  								{
   171  									Path:    "/nix/store/1zi0k7y01rhqr2gfqb42if0icswg65sj-locale-C.diff.drv",
   172  									Outputs: []string{"out"},
   173  								},
   174  								{
   175  									Path:    "/nix/store/45j86ggi8mlpfslcrgvjf7m6phia21fp-raw.drv",
   176  									Outputs: []string{"out"},
   177  								},
   178  								{
   179  									Path:    "/nix/store/4fnfsd9sc7bam6886hwyaprdsww66dg3-bison-3.8.2.drv",
   180  									Outputs: []string{"out"},
   181  								},
   182  								{
   183  									Path:    "/nix/store/51azdrrvcqrk2hbky7ryphlwd99yz25d-linux-headers-5.18.drv",
   184  									Outputs: []string{"out"},
   185  								},
   186  								{
   187  									Path:    "/nix/store/67s0qc21gyarmdwc181bqmjc3qzv8zkz-libidn2-2.3.2.drv",
   188  									Outputs: []string{"out"},
   189  								},
   190  								{
   191  									Path:    "/nix/store/9rhliwskh3mrrs5nfzgz0x6wrccyfg7k-bootstrap-stage0-glibc-bootstrap.drv",
   192  									Outputs: []string{"out"},
   193  								},
   194  								{
   195  									Path:    "/nix/store/cl1wcw2v1ifzjlkzi50h32a6lms9m25s-binutils-2.38.drv",
   196  									Outputs: []string{"out"},
   197  								},
   198  								{
   199  									Path:    "/nix/store/ghjc8bkfk8lh53z14mk2nk7h059zh7vx-python3-minimal-3.10.5.drv",
   200  									Outputs: []string{"out"},
   201  								},
   202  								{
   203  									Path:    "/nix/store/k3786wfzw637r7sylccdmm92saqp73d8-glibc-2.34.tar.xz.drv",
   204  									Outputs: []string{"out"},
   205  								},
   206  								{
   207  									Path:    "/nix/store/l5zr5m1agvvnic49fg6qc44g5fgj3la1-glibc-reinstate-prlimit64-fallback.patch?id=eab07e78b691ae7866267fc04d31c7c3ad6b0eeb.drv",
   208  									Outputs: []string{"out"},
   209  								},
   210  								{
   211  									Path:    "/nix/store/mf5kz6d01ab8h0rswzyr04mbcd6g5x9n-bootstrap-stage2-stdenv-linux.drv",
   212  									Outputs: []string{"out"},
   213  								},
   214  								{
   215  									Path:    "/nix/store/nd1zy67vp028707pbh466qhrfqh4cpq6-bootstrap-stage2-gcc-wrapper-.drv",
   216  									Outputs: []string{"out"},
   217  								},
   218  								{
   219  									Path:    "/nix/store/ra77ww7p2xx8jh8n4m9vmj6wc8wxijdb-bootstrap-tools.drv",
   220  									Outputs: []string{"out"},
   221  								},
   222  								{
   223  									Path:    "/nix/store/wlldapf5bg58kivw520ll5bw0fmlaid7-raw.drv",
   224  									Outputs: []string{"out"},
   225  								},
   226  							},
   227  							InputSources: []string{
   228  								"/nix/store/001gp43bjqzx60cg345n2slzg7131za8-nix-nss-open-files.patch",
   229  								"/nix/store/7kw224hdyxd7115lrqh9a4dv2x8msq2s-fix-x64-abi.patch",
   230  								"/nix/store/8haph3ng4mgsqr6p4024vj8k6kg3mqc4-nix-locale-archive.patch",
   231  								"/nix/store/95hp6hs9g73h93safadb8x6vajyqkv6q-0001-Revert-Remove-all-usage-of-BASH-or-BASH-in-installed.patch",
   232  								"/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh",
   233  								"/nix/store/b1w7zbvm39ff1i52iyjggyvw2rdxz104-dont-use-system-ld-so-cache.patch",
   234  								"/nix/store/ikmqczy0y20n04a2b8qfflzwihv8139g-separate-debug-info.sh",
   235  								"/nix/store/mgx19wbmgrh3rblbxhs6vi47sha15n11-2.34-master.patch.gz",
   236  								"/nix/store/mnglr8rr7nl444h7p50ysyq8qd0fm1lm-dont-use-system-ld-so-preload.patch",
   237  								"/nix/store/xkd50xxii6k7l1kmw4l5x6xzbhamcs87-allow-kernel-2.6.32.patch",
   238  								"/nix/store/za0pg7fmysrcwrqcal26fnmzw6vycgdn-fix_path_attribute_in_getconf.patch",
   239  							},
   240  						},
   241  						OutputHash: "h0cnbmfcn93xm5dg2x27ixhag1cwndga",
   242  						Output:     "bin",
   243  						Files:      nil, // default cataloger configure does not capture owned files
   244  					},
   245  				},
   246  			},
   247  		},
   248  	}
   249  	for _, tt := range tests {
   250  		t.Run(tt.fixture, func(t *testing.T) {
   251  			pkgtest.NewCatalogTester().
   252  				FromDirectory(t, tt.fixture).
   253  				Expects(tt.wantPkgs, tt.wantRel).
   254  				TestCataloger(t, NewCataloger(DefaultConfig()))
   255  		})
   256  	}
   257  }