gitee.com/mirrors_u-root/u-root@v7.0.0+incompatible/cmds/core/cp/cp_test.go (about)

     1  // Copyright 2016 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // created by Manoel Vilela <manoel_vilela@engineer.com>
     6  
     7  package main
     8  
     9  import (
    10  	"bytes"
    11  	"fmt"
    12  	"io/ioutil"
    13  	"log"
    14  	"math/rand"
    15  	"os"
    16  	"path/filepath"
    17  	"strings"
    18  	"testing"
    19  
    20  	"github.com/u-root/u-root/pkg/cp"
    21  	"github.com/u-root/u-root/pkg/cp/cmp"
    22  )
    23  
    24  const (
    25  	maxSizeFile = 1000
    26  	maxDirDepth = 5
    27  	maxFiles    = 5
    28  )
    29  
    30  // resetFlags is used to reset the cp flags to default
    31  func resetFlags() {
    32  	flags.recursive = false
    33  	flags.ask = false
    34  	flags.force = false
    35  	flags.verbose = false
    36  	flags.noFollowSymlinks = false
    37  }
    38  
    39  // randomFile create a random file with random content
    40  func randomFile(fpath, prefix string) (*os.File, error) {
    41  	f, err := ioutil.TempFile(fpath, prefix)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  	// generate random content for files
    46  	bytes := []byte{}
    47  	for i := 0; i < rand.Intn(maxSizeFile); i++ {
    48  		bytes = append(bytes, byte(i))
    49  	}
    50  	f.Write(bytes)
    51  
    52  	return f, nil
    53  }
    54  
    55  // createFilesTree create a random files tree
    56  func createFilesTree(root string, maxDepth, depth int) error {
    57  	// create more one dir if don't achieve the maxDepth
    58  	if depth < maxDepth {
    59  		newDir, err := ioutil.TempDir(root, fmt.Sprintf("cpdir_%d_", depth))
    60  		if err != nil {
    61  			return err
    62  		}
    63  
    64  		if err = createFilesTree(newDir, maxDepth, depth+1); err != nil {
    65  			return err
    66  		}
    67  	}
    68  	// generate random files
    69  	for i := 0; i < maxFiles; i++ {
    70  		f, err := randomFile(root, fmt.Sprintf("cpfile_%d_", i))
    71  		if err != nil {
    72  			return err
    73  		}
    74  		f.Close()
    75  	}
    76  
    77  	return nil
    78  }
    79  
    80  // TestCpsSimple make a simple test for copy file-to-file
    81  // cmd-line equivalent: cp file file-copy
    82  func TestCpSimple(t *testing.T) {
    83  	tempDir, err := ioutil.TempDir("", "TestCpSimple")
    84  	if err != nil {
    85  		t.Fatal(err)
    86  	}
    87  	defer os.RemoveAll(tempDir)
    88  
    89  	f, err := randomFile(tempDir, "src-")
    90  	if err != nil {
    91  		t.Fatalf("cannot create a random file: %v", err)
    92  	}
    93  	defer f.Close()
    94  
    95  	srcf := f.Name()
    96  	dstf := filepath.Join(tempDir, "destination")
    97  
    98  	if err := cpArgs([]string{srcf, dstf}); err != nil {
    99  		t.Fatalf("copy(%q -> %q) = %v, want nil", srcf, dstf, err)
   100  	}
   101  	if err := cmp.IsEqualTree(cp.Default, srcf, dstf); err != nil {
   102  		t.Fatalf("copy(%q -> %q): file trees not equal: %v", srcf, dstf, err)
   103  	}
   104  }
   105  
   106  // TestCpSrcDirectory tests copying source to destination without recursive
   107  // cmd-line equivalent: cp ~/dir ~/dir2
   108  func TestCpSrcDirectory(t *testing.T) {
   109  	flags.recursive = false
   110  	defer resetFlags()
   111  
   112  	tempDir, err := ioutil.TempDir("", "TestCpSrcDirectory")
   113  	if err != nil {
   114  		t.Fatal(err)
   115  	}
   116  	defer os.RemoveAll(tempDir)
   117  
   118  	tempDirTwo, err := ioutil.TempDir("", "TestCpSrcDirectoryTwo")
   119  	if err != nil {
   120  		t.Fatal(err)
   121  	}
   122  	defer os.RemoveAll(tempDirTwo)
   123  
   124  	// capture log output to verify
   125  	var logBytes bytes.Buffer
   126  	log.SetOutput(&logBytes)
   127  
   128  	if err := cpArgs([]string{tempDir, tempDirTwo}); err != nil {
   129  		t.Fatalf("copy(%q -> %q) = %v, want nil", tempDir, tempDirTwo, err)
   130  	}
   131  
   132  	outString := fmt.Sprintf("cp: -r not specified, omitting directory %s", tempDir)
   133  	capturedString := logBytes.String()
   134  	if !strings.Contains(capturedString, outString) {
   135  		t.Fatalf("copy(%q -> %q) = %v, want %v", tempDir, tempDirTwo, capturedString, outString)
   136  	}
   137  }
   138  
   139  // TestCpRecursive tests the recursive mode copy
   140  // Copy dir hierarchies src-dir to dst-dir
   141  // whose src-dir and dst-dir already exists
   142  // cmd-line equivalent: $ cp -R src-dir/ dst-dir/
   143  func TestCpRecursive(t *testing.T) {
   144  	flags.recursive = true
   145  	defer resetFlags()
   146  
   147  	tempDir, err := ioutil.TempDir("", "TestCpRecursive")
   148  	if err != nil {
   149  		t.Fatal(err)
   150  	}
   151  	defer os.RemoveAll(tempDir)
   152  
   153  	srcDir := filepath.Join(tempDir, "src")
   154  	if err := os.Mkdir(srcDir, 0755); err != nil {
   155  		t.Fatal(err)
   156  	}
   157  	dstDir := filepath.Join(tempDir, "dst-exists")
   158  	if err := os.Mkdir(dstDir, 0755); err != nil {
   159  		t.Fatal(err)
   160  	}
   161  
   162  	if err = createFilesTree(srcDir, maxDirDepth, 0); err != nil {
   163  		t.Fatalf("cannot create files tree on directory %q: %v", srcDir, err)
   164  	}
   165  
   166  	t.Run("existing-dst-dir", func(t *testing.T) {
   167  		if err := cpArgs([]string{srcDir, dstDir}); err != nil {
   168  			t.Fatalf("cp(%q -> %q) = %v, want nil", srcDir, dstDir, err)
   169  		}
   170  		// Because dstDir already existed, a new dir was created inside it.
   171  		realDestination := filepath.Join(dstDir, filepath.Base(srcDir))
   172  		if err := cmp.IsEqualTree(cp.Default, srcDir, realDestination); err != nil {
   173  			t.Fatalf("copy(%q -> %q): file trees not equal: %v", srcDir, realDestination, err)
   174  		}
   175  	})
   176  
   177  	t.Run("non-existing-dst-dir", func(t *testing.T) {
   178  		notExistDstDir := filepath.Join(tempDir, "dst-does-not-exist")
   179  		if err := cpArgs([]string{srcDir, notExistDstDir}); err != nil {
   180  			t.Fatalf("cp(%q -> %q) = %v, want nil", srcDir, notExistDstDir, err)
   181  		}
   182  
   183  		if err := cmp.IsEqualTree(cp.Default, srcDir, notExistDstDir); err != nil {
   184  			t.Fatalf("copy(%q -> %q): file trees not equal: %v", srcDir, notExistDstDir, err)
   185  		}
   186  	})
   187  }
   188  
   189  // Other test to verify the CopyRecursive
   190  // whose dir$n and dst-dir already exists
   191  // cmd-line equivalent: $ cp -R dir1/ dir2/ dir3/ dst-dir/
   192  //
   193  // dst-dir will content dir{1, 3}
   194  // $ dst-dir/
   195  // ..	dir1/
   196  // ..	dir2/
   197  // ..   dir3/
   198  func TestCpRecursiveMultiple(t *testing.T) {
   199  	flags.recursive = true
   200  	defer resetFlags()
   201  	tempDir, err := ioutil.TempDir("", "TestCpRecursiveMultiple")
   202  	if err != nil {
   203  		t.Fatal(err)
   204  	}
   205  	defer os.RemoveAll(tempDir)
   206  
   207  	dstTest := filepath.Join(tempDir, "destination")
   208  	if err := os.Mkdir(dstTest, 0755); err != nil {
   209  		t.Fatalf("Failed on build directory %v: %v", dstTest, err)
   210  	}
   211  
   212  	// create multiple random directories sources
   213  	srcDirs := []string{}
   214  	for i := 0; i < maxDirDepth; i++ {
   215  		srcTest, err := ioutil.TempDir(tempDir, "src-")
   216  		if err != nil {
   217  			t.Fatalf("Failed on build directory %v: %v\n", srcTest, err)
   218  		}
   219  		if err = createFilesTree(srcTest, maxDirDepth, 0); err != nil {
   220  			t.Fatalf("cannot create files tree on directory %v: %v", srcTest, err)
   221  		}
   222  
   223  		srcDirs = append(srcDirs, srcTest)
   224  
   225  	}
   226  
   227  	args := srcDirs
   228  	args = append(args, dstTest)
   229  	if err := cpArgs(args); err != nil {
   230  		t.Fatalf("cp %q exit with error: %v", args, err)
   231  	}
   232  	for _, src := range srcDirs {
   233  		_, srcFile := filepath.Split(src)
   234  
   235  		dst := filepath.Join(dstTest, srcFile)
   236  		if err := cmp.IsEqualTree(cp.Default, src, dst); err != nil {
   237  			t.Fatalf("The copy %q -> %q failed: %v", src, dst, err)
   238  		}
   239  	}
   240  }
   241  
   242  // using -P don't follow symlinks, create other symlink
   243  // cmd-line equivalent: $ cp -P symlink symlink-copy
   244  func TestCpSymlink(t *testing.T) {
   245  	tempDir, err := ioutil.TempDir("", "TestCpSymlink")
   246  	if err != nil {
   247  		t.Fatal(err)
   248  	}
   249  	defer os.RemoveAll(tempDir)
   250  
   251  	f, err := randomFile(tempDir, "src-")
   252  	if err != nil {
   253  		t.Fatalf("cannot create a random file: %v", err)
   254  	}
   255  	defer f.Close()
   256  
   257  	srcFpath := f.Name()
   258  	srcFname := filepath.Base(srcFpath)
   259  
   260  	newName := filepath.Join(tempDir, srcFname+"_link")
   261  	if err := os.Symlink(srcFname, newName); err != nil {
   262  		t.Fatalf("cannot create a link %q with target %q: %v", newName, srcFname, err)
   263  	}
   264  
   265  	t.Run("no-follow-symlink", func(t *testing.T) {
   266  		defer resetFlags()
   267  		flags.noFollowSymlinks = true
   268  
   269  		dst := filepath.Join(tempDir, "dst-no-follow")
   270  		if err := cpArgs([]string{newName, dst}); err != nil {
   271  			t.Fatalf("cp(%q -> %q) = %v, want nil", newName, dst, err)
   272  		}
   273  		if err := cmp.IsEqualTree(cp.NoFollowSymlinks, newName, dst); err != nil {
   274  			t.Fatalf("The copy %q -> %q failed: %v", newName, dst, err)
   275  		}
   276  	})
   277  
   278  	t.Run("follow-symlink", func(t *testing.T) {
   279  		defer resetFlags()
   280  		flags.noFollowSymlinks = false
   281  
   282  		dst := filepath.Join(tempDir, "dst-follow")
   283  		if err := cpArgs([]string{newName, dst}); err != nil {
   284  			t.Fatalf("cp(%q -> %q) = %v, want nil", newName, dst, err)
   285  		}
   286  		if err := cmp.IsEqualTree(cp.Default, newName, dst); err != nil {
   287  			t.Fatalf("The copy %q -> %q failed: %v", newName, dst, err)
   288  		}
   289  	})
   290  }