github.com/google/osv-scalibr@v0.4.1/testing/fakeextractor/fake_extractor_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 fakeextractor_test
    16  
    17  import (
    18  	"context"
    19  	"io/fs"
    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/osv-scalibr/extractor"
    26  	"github.com/google/osv-scalibr/extractor/filesystem"
    27  	"github.com/google/osv-scalibr/extractor/filesystem/simplefileapi"
    28  	"github.com/google/osv-scalibr/inventory"
    29  	"github.com/google/osv-scalibr/testing/fakeextractor"
    30  	"github.com/google/osv-scalibr/testing/fakefs"
    31  )
    32  
    33  func TestName(t *testing.T) {
    34  	tests := []struct {
    35  		name      string
    36  		extractor filesystem.Extractor
    37  		want      string
    38  	}{
    39  		{
    40  			name:      "no name",
    41  			extractor: fakeextractor.New("", 1, nil, nil),
    42  			want:      "",
    43  		},
    44  		{
    45  			name:      "name",
    46  			extractor: fakeextractor.New("some extractor", 1, nil, nil),
    47  			want:      "some extractor",
    48  		},
    49  	}
    50  
    51  	for _, test := range tests {
    52  		t.Run(test.name, func(t *testing.T) {
    53  			got := test.extractor.Name()
    54  			if got != test.want {
    55  				t.Fatalf("extractor.Name() = %q, want %q", got, test.want)
    56  			}
    57  		})
    58  	}
    59  }
    60  
    61  func TestVersion(t *testing.T) {
    62  	tests := []struct {
    63  		name      string
    64  		extractor filesystem.Extractor
    65  		want      int
    66  	}{
    67  		{
    68  			name:      "zero version",
    69  			extractor: fakeextractor.New("", 0, nil, nil),
    70  			want:      0,
    71  		},
    72  		{
    73  			name:      "positive version",
    74  			extractor: fakeextractor.New("some extractor", 7, nil, nil),
    75  			want:      7,
    76  		},
    77  	}
    78  
    79  	for _, test := range tests {
    80  		t.Run(test.name, func(t *testing.T) {
    81  			got := test.extractor.Version()
    82  			if got != test.want {
    83  				t.Fatalf("extractor.Version() = %d, want %d", got, test.want)
    84  			}
    85  		})
    86  	}
    87  }
    88  
    89  func TestFileRequired(t *testing.T) {
    90  	type args struct {
    91  		path string
    92  		mode fs.FileMode
    93  	}
    94  
    95  	tests := []struct {
    96  		name      string
    97  		extractor filesystem.Extractor
    98  		args      args
    99  		want      bool
   100  	}{
   101  		{
   102  			name:      "file required",
   103  			extractor: fakeextractor.New("", 1, []string{"some file", "another file"}, nil),
   104  			args:      args{"some file", fs.ModePerm},
   105  			want:      true,
   106  		},
   107  		{
   108  			name:      "file not required because none are required by extractor",
   109  			extractor: fakeextractor.New("", 1, nil, nil),
   110  			args:      args{"some file", fs.ModePerm},
   111  			want:      false,
   112  		},
   113  		{
   114  			name:      "file not the same as required files",
   115  			extractor: fakeextractor.New("", 1, []string{"some file", "another file"}, nil),
   116  			args:      args{"yet another file", fs.ModePerm},
   117  			want:      false,
   118  		},
   119  	}
   120  
   121  	for _, test := range tests {
   122  		t.Run(test.name, func(t *testing.T) {
   123  			got := test.extractor.FileRequired(simplefileapi.New(test.args.path, fakefs.FakeFileInfo{
   124  				FileName: filepath.Base(test.args.path),
   125  				FileMode: test.args.mode,
   126  			}))
   127  			if diff := cmp.Diff(test.want, got); diff != "" {
   128  				t.Fatalf("extractor.FileRequired(%v, %v) returned unexpected result; diff (-want +got):\n%s", test.args.path, test.args.mode, diff)
   129  			}
   130  		})
   131  	}
   132  }
   133  
   134  func TestExtract(t *testing.T) {
   135  	name1 := "package"
   136  	name2 := "another package"
   137  	multiplePackages := []*extractor.Package{{
   138  		Name:      name1,
   139  		Locations: []string{"some path"},
   140  	}, {
   141  		Name:      name2,
   142  		Locations: []string{"some path"},
   143  	}}
   144  
   145  	type args struct {
   146  		//nolint:containedctx
   147  		ctx   context.Context
   148  		input *filesystem.ScanInput
   149  	}
   150  	tests := []struct {
   151  		name      string
   152  		extractor filesystem.Extractor
   153  		args      args
   154  		want      []*extractor.Package
   155  		wantErr   error
   156  	}{
   157  		{
   158  			name: "no_results",
   159  			extractor: fakeextractor.New("", 1, nil, map[string]fakeextractor.NamesErr{
   160  				"some path": {nil, nil},
   161  			}),
   162  			args: args{t.Context(), &filesystem.ScanInput{Path: "some path"}},
   163  			want: []*extractor.Package{},
   164  		},
   165  		{
   166  			name: "multiple_results",
   167  			extractor: fakeextractor.New("extractor name", 1, nil, map[string]fakeextractor.NamesErr{
   168  				"some path": {[]string{name1, name2}, nil},
   169  			}),
   170  			args: args{t.Context(), &filesystem.ScanInput{Path: "some path"}},
   171  			want: multiplePackages,
   172  		},
   173  		{
   174  			name: "unrecognized_path_throws_an_error",
   175  			extractor: fakeextractor.New("", 1, nil, map[string]fakeextractor.NamesErr{
   176  				"some path": {nil, nil},
   177  			}),
   178  			args:    args{t.Context(), &filesystem.ScanInput{Path: "another path"}},
   179  			wantErr: cmpopts.AnyError,
   180  		},
   181  	}
   182  
   183  	for _, test := range tests {
   184  		t.Run(test.name, func(t *testing.T) {
   185  			got, err := test.extractor.Extract(test.args.ctx, test.args.input)
   186  			if !cmp.Equal(err, test.wantErr, cmpopts.EquateErrors()) {
   187  				t.Fatalf("extractor.Extract(%v, %+v) got error: %v, want: %v\n", test.args.ctx, test.args.input, err, test.wantErr)
   188  			}
   189  			wantInv := inventory.Inventory{Packages: test.want}
   190  			if diff := cmp.Diff(wantInv, got); diff != "" {
   191  				t.Fatalf("extractor.Extract(%v, %+v) returned unexpected result; diff (-want +got):\n%s", test.args.ctx, test.args.input, diff)
   192  			}
   193  		})
   194  	}
   195  }