github.com/google/osv-scalibr@v0.4.1/enricher/license/license_test.go (about) 1 // Copyright 2025 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package license_test 16 17 import ( 18 "context" 19 "testing" 20 21 depsdevpb "deps.dev/api/v3" 22 "github.com/google/go-cmp/cmp" 23 "github.com/google/go-cmp/cmp/cmpopts" 24 "github.com/google/go-cpy/cpy" 25 "github.com/google/osv-scalibr/enricher" 26 "github.com/google/osv-scalibr/enricher/license" 27 "github.com/google/osv-scalibr/enricher/license/fakeclient" 28 "github.com/google/osv-scalibr/extractor" 29 "github.com/google/osv-scalibr/inventory" 30 "github.com/google/osv-scalibr/purl" 31 "google.golang.org/protobuf/proto" 32 ) 33 34 func TestEnrich(t *testing.T) { 35 cancelledContext, cancel := context.WithCancel(t.Context()) 36 cancel() 37 38 copier := cpy.New( 39 cpy.Func(proto.Clone), 40 cpy.IgnoreAllUnexported(), 41 ) 42 43 licenseMap := map[*depsdevpb.VersionKey][]string{ 44 {System: depsdevpb.System_NPM, Name: "express", Version: "4.17.1"}: {"MIT"}, 45 {System: depsdevpb.System_PYPI, Name: "requests", Version: "2.26.0"}: {"Apache-2.0"}, 46 {System: depsdevpb.System_GO, Name: "github.com/gin-gonic/gin", Version: "v1.8.1"}: {"MIT"}, 47 } 48 49 cli := fakeclient.New(licenseMap) 50 e := license.NewWithClient(cli) 51 52 tests := []struct { 53 name string 54 packages []*extractor.Package 55 //nolint:containedctx 56 ctx context.Context 57 wantErr error 58 wantPackages []*extractor.Package 59 }{ 60 { 61 name: "ctx_cancelled", 62 ctx: cancelledContext, 63 wantErr: cmpopts.AnyError, 64 packages: []*extractor.Package{ 65 {Name: "express", Version: "4.17.1", PURLType: purl.TypeNPM}, 66 {Name: "requests", Version: "2.26.0", PURLType: purl.TypePyPi}, 67 {Name: "github.com/gin-gonic/gin", Version: "1.8.1", PURLType: purl.TypeGolang}, 68 }, 69 wantPackages: []*extractor.Package{ 70 // No license data 71 {Name: "express", Version: "4.17.1", PURLType: purl.TypeNPM}, 72 {Name: "requests", Version: "2.26.0", PURLType: purl.TypePyPi}, 73 {Name: "github.com/gin-gonic/gin", Version: "1.8.1", PURLType: purl.TypeGolang}, 74 }, 75 }, 76 { 77 name: "simple_test", 78 packages: []*extractor.Package{ 79 {Name: "express", Version: "4.17.1", PURLType: purl.TypeNPM}, 80 {Name: "requests", Version: "2.26.0", PURLType: purl.TypePyPi}, 81 {Name: "github.com/gin-gonic/gin", Version: "1.8.1", PURLType: purl.TypeGolang}, 82 }, 83 wantPackages: []*extractor.Package{ 84 {Name: "express", Version: "4.17.1", PURLType: purl.TypeNPM, Licenses: []string{"MIT"}}, 85 {Name: "requests", Version: "2.26.0", PURLType: purl.TypePyPi, Licenses: []string{"Apache-2.0"}}, 86 {Name: "github.com/gin-gonic/gin", Version: "1.8.1", PURLType: purl.TypeGolang, Licenses: []string{"MIT"}}, 87 }, 88 }, 89 { 90 name: "not_covered_purl_type", 91 packages: []*extractor.Package{ 92 {Name: "fzf", Version: "0.63.0", PURLType: purl.TypeBrew}, 93 }, 94 wantPackages: []*extractor.Package{ 95 // UNKNOWN license 96 {Name: "fzf", Version: "0.63.0", PURLType: purl.TypeBrew, Licenses: []string{"UNKNOWN"}}, 97 }, 98 }, 99 { 100 name: "unknown_package", 101 packages: []*extractor.Package{ 102 {Name: "unknown", Version: "1.8.1", PURLType: purl.TypeGolang}, 103 }, 104 wantPackages: []*extractor.Package{ 105 // UNKNOWN license 106 {Name: "unknown", Version: "1.8.1", PURLType: purl.TypeGolang, Licenses: []string{"UNKNOWN"}}, 107 }, 108 }, 109 { 110 name: "not_covered_pkg_with_already_a_license", 111 packages: []*extractor.Package{ 112 {Name: "fzf", Version: "0.63.0", PURLType: purl.TypeBrew, Licenses: []string{"Apache-2.0"}}, 113 }, 114 wantPackages: []*extractor.Package{ 115 {Name: "fzf", Version: "0.63.0", PURLType: purl.TypeBrew, Licenses: []string{"Apache-2.0"}}, 116 }, 117 }, 118 { 119 name: "covered_pkg_with_already_a_license", 120 packages: []*extractor.Package{ 121 {Name: "express", Version: "4.17.1", PURLType: purl.TypeNPM, Licenses: []string{"MIT"}}, 122 }, 123 wantPackages: []*extractor.Package{ 124 {Name: "express", Version: "4.17.1", PURLType: purl.TypeNPM, Licenses: []string{"MIT"}}, 125 }, 126 }, 127 { 128 name: "covered_pkg_with_wrong_license", 129 packages: []*extractor.Package{ 130 {Name: "express", Version: "4.17.1", PURLType: purl.TypeNPM, Licenses: []string{"Apache-2.0"}}, 131 }, 132 wantPackages: []*extractor.Package{ 133 {Name: "express", Version: "4.17.1", PURLType: purl.TypeNPM, Licenses: []string{"MIT"}}, 134 }, 135 }, 136 { 137 name: "not_covered_purl_type_between_covered_pkgs", 138 packages: []*extractor.Package{ 139 {Name: "express", Version: "4.17.1", PURLType: purl.TypeNPM}, 140 {Name: "github.com/gin-gonic/gin", Version: "1.8.1", PURLType: purl.TypeGolang}, 141 {Name: "fzf", Version: "0.63.0", PURLType: purl.TypeBrew}, 142 {Name: "requests", Version: "2.26.0", PURLType: purl.TypePyPi}, 143 }, 144 wantPackages: []*extractor.Package{ 145 {Name: "express", Version: "4.17.1", PURLType: purl.TypeNPM, Licenses: []string{"MIT"}}, 146 {Name: "github.com/gin-gonic/gin", Version: "1.8.1", PURLType: purl.TypeGolang, Licenses: []string{"MIT"}}, 147 {Name: "fzf", Version: "0.63.0", PURLType: purl.TypeBrew, Licenses: []string{"UNKNOWN"}}, 148 {Name: "requests", Version: "2.26.0", PURLType: purl.TypePyPi, Licenses: []string{"Apache-2.0"}}, 149 }, 150 }, 151 } 152 153 for _, tt := range tests { 154 t.Run(tt.name, func(t *testing.T) { 155 if tt.ctx == nil { 156 tt.ctx = t.Context() 157 } 158 159 var input *enricher.ScanInput 160 161 packages := copier.Copy(tt.packages).([]*extractor.Package) 162 inv := &inventory.Inventory{Packages: packages} 163 164 err := e.Enrich(tt.ctx, input, inv) 165 if !cmp.Equal(tt.wantErr, err, cmpopts.EquateErrors()) { 166 t.Fatalf("Enrich(%v) error: %v, want %v", tt.packages, err, tt.wantErr) 167 } 168 169 want := &inventory.Inventory{Packages: tt.wantPackages} 170 if diff := cmp.Diff(want, inv); diff != "" { 171 t.Errorf("Enrich(%v): unexpected diff (-want +got): %v", tt.packages, diff) 172 } 173 }) 174 } 175 }