github.com/opencontainers/umoci@v0.4.8-0.20240508124516-656e4836fb0d/oci/casext/json_dir_test.go (about)

     1  /*
     2   * umoci: Umoci Modifies Open Containers' Images
     3   * Copyright (C) 2016-2020 SUSE LLC
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *    http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  package casext
    19  
    20  import (
    21  	"context"
    22  	"encoding/json"
    23  	"io/ioutil"
    24  	"os"
    25  	"path/filepath"
    26  	"reflect"
    27  	"testing"
    28  
    29  	"github.com/opencontainers/umoci/oci/cas/dir"
    30  	"github.com/opencontainers/umoci/pkg/testutils"
    31  	"github.com/pkg/errors"
    32  )
    33  
    34  func TestEngineBlobJSON(t *testing.T) {
    35  	ctx := context.Background()
    36  
    37  	root, err := ioutil.TempDir("", "umoci-TestEngineBlobJSON")
    38  	if err != nil {
    39  		t.Fatal(err)
    40  	}
    41  	defer os.RemoveAll(root)
    42  
    43  	image := filepath.Join(root, "image")
    44  	if err := dir.Create(image); err != nil {
    45  		t.Fatalf("unexpected error creating image: %+v", err)
    46  	}
    47  
    48  	engine, err := dir.Open(image)
    49  	if err != nil {
    50  		t.Fatalf("unexpected error opening image: %+v", err)
    51  	}
    52  	engineExt := NewEngine(engine)
    53  	defer engine.Close()
    54  
    55  	type object struct {
    56  		A string `json:"A"`
    57  		B int64  `json:"B,omitempty"`
    58  	}
    59  
    60  	for _, test := range []struct {
    61  		object object
    62  	}{
    63  		{object{}},
    64  		{object{"a value", 100}},
    65  		{object{"another value", 200}},
    66  	} {
    67  		digest, _, err := engineExt.PutBlobJSON(ctx, test.object)
    68  		if err != nil {
    69  			t.Errorf("PutBlobJSON: unexpected error: %+v", err)
    70  		}
    71  
    72  		blobReader, err := engine.GetBlob(ctx, digest)
    73  		if err != nil {
    74  			t.Errorf("GetBlob: unexpected error: %+v", err)
    75  		}
    76  		defer blobReader.Close()
    77  
    78  		gotBytes, err := ioutil.ReadAll(blobReader)
    79  		if err != nil {
    80  			t.Errorf("GetBlob: failed to ReadAll: %+v", err)
    81  		}
    82  
    83  		var gotObject object
    84  		if err := json.Unmarshal(gotBytes, &gotObject); err != nil {
    85  			t.Errorf("GetBlob: got an invalid JSON blob: %+v", err)
    86  		}
    87  		if !reflect.DeepEqual(test.object, gotObject) {
    88  			t.Errorf("GetBlob: got different object to original JSON. expected=%v got=%v gotBytes=%v", test.object, gotObject, gotBytes)
    89  		}
    90  
    91  		if err := engine.DeleteBlob(ctx, digest); err != nil {
    92  			t.Errorf("DeleteBlob: unexpected error: %+v", err)
    93  		}
    94  
    95  		if br, err := engine.GetBlob(ctx, digest); !os.IsNotExist(errors.Cause(err)) {
    96  			if err == nil {
    97  				br.Close()
    98  				t.Errorf("GetBlob: still got blob contents after DeleteBlob!")
    99  			} else {
   100  				t.Errorf("GetBlob: unexpected error: %+v", err)
   101  			}
   102  		}
   103  
   104  		// DeleteBlob is idempotent. It shouldn't cause an error.
   105  		if err := engine.DeleteBlob(ctx, digest); err != nil {
   106  			t.Errorf("DeleteBlob: unexpected error on double-delete: %+v", err)
   107  		}
   108  	}
   109  
   110  	// Should be no blobs left.
   111  	if blobs, err := engine.ListBlobs(ctx); err != nil {
   112  		t.Errorf("unexpected error getting list of blobs: %+v", err)
   113  	} else if len(blobs) > 0 {
   114  		t.Errorf("got blobs in a clean image: %v", blobs)
   115  	}
   116  }
   117  
   118  func TestEngineBlobJSONReadonly(t *testing.T) {
   119  	ctx := context.Background()
   120  
   121  	root, err := ioutil.TempDir("", "umoci-TestEngineBlobJSONReadonly")
   122  	if err != nil {
   123  		t.Fatal(err)
   124  	}
   125  	defer os.RemoveAll(root)
   126  
   127  	image := filepath.Join(root, "image")
   128  	if err := dir.Create(image); err != nil {
   129  		t.Fatalf("unexpected error creating image: %+v", err)
   130  	}
   131  
   132  	type object struct {
   133  		A string `json:"A"`
   134  		B int64  `json:"B,omitempty"`
   135  	}
   136  
   137  	for _, test := range []struct {
   138  		object object
   139  	}{
   140  		{object{}},
   141  		{object{"a value", 100}},
   142  		{object{"another value", 200}},
   143  	} {
   144  		engine, err := dir.Open(image)
   145  		if err != nil {
   146  			t.Fatalf("unexpected error opening image: %+v", err)
   147  		}
   148  		engineExt := NewEngine(engine)
   149  
   150  		digest, _, err := engineExt.PutBlobJSON(ctx, test.object)
   151  		if err != nil {
   152  			t.Errorf("PutBlobJSON: unexpected error: %+v", err)
   153  		}
   154  
   155  		if err := engine.Close(); err != nil {
   156  			t.Errorf("Close: unexpected error encountered: %+v", err)
   157  		}
   158  
   159  		// make it readonly
   160  		testutils.MakeReadOnly(t, image)
   161  
   162  		newEngine, err := dir.Open(image)
   163  		if err != nil {
   164  			t.Errorf("unexpected error opening ro image: %+v", err)
   165  		}
   166  		newEngineExt := NewEngine(newEngine)
   167  
   168  		blobReader, err := newEngineExt.GetBlob(ctx, digest)
   169  		if err != nil {
   170  			t.Errorf("GetBlob: unexpected error: %+v", err)
   171  		}
   172  		defer blobReader.Close()
   173  
   174  		gotBytes, err := ioutil.ReadAll(blobReader)
   175  		if err != nil {
   176  			t.Errorf("GetBlob: failed to ReadAll: %+v", err)
   177  		}
   178  
   179  		var gotObject object
   180  		if err := json.Unmarshal(gotBytes, &gotObject); err != nil {
   181  			t.Errorf("GetBlob: got an invalid JSON blob: %+v", err)
   182  		}
   183  		if !reflect.DeepEqual(test.object, gotObject) {
   184  			t.Errorf("GetBlob: got different object to original JSON. expected=%v got=%v gotBytes=%v", test.object, gotObject, gotBytes)
   185  		}
   186  
   187  		// Make sure that writing again will FAIL.
   188  		_, _, err = newEngineExt.PutBlobJSON(ctx, test.object)
   189  		if err == nil {
   190  			t.Errorf("PutBlob: expected error on ro image!")
   191  		}
   192  
   193  		if err := newEngine.Close(); err != nil {
   194  			t.Errorf("Close: unexpected error encountered on ro: %+v", err)
   195  		}
   196  
   197  		// make it readwrite again.
   198  		testutils.MakeReadWrite(t, image)
   199  	}
   200  }