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 }