github.com/anchore/syft@v1.4.2-0.20240516191711-1bec1fc5d397/syft/file/location_set_test.go (about)

     1  package file
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/assert"
     7  	"github.com/stretchr/testify/require"
     8  
     9  	"github.com/anchore/syft/syft/artifact"
    10  )
    11  
    12  func TestLocationSet(t *testing.T) {
    13  
    14  	etcHostsLinkVar := Location{
    15  		LocationData: LocationData{
    16  			Coordinates: Coordinates{
    17  				RealPath:     "/etc/hosts",
    18  				FileSystemID: "a",
    19  			},
    20  			AccessPath: "/var/etc/hosts",
    21  		},
    22  	}
    23  
    24  	etcHostsLinkHome := Location{
    25  		LocationData: LocationData{
    26  			Coordinates: Coordinates{
    27  				RealPath:     "/etc/hosts",
    28  				FileSystemID: "a",
    29  			},
    30  			AccessPath: "/home/wagoodman/hosts",
    31  		},
    32  	}
    33  
    34  	binA := Location{
    35  		LocationData: LocationData{
    36  			Coordinates: Coordinates{
    37  				RealPath:     "/bin",
    38  				FileSystemID: "a",
    39  			},
    40  			AccessPath: "/usr/bin",
    41  		},
    42  	}
    43  
    44  	binB := Location{
    45  		LocationData: LocationData{
    46  			Coordinates: Coordinates{
    47  				RealPath:     "/bin",
    48  				FileSystemID: "b",
    49  			},
    50  			AccessPath: "/usr/bin",
    51  		},
    52  	}
    53  
    54  	tests := []struct {
    55  		name     string
    56  		input    []Location
    57  		expected []Location
    58  	}{
    59  		{
    60  			name: "de-dup same location",
    61  			input: []Location{
    62  				binA, binA, binA,
    63  			},
    64  			expected: []Location{
    65  				binA,
    66  			},
    67  		},
    68  		{
    69  			name: "dont de-dup different filesystem",
    70  			input: []Location{
    71  				binB, binA,
    72  			},
    73  			expected: []Location{
    74  				binA, binB,
    75  			},
    76  		},
    77  		{
    78  			name: "dont de-dup different virtual paths",
    79  			input: []Location{
    80  				etcHostsLinkVar, etcHostsLinkHome,
    81  			},
    82  			expected: []Location{
    83  				etcHostsLinkHome, etcHostsLinkVar,
    84  			},
    85  		},
    86  	}
    87  
    88  	for _, test := range tests {
    89  		t.Run(test.name, func(t *testing.T) {
    90  			set := NewLocationSet(test.input...)
    91  			assert.Equal(t, test.expected, set.ToSlice())
    92  		})
    93  	}
    94  }
    95  
    96  func TestLocationSet_Hash(t *testing.T) {
    97  	etcAlink := Location{
    98  		LocationData: LocationData{
    99  			Coordinates: Coordinates{
   100  				RealPath:     "/etc/hosts",
   101  				FileSystemID: "a",
   102  			},
   103  			AccessPath: "/var/etc/hosts",
   104  		},
   105  	}
   106  
   107  	etcA := Location{
   108  		LocationData: LocationData{
   109  			Coordinates: Coordinates{
   110  				RealPath:     "/etc/hosts",
   111  				FileSystemID: "a",
   112  			},
   113  		},
   114  	}
   115  
   116  	etcB := Location{
   117  		LocationData: LocationData{
   118  			Coordinates: Coordinates{
   119  				RealPath:     "/etc/hosts",
   120  				FileSystemID: "b",
   121  			},
   122  		},
   123  	}
   124  
   125  	binA := Location{
   126  		LocationData: LocationData{
   127  			Coordinates: Coordinates{
   128  				RealPath:     "/bin",
   129  				FileSystemID: "a",
   130  			},
   131  			AccessPath: "/usr/bin",
   132  		},
   133  	}
   134  
   135  	binB := Location{
   136  		LocationData: LocationData{
   137  			Coordinates: Coordinates{
   138  				RealPath:     "/bin",
   139  				FileSystemID: "b",
   140  			},
   141  			AccessPath: "/usr/bin",
   142  		},
   143  	}
   144  
   145  	tests := []struct {
   146  		name string
   147  		setA LocationSet
   148  		setB LocationSet
   149  		want assert.ComparisonAssertionFunc
   150  	}{
   151  		{
   152  			name: "empty sets have the same hash",
   153  			setA: NewLocationSet(),
   154  			setB: NewLocationSet(),
   155  			want: assert.Equal,
   156  		},
   157  		{
   158  			name: "sets with same elements accessed through different paths have the same hash",
   159  			setA: NewLocationSet(binA, etcA),
   160  			setB: NewLocationSet(etcAlink, binA),
   161  			want: assert.Equal,
   162  		},
   163  		{
   164  			name: "sets with same elements have the same hash",
   165  			setA: NewLocationSet(binA, etcA),
   166  			setB: NewLocationSet(etcA, binA),
   167  			want: assert.Equal,
   168  		},
   169  		{
   170  			name: "sets with different element counts have different hashes",
   171  			setA: NewLocationSet(binA, etcA),
   172  			setB: NewLocationSet(binA),
   173  			want: assert.NotEqual,
   174  		},
   175  		{
   176  			name: "sets with same path but different FS IDs have the same hash",
   177  			setA: NewLocationSet(binA),
   178  			setB: NewLocationSet(binB),
   179  			want: assert.Equal,
   180  		},
   181  		{
   182  			name: "sets with same paths but different FS IDs have the same hash",
   183  			setA: NewLocationSet(etcA, binA),
   184  			setB: NewLocationSet(binB, etcB),
   185  			want: assert.Equal,
   186  		},
   187  	}
   188  	for _, tt := range tests {
   189  		t.Run(tt.name, func(t *testing.T) {
   190  			gotA, err := artifact.IDByHash(tt.setA)
   191  			require.NoError(t, err)
   192  			gotB, err := artifact.IDByHash(tt.setB)
   193  			require.NoError(t, err)
   194  			tt.want(t, gotA, gotB)
   195  		})
   196  	}
   197  }