github.com/google/osv-scalibr@v0.4.1/annotator/osduplicate/osduplicate_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 osduplicate_test
    16  
    17  import (
    18  	"testing"
    19  
    20  	"github.com/google/go-cmp/cmp"
    21  	"github.com/google/osv-scalibr/annotator/osduplicate"
    22  	"github.com/google/osv-scalibr/extractor"
    23  	scalibrfs "github.com/google/osv-scalibr/fs"
    24  	"github.com/google/osv-scalibr/inventory"
    25  )
    26  
    27  func TestBuildLocationToPKGsMap(t *testing.T) {
    28  	tests := []struct {
    29  		desc      string
    30  		inventory *inventory.Inventory
    31  		scanRoot  string
    32  		want      map[string][]*extractor.Package
    33  	}{
    34  		{
    35  			desc:      "empty_inventory",
    36  			inventory: &inventory.Inventory{},
    37  			want:      map[string][]*extractor.Package{},
    38  		},
    39  		{
    40  			desc: "one_pkg_per_location",
    41  			inventory: &inventory.Inventory{
    42  				Packages: []*extractor.Package{
    43  					{Name: "package1", Locations: []string{"location1"}},
    44  					{Name: "package2", Locations: []string{"location2"}},
    45  				},
    46  			},
    47  			want: map[string][]*extractor.Package{
    48  				"location1": []*extractor.Package{{Name: "package1", Locations: []string{"location1"}}},
    49  				"location2": []*extractor.Package{{Name: "package2", Locations: []string{"location2"}}},
    50  			},
    51  		},
    52  		{
    53  			desc: "multiple_pkgs_per_location",
    54  			inventory: &inventory.Inventory{
    55  				Packages: []*extractor.Package{
    56  					{Name: "package1", Locations: []string{"location"}},
    57  					{Name: "package2", Locations: []string{"location"}},
    58  				},
    59  			},
    60  			want: map[string][]*extractor.Package{
    61  				"location": []*extractor.Package{
    62  					{Name: "package1", Locations: []string{"location"}},
    63  					{Name: "package2", Locations: []string{"location"}},
    64  				},
    65  			},
    66  		},
    67  		{
    68  			desc: "ignore_non_lockfile_locations",
    69  			inventory: &inventory.Inventory{
    70  				Packages: []*extractor.Package{
    71  					{Name: "package", Locations: []string{"lockfile", "non-lockfile"}},
    72  				},
    73  			},
    74  			want: map[string][]*extractor.Package{
    75  				"lockfile": []*extractor.Package{{Name: "package", Locations: []string{"lockfile", "non-lockfile"}}},
    76  			},
    77  		},
    78  		{
    79  			desc: "ignore_os_packages",
    80  			inventory: &inventory.Inventory{
    81  				Packages: []*extractor.Package{
    82  					{Name: "os-package", Locations: []string{"location-1"}, Plugins: []string{"os/dpkg"}},
    83  					{Name: "language-package", Locations: []string{"location-2"}, Plugins: []string{"python/wheelegg"}},
    84  				},
    85  			},
    86  			want: map[string][]*extractor.Package{
    87  				"location-2": []*extractor.Package{{Name: "language-package", Locations: []string{"location-2"}, Plugins: []string{"python/wheelegg"}}},
    88  			},
    89  		},
    90  		{
    91  			desc: "absolute_to_relative_paths",
    92  			inventory: &inventory.Inventory{
    93  				Packages: []*extractor.Package{
    94  					{Name: "package1", Locations: []string{"/root/location1"}},
    95  					{Name: "package2", Locations: []string{"/root/location2"}},
    96  				},
    97  			},
    98  			scanRoot: "/root/",
    99  			want: map[string][]*extractor.Package{
   100  				"location1": []*extractor.Package{{Name: "package1", Locations: []string{"/root/location1"}}},
   101  				"location2": []*extractor.Package{{Name: "package2", Locations: []string{"/root/location2"}}},
   102  			},
   103  		},
   104  		{
   105  			desc: "absolute_to_relative_paths_no_leading_slash",
   106  			inventory: &inventory.Inventory{
   107  				Packages: []*extractor.Package{
   108  					{Name: "package1", Locations: []string{"/root/location1"}},
   109  					{Name: "package2", Locations: []string{"/root/location2"}},
   110  				},
   111  			},
   112  			scanRoot: "/root",
   113  			want: map[string][]*extractor.Package{
   114  				"location1": []*extractor.Package{{Name: "package1", Locations: []string{"/root/location1"}}},
   115  				"location2": []*extractor.Package{{Name: "package2", Locations: []string{"/root/location2"}}},
   116  			},
   117  		},
   118  	}
   119  
   120  	for _, tt := range tests {
   121  		t.Run(tt.desc, func(t *testing.T) {
   122  			got := osduplicate.BuildLocationToPKGsMap(tt.inventory, &scalibrfs.ScanRoot{Path: tt.scanRoot})
   123  
   124  			if diff := cmp.Diff(tt.want, got); diff != "" {
   125  				t.Errorf("BuildLocationToPKGsMap(%v): unexpected diff (-want +got): %v", tt.inventory, diff)
   126  			}
   127  		})
   128  	}
   129  }