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 }