...

Source file src/github.com/containerd/continuity/fs/copy_unix_test.go

Documentation: github.com/containerd/continuity/fs

     1  //go:build linux || darwin
     2  // +build linux darwin
     3  
     4  /*
     5     Copyright The containerd Authors.
     6  
     7     Licensed under the Apache License, Version 2.0 (the "License");
     8     you may not use this file except in compliance with the License.
     9     You may obtain a copy of the License at
    10  
    11         http://www.apache.org/licenses/LICENSE-2.0
    12  
    13     Unless required by applicable law or agreed to in writing, software
    14     distributed under the License is distributed on an "AS IS" BASIS,
    15     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16     See the License for the specific language governing permissions and
    17     limitations under the License.
    18  */
    19  
    20  package fs
    21  
    22  import (
    23  	"os"
    24  	"path/filepath"
    25  	"runtime"
    26  	"syscall"
    27  	"testing"
    28  
    29  	"github.com/containerd/continuity/fs/fstest"
    30  	"github.com/containerd/continuity/sysx"
    31  	"golang.org/x/sys/unix"
    32  )
    33  
    34  func assertXAttr(t *testing.T, dir, xattr, xval string, xerr error) {
    35  	t.Helper()
    36  	value, err := sysx.Getxattr(dir, xattr)
    37  	switch {
    38  	case xerr == nil && err != nil:
    39  		t.Errorf("err=%v; expected val=%s", err, xval)
    40  	case xerr == nil && err == nil && string(value) != xval:
    41  		t.Errorf("val=%s; expected val=%s", value, xval)
    42  	case xerr != nil && err != xerr:
    43  		t.Errorf("val=%s, err=%v; expected err=%v", value, err, xerr)
    44  	}
    45  }
    46  
    47  func TestCopyDirWithXAttrExcludes(t *testing.T) {
    48  	src := t.TempDir()
    49  	if err := fstest.Apply(
    50  		fstest.SetXAttr(".", "user.test-1", "one"),
    51  		fstest.SetXAttr(".", "user.test-2", "two"),
    52  		fstest.SetXAttr(".", "user.test-x", "three-four-five"),
    53  	).Apply(src); err != nil {
    54  		t.Fatal(err)
    55  	}
    56  
    57  	t.Run("none", func(t *testing.T) {
    58  		dst := t.TempDir()
    59  		err := CopyDir(dst, src, WithXAttrExclude())
    60  		if err != nil {
    61  			t.Fatal(err)
    62  		}
    63  		assertXAttr(t, dst, "user.test-1", "one", nil)
    64  		assertXAttr(t, dst, "user.test-2", "two", nil)
    65  		assertXAttr(t, dst, "user.test-x", "three-four-five", nil)
    66  	})
    67  
    68  	t.Run("some", func(t *testing.T) {
    69  		dst := t.TempDir()
    70  		err := CopyDir(dst, src, WithXAttrExclude("user.test-x"))
    71  		if err != nil {
    72  			t.Fatal(err)
    73  		}
    74  		assertXAttr(t, dst, "user.test-1", "one", nil)
    75  		assertXAttr(t, dst, "user.test-2", "two", nil)
    76  		assertXAttr(t, dst, "user.test-x", "", sysx.ENODATA)
    77  	})
    78  }
    79  
    80  func TestCopyIrregular(t *testing.T) {
    81  	var prepared int
    82  	prepareSrc := func(src string) {
    83  		f0Pipe := filepath.Join(src, "f0.pipe")
    84  		if err := unix.Mkfifo(f0Pipe, 0o600); err != nil {
    85  			t.Fatal(err)
    86  		}
    87  		prepared++
    88  		f1Normal := filepath.Join(src, "f1.normal")
    89  		if err := os.WriteFile(f1Normal, []byte("content of f1.normal"), 0o600); err != nil {
    90  			t.Fatal(err)
    91  		}
    92  		prepared++
    93  		if runtime.GOOS != "darwin" {
    94  			f2Socket := filepath.Join(src, "f2.sock")
    95  			if err := unix.Mknod(f2Socket, 0o600|unix.S_IFSOCK, 0); err != nil {
    96  				t.Fatal(err)
    97  			}
    98  			prepared++
    99  		}
   100  		f3Dev := filepath.Join(src, "f3.dev")
   101  		if err := unix.Mknod(f3Dev, 0o600|unix.S_IFCHR, 42); err != nil {
   102  			t.Logf("skipping testing S_IFCHR: %v", err)
   103  		} else {
   104  			prepared++
   105  		}
   106  	}
   107  
   108  	verifyDst := func(dst string) {
   109  		entries, err := os.ReadDir(dst)
   110  		if err != nil {
   111  			t.Fatal(err)
   112  		}
   113  		var verified int
   114  		for _, f := range entries {
   115  			name := f.Name()
   116  			full := filepath.Join(dst, name)
   117  			fi, err := os.Stat(full)
   118  			if err != nil {
   119  				t.Fatal(err)
   120  			}
   121  			mode := fi.Mode()
   122  			switch name {
   123  			case "f0.pipe":
   124  				if mode&os.ModeNamedPipe != os.ModeNamedPipe {
   125  					t.Fatalf("unexpected mode of %s: %v", name, mode)
   126  				}
   127  			case "f1.normal":
   128  				b, err := os.ReadFile(full)
   129  				if err != nil {
   130  					t.Fatal(err)
   131  				}
   132  				if string(b) != "content of f1.normal" {
   133  					t.Fatalf("unexpected content of %s: %q", name, string(b))
   134  				}
   135  			case "f2.sock":
   136  				if mode&os.ModeSocket != os.ModeSocket {
   137  					t.Fatalf("unexpected mode of %s: %v", name, mode)
   138  				}
   139  			case "f3.dev":
   140  				if mode&os.ModeDevice != os.ModeDevice {
   141  					t.Fatalf("unexpected mode of %s: %v", name, mode)
   142  				}
   143  				sys, ok := fi.Sys().(*syscall.Stat_t)
   144  				if !ok {
   145  					t.Fatalf("unexpected type: %v", fi.Sys())
   146  				}
   147  				if sys.Rdev != 42 {
   148  					t.Fatalf("unexpected rdev of %s: %d", name, sys.Rdev)
   149  				}
   150  			}
   151  			verified++
   152  		}
   153  		if verified != prepared {
   154  			t.Fatalf("prepared %d files, verified %d files", prepared, verified)
   155  		}
   156  	}
   157  
   158  	src := t.TempDir()
   159  	dst := t.TempDir()
   160  	prepareSrc(src)
   161  	if err := CopyDir(dst, src); err != nil {
   162  		t.Fatal(err)
   163  	}
   164  	verifyDst(dst)
   165  }
   166  

View as plain text