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 }