github.com/anchore/syft@v1.38.2/syft/file/locations_test.go (about)

     1  package file
     2  
     3  import (
     4  	"fmt"
     5  	"slices"
     6  	"testing"
     7  
     8  	"github.com/google/go-cmp/cmp"
     9  
    10  	"github.com/anchore/syft/internal/evidence"
    11  )
    12  
    13  func TestLocationAndCoordinatesSorters(t *testing.T) {
    14  	tests := []struct {
    15  		name       string
    16  		layers     []string
    17  		locs       []Location
    18  		coords     []Coordinates
    19  		wantLocs   []string
    20  		wantCoords []string
    21  	}{
    22  		{
    23  			name:       "empty location slice",
    24  			layers:     []string{"fsid-1"},
    25  			locs:       []Location{},
    26  			coords:     []Coordinates{},
    27  			wantLocs:   []string{},
    28  			wantCoords: []string{},
    29  		},
    30  		{
    31  			name:   "nil layer list",
    32  			layers: nil,
    33  			locs: []Location{
    34  				{
    35  					LocationData: LocationData{
    36  						Coordinates: Coordinates{
    37  							RealPath:     "/a",
    38  							FileSystemID: "fsid-1",
    39  						},
    40  						AccessPath: "/a",
    41  					},
    42  					LocationMetadata: LocationMetadata{
    43  						Annotations: map[string]string{},
    44  					},
    45  				},
    46  				{
    47  					LocationData: LocationData{
    48  						Coordinates: Coordinates{
    49  							RealPath:     "/b",
    50  							FileSystemID: "fsid-2",
    51  						},
    52  						AccessPath: "/b",
    53  					},
    54  					LocationMetadata: LocationMetadata{
    55  						Annotations: map[string]string{},
    56  					},
    57  				},
    58  			},
    59  			coords: []Coordinates{
    60  				{
    61  					RealPath:     "/a",
    62  					FileSystemID: "fsid-1",
    63  				},
    64  				{
    65  					RealPath:     "/b",
    66  					FileSystemID: "fsid-2",
    67  				},
    68  			},
    69  			wantLocs: []string{
    70  				"/a (/a) @ fsid-1 map[]",
    71  				"/b (/b) @ fsid-2 map[]",
    72  			},
    73  			wantCoords: []string{
    74  				"/a @ fsid-1",
    75  				"/b @ fsid-2",
    76  			},
    77  		},
    78  		{
    79  			name:   "sort by evidence type only",
    80  			layers: []string{"fsid-1"},
    81  			locs: []Location{
    82  				{
    83  					LocationData: LocationData{
    84  						Coordinates: Coordinates{
    85  							RealPath:     "/a",
    86  							FileSystemID: "fsid-1",
    87  						},
    88  						AccessPath: "/a",
    89  					},
    90  					LocationMetadata: LocationMetadata{
    91  						Annotations: map[string]string{
    92  							evidence.AnnotationKey: "",
    93  						},
    94  					},
    95  				},
    96  				{
    97  					LocationData: LocationData{
    98  						Coordinates: Coordinates{
    99  							RealPath:     "/b",
   100  							FileSystemID: "fsid-1",
   101  						},
   102  						AccessPath: "/b",
   103  					},
   104  					LocationMetadata: LocationMetadata{
   105  						Annotations: map[string]string{
   106  							evidence.AnnotationKey: evidence.SupportingAnnotation,
   107  						},
   108  					},
   109  				},
   110  				{
   111  					LocationData: LocationData{
   112  						Coordinates: Coordinates{
   113  							RealPath:     "/c",
   114  							FileSystemID: "fsid-1",
   115  						},
   116  						AccessPath: "/c",
   117  					},
   118  					LocationMetadata: LocationMetadata{
   119  						Annotations: map[string]string{
   120  							evidence.AnnotationKey: evidence.PrimaryAnnotation,
   121  						},
   122  					},
   123  				},
   124  			},
   125  			coords: []Coordinates{
   126  				{
   127  					RealPath:     "/a",
   128  					FileSystemID: "fsid-1",
   129  				},
   130  				{
   131  					RealPath:     "/b",
   132  					FileSystemID: "fsid-1",
   133  				},
   134  				{
   135  					RealPath:     "/c",
   136  					FileSystemID: "fsid-1",
   137  				},
   138  			},
   139  			wantLocs: []string{
   140  				"/c (/c) @ fsid-1 map[evidence:primary]",
   141  				"/b (/b) @ fsid-1 map[evidence:supporting]",
   142  				"/a (/a) @ fsid-1 map[evidence:]",
   143  			},
   144  			wantCoords: []string{
   145  				"/a @ fsid-1",
   146  				"/b @ fsid-1",
   147  				"/c @ fsid-1",
   148  			},
   149  		},
   150  		{
   151  			name:   "same evidence type, sort by layer",
   152  			layers: []string{"fsid-1", "fsid-2", "fsid-3"},
   153  			locs: []Location{
   154  				{
   155  					LocationData: LocationData{
   156  						Coordinates: Coordinates{
   157  							RealPath:     "/a",
   158  							FileSystemID: "fsid-3",
   159  						},
   160  						AccessPath: "/a",
   161  					},
   162  					LocationMetadata: LocationMetadata{
   163  						Annotations: map[string]string{
   164  							evidence.AnnotationKey: evidence.PrimaryAnnotation,
   165  						},
   166  					},
   167  				},
   168  				{
   169  					LocationData: LocationData{
   170  						Coordinates: Coordinates{
   171  							RealPath:     "/b",
   172  							FileSystemID: "fsid-1",
   173  						},
   174  						AccessPath: "/b",
   175  					},
   176  					LocationMetadata: LocationMetadata{
   177  						Annotations: map[string]string{
   178  							evidence.AnnotationKey: evidence.PrimaryAnnotation,
   179  						},
   180  					},
   181  				},
   182  				{
   183  					LocationData: LocationData{
   184  						Coordinates: Coordinates{
   185  							RealPath:     "/c",
   186  							FileSystemID: "fsid-2",
   187  						},
   188  						AccessPath: "/c",
   189  					},
   190  					LocationMetadata: LocationMetadata{
   191  						Annotations: map[string]string{
   192  							evidence.AnnotationKey: evidence.PrimaryAnnotation,
   193  						},
   194  					},
   195  				},
   196  			},
   197  			coords: []Coordinates{
   198  				{
   199  					RealPath:     "/a",
   200  					FileSystemID: "fsid-3",
   201  				},
   202  				{
   203  					RealPath:     "/b",
   204  					FileSystemID: "fsid-1",
   205  				},
   206  				{
   207  					RealPath:     "/c",
   208  					FileSystemID: "fsid-2",
   209  				},
   210  			},
   211  			wantLocs: []string{
   212  				"/b (/b) @ fsid-1 map[evidence:primary]",
   213  				"/c (/c) @ fsid-2 map[evidence:primary]",
   214  				"/a (/a) @ fsid-3 map[evidence:primary]",
   215  			},
   216  			wantCoords: []string{
   217  				"/b @ fsid-1",
   218  				"/c @ fsid-2",
   219  				"/a @ fsid-3",
   220  			},
   221  		},
   222  		{
   223  			name:   "same evidence and layer, sort by access path",
   224  			layers: []string{"fsid-1"},
   225  			locs: []Location{
   226  				{
   227  					LocationData: LocationData{
   228  						Coordinates: Coordinates{
   229  							RealPath:     "/x",
   230  							FileSystemID: "fsid-1",
   231  						},
   232  						AccessPath: "/c",
   233  					},
   234  					LocationMetadata: LocationMetadata{
   235  						Annotations: map[string]string{
   236  							evidence.AnnotationKey: evidence.PrimaryAnnotation,
   237  						},
   238  					},
   239  				},
   240  				{
   241  					LocationData: LocationData{
   242  						Coordinates: Coordinates{
   243  							RealPath:     "/y",
   244  							FileSystemID: "fsid-1",
   245  						},
   246  						AccessPath: "/a",
   247  					},
   248  					LocationMetadata: LocationMetadata{
   249  						Annotations: map[string]string{
   250  							evidence.AnnotationKey: evidence.PrimaryAnnotation,
   251  						},
   252  					},
   253  				},
   254  				{
   255  					LocationData: LocationData{
   256  						Coordinates: Coordinates{
   257  							RealPath:     "/z",
   258  							FileSystemID: "fsid-1",
   259  						},
   260  						AccessPath: "/b",
   261  					},
   262  					LocationMetadata: LocationMetadata{
   263  						Annotations: map[string]string{
   264  							evidence.AnnotationKey: evidence.PrimaryAnnotation,
   265  						},
   266  					},
   267  				},
   268  			},
   269  			coords: []Coordinates{
   270  				{
   271  					RealPath:     "/x",
   272  					FileSystemID: "fsid-1",
   273  				},
   274  				{
   275  					RealPath:     "/y",
   276  					FileSystemID: "fsid-1",
   277  				},
   278  				{
   279  					RealPath:     "/z",
   280  					FileSystemID: "fsid-1",
   281  				},
   282  			},
   283  			wantLocs: []string{
   284  				"/y (/a) @ fsid-1 map[evidence:primary]",
   285  				"/z (/b) @ fsid-1 map[evidence:primary]",
   286  				"/x (/c) @ fsid-1 map[evidence:primary]",
   287  			},
   288  			wantCoords: []string{
   289  				"/x @ fsid-1",
   290  				"/y @ fsid-1",
   291  				"/z @ fsid-1",
   292  			},
   293  		},
   294  		{
   295  			name:   "same evidence, layer, and access path - sort by real path",
   296  			layers: []string{"fsid-1"},
   297  			locs: []Location{
   298  				{
   299  					LocationData: LocationData{
   300  						Coordinates: Coordinates{
   301  							RealPath:     "/c",
   302  							FileSystemID: "fsid-1",
   303  						},
   304  						AccessPath: "/same",
   305  					},
   306  					LocationMetadata: LocationMetadata{
   307  						Annotations: map[string]string{
   308  							evidence.AnnotationKey: evidence.PrimaryAnnotation,
   309  						},
   310  					},
   311  				},
   312  				{
   313  					LocationData: LocationData{
   314  						Coordinates: Coordinates{
   315  							RealPath:     "/a",
   316  							FileSystemID: "fsid-1",
   317  						},
   318  						AccessPath: "/same",
   319  					},
   320  					LocationMetadata: LocationMetadata{
   321  						Annotations: map[string]string{
   322  							evidence.AnnotationKey: evidence.PrimaryAnnotation,
   323  						},
   324  					},
   325  				},
   326  				{
   327  					LocationData: LocationData{
   328  						Coordinates: Coordinates{
   329  							RealPath:     "/b",
   330  							FileSystemID: "fsid-1",
   331  						},
   332  						AccessPath: "/same",
   333  					},
   334  					LocationMetadata: LocationMetadata{
   335  						Annotations: map[string]string{
   336  							evidence.AnnotationKey: evidence.PrimaryAnnotation,
   337  						},
   338  					},
   339  				},
   340  			},
   341  			coords: []Coordinates{
   342  				{
   343  					RealPath:     "/c",
   344  					FileSystemID: "fsid-1",
   345  				},
   346  				{
   347  					RealPath:     "/a",
   348  					FileSystemID: "fsid-1",
   349  				},
   350  				{
   351  					RealPath:     "/b",
   352  					FileSystemID: "fsid-1",
   353  				},
   354  			},
   355  			wantLocs: []string{
   356  				"/a (/same) @ fsid-1 map[evidence:primary]",
   357  				"/b (/same) @ fsid-1 map[evidence:primary]",
   358  				"/c (/same) @ fsid-1 map[evidence:primary]",
   359  			},
   360  			wantCoords: []string{
   361  				"/a @ fsid-1",
   362  				"/b @ fsid-1",
   363  				"/c @ fsid-1",
   364  			},
   365  		},
   366  		{
   367  			name:   "unknown layers",
   368  			layers: []string{"fsid-1", "fsid-2"},
   369  			locs: []Location{
   370  				{
   371  					LocationData: LocationData{
   372  						Coordinates: Coordinates{
   373  							RealPath:     "/a",
   374  							FileSystemID: "unknown-1",
   375  						},
   376  						AccessPath: "/a",
   377  					},
   378  					LocationMetadata: LocationMetadata{
   379  						Annotations: map[string]string{},
   380  					},
   381  				},
   382  				{
   383  					LocationData: LocationData{
   384  						Coordinates: Coordinates{
   385  							RealPath:     "/b",
   386  							FileSystemID: "unknown-2",
   387  						},
   388  						AccessPath: "/b",
   389  					},
   390  					LocationMetadata: LocationMetadata{
   391  						Annotations: map[string]string{},
   392  					},
   393  				},
   394  			},
   395  			coords: []Coordinates{
   396  				{
   397  					RealPath:     "/a",
   398  					FileSystemID: "unknown-1",
   399  				},
   400  				{
   401  					RealPath:     "/b",
   402  					FileSystemID: "unknown-2",
   403  				},
   404  			},
   405  			wantLocs: []string{
   406  				"/a (/a) @ unknown-1 map[]",
   407  				"/b (/b) @ unknown-2 map[]",
   408  			},
   409  			wantCoords: []string{
   410  				"/a @ unknown-1",
   411  				"/b @ unknown-2",
   412  			},
   413  		},
   414  		{
   415  			name:   "mixed known and unknown layers",
   416  			layers: []string{"fsid-1", "fsid-2"},
   417  			locs: []Location{
   418  				{
   419  					LocationData: LocationData{
   420  						Coordinates: Coordinates{
   421  							RealPath:     "/a",
   422  							FileSystemID: "fsid-1",
   423  						},
   424  						AccessPath: "/a",
   425  					},
   426  					LocationMetadata: LocationMetadata{
   427  						Annotations: map[string]string{},
   428  					},
   429  				},
   430  				{
   431  					LocationData: LocationData{
   432  						Coordinates: Coordinates{
   433  							RealPath:     "/b",
   434  							FileSystemID: "unknown",
   435  						},
   436  						AccessPath: "/b",
   437  					},
   438  					LocationMetadata: LocationMetadata{
   439  						Annotations: map[string]string{},
   440  					},
   441  				},
   442  			},
   443  			coords: []Coordinates{
   444  				{
   445  					RealPath:     "/a",
   446  					FileSystemID: "fsid-1",
   447  				},
   448  				{
   449  					RealPath:     "/b",
   450  					FileSystemID: "unknown",
   451  				},
   452  			},
   453  			wantLocs: []string{
   454  				"/a (/a) @ fsid-1 map[]",
   455  				"/b (/b) @ unknown map[]",
   456  			},
   457  			wantCoords: []string{
   458  				"/a @ fsid-1",
   459  				"/b @ unknown",
   460  			},
   461  		},
   462  		{
   463  			name:   "evidence comparison when one has none",
   464  			layers: []string{"fsid-1"},
   465  			locs: []Location{
   466  				{
   467  					LocationData: LocationData{
   468  						Coordinates: Coordinates{
   469  							RealPath:     "/a",
   470  							FileSystemID: "fsid-1",
   471  						},
   472  						AccessPath: "/a",
   473  					},
   474  					LocationMetadata: LocationMetadata{
   475  						Annotations: map[string]string{
   476  							// No evidence.AnnotationKey
   477  						},
   478  					},
   479  				},
   480  				{
   481  					LocationData: LocationData{
   482  						Coordinates: Coordinates{
   483  							RealPath:     "/b",
   484  							FileSystemID: "fsid-1",
   485  						},
   486  						AccessPath: "/b",
   487  					},
   488  					LocationMetadata: LocationMetadata{
   489  						Annotations: map[string]string{
   490  							evidence.AnnotationKey: evidence.PrimaryAnnotation,
   491  						},
   492  					},
   493  				},
   494  			},
   495  			coords: []Coordinates{
   496  				{
   497  					RealPath:     "/a",
   498  					FileSystemID: "fsid-1",
   499  				},
   500  				{
   501  					RealPath:     "/b",
   502  					FileSystemID: "fsid-1",
   503  				},
   504  			},
   505  			wantLocs: []string{
   506  				"/b (/b) @ fsid-1 map[evidence:primary]",
   507  				"/a (/a) @ fsid-1 map[]",
   508  			},
   509  			wantCoords: []string{
   510  				"/a @ fsid-1",
   511  				"/b @ fsid-1",
   512  			},
   513  		},
   514  	}
   515  
   516  	for _, tt := range tests {
   517  		t.Run(tt.name, func(t *testing.T) {
   518  			t.Run("Location", func(t *testing.T) {
   519  				locs := make([]Location, len(tt.locs))
   520  				copy(locs, tt.locs)
   521  
   522  				slices.SortFunc(locs, LocationSorter(tt.layers))
   523  
   524  				got := make([]string, len(locs))
   525  				for i, loc := range locs {
   526  					got[i] = fmt.Sprintf("%s (%s) @ %s %s",
   527  						loc.RealPath,
   528  						loc.AccessPath,
   529  						loc.FileSystemID,
   530  						loc.LocationMetadata.Annotations)
   531  				}
   532  
   533  				if d := cmp.Diff(tt.wantLocs, got); d != "" {
   534  					t.Errorf("LocationSorter() mismatch (-want +got):\n%s", d)
   535  				}
   536  			})
   537  
   538  			t.Run("Coordinates", func(t *testing.T) {
   539  				coords := make([]Coordinates, len(tt.coords))
   540  				copy(coords, tt.coords)
   541  
   542  				slices.SortFunc(coords, CoordinatesSorter(tt.layers))
   543  
   544  				got := make([]string, len(coords))
   545  				for i, coord := range coords {
   546  					got[i] = fmt.Sprintf("%s @ %s",
   547  						coord.RealPath,
   548  						coord.FileSystemID)
   549  				}
   550  
   551  				if d := cmp.Diff(tt.wantCoords, got); d != "" {
   552  					t.Errorf("CoordinatesSorter() mismatch (-want +got):\n%s", d)
   553  				}
   554  			})
   555  		})
   556  	}
   557  }