github.com/nextlinux/gosbom@v0.81.1-0.20230627115839-1ff50c281391/gosbom/formats/gosbomjson/model/package_test.go (about) 1 package model 2 3 import ( 4 "encoding/json" 5 "reflect" 6 "testing" 7 8 "github.com/nextlinux/gosbom/gosbom/license" 9 "github.com/nextlinux/gosbom/gosbom/pkg" 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 ) 13 14 func TestUnmarshalPackageGolang(t *testing.T) { 15 tests := []struct { 16 name string 17 packageData []byte 18 assert func(*Package) 19 }{ 20 { 21 name: "unmarshal package metadata", 22 packageData: []byte(`{ 23 "id": "8b594519bc23da50", 24 "name": "gopkg.in/square/go-jose.v2", 25 "version": "v2.6.0", 26 "type": "go-module", 27 "foundBy": "go-module-binary-cataloger", 28 "locations": [ 29 { 30 "path": "/Users/hal/go/bin/gosbom" 31 } 32 ], 33 "licenses": [ 34 { 35 "value": "MIT", 36 "spdxExpression": "MIT", 37 "type": "declared", 38 "url": [] 39 } 40 ], 41 "language": "go", 42 "cpes": [], 43 "purl": "pkg:golang/gopkg.in/square/go-jose.v2@v2.6.0", 44 "metadataType": "GolangBinMetadata", 45 "metadata": { 46 "goCompiledVersion": "go1.18", 47 "architecture": "amd64", 48 "h1Digest": "h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=" 49 } 50 }`), 51 assert: func(p *Package) { 52 assert.NotNil(t, p.Metadata) 53 golangMetadata := p.Metadata.(pkg.GolangBinMetadata) 54 assert.NotEmpty(t, golangMetadata) 55 assert.Equal(t, "go1.18", golangMetadata.GoCompiledVersion) 56 }, 57 }, 58 { 59 name: "can handle package without metadata", 60 packageData: []byte(`{ 61 "id": "8b594519bc23da50", 62 "name": "gopkg.in/square/go-jose.v2", 63 "version": "v2.6.0", 64 "type": "go-module", 65 "foundBy": "go-mod-cataloger", 66 "locations": [ 67 { 68 "path": "/Users/hal/go/bin/gosbom" 69 } 70 ], 71 "licenses": [ 72 { 73 "value": "MIT", 74 "spdxExpression": "MIT", 75 "type": "declared", 76 "url": ["https://www.github.com"] 77 }, 78 { 79 "value": "MIT", 80 "spdxExpression": "MIT", 81 "type": "declared", 82 "locations": [{"path": "/Users/hal/go/bin/gosbom"}] 83 } 84 ], 85 "language": "go", 86 "cpes": [], 87 "purl": "pkg:golang/gopkg.in/square/go-jose.v2@v2.6.0" 88 }`), 89 assert: func(p *Package) { 90 assert.Empty(t, p.MetadataType) 91 assert.Empty(t, p.Metadata) 92 }, 93 }, 94 { 95 name: "can handle package with []string licenses", 96 packageData: []byte(`{ 97 "id": "8b594519bc23da50", 98 "name": "gopkg.in/square/go-jose.v2", 99 "version": "v2.6.0", 100 "type": "go-module", 101 "foundBy": "go-mod-cataloger", 102 "locations": [ 103 { 104 "path": "/Users/hal/go/bin/gosbom" 105 } 106 ], 107 "licenses": ["MIT", "Apache-2.0"], 108 "language": "go", 109 "cpes": [], 110 "purl": "pkg:golang/gopkg.in/square/go-jose.v2@v2.6.0" 111 }`), 112 assert: func(p *Package) { 113 assert.Equal(t, licenses{ 114 { 115 Value: "MIT", 116 SPDXExpression: "MIT", 117 Type: license.Declared, 118 }, 119 { 120 Value: "Apache-2.0", 121 SPDXExpression: "Apache-2.0", 122 Type: license.Declared, 123 }, 124 }, p.Licenses) 125 }, 126 }, 127 { 128 name: "can handle package with []pkg.License licenses", 129 packageData: []byte(`{ 130 "id": "8b594519bc23da50", 131 "name": "gopkg.in/square/go-jose.v2", 132 "version": "v2.6.0", 133 "type": "go-module", 134 "foundBy": "go-mod-cataloger", 135 "locations": [ 136 { 137 "path": "/Users/hal/go/bin/gosbom" 138 } 139 ], 140 "licenses": [ 141 { 142 "value": "MIT", 143 "spdxExpression": "MIT", 144 "type": "declared" 145 }, 146 { 147 "value": "Apache-2.0", 148 "spdxExpression": "Apache-2.0", 149 "type": "declared" 150 } 151 ], 152 "language": "go", 153 "cpes": [], 154 "purl": "pkg:golang/gopkg.in/square/go-jose.v2@v2.6.0" 155 }`), 156 assert: func(p *Package) { 157 assert.Equal(t, licenses{ 158 { 159 Value: "MIT", 160 SPDXExpression: "MIT", 161 Type: license.Declared, 162 }, 163 { 164 Value: "Apache-2.0", 165 SPDXExpression: "Apache-2.0", 166 Type: license.Declared, 167 }, 168 }, p.Licenses) 169 }, 170 }, 171 } 172 173 for _, test := range tests { 174 t.Run(test.name, func(t *testing.T) { 175 p := &Package{} 176 err := p.UnmarshalJSON(test.packageData) 177 require.NoError(t, err) 178 test.assert(p) 179 }) 180 } 181 } 182 183 func Test_unpackMetadata(t *testing.T) { 184 tests := []struct { 185 name string 186 packageData []byte 187 metadataType pkg.MetadataType 188 wantMetadata interface{} 189 wantErr require.ErrorAssertionFunc 190 }{ 191 { 192 name: "unmarshal package metadata", 193 metadataType: pkg.GolangBinMetadataType, 194 packageData: []byte(`{ 195 "id": "8b594519bc23da50", 196 "name": "gopkg.in/square/go-jose.v2", 197 "version": "v2.6.0", 198 "type": "go-module", 199 "foundBy": "go-module-binary-cataloger", 200 "locations": [ 201 { 202 "path": "/Users/hal/go/bin/gosbom" 203 } 204 ], 205 "licenses": [], 206 "language": "go", 207 "cpes": [], 208 "purl": "pkg:golang/gopkg.in/square/go-jose.v2@v2.6.0", 209 "metadataType": "GolangBinMetadata", 210 "metadata": { 211 "goCompiledVersion": "go1.18", 212 "architecture": "amd64", 213 "h1Digest": "h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=" 214 } 215 }`), 216 }, 217 { 218 name: "can handle package without metadata", 219 metadataType: "", 220 packageData: []byte(`{ 221 "id": "8b594519bc23da50", 222 "name": "gopkg.in/square/go-jose.v2", 223 "version": "v2.6.0", 224 "type": "go-module", 225 "foundBy": "go-mod-cataloger", 226 "locations": [ 227 { 228 "path": "/Users/hal/go/bin/gosbom" 229 } 230 ], 231 "licenses": [], 232 "language": "go", 233 "cpes": [], 234 "purl": "pkg:golang/gopkg.in/square/go-jose.v2@v2.6.0" 235 }`), 236 }, 237 { 238 name: "can handle RpmdbMetadata", 239 metadataType: pkg.RpmMetadataType, 240 packageData: []byte(`{ 241 "id": "4ac699c3b8fe1835", 242 "name": "acl", 243 "version": "2.2.53-1.el8", 244 "type": "rpm", 245 "foundBy": "rpm-db-cataloger", 246 "locations": [ 247 { 248 "path": "/var/lib/rpm/Packages", 249 "layerID": "sha256:74ddd0ec08fa43d09f32636ba91a0a3053b02cb4627c35051aff89f853606b59" 250 } 251 ], 252 "language": "", 253 "cpes": [ 254 "cpe:2.3:a:centos:acl:2.2.53-1.el8:*:*:*:*:*:*:*", 255 "cpe:2.3:a:acl:acl:2.2.53-1.el8:*:*:*:*:*:*:*" 256 ], 257 "purl": "pkg:rpm/centos/acl@2.2.53-1.el8?arch=x86_64&upstream=acl-2.2.53-1.el8.src.rpm&distro=centos-8", 258 "metadataType": "RpmdbMetadata", 259 "metadata": { 260 "name": "acl", 261 "version": "2.2.53", 262 "epoch": null, 263 "architecture": "x86_64", 264 "release": "1.el8", 265 "sourceRpm": "acl-2.2.53-1.el8.src.rpm", 266 "size": 205740, 267 "license": "GPLv2+", 268 "vendor": "CentOS", 269 "modularityLabel": "" 270 } 271 }`), 272 }, 273 { 274 name: "bad metadata type is an error", 275 metadataType: "BOGOSITY", 276 wantErr: require.Error, 277 packageData: []byte(`{ 278 "id": "8b594519bc23da50", 279 "name": "gopkg.in/square/go-jose.v2", 280 "version": "v2.6.0", 281 "type": "go-module", 282 "foundBy": "go-mod-cataloger", 283 "locations": [ 284 { 285 "path": "/Users/hal/go/bin/gosbom" 286 } 287 ], 288 "licenses": [], 289 "language": "go", 290 "cpes": [], 291 "purl": "pkg:golang/gopkg.in/square/go-jose.v2@v2.6.0", 292 "metadataType": "BOGOSITY" 293 }`), 294 }, 295 { 296 name: "unknown metadata type", 297 packageData: []byte(`{ 298 "metadataType": "NewMetadataType", 299 "metadata": { 300 "thing": "thing-1" 301 } 302 }`), 303 wantErr: require.Error, 304 metadataType: "NewMetadataType", 305 wantMetadata: map[string]interface{}{ 306 "thing": "thing-1", 307 }, 308 }, 309 { 310 name: "can handle package with metadata type but missing metadata", 311 packageData: []byte(`{ 312 "metadataType": "GolangBinMetadata" 313 }`), 314 metadataType: pkg.GolangBinMetadataType, 315 wantMetadata: pkg.GolangBinMetadata{}, 316 }, 317 { 318 name: "can handle package with golang bin metadata type", 319 packageData: []byte(`{ 320 "metadataType": "GolangBinMetadata" 321 }`), 322 metadataType: pkg.GolangBinMetadataType, 323 wantMetadata: pkg.GolangBinMetadata{}, 324 }, 325 { 326 name: "can handle package with unknonwn metadata type and missing metadata", 327 packageData: []byte(`{ 328 "metadataType": "BadMetadata" 329 }`), 330 wantErr: require.Error, 331 metadataType: "BadMetadata", 332 wantMetadata: nil, 333 }, 334 { 335 name: "can handle package with unknonwn metadata type and metadata", 336 packageData: []byte(`{ 337 "metadataType": "BadMetadata", 338 "metadata": { 339 "random": "thing" 340 } 341 }`), 342 wantErr: require.Error, 343 metadataType: "BadMetadata", 344 wantMetadata: map[string]interface{}{ 345 "random": "thing", 346 }, 347 }, 348 } 349 350 for _, test := range tests { 351 t.Run(test.name, func(t *testing.T) { 352 if test.wantErr == nil { 353 test.wantErr = require.NoError 354 } 355 p := &Package{} 356 357 var basic PackageBasicData 358 require.NoError(t, json.Unmarshal(test.packageData, &basic)) 359 p.PackageBasicData = basic 360 361 var unpacker packageMetadataUnpacker 362 require.NoError(t, json.Unmarshal(test.packageData, &unpacker)) 363 364 err := unpackMetadata(p, unpacker) 365 assert.Equal(t, test.metadataType, p.MetadataType) 366 test.wantErr(t, err) 367 368 if test.wantMetadata != nil { 369 assert.True(t, reflect.DeepEqual(test.wantMetadata, p.Metadata)) 370 } 371 }) 372 } 373 }