github.com/google/osv-scalibr@v0.4.1/extractor/filesystem/language/nim/nimble/nimble_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 nimble_test 16 17 import ( 18 "testing" 19 20 "github.com/google/go-cmp/cmp" 21 "github.com/google/go-cmp/cmp/cmpopts" 22 "github.com/google/osv-scalibr/extractor" 23 "github.com/google/osv-scalibr/extractor/filesystem" 24 "github.com/google/osv-scalibr/extractor/filesystem/language/nim/nimble" 25 "github.com/google/osv-scalibr/extractor/filesystem/simplefileapi" 26 "github.com/google/osv-scalibr/inventory" 27 "github.com/google/osv-scalibr/purl" 28 ) 29 30 func TestFileRequired(t *testing.T) { 31 tests := []struct { 32 name string 33 path string 34 wantRequired bool 35 }{ 36 { 37 name: "nimble file under the pkgs directory", 38 path: "test/.nimble/pkgs/arrayutils-0.2.0/arrayutils.nimble", 39 wantRequired: true, 40 }, 41 { 42 name: "nimble file under the pkgs2 directory", 43 path: "test/.nimble/pkgs2/json_serialization-0.4.2-2b26a9e0fc79638dbb9272fb4ab5a1d79264f938/json_serialization.nimble", 44 wantRequired: true, 45 }, 46 { 47 name: "nimble file under the pkgs2 directory with non-default installation", 48 path: "test/nimblefolder/pkgs2/stew-0.4.1-996d9c058ee078d0209a5f539424a0235683918c/stew.nimble", 49 wantRequired: true, 50 }, 51 { 52 name: "arbitrary file under the pkgs2 directory with no extension", 53 path: "test/.nimble/pkgs2/arrayutils-0.2.0/foo", 54 wantRequired: false, 55 }, 56 { 57 name: "nimble file under the wrong director", 58 path: "test/test-01/test.nimble", 59 wantRequired: false, 60 }, 61 } 62 63 for _, tt := range tests { 64 t.Run(tt.name, func(t *testing.T) { 65 var e filesystem.Extractor = nimble.Extractor{} 66 if got := e.FileRequired(simplefileapi.New(tt.path, nil)); got != tt.wantRequired { 67 t.Fatalf("FileRequired(%s): got %v, want %v", tt.path, got, tt.wantRequired) 68 } 69 }) 70 } 71 } 72 73 func pkgLess(i1, i2 *extractor.Package) bool { 74 return i1.Name < i2.Name 75 } 76 77 func TestExtract(t *testing.T) { 78 tests := []struct { 79 name string 80 path string 81 wantPackages []*extractor.Package 82 wantErr error 83 }{ 84 { 85 name: "valid_nimble_file_path_for_older_versions", 86 path: "/root/.nimble/pkgs/arrayutils-0.2.0/arrayutils.nimble", 87 wantPackages: []*extractor.Package{ 88 { 89 Name: "arrayutils", 90 Version: "0.2.0", 91 PURLType: purl.TypeNim, 92 Locations: []string{"/root/.nimble/pkgs/arrayutils-0.2.0/arrayutils.nimble"}, 93 }, 94 }, 95 }, 96 { 97 name: "valid_nimble_file_path_for_newer_versions", 98 path: "/root/.nimble/pkgs2/libsodium-0.6.0-a2bcc3d783446e393eacf5759dda821f0f714796/libsodium.nimble", 99 wantPackages: []*extractor.Package{ 100 { 101 Name: "libsodium", 102 Version: "0.6.0", 103 PURLType: purl.TypeNim, 104 Locations: []string{"/root/.nimble/pkgs2/libsodium-0.6.0-a2bcc3d783446e393eacf5759dda821f0f714796/libsodium.nimble"}, 105 }, 106 }, 107 }, 108 { 109 name: "valid_nimble_file_path_with_number", 110 path: "/root/.nimble/pkgs2/libp2p-1.12.0-336ec68bcd5f13337666dac935007f450a48a9be/libp2p.nimble", 111 wantPackages: []*extractor.Package{ 112 { 113 Name: "libp2p", 114 Version: "1.12.0", 115 PURLType: purl.TypeNim, 116 Locations: []string{"/root/.nimble/pkgs2/libp2p-1.12.0-336ec68bcd5f13337666dac935007f450a48a9be/libp2p.nimble"}, 117 }, 118 }, 119 }, 120 { 121 name: "valid_nimble_path_with_underscore", 122 path: "/root/.nimble/pkgs2/bearssl_pkey_decoder-0.1.0-21b42e2e6ddca6c875d3fc50f36a5115abf51714/bearssl_pkey_decoder.nimble", 123 wantPackages: []*extractor.Package{ 124 { 125 Name: "bearssl_pkey_decoder", 126 Version: "0.1.0", 127 PURLType: purl.TypeNim, 128 Locations: []string{"/root/.nimble/pkgs2/bearssl_pkey_decoder-0.1.0-21b42e2e6ddca6c875d3fc50f36a5115abf51714/bearssl_pkey_decoder.nimble"}, 129 }, 130 }, 131 }, 132 { 133 name: "valid_nimble_path_with_longer_version", 134 path: "/root/.nimble/pkgs2/secp256k1-0.6.0.3.2-0cda1744a5d85c872128c50e826b979a6c0f5471/secp256k1.nimble", 135 wantPackages: []*extractor.Package{ 136 { 137 Name: "secp256k1", 138 Version: "0.6.0.3.2", 139 PURLType: purl.TypeNim, 140 Locations: []string{"/root/.nimble/pkgs2/secp256k1-0.6.0.3.2-0cda1744a5d85c872128c50e826b979a6c0f5471/secp256k1.nimble"}, 141 }, 142 }, 143 }, 144 { 145 name: "invalid path", 146 path: "/tmp/var/scalibr", 147 wantPackages: nil, 148 }, 149 } 150 151 for _, tt := range tests { 152 t.Run(tt.name, func(t *testing.T) { 153 var e filesystem.Extractor = nimble.Extractor{} 154 input := &filesystem.ScanInput{Path: tt.path, Reader: nil} 155 got, err := e.Extract(t.Context(), input) 156 if diff := cmp.Diff(tt.wantErr, err, cmpopts.EquateErrors()); diff != "" { 157 t.Errorf("Extract(%s) unexpected error (-want +got):\n%s", tt.path, diff) 158 } 159 160 want := inventory.Inventory{Packages: tt.wantPackages} 161 162 if diff := cmp.Diff(want, got, cmpopts.SortSlices(pkgLess)); diff != "" { 163 t.Errorf("Extract(%s) (-want +got):\n%s", tt.path, diff) 164 } 165 }) 166 } 167 }