github.com/lineaje-labs/syft@v0.98.1-0.20231227153149-9e393f60ff1b/syft/pkg/cataloger/alpine/package_test.go (about)

     1  package alpine
     2  
     3  import (
     4  	"strings"
     5  	"testing"
     6  
     7  	"github.com/go-test/deep"
     8  	"github.com/sergi/go-diff/diffmatchpatch"
     9  
    10  	"github.com/anchore/packageurl-go"
    11  	"github.com/anchore/syft/syft/linux"
    12  	"github.com/anchore/syft/syft/pkg"
    13  )
    14  
    15  func Test_PackageURL(t *testing.T) {
    16  	tests := []struct {
    17  		name     string
    18  		metadata parsedData
    19  		distro   linux.Release
    20  		expected string
    21  	}{
    22  		{
    23  			name: "non-alpine distro",
    24  			metadata: parsedData{
    25  				License: "",
    26  				ApkDBEntry: pkg.ApkDBEntry{
    27  					Package:      "p",
    28  					Version:      "v",
    29  					Architecture: "a",
    30  				},
    31  			},
    32  			distro: linux.Release{
    33  				ID:        "something else",
    34  				VersionID: "3.4.6",
    35  			},
    36  			expected: "pkg:apk/something%20else/p@v?arch=a&distro=something%20else-3.4.6",
    37  		},
    38  		{
    39  			name: "gocase",
    40  			metadata: parsedData{
    41  				License: "",
    42  				ApkDBEntry: pkg.ApkDBEntry{
    43  					Package:      "p",
    44  					Version:      "v",
    45  					Architecture: "a",
    46  				},
    47  			},
    48  			distro: linux.Release{
    49  				ID:        "alpine",
    50  				VersionID: "3.4.6",
    51  			},
    52  			expected: "pkg:apk/alpine/p@v?arch=a&distro=alpine-3.4.6",
    53  		},
    54  		{
    55  			name: "missing architecture",
    56  			metadata: parsedData{
    57  				License: "",
    58  				ApkDBEntry: pkg.ApkDBEntry{
    59  					Package: "p",
    60  					Version: "v",
    61  				},
    62  			},
    63  			distro: linux.Release{
    64  				ID:        "alpine",
    65  				VersionID: "3.4.6",
    66  			},
    67  			expected: "pkg:apk/alpine/p@v?distro=alpine-3.4.6",
    68  		},
    69  		// verify #351
    70  		{
    71  			metadata: parsedData{
    72  				License: "",
    73  				ApkDBEntry: pkg.ApkDBEntry{
    74  					Package:      "g++",
    75  					Version:      "v84",
    76  					Architecture: "am86",
    77  				},
    78  			},
    79  			distro: linux.Release{
    80  				ID:        "alpine",
    81  				VersionID: "3.4.6",
    82  			},
    83  			expected: "pkg:apk/alpine/g++@v84?arch=am86&distro=alpine-3.4.6",
    84  		},
    85  		{
    86  			metadata: parsedData{
    87  				License: "",
    88  				ApkDBEntry: pkg.ApkDBEntry{
    89  					Package:      "g plus plus",
    90  					Version:      "v84",
    91  					Architecture: "am86",
    92  				},
    93  			},
    94  			distro: linux.Release{
    95  				ID:        "alpine",
    96  				VersionID: "3.15.0",
    97  			},
    98  			expected: "pkg:apk/alpine/g%20plus%20plus@v84?arch=am86&distro=alpine-3.15.0",
    99  		},
   100  		{
   101  			name: "add source information as qualifier",
   102  			metadata: parsedData{
   103  				License: "",
   104  				ApkDBEntry: pkg.ApkDBEntry{
   105  					Package:       "p",
   106  					Version:       "v",
   107  					Architecture:  "a",
   108  					OriginPackage: "origin",
   109  				},
   110  			},
   111  			distro: linux.Release{
   112  				ID:        "alpine",
   113  				VersionID: "3.4.6",
   114  			},
   115  			expected: "pkg:apk/alpine/p@v?arch=a&upstream=origin&distro=alpine-3.4.6",
   116  		},
   117  		{
   118  			name: "wolfi distro",
   119  			metadata: parsedData{
   120  				License: "",
   121  				ApkDBEntry: pkg.ApkDBEntry{
   122  					Package:      "p",
   123  					Version:      "v",
   124  					Architecture: "a",
   125  				},
   126  			},
   127  			distro: linux.Release{
   128  				ID:        "wolfi",
   129  				VersionID: "20221230",
   130  			},
   131  			expected: "pkg:apk/wolfi/p@v?arch=a&distro=wolfi-20221230",
   132  		},
   133  	}
   134  
   135  	for _, test := range tests {
   136  		t.Run(test.name, func(t *testing.T) {
   137  			actual := packageURL(test.metadata.ApkDBEntry, &test.distro)
   138  			if actual != test.expected {
   139  				dmp := diffmatchpatch.New()
   140  				diffs := dmp.DiffMain(test.expected, actual, true)
   141  				t.Errorf("diff: %s", dmp.DiffPrettyText(diffs))
   142  			}
   143  
   144  			if test.expected == "" {
   145  				return
   146  			}
   147  
   148  			// verify packageurl can parse
   149  			purl, err := packageurl.FromString(actual)
   150  			if err != nil {
   151  				t.Errorf("cannot re-parse purl: %s", actual)
   152  			}
   153  			if purl.Name != test.metadata.Package {
   154  				dmp := diffmatchpatch.New()
   155  				diffs := dmp.DiffMain(test.metadata.Package, purl.Name, true)
   156  				t.Errorf("invalid purl name: %s", dmp.DiffPrettyText(diffs))
   157  			}
   158  			if purl.Version != test.metadata.Version {
   159  				dmp := diffmatchpatch.New()
   160  				diffs := dmp.DiffMain(test.metadata.Version, purl.Version, true)
   161  				t.Errorf("invalid purl version: %s", dmp.DiffPrettyText(diffs))
   162  			}
   163  			if purl.Qualifiers.Map()["arch"] != test.metadata.Architecture {
   164  				dmp := diffmatchpatch.New()
   165  				diffs := dmp.DiffMain(test.metadata.Architecture, purl.Qualifiers.Map()["arch"], true)
   166  				t.Errorf("invalid purl architecture: %s", dmp.DiffPrettyText(diffs))
   167  			}
   168  		})
   169  	}
   170  }
   171  
   172  func TestApkMetadata_FileOwner(t *testing.T) {
   173  	tests := []struct {
   174  		metadata pkg.ApkDBEntry
   175  		expected []string
   176  	}{
   177  		{
   178  			metadata: pkg.ApkDBEntry{
   179  				Files: []pkg.ApkFileRecord{
   180  					{Path: "/somewhere"},
   181  					{Path: "/else"},
   182  				},
   183  			},
   184  			expected: []string{
   185  				"/else",
   186  				"/somewhere",
   187  			},
   188  		},
   189  		{
   190  			metadata: pkg.ApkDBEntry{
   191  				Files: []pkg.ApkFileRecord{
   192  					{Path: "/somewhere"},
   193  					{Path: ""},
   194  				},
   195  			},
   196  			expected: []string{
   197  				"/somewhere",
   198  			},
   199  		},
   200  	}
   201  
   202  	for _, test := range tests {
   203  		t.Run(strings.Join(test.expected, ","), func(t *testing.T) {
   204  			actual := test.metadata.OwnedFiles()
   205  			for _, d := range deep.Equal(test.expected, actual) {
   206  				t.Errorf("diff: %+v", d)
   207  			}
   208  		})
   209  	}
   210  }