github.com/anchore/syft@v1.38.2/syft/format/syftjson/model/source_test.go (about)

     1  package model
     2  
     3  import (
     4  	"encoding/json"
     5  	"testing"
     6  
     7  	"github.com/google/go-cmp/cmp"
     8  	"github.com/stretchr/testify/assert"
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"github.com/anchore/syft/internal/sourcemetadata"
    12  	"github.com/anchore/syft/syft/file"
    13  	"github.com/anchore/syft/syft/source"
    14  )
    15  
    16  func TestSource_UnmarshalJSON(t *testing.T) {
    17  	tracker := sourcemetadata.NewCompletionTester(t)
    18  
    19  	cases := []struct {
    20  		name     string
    21  		input    []byte
    22  		expected *Source
    23  		wantErr  require.ErrorAssertionFunc
    24  	}{
    25  		{
    26  			name: "empty",
    27  			input: []byte(`{
    28  				"id": "",
    29  				"type": "",
    30  				"metadata": null
    31  			}`),
    32  			expected: &Source{},
    33  		},
    34  		{
    35  			name: "directory",
    36  			input: []byte(`{
    37  				"id": "foobar",
    38  				"type": "directory",
    39  				"metadata": {"path": "/var/lib/foo", "base":"/nope"}
    40  			}`),
    41  			expected: &Source{
    42  				ID:   "foobar",
    43  				Type: "directory",
    44  				Metadata: source.DirectoryMetadata{
    45  					Path: "/var/lib/foo",
    46  					//Base: "/nope", // note: should be ignored entirely
    47  				},
    48  			},
    49  		},
    50  		{
    51  			name: "image",
    52  			input: []byte(`{
    53  				"id": "foobar",
    54  				"type": "image",
    55  				"metadata": {
    56  					"userInput": "alpine:3.10",
    57  					"imageID": "sha256:e7b300aee9f9bf3433d32bc9305bfdd22183beb59d933b48d77ab56ba53a197a",
    58  					"manifestDigest": "sha256:e515aad2ed234a5072c4d2ef86a1cb77d5bfe4b11aa865d9214875734c4eeb3c",
    59  					"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    60  					"tags": [],
    61  					"imageSize": 5576169,
    62  					"layers": [
    63  						{
    64  							"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
    65  							"digest": "sha256:9fb3aa2f8b8023a4bebbf92aa567caf88e38e969ada9f0ac12643b2847391635",
    66  							"size": 5576169
    67  						}
    68  					],
    69  					"manifest": "ewogICAic2NoZW1hVmVyc2lvbiI6IDIsCiAgICJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLmRvY2tlci5kaXN0cmlidXRpb24ubWFuaWZlc3QudjIranNvbiIsCiAgICJjb25maWciOiB7CiAgICAgICJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLmRvY2tlci5jb250YWluZXIuaW1hZ2UudjEranNvbiIsCiAgICAgICJzaXplIjogMTQ3MiwKICAgICAgImRpZ2VzdCI6ICJzaGEyNTY6ZTdiMzAwYWVlOWY5YmYzNDMzZDMyYmM5MzA1YmZkZDIyMTgzYmViNTlkOTMzYjQ4ZDc3YWI1NmJhNTNhMTk3YSIKICAgfSwKICAgImxheWVycyI6IFsKICAgICAgewogICAgICAgICAibWVkaWFUeXBlIjogImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuaW1hZ2Uucm9vdGZzLmRpZmYudGFyLmd6aXAiLAogICAgICAgICAic2l6ZSI6IDI3OTgzMzgsCiAgICAgICAgICJkaWdlc3QiOiAic2hhMjU2OjM5NmMzMTgzNzExNmFjMjkwNDU4YWZjYjkyOGY2OGI2Y2MxYzdiZGQ2OTYzZmM3MmY1MmYzNjVhMmE4OWMxYjUiCiAgICAgIH0KICAgXQp9",
    70  					"config": "eyJhcmNoaXRlY3R1cmUiOiJhbWQ2NCIsImNvbmZpZyI6eyJIb3N0bmFtZSI6IiIsIkRvbWFpbm5hbWUiOiIiLCJVc2VyIjoiIiwiQXR0YWNoU3RkaW4iOmZhbHNlLCJBdHRhY2hTdGRvdXQiOmZhbHNlLCJBdHRhY2hTdGRlcnIiOmZhbHNlLCJUdHkiOmZhbHNlLCJPcGVuU3RkaW4iOmZhbHNlLCJTdGRpbk9uY2UiOmZhbHNlLCJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiQ21kIjpbIi9iaW4vc2giXSwiSW1hZ2UiOiJzaGEyNTY6ZWIyMDgwYzQ1NWU5NGMyMmFlMzViM2FlZjllMDc4YzQ5MmEwMDc5NTQxMmUwMjZlNGQ2YjQxZWY2NGJjN2RkOCIsIlZvbHVtZXMiOm51bGwsIldvcmtpbmdEaXIiOiIiLCJFbnRyeXBvaW50IjpudWxsLCJPbkJ1aWxkIjpudWxsLCJMYWJlbHMiOm51bGx9LCJjb250YWluZXIiOiJmZGI3ZTgwZTMzMzllOGQwNTk5MjgyZTYwNmM5MDdhYTU4ODFlZTRjNjY4YTY4MTM2MTE5ZTZkZmFjNmNlM2E0IiwiY29udGFpbmVyX2NvbmZpZyI6eyJIb3N0bmFtZSI6ImZkYjdlODBlMzMzOSIsIkRvbWFpbm5hbWUiOiIiLCJVc2VyIjoiIiwiQXR0YWNoU3RkaW4iOmZhbHNlLCJBdHRhY2hTdGRvdXQiOmZhbHNlLCJBdHRhY2hTdGRlcnIiOmZhbHNlLCJUdHkiOmZhbHNlLCJPcGVuU3RkaW4iOmZhbHNlLCJTdGRpbk9uY2UiOmZhbHNlLCJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiQ21kIjpbIi9iaW4vc2giLCItYyIsIiMobm9wKSAiLCJDTUQgW1wiL2Jpbi9zaFwiXSJdLCJJbWFnZSI6InNoYTI1NjplYjIwODBjNDU1ZTk0YzIyYWUzNWIzYWVmOWUwNzhjNDkyYTAwNzk1NDEyZTAyNmU0ZDZiNDFlZjY0YmM3ZGQ4IiwiVm9sdW1lcyI6bnVsbCwiV29ya2luZ0RpciI6IiIsIkVudHJ5cG9pbnQiOm51bGwsIk9uQnVpbGQiOm51bGwsIkxhYmVscyI6e319LCJjcmVhdGVkIjoiMjAyMS0wNC0xNFQxOToyMDowNS4zMzgzOTc3NjFaIiwiZG9ja2VyX3ZlcnNpb24iOiIxOS4wMy4xMiIsImhpc3RvcnkiOlt7ImNyZWF0ZWQiOiIyMDIxLTA0LTE0VDE5OjIwOjA0Ljk4NzIxOTEyNFoiLCJjcmVhdGVkX2J5IjoiL2Jpbi9zaCAtYyAjKG5vcCkgQUREIGZpbGU6YzUzNzdlYWE5MjZiZjQxMmRkOGQ0YTA4YjBhMWYyMzk5Y2ZkNzA4NzQzNTMzYjBhYTAzYjUzZDE0Y2I0YmI0ZSBpbiAvICJ9LHsiY3JlYXRlZCI6IjIwMjEtMDQtMTRUMTk6MjA6MDUuMzM4Mzk3NzYxWiIsImNyZWF0ZWRfYnkiOiIvYmluL3NoIC1jICMobm9wKSAgQ01EIFtcIi9iaW4vc2hcIl0iLCJlbXB0eV9sYXllciI6dHJ1ZX1dLCJvcyI6ImxpbnV4Iiwicm9vdGZzIjp7InR5cGUiOiJsYXllcnMiLCJkaWZmX2lkcyI6WyJzaGEyNTY6OWZiM2FhMmY4YjgwMjNhNGJlYmJmOTJhYTU2N2NhZjg4ZTM4ZTk2OWFkYTlmMGFjMTI2NDNiMjg0NzM5MTYzNSJdfX0=",
    71  					"repoDigests": [
    72  						"index.docker.io/library/alpine@sha256:451eee8bedcb2f029756dc3e9d73bab0e7943c1ac55cff3a4861c52a0fdd3e98"
    73  					]
    74  				}
    75  			}`),
    76  			expected: &Source{
    77  				ID:   "foobar",
    78  				Type: "image",
    79  				Metadata: source.ImageMetadata{
    80  					UserInput:      "alpine:3.10",
    81  					ID:             "sha256:e7b300aee9f9bf3433d32bc9305bfdd22183beb59d933b48d77ab56ba53a197a",
    82  					ManifestDigest: "sha256:e515aad2ed234a5072c4d2ef86a1cb77d5bfe4b11aa865d9214875734c4eeb3c",
    83  					MediaType:      "application/vnd.docker.distribution.manifest.v2+json",
    84  					Tags:           []string{},
    85  					Size:           5576169,
    86  					Layers: []source.LayerMetadata{
    87  						{
    88  							MediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip",
    89  							Digest:    "sha256:9fb3aa2f8b8023a4bebbf92aa567caf88e38e969ada9f0ac12643b2847391635",
    90  							Size:      5576169,
    91  						},
    92  					},
    93  					RawManifest: []byte(`{
    94     "schemaVersion": 2,
    95     "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    96     "config": {
    97        "mediaType": "application/vnd.docker.container.image.v1+json",
    98        "size": 1472,
    99        "digest": "sha256:e7b300aee9f9bf3433d32bc9305bfdd22183beb59d933b48d77ab56ba53a197a"
   100     },
   101     "layers": [
   102        {
   103           "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
   104           "size": 2798338,
   105           "digest": "sha256:396c31837116ac290458afcb928f68b6cc1c7bdd6963fc72f52f365a2a89c1b5"
   106        }
   107     ]
   108  }`),
   109  					RawConfig: []byte(`{"architecture":"amd64","config":{"Hostname":"","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/sh"],"Image":"sha256:eb2080c455e94c22ae35b3aef9e078c492a00795412e026e4d6b41ef64bc7dd8","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"container":"fdb7e80e3339e8d0599282e606c907aa5881ee4c668a68136119e6dfac6ce3a4","container_config":{"Hostname":"fdb7e80e3339","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/sh","-c","#(nop) ","CMD [\"/bin/sh\"]"],"Image":"sha256:eb2080c455e94c22ae35b3aef9e078c492a00795412e026e4d6b41ef64bc7dd8","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":{}},"created":"2021-04-14T19:20:05.338397761Z","docker_version":"19.03.12","history":[{"created":"2021-04-14T19:20:04.987219124Z","created_by":"/bin/sh -c #(nop) ADD file:c5377eaa926bf412dd8d4a08b0a1f2399cfd708743533b0aa03b53d14cb4bb4e in / "},{"created":"2021-04-14T19:20:05.338397761Z","created_by":"/bin/sh -c #(nop)  CMD [\"/bin/sh\"]","empty_layer":true}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:9fb3aa2f8b8023a4bebbf92aa567caf88e38e969ada9f0ac12643b2847391635"]}}`),
   110  					RepoDigests: []string{
   111  						"index.docker." +
   112  							"io/library/alpine@sha256:451eee8bedcb2f029756dc3e9d73bab0e7943c1ac55cff3a4861c52a0fdd3e98",
   113  					},
   114  				},
   115  			},
   116  		},
   117  		{
   118  			name: "file",
   119  			input: []byte(`{
   120  				"id": "foobar",
   121  				"type": "file",
   122  				"metadata": {
   123  					"path": "/var/lib/foo/go.mod",
   124  					"mimeType": "text/plain",
   125  					"digests": [
   126  						{
   127  							"algorithm": "sha256",
   128  							"value": 	 "e7b300aee9f9bf3433d32bc9305bfdd22183beb59d933b48d77ab56ba53a197a"
   129  						}
   130  					]
   131  				}
   132  			}`),
   133  			expected: &Source{
   134  				ID:   "foobar",
   135  				Type: "file",
   136  				Metadata: source.FileMetadata{
   137  					Path: "/var/lib/foo/go.mod",
   138  					Digests: []file.Digest{
   139  						{
   140  							Algorithm: "sha256",
   141  							Value:     "e7b300aee9f9bf3433d32bc9305bfdd22183beb59d933b48d77ab56ba53a197a",
   142  						},
   143  					},
   144  					MIMEType: "text/plain",
   145  				},
   146  			},
   147  		},
   148  		{
   149  			name: "snap",
   150  			input: []byte(`{
   151    "id": "foobar",
   152    "name": "etcd",
   153    "version": "3.4.36",
   154    "type": "snap",
   155    "metadata": {
   156      "summary": "Distributed reliable key-value store",
   157      "base": "core18",
   158      "grade": "stable",
   159      "confinement": "strict",
   160      "architectures": [
   161        "amd64"
   162      ],
   163      "digests": [
   164        {
   165          "algorithm": "sha256",
   166          "value": "6700d789d2c38b0f7513058ddcea8f9a275e2206b4621a772eb065e12069956e"
   167        }
   168      ]
   169    }
   170  }`),
   171  			expected: &Source{
   172  				ID:      "foobar",
   173  				Name:    "etcd",
   174  				Version: "3.4.36",
   175  				Type:    "snap",
   176  				Metadata: source.SnapMetadata{
   177  					Summary:     "Distributed reliable key-value store",
   178  					Base:        "core18",
   179  					Grade:       "stable",
   180  					Confinement: "strict",
   181  					Architectures: []string{
   182  						"amd64",
   183  					},
   184  					Digests: []file.Digest{
   185  						{
   186  							Algorithm: "sha256",
   187  							Value:     "6700d789d2c38b0f7513058ddcea8f9a275e2206b4621a772eb065e12069956e",
   188  						},
   189  					},
   190  				},
   191  			},
   192  		},
   193  		{
   194  			name: "unknown source type",
   195  			input: []byte(`{
   196  				"id": "foobar",
   197  				"type": "unknown-thing",
   198  				"target":"/var/lib/foo"
   199  			}`),
   200  			expected: &Source{
   201  				ID:   "foobar",
   202  				Type: "unknown-thing",
   203  			},
   204  			wantErr: require.Error,
   205  		},
   206  	}
   207  
   208  	for _, tt := range cases {
   209  		t.Run(tt.name, func(t *testing.T) {
   210  			if tt.wantErr == nil {
   211  				tt.wantErr = require.NoError
   212  			}
   213  
   214  			var src Source
   215  			err := json.Unmarshal(tt.input, &src)
   216  
   217  			tt.wantErr(t, err)
   218  
   219  			if diff := cmp.Diff(tt.expected, &src); diff != "" {
   220  				t.Errorf("unexpected result from Source unmarshaling (-want +got)\n%s", diff)
   221  			}
   222  
   223  			tracker.Tested(t, tt.expected.Metadata)
   224  		})
   225  	}
   226  }
   227  
   228  func TestSource_UnmarshalJSON_PreSchemaV9(t *testing.T) {
   229  	cases := []struct {
   230  		name           string
   231  		input          []byte
   232  		expectedSource *Source
   233  		errAssertion   assert.ErrorAssertionFunc
   234  	}{
   235  		{
   236  			name: "abbreviated directory",
   237  			input: []byte(`{
   238  				"id": "foobar",
   239  				"type": "dir",
   240  				"target":"/var/lib/foo"
   241  			}`),
   242  			expectedSource: &Source{
   243  				ID:   "foobar",
   244  				Type: "directory",
   245  				Metadata: source.DirectoryMetadata{
   246  					Path: "/var/lib/foo",
   247  				},
   248  			},
   249  			errAssertion: assert.NoError,
   250  		},
   251  		{
   252  			name: "directory",
   253  			input: []byte(`{
   254  				"id": "foobar",
   255  				"type": "directory",
   256  				"target":"/var/lib/foo"
   257  			}`),
   258  			expectedSource: &Source{
   259  				ID:   "foobar",
   260  				Type: "directory",
   261  				Metadata: source.DirectoryMetadata{
   262  					Path: "/var/lib/foo",
   263  				},
   264  			},
   265  			errAssertion: assert.NoError,
   266  		},
   267  		{
   268  			name: "image",
   269  			input: []byte(`{
   270  				"id": "foobar",
   271  				"type": "image",
   272  				"target": {
   273  					"userInput": "alpine:3.10",
   274  					"imageID": "sha256:e7b300aee9f9bf3433d32bc9305bfdd22183beb59d933b48d77ab56ba53a197a",
   275  					"manifestDigest": "sha256:e515aad2ed234a5072c4d2ef86a1cb77d5bfe4b11aa865d9214875734c4eeb3c",
   276  					"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
   277  					"tags": [],
   278  					"imageSize": 5576169,
   279  					"layers": [
   280  						{
   281  							"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
   282  							"digest": "sha256:9fb3aa2f8b8023a4bebbf92aa567caf88e38e969ada9f0ac12643b2847391635",
   283  							"size": 5576169
   284  						}
   285  					],
   286  					"manifest": "ewogICAic2NoZW1hVmVyc2lvbiI6IDIsCiAgICJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLmRvY2tlci5kaXN0cmlidXRpb24ubWFuaWZlc3QudjIranNvbiIsCiAgICJjb25maWciOiB7CiAgICAgICJtZWRpYVR5cGUiOiAiYXBwbGljYXRpb24vdm5kLmRvY2tlci5jb250YWluZXIuaW1hZ2UudjEranNvbiIsCiAgICAgICJzaXplIjogMTQ3MiwKICAgICAgImRpZ2VzdCI6ICJzaGEyNTY6ZTdiMzAwYWVlOWY5YmYzNDMzZDMyYmM5MzA1YmZkZDIyMTgzYmViNTlkOTMzYjQ4ZDc3YWI1NmJhNTNhMTk3YSIKICAgfSwKICAgImxheWVycyI6IFsKICAgICAgewogICAgICAgICAibWVkaWFUeXBlIjogImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuaW1hZ2Uucm9vdGZzLmRpZmYudGFyLmd6aXAiLAogICAgICAgICAic2l6ZSI6IDI3OTgzMzgsCiAgICAgICAgICJkaWdlc3QiOiAic2hhMjU2OjM5NmMzMTgzNzExNmFjMjkwNDU4YWZjYjkyOGY2OGI2Y2MxYzdiZGQ2OTYzZmM3MmY1MmYzNjVhMmE4OWMxYjUiCiAgICAgIH0KICAgXQp9",
   287  					"config": "eyJhcmNoaXRlY3R1cmUiOiJhbWQ2NCIsImNvbmZpZyI6eyJIb3N0bmFtZSI6IiIsIkRvbWFpbm5hbWUiOiIiLCJVc2VyIjoiIiwiQXR0YWNoU3RkaW4iOmZhbHNlLCJBdHRhY2hTdGRvdXQiOmZhbHNlLCJBdHRhY2hTdGRlcnIiOmZhbHNlLCJUdHkiOmZhbHNlLCJPcGVuU3RkaW4iOmZhbHNlLCJTdGRpbk9uY2UiOmZhbHNlLCJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiQ21kIjpbIi9iaW4vc2giXSwiSW1hZ2UiOiJzaGEyNTY6ZWIyMDgwYzQ1NWU5NGMyMmFlMzViM2FlZjllMDc4YzQ5MmEwMDc5NTQxMmUwMjZlNGQ2YjQxZWY2NGJjN2RkOCIsIlZvbHVtZXMiOm51bGwsIldvcmtpbmdEaXIiOiIiLCJFbnRyeXBvaW50IjpudWxsLCJPbkJ1aWxkIjpudWxsLCJMYWJlbHMiOm51bGx9LCJjb250YWluZXIiOiJmZGI3ZTgwZTMzMzllOGQwNTk5MjgyZTYwNmM5MDdhYTU4ODFlZTRjNjY4YTY4MTM2MTE5ZTZkZmFjNmNlM2E0IiwiY29udGFpbmVyX2NvbmZpZyI6eyJIb3N0bmFtZSI6ImZkYjdlODBlMzMzOSIsIkRvbWFpbm5hbWUiOiIiLCJVc2VyIjoiIiwiQXR0YWNoU3RkaW4iOmZhbHNlLCJBdHRhY2hTdGRvdXQiOmZhbHNlLCJBdHRhY2hTdGRlcnIiOmZhbHNlLCJUdHkiOmZhbHNlLCJPcGVuU3RkaW4iOmZhbHNlLCJTdGRpbk9uY2UiOmZhbHNlLCJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiQ21kIjpbIi9iaW4vc2giLCItYyIsIiMobm9wKSAiLCJDTUQgW1wiL2Jpbi9zaFwiXSJdLCJJbWFnZSI6InNoYTI1NjplYjIwODBjNDU1ZTk0YzIyYWUzNWIzYWVmOWUwNzhjNDkyYTAwNzk1NDEyZTAyNmU0ZDZiNDFlZjY0YmM3ZGQ4IiwiVm9sdW1lcyI6bnVsbCwiV29ya2luZ0RpciI6IiIsIkVudHJ5cG9pbnQiOm51bGwsIk9uQnVpbGQiOm51bGwsIkxhYmVscyI6e319LCJjcmVhdGVkIjoiMjAyMS0wNC0xNFQxOToyMDowNS4zMzgzOTc3NjFaIiwiZG9ja2VyX3ZlcnNpb24iOiIxOS4wMy4xMiIsImhpc3RvcnkiOlt7ImNyZWF0ZWQiOiIyMDIxLTA0LTE0VDE5OjIwOjA0Ljk4NzIxOTEyNFoiLCJjcmVhdGVkX2J5IjoiL2Jpbi9zaCAtYyAjKG5vcCkgQUREIGZpbGU6YzUzNzdlYWE5MjZiZjQxMmRkOGQ0YTA4YjBhMWYyMzk5Y2ZkNzA4NzQzNTMzYjBhYTAzYjUzZDE0Y2I0YmI0ZSBpbiAvICJ9LHsiY3JlYXRlZCI6IjIwMjEtMDQtMTRUMTk6MjA6MDUuMzM4Mzk3NzYxWiIsImNyZWF0ZWRfYnkiOiIvYmluL3NoIC1jICMobm9wKSAgQ01EIFtcIi9iaW4vc2hcIl0iLCJlbXB0eV9sYXllciI6dHJ1ZX1dLCJvcyI6ImxpbnV4Iiwicm9vdGZzIjp7InR5cGUiOiJsYXllcnMiLCJkaWZmX2lkcyI6WyJzaGEyNTY6OWZiM2FhMmY4YjgwMjNhNGJlYmJmOTJhYTU2N2NhZjg4ZTM4ZTk2OWFkYTlmMGFjMTI2NDNiMjg0NzM5MTYzNSJdfX0=",
   288  					"repoDigests": [
   289  						"index.docker.io/library/alpine@sha256:451eee8bedcb2f029756dc3e9d73bab0e7943c1ac55cff3a4861c52a0fdd3e98"
   290  					]
   291  				}
   292  			}`),
   293  			expectedSource: &Source{
   294  				ID:   "foobar",
   295  				Type: "image",
   296  				Metadata: source.ImageMetadata{
   297  					UserInput:      "alpine:3.10",
   298  					ID:             "sha256:e7b300aee9f9bf3433d32bc9305bfdd22183beb59d933b48d77ab56ba53a197a",
   299  					ManifestDigest: "sha256:e515aad2ed234a5072c4d2ef86a1cb77d5bfe4b11aa865d9214875734c4eeb3c",
   300  					MediaType:      "application/vnd.docker.distribution.manifest.v2+json",
   301  					Tags:           []string{},
   302  					Size:           5576169,
   303  					Layers: []source.LayerMetadata{
   304  						{
   305  							MediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip",
   306  							Digest:    "sha256:9fb3aa2f8b8023a4bebbf92aa567caf88e38e969ada9f0ac12643b2847391635",
   307  							Size:      5576169,
   308  						},
   309  					},
   310  					RawManifest: []byte(`{
   311     "schemaVersion": 2,
   312     "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
   313     "config": {
   314        "mediaType": "application/vnd.docker.container.image.v1+json",
   315        "size": 1472,
   316        "digest": "sha256:e7b300aee9f9bf3433d32bc9305bfdd22183beb59d933b48d77ab56ba53a197a"
   317     },
   318     "layers": [
   319        {
   320           "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
   321           "size": 2798338,
   322           "digest": "sha256:396c31837116ac290458afcb928f68b6cc1c7bdd6963fc72f52f365a2a89c1b5"
   323        }
   324     ]
   325  }`),
   326  					RawConfig: []byte(`{"architecture":"amd64","config":{"Hostname":"","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/sh"],"Image":"sha256:eb2080c455e94c22ae35b3aef9e078c492a00795412e026e4d6b41ef64bc7dd8","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":null},"container":"fdb7e80e3339e8d0599282e606c907aa5881ee4c668a68136119e6dfac6ce3a4","container_config":{"Hostname":"fdb7e80e3339","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"Tty":false,"OpenStdin":false,"StdinOnce":false,"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/bin/sh","-c","#(nop) ","CMD [\"/bin/sh\"]"],"Image":"sha256:eb2080c455e94c22ae35b3aef9e078c492a00795412e026e4d6b41ef64bc7dd8","Volumes":null,"WorkingDir":"","Entrypoint":null,"OnBuild":null,"Labels":{}},"created":"2021-04-14T19:20:05.338397761Z","docker_version":"19.03.12","history":[{"created":"2021-04-14T19:20:04.987219124Z","created_by":"/bin/sh -c #(nop) ADD file:c5377eaa926bf412dd8d4a08b0a1f2399cfd708743533b0aa03b53d14cb4bb4e in / "},{"created":"2021-04-14T19:20:05.338397761Z","created_by":"/bin/sh -c #(nop)  CMD [\"/bin/sh\"]","empty_layer":true}],"os":"linux","rootfs":{"type":"layers","diff_ids":["sha256:9fb3aa2f8b8023a4bebbf92aa567caf88e38e969ada9f0ac12643b2847391635"]}}`),
   327  					RepoDigests: []string{
   328  						"index.docker." +
   329  							"io/library/alpine@sha256:451eee8bedcb2f029756dc3e9d73bab0e7943c1ac55cff3a4861c52a0fdd3e98",
   330  					},
   331  				},
   332  			},
   333  			errAssertion: assert.NoError,
   334  		},
   335  		{
   336  			name: "file",
   337  			input: []byte(`{
   338  				"id": "foobar",
   339  				"type": "file",
   340  				"target":"/var/lib/foo/go.mod"
   341  			}`),
   342  			expectedSource: &Source{
   343  				ID:   "foobar",
   344  				Type: "file",
   345  				Metadata: source.FileMetadata{
   346  					Path: "/var/lib/foo/go.mod",
   347  				},
   348  			},
   349  			errAssertion: assert.NoError,
   350  		},
   351  		{
   352  			name: "unknown source type",
   353  			input: []byte(`{
   354  				"id": "foobar",
   355  				"type": "unknown-thing",
   356  				"target":"/var/lib/foo"
   357  			}`),
   358  			expectedSource: &Source{
   359  				ID:   "foobar",
   360  				Type: "unknown-thing",
   361  			},
   362  			errAssertion: assert.Error,
   363  		},
   364  	}
   365  
   366  	for _, testCase := range cases {
   367  		t.Run(testCase.name, func(t *testing.T) {
   368  			src := new(Source)
   369  
   370  			err := json.Unmarshal(testCase.input, src)
   371  
   372  			testCase.errAssertion(t, err)
   373  			if diff := cmp.Diff(testCase.expectedSource, src); diff != "" {
   374  				t.Errorf("unexpected result from Source unmarshaling (-want +got)\n%s", diff)
   375  			}
   376  		})
   377  	}
   378  }