github.com/dtroyer-salad/og2/v2@v2.0.0-20240412154159-c47231610877/pack_test.go (about) 1 /* 2 Copyright The ORAS Authors. 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 */ 15 16 package oras 17 18 import ( 19 "bytes" 20 "context" 21 "encoding/json" 22 "errors" 23 "io" 24 "reflect" 25 "testing" 26 "time" 27 28 "github.com/opencontainers/go-digest" 29 specs "github.com/opencontainers/image-spec/specs-go" 30 ocispec "github.com/opencontainers/image-spec/specs-go/v1" 31 "oras.land/oras-go/v2/content" 32 "oras.land/oras-go/v2/content/memory" 33 "oras.land/oras-go/v2/errdef" 34 "oras.land/oras-go/v2/internal/spec" 35 ) 36 37 func Test_Pack_Artifact_NoOption(t *testing.T) { 38 s := memory.New() 39 40 // prepare test content 41 blobs := []ocispec.Descriptor{ 42 content.NewDescriptorFromBytes("test", []byte("hello world")), 43 content.NewDescriptorFromBytes("test", []byte("goodbye world")), 44 } 45 artifactType := "application/vnd.test" 46 47 // test Pack 48 ctx := context.Background() 49 manifestDesc, err := Pack(ctx, s, artifactType, blobs, PackOptions{}) 50 if err != nil { 51 t.Fatal("Oras.Pack() error =", err) 52 } 53 54 // verify blobs 55 var manifest spec.Artifact 56 rc, err := s.Fetch(ctx, manifestDesc) 57 if err != nil { 58 t.Fatal("Store.Fetch() error =", err) 59 } 60 if err := json.NewDecoder(rc).Decode(&manifest); err != nil { 61 t.Fatal("error decoding manifest, error =", err) 62 } 63 if err := rc.Close(); err != nil { 64 t.Fatal("Store.Fetch().Close() error =", err) 65 } 66 if !reflect.DeepEqual(manifest.Blobs, blobs) { 67 t.Errorf("Store.Fetch() = %v, want %v", manifest.Blobs, blobs) 68 } 69 70 // verify media type 71 if got := manifest.MediaType; got != spec.MediaTypeArtifactManifest { 72 t.Fatalf("got media type = %s, want %s", got, spec.MediaTypeArtifactManifest) 73 } 74 75 // verify artifact type 76 if got := manifest.ArtifactType; got != artifactType { 77 t.Fatalf("got artifact type = %s, want %s", got, artifactType) 78 } 79 80 // verify created time annotation 81 createdTime, ok := manifest.Annotations[spec.AnnotationArtifactCreated] 82 if !ok { 83 t.Errorf("Annotation %s = %v, want %v", spec.AnnotationArtifactCreated, ok, true) 84 } 85 _, err = time.Parse(time.RFC3339, createdTime) 86 if err != nil { 87 t.Errorf("error parsing created time: %s, error = %v", createdTime, err) 88 } 89 90 // verify descriptor artifact type 91 if want := manifest.ArtifactType; !reflect.DeepEqual(manifestDesc.ArtifactType, want) { 92 t.Errorf("got descriptor artifactType = %v, want %v", manifestDesc.ArtifactType, want) 93 } 94 95 // verify descriptor annotations 96 if want := manifest.Annotations; !reflect.DeepEqual(manifestDesc.Annotations, want) { 97 t.Errorf("got descriptor annotations = %v, want %v", manifestDesc.Annotations, want) 98 } 99 } 100 101 func Test_Pack_Artifact_WithOptions(t *testing.T) { 102 s := memory.New() 103 104 // prepare test content 105 blobs := []ocispec.Descriptor{ 106 content.NewDescriptorFromBytes("test", []byte("hello world")), 107 content.NewDescriptorFromBytes("test", []byte("goodbye world")), 108 } 109 110 artifactType := "application/vnd.test" 111 annotations := map[string]string{ 112 spec.AnnotationArtifactCreated: "2000-01-01T00:00:00Z", 113 "foo": "bar", 114 } 115 subjectManifest := []byte(`{"layers":[]}`) 116 subjectDesc := ocispec.Descriptor{ 117 MediaType: ocispec.MediaTypeImageManifest, 118 Digest: digest.FromBytes(subjectManifest), 119 Size: int64(len(subjectManifest)), 120 ArtifactType: artifactType, 121 Annotations: annotations, 122 } 123 configBytes := []byte("{}") 124 configDesc := content.NewDescriptorFromBytes("application/vnd.test.config", configBytes) 125 configAnnotations := map[string]string{"foo": "bar"} 126 127 // test Pack 128 ctx := context.Background() 129 opts := PackOptions{ 130 Subject: &subjectDesc, 131 ManifestAnnotations: annotations, 132 ConfigDescriptor: &configDesc, // should not work 133 ConfigAnnotations: configAnnotations, // should not work 134 } 135 manifestDesc, err := Pack(ctx, s, artifactType, blobs, opts) 136 if err != nil { 137 t.Fatal("Oras.Pack() error =", err) 138 } 139 140 expectedManifest := spec.Artifact{ 141 MediaType: spec.MediaTypeArtifactManifest, 142 ArtifactType: artifactType, 143 Blobs: blobs, 144 Subject: opts.Subject, 145 Annotations: annotations, 146 } 147 expectedManifestBytes, err := json.Marshal(expectedManifest) 148 if err != nil { 149 t.Fatal("failed to marshal manifest:", err) 150 } 151 152 // verify manifest 153 rc, err := s.Fetch(ctx, manifestDesc) 154 if err != nil { 155 t.Fatal("Store.Fetch() error =", err) 156 } 157 got, err := io.ReadAll(rc) 158 if err != nil { 159 t.Fatal("Store.Fetch().Read() error =", err) 160 } 161 err = rc.Close() 162 if err != nil { 163 t.Error("Store.Fetch().Close() error =", err) 164 } 165 if !bytes.Equal(got, expectedManifestBytes) { 166 t.Errorf("Store.Fetch() = %v, want %v", got, expectedManifestBytes) 167 } 168 169 // verify descriptor 170 expectedManifestDesc := content.NewDescriptorFromBytes(expectedManifest.MediaType, expectedManifestBytes) 171 expectedManifestDesc.ArtifactType = expectedManifest.ArtifactType 172 expectedManifestDesc.Annotations = expectedManifest.Annotations 173 if !reflect.DeepEqual(manifestDesc, expectedManifestDesc) { 174 t.Errorf("Pack() = %v, want %v", manifestDesc, expectedManifestDesc) 175 } 176 } 177 178 func Test_Pack_Artifact_NoBlob(t *testing.T) { 179 s := memory.New() 180 181 // test Pack 182 ctx := context.Background() 183 artifactType := "application/vnd.test" 184 manifestDesc, err := Pack(ctx, s, artifactType, nil, PackOptions{}) 185 if err != nil { 186 t.Fatal("Oras.Pack() error =", err) 187 } 188 189 var manifest spec.Artifact 190 rc, err := s.Fetch(ctx, manifestDesc) 191 if err != nil { 192 t.Fatal("Store.Fetch() error =", err) 193 } 194 if err := json.NewDecoder(rc).Decode(&manifest); err != nil { 195 t.Fatal("error decoding manifest, error =", err) 196 } 197 if err := rc.Close(); err != nil { 198 t.Fatal("Store.Fetch().Close() error =", err) 199 } 200 201 // verify blobs 202 var expectedBlobs []ocispec.Descriptor 203 if !reflect.DeepEqual(manifest.Blobs, expectedBlobs) { 204 t.Errorf("Store.Fetch() = %v, want %v", manifest.Blobs, expectedBlobs) 205 } 206 } 207 208 func Test_Pack_Artifact_NoArtifactType(t *testing.T) { 209 s := memory.New() 210 211 ctx := context.Background() 212 manifestDesc, err := Pack(ctx, s, "", nil, PackOptions{}) 213 if err != nil { 214 t.Fatal("Oras.Pack() error =", err) 215 } 216 217 var manifest spec.Artifact 218 rc, err := s.Fetch(ctx, manifestDesc) 219 if err != nil { 220 t.Fatal("Store.Fetch() error =", err) 221 } 222 if err := json.NewDecoder(rc).Decode(&manifest); err != nil { 223 t.Fatal("error decoding manifest, error =", err) 224 } 225 if err := rc.Close(); err != nil { 226 t.Fatal("Store.Fetch().Close() error =", err) 227 } 228 229 // verify artifact type 230 if manifestDesc.ArtifactType != MediaTypeUnknownArtifact { 231 t.Fatalf("got artifact type = %s, want %s", manifestDesc.ArtifactType, MediaTypeUnknownArtifact) 232 } 233 if manifest.ArtifactType != MediaTypeUnknownArtifact { 234 t.Fatalf("got artifact type = %s, want %s", manifest.ArtifactType, MediaTypeUnknownArtifact) 235 } 236 } 237 238 func Test_Pack_Artifact_InvalidDateTimeFormat(t *testing.T) { 239 s := memory.New() 240 241 ctx := context.Background() 242 opts := PackOptions{ 243 ManifestAnnotations: map[string]string{ 244 spec.AnnotationArtifactCreated: "2000/01/01 00:00:00", 245 }, 246 } 247 artifactType := "application/vnd.test" 248 _, err := Pack(ctx, s, artifactType, nil, opts) 249 if wantErr := ErrInvalidDateTimeFormat; !errors.Is(err, wantErr) { 250 t.Errorf("Oras.Pack() error = %v, wantErr = %v", err, wantErr) 251 } 252 } 253 254 func Test_Pack_ImageV1_1_RC2(t *testing.T) { 255 s := memory.New() 256 257 // prepare test content 258 layers := []ocispec.Descriptor{ 259 content.NewDescriptorFromBytes("test", []byte("hello world")), 260 content.NewDescriptorFromBytes("test", []byte("goodbye world")), 261 } 262 263 // test Pack 264 ctx := context.Background() 265 artifactType := "application/vnd.test" 266 manifestDesc, err := Pack(ctx, s, artifactType, layers, PackOptions{PackImageManifest: true}) 267 if err != nil { 268 t.Fatal("Oras.Pack() error =", err) 269 } 270 271 var manifest ocispec.Manifest 272 rc, err := s.Fetch(ctx, manifestDesc) 273 if err != nil { 274 t.Fatal("Store.Fetch() error =", err) 275 } 276 if err := json.NewDecoder(rc).Decode(&manifest); err != nil { 277 t.Fatal("error decoding manifest, error =", err) 278 } 279 if err := rc.Close(); err != nil { 280 t.Fatal("Store.Fetch().Close() error =", err) 281 } 282 283 // verify media type 284 got := manifest.MediaType 285 if got != ocispec.MediaTypeImageManifest { 286 t.Fatalf("got media type = %s, want %s", got, ocispec.MediaTypeImageManifest) 287 } 288 289 // verify config 290 expectedConfigBytes := []byte("{}") 291 expectedConfig := ocispec.Descriptor{ 292 MediaType: artifactType, 293 Digest: digest.FromBytes(expectedConfigBytes), 294 Size: int64(len(expectedConfigBytes)), 295 } 296 if !reflect.DeepEqual(manifest.Config, expectedConfig) { 297 t.Errorf("got config = %v, want %v", manifest.Config, expectedConfig) 298 } 299 300 // verify layers 301 if !reflect.DeepEqual(manifest.Layers, layers) { 302 t.Errorf("got layers = %v, want %v", manifest.Layers, layers) 303 } 304 305 // verify created time annotation 306 createdTime, ok := manifest.Annotations[ocispec.AnnotationCreated] 307 if !ok { 308 t.Errorf("Annotation %s = %v, want %v", ocispec.AnnotationCreated, ok, true) 309 } 310 _, err = time.Parse(time.RFC3339, createdTime) 311 if err != nil { 312 t.Errorf("error parsing created time: %s, error = %v", createdTime, err) 313 } 314 315 // verify descriptor annotations 316 if want := manifest.Annotations; !reflect.DeepEqual(manifestDesc.Annotations, want) { 317 t.Errorf("got descriptor annotations = %v, want %v", manifestDesc.Annotations, want) 318 } 319 } 320 321 func Test_Pack_ImageV1_1_RC2_WithOptions(t *testing.T) { 322 s := memory.New() 323 324 // prepare test content 325 layers := []ocispec.Descriptor{ 326 content.NewDescriptorFromBytes("test", []byte("hello world")), 327 content.NewDescriptorFromBytes("test", []byte("goodbye world")), 328 } 329 configBytes := []byte("{}") 330 configDesc := content.NewDescriptorFromBytes("application/vnd.test.config", configBytes) 331 configAnnotations := map[string]string{"foo": "bar"} 332 annotations := map[string]string{ 333 ocispec.AnnotationCreated: "2000-01-01T00:00:00Z", 334 "foo": "bar", 335 } 336 artifactType := "application/vnd.test" 337 subjectManifest := []byte(`{"layers":[]}`) 338 subjectDesc := ocispec.Descriptor{ 339 MediaType: ocispec.MediaTypeImageManifest, 340 Digest: digest.FromBytes(subjectManifest), 341 Size: int64(len(subjectManifest)), 342 } 343 344 // test Pack with ConfigDescriptor 345 ctx := context.Background() 346 opts := PackOptions{ 347 PackImageManifest: true, 348 Subject: &subjectDesc, 349 ConfigDescriptor: &configDesc, 350 ConfigAnnotations: configAnnotations, 351 ManifestAnnotations: annotations, 352 } 353 manifestDesc, err := Pack(ctx, s, artifactType, layers, opts) 354 if err != nil { 355 t.Fatal("Oras.Pack() error =", err) 356 } 357 358 expectedManifest := ocispec.Manifest{ 359 Versioned: specs.Versioned{ 360 SchemaVersion: 2, // historical value. does not pertain to OCI or docker version 361 }, 362 MediaType: ocispec.MediaTypeImageManifest, 363 Subject: &subjectDesc, 364 Config: configDesc, 365 Layers: layers, 366 Annotations: annotations, 367 } 368 expectedManifestBytes, err := json.Marshal(expectedManifest) 369 if err != nil { 370 t.Fatal("failed to marshal manifest:", err) 371 } 372 373 rc, err := s.Fetch(ctx, manifestDesc) 374 if err != nil { 375 t.Fatal("Store.Fetch() error =", err) 376 } 377 got, err := io.ReadAll(rc) 378 if err != nil { 379 t.Fatal("Store.Fetch().Read() error =", err) 380 } 381 err = rc.Close() 382 if err != nil { 383 t.Error("Store.Fetch().Close() error =", err) 384 } 385 if !bytes.Equal(got, expectedManifestBytes) { 386 t.Errorf("Store.Fetch() = %v, want %v", string(got), string(expectedManifestBytes)) 387 } 388 389 // verify descriptor 390 expectedManifestDesc := content.NewDescriptorFromBytes(expectedManifest.MediaType, expectedManifestBytes) 391 expectedManifestDesc.ArtifactType = expectedManifest.Config.MediaType 392 expectedManifestDesc.Annotations = expectedManifest.Annotations 393 if !reflect.DeepEqual(manifestDesc, expectedManifestDesc) { 394 t.Errorf("Pack() = %v, want %v", manifestDesc, expectedManifestDesc) 395 } 396 397 // test Pack without ConfigDescriptor 398 opts = PackOptions{ 399 PackImageManifest: true, 400 Subject: &subjectDesc, 401 ConfigAnnotations: configAnnotations, 402 ManifestAnnotations: annotations, 403 } 404 manifestDesc, err = Pack(ctx, s, artifactType, layers, opts) 405 if err != nil { 406 t.Fatal("Oras.Pack() error =", err) 407 } 408 409 expectedConfigDesc := content.NewDescriptorFromBytes(artifactType, configBytes) 410 expectedConfigDesc.Annotations = configAnnotations 411 expectedManifest = ocispec.Manifest{ 412 Versioned: specs.Versioned{ 413 SchemaVersion: 2, // historical value. does not pertain to OCI or docker version 414 }, 415 MediaType: ocispec.MediaTypeImageManifest, 416 Subject: &subjectDesc, 417 Config: expectedConfigDesc, 418 Layers: layers, 419 Annotations: annotations, 420 } 421 expectedManifestBytes, err = json.Marshal(expectedManifest) 422 if err != nil { 423 t.Fatal("failed to marshal manifest:", err) 424 } 425 426 rc, err = s.Fetch(ctx, manifestDesc) 427 if err != nil { 428 t.Fatal("Store.Fetch() error =", err) 429 } 430 got, err = io.ReadAll(rc) 431 if err != nil { 432 t.Fatal("Store.Fetch().Read() error =", err) 433 } 434 err = rc.Close() 435 if err != nil { 436 t.Error("Store.Fetch().Close() error =", err) 437 } 438 if !bytes.Equal(got, expectedManifestBytes) { 439 t.Errorf("Store.Fetch() = %v, want %v", string(got), string(expectedManifestBytes)) 440 } 441 442 // verify descriptor 443 expectedManifestDesc = content.NewDescriptorFromBytes(expectedManifest.MediaType, expectedManifestBytes) 444 expectedManifestDesc.ArtifactType = expectedManifest.Config.MediaType 445 expectedManifestDesc.Annotations = expectedManifest.Annotations 446 if !reflect.DeepEqual(manifestDesc, expectedManifestDesc) { 447 t.Errorf("Pack() = %v, want %v", manifestDesc, expectedManifestDesc) 448 } 449 } 450 451 func Test_Pack_ImageV1_1_RC2_NoArtifactType(t *testing.T) { 452 s := memory.New() 453 454 ctx := context.Background() 455 manifestDesc, err := Pack(ctx, s, "", nil, PackOptions{PackImageManifest: true}) 456 if err != nil { 457 t.Fatal("Oras.Pack() error =", err) 458 } 459 460 var manifest ocispec.Manifest 461 rc, err := s.Fetch(ctx, manifestDesc) 462 if err != nil { 463 t.Fatal("Store.Fetch() error =", err) 464 } 465 if err := json.NewDecoder(rc).Decode(&manifest); err != nil { 466 t.Fatal("error decoding manifest, error =", err) 467 } 468 if err := rc.Close(); err != nil { 469 t.Fatal("Store.Fetch().Close() error =", err) 470 } 471 472 // verify artifact type and config media type 473 if manifestDesc.ArtifactType != MediaTypeUnknownConfig { 474 t.Fatalf("got artifact type = %s, want %s", manifestDesc.ArtifactType, MediaTypeUnknownConfig) 475 } 476 if manifest.Config.MediaType != MediaTypeUnknownConfig { 477 t.Fatalf("got artifact type = %s, want %s", manifest.Config.MediaType, MediaTypeUnknownConfig) 478 } 479 } 480 481 func Test_Pack_ImageV1_1_RC2_NoLayer(t *testing.T) { 482 s := memory.New() 483 484 // test Pack 485 ctx := context.Background() 486 manifestDesc, err := Pack(ctx, s, "", nil, PackOptions{PackImageManifest: true}) 487 if err != nil { 488 t.Fatal("Oras.Pack() error =", err) 489 } 490 491 var manifest ocispec.Manifest 492 rc, err := s.Fetch(ctx, manifestDesc) 493 if err != nil { 494 t.Fatal("Store.Fetch() error =", err) 495 } 496 if err := json.NewDecoder(rc).Decode(&manifest); err != nil { 497 t.Fatal("error decoding manifest, error =", err) 498 } 499 if err := rc.Close(); err != nil { 500 t.Fatal("Store.Fetch().Close() error =", err) 501 } 502 503 // verify layers 504 expectedLayers := []ocispec.Descriptor{} 505 if !reflect.DeepEqual(manifest.Layers, expectedLayers) { 506 t.Errorf("got layers = %v, want %v", manifest.Layers, expectedLayers) 507 } 508 } 509 510 func Test_Pack_ImageV1_1_RC2_InvalidDateTimeFormat(t *testing.T) { 511 s := memory.New() 512 513 ctx := context.Background() 514 opts := PackOptions{ 515 PackImageManifest: true, 516 ManifestAnnotations: map[string]string{ 517 ocispec.AnnotationCreated: "2000/01/01 00:00:00", 518 }, 519 } 520 _, err := Pack(ctx, s, "", nil, opts) 521 if wantErr := ErrInvalidDateTimeFormat; !errors.Is(err, wantErr) { 522 t.Errorf("Oras.Pack() error = %v, wantErr = %v", err, wantErr) 523 } 524 } 525 526 func Test_PackManifest_ImageV1_0(t *testing.T) { 527 s := memory.New() 528 529 // test Pack 530 ctx := context.Background() 531 artifactType := "application/vnd.test" 532 manifestDesc, err := PackManifest(ctx, s, PackManifestVersion1_0, artifactType, PackManifestOptions{}) 533 if err != nil { 534 t.Fatal("Oras.PackManifest() error =", err) 535 } 536 537 var manifest ocispec.Manifest 538 rc, err := s.Fetch(ctx, manifestDesc) 539 if err != nil { 540 t.Fatal("Store.Fetch() error =", err) 541 } 542 if err := json.NewDecoder(rc).Decode(&manifest); err != nil { 543 t.Fatal("error decoding manifest, error =", err) 544 } 545 if err := rc.Close(); err != nil { 546 t.Fatal("Store.Fetch().Close() error =", err) 547 } 548 549 // verify media type 550 got := manifest.MediaType 551 if got != ocispec.MediaTypeImageManifest { 552 t.Fatalf("got media type = %s, want %s", got, ocispec.MediaTypeImageManifest) 553 } 554 555 // verify config 556 expectedConfigBytes := []byte("{}") 557 expectedConfig := ocispec.Descriptor{ 558 MediaType: artifactType, 559 Digest: digest.FromBytes(expectedConfigBytes), 560 Size: int64(len(expectedConfigBytes)), 561 } 562 if !reflect.DeepEqual(manifest.Config, expectedConfig) { 563 t.Errorf("got config = %v, want %v", manifest.Config, expectedConfig) 564 } 565 566 // verify layers 567 expectedLayers := []ocispec.Descriptor{} 568 if !reflect.DeepEqual(manifest.Layers, expectedLayers) { 569 t.Errorf("got layers = %v, want %v", manifest.Layers, expectedLayers) 570 } 571 572 // verify created time annotation 573 createdTime, ok := manifest.Annotations[ocispec.AnnotationCreated] 574 if !ok { 575 t.Errorf("Annotation %s = %v, want %v", ocispec.AnnotationCreated, ok, true) 576 } 577 _, err = time.Parse(time.RFC3339, createdTime) 578 if err != nil { 579 t.Errorf("error parsing created time: %s, error = %v", createdTime, err) 580 } 581 582 // verify descriptor annotations 583 if want := manifest.Annotations; !reflect.DeepEqual(manifestDesc.Annotations, want) { 584 t.Errorf("got descriptor annotations = %v, want %v", manifestDesc.Annotations, want) 585 } 586 } 587 588 func Test_PackManifest_ImageV1_0_WithOptions(t *testing.T) { 589 s := memory.New() 590 591 // prepare test content 592 layers := []ocispec.Descriptor{ 593 content.NewDescriptorFromBytes("test", []byte("hello world")), 594 content.NewDescriptorFromBytes("test", []byte("goodbye world")), 595 } 596 configBytes := []byte("{}") 597 configDesc := content.NewDescriptorFromBytes("application/vnd.test.config", configBytes) 598 configAnnotations := map[string]string{"foo": "bar"} 599 annotations := map[string]string{ 600 ocispec.AnnotationCreated: "2000-01-01T00:00:00Z", 601 "foo": "bar", 602 } 603 artifactType := "application/vnd.test" 604 605 // test PackManifest with ConfigDescriptor 606 ctx := context.Background() 607 opts := PackManifestOptions{ 608 Layers: layers, 609 ConfigDescriptor: &configDesc, 610 ConfigAnnotations: configAnnotations, 611 ManifestAnnotations: annotations, 612 } 613 manifestDesc, err := PackManifest(ctx, s, PackManifestVersion1_0, artifactType, opts) 614 if err != nil { 615 t.Fatal("Oras.PackManifest() error =", err) 616 } 617 618 expectedManifest := ocispec.Manifest{ 619 Versioned: specs.Versioned{ 620 SchemaVersion: 2, // historical value. does not pertain to OCI or docker version 621 }, 622 MediaType: ocispec.MediaTypeImageManifest, 623 Config: configDesc, 624 Layers: layers, 625 Annotations: annotations, 626 } 627 expectedManifestBytes, err := json.Marshal(expectedManifest) 628 if err != nil { 629 t.Fatal("failed to marshal manifest:", err) 630 } 631 632 rc, err := s.Fetch(ctx, manifestDesc) 633 if err != nil { 634 t.Fatal("Store.Fetch() error =", err) 635 } 636 got, err := io.ReadAll(rc) 637 if err != nil { 638 t.Fatal("Store.Fetch().Read() error =", err) 639 } 640 err = rc.Close() 641 if err != nil { 642 t.Error("Store.Fetch().Close() error =", err) 643 } 644 if !bytes.Equal(got, expectedManifestBytes) { 645 t.Errorf("Store.Fetch() = %v, want %v", string(got), string(expectedManifestBytes)) 646 } 647 648 // verify descriptor 649 expectedManifestDesc := content.NewDescriptorFromBytes(expectedManifest.MediaType, expectedManifestBytes) 650 expectedManifestDesc.ArtifactType = expectedManifest.Config.MediaType 651 expectedManifestDesc.Annotations = expectedManifest.Annotations 652 if !reflect.DeepEqual(manifestDesc, expectedManifestDesc) { 653 t.Errorf("Pack() = %v, want %v", manifestDesc, expectedManifestDesc) 654 } 655 656 // test PackManifest without ConfigDescriptor 657 opts = PackManifestOptions{ 658 Layers: layers, 659 ConfigAnnotations: configAnnotations, 660 ManifestAnnotations: annotations, 661 } 662 manifestDesc, err = PackManifest(ctx, s, PackManifestVersion1_0, artifactType, opts) 663 if err != nil { 664 t.Fatal("Oras.PackManifest() error =", err) 665 } 666 667 expectedConfigDesc := content.NewDescriptorFromBytes(artifactType, configBytes) 668 expectedConfigDesc.Annotations = configAnnotations 669 expectedManifest = ocispec.Manifest{ 670 Versioned: specs.Versioned{ 671 SchemaVersion: 2, // historical value. does not pertain to OCI or docker version 672 }, 673 MediaType: ocispec.MediaTypeImageManifest, 674 Config: expectedConfigDesc, 675 Layers: layers, 676 Annotations: annotations, 677 } 678 expectedManifestBytes, err = json.Marshal(expectedManifest) 679 if err != nil { 680 t.Fatal("failed to marshal manifest:", err) 681 } 682 683 rc, err = s.Fetch(ctx, manifestDesc) 684 if err != nil { 685 t.Fatal("Store.Fetch() error =", err) 686 } 687 got, err = io.ReadAll(rc) 688 if err != nil { 689 t.Fatal("Store.Fetch().Read() error =", err) 690 } 691 err = rc.Close() 692 if err != nil { 693 t.Error("Store.Fetch().Close() error =", err) 694 } 695 if !bytes.Equal(got, expectedManifestBytes) { 696 t.Errorf("Store.Fetch() = %v, want %v", string(got), string(expectedManifestBytes)) 697 } 698 699 // verify descriptor 700 expectedManifestDesc = content.NewDescriptorFromBytes(expectedManifest.MediaType, expectedManifestBytes) 701 expectedManifestDesc.ArtifactType = expectedManifest.Config.MediaType 702 expectedManifestDesc.Annotations = expectedManifest.Annotations 703 if !reflect.DeepEqual(manifestDesc, expectedManifestDesc) { 704 t.Errorf("PackManifest() = %v, want %v", manifestDesc, expectedManifestDesc) 705 } 706 } 707 708 func Test_PackManifest_ImageV1_0_SubjectUnsupported(t *testing.T) { 709 s := memory.New() 710 711 // prepare test content 712 artifactType := "application/vnd.test" 713 subjectManifest := []byte(`{"layers":[]}`) 714 subjectDesc := ocispec.Descriptor{ 715 MediaType: ocispec.MediaTypeImageManifest, 716 Digest: digest.FromBytes(subjectManifest), 717 Size: int64(len(subjectManifest)), 718 } 719 720 // test Pack with ConfigDescriptor 721 ctx := context.Background() 722 opts := PackManifestOptions{ 723 Subject: &subjectDesc, 724 } 725 _, err := PackManifest(ctx, s, PackManifestVersion1_0, artifactType, opts) 726 if wantErr := errdef.ErrUnsupported; !errors.Is(err, wantErr) { 727 t.Errorf("Oras.PackManifest() error = %v, wantErr %v", err, wantErr) 728 } 729 } 730 731 func Test_PackManifest_ImageV1_0_NoArtifactType(t *testing.T) { 732 s := memory.New() 733 734 ctx := context.Background() 735 manifestDesc, err := PackManifest(ctx, s, PackManifestVersion1_0, "", PackManifestOptions{}) 736 if err != nil { 737 t.Fatal("Oras.PackManifest() error =", err) 738 } 739 740 var manifest ocispec.Manifest 741 rc, err := s.Fetch(ctx, manifestDesc) 742 if err != nil { 743 t.Fatal("Store.Fetch() error =", err) 744 } 745 if err := json.NewDecoder(rc).Decode(&manifest); err != nil { 746 t.Fatal("error decoding manifest, error =", err) 747 } 748 if err := rc.Close(); err != nil { 749 t.Fatal("Store.Fetch().Close() error =", err) 750 } 751 752 // verify artifact type and config media type 753 if manifestDesc.ArtifactType != MediaTypeUnknownConfig { 754 t.Fatalf("got artifact type = %s, want %s", manifestDesc.ArtifactType, MediaTypeUnknownConfig) 755 } 756 if manifest.Config.MediaType != MediaTypeUnknownConfig { 757 t.Fatalf("got artifact type = %s, want %s", manifest.Config.MediaType, MediaTypeUnknownConfig) 758 } 759 } 760 761 func Test_PackManifest_ImageV1_0_InvalidMediaType(t *testing.T) { 762 s := memory.New() 763 764 ctx := context.Background() 765 // test invalid artifact type + valid config media type 766 artifactType := "random" 767 configBytes := []byte("{}") 768 configDesc := content.NewDescriptorFromBytes("application/vnd.test.config", configBytes) 769 opts := PackManifestOptions{ 770 ConfigDescriptor: &configDesc, 771 } 772 _, err := PackManifest(ctx, s, PackManifestVersion1_0, artifactType, opts) 773 if err != nil { 774 t.Error("Oras.PackManifest() error =", err) 775 } 776 777 // test invalid config media type + valid artifact type 778 artifactType = "application/vnd.test" 779 configDesc = content.NewDescriptorFromBytes("random", configBytes) 780 opts = PackManifestOptions{ 781 ConfigDescriptor: &configDesc, 782 } 783 _, err = PackManifest(ctx, s, PackManifestVersion1_0, artifactType, opts) 784 if wantErr := errdef.ErrInvalidMediaType; !errors.Is(err, wantErr) { 785 t.Errorf("Oras.PackManifest() error = %v, wantErr = %v", err, wantErr) 786 } 787 } 788 789 func Test_PackManifest_ImageV1_0_InvalidDateTimeFormat(t *testing.T) { 790 s := memory.New() 791 792 ctx := context.Background() 793 opts := PackManifestOptions{ 794 ManifestAnnotations: map[string]string{ 795 ocispec.AnnotationCreated: "2000/01/01 00:00:00", 796 }, 797 } 798 _, err := PackManifest(ctx, s, PackManifestVersion1_0, "", opts) 799 if wantErr := ErrInvalidDateTimeFormat; !errors.Is(err, wantErr) { 800 t.Errorf("Oras.PackManifest() error = %v, wantErr = %v", err, wantErr) 801 } 802 } 803 804 func Test_PackManifest_ImageV1_1(t *testing.T) { 805 s := memory.New() 806 807 // test PackManifest 808 ctx := context.Background() 809 artifactType := "application/vnd.test" 810 manifestDesc, err := PackManifest(ctx, s, PackManifestVersion1_1, artifactType, PackManifestOptions{}) 811 if err != nil { 812 t.Fatal("Oras.PackManifest() error =", err) 813 } 814 815 var manifest ocispec.Manifest 816 rc, err := s.Fetch(ctx, manifestDesc) 817 if err != nil { 818 t.Fatal("Store.Fetch() error =", err) 819 } 820 if err := json.NewDecoder(rc).Decode(&manifest); err != nil { 821 t.Fatal("error decoding manifest, error =", err) 822 } 823 if err := rc.Close(); err != nil { 824 t.Fatal("Store.Fetch().Close() error =", err) 825 } 826 827 // verify layers 828 expectedLayers := []ocispec.Descriptor{ocispec.DescriptorEmptyJSON} 829 if !reflect.DeepEqual(manifest.Layers, expectedLayers) { 830 t.Errorf("got layers = %v, want %v", manifest.Layers, expectedLayers) 831 } 832 } 833 834 func Test_PackManifest_ImageV1_1_WithOptions(t *testing.T) { 835 s := memory.New() 836 837 // prepare test content 838 layers := []ocispec.Descriptor{ 839 content.NewDescriptorFromBytes("test", []byte("hello world")), 840 content.NewDescriptorFromBytes("test", []byte("goodbye world")), 841 } 842 configBytes := []byte("config") 843 configDesc := content.NewDescriptorFromBytes("application/vnd.test.config", configBytes) 844 configAnnotations := map[string]string{"foo": "bar"} 845 annotations := map[string]string{ 846 ocispec.AnnotationCreated: "2000-01-01T00:00:00Z", 847 "foo": "bar", 848 } 849 artifactType := "application/vnd.test" 850 subjectManifest := []byte(`{"layers":[]}`) 851 subjectDesc := ocispec.Descriptor{ 852 MediaType: ocispec.MediaTypeImageManifest, 853 Digest: digest.FromBytes(subjectManifest), 854 Size: int64(len(subjectManifest)), 855 } 856 857 // test PackManifest with ConfigDescriptor 858 ctx := context.Background() 859 opts := PackManifestOptions{ 860 Subject: &subjectDesc, 861 Layers: layers, 862 ConfigDescriptor: &configDesc, 863 ConfigAnnotations: configAnnotations, 864 ManifestAnnotations: annotations, 865 } 866 manifestDesc, err := PackManifest(ctx, s, PackManifestVersion1_1, artifactType, opts) 867 if err != nil { 868 t.Fatal("Oras.PackManifest() error =", err) 869 } 870 871 expectedManifest := ocispec.Manifest{ 872 Versioned: specs.Versioned{ 873 SchemaVersion: 2, // historical value. does not pertain to OCI or docker version 874 }, 875 MediaType: ocispec.MediaTypeImageManifest, 876 ArtifactType: artifactType, 877 Subject: &subjectDesc, 878 Config: configDesc, 879 Layers: layers, 880 Annotations: annotations, 881 } 882 expectedManifestBytes, err := json.Marshal(expectedManifest) 883 if err != nil { 884 t.Fatal("failed to marshal manifest:", err) 885 } 886 887 rc, err := s.Fetch(ctx, manifestDesc) 888 if err != nil { 889 t.Fatal("Store.Fetch() error =", err) 890 } 891 got, err := io.ReadAll(rc) 892 if err != nil { 893 t.Fatal("Store.Fetch().Read() error =", err) 894 } 895 err = rc.Close() 896 if err != nil { 897 t.Error("Store.Fetch().Close() error =", err) 898 } 899 if !bytes.Equal(got, expectedManifestBytes) { 900 t.Errorf("Store.Fetch() = %v, want %v", string(got), string(expectedManifestBytes)) 901 } 902 903 // verify descriptor 904 expectedManifestDesc := content.NewDescriptorFromBytes(expectedManifest.MediaType, expectedManifestBytes) 905 expectedManifestDesc.ArtifactType = expectedManifest.ArtifactType 906 expectedManifestDesc.Annotations = expectedManifest.Annotations 907 if !reflect.DeepEqual(manifestDesc, expectedManifestDesc) { 908 t.Errorf("PackManifest() = %v, want %v", manifestDesc, expectedManifestDesc) 909 } 910 911 // test PackManifest with ConfigDescriptor, but without artifactType 912 opts = PackManifestOptions{ 913 Subject: &subjectDesc, 914 Layers: layers, 915 ConfigDescriptor: &configDesc, 916 ConfigAnnotations: configAnnotations, 917 ManifestAnnotations: annotations, 918 } 919 manifestDesc, err = PackManifest(ctx, s, PackManifestVersion1_1, "", opts) 920 if err != nil { 921 t.Fatal("Oras.PackManifest() error =", err) 922 } 923 924 expectedManifest = ocispec.Manifest{ 925 Versioned: specs.Versioned{ 926 SchemaVersion: 2, // historical value. does not pertain to OCI or docker version 927 }, 928 MediaType: ocispec.MediaTypeImageManifest, 929 Subject: &subjectDesc, 930 Config: configDesc, 931 Layers: layers, 932 Annotations: annotations, 933 } 934 expectedManifestBytes, err = json.Marshal(expectedManifest) 935 if err != nil { 936 t.Fatal("failed to marshal manifest:", err) 937 } 938 939 rc, err = s.Fetch(ctx, manifestDesc) 940 if err != nil { 941 t.Fatal("Store.Fetch() error =", err) 942 } 943 got, err = io.ReadAll(rc) 944 if err != nil { 945 t.Fatal("Store.Fetch().Read() error =", err) 946 } 947 err = rc.Close() 948 if err != nil { 949 t.Error("Store.Fetch().Close() error =", err) 950 } 951 if !bytes.Equal(got, expectedManifestBytes) { 952 t.Errorf("Store.Fetch() = %v, want %v", string(got), string(expectedManifestBytes)) 953 } 954 955 // verify descriptor 956 expectedManifestDesc = content.NewDescriptorFromBytes(expectedManifest.MediaType, expectedManifestBytes) 957 expectedManifestDesc.ArtifactType = expectedManifest.ArtifactType 958 expectedManifestDesc.Annotations = expectedManifest.Annotations 959 if !reflect.DeepEqual(manifestDesc, expectedManifestDesc) { 960 t.Errorf("PackManifest() = %v, want %v", manifestDesc, expectedManifestDesc) 961 } 962 963 // test Pack without ConfigDescriptor 964 opts = PackManifestOptions{ 965 Subject: &subjectDesc, 966 Layers: layers, 967 ConfigAnnotations: configAnnotations, 968 ManifestAnnotations: annotations, 969 } 970 manifestDesc, err = PackManifest(ctx, s, PackManifestVersion1_1, artifactType, opts) 971 if err != nil { 972 t.Fatal("Oras.PackManifest() error =", err) 973 } 974 975 expectedConfigDesc := ocispec.DescriptorEmptyJSON 976 expectedConfigDesc.Annotations = configAnnotations 977 expectedManifest = ocispec.Manifest{ 978 Versioned: specs.Versioned{ 979 SchemaVersion: 2, // historical value. does not pertain to OCI or docker version 980 }, 981 MediaType: ocispec.MediaTypeImageManifest, 982 ArtifactType: artifactType, 983 Subject: &subjectDesc, 984 Config: expectedConfigDesc, 985 Layers: layers, 986 Annotations: annotations, 987 } 988 expectedManifestBytes, err = json.Marshal(expectedManifest) 989 if err != nil { 990 t.Fatal("failed to marshal manifest:", err) 991 } 992 993 rc, err = s.Fetch(ctx, manifestDesc) 994 if err != nil { 995 t.Fatal("Store.Fetch() error =", err) 996 } 997 got, err = io.ReadAll(rc) 998 if err != nil { 999 t.Fatal("Store.Fetch().Read() error =", err) 1000 } 1001 err = rc.Close() 1002 if err != nil { 1003 t.Error("Store.Fetch().Close() error =", err) 1004 } 1005 if !bytes.Equal(got, expectedManifestBytes) { 1006 t.Errorf("Store.Fetch() = %v, want %v", string(got), string(expectedManifestBytes)) 1007 } 1008 1009 // verify descriptor 1010 expectedManifestDesc = content.NewDescriptorFromBytes(expectedManifest.MediaType, expectedManifestBytes) 1011 expectedManifestDesc.ArtifactType = expectedManifest.ArtifactType 1012 expectedManifestDesc.Annotations = expectedManifest.Annotations 1013 if !reflect.DeepEqual(manifestDesc, expectedManifestDesc) { 1014 t.Errorf("PackManifest() = %v, want %v", manifestDesc, expectedManifestDesc) 1015 } 1016 } 1017 1018 func Test_PackManifest_ImageV1_1_NoArtifactType(t *testing.T) { 1019 s := memory.New() 1020 1021 ctx := context.Background() 1022 // test no artifact type and no config 1023 _, err := PackManifest(ctx, s, PackManifestVersion1_1, "", PackManifestOptions{}) 1024 if wantErr := ErrMissingArtifactType; !errors.Is(err, wantErr) { 1025 t.Errorf("Oras.PackManifest() error = %v, wantErr = %v", err, wantErr) 1026 } 1027 1028 // test no artifact type and config with empty media type 1029 opts := PackManifestOptions{ 1030 ConfigDescriptor: &ocispec.Descriptor{ 1031 MediaType: ocispec.DescriptorEmptyJSON.MediaType, 1032 }, 1033 } 1034 _, err = PackManifest(ctx, s, PackManifestVersion1_1, "", opts) 1035 if wantErr := ErrMissingArtifactType; !errors.Is(err, wantErr) { 1036 t.Errorf("Oras.PackManifest() error = %v, wantErr = %v", err, wantErr) 1037 } 1038 } 1039 1040 func Test_PackManifest_ImageV1_1_InvalidMediaType(t *testing.T) { 1041 s := memory.New() 1042 1043 ctx := context.Background() 1044 // test invalid artifact type + valid config media type 1045 artifactType := "random" 1046 configBytes := []byte("{}") 1047 configDesc := content.NewDescriptorFromBytes("application/vnd.test.config", configBytes) 1048 opts := PackManifestOptions{ 1049 ConfigDescriptor: &configDesc, 1050 } 1051 _, err := PackManifest(ctx, s, PackManifestVersion1_1, artifactType, opts) 1052 if wantErr := errdef.ErrInvalidMediaType; !errors.Is(err, wantErr) { 1053 t.Errorf("Oras.PackManifest() error = %v, wantErr = %v", err, wantErr) 1054 } 1055 1056 // test invalid config media type + invalid artifact type 1057 artifactType = "application/vnd.test" 1058 configDesc = content.NewDescriptorFromBytes("random", configBytes) 1059 opts = PackManifestOptions{ 1060 ConfigDescriptor: &configDesc, 1061 } 1062 _, err = PackManifest(ctx, s, PackManifestVersion1_1, artifactType, opts) 1063 if wantErr := errdef.ErrInvalidMediaType; !errors.Is(err, wantErr) { 1064 t.Errorf("Oras.PackManifest() error = %v, wantErr = %v", err, wantErr) 1065 } 1066 } 1067 1068 func Test_PackManifest_ImageV1_1_InvalidDateTimeFormat(t *testing.T) { 1069 s := memory.New() 1070 1071 ctx := context.Background() 1072 opts := PackManifestOptions{ 1073 ManifestAnnotations: map[string]string{ 1074 ocispec.AnnotationCreated: "2000/01/01 00:00:00", 1075 }, 1076 } 1077 artifactType := "application/vnd.test" 1078 _, err := PackManifest(ctx, s, PackManifestVersion1_1, artifactType, opts) 1079 if wantErr := ErrInvalidDateTimeFormat; !errors.Is(err, wantErr) { 1080 t.Errorf("Oras.PackManifest() error = %v, wantErr = %v", err, wantErr) 1081 } 1082 } 1083 1084 func Test_PackManifest_UnsupportedPackManifestVersion(t *testing.T) { 1085 s := memory.New() 1086 1087 ctx := context.Background() 1088 _, err := PackManifest(ctx, s, -1, "", PackManifestOptions{}) 1089 if wantErr := errdef.ErrUnsupported; !errors.Is(err, wantErr) { 1090 t.Errorf("Oras.PackManifest() error = %v, wantErr = %v", err, wantErr) 1091 } 1092 }