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  }