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  }