github.com/coreos/rocket@v1.30.1-0.20200224141603-171c416fac02/store/treestore/tree_test.go (about) 1 // Copyright 2015 The rkt Authors 2 // 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 package treestore 16 17 import ( 18 "archive/tar" 19 "io/ioutil" 20 "os" 21 "path/filepath" 22 "testing" 23 24 "github.com/rkt/rkt/pkg/aci" 25 "github.com/rkt/rkt/pkg/aci/acitest" 26 "github.com/rkt/rkt/pkg/sys" 27 "github.com/rkt/rkt/store/imagestore" 28 ) 29 30 const tstprefix = "treestore-test" 31 32 // TODO(sgotti) when the TreeStore will use an interface, change it to a 33 // test implementation without relying on store/imagestore 34 func testStoreWriteACI(dir string, s *imagestore.Store) (string, error) { 35 imj, err := acitest.ImageManifestString(nil) 36 if err != nil { 37 return "", err 38 } 39 40 entries := []*aci.ACIEntry{ 41 // An empty dir 42 { 43 Header: &tar.Header{ 44 Name: "rootfs/a", 45 Typeflag: tar.TypeDir, 46 }, 47 }, 48 { 49 Contents: "hello", 50 Header: &tar.Header{ 51 Name: "hello.txt", 52 Size: 5, 53 }, 54 }, 55 { 56 Header: &tar.Header{ 57 Name: "rootfs/link.txt", 58 Linkname: "rootfs/hello.txt", 59 Typeflag: tar.TypeSymlink, 60 }, 61 }, 62 // dangling symlink 63 { 64 Header: &tar.Header{ 65 Name: "rootfs/link2.txt", 66 Linkname: "rootfs/missingfile.txt", 67 Typeflag: tar.TypeSymlink, 68 }, 69 }, 70 { 71 Header: &tar.Header{ 72 Name: "rootfs/fifo", 73 Typeflag: tar.TypeFifo, 74 }, 75 }, 76 } 77 aci, err := aci.NewACI(dir, imj, entries) 78 if err != nil { 79 return "", err 80 } 81 defer aci.Close() 82 83 // Rewind the ACI 84 if _, err := aci.Seek(0, 0); err != nil { 85 return "", err 86 } 87 88 // Import the new ACI 89 key, err := s.WriteACI(aci, imagestore.ACIFetchInfo{Latest: false}) 90 if err != nil { 91 return "", err 92 } 93 return key, nil 94 } 95 96 func TestTreeStoreRender(t *testing.T) { 97 if !sys.HasChrootCapability() { 98 t.Skipf("chroot capability not available. Disabling test.") 99 } 100 101 dir, err := ioutil.TempDir("", tstprefix) 102 if err != nil { 103 t.Fatalf("error creating tempdir: %v", err) 104 } 105 defer os.RemoveAll(dir) 106 107 s, err := imagestore.NewStore(dir) 108 if err != nil { 109 t.Fatalf("unexpected error: %v", err) 110 } 111 ts, err := NewStore(dir, s) 112 if err != nil { 113 t.Fatalf("unexpected error: %v", err) 114 } 115 116 key, err := testStoreWriteACI(dir, s) 117 if err != nil { 118 t.Fatalf("unexpected error: %v", err) 119 } 120 121 id := "treestoreid01" 122 123 _, err = ts.render(id, key) 124 if err != nil { 125 t.Fatalf("unexpected error: %v", err) 126 } 127 128 // Verify image Hash. Should be the same. 129 _, err = ts.Check(id) 130 if err != nil { 131 t.Fatalf("unexpected error: %v", err) 132 } 133 } 134 135 func TestTreeStoreRemove(t *testing.T) { 136 if !sys.HasChrootCapability() { 137 t.Skipf("chroot capability not available. Disabling test.") 138 } 139 140 dir, err := ioutil.TempDir("", tstprefix) 141 if err != nil { 142 t.Fatalf("error creating tempdir: %v", err) 143 } 144 defer os.RemoveAll(dir) 145 146 s, err := imagestore.NewStore(dir) 147 if err != nil { 148 t.Fatalf("unexpected error: %v", err) 149 } 150 ts, err := NewStore(dir, s) 151 if err != nil { 152 t.Fatalf("unexpected error: %v", err) 153 } 154 155 key, err := testStoreWriteACI(dir, s) 156 if err != nil { 157 t.Fatalf("unexpected error: %v", err) 158 } 159 160 id := "treestoreid01" 161 162 // Test non existent dir 163 err = ts.remove(id) 164 if err != nil { 165 t.Fatalf("unexpected error: %v", err) 166 } 167 168 // Test rendered tree 169 _, err = ts.render(id, key) 170 if err != nil { 171 t.Fatalf("unexpected error: %v", err) 172 } 173 174 err = ts.remove(id) 175 if err != nil { 176 t.Fatalf("unexpected error: %v", err) 177 } 178 } 179 180 func TestTreeStore(t *testing.T) { 181 if !sys.HasChrootCapability() { 182 t.Skipf("chroot capability not available. Disabling test.") 183 } 184 185 dir, err := ioutil.TempDir("", tstprefix) 186 if err != nil { 187 t.Fatalf("error creating tempdir: %v", err) 188 } 189 defer os.RemoveAll(dir) 190 191 s, err := imagestore.NewStore(dir) 192 if err != nil { 193 t.Fatalf("unexpected error: %v", err) 194 } 195 ts, err := NewStore(dir, s) 196 if err != nil { 197 t.Fatalf("unexpected error: %v", err) 198 } 199 200 imj, err := acitest.ImageManifestString(nil) 201 if err != nil { 202 t.Fatalf("unexpected error: %v", err) 203 } 204 205 entries := []*aci.ACIEntry{ 206 // An empty dir 207 { 208 Header: &tar.Header{ 209 Name: "rootfs/a", 210 Typeflag: tar.TypeDir, 211 }, 212 }, 213 { 214 Contents: "hello", 215 Header: &tar.Header{ 216 Name: "hello.txt", 217 Size: 5, 218 }, 219 }, 220 { 221 Header: &tar.Header{ 222 Name: "rootfs/link.txt", 223 Linkname: "rootfs/hello.txt", 224 Typeflag: tar.TypeSymlink, 225 }, 226 }, 227 // dangling symlink 228 { 229 Header: &tar.Header{ 230 Name: "rootfs/link2.txt", 231 Linkname: "rootfs/missingfile.txt", 232 Typeflag: tar.TypeSymlink, 233 }, 234 }, 235 { 236 Header: &tar.Header{ 237 Name: "rootfs/fifo", 238 Typeflag: tar.TypeFifo, 239 }, 240 }, 241 } 242 aci, err := aci.NewACI(dir, imj, entries) 243 if err != nil { 244 t.Fatalf("error creating test tar: %v", err) 245 } 246 defer aci.Close() 247 248 // Rewind the ACI 249 if _, err := aci.Seek(0, 0); err != nil { 250 t.Fatalf("unexpected error: %v", err) 251 } 252 253 // Import the new ACI 254 key, err := s.WriteACI(aci, imagestore.ACIFetchInfo{Latest: false}) 255 if err != nil { 256 t.Fatalf("unexpected error: %v", err) 257 } 258 259 // Ask the store to render the treestore 260 id, _, err := ts.Render(key, false) 261 if err != nil { 262 t.Fatalf("unexpected error: %v", err) 263 } 264 265 // Verify image Hash. Should be the same. 266 _, err = ts.Check(id) 267 if err != nil { 268 t.Fatalf("unexpected error: %v", err) 269 } 270 271 // Change a file permission 272 rootfs := ts.GetRootFS(id) 273 err = os.Chmod(filepath.Join(rootfs, "a"), 0600) 274 if err != nil { 275 t.Fatalf("unexpected error: %v", err) 276 } 277 278 // Verify image Hash. Should be different 279 _, err = ts.Check(id) 280 if err == nil { 281 t.Errorf("expected non-nil error!") 282 } 283 284 // rebuild the tree 285 prevID := id 286 id, _, err = ts.Render(key, true) 287 if err != nil { 288 t.Fatalf("unexpected error: %v", err) 289 } 290 291 if id != prevID { 292 t.Fatalf("unexpected different IDs. prevID: %s, id: %s", prevID, id) 293 } 294 295 // Add a file 296 rootfs = ts.GetRootFS(id) 297 err = ioutil.WriteFile(filepath.Join(rootfs, "newfile"), []byte("newfile"), 0644) 298 if err != nil { 299 t.Fatalf("unexpected error: %v", err) 300 } 301 302 // Verify image Hash. Should be different 303 _, err = ts.Check(id) 304 if err == nil { 305 t.Errorf("expected non-nil error!") 306 } 307 }