github.com/google/osv-scalibr@v0.4.1/annotator/osduplicate/apk/apk_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 apk_test 16 17 import ( 18 "context" 19 "os" 20 "path/filepath" 21 "testing" 22 23 "github.com/google/go-cmp/cmp" 24 "github.com/google/go-cmp/cmp/cmpopts" 25 "github.com/google/go-cpy/cpy" 26 "github.com/google/osv-scalibr/annotator" 27 "github.com/google/osv-scalibr/annotator/osduplicate/apk" 28 "github.com/google/osv-scalibr/extractor" 29 scalibrfs "github.com/google/osv-scalibr/fs" 30 "github.com/google/osv-scalibr/inventory" 31 "github.com/google/osv-scalibr/inventory/vex" 32 "google.golang.org/protobuf/proto" 33 ) 34 35 func TestAnnotate(t *testing.T) { 36 cancelledContext, cancel := context.WithCancel(context.Background()) 37 cancel() 38 39 copier := cpy.New( 40 cpy.Func(proto.Clone), 41 cpy.IgnoreAllUnexported(), 42 ) 43 44 tests := []struct { 45 desc string 46 apkDB string 47 packages []*extractor.Package 48 //nolint:containedctx 49 ctx context.Context 50 wantErr error 51 wantPackages []*extractor.Package 52 }{ 53 { 54 desc: "empty_db", 55 apkDB: "testdata/empty", 56 packages: []*extractor.Package{ 57 { 58 Name: "libstdc++", 59 Locations: []string{"usr/lib/libstdc++.so.6.0.33"}, 60 }, 61 }, 62 wantPackages: []*extractor.Package{ 63 { 64 Name: "libstdc++", 65 Locations: []string{"usr/lib/libstdc++.so.6.0.33"}, 66 }, 67 }, 68 }, 69 { 70 desc: "some_pkgs_found_in_db", 71 apkDB: "testdata/some", 72 packages: []*extractor.Package{ 73 { 74 Name: "libstdc++", 75 Locations: []string{"usr/lib/libstdc++.so.6.0.33"}, 76 }, 77 { 78 Name: "not-in-db", 79 Locations: []string{"path/not/in/db"}, 80 }, 81 }, 82 wantPackages: []*extractor.Package{ 83 { 84 Name: "libstdc++", 85 Locations: []string{"usr/lib/libstdc++.so.6.0.33"}, 86 ExploitabilitySignals: []*vex.PackageExploitabilitySignal{&vex.PackageExploitabilitySignal{ 87 Plugin: apk.Name, 88 Justification: vex.ComponentNotPresent, 89 MatchesAllVulns: true, 90 }}, 91 }, 92 { 93 Name: "not-in-db", 94 Locations: []string{"path/not/in/db"}, 95 }, 96 }, 97 }, 98 { 99 desc: "ctx_cancelled", 100 ctx: cancelledContext, 101 apkDB: "testdata/some", 102 packages: []*extractor.Package{ 103 { 104 Name: "libstdc++", 105 Locations: []string{"usr/lib/libstdc++.so.6.0.33"}, 106 }, 107 }, 108 wantPackages: []*extractor.Package{ 109 { 110 Name: "libstdc++", 111 Locations: []string{"usr/lib/libstdc++.so.6.0.33"}, 112 // No annotations 113 }, 114 }, 115 wantErr: cmpopts.AnyError, 116 }, 117 } 118 119 for _, tt := range tests { 120 t.Run(tt.desc, func(t *testing.T) { 121 if tt.ctx == nil { 122 tt.ctx = context.Background() 123 } 124 125 tmpPath := setupApkDB(t, tt.apkDB) 126 input := &annotator.ScanInput{ 127 ScanRoot: scalibrfs.RealFSScanRoot(tmpPath), 128 } 129 130 // Deep copy the packages to avoid modifying the original inventory that is used in other tests. 131 packages := copier.Copy(tt.packages).([]*extractor.Package) 132 inv := &inventory.Inventory{Packages: packages} 133 134 err := apk.New().Annotate(tt.ctx, input, inv) 135 if !cmp.Equal(tt.wantErr, err, cmpopts.EquateErrors()) { 136 t.Fatalf("Annotate(%v) error: %v, want %v", tt.packages, err, tt.wantErr) 137 } 138 139 want := &inventory.Inventory{Packages: tt.wantPackages} 140 if diff := cmp.Diff(want, inv); diff != "" { 141 t.Errorf("Annotate(%v): unexpected diff (-want +got): %v", tt.packages, diff) 142 } 143 }) 144 } 145 } 146 147 // Sets up the apk db 148 func setupApkDB(t *testing.T, file string) string { 149 t.Helper() 150 dir := t.TempDir() 151 dbFolder := filepath.Join(dir, "lib/apk/db/") 152 if err := os.MkdirAll(dbFolder, 0777); err != nil { 153 t.Fatalf("error creating directory %q: %v", dbFolder, err) 154 } 155 156 content, err := os.ReadFile(file) 157 if err != nil { 158 t.Fatalf("Error reading content file %q: %v", content, err) 159 } 160 161 dbFile := filepath.Join(dbFolder, "installed") 162 if err := os.WriteFile(dbFile, content, 0644); err != nil { 163 t.Fatalf("Error creating file %q: %v", dbFile, err) 164 } 165 166 return dir 167 }