mirror of
https://github.com/anchore/syft.git
synced 2026-02-12 18:46:41 +01:00
* add info command from generated capabilities Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * correct gentoo and arch ecosystems Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * rename os pkg types Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * better binary cataloger description Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * expose metadata and pacakge types in json Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * expose json schema types Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * add completeness tests for metadata types Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * latest generation Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix linting Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * improve testing a docs Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix tests and linting Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * restore goreleaser config Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * tweak diagram Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix pdm Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * chore: java binary data Signed-off-by: Keith Zantow <kzantow@gmail.com> * new capability descriptions for gguf and python Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * correct poetry lock integrity hash claim Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix compile error Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix: remove purl version from overrides Signed-off-by: Keith Zantow <kzantow@gmail.com> * fix lua deps ref Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * keep gguf as ai ecosystem Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * split packages.yaml to multiple files by go package Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * ensure tests do not use go test cache Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * sort json output for info command Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * docs: fix ocaml, php, and portage capabilities yaml Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com> * chore: update erlang capabilities Signed-off-by: Keith Zantow <kzantow@gmail.com> * chore: update java capabilities Signed-off-by: Keith Zantow <kzantow@gmail.com> * chore: update javascript capabilities Signed-off-by: Keith Zantow <kzantow@gmail.com> * chore: update linux kernel capabilities Signed-off-by: Keith Zantow <kzantow@gmail.com> * remove missing tests Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix package.yaml references Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * revert license list change Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * check for drift in capability descriptions Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * regenerate capabilities Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * test cleanup Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * use fixture cache in static analysis Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * claim fixtures pre-req for cap generation Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * update documentation with correct regeneration procedure Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * chore: ruby-gemspec-cataloger finds no dependencies Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com> * chore: fix python docs and config comment Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com> * chore: commit re-generated java yaml Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com> * add cataloger selection to caps command Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * re-generate cap yamls Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix tests for cataloger selection Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix cli test Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * add missing tests Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix linting Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * rename cmd to `cataloger info` Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * [wip] change capability description locations Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * [wip] continued Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * [wip] adjust for import cycles Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * correct docs Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix linting Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> --------- Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> Signed-off-by: Keith Zantow <kzantow@gmail.com> Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com> Co-authored-by: Keith Zantow <kzantow@gmail.com> Co-authored-by: Will Murphy <willmurphyscode@users.noreply.github.com>
402 lines
10 KiB
Go
402 lines
10 KiB
Go
package main
|
|
|
|
import (
|
|
"go/ast"
|
|
"go/parser"
|
|
"go/token"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestLinkCatalogersToConfigsFromPath(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
fixturePath string
|
|
expectedLinkages map[string]string
|
|
wantErr require.ErrorAssertionFunc
|
|
}{
|
|
{
|
|
name: "simple generic cataloger with local config",
|
|
fixturePath: "simple-generic-cataloger",
|
|
expectedLinkages: map[string]string{
|
|
"go-module-cataloger": "golang.CatalogerConfig",
|
|
},
|
|
},
|
|
{
|
|
name: "cataloger name from constant",
|
|
fixturePath: "cataloger-with-constant",
|
|
expectedLinkages: map[string]string{
|
|
"python-package-cataloger": "python.CatalogerConfig",
|
|
},
|
|
},
|
|
{
|
|
name: "custom cataloger with Name() in same file",
|
|
fixturePath: "custom-cataloger-same-file",
|
|
expectedLinkages: map[string]string{
|
|
"java-pom-cataloger": "java.ArchiveCatalogerConfig",
|
|
},
|
|
},
|
|
{
|
|
name: "custom cataloger with Name() in different file - not detected",
|
|
fixturePath: "custom-cataloger-different-file",
|
|
expectedLinkages: map[string]string{
|
|
// empty - current limitation, cannot detect cross-file Names
|
|
},
|
|
},
|
|
{
|
|
name: "cataloger without config parameter",
|
|
fixturePath: "no-config-cataloger",
|
|
expectedLinkages: map[string]string{
|
|
"javascript-cataloger": "", // empty string means no config
|
|
},
|
|
},
|
|
{
|
|
name: "imported config type",
|
|
fixturePath: "imported-config-type",
|
|
expectedLinkages: map[string]string{
|
|
"linux-kernel-cataloger": "kernel.LinuxKernelCatalogerConfig",
|
|
},
|
|
},
|
|
{
|
|
name: "non-config first parameter",
|
|
fixturePath: "non-config-first-param",
|
|
expectedLinkages: map[string]string{
|
|
"binary-cataloger": "", // Parser not a config type
|
|
},
|
|
},
|
|
{
|
|
name: "conflicting cataloger names",
|
|
fixturePath: "conflicting-names",
|
|
wantErr: require.Error,
|
|
},
|
|
{
|
|
name: "mixed naming patterns",
|
|
fixturePath: "mixed-naming-patterns",
|
|
expectedLinkages: map[string]string{
|
|
"ruby-cataloger": "ruby.Config",
|
|
},
|
|
},
|
|
{
|
|
name: "selector expression config",
|
|
fixturePath: "selector-expression-config",
|
|
expectedLinkages: map[string]string{
|
|
"rust-cataloger": "rust.CatalogerConfig",
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if tt.wantErr == nil {
|
|
tt.wantErr = require.NoError
|
|
}
|
|
|
|
fixtureDir := filepath.Join("testdata", "cataloger", tt.fixturePath)
|
|
catalogerRoot := filepath.Join(fixtureDir, "cataloger")
|
|
linkages, err := LinkCatalogersToConfigsFromPath(catalogerRoot, fixtureDir)
|
|
tt.wantErr(t, err)
|
|
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
require.Equal(t, tt.expectedLinkages, linkages)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestExtractConfigTypeName(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
fixturePath string
|
|
catalogerName string
|
|
expectedConfig string
|
|
expectedNoConfig bool
|
|
}{
|
|
{
|
|
name: "golang config",
|
|
fixturePath: "simple-generic-cataloger",
|
|
catalogerName: "go-module-cataloger",
|
|
expectedConfig: "golang.CatalogerConfig",
|
|
},
|
|
{
|
|
name: "python config with constant",
|
|
fixturePath: "cataloger-with-constant",
|
|
catalogerName: "python-package-cataloger",
|
|
expectedConfig: "python.CatalogerConfig",
|
|
},
|
|
{
|
|
name: "java archive config same file",
|
|
fixturePath: "custom-cataloger-same-file",
|
|
catalogerName: "java-pom-cataloger",
|
|
expectedConfig: "java.ArchiveCatalogerConfig",
|
|
},
|
|
{
|
|
name: "kernel config imported type",
|
|
fixturePath: "imported-config-type",
|
|
catalogerName: "linux-kernel-cataloger",
|
|
expectedConfig: "kernel.LinuxKernelCatalogerConfig",
|
|
},
|
|
{
|
|
name: "javascript - no config",
|
|
fixturePath: "no-config-cataloger",
|
|
catalogerName: "javascript-cataloger",
|
|
expectedNoConfig: true,
|
|
},
|
|
{
|
|
name: "ruby with mixed naming",
|
|
fixturePath: "mixed-naming-patterns",
|
|
catalogerName: "ruby-cataloger",
|
|
expectedConfig: "ruby.Config",
|
|
},
|
|
{
|
|
name: "rust with selector expression",
|
|
fixturePath: "selector-expression-config",
|
|
catalogerName: "rust-cataloger",
|
|
expectedConfig: "rust.CatalogerConfig",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
fixtureDir := filepath.Join("testdata", "cataloger", tt.fixturePath)
|
|
catalogerRoot := filepath.Join(fixtureDir, "cataloger")
|
|
linkages, err := LinkCatalogersToConfigsFromPath(catalogerRoot, fixtureDir)
|
|
require.NoError(t, err)
|
|
|
|
config, ok := linkages[tt.catalogerName]
|
|
|
|
if tt.expectedNoConfig {
|
|
if ok {
|
|
require.Empty(t, config, "expected no config for %s", tt.catalogerName)
|
|
}
|
|
} else {
|
|
require.True(t, ok, "should find cataloger %s", tt.catalogerName)
|
|
require.Equal(t, tt.expectedConfig, config)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestLooksLikeConfigType(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
typeName string
|
|
want bool
|
|
}{
|
|
{
|
|
name: "golang config",
|
|
typeName: "golang.CatalogerConfig",
|
|
want: true,
|
|
},
|
|
{
|
|
name: "python config",
|
|
typeName: "python.CatalogerConfig",
|
|
want: true,
|
|
},
|
|
{
|
|
name: "java archive config",
|
|
typeName: "java.ArchiveCatalogerConfig",
|
|
want: true,
|
|
},
|
|
{
|
|
name: "kernel config",
|
|
typeName: "kernel.LinuxKernelCatalogerConfig",
|
|
want: true,
|
|
},
|
|
{
|
|
name: "nix config",
|
|
typeName: "nix.Config",
|
|
want: true,
|
|
},
|
|
{
|
|
name: "config prefix",
|
|
typeName: "package.ConfigOptions",
|
|
want: true,
|
|
},
|
|
{
|
|
name: "not a config type",
|
|
typeName: "package.Parser",
|
|
want: false,
|
|
},
|
|
{
|
|
name: "not a config type - resolver",
|
|
typeName: "file.Resolver",
|
|
want: false,
|
|
},
|
|
{
|
|
name: "no package prefix",
|
|
typeName: "CatalogerConfig",
|
|
want: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := looksLikeConfigType(tt.typeName)
|
|
require.Equal(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestExtractReceiverTypeName(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
receiver string // receiver code snippet
|
|
want string
|
|
}{
|
|
{
|
|
name: "value receiver",
|
|
receiver: "func (c Cataloger) Name() string { return \"\" }",
|
|
want: "Cataloger",
|
|
},
|
|
{
|
|
name: "pointer receiver",
|
|
receiver: "func (c *Cataloger) Name() string { return \"\" }",
|
|
want: "Cataloger",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// parse the function to get the receiver type
|
|
fset := token.NewFileSet()
|
|
file, err := parser.ParseFile(fset, "", "package test\n"+tt.receiver, 0)
|
|
require.NoError(t, err)
|
|
|
|
// extract the function declaration
|
|
require.Len(t, file.Decls, 1)
|
|
funcDecl, ok := file.Decls[0].(*ast.FuncDecl)
|
|
require.True(t, ok)
|
|
|
|
// get receiver type
|
|
var recvType ast.Expr
|
|
if funcDecl.Recv != nil && len(funcDecl.Recv.List) > 0 {
|
|
recvType = funcDecl.Recv.List[0].Type
|
|
}
|
|
|
|
got := extractReceiverTypeName(recvType)
|
|
require.Equal(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestExtractConfigTypeNameHelper(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
funcSig string // function signature with parameter
|
|
localPackageName string
|
|
want string
|
|
}{
|
|
{
|
|
name: "local type",
|
|
funcSig: "func New(cfg CatalogerConfig) pkg.Cataloger { return nil }",
|
|
localPackageName: "python",
|
|
want: "python.CatalogerConfig",
|
|
},
|
|
{
|
|
name: "imported type",
|
|
funcSig: "func New(cfg java.ArchiveCatalogerConfig) pkg.Cataloger { return nil }",
|
|
localPackageName: "python",
|
|
want: "java.ArchiveCatalogerConfig",
|
|
},
|
|
{
|
|
name: "imported type - kernel package",
|
|
funcSig: "func New(cfg kernel.LinuxKernelCatalogerConfig) pkg.Cataloger { return nil }",
|
|
localPackageName: "other",
|
|
want: "kernel.LinuxKernelCatalogerConfig",
|
|
},
|
|
{
|
|
name: "no parameters",
|
|
funcSig: "func New() pkg.Cataloger { return nil }",
|
|
localPackageName: "python",
|
|
want: "",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// parse the function to get parameter type
|
|
fset := token.NewFileSet()
|
|
file, err := parser.ParseFile(fset, "", "package test\n"+tt.funcSig, 0)
|
|
require.NoError(t, err)
|
|
|
|
// extract the function declaration
|
|
require.Len(t, file.Decls, 1)
|
|
funcDecl, ok := file.Decls[0].(*ast.FuncDecl)
|
|
require.True(t, ok)
|
|
|
|
// get first parameter type
|
|
var paramType ast.Expr
|
|
if funcDecl.Type.Params != nil && len(funcDecl.Type.Params.List) > 0 {
|
|
paramType = funcDecl.Type.Params.List[0].Type
|
|
}
|
|
|
|
got := extractConfigTypeName(paramType, tt.localPackageName)
|
|
require.Equal(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestExtractReturnTypeName(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
funcDef string // complete function definition
|
|
want string
|
|
}{
|
|
{
|
|
name: "pointer to composite literal",
|
|
funcDef: `func New() pkg.Cataloger {
|
|
return &javaCataloger{name: "test"}
|
|
}`,
|
|
want: "javaCataloger",
|
|
},
|
|
{
|
|
name: "composite literal",
|
|
funcDef: `func New() pkg.Cataloger {
|
|
return pythonCataloger{name: "test"}
|
|
}`,
|
|
want: "pythonCataloger",
|
|
},
|
|
{
|
|
name: "variable return",
|
|
funcDef: `func New() pkg.Cataloger {
|
|
c := &Cataloger{}
|
|
return c
|
|
}`,
|
|
want: "",
|
|
},
|
|
{
|
|
name: "nil return",
|
|
funcDef: `func New() pkg.Cataloger {
|
|
return nil
|
|
}`,
|
|
want: "",
|
|
},
|
|
{
|
|
name: "empty function body",
|
|
funcDef: `func New() pkg.Cataloger {}`,
|
|
want: "",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// parse the function
|
|
fset := token.NewFileSet()
|
|
file, err := parser.ParseFile(fset, "", "package test\n"+tt.funcDef, 0)
|
|
require.NoError(t, err)
|
|
|
|
// extract the function declaration
|
|
require.Len(t, file.Decls, 1)
|
|
funcDecl, ok := file.Decls[0].(*ast.FuncDecl)
|
|
require.True(t, ok)
|
|
|
|
got := extractReturnTypeName(funcDecl)
|
|
require.Equal(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|