github.com/google/osv-scalibr@v0.4.1/testing/fakeenricher/fake_enricher_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 fakeenricher_test
    16  
    17  import (
    18  	"io/fs"
    19  	"testing"
    20  	"testing/fstest"
    21  
    22  	"github.com/google/go-cmp/cmp"
    23  	"github.com/google/go-cmp/cmp/cmpopts"
    24  	"github.com/google/osv-scalibr/enricher"
    25  	"github.com/google/osv-scalibr/extractor"
    26  	scalibrfs "github.com/google/osv-scalibr/fs"
    27  	"github.com/google/osv-scalibr/inventory"
    28  	"github.com/google/osv-scalibr/plugin"
    29  	"github.com/google/osv-scalibr/testing/fakeenricher"
    30  	osvpb "github.com/ossf/osv-schema/bindings/go/osvschema"
    31  	"google.golang.org/protobuf/testing/protocmp"
    32  )
    33  
    34  func TestName(t *testing.T) {
    35  	tests := []struct {
    36  		name string
    37  		cfg  *fakeenricher.Config
    38  	}{
    39  		{
    40  			name: "no_name",
    41  			cfg:  &fakeenricher.Config{},
    42  		},
    43  		{
    44  			name: "name",
    45  			cfg:  &fakeenricher.Config{Name: "some enricher"},
    46  		},
    47  	}
    48  
    49  	for _, tc := range tests {
    50  		t.Run(tc.name, func(t *testing.T) {
    51  			e := fakeenricher.MustNew(t, tc.cfg)
    52  			got := e.Name()
    53  			if got != tc.cfg.Name {
    54  				t.Errorf("Enricher{%+v}.Name() = %q, want %q", tc.cfg, got, tc.cfg.Name)
    55  			}
    56  		})
    57  	}
    58  }
    59  
    60  func TestVersion(t *testing.T) {
    61  	tests := []struct {
    62  		name string
    63  		cfg  *fakeenricher.Config
    64  	}{
    65  		{
    66  			name: "zero_version",
    67  			cfg:  &fakeenricher.Config{},
    68  		},
    69  		{
    70  			name: "positive_version",
    71  			cfg:  &fakeenricher.Config{Version: 7},
    72  		},
    73  	}
    74  
    75  	for _, tc := range tests {
    76  		t.Run(tc.name, func(t *testing.T) {
    77  			e := fakeenricher.MustNew(t, tc.cfg)
    78  			got := e.Version()
    79  			if got != tc.cfg.Version {
    80  				t.Errorf("Enricher{%+v}.Version() = %d, want %d", tc.cfg, got, tc.cfg.Version)
    81  			}
    82  		})
    83  	}
    84  }
    85  
    86  func TestRequirements(t *testing.T) {
    87  	tests := []struct {
    88  		name string
    89  		cfg  *fakeenricher.Config
    90  	}{
    91  		{
    92  			name: "no_requirements",
    93  			cfg:  &fakeenricher.Config{},
    94  		},
    95  		{
    96  			name: "some_requirements",
    97  			cfg: &fakeenricher.Config{
    98  				Capabilities: &plugin.Capabilities{
    99  					Network:  plugin.NetworkOnline,
   100  					DirectFS: true,
   101  				},
   102  			},
   103  		},
   104  	}
   105  
   106  	for _, tc := range tests {
   107  		t.Run(tc.name, func(t *testing.T) {
   108  			e := fakeenricher.MustNew(t, tc.cfg)
   109  			got := e.Requirements()
   110  			if diff := cmp.Diff(tc.cfg.Capabilities, got); diff != "" {
   111  				t.Errorf("Enricher{%+v}.Requirements() returned unexpected diff (-want +got):\n%s", tc.cfg, diff)
   112  			}
   113  		})
   114  	}
   115  }
   116  
   117  func TestRequiredPlugins(t *testing.T) {
   118  	tests := []struct {
   119  		name string
   120  		cfg  *fakeenricher.Config
   121  	}{
   122  		{
   123  			name: "no_required_plugins",
   124  			cfg:  &fakeenricher.Config{},
   125  		},
   126  		{
   127  			name: "some_required_plugins",
   128  			cfg:  &fakeenricher.Config{RequiredPlugins: []string{"plugin1", "plugin2"}},
   129  		},
   130  	}
   131  
   132  	for _, tc := range tests {
   133  		t.Run(tc.name, func(t *testing.T) {
   134  			e := fakeenricher.MustNew(t, tc.cfg)
   135  			got := e.RequiredPlugins()
   136  			if diff := cmp.Diff(tc.cfg.RequiredPlugins, got); diff != "" {
   137  				t.Errorf("Enricher{%+v}.RequiredPlugins() returned unexpected diff (-want +got):\n%s", tc.cfg, diff)
   138  			}
   139  		})
   140  	}
   141  }
   142  
   143  func TestEnrich(t *testing.T) {
   144  	input1 := &enricher.ScanInput{
   145  		ScanRoot: &scalibrfs.ScanRoot{
   146  			FS: fstest.MapFS{
   147  				"/some/file.text":  {Mode: fs.ModePerm},
   148  				"/another/file.md": {Mode: fs.ModePerm},
   149  			},
   150  			Path: "root",
   151  		},
   152  	}
   153  	inventory1 := &inventory.Inventory{
   154  		Packages: []*extractor.Package{{
   155  			Name:    "package1",
   156  			Version: "1.0",
   157  		}},
   158  		PackageVulns: []*inventory.PackageVuln{
   159  			{
   160  				Vulnerability: &osvpb.Vulnerability{Id: "CVE-9012"},
   161  			},
   162  		},
   163  		GenericFindings: []*inventory.GenericFinding{{
   164  			Adv: &inventory.GenericFindingAdvisory{
   165  				ID: &inventory.AdvisoryID{
   166  					Publisher: "CVE",
   167  					Reference: "CVE-2024-12345",
   168  				},
   169  			},
   170  		}},
   171  	}
   172  
   173  	inventory2 := &inventory.Inventory{
   174  		Packages: []*extractor.Package{{
   175  			Name:    "package2",
   176  			Version: "2.0",
   177  		}, {
   178  			Name:    "package3",
   179  			Version: "3.0",
   180  		}},
   181  		PackageVulns: []*inventory.PackageVuln{{
   182  			Vulnerability: &osvpb.Vulnerability{Id: "CVE-9012"},
   183  		}},
   184  		GenericFindings: []*inventory.GenericFinding{{
   185  			Adv: &inventory.GenericFindingAdvisory{
   186  				ID: &inventory.AdvisoryID{
   187  					Publisher: "CVE",
   188  					Reference: "CVE-2024-12345",
   189  				},
   190  			},
   191  		}, {
   192  			Adv: &inventory.GenericFindingAdvisory{
   193  				ID: &inventory.AdvisoryID{
   194  					Publisher: "CVE",
   195  					Reference: "CVE-2024-67890",
   196  				},
   197  				Recommendation: "do something",
   198  			},
   199  			Target: &inventory.GenericFindingTargetDetails{
   200  				Extra: "extra info",
   201  			},
   202  		}},
   203  	}
   204  
   205  	tests := []struct {
   206  		name    string
   207  		cfg     *fakeenricher.Config
   208  		input   *enricher.ScanInput
   209  		inv     *inventory.Inventory
   210  		wantInv *inventory.Inventory
   211  		wantErr error
   212  	}{
   213  		{
   214  			name: "nothing_to_enrich",
   215  			cfg: &fakeenricher.Config{
   216  				WantEnrich: map[uint64]fakeenricher.InventoryAndErr{
   217  					fakeenricher.MustHash(t, nil, &inventory.Inventory{}): fakeenricher.InventoryAndErr{
   218  						Inventory: &inventory.Inventory{},
   219  					},
   220  				},
   221  			},
   222  			inv:     &inventory.Inventory{},
   223  			wantInv: &inventory.Inventory{},
   224  		},
   225  		{
   226  			name: "enrich_packages_and_findings",
   227  			cfg: &fakeenricher.Config{
   228  				WantEnrich: map[uint64]fakeenricher.InventoryAndErr{
   229  					fakeenricher.MustHash(t, input1, inventory1): fakeenricher.InventoryAndErr{
   230  						Inventory: inventory2,
   231  					},
   232  				},
   233  			},
   234  			input:   input1,
   235  			inv:     inventory1,
   236  			wantInv: inventory2,
   237  		},
   238  	}
   239  
   240  	for _, tc := range tests {
   241  		t.Run(tc.name, func(t *testing.T) {
   242  			e := fakeenricher.MustNew(t, tc.cfg)
   243  			gotErr := e.Enrich(t.Context(), tc.input, tc.inv)
   244  			if !cmp.Equal(gotErr, tc.wantErr, cmpopts.EquateErrors()) {
   245  				t.Errorf("Enricher{%+v}.Enrich(%+v, %+v) error: got %v, want %v\n", tc.cfg, tc.input, tc.inv, gotErr, tc.wantErr)
   246  			}
   247  			if diff := cmp.Diff(tc.wantInv, tc.inv, protocmp.Transform()); diff != "" {
   248  				t.Errorf("Enricher{%+v}.Enrich(%+v, %+v) returned unexpected diff (-want +got):\n%s", tc.cfg, tc.input, tc.inv, diff)
   249  			}
   250  		})
   251  	}
   252  }