github.com/drud/ddev@v1.21.5-alpha1.0.20230226034409-94fcc4b94453/pkg/fileutil/files_test.go (about)

     1  package fileutil_test
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/stretchr/testify/require"
     6  	"os"
     7  	"path/filepath"
     8  	"runtime"
     9  	"testing"
    10  
    11  	"github.com/drud/ddev/pkg/fileutil"
    12  	"github.com/drud/ddev/pkg/testcommon"
    13  	asrt "github.com/stretchr/testify/assert"
    14  )
    15  
    16  var testFileLocation = "testdata/regular_file"
    17  
    18  // TestCopyDir tests copying a directory.
    19  func TestCopyDir(t *testing.T) {
    20  	assert := asrt.New(t)
    21  	sourceDir := testcommon.CreateTmpDir("TestCopyDir_source")
    22  	targetDir := testcommon.CreateTmpDir("TestCopyDir_target")
    23  
    24  	subdir := filepath.Join(sourceDir, "some_content")
    25  	err := os.Mkdir(subdir, 0755)
    26  	assert.NoError(err)
    27  
    28  	// test source not a directory
    29  	err = fileutil.CopyDir(testFileLocation, sourceDir)
    30  	assert.Error(err)
    31  	if err != nil {
    32  		assert.Contains(err.Error(), fmt.Sprintf("CopyDir: source directory %s is not a directory", filepath.Join(testFileLocation)))
    33  	}
    34  
    35  	// test destination exists
    36  	err = fileutil.CopyDir(sourceDir, targetDir)
    37  	assert.Error(err)
    38  	if err != nil {
    39  		assert.Contains(err.Error(), fmt.Sprintf("CopyDir: destination %s already exists", filepath.Join(targetDir)))
    40  	}
    41  	err = os.RemoveAll(subdir)
    42  	assert.NoError(err)
    43  
    44  	// copy a directory and validate that we find files elsewhere
    45  	err = os.RemoveAll(targetDir)
    46  	assert.NoError(err)
    47  
    48  	file, err := os.Create(filepath.Join(sourceDir, "touch1.txt"))
    49  	assert.NoError(err)
    50  	_ = file.Close()
    51  	file, err = os.Create(filepath.Join(sourceDir, "touch2.txt"))
    52  	assert.NoError(err)
    53  	_ = file.Close()
    54  
    55  	err = fileutil.CopyDir(sourceDir, targetDir)
    56  	assert.NoError(err)
    57  	assert.True(fileutil.FileExists(filepath.Join(targetDir, "touch1.txt")))
    58  	assert.True(fileutil.FileExists(filepath.Join(targetDir, "touch2.txt")))
    59  
    60  	err = os.RemoveAll(sourceDir)
    61  	assert.NoError(err)
    62  	err = os.RemoveAll(targetDir)
    63  	assert.NoError(err)
    64  
    65  }
    66  
    67  // TestCopyFile tests copying a file.
    68  func TestCopyFile(t *testing.T) {
    69  	assert := asrt.New(t)
    70  	tmpTargetDir := testcommon.CreateTmpDir("TestCopyFile")
    71  	tmpTargetFile := filepath.Join(tmpTargetDir, filepath.Base(testFileLocation))
    72  
    73  	err := fileutil.CopyFile(testFileLocation, tmpTargetFile)
    74  	assert.NoError(err)
    75  
    76  	file, err := os.Stat(tmpTargetFile)
    77  	assert.NoError(err)
    78  
    79  	if err != nil {
    80  		assert.False(file.IsDir())
    81  	}
    82  	err = os.RemoveAll(tmpTargetDir)
    83  	assert.NoError(err)
    84  }
    85  
    86  // TestPurgeDirectory tests removal of directory contents without removing
    87  // the directory itself.
    88  func TestPurgeDirectory(t *testing.T) {
    89  	assert := asrt.New(t)
    90  	tmpPurgeDir := testcommon.CreateTmpDir("TestPurgeDirectory")
    91  	tmpPurgeFile := filepath.Join(tmpPurgeDir, "regular_file")
    92  	tmpPurgeSubFile := filepath.Join(tmpPurgeDir, "subdir", "regular_file")
    93  
    94  	err := fileutil.CopyFile(testFileLocation, tmpPurgeFile)
    95  	assert.NoError(err)
    96  
    97  	err = os.Mkdir(filepath.Join(tmpPurgeDir, "subdir"), 0755)
    98  	assert.NoError(err)
    99  
   100  	err = fileutil.CopyFile(testFileLocation, tmpPurgeSubFile)
   101  	assert.NoError(err)
   102  
   103  	err = os.Chmod(tmpPurgeSubFile, 0444)
   104  	assert.NoError(err)
   105  
   106  	err = fileutil.PurgeDirectory(tmpPurgeDir)
   107  	assert.NoError(err)
   108  
   109  	assert.True(fileutil.FileExists(tmpPurgeDir))
   110  	assert.False(fileutil.FileExists(tmpPurgeFile))
   111  	assert.False(fileutil.FileExists(tmpPurgeSubFile))
   112  }
   113  
   114  // TestFgrepStringInFile tests the FgrepStringInFile utility function.
   115  func TestFgrepStringInFile(t *testing.T) {
   116  	assert := asrt.New(t)
   117  	result, err := fileutil.FgrepStringInFile("testdata/fgrep_has_positive_contents.txt", "some needle we're looking for")
   118  	assert.NoError(err)
   119  	assert.True(result)
   120  	result, err = fileutil.FgrepStringInFile("testdata/fgrep_negative_contents.txt", "some needle we're looking for")
   121  	assert.NoError(err)
   122  	assert.False(result)
   123  }
   124  
   125  // TestListFilesInDir makes sure the files we have in testfiles are properly enumerated
   126  func TestListFilesInDir(t *testing.T) {
   127  	assert := asrt.New(t)
   128  
   129  	fileList, err := fileutil.ListFilesInDir("testdata/testfiles/")
   130  	assert.NoError(err)
   131  	assert.True(len(fileList) == 2)
   132  	assert.Contains(fileList[0], "one.txt")
   133  	assert.Contains(fileList[1], "two.txt")
   134  }
   135  
   136  // TestReplaceStringInFile tests the ReplaceStringInFile utility function.
   137  func TestReplaceStringInFile(t *testing.T) {
   138  	assert := asrt.New(t)
   139  	tmp, err := os.MkdirTemp("", "")
   140  	assert.NoError(err)
   141  	newFilePath := filepath.Join(tmp, "newfile.txt")
   142  	err = fileutil.ReplaceStringInFile("some needle we're looking for", "specialJUNKPattern", "testdata/fgrep_has_positive_contents.txt", newFilePath)
   143  	assert.NoError(err)
   144  	found, err := fileutil.FgrepStringInFile(newFilePath, "specialJUNKPattern")
   145  	assert.NoError(err)
   146  	assert.True(found)
   147  }
   148  
   149  // TestFindSimulatedXsymSymlinks tests FindSimulatedXsymSymlinks
   150  func TestFindSimulatedXsymSymlinks(t *testing.T) {
   151  	assert := asrt.New(t)
   152  	testDir, _ := os.Getwd()
   153  	targetDir := filepath.Join(testDir, "testdata", "symlinks")
   154  	links, err := fileutil.FindSimulatedXsymSymlinks(targetDir)
   155  	assert.NoError(err)
   156  	assert.Len(links, 8)
   157  }
   158  
   159  // TestReplaceSimulatedXsymSymlinks tries a number of symlinks to make
   160  // sure we can parse and replace symlinks.
   161  func TestReplaceSimulatedXsymSymlinks(t *testing.T) {
   162  	testDir, _ := os.Getwd()
   163  	assert := asrt.New(t)
   164  	if runtime.GOOS == "windows" && !fileutil.CanCreateSymlinks() {
   165  		t.Skip("Skipping on Windows because test machine can't create symlnks")
   166  	}
   167  	sourceDir := filepath.Join(testDir, "testdata", "symlinks")
   168  	targetDir := testcommon.CreateTmpDir("TestReplaceSimulated")
   169  	//nolint: errcheck
   170  	defer os.RemoveAll(targetDir)
   171  	err := os.Chdir(targetDir)
   172  	assert.NoError(err)
   173  
   174  	// Make sure we leave the testDir as we found it..
   175  	//nolint: errcheck
   176  	defer os.Chdir(testDir)
   177  	// CopyDir skips real symlinks, but we only care about simulated ones, so it's OK
   178  	err = fileutil.CopyDir(sourceDir, filepath.Join(targetDir, "symlinks"))
   179  	assert.NoError(err)
   180  	links, err := fileutil.FindSimulatedXsymSymlinks(targetDir)
   181  	assert.NoError(err)
   182  	assert.Len(links, 8)
   183  	err = fileutil.ReplaceSimulatedXsymSymlinks(links)
   184  	assert.NoError(err)
   185  
   186  	for _, link := range links {
   187  		fi, err := os.Stat(link.LinkLocation)
   188  		assert.NoError(err)
   189  		linkFi, err := os.Lstat(link.LinkLocation)
   190  		assert.NoError(err)
   191  		if err == nil && fi != nil && !fi.IsDir() {
   192  			// Read the symlink as a file. It should resolve with the actual content of target
   193  			contents, err := os.ReadFile(link.LinkLocation)
   194  			assert.NoError(err)
   195  			expectedContent := "textfile " + filepath.Base(link.LinkTarget) + "\n"
   196  			assert.Equal(expectedContent, string(contents))
   197  		}
   198  		// Now stat the link and make sure it's a link and points where it should
   199  		if linkFi.Mode()&os.ModeSymlink != 0 {
   200  			targetFile, err := os.Readlink(link.LinkLocation)
   201  			assert.NoError(err)
   202  			assert.Equal(link.LinkTarget, targetFile)
   203  			_ = targetFile
   204  		}
   205  	}
   206  
   207  }
   208  
   209  // TestIsSameFile tests the IsSameFile utility function.
   210  func TestIsSameFile(t *testing.T) {
   211  	assert := asrt.New(t)
   212  
   213  	tmpDir, err := testcommon.OsTempDir()
   214  	assert.NoError(err)
   215  
   216  	dirSymlink, err := filepath.Abs(filepath.Join(tmpDir, fileutil.RandomFilenameBase()))
   217  	require.NoError(t, err)
   218  	testdataAbsolute, err := filepath.Abs("testdata")
   219  	require.NoError(t, err)
   220  	err = os.Symlink(testdataAbsolute, dirSymlink)
   221  	assert.NoError(err)
   222  	//nolint: errcheck
   223  	defer os.Remove(dirSymlink)
   224  
   225  	// At this point, dirSymLink and "testdata" should be equivalent
   226  	isSame, err := fileutil.IsSameFile("testdata", dirSymlink)
   227  	assert.NoError(err)
   228  	assert.True(isSame)
   229  	// Test with files that are equivalent (through symlink)
   230  	isSame, err = fileutil.IsSameFile("testdata/testfiles/one.txt", filepath.Join(dirSymlink, "testfiles", "one.txt"))
   231  	assert.NoError(err)
   232  	assert.True(isSame)
   233  
   234  	// Test files that are *not* equivalent.
   235  	isSame, err = fileutil.IsSameFile("testdata/testfiles/one.txt", "testdata/testfiles/two.txt")
   236  	assert.NoError(err)
   237  	assert.False(isSame)
   238  }