...

Source file src/k8s.io/kubernetes/pkg/volume/util/subpath/subpath_windows_test.go

Documentation: k8s.io/kubernetes/pkg/volume/util/subpath

     1  //go:build windows
     2  // +build windows
     3  
     4  /*
     5  Copyright 2017 The Kubernetes 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 subpath
    21  
    22  import (
    23  	"fmt"
    24  	"io/ioutil"
    25  	"os"
    26  	"os/exec"
    27  	"path/filepath"
    28  	"testing"
    29  
    30  	"github.com/stretchr/testify/assert"
    31  )
    32  
    33  func makeLink(link, target string) error {
    34  	if output, err := exec.Command("cmd", "/c", "mklink", "/D", link, target).CombinedOutput(); err != nil {
    35  		return fmt.Errorf("mklink failed: %v, link(%q) target(%q) output: %q", err, link, target, string(output))
    36  	}
    37  	return nil
    38  }
    39  
    40  func TestDoSafeMakeDir(t *testing.T) {
    41  	base, err := ioutil.TempDir("", "TestDoSafeMakeDir")
    42  	if err != nil {
    43  		t.Fatalf(err.Error())
    44  	}
    45  
    46  	defer os.RemoveAll(base)
    47  
    48  	testingVolumePath := filepath.Join(base, "testingVolumePath")
    49  	os.MkdirAll(testingVolumePath, 0755)
    50  	defer os.RemoveAll(testingVolumePath)
    51  
    52  	tests := []struct {
    53  		volumePath    string
    54  		subPath       string
    55  		expectError   bool
    56  		symlinkTarget string
    57  	}{
    58  		{
    59  			volumePath:    testingVolumePath,
    60  			subPath:       ``,
    61  			expectError:   true,
    62  			symlinkTarget: "",
    63  		},
    64  		{
    65  			volumePath:    testingVolumePath,
    66  			subPath:       filepath.Join(testingVolumePath, `x`),
    67  			expectError:   false,
    68  			symlinkTarget: "",
    69  		},
    70  		{
    71  			volumePath:    testingVolumePath,
    72  			subPath:       filepath.Join(testingVolumePath, `a\b\c\d`),
    73  			expectError:   false,
    74  			symlinkTarget: "",
    75  		},
    76  		{
    77  			volumePath:    testingVolumePath,
    78  			subPath:       filepath.Join(testingVolumePath, `symlink`),
    79  			expectError:   false,
    80  			symlinkTarget: base,
    81  		},
    82  		{
    83  			volumePath:    testingVolumePath,
    84  			subPath:       filepath.Join(testingVolumePath, `symlink\c\d`),
    85  			expectError:   true,
    86  			symlinkTarget: "",
    87  		},
    88  		{
    89  			volumePath:    testingVolumePath,
    90  			subPath:       filepath.Join(testingVolumePath, `symlink\y926`),
    91  			expectError:   true,
    92  			symlinkTarget: "",
    93  		},
    94  		{
    95  			volumePath:    testingVolumePath,
    96  			subPath:       filepath.Join(testingVolumePath, `a\b\symlink`),
    97  			expectError:   false,
    98  			symlinkTarget: base,
    99  		},
   100  		{
   101  			volumePath:    testingVolumePath,
   102  			subPath:       filepath.Join(testingVolumePath, `a\x\symlink`),
   103  			expectError:   false,
   104  			symlinkTarget: filepath.Join(testingVolumePath, `a`),
   105  		},
   106  	}
   107  
   108  	for _, test := range tests {
   109  		if len(test.volumePath) > 0 && len(test.subPath) > 0 && len(test.symlinkTarget) > 0 {
   110  			// make all parent sub directories
   111  			if parent := filepath.Dir(test.subPath); parent != "." {
   112  				os.MkdirAll(parent, 0755)
   113  			}
   114  
   115  			// make last element as symlink
   116  			linkPath := test.subPath
   117  			if _, err := os.Stat(linkPath); err != nil && os.IsNotExist(err) {
   118  				if err := makeLink(linkPath, test.symlinkTarget); err != nil {
   119  					t.Fatalf("unexpected error: %v", fmt.Errorf("mklink link(%q) target(%q) error: %q", linkPath, test.symlinkTarget, err))
   120  				}
   121  			}
   122  		}
   123  
   124  		err := doSafeMakeDir(test.subPath, test.volumePath, os.FileMode(0755))
   125  		if test.expectError {
   126  			assert.NotNil(t, err, "Expect error during doSafeMakeDir(%s, %s)", test.subPath, test.volumePath)
   127  			continue
   128  		}
   129  		assert.Nil(t, err, "Expect no error during doSafeMakeDir(%s, %s)", test.subPath, test.volumePath)
   130  		if _, err := os.Stat(test.subPath); os.IsNotExist(err) {
   131  			t.Errorf("subPath should exists after doSafeMakeDir(%s, %s)", test.subPath, test.volumePath)
   132  		}
   133  	}
   134  }
   135  
   136  func TestLockAndCheckSubPath(t *testing.T) {
   137  	base, err := ioutil.TempDir("", "TestLockAndCheckSubPath")
   138  	if err != nil {
   139  		t.Fatalf(err.Error())
   140  	}
   141  
   142  	defer os.RemoveAll(base)
   143  
   144  	testingVolumePath := filepath.Join(base, "testingVolumePath")
   145  
   146  	tests := []struct {
   147  		volumePath          string
   148  		subPath             string
   149  		expectedHandleCount int
   150  		expectError         bool
   151  		symlinkTarget       string
   152  	}{
   153  		{
   154  			volumePath:          `c:\`,
   155  			subPath:             ``,
   156  			expectedHandleCount: 0,
   157  			expectError:         false,
   158  			symlinkTarget:       "",
   159  		},
   160  		{
   161  			volumePath:          ``,
   162  			subPath:             `a`,
   163  			expectedHandleCount: 0,
   164  			expectError:         false,
   165  			symlinkTarget:       "",
   166  		},
   167  		{
   168  			volumePath:          testingVolumePath,
   169  			subPath:             filepath.Join(testingVolumePath, `a`),
   170  			expectedHandleCount: 1,
   171  			expectError:         false,
   172  			symlinkTarget:       "",
   173  		},
   174  		{
   175  			volumePath:          testingVolumePath,
   176  			subPath:             filepath.Join(testingVolumePath, `a\b\c\d`),
   177  			expectedHandleCount: 4,
   178  			expectError:         false,
   179  			symlinkTarget:       "",
   180  		},
   181  		{
   182  			volumePath:          testingVolumePath,
   183  			subPath:             filepath.Join(testingVolumePath, `symlink`),
   184  			expectedHandleCount: 0,
   185  			expectError:         true,
   186  			symlinkTarget:       base,
   187  		},
   188  		{
   189  			volumePath:          testingVolumePath,
   190  			subPath:             filepath.Join(testingVolumePath, `a\b\c\symlink`),
   191  			expectedHandleCount: 0,
   192  			expectError:         true,
   193  			symlinkTarget:       base,
   194  		},
   195  		{
   196  			volumePath:          testingVolumePath,
   197  			subPath:             filepath.Join(testingVolumePath, `a\b\c\d\symlink`),
   198  			expectedHandleCount: 2,
   199  			expectError:         false,
   200  			symlinkTarget:       filepath.Join(testingVolumePath, `a\b`),
   201  		},
   202  	}
   203  
   204  	for _, test := range tests {
   205  		if len(test.volumePath) > 0 && len(test.subPath) > 0 {
   206  			os.MkdirAll(test.volumePath, 0755)
   207  			if len(test.symlinkTarget) == 0 {
   208  				// make all intermediate sub directories
   209  				os.MkdirAll(test.subPath, 0755)
   210  			} else {
   211  				// make all parent sub directories
   212  				if parent := filepath.Dir(test.subPath); parent != "." {
   213  					os.MkdirAll(parent, 0755)
   214  				}
   215  
   216  				// make last element as symlink
   217  				linkPath := test.subPath
   218  				if _, err := os.Stat(linkPath); err != nil && os.IsNotExist(err) {
   219  					if err := makeLink(linkPath, test.symlinkTarget); err != nil {
   220  						t.Fatalf("unexpected error: %v", fmt.Errorf("mklink link(%q) target(%q) error: %q", linkPath, test.symlinkTarget, err))
   221  					}
   222  				}
   223  			}
   224  		}
   225  
   226  		fileHandles, err := lockAndCheckSubPath(test.volumePath, test.subPath)
   227  		unlockPath(fileHandles)
   228  		assert.Equal(t, test.expectedHandleCount, len(fileHandles))
   229  		if test.expectError {
   230  			assert.NotNil(t, err, "Expect error during LockAndCheckSubPath(%s, %s)", test.volumePath, test.subPath)
   231  			continue
   232  		}
   233  		assert.Nil(t, err, "Expect no error during LockAndCheckSubPath(%s, %s)", test.volumePath, test.subPath)
   234  	}
   235  
   236  	// remove dir will happen after closing all file handles
   237  	assert.Nil(t, os.RemoveAll(testingVolumePath), "Expect no error during remove dir %s", testingVolumePath)
   238  }
   239  
   240  func TestLockAndCheckSubPathWithoutSymlink(t *testing.T) {
   241  	base, err := ioutil.TempDir("", "TestLockAndCheckSubPathWithoutSymlink")
   242  	if err != nil {
   243  		t.Fatalf(err.Error())
   244  	}
   245  
   246  	defer os.RemoveAll(base)
   247  
   248  	testingVolumePath := filepath.Join(base, "testingVolumePath")
   249  
   250  	tests := []struct {
   251  		volumePath          string
   252  		subPath             string
   253  		expectedHandleCount int
   254  		expectError         bool
   255  		symlinkTarget       string
   256  	}{
   257  		{
   258  			volumePath:          `c:\`,
   259  			subPath:             ``,
   260  			expectedHandleCount: 0,
   261  			expectError:         false,
   262  			symlinkTarget:       "",
   263  		},
   264  		{
   265  			volumePath:          ``,
   266  			subPath:             `a`,
   267  			expectedHandleCount: 0,
   268  			expectError:         false,
   269  			symlinkTarget:       "",
   270  		},
   271  		{
   272  			volumePath:          testingVolumePath,
   273  			subPath:             filepath.Join(testingVolumePath, `a`),
   274  			expectedHandleCount: 1,
   275  			expectError:         false,
   276  			symlinkTarget:       "",
   277  		},
   278  		{
   279  			volumePath:          testingVolumePath,
   280  			subPath:             filepath.Join(testingVolumePath, `a\b\c\d`),
   281  			expectedHandleCount: 4,
   282  			expectError:         false,
   283  			symlinkTarget:       "",
   284  		},
   285  		{
   286  			volumePath:          testingVolumePath,
   287  			subPath:             filepath.Join(testingVolumePath, `symlink`),
   288  			expectedHandleCount: 1,
   289  			expectError:         true,
   290  			symlinkTarget:       base,
   291  		},
   292  		{
   293  			volumePath:          testingVolumePath,
   294  			subPath:             filepath.Join(testingVolumePath, `a\b\c\symlink`),
   295  			expectedHandleCount: 4,
   296  			expectError:         true,
   297  			symlinkTarget:       base,
   298  		},
   299  		{
   300  			volumePath:          testingVolumePath,
   301  			subPath:             filepath.Join(testingVolumePath, `a\b\c\d\symlink`),
   302  			expectedHandleCount: 5,
   303  			expectError:         true,
   304  			symlinkTarget:       filepath.Join(testingVolumePath, `a\b`),
   305  		},
   306  	}
   307  
   308  	for _, test := range tests {
   309  		if len(test.volumePath) > 0 && len(test.subPath) > 0 {
   310  			os.MkdirAll(test.volumePath, 0755)
   311  			if len(test.symlinkTarget) == 0 {
   312  				// make all intermediate sub directories
   313  				os.MkdirAll(test.subPath, 0755)
   314  			} else {
   315  				// make all parent sub directories
   316  				if parent := filepath.Dir(test.subPath); parent != "." {
   317  					os.MkdirAll(parent, 0755)
   318  				}
   319  
   320  				// make last element as symlink
   321  				linkPath := test.subPath
   322  				if _, err := os.Stat(linkPath); err != nil && os.IsNotExist(err) {
   323  					if err := makeLink(linkPath, test.symlinkTarget); err != nil {
   324  						t.Fatalf("unexpected error: %v", fmt.Errorf("mklink link(%q) target(%q) error: %q", linkPath, test.symlinkTarget, err))
   325  					}
   326  				}
   327  			}
   328  		}
   329  
   330  		fileHandles, err := lockAndCheckSubPathWithoutSymlink(test.volumePath, test.subPath)
   331  		unlockPath(fileHandles)
   332  		assert.Equal(t, test.expectedHandleCount, len(fileHandles))
   333  		if test.expectError {
   334  			assert.NotNil(t, err, "Expect error during LockAndCheckSubPath(%s, %s)", test.volumePath, test.subPath)
   335  			continue
   336  		}
   337  		assert.Nil(t, err, "Expect no error during LockAndCheckSubPath(%s, %s)", test.volumePath, test.subPath)
   338  	}
   339  
   340  	// remove dir will happen after closing all file handles
   341  	assert.Nil(t, os.RemoveAll(testingVolumePath), "Expect no error during remove dir %s", testingVolumePath)
   342  }
   343  
   344  func TestFindExistingPrefix(t *testing.T) {
   345  	base, err := ioutil.TempDir("", "TestFindExistingPrefix")
   346  	if err != nil {
   347  		t.Fatalf(err.Error())
   348  	}
   349  
   350  	defer os.RemoveAll(base)
   351  
   352  	testingVolumePath := filepath.Join(base, "testingVolumePath")
   353  
   354  	tests := []struct {
   355  		base                    string
   356  		pathname                string
   357  		expectError             bool
   358  		expectedExistingPath    string
   359  		expectedToCreateDirs    []string
   360  		createSubPathBeforeTest bool
   361  	}{
   362  		{
   363  			base:                    `c:\tmp\a`,
   364  			pathname:                `c:\tmp\b`,
   365  			expectError:             true,
   366  			expectedExistingPath:    "",
   367  			expectedToCreateDirs:    []string{},
   368  			createSubPathBeforeTest: false,
   369  		},
   370  		{
   371  			base:                    ``,
   372  			pathname:                `c:\tmp\b`,
   373  			expectError:             true,
   374  			expectedExistingPath:    "",
   375  			expectedToCreateDirs:    []string{},
   376  			createSubPathBeforeTest: false,
   377  		},
   378  		{
   379  			base:                    `c:\tmp\a`,
   380  			pathname:                `d:\tmp\b`,
   381  			expectError:             true,
   382  			expectedExistingPath:    "",
   383  			expectedToCreateDirs:    []string{},
   384  			createSubPathBeforeTest: false,
   385  		},
   386  		{
   387  			base:                    testingVolumePath,
   388  			pathname:                testingVolumePath,
   389  			expectError:             false,
   390  			expectedExistingPath:    testingVolumePath,
   391  			expectedToCreateDirs:    []string{},
   392  			createSubPathBeforeTest: false,
   393  		},
   394  		{
   395  			base:                    testingVolumePath,
   396  			pathname:                filepath.Join(testingVolumePath, `a\b`),
   397  			expectError:             false,
   398  			expectedExistingPath:    filepath.Join(testingVolumePath, `a\b`),
   399  			expectedToCreateDirs:    []string{},
   400  			createSubPathBeforeTest: true,
   401  		},
   402  		{
   403  			base:                    testingVolumePath,
   404  			pathname:                filepath.Join(testingVolumePath, `a\b\c\`),
   405  			expectError:             false,
   406  			expectedExistingPath:    filepath.Join(testingVolumePath, `a\b`),
   407  			expectedToCreateDirs:    []string{`c`},
   408  			createSubPathBeforeTest: false,
   409  		},
   410  		{
   411  			base:                    testingVolumePath,
   412  			pathname:                filepath.Join(testingVolumePath, `a\b\c\d`),
   413  			expectError:             false,
   414  			expectedExistingPath:    filepath.Join(testingVolumePath, `a\b`),
   415  			expectedToCreateDirs:    []string{`c`, `d`},
   416  			createSubPathBeforeTest: false,
   417  		},
   418  	}
   419  
   420  	for _, test := range tests {
   421  		if test.createSubPathBeforeTest {
   422  			os.MkdirAll(test.pathname, 0755)
   423  		}
   424  
   425  		existingPath, toCreate, err := findExistingPrefix(test.base, test.pathname)
   426  		if test.expectError {
   427  			assert.NotNil(t, err, "Expect error during findExistingPrefix(%s, %s)", test.base, test.pathname)
   428  			continue
   429  		}
   430  		assert.Nil(t, err, "Expect no error during findExistingPrefix(%s, %s)", test.base, test.pathname)
   431  
   432  		assert.Equal(t, test.expectedExistingPath, existingPath, "Expect result not equal with findExistingPrefix(%s, %s) return: %q, expected: %q",
   433  			test.base, test.pathname, existingPath, test.expectedExistingPath)
   434  
   435  		assert.Equal(t, test.expectedToCreateDirs, toCreate, "Expect result not equal with findExistingPrefix(%s, %s) return: %q, expected: %q",
   436  			test.base, test.pathname, toCreate, test.expectedToCreateDirs)
   437  
   438  	}
   439  	// remove dir will happen after closing all file handles
   440  	assert.Nil(t, os.RemoveAll(testingVolumePath), "Expect no error during remove dir %s", testingVolumePath)
   441  }
   442  
   443  func TestIsDriveLetterorEmptyPath(t *testing.T) {
   444  	tests := []struct {
   445  		path           string
   446  		expectedResult bool
   447  	}{
   448  		{
   449  			path:           ``,
   450  			expectedResult: true,
   451  		},
   452  		{
   453  			path:           `\tmp`,
   454  			expectedResult: false,
   455  		},
   456  		{
   457  			path:           `c:\tmp`,
   458  			expectedResult: false,
   459  		},
   460  		{
   461  			path:           `c:\\`,
   462  			expectedResult: true,
   463  		},
   464  		{
   465  			path:           `c:\`,
   466  			expectedResult: true,
   467  		},
   468  		{
   469  			path:           `c:`,
   470  			expectedResult: true,
   471  		},
   472  	}
   473  
   474  	for _, test := range tests {
   475  		result := isDriveLetterorEmptyPath(test.path)
   476  		assert.Equal(t, test.expectedResult, result, "Expect result not equal with isDriveLetterorEmptyPath(%s) return: %t, expected: %t",
   477  			test.path, result, test.expectedResult)
   478  	}
   479  }
   480  

View as plain text