github.com/metasources/buildx@v0.0.0-20230418141019-7aa1459cedea/test/cli/cyclonedx_valid_test.go (about) 1 package cli 2 3 import ( 4 "os" 5 "strings" 6 "testing" 7 8 "github.com/anchore/stereoscope/pkg/imagetest" 9 ) 10 11 // We have schema validation mechanims in schema/cyclonedx/ 12 // This test allows us to double check that validation against the cyclonedx-cli tool 13 func TestValidCycloneDX(t *testing.T) { 14 imageFixture := func(t *testing.T) string { 15 fixtureImageName := "image-pkg-coverage" 16 imagetest.GetFixtureImage(t, "docker-archive", fixtureImageName) 17 tarPath := imagetest.GetFixtureImageTarPath(t, fixtureImageName) 18 return "docker-archive:" + tarPath 19 } 20 21 // TODO update image to exercise entire cyclonedx schema 22 tests := []struct { 23 name string 24 subcommand string 25 args []string 26 fixture func(*testing.T) string 27 assertions []traitAssertion 28 }{ 29 { 30 name: "validate cyclonedx output", 31 subcommand: "packages", 32 args: []string{"-o", "cyclonedx-json"}, 33 fixture: imageFixture, 34 assertions: []traitAssertion{ 35 assertSuccessfulReturnCode, 36 assertValidCycloneDX, 37 }, 38 }, 39 } 40 41 for _, test := range tests { 42 t.Run(test.name, func(t *testing.T) { 43 fixtureRef := test.fixture(t) 44 args := []string{ 45 test.subcommand, fixtureRef, "-q", 46 } 47 for _, a := range test.args { 48 args = append(args, a) 49 } 50 51 cmd, stdout, stderr := runBuildx(t, nil, args...) 52 for _, traitFn := range test.assertions { 53 traitFn(t, stdout, stderr, cmd.ProcessState.ExitCode()) 54 } 55 logOutputOnFailure(t, cmd, stdout, stderr) 56 57 validateCycloneDXJSON(t, stdout) 58 }) 59 } 60 } 61 62 func assertValidCycloneDX(tb testing.TB, stdout, stderr string, rc int) { 63 tb.Helper() 64 f, err := os.CreateTemp("", "tmpfile-") 65 if err != nil { 66 tb.Fatal(err) 67 } 68 69 // close and remove the temporary file at the end of the program 70 defer f.Close() 71 defer os.Remove(f.Name()) 72 73 data := []byte(stdout) 74 75 if _, err := f.Write(data); err != nil { 76 tb.Fatal(err) 77 } 78 79 args := []string{ 80 "validate", 81 "--input-format", 82 "json", 83 "--input-version", 84 "v1_4", 85 "--input-file", 86 "/sbom", 87 } 88 89 cmd, stdout, stderr := runCycloneDXInDocker(tb, nil, "cyclonedx/cyclonedx-cli", f, args...) 90 if cmd.ProcessState.ExitCode() != 0 { 91 tb.Errorf("expected no validation failures for cyclonedx-cli but got rc=%d", rc) 92 } 93 94 logOutputOnFailure(tb, cmd, stdout, stderr) 95 } 96 97 // validate --input-format json --input-version v1_4 --input-file bom.json 98 func validateCycloneDXJSON(t *testing.T, stdout string) { 99 f, err := os.CreateTemp("", "tmpfile-") 100 if err != nil { 101 t.Fatal(err) 102 } 103 104 // close and remove the temporary file at the end of the program 105 defer f.Close() 106 defer os.Remove(f.Name()) 107 108 data := []byte(stdout) 109 110 if _, err := f.Write(data); err != nil { 111 t.Fatal(err) 112 } 113 114 args := []string{ 115 "validate", 116 "--input-format", 117 "json", 118 "--input-version", 119 "v1_4", 120 "--input-file", 121 "/sbom", 122 } 123 124 cmd, stdout, stderr := runCycloneDXInDocker(t, nil, "cyclonedx/cyclonedx-cli", f, args...) 125 if strings.Contains(stdout, "BOM is not valid") { 126 t.Errorf("expected no validation failures for cyclonedx-cli but found invalid BOM") 127 } 128 129 logOutputOnFailure(t, cmd, stdout, stderr) 130 }