package golang import ( "testing" "github.com/stretchr/testify/assert" "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" ) func Test_PackageCataloger_Binary(t *testing.T) { tests := []struct { name string fixture string expectedPkgs []string expectedRels []string }{ { name: "simple module with dependencies", fixture: "image-small", expectedPkgs: []string{ "anchore.io/not/real @ v1.0.0 (/run-me)", "github.com/andybalholm/brotli @ v1.1.1 (/run-me)", "github.com/dsnet/compress @ v0.0.2-0.20210315054119-f66993602bf5 (/run-me)", "github.com/golang/snappy @ v0.0.4 (/run-me)", "github.com/klauspost/compress @ v1.17.11 (/run-me)", "github.com/klauspost/pgzip @ v1.2.6 (/run-me)", "github.com/nwaples/rardecode @ v1.1.3 (/run-me)", "github.com/pierrec/lz4/v4 @ v4.1.21 (/run-me)", "github.com/ulikunitz/xz @ v0.5.12 (/run-me)", "github.com/xi2/xz @ v0.0.0-20171230120015-48954b6210f8 (/run-me)", "stdlib @ go1.23.2 (/run-me)", "github.com/anchore/archiver/v3 @ v3.5.3-0.20241210171143-5b1d8d1c7c51 (/run-me)", }, expectedRels: []string{ "github.com/andybalholm/brotli @ v1.1.1 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", "github.com/dsnet/compress @ v0.0.2-0.20210315054119-f66993602bf5 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", "github.com/golang/snappy @ v0.0.4 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", "github.com/klauspost/compress @ v1.17.11 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", "github.com/klauspost/pgzip @ v1.2.6 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", "github.com/anchore/archiver/v3 @ v3.5.3-0.20241210171143-5b1d8d1c7c51 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", "github.com/nwaples/rardecode @ v1.1.3 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", "github.com/pierrec/lz4/v4 @ v4.1.21 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", "github.com/ulikunitz/xz @ v0.5.12 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", "github.com/xi2/xz @ v0.0.0-20171230120015-48954b6210f8 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", "stdlib @ go1.23.2 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", }, }, { name: "upx compressed binary", fixture: "image-small-upx", expectedPkgs: []string{ "anchore.io/not/real @ v1.0.0 (/run-me)", "github.com/andybalholm/brotli @ v1.1.1 (/run-me)", "github.com/dsnet/compress @ v0.0.2-0.20210315054119-f66993602bf5 (/run-me)", "github.com/golang/snappy @ v0.0.4 (/run-me)", "github.com/klauspost/compress @ v1.17.11 (/run-me)", "github.com/klauspost/pgzip @ v1.2.6 (/run-me)", "github.com/nwaples/rardecode @ v1.1.3 (/run-me)", "github.com/pierrec/lz4/v4 @ v4.1.21 (/run-me)", "github.com/ulikunitz/xz @ v0.5.12 (/run-me)", "github.com/xi2/xz @ v0.0.0-20171230120015-48954b6210f8 (/run-me)", "stdlib @ go1.23.2 (/run-me)", "github.com/anchore/archiver/v3 @ v3.5.3-0.20241210171143-5b1d8d1c7c51 (/run-me)", }, expectedRels: []string{ "github.com/andybalholm/brotli @ v1.1.1 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", "github.com/dsnet/compress @ v0.0.2-0.20210315054119-f66993602bf5 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", "github.com/golang/snappy @ v0.0.4 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", "github.com/klauspost/compress @ v1.17.11 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", "github.com/klauspost/pgzip @ v1.2.6 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", "github.com/anchore/archiver/v3 @ v3.5.3-0.20241210171143-5b1d8d1c7c51 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", "github.com/nwaples/rardecode @ v1.1.3 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", "github.com/pierrec/lz4/v4 @ v4.1.21 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", "github.com/ulikunitz/xz @ v0.5.12 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", "github.com/xi2/xz @ v0.0.0-20171230120015-48954b6210f8 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", "stdlib @ go1.23.2 (/run-me) [dependency-of] anchore.io/not/real @ v1.0.0 (/run-me)", }, }, { name: "partially built binary", // the difference is the build flags used to build the binary... they will not reference the module directly // see the dockerfile for details fixture: "image-not-a-module", expectedPkgs: []string{ "command-line-arguments @ (/run-me)", // this is the difference! "github.com/andybalholm/brotli @ v1.1.1 (/run-me)", "github.com/dsnet/compress @ v0.0.2-0.20210315054119-f66993602bf5 (/run-me)", "github.com/golang/snappy @ v0.0.4 (/run-me)", "github.com/anchore/archiver/v3 @ v3.5.3-0.20241210171143-5b1d8d1c7c51 (/run-me)", "github.com/klauspost/compress @ v1.17.11 (/run-me)", "github.com/klauspost/pgzip @ v1.2.6 (/run-me)", "github.com/nwaples/rardecode @ v1.1.3 (/run-me)", "github.com/pierrec/lz4/v4 @ v4.1.21 (/run-me)", "github.com/ulikunitz/xz @ v0.5.12 (/run-me)", "github.com/xi2/xz @ v0.0.0-20171230120015-48954b6210f8 (/run-me)", "stdlib @ go1.23.2 (/run-me)", }, expectedRels: []string{ "github.com/anchore/archiver/v3 @ v3.5.3-0.20241210171143-5b1d8d1c7c51 (/run-me) [dependency-of] command-line-arguments @ (/run-me)", "github.com/andybalholm/brotli @ v1.1.1 (/run-me) [dependency-of] command-line-arguments @ (/run-me)", "github.com/dsnet/compress @ v0.0.2-0.20210315054119-f66993602bf5 (/run-me) [dependency-of] command-line-arguments @ (/run-me)", "github.com/golang/snappy @ v0.0.4 (/run-me) [dependency-of] command-line-arguments @ (/run-me)", "github.com/klauspost/compress @ v1.17.11 (/run-me) [dependency-of] command-line-arguments @ (/run-me)", "github.com/klauspost/pgzip @ v1.2.6 (/run-me) [dependency-of] command-line-arguments @ (/run-me)", "github.com/nwaples/rardecode @ v1.1.3 (/run-me) [dependency-of] command-line-arguments @ (/run-me)", "github.com/pierrec/lz4/v4 @ v4.1.21 (/run-me) [dependency-of] command-line-arguments @ (/run-me)", "github.com/ulikunitz/xz @ v0.5.12 (/run-me) [dependency-of] command-line-arguments @ (/run-me)", "github.com/xi2/xz @ v0.0.0-20171230120015-48954b6210f8 (/run-me) [dependency-of] command-line-arguments @ (/run-me)", "stdlib @ go1.23.2 (/run-me) [dependency-of] command-line-arguments @ (/run-me)", }, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { pkgtest.NewCatalogTester(). WithImageResolver(t, test.fixture). ExpectsPackageStrings(test.expectedPkgs). ExpectsRelationshipStrings(test.expectedRels). TestCataloger(t, NewGoModuleBinaryCataloger(DefaultCatalogerConfig())) }) } } func Test_Mod_Cataloger_Globs(t *testing.T) { tests := []struct { name string fixture string expected []string }{ { name: "obtain go.mod files", fixture: "testdata/glob-paths", expected: []string{ "src/go.mod", }, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { pkgtest.NewCatalogTester(). FromDirectory(t, test.fixture). ExpectsResolverContentQueries(test.expected). IgnoreUnfulfilledPathResponses("src/go.sum"). TestCataloger(t, NewGoModuleFileCataloger(CatalogerConfig{})) }) } } func Test_Binary_Cataloger_Globs(t *testing.T) { tests := []struct { name string fixture string expected []string }{ { name: "obtain binary files", fixture: "testdata/glob-paths", expected: []string{ "partial-binary", }, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { pkgtest.NewCatalogTester(). FromDirectory(t, test.fixture). ExpectsResolverContentQueries(test.expected). TestCataloger(t, NewGoModuleBinaryCataloger(CatalogerConfig{})) }) } } func Test_Binary_Cataloger_Stdlib_Cpe(t *testing.T) { tests := []struct { name string candidate string want string }{ { name: "generateStdlibCpe generates a cpe with a - for a major version", candidate: "go1.21.0", want: "cpe:2.3:a:golang:go:1.21.0:-:*:*:*:*:*:*", }, { name: "generateStdlibCpe generates a cpe with an rc candidate for a major rc version", candidate: "go1.21rc2", want: "cpe:2.3:a:golang:go:1.21:rc2:*:*:*:*:*:*", }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { got, err := generateStdlibCpe(tc.candidate) assert.NoError(t, err, "expected no err; got %v", err) assert.Equal(t, got.Attributes.String(), tc.want) }) } }