Add basic CLI tests for SBOM input

Signed-off-by: Dan Luhring <dan.luhring@anchore.com>
This commit is contained in:
Dan Luhring 2021-02-22 21:13:49 -05:00
parent 12646be461
commit 49b04f13eb
No known key found for this signature in database
GPG key ID: 9CEE23D079426CEF
3 changed files with 401 additions and 0 deletions

View file

@ -133,6 +133,11 @@ integration: ## Run integration tests
integration-fingerprint:
find test/integration/test-fixtures/image-* -type f -exec md5sum {} + | awk '{print $1}' | sort | md5sum | tee test/integration/test-fixtures/cache.fingerprint
.PHONY: cli
cli: ## Run CLI tests
GRYPE_BINARY_LOCATION='snapshot/grype-macos_darwin_amd64/grype' \
go test -count=1 -v ./test/cli
.PHONY: clear-test-cache
clear-test-cache: ## Delete all test cache (built docker image tars)
find . -type f -wholename "**/test-fixtures/cache/*.tar" -delete

130
test/cli/sbom_input_test.go Normal file
View file

@ -0,0 +1,130 @@
package cli
import (
"fmt"
"io"
"os"
"os/exec"
"path"
"testing"
)
// GRYPE_BINARY_LOCATION is relative to the repository root. (e.g., "snapshot/grype_linux_amd64/grype")
// This value is transformed due to the CLI tests' need for a path relative to the test directory.
var grypeBinaryLocation = path.Join("..", "..", os.Getenv("GRYPE_BINARY_LOCATION"))
const sbomLocation = "./test-fixtures/sbom-ubuntu-20.04--pruned.json"
func TestSBOMInput_AsArgument(t *testing.T) {
workingDirectory, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
cases := []struct {
name string
path string
}{
{
"absolute path",
path.Join(workingDirectory, sbomLocation),
},
{
"relative path",
sbomLocation,
},
}
t.Run("explicit", func(t *testing.T) {
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
sbomArg := "sbom:" + tc.path
cmd := getGrypeCommand(t, sbomArg)
assertCommandExecutionSuccess(t, cmd)
})
}
})
t.Run("implicit", func(t *testing.T) {
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
sbomArg := tc.path
cmd := getGrypeCommand(t, sbomArg)
assertCommandExecutionSuccess(t, cmd)
})
}
})
}
func TestSBOMInput_FromStdin(t *testing.T) {
cmd := getGrypeCommand(t)
sbom, err := os.Open(sbomLocation)
if err != nil {
t.Fatal(err)
}
attachFileToCommandStdin(t, sbom, cmd)
assertCommandExecutionSuccess(t, cmd)
}
func getGrypeCommand(t *testing.T, args ...string) *exec.Cmd {
grype, err := getCommand(grypeBinaryLocation, args...)
if err != nil {
t.Fatal(err)
}
return grype
}
// —— below this line is generalizable across projects
func getCommand(relativePathToBinary string, args ...string) (*exec.Cmd, error) {
_, err := os.Stat(relativePathToBinary)
if err != nil {
return nil, fmt.Errorf("unable to lookup binary path %q: %w", relativePathToBinary, err)
}
workingDirectory, err := os.Getwd()
if err != nil {
return nil, err
}
resolvedPathToBinary := path.Join(workingDirectory, relativePathToBinary)
return exec.Command(resolvedPathToBinary, args...), nil
}
func attachFileToCommandStdin(t *testing.T, file io.Reader, command *exec.Cmd) {
stdin, err := command.StdinPipe()
if err != nil {
t.Fatal(err)
}
_, err = io.Copy(stdin, file)
if err != nil {
t.Fatal(err)
}
err = stdin.Close()
if err != nil {
t.Fatal(err)
}
}
func assertCommandExecutionSuccess(t *testing.T, cmd *exec.Cmd) {
t.Logf("Running command: %q", cmd)
output, err := cmd.CombinedOutput()
t.Logf("Full command output:\n%s\n", output)
if err != nil {
if exitErr, ok := err.(*exec.ExitError); ok {
t.Fatal(exitErr)
}
t.Fatalf("unable to run command %q: %v", cmd, err)
}
}

View file

@ -0,0 +1,266 @@
{
"artifacts": [
{
"name": "gcc-10-base",
"version": "10.2.0-5ubuntu1~20.04",
"type": "deb",
"foundBy": "dpkgdb-cataloger",
"locations": [
{
"path": "/var/lib/dpkg/status",
"layerID": "sha256:9f32931c9d28f10104a8eb1330954ba90e76d92b02c5256521ba864feec14009"
},
{
"path": "/var/lib/dpkg/info/gcc-10-base:amd64.md5sums",
"layerID": "sha256:9f32931c9d28f10104a8eb1330954ba90e76d92b02c5256521ba864feec14009"
},
{
"path": "/usr/share/doc/gcc-10-base/copyright",
"layerID": "sha256:9f32931c9d28f10104a8eb1330954ba90e76d92b02c5256521ba864feec14009"
}
],
"licenses": [],
"language": "",
"cpes": [
"cpe:2.3:a:gcc-10-base:gcc-10-base:10.2.0-5ubuntu1~20.04:*:*:*:*:*:*:*",
"cpe:2.3:a:*:gcc-10-base:10.2.0-5ubuntu1~20.04:*:*:*:*:*:*:*"
],
"purl": "pkg:deb/ubuntu/gcc-10-base@10.2.0-5ubuntu1~20.04?arch=amd64",
"metadataType": "DpkgMetadata",
"metadata": {
"package": "gcc-10-base",
"source": "gcc-10",
"version": "10.2.0-5ubuntu1~20.04",
"sourceVersion": "",
"architecture": "amd64",
"maintainer": "Ubuntu Core developers <ubuntu-devel-discuss@lists.ubuntu.com>",
"installedSize": 260,
"files": [
{
"path": "/usr/share/doc/gcc-10-base/README.Debian.amd64.gz",
"md5": "3c03902e06eef5dcfe3005376c23a120"
},
{
"path": "/usr/share/doc/gcc-10-base/TODO.Debian",
"md5": "8afe308ec72834f3c24b209fbc4d149e"
},
{
"path": "/usr/share/doc/gcc-10-base/changelog.Debian.gz",
"md5": "0e3cbc1152a18bddf7c24fe3913866c6"
},
{
"path": "/usr/share/doc/gcc-10-base/copyright",
"md5": "a80ca2e181b9eecc3e4d373fd7ca59f2"
}
]
}
},
{
"name": "hostname",
"version": "3.23",
"type": "deb",
"foundBy": "dpkgdb-cataloger",
"locations": [
{
"path": "/var/lib/dpkg/status",
"layerID": "sha256:9f32931c9d28f10104a8eb1330954ba90e76d92b02c5256521ba864feec14009"
},
{
"path": "/var/lib/dpkg/info/hostname.md5sums",
"layerID": "sha256:9f32931c9d28f10104a8eb1330954ba90e76d92b02c5256521ba864feec14009"
},
{
"path": "/usr/share/doc/hostname/copyright",
"layerID": "sha256:9f32931c9d28f10104a8eb1330954ba90e76d92b02c5256521ba864feec14009"
}
],
"licenses": [],
"language": "",
"cpes": [
"cpe:2.3:a:hostname:hostname:3.23:*:*:*:*:*:*:*",
"cpe:2.3:a:*:hostname:3.23:*:*:*:*:*:*:*"
],
"purl": "pkg:deb/ubuntu/hostname@3.23?arch=amd64",
"metadataType": "DpkgMetadata",
"metadata": {
"package": "hostname",
"source": "",
"version": "3.23",
"sourceVersion": "",
"architecture": "amd64",
"maintainer": "Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>",
"installedSize": 54,
"files": [
{
"path": "/bin/hostname",
"md5": "1ce73d718e3dccc1aaa7bce6ae2ef0a7"
},
{
"path": "/usr/share/doc/hostname/changelog.gz",
"md5": "087a3eabd7427692c216a5d7a4341127"
},
{
"path": "/usr/share/doc/hostname/copyright",
"md5": "460b6a1df2db2b5e80f05a44ec21c62f"
},
{
"path": "/usr/share/man/man1/hostname.1.gz",
"md5": "62e6be6a928b4b9f2a985778fee171fd"
}
]
}
},
{
"name": "libacl1",
"version": "2.2.53-6",
"type": "deb",
"foundBy": "dpkgdb-cataloger",
"locations": [
{
"path": "/var/lib/dpkg/status",
"layerID": "sha256:9f32931c9d28f10104a8eb1330954ba90e76d92b02c5256521ba864feec14009"
},
{
"path": "/var/lib/dpkg/info/libacl1:amd64.md5sums",
"layerID": "sha256:9f32931c9d28f10104a8eb1330954ba90e76d92b02c5256521ba864feec14009"
},
{
"path": "/usr/share/doc/libacl1/copyright",
"layerID": "sha256:9f32931c9d28f10104a8eb1330954ba90e76d92b02c5256521ba864feec14009"
}
],
"licenses": [
"GPL-2+",
"LGPL-2+"
],
"language": "",
"cpes": [
"cpe:2.3:a:libacl1:libacl1:2.2.53-6:*:*:*:*:*:*:*",
"cpe:2.3:a:*:libacl1:2.2.53-6:*:*:*:*:*:*:*"
],
"purl": "pkg:deb/ubuntu/libacl1@2.2.53-6?arch=amd64",
"metadataType": "DpkgMetadata",
"metadata": {
"package": "libacl1",
"source": "acl",
"version": "2.2.53-6",
"sourceVersion": "",
"architecture": "amd64",
"maintainer": "Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>",
"installedSize": 70,
"files": [
{
"path": "/usr/lib/x86_64-linux-gnu/libacl.so.1.1.2253",
"md5": "e77bf61a72656a594ef49768a7d6097b"
},
{
"path": "/usr/share/doc/libacl1/changelog.Debian.gz",
"md5": "65de3b787d67d4755ad3ae0584aee9f2"
},
{
"path": "/usr/share/doc/libacl1/copyright",
"md5": "40822d07cf4c0fb9ab13c2bebf51d981"
}
]
}
},
{
"name": "libattr1",
"version": "1:2.4.48-5",
"type": "deb",
"foundBy": "dpkgdb-cataloger",
"locations": [
{
"path": "/var/lib/dpkg/status",
"layerID": "sha256:9f32931c9d28f10104a8eb1330954ba90e76d92b02c5256521ba864feec14009"
},
{
"path": "/var/lib/dpkg/info/libattr1:amd64.md5sums",
"layerID": "sha256:9f32931c9d28f10104a8eb1330954ba90e76d92b02c5256521ba864feec14009"
},
{
"path": "/usr/share/doc/libattr1/copyright",
"layerID": "sha256:9f32931c9d28f10104a8eb1330954ba90e76d92b02c5256521ba864feec14009"
}
],
"licenses": [
"GPL-2+",
"LGPL-2+"
],
"language": "",
"cpes": [
"cpe:2.3:a:libattr1:libattr1:1:2.4.48-5:*:*:*:*:*:*:*",
"cpe:2.3:a:*:libattr1:1:2.4.48-5:*:*:*:*:*:*:*"
],
"purl": "pkg:deb/ubuntu/libattr1@1:2.4.48-5?arch=amd64",
"metadataType": "DpkgMetadata",
"metadata": {
"package": "libattr1",
"source": "attr",
"version": "1:2.4.48-5",
"sourceVersion": "",
"architecture": "amd64",
"maintainer": "Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>",
"installedSize": 57,
"files": [
{
"path": "/usr/lib/x86_64-linux-gnu/libattr.so.1.1.2448",
"md5": "708453da8ebde1aaca2ca69c04d4c0a8"
},
{
"path": "/usr/share/doc/libattr1/changelog.Debian.gz",
"md5": "6465a4cda28287d4ea9979b530648ee3"
},
{
"path": "/usr/share/doc/libattr1/copyright",
"md5": "1e0c5c8b55170890f960aad90336aaed"
}
]
}
}
],
"source": {
"type": "image",
"target": {
"userInput": "ubuntu:20.04",
"imageID": "sha256:f63181f19b2fe819156dcb068b3b5bc036820bec7014c5f77277cfa341d4cb5e",
"manifestDigest": "sha256:5146935f9248826d44dfc2489abfd5f4bdfbc319a738c04dfe1ef071f228a1ac",
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"tags": [
"ubuntu:20.04"
],
"imageSize": 72898411,
"scope": "Squashed",
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"digest": "sha256:9f32931c9d28f10104a8eb1330954ba90e76d92b02c5256521ba864feec14009",
"size": 72897593
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"digest": "sha256:dbf2c0f42a39b60301f6d3936f7f8adb59bb97d31ec11cc4a049ce81155fef89",
"size": 811
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"digest": "sha256:02473afd360bd5391fa51b6e7849ce88732ae29f50f3630c3551f528eba66d1e",
"size": 7
}
]
}
},
"distro": {
"name": "ubuntu",
"version": "20.04",
"idLike": "debian"
},
"descriptor": {
"name": "syft",
"version": "0.12.7"
},
"schema": {
"version": "1.0.1",
"url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-1.0.1.json"
}
}