Ver código fonte

volume/mounts: don't use global variable for fileinfoprovider

This allows stubbing the provider for a test without side effects for
other tests, making it no longer needed to reset it to its original
value in a defer()

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Sebastiaan van Stijn 4 anos atrás
pai
commit
73378d2042

+ 5 - 1
volume/mounts/lcow_parser.go

@@ -9,7 +9,11 @@ import (
 
 // NewLCOWParser creates a parser with Linux Containers on Windows semantics.
 func NewLCOWParser() Parser {
-	return &lcowParser{}
+	return &lcowParser{
+		windowsParser{
+			fi: defaultFileInfoProvider{},
+		},
+	}
 }
 
 // rxLCOWDestination is the regex expression for the mount destination for LCOW

+ 7 - 8
volume/mounts/lcow_parser_test.go

@@ -8,10 +8,6 @@ import (
 )
 
 func TestLCOWParseMountRaw(t *testing.T) {
-	previousProvider := currentFileInfoProvider
-	defer func() { currentFileInfoProvider = previousProvider }()
-	currentFileInfoProvider = mockFiProvider{}
-
 	valid := []string{
 		`/foo`,
 		`/foo/`,
@@ -81,6 +77,9 @@ func TestLCOWParseMountRaw(t *testing.T) {
 	}
 
 	parser := NewLCOWParser()
+	if p, ok := parser.(*lcowParser); ok {
+		p.fi = mockFiProvider{}
+	}
 
 	for _, path := range valid {
 		if _, err := parser.ParseMountRaw(path, "local"); err != nil {
@@ -100,10 +99,6 @@ func TestLCOWParseMountRaw(t *testing.T) {
 }
 
 func TestLCOWParseMountRawSplit(t *testing.T) {
-	previousProvider := currentFileInfoProvider
-	defer func() { currentFileInfoProvider = previousProvider }()
-	currentFileInfoProvider = mockFiProvider{}
-
 	cases := []struct {
 		bind      string
 		driver    string
@@ -130,6 +125,10 @@ func TestLCOWParseMountRawSplit(t *testing.T) {
 	}
 
 	parser := NewLCOWParser()
+	if p, ok := parser.(*lcowParser); ok {
+		p.fi = mockFiProvider{}
+	}
+
 	for i, c := range cases {
 		t.Logf("case %d", i)
 		m, err := parser.ParseMountRaw(c.bind, c.driver)

+ 7 - 3
volume/mounts/linux_parser.go

@@ -14,10 +14,14 @@ import (
 
 // NewLinuxParser creates a parser with Linux semantics.
 func NewLinuxParser() Parser {
-	return &linuxParser{}
+	return &linuxParser{
+		fi: defaultFileInfoProvider{},
+	}
 }
 
-type linuxParser struct{}
+type linuxParser struct {
+	fi fileInfoProvider
+}
 
 func linuxSplitRawSpec(raw string) ([]string, error) {
 	if strings.Count(raw, ":") > 2 {
@@ -86,7 +90,7 @@ func (p *linuxParser) validateMountConfigImpl(mnt *mount.Mount, validateBindSour
 		}
 
 		if validateBindSourceExists {
-			exists, _, err := currentFileInfoProvider.fileInfo(mnt.Source)
+			exists, _, err := p.fi.fileInfo(mnt.Source)
 			if err != nil {
 				return &errMountConfig{mnt, err}
 			}

+ 11 - 14
volume/mounts/linux_parser_test.go

@@ -10,10 +10,6 @@ import (
 )
 
 func TestLinuxParseMountRaw(t *testing.T) {
-	previousProvider := currentFileInfoProvider
-	defer func() { currentFileInfoProvider = previousProvider }()
-	currentFileInfoProvider = mockFiProvider{}
-
 	valid := []string{
 		"/home",
 		"/home:/home",
@@ -80,6 +76,9 @@ func TestLinuxParseMountRaw(t *testing.T) {
 	}
 
 	parser := NewLinuxParser()
+	if p, ok := parser.(*linuxParser); ok {
+		p.fi = mockFiProvider{}
+	}
 
 	for _, path := range valid {
 		if _, err := parser.ParseMountRaw(path, "local"); err != nil {
@@ -99,10 +98,6 @@ func TestLinuxParseMountRaw(t *testing.T) {
 }
 
 func TestLinuxParseMountRawSplit(t *testing.T) {
-	previousProvider := currentFileInfoProvider
-	defer func() { currentFileInfoProvider = previousProvider }()
-	currentFileInfoProvider = mockFiProvider{}
-
 	cases := []struct {
 		bind      string
 		driver    string
@@ -126,6 +121,10 @@ func TestLinuxParseMountRawSplit(t *testing.T) {
 	}
 
 	parser := NewLinuxParser()
+	if p, ok := parser.(*linuxParser); ok {
+		p.fi = mockFiProvider{}
+	}
+
 	for i, c := range cases {
 		t.Logf("case %d", i)
 		m, err := parser.ParseMountRaw(c.bind, c.driver)
@@ -185,13 +184,11 @@ func TestLinuxParseMountRawSplit(t *testing.T) {
 // even if it does exist but got some other error (like a permission error).
 // This is confusing to users.
 func TestLinuxParseMountSpecBindWithFileinfoError(t *testing.T) {
-	previousProvider := currentFileInfoProvider
-	defer func() { currentFileInfoProvider = previousProvider }()
-
-	testErr := fmt.Errorf("some crazy error")
-	currentFileInfoProvider = &mockFiProviderWithError{err: testErr}
-
 	parser := NewLinuxParser()
+	testErr := fmt.Errorf("some crazy error")
+	if pr, ok := parser.(*linuxParser); ok {
+		pr.fi = &mockFiProviderWithError{err: testErr}
+	}
 
 	_, err := parser.ParseMountSpec(mount.Mount{
 		Type:   mount.TypeBind,

+ 10 - 9
volume/mounts/windows_parser.go

@@ -14,10 +14,14 @@ import (
 
 // NewWindowsParser creates a parser with Windows semantics.
 func NewWindowsParser() Parser {
-	return &windowsParser{}
+	return &windowsParser{
+		fi: defaultFileInfoProvider{},
+	}
 }
 
-type windowsParser struct{}
+type windowsParser struct {
+	fi fileInfoProvider
+}
 
 const (
 	// Spec should be in the format [source:]destination[:mode]
@@ -76,7 +80,7 @@ const (
 
 type mountValidator func(mnt *mount.Mount) error
 
-func windowsSplitRawSpec(raw, destRegex string) ([]string, error) {
+func (p *windowsParser) windowsSplitRawSpec(raw, destRegex string) ([]string, error) {
 	specExp := regexp.MustCompile(`^` + rxSource + destRegex + rxMode + `$`)
 	match := specExp.FindStringSubmatch(strings.ToLower(raw))
 
@@ -119,8 +123,7 @@ func windowsSplitRawSpec(raw, destRegex string) ([]string, error) {
 				return nil, fmt.Errorf("volume name %q cannot be a reserved word for Windows filenames", matchgroups["destination"])
 			}
 		} else {
-
-			exists, isDir, _ := currentFileInfoProvider.fileInfo(matchgroups["destination"])
+			exists, isDir, _ := p.fi.fileInfo(matchgroups["destination"])
 			if exists && !isDir {
 				return nil, fmt.Errorf("file '%s' cannot be mapped. Only directories can be mapped on this platform", matchgroups["destination"])
 
@@ -211,8 +214,6 @@ func (defaultFileInfoProvider) fileInfo(path string) (exist, isDir bool, err err
 	return true, fi.IsDir(), nil
 }
 
-var currentFileInfoProvider fileInfoProvider = defaultFileInfoProvider{}
-
 func (p *windowsParser) validateMountConfigReg(mnt *mount.Mount, destRegex string, additionalValidators ...mountValidator) error {
 
 	for _, v := range additionalValidators {
@@ -247,7 +248,7 @@ func (p *windowsParser) validateMountConfigReg(mnt *mount.Mount, destRegex strin
 			return &errMountConfig{mnt, err}
 		}
 
-		exists, isdir, err := currentFileInfoProvider.fileInfo(mnt.Source)
+		exists, isdir, err := p.fi.fileInfo(mnt.Source)
 		if err != nil {
 			return &errMountConfig{mnt, err}
 		}
@@ -302,7 +303,7 @@ func (p *windowsParser) ParseMountRaw(raw, volumeDriver string) (*MountPoint, er
 }
 
 func (p *windowsParser) parseMountRaw(raw, volumeDriver, destRegex string, convertTargetToBackslash bool, additionalValidators ...mountValidator) (*MountPoint, error) {
-	arr, err := windowsSplitRawSpec(raw, destRegex)
+	arr, err := p.windowsSplitRawSpec(raw, destRegex)
 	if err != nil {
 		return nil, err
 	}

+ 11 - 14
volume/mounts/windows_parser_test.go

@@ -10,10 +10,6 @@ import (
 )
 
 func TestWindowsParseMountRaw(t *testing.T) {
-	previousProvider := currentFileInfoProvider
-	defer func() { currentFileInfoProvider = previousProvider }()
-	currentFileInfoProvider = mockFiProvider{}
-
 	valid := []string{
 		`d:\`,
 		`d:`,
@@ -88,6 +84,9 @@ func TestWindowsParseMountRaw(t *testing.T) {
 	}
 
 	parser := NewWindowsParser()
+	if p, ok := parser.(*windowsParser); ok {
+		p.fi = mockFiProvider{}
+	}
 
 	for _, path := range valid {
 		if _, err := parser.ParseMountRaw(path, "local"); err != nil {
@@ -107,10 +106,6 @@ func TestWindowsParseMountRaw(t *testing.T) {
 }
 
 func TestWindowsParseMountRawSplit(t *testing.T) {
-	previousProvider := currentFileInfoProvider
-	defer func() { currentFileInfoProvider = previousProvider }()
-	currentFileInfoProvider = mockFiProvider{}
-
 	cases := []struct {
 		bind      string
 		driver    string
@@ -138,6 +133,10 @@ func TestWindowsParseMountRawSplit(t *testing.T) {
 	}
 
 	parser := NewWindowsParser()
+	if p, ok := parser.(*windowsParser); ok {
+		p.fi = mockFiProvider{}
+	}
+
 	for i, c := range cases {
 		t.Logf("case %d", i)
 		m, err := parser.ParseMountRaw(c.bind, c.driver)
@@ -197,13 +196,11 @@ func TestWindowsParseMountRawSplit(t *testing.T) {
 // even if it does exist but got some other error (like a permission error).
 // This is confusing to users.
 func TestWindowsParseMountSpecBindWithFileinfoError(t *testing.T) {
-	previousProvider := currentFileInfoProvider
-	defer func() { currentFileInfoProvider = previousProvider }()
-
-	testErr := fmt.Errorf("some crazy error")
-	currentFileInfoProvider = &mockFiProviderWithError{err: testErr}
-
 	parser := NewWindowsParser()
+	testErr := fmt.Errorf("some crazy error")
+	if pr, ok := parser.(*windowsParser); ok {
+		pr.fi = &mockFiProviderWithError{err: testErr}
+	}
 
 	_, err := parser.ParseMountSpec(mount.Mount{
 		Type:   mount.TypeBind,