github.com/nextlinux/gosbom@v0.81.1-0.20230627115839-1ff50c281391/gosbom/formats/gosbomjson/encoder_test.go (about)

     1  package gosbomjson
     2  
     3  import (
     4  	"flag"
     5  	"regexp"
     6  	"testing"
     7  
     8  	"github.com/nextlinux/gosbom/gosbom/artifact"
     9  	"github.com/nextlinux/gosbom/gosbom/cpe"
    10  	"github.com/nextlinux/gosbom/gosbom/file"
    11  	"github.com/nextlinux/gosbom/gosbom/formats/internal/testutils"
    12  	"github.com/nextlinux/gosbom/gosbom/linux"
    13  	"github.com/nextlinux/gosbom/gosbom/pkg"
    14  	"github.com/nextlinux/gosbom/gosbom/sbom"
    15  	"github.com/nextlinux/gosbom/gosbom/source"
    16  
    17  	stereoFile "github.com/anchore/stereoscope/pkg/file"
    18  )
    19  
    20  var updateJson = flag.Bool("update-json", false, "update the *.golden files for json encoders")
    21  
    22  func TestDirectoryEncoder(t *testing.T) {
    23  	testutils.AssertEncoderAgainstGoldenSnapshot(t,
    24  		Format(),
    25  		testutils.DirectoryInput(t),
    26  		*updateJson,
    27  		true,
    28  		schemaVersionRedactor,
    29  	)
    30  }
    31  
    32  func TestImageEncoder(t *testing.T) {
    33  	testImage := "image-simple"
    34  	testutils.AssertEncoderAgainstGoldenImageSnapshot(t,
    35  		Format(),
    36  		testutils.ImageInput(t, testImage, testutils.FromSnapshot()),
    37  		testImage,
    38  		*updateJson,
    39  		true,
    40  		schemaVersionRedactor,
    41  	)
    42  }
    43  
    44  func schemaVersionRedactor(s []byte) []byte {
    45  	pattern := regexp.MustCompile(`,?\s*"schema":\s*\{[^}]*}`)
    46  	out := pattern.ReplaceAll(s, []byte(""))
    47  	return out
    48  }
    49  
    50  func TestEncodeFullJSONDocument(t *testing.T) {
    51  	catalog := pkg.NewCollection()
    52  
    53  	p1 := pkg.Package{
    54  		Name:    "package-1",
    55  		Version: "1.0.1",
    56  		Locations: file.NewLocationSet(
    57  			file.NewLocationFromCoordinates(file.Coordinates{
    58  				RealPath: "/a/place/a",
    59  			}),
    60  		),
    61  		Type:         pkg.PythonPkg,
    62  		FoundBy:      "the-cataloger-1",
    63  		Language:     pkg.Python,
    64  		MetadataType: pkg.PythonPackageMetadataType,
    65  		Licenses:     pkg.NewLicenseSet(pkg.NewLicense("MIT")),
    66  		Metadata: pkg.PythonPackageMetadata{
    67  			Name:    "package-1",
    68  			Version: "1.0.1",
    69  			Files:   []pkg.PythonFileRecord{},
    70  		},
    71  		PURL: "a-purl-1",
    72  		CPEs: []cpe.CPE{
    73  			cpe.Must("cpe:2.3:*:some:package:1:*:*:*:*:*:*:*"),
    74  		},
    75  	}
    76  
    77  	p2 := pkg.Package{
    78  		Name:    "package-2",
    79  		Version: "2.0.1",
    80  		Locations: file.NewLocationSet(
    81  			file.NewLocationFromCoordinates(file.Coordinates{
    82  				RealPath: "/b/place/b",
    83  			}),
    84  		),
    85  		Type:         pkg.DebPkg,
    86  		FoundBy:      "the-cataloger-2",
    87  		MetadataType: pkg.DpkgMetadataType,
    88  		Metadata: pkg.DpkgMetadata{
    89  			Package: "package-2",
    90  			Version: "2.0.1",
    91  			Files:   []pkg.DpkgFileRecord{},
    92  		},
    93  		PURL: "a-purl-2",
    94  		CPEs: []cpe.CPE{
    95  			cpe.Must("cpe:2.3:*:some:package:2:*:*:*:*:*:*:*"),
    96  		},
    97  	}
    98  
    99  	catalog.Add(p1)
   100  	catalog.Add(p2)
   101  
   102  	s := sbom.SBOM{
   103  		Artifacts: sbom.Artifacts{
   104  			Packages: catalog,
   105  			FileMetadata: map[file.Coordinates]file.Metadata{
   106  				file.NewLocation("/a/place").Coordinates: {
   107  					FileInfo: stereoFile.ManualInfo{
   108  						NameValue: "/a/place",
   109  						ModeValue: 0775,
   110  					},
   111  					Type:    stereoFile.TypeDirectory,
   112  					UserID:  0,
   113  					GroupID: 0,
   114  				},
   115  				file.NewLocation("/a/place/a").Coordinates: {
   116  					FileInfo: stereoFile.ManualInfo{
   117  						NameValue: "/a/place/a",
   118  						ModeValue: 0775,
   119  					},
   120  					Type:    stereoFile.TypeRegular,
   121  					UserID:  0,
   122  					GroupID: 0,
   123  				},
   124  				file.NewLocation("/b").Coordinates: {
   125  					FileInfo: stereoFile.ManualInfo{
   126  						NameValue: "/b",
   127  						ModeValue: 0775,
   128  					},
   129  					Type:            stereoFile.TypeSymLink,
   130  					LinkDestination: "/c",
   131  					UserID:          0,
   132  					GroupID:         0,
   133  				},
   134  				file.NewLocation("/b/place/b").Coordinates: {
   135  					FileInfo: stereoFile.ManualInfo{
   136  						NameValue: "/b/place/b",
   137  						ModeValue: 0644,
   138  					},
   139  					Type:    stereoFile.TypeRegular,
   140  					UserID:  1,
   141  					GroupID: 2,
   142  				},
   143  			},
   144  			FileDigests: map[file.Coordinates][]file.Digest{
   145  				file.NewLocation("/a/place/a").Coordinates: {
   146  					{
   147  						Algorithm: "sha256",
   148  						Value:     "366a3f5653e34673b875891b021647440d0127c2ef041e3b1a22da2a7d4f3703",
   149  					},
   150  				},
   151  				file.NewLocation("/b/place/b").Coordinates: {
   152  					{
   153  						Algorithm: "sha256",
   154  						Value:     "1b3722da2a7d90d033b87581a2a3f12021647445653e34666ef041e3b4f3707c",
   155  					},
   156  				},
   157  			},
   158  			FileContents: map[file.Coordinates]string{
   159  				file.NewLocation("/a/place/a").Coordinates: "the-contents",
   160  			},
   161  			LinuxDistribution: &linux.Release{
   162  				ID:        "redhat",
   163  				Version:   "7",
   164  				VersionID: "7",
   165  				IDLike: []string{
   166  					"rhel",
   167  				},
   168  			},
   169  		},
   170  		Relationships: []artifact.Relationship{
   171  			{
   172  				From: p1,
   173  				To:   p2,
   174  				Type: artifact.OwnershipByFileOverlapRelationship,
   175  				Data: map[string]string{
   176  					"file": "path",
   177  				},
   178  			},
   179  		},
   180  		Source: source.Metadata{
   181  			ID:     "c2b46b4eb06296933b7cf0722683964e9ecbd93265b9ef6ae9642e3952afbba0",
   182  			Scheme: source.ImageScheme,
   183  			ImageMetadata: source.ImageMetadata{
   184  				UserInput:      "user-image-input",
   185  				ID:             "sha256:c2b46b4eb06296933b7cf0722683964e9ecbd93265b9ef6ae9642e3952afbba0",
   186  				ManifestDigest: "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368",
   187  				MediaType:      "application/vnd.docker.distribution.manifest.v2+json",
   188  				Tags: []string{
   189  					"stereoscope-fixture-image-simple:85066c51088bdd274f7a89e99e00490f666c49e72ffc955707cd6e18f0e22c5b",
   190  				},
   191  				Size: 38,
   192  				Layers: []source.LayerMetadata{
   193  					{
   194  						MediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip",
   195  						Digest:    "sha256:3de16c5b8659a2e8d888b8ded8427be7a5686a3c8c4e4dd30de20f362827285b",
   196  						Size:      22,
   197  					},
   198  					{
   199  						MediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip",
   200  						Digest:    "sha256:366a3f5653e34673b875891b021647440d0127c2ef041e3b1a22da2a7d4f3703",
   201  						Size:      16,
   202  					},
   203  				},
   204  				RawManifest: []byte("eyJzY2hlbWFWZXJzaW9uIjoyLCJtZWRpYVR5cGUiOiJh..."),
   205  				RawConfig:   []byte("eyJhcmNoaXRlY3R1cmUiOiJhbWQ2NCIsImNvbmZp..."),
   206  				RepoDigests: []string{},
   207  			},
   208  		},
   209  		Descriptor: sbom.Descriptor{
   210  			Name:    "gosbom",
   211  			Version: "v0.42.0-bogus",
   212  			// the application configuration should be persisted here, however, we do not want to import
   213  			// the application configuration in this package (it's reserved only for ingestion by the cmd package)
   214  			Configuration: map[string]string{
   215  				"config-key": "config-value",
   216  			},
   217  		},
   218  	}
   219  
   220  	testutils.AssertEncoderAgainstGoldenSnapshot(t,
   221  		Format(),
   222  		s,
   223  		*updateJson,
   224  		true,
   225  		schemaVersionRedactor,
   226  	)
   227  }