github.com/anchore/syft@v1.38.2/syft/format/cpes/decoder_test.go (about) 1 package cpes 2 3 import ( 4 "strings" 5 "testing" 6 7 "github.com/google/go-cmp/cmp" 8 "github.com/google/go-cmp/cmp/cmpopts" 9 "github.com/stretchr/testify/require" 10 11 "github.com/anchore/syft/syft/cpe" 12 "github.com/anchore/syft/syft/file" 13 "github.com/anchore/syft/syft/pkg" 14 "github.com/anchore/syft/syft/sbom" 15 ) 16 17 func TestDecoder_Decode(t *testing.T) { 18 tests := []struct { 19 name string 20 userInput string 21 sbom *sbom.SBOM 22 }{ 23 { 24 name: "takes a single cpe", 25 userInput: "cpe:/a:apache:log4j:2.14.1", 26 sbom: &sbom.SBOM{ 27 Artifacts: sbom.Artifacts{ 28 Packages: pkg.NewCollection(pkg.Package{ 29 Name: "log4j", 30 Version: "2.14.1", 31 CPEs: []cpe.CPE{ 32 cpe.Must("cpe:/a:apache:log4j:2.14.1", ""), 33 }, 34 }), 35 }, 36 }, 37 }, 38 { 39 name: "takes multiple cpes", 40 userInput: `cpe:/a:apache:log4j:2.14.1 41 cpe:2.3:a:f5:nginx:*:*:*:*:*:*:*:*; 42 cpe:2.3:a:f5:nginx:0.5.2:*:*:*:*:*:*:*; 43 cpe:2.3:a:f5:nginx:0.5.3:*:*:*:*:*:*:*;`, 44 sbom: &sbom.SBOM{ 45 Artifacts: sbom.Artifacts{ 46 Packages: pkg.NewCollection( 47 pkg.Package{ 48 Name: "log4j", 49 Version: "2.14.1", 50 CPEs: []cpe.CPE{ 51 cpe.Must("cpe:/a:apache:log4j:2.14.1", ""), 52 }, 53 }, 54 pkg.Package{ 55 Name: "nginx", 56 Version: "", 57 CPEs: []cpe.CPE{ 58 cpe.Must("cpe:2.3:a:f5:nginx:*:*:*:*:*:*:*:*;", ""), 59 }, 60 }, 61 pkg.Package{ 62 Name: "nginx", 63 Version: "0.5.2", 64 CPEs: []cpe.CPE{ 65 cpe.Must("cpe:2.3:a:f5:nginx:0.5.2:*:*:*:*:*:*:*;", ""), 66 }, 67 }, 68 pkg.Package{ 69 Name: "nginx", 70 Version: "0.5.3", 71 CPEs: []cpe.CPE{ 72 cpe.Must("cpe:2.3:a:f5:nginx:0.5.3:*:*:*:*:*:*:*;", ""), 73 }, 74 }, 75 ), 76 }, 77 }, 78 }, 79 { 80 name: "takes cpe with no version", 81 userInput: "cpe:/a:apache:log4j", 82 sbom: &sbom.SBOM{ 83 Artifacts: sbom.Artifacts{ 84 Packages: pkg.NewCollection(pkg.Package{ 85 Name: "log4j", 86 CPEs: []cpe.CPE{ 87 cpe.Must("cpe:/a:apache:log4j", ""), 88 }, 89 }), 90 }, 91 }, 92 }, 93 { 94 name: "takes CPE 2.3 format", 95 userInput: "cpe:2.3:a:apache:log4j:2.14.1:*:*:*:*:*:*:*", 96 sbom: &sbom.SBOM{ 97 Artifacts: sbom.Artifacts{ 98 Packages: pkg.NewCollection(pkg.Package{ 99 Name: "log4j", 100 Version: "2.14.1", 101 CPEs: []cpe.CPE{ 102 cpe.Must("cpe:2.3:a:apache:log4j:2.14.1:*:*:*:*:*:*:*", ""), 103 }, 104 }), 105 }, 106 }, 107 }, 108 { 109 name: "deduces target SW from CPE - known target_sw", 110 userInput: "cpe:2.3:a:amazon:opensearch:*:*:*:*:*:ruby:*:*", 111 sbom: &sbom.SBOM{ 112 Artifacts: sbom.Artifacts{ 113 Packages: pkg.NewCollection(pkg.Package{ 114 Name: "opensearch", 115 Type: pkg.GemPkg, 116 CPEs: []cpe.CPE{ 117 cpe.Must("cpe:2.3:a:amazon:opensearch:*:*:*:*:*:ruby:*:*", ""), 118 }, 119 }), 120 }, 121 }, 122 }, 123 { 124 name: "handles unknown target_sw CPE field", 125 userInput: "cpe:2.3:a:amazon:opensearch:*:*:*:*:*:loremipsum:*:*", 126 sbom: &sbom.SBOM{ 127 Artifacts: sbom.Artifacts{ 128 Packages: pkg.NewCollection(pkg.Package{ 129 Name: "opensearch", 130 Type: "", 131 CPEs: []cpe.CPE{ 132 cpe.Must("cpe:2.3:a:amazon:opensearch:*:*:*:*:*:loremipsum:*:*", ""), 133 }, 134 }), 135 }, 136 }, 137 }, 138 { 139 name: "invalid prefix", 140 userInput: "dir:test-fixtures/cpe", 141 sbom: &sbom.SBOM{ 142 Artifacts: sbom.Artifacts{ 143 Packages: pkg.NewCollection(), 144 }, 145 }, 146 }, 147 } 148 149 syftPkgOpts := []cmp.Option{ 150 cmpopts.IgnoreFields(pkg.Package{}, "id", "Language"), 151 cmpopts.IgnoreUnexported(pkg.Package{}, file.LocationSet{}, pkg.LicenseSet{}), 152 } 153 154 for _, tc := range tests { 155 t.Run(tc.name, func(t *testing.T) { 156 dec := NewFormatDecoder() 157 158 decodedSBOM, _, _, err := dec.Decode(strings.NewReader(tc.userInput)) 159 require.NoError(t, err) 160 161 gotSyftPkgs := decodedSBOM.Artifacts.Packages.Sorted() 162 wantSyftPkgs := tc.sbom.Artifacts.Packages.Sorted() 163 require.Equal(t, len(gotSyftPkgs), len(wantSyftPkgs)) 164 for idx, wantPkg := range wantSyftPkgs { 165 if d := cmp.Diff(wantPkg, gotSyftPkgs[idx], syftPkgOpts...); d != "" { 166 t.Errorf("unexpected Syft Package (-want +got):\n%s", d) 167 } 168 } 169 }) 170 } 171 }