Source file src/os/tempfile_test.go

     1  // Copyright 2010 The Go 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  package os_test
     6  
     7  import (
     8  	"errors"
     9  	"io/fs"
    10  	. "os"
    11  	"path/filepath"
    12  	"regexp"
    13  	"strings"
    14  	"testing"
    15  )
    16  
    17  func TestCreateTemp(t *testing.T) {
    18  	t.Parallel()
    19  
    20  	dir, err := MkdirTemp("", "TestCreateTempBadDir")
    21  	if err != nil {
    22  		t.Fatal(err)
    23  	}
    24  	defer RemoveAll(dir)
    25  
    26  	nonexistentDir := filepath.Join(dir, "_not_exists_")
    27  	f, err := CreateTemp(nonexistentDir, "foo")
    28  	if f != nil || err == nil {
    29  		t.Errorf("CreateTemp(%q, `foo`) = %v, %v", nonexistentDir, f, err)
    30  	}
    31  }
    32  
    33  func TestCreateTempPattern(t *testing.T) {
    34  	t.Parallel()
    35  
    36  	tests := []struct{ pattern, prefix, suffix string }{
    37  		{"tempfile_test", "tempfile_test", ""},
    38  		{"tempfile_test*", "tempfile_test", ""},
    39  		{"tempfile_test*xyz", "tempfile_test", "xyz"},
    40  	}
    41  	for _, test := range tests {
    42  		f, err := CreateTemp("", test.pattern)
    43  		if err != nil {
    44  			t.Errorf("CreateTemp(..., %q) error: %v", test.pattern, err)
    45  			continue
    46  		}
    47  		defer Remove(f.Name())
    48  		base := filepath.Base(f.Name())
    49  		f.Close()
    50  		if !(strings.HasPrefix(base, test.prefix) && strings.HasSuffix(base, test.suffix)) {
    51  			t.Errorf("CreateTemp pattern %q created bad name %q; want prefix %q & suffix %q",
    52  				test.pattern, base, test.prefix, test.suffix)
    53  		}
    54  	}
    55  }
    56  
    57  func TestCreateTempBadPattern(t *testing.T) {
    58  	t.Parallel()
    59  
    60  	tmpDir, err := MkdirTemp("", t.Name())
    61  	if err != nil {
    62  		t.Fatal(err)
    63  	}
    64  	defer RemoveAll(tmpDir)
    65  
    66  	const sep = string(PathSeparator)
    67  	tests := []struct {
    68  		pattern string
    69  		wantErr bool
    70  	}{
    71  		{"ioutil*test", false},
    72  		{"tempfile_test*foo", false},
    73  		{"tempfile_test" + sep + "foo", true},
    74  		{"tempfile_test*" + sep + "foo", true},
    75  		{"tempfile_test" + sep + "*foo", true},
    76  		{sep + "tempfile_test" + sep + "*foo", true},
    77  		{"tempfile_test*foo" + sep, true},
    78  	}
    79  	for _, tt := range tests {
    80  		t.Run(tt.pattern, func(t *testing.T) {
    81  			tmpfile, err := CreateTemp(tmpDir, tt.pattern)
    82  			if tmpfile != nil {
    83  				defer tmpfile.Close()
    84  			}
    85  			if tt.wantErr {
    86  				if err == nil {
    87  					t.Errorf("CreateTemp(..., %#q) succeeded, expected error", tt.pattern)
    88  				}
    89  				if !errors.Is(err, ErrPatternHasSeparator) {
    90  					t.Errorf("CreateTemp(..., %#q): %v, expected ErrPatternHasSeparator", tt.pattern, err)
    91  				}
    92  			} else if err != nil {
    93  				t.Errorf("CreateTemp(..., %#q): %v", tt.pattern, err)
    94  			}
    95  		})
    96  	}
    97  }
    98  
    99  func TestMkdirTemp(t *testing.T) {
   100  	t.Parallel()
   101  
   102  	name, err := MkdirTemp("/_not_exists_", "foo")
   103  	if name != "" || err == nil {
   104  		t.Errorf("MkdirTemp(`/_not_exists_`, `foo`) = %v, %v", name, err)
   105  	}
   106  
   107  	tests := []struct {
   108  		pattern                string
   109  		wantPrefix, wantSuffix string
   110  	}{
   111  		{"tempfile_test", "tempfile_test", ""},
   112  		{"tempfile_test*", "tempfile_test", ""},
   113  		{"tempfile_test*xyz", "tempfile_test", "xyz"},
   114  	}
   115  
   116  	dir := filepath.Clean(TempDir())
   117  
   118  	runTestMkdirTemp := func(t *testing.T, pattern, wantRePat string) {
   119  		name, err := MkdirTemp(dir, pattern)
   120  		if name == "" || err != nil {
   121  			t.Fatalf("MkdirTemp(dir, `tempfile_test`) = %v, %v", name, err)
   122  		}
   123  		defer Remove(name)
   124  
   125  		re := regexp.MustCompile(wantRePat)
   126  		if !re.MatchString(name) {
   127  			t.Errorf("MkdirTemp(%q, %q) created bad name\n\t%q\ndid not match pattern\n\t%q", dir, pattern, name, wantRePat)
   128  		}
   129  	}
   130  
   131  	for _, tt := range tests {
   132  		t.Run(tt.pattern, func(t *testing.T) {
   133  			wantRePat := "^" + regexp.QuoteMeta(filepath.Join(dir, tt.wantPrefix)) + "[0-9]+" + regexp.QuoteMeta(tt.wantSuffix) + "$"
   134  			runTestMkdirTemp(t, tt.pattern, wantRePat)
   135  		})
   136  	}
   137  
   138  	// Separately testing "*xyz" (which has no prefix). That is when constructing the
   139  	// pattern to assert on, as in the previous loop, using filepath.Join for an empty
   140  	// prefix filepath.Join(dir, ""), produces the pattern:
   141  	//     ^<DIR>[0-9]+xyz$
   142  	// yet we just want to match
   143  	//     "^<DIR>/[0-9]+xyz"
   144  	t.Run("*xyz", func(t *testing.T) {
   145  		wantRePat := "^" + regexp.QuoteMeta(filepath.Join(dir)) + regexp.QuoteMeta(string(filepath.Separator)) + "[0-9]+xyz$"
   146  		runTestMkdirTemp(t, "*xyz", wantRePat)
   147  	})
   148  }
   149  
   150  // test that we return a nice error message if the dir argument to TempDir doesn't
   151  // exist (or that it's empty and TempDir doesn't exist)
   152  func TestMkdirTempBadDir(t *testing.T) {
   153  	t.Parallel()
   154  
   155  	dir, err := MkdirTemp("", "MkdirTempBadDir")
   156  	if err != nil {
   157  		t.Fatal(err)
   158  	}
   159  	defer RemoveAll(dir)
   160  
   161  	badDir := filepath.Join(dir, "not-exist")
   162  	_, err = MkdirTemp(badDir, "foo")
   163  	if pe, ok := err.(*fs.PathError); !ok || !IsNotExist(err) || pe.Path != badDir {
   164  		t.Errorf("TempDir error = %#v; want PathError for path %q satisfying IsNotExist", err, badDir)
   165  	}
   166  }
   167  
   168  func TestMkdirTempBadPattern(t *testing.T) {
   169  	t.Parallel()
   170  
   171  	tmpDir, err := MkdirTemp("", t.Name())
   172  	if err != nil {
   173  		t.Fatal(err)
   174  	}
   175  	defer RemoveAll(tmpDir)
   176  
   177  	const sep = string(PathSeparator)
   178  	tests := []struct {
   179  		pattern string
   180  		wantErr bool
   181  	}{
   182  		{"ioutil*test", false},
   183  		{"tempfile_test*foo", false},
   184  		{"tempfile_test" + sep + "foo", true},
   185  		{"tempfile_test*" + sep + "foo", true},
   186  		{"tempfile_test" + sep + "*foo", true},
   187  		{sep + "tempfile_test" + sep + "*foo", true},
   188  		{"tempfile_test*foo" + sep, true},
   189  	}
   190  	for _, tt := range tests {
   191  		t.Run(tt.pattern, func(t *testing.T) {
   192  			_, err := MkdirTemp(tmpDir, tt.pattern)
   193  			if tt.wantErr {
   194  				if err == nil {
   195  					t.Errorf("MkdirTemp(..., %#q) succeeded, expected error", tt.pattern)
   196  				}
   197  				if !errors.Is(err, ErrPatternHasSeparator) {
   198  					t.Errorf("MkdirTemp(..., %#q): %v, expected ErrPatternHasSeparator", tt.pattern, err)
   199  				}
   200  			} else if err != nil {
   201  				t.Errorf("MkdirTemp(..., %#q): %v", tt.pattern, err)
   202  			}
   203  		})
   204  	}
   205  }
   206  

View as plain text