github.com/lineaje-labs/syft@v0.98.1-0.20231227153149-9e393f60ff1b/syft/format/common/cyclonedxhelpers/format_test.go (about)

     1  package cyclonedxhelpers
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/CycloneDX/cyclonedx-go"
     8  	"github.com/google/go-cmp/cmp"
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/require"
    11  
    12  	"github.com/anchore/syft/syft/artifact"
    13  	"github.com/anchore/syft/syft/pkg"
    14  	"github.com/anchore/syft/syft/sbom"
    15  	"github.com/anchore/syft/syft/source"
    16  )
    17  
    18  func Test_formatCPE(t *testing.T) {
    19  	tests := []struct {
    20  		cpe      string
    21  		expected string
    22  	}{
    23  		{
    24  			cpe:      "cpe:2.3:o:amazon:amazon_linux:2",
    25  			expected: "cpe:2.3:o:amazon:amazon_linux:2:*:*:*:*:*:*:*",
    26  		},
    27  		{
    28  			cpe:      "cpe:/o:opensuse:leap:15.2",
    29  			expected: "cpe:2.3:o:opensuse:leap:15.2:*:*:*:*:*:*:*",
    30  		},
    31  		{
    32  			cpe:      "invalid-cpe",
    33  			expected: "",
    34  		},
    35  	}
    36  
    37  	for _, test := range tests {
    38  		t.Run(test.cpe, func(t *testing.T) {
    39  			out := formatCPE(test.cpe)
    40  			assert.Equal(t, test.expected, out)
    41  		})
    42  	}
    43  }
    44  
    45  func Test_relationships(t *testing.T) {
    46  	p1 := pkg.Package{
    47  		Name: "p1",
    48  	}
    49  
    50  	p2 := pkg.Package{
    51  		Name: "p2",
    52  	}
    53  
    54  	p3 := pkg.Package{
    55  		Name: "p3",
    56  	}
    57  
    58  	p4 := pkg.Package{
    59  		Name: "p4",
    60  	}
    61  
    62  	for _, p := range []*pkg.Package{&p1, &p2, &p3, &p4} {
    63  		p.PURL = fmt.Sprintf("pkg:generic/%s@%s", p.Name, p.Name)
    64  		p.SetID()
    65  	}
    66  
    67  	tests := []struct {
    68  		name     string
    69  		sbom     sbom.SBOM
    70  		expected *[]cyclonedx.Dependency
    71  	}{
    72  		{
    73  			name: "package dependencyOf relationships output as dependencies",
    74  			sbom: sbom.SBOM{
    75  				Artifacts: sbom.Artifacts{
    76  					Packages: pkg.NewCollection(p1, p2, p3, p4),
    77  				},
    78  				Relationships: []artifact.Relationship{
    79  					{
    80  						From: p2,
    81  						To:   p1,
    82  						Type: artifact.DependencyOfRelationship,
    83  					},
    84  					{
    85  						From: p3,
    86  						To:   p1,
    87  						Type: artifact.DependencyOfRelationship,
    88  					},
    89  					{
    90  						From: p4,
    91  						To:   p2,
    92  						Type: artifact.DependencyOfRelationship,
    93  					},
    94  				},
    95  			},
    96  			expected: &[]cyclonedx.Dependency{
    97  				{
    98  					Ref: deriveBomRef(p1),
    99  					Dependencies: &[]string{
   100  						deriveBomRef(p2),
   101  						deriveBomRef(p3),
   102  					},
   103  				},
   104  				{
   105  					Ref: deriveBomRef(p2),
   106  					Dependencies: &[]string{
   107  						deriveBomRef(p4),
   108  					},
   109  				},
   110  			},
   111  		},
   112  		{
   113  			name: "package contains relationships not output",
   114  			sbom: sbom.SBOM{
   115  				Artifacts: sbom.Artifacts{
   116  					Packages: pkg.NewCollection(p1, p2, p3),
   117  				},
   118  				Relationships: []artifact.Relationship{
   119  					{
   120  						From: p2,
   121  						To:   p1,
   122  						Type: artifact.ContainsRelationship,
   123  					},
   124  					{
   125  						From: p3,
   126  						To:   p1,
   127  						Type: artifact.ContainsRelationship,
   128  					},
   129  				},
   130  			},
   131  			expected: nil,
   132  		},
   133  	}
   134  
   135  	for _, test := range tests {
   136  		t.Run(test.name, func(t *testing.T) {
   137  			cdx := ToFormatModel(test.sbom)
   138  			got := cdx.Dependencies
   139  			require.Equal(t, test.expected, got)
   140  		})
   141  	}
   142  }
   143  
   144  func Test_toBomDescriptor(t *testing.T) {
   145  	type args struct {
   146  		name        string
   147  		version     string
   148  		srcMetadata source.Description
   149  	}
   150  	tests := []struct {
   151  		name string
   152  		args args
   153  		want *cyclonedx.Metadata
   154  	}{
   155  		{
   156  			name: "with image labels source metadata",
   157  			args: args{
   158  				name:    "test-image",
   159  				version: "1.0.0",
   160  				srcMetadata: source.Description{
   161  					Metadata: source.StereoscopeImageSourceMetadata{
   162  						Labels: map[string]string{
   163  							"key1": "value1",
   164  						},
   165  					},
   166  				},
   167  			},
   168  			want: &cyclonedx.Metadata{
   169  				Timestamp:  "",
   170  				Lifecycles: nil,
   171  				Tools: &[]cyclonedx.Tool{
   172  					{
   173  						Vendor:             "anchore",
   174  						Name:               "test-image",
   175  						Version:            "1.0.0",
   176  						Hashes:             nil,
   177  						ExternalReferences: nil,
   178  					},
   179  				},
   180  				Authors: nil,
   181  				Component: &cyclonedx.Component{
   182  					BOMRef:             "",
   183  					MIMEType:           "",
   184  					Type:               "container",
   185  					Supplier:           nil,
   186  					Author:             "",
   187  					Publisher:          "",
   188  					Group:              "",
   189  					Name:               "",
   190  					Version:            "",
   191  					Description:        "",
   192  					Scope:              "",
   193  					Hashes:             nil,
   194  					Licenses:           nil,
   195  					Copyright:          "",
   196  					CPE:                "",
   197  					PackageURL:         "",
   198  					SWID:               nil,
   199  					Modified:           nil,
   200  					Pedigree:           nil,
   201  					ExternalReferences: nil,
   202  					Properties:         nil,
   203  					Components:         nil,
   204  					Evidence:           nil,
   205  					ReleaseNotes:       nil,
   206  				},
   207  				Manufacture: nil,
   208  				Supplier:    nil,
   209  				Licenses:    nil,
   210  				Properties: &[]cyclonedx.Property{
   211  					{
   212  						Name:  "syft:image:labels:key1",
   213  						Value: "value1",
   214  					},
   215  				}},
   216  		},
   217  	}
   218  	for _, tt := range tests {
   219  		t.Run(tt.name, func(t *testing.T) {
   220  			subject := toBomDescriptor(tt.args.name, tt.args.version, tt.args.srcMetadata)
   221  
   222  			require.NotEmpty(t, subject.Component.BOMRef)
   223  			subject.Timestamp = "" // not under test
   224  
   225  			require.NotNil(t, subject.Component)
   226  			require.NotEmpty(t, subject.Component.BOMRef)
   227  			subject.Component.BOMRef = "" // not under test
   228  
   229  			if d := cmp.Diff(tt.want, subject); d != "" {
   230  				t.Errorf("toBomDescriptor() mismatch (-want +got):\n%s", d)
   231  			}
   232  		})
   233  	}
   234  }