github.com/dtroyer-salad/og2/v2@v2.0.0-20240412154159-c47231610877/content/file/file_unix_test.go (about) 1 //go:build !windows 2 3 /* 4 Copyright The ORAS Authors. 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 file 19 20 import ( 21 "bytes" 22 "context" 23 "os" 24 "path/filepath" 25 "testing" 26 27 ocispec "github.com/opencontainers/image-spec/specs-go/v1" 28 "oras.land/oras-go/v2" 29 ) 30 31 // Related issue: https://github.com/oras-project/oras-go/issues/402 32 func TestStore_Dir_ExtractSymlinkRel(t *testing.T) { 33 // prepare test content 34 tempDir := t.TempDir() 35 dirName := "testdir" 36 dirPath := filepath.Join(tempDir, dirName) 37 if err := os.MkdirAll(dirPath, 0777); err != nil { 38 t.Fatal("error calling Mkdir(), error =", err) 39 } 40 41 content := []byte("hello world") 42 fileName := "test.txt" 43 filePath := filepath.Join(dirPath, fileName) 44 if err := os.WriteFile(filePath, content, 0444); err != nil { 45 t.Fatal("error calling WriteFile(), error =", err) 46 } 47 // create symlink to a relative path 48 symlinkName := "test_symlink" 49 symlinkPath := filepath.Join(dirPath, symlinkName) 50 if err := os.Symlink(fileName, symlinkPath); err != nil { 51 t.Fatal("error calling Symlink(), error =", err) 52 } 53 54 src, err := New(tempDir) 55 if err != nil { 56 t.Fatal("Store.New() error =", err) 57 } 58 defer src.Close() 59 ctx := context.Background() 60 61 // add dir 62 desc, err := src.Add(ctx, dirName, "", dirPath) 63 if err != nil { 64 t.Fatal("Store.Add() error =", err) 65 } 66 // pack a manifest 67 manifestDesc, err := oras.Pack(ctx, src, "dir", []ocispec.Descriptor{desc}, oras.PackOptions{}) 68 if err != nil { 69 t.Fatal("oras.Pack() error =", err) 70 } 71 72 // copy to another file store created from an absolute root, to trigger extracting directory 73 tempDir = t.TempDir() 74 dstAbs, err := New(tempDir) 75 if err != nil { 76 t.Fatal("Store.New() error =", err) 77 } 78 defer dstAbs.Close() 79 if err := oras.CopyGraph(ctx, src, dstAbs, manifestDesc, oras.DefaultCopyGraphOptions); err != nil { 80 t.Fatal("oras.CopyGraph() error =", err) 81 } 82 83 // verify extracted symlink 84 extractedSymlink := filepath.Join(tempDir, dirName, symlinkName) 85 symlinkDst, err := os.Readlink(extractedSymlink) 86 if err != nil { 87 t.Fatal("failed to get symlink destination, error =", err) 88 } 89 if want := fileName; symlinkDst != want { 90 t.Errorf("symlink destination = %v, want %v", symlinkDst, want) 91 } 92 got, err := os.ReadFile(extractedSymlink) 93 if err != nil { 94 t.Fatal("failed to read symlink file, error =", err) 95 } 96 if !bytes.Equal(got, content) { 97 t.Errorf("symlink content = %v, want %v", got, content) 98 } 99 100 // copy to another file store created from a relative root, to trigger extracting directory 101 tempDir = t.TempDir() 102 if err := os.Chdir(tempDir); err != nil { 103 t.Fatal("error calling Chdir(), error=", err) 104 } 105 dstRel, err := New(".") 106 if err != nil { 107 t.Fatal("Store.New() error =", err) 108 } 109 defer dstRel.Close() 110 if err := oras.CopyGraph(ctx, src, dstRel, manifestDesc, oras.DefaultCopyGraphOptions); err != nil { 111 t.Fatal("oras.CopyGraph() error =", err) 112 } 113 114 // verify extracted symlink 115 extractedSymlink = filepath.Join(tempDir, dirName, symlinkName) 116 symlinkDst, err = os.Readlink(extractedSymlink) 117 if err != nil { 118 t.Fatal("failed to get symlink destination, error =", err) 119 } 120 if want := fileName; symlinkDst != want { 121 t.Errorf("symlink destination = %v, want %v", symlinkDst, want) 122 } 123 got, err = os.ReadFile(extractedSymlink) 124 if err != nil { 125 t.Fatal("failed to read symlink file, error =", err) 126 } 127 if !bytes.Equal(got, content) { 128 t.Errorf("symlink content = %v, want %v", got, content) 129 } 130 } 131 132 // Related issue: https://github.com/oras-project/oras-go/issues/402 133 func TestStore_Dir_ExtractSymlinkAbs(t *testing.T) { 134 // prepare test content 135 tempDir, err := filepath.EvalSymlinks(t.TempDir()) 136 if err != nil { 137 t.Fatal("error calling filepath.EvalSymlinks(), error =", err) 138 } 139 dirName := "testdir" 140 dirPath := filepath.Join(tempDir, dirName) 141 if err := os.MkdirAll(dirPath, 0777); err != nil { 142 t.Fatal("error calling Mkdir(), error =", err) 143 } 144 145 content := []byte("hello world") 146 fileName := "test.txt" 147 filePath := filepath.Join(dirPath, fileName) 148 if err := os.WriteFile(filePath, content, 0444); err != nil { 149 t.Fatal("error calling WriteFile(), error =", err) 150 } 151 // create symlink to an absolute path 152 symlink := filepath.Join(dirPath, "test_symlink") 153 if err := os.Symlink(filePath, symlink); err != nil { 154 t.Fatal("error calling Symlink(), error =", err) 155 } 156 157 src, err := New(tempDir) 158 if err != nil { 159 t.Fatal("Store.New() error =", err) 160 } 161 defer src.Close() 162 ctx := context.Background() 163 164 // add dir 165 desc, err := src.Add(ctx, dirName, "", dirPath) 166 if err != nil { 167 t.Fatal("Store.Add() error =", err) 168 } 169 // pack a manifest 170 manifestDesc, err := oras.Pack(ctx, src, "dir", []ocispec.Descriptor{desc}, oras.PackOptions{}) 171 if err != nil { 172 t.Fatal("oras.Pack() error =", err) 173 } 174 175 // remove the original testing directory and create a new store using an absolute root 176 if err := os.RemoveAll(dirPath); err != nil { 177 t.Fatal("error calling RemoveAll(), error =", err) 178 } 179 dstAbs, err := New(tempDir) 180 if err != nil { 181 t.Fatal("Store.New() error =", err) 182 } 183 defer dstAbs.Close() 184 if err := oras.CopyGraph(ctx, src, dstAbs, manifestDesc, oras.DefaultCopyGraphOptions); err != nil { 185 t.Fatal("oras.CopyGraph() error =", err) 186 } 187 188 // verify extracted symlink 189 symlinkDst, err := os.Readlink(symlink) 190 if err != nil { 191 t.Fatal("failed to get symlink destination, error =", err) 192 } 193 if want := filePath; symlinkDst != want { 194 t.Errorf("symlink destination = %v, want %v", symlinkDst, want) 195 } 196 got, err := os.ReadFile(symlink) 197 if err != nil { 198 t.Fatal("failed to read symlink file, error =", err) 199 } 200 if !bytes.Equal(got, content) { 201 t.Errorf("symlink content = %v, want %v", got, content) 202 } 203 204 // remove the original testing directory and create a new store using a relative path 205 if err := os.RemoveAll(dirPath); err != nil { 206 t.Fatal("error calling RemoveAll(), error =", err) 207 } 208 if err := os.Chdir(tempDir); err != nil { 209 t.Fatal("error calling Chdir(), error=", err) 210 } 211 dstRel, err := New(".") 212 if err != nil { 213 t.Fatal("Store.New() error =", err) 214 } 215 defer dstRel.Close() 216 if err := oras.CopyGraph(ctx, src, dstRel, manifestDesc, oras.DefaultCopyGraphOptions); err != nil { 217 t.Fatal("oras.CopyGraph() error =", err) 218 } 219 220 // verify extracted symlink 221 symlinkDst, err = os.Readlink(symlink) 222 if err != nil { 223 t.Fatal("failed to get symlink destination, error =", err) 224 } 225 if want := filePath; symlinkDst != want { 226 t.Errorf("symlink destination = %v, want %v", symlinkDst, want) 227 } 228 got, err = os.ReadFile(symlink) 229 if err != nil { 230 t.Fatal("failed to read symlink file, error =", err) 231 } 232 if !bytes.Equal(got, content) { 233 t.Errorf("symlink content = %v, want %v", got, content) 234 } 235 236 // copy to another file store created from an outside root, to trigger extracting directory 237 tempDir = t.TempDir() 238 dstOutside, err := New(tempDir) 239 if err != nil { 240 t.Fatal("Store.New() error =", err) 241 } 242 defer dstOutside.Close() 243 if err := oras.CopyGraph(ctx, src, dstOutside, manifestDesc, oras.DefaultCopyGraphOptions); err == nil { 244 t.Error("oras.CopyGraph() error = nil, wantErr ", true) 245 } 246 }