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>
This commit is contained in:
parent
28b0f47599
commit
73378d2042
6 changed files with 51 additions and 49 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue