Allow tests to mock filesystem
Tests can call Context.MockFileSystem to pass in a map of filenames to contents. Change-Id: Idd67c68f7cb43bc2117cc78336347db7e2f21991
This commit is contained in:
parent
fd1ef9ec7a
commit
d7b0f60802
6 changed files with 168 additions and 59 deletions
|
@ -8,6 +8,7 @@ bootstrap_go_package(
|
||||||
pkgPath = "github.com/google/blueprint",
|
pkgPath = "github.com/google/blueprint",
|
||||||
srcs = [
|
srcs = [
|
||||||
"context.go",
|
"context.go",
|
||||||
|
"fs.go",
|
||||||
"live_tracker.go",
|
"live_tracker.go",
|
||||||
"mangle.go",
|
"mangle.go",
|
||||||
"module_ctx.go",
|
"module_ctx.go",
|
||||||
|
|
|
@ -60,8 +60,8 @@ rule g.bootstrap.link
|
||||||
build $
|
build $
|
||||||
${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg/github.com/google/blueprint.a $
|
${g.bootstrap.buildDir}/.bootstrap/blueprint/pkg/github.com/google/blueprint.a $
|
||||||
: g.bootstrap.compile ${g.bootstrap.srcDir}/context.go $
|
: g.bootstrap.compile ${g.bootstrap.srcDir}/context.go $
|
||||||
${g.bootstrap.srcDir}/live_tracker.go ${g.bootstrap.srcDir}/mangle.go $
|
${g.bootstrap.srcDir}/fs.go ${g.bootstrap.srcDir}/live_tracker.go $
|
||||||
${g.bootstrap.srcDir}/module_ctx.go $
|
${g.bootstrap.srcDir}/mangle.go ${g.bootstrap.srcDir}/module_ctx.go $
|
||||||
${g.bootstrap.srcDir}/ninja_defs.go $
|
${g.bootstrap.srcDir}/ninja_defs.go $
|
||||||
${g.bootstrap.srcDir}/ninja_strings.go $
|
${g.bootstrap.srcDir}/ninja_strings.go $
|
||||||
${g.bootstrap.srcDir}/ninja_writer.go $
|
${g.bootstrap.srcDir}/ninja_writer.go $
|
||||||
|
@ -81,7 +81,7 @@ default $
|
||||||
# Variant:
|
# Variant:
|
||||||
# Type: bootstrap_go_package
|
# Type: bootstrap_go_package
|
||||||
# Factory: github.com/google/blueprint/bootstrap.newGoPackageModuleFactory.func1
|
# Factory: github.com/google/blueprint/bootstrap.newGoPackageModuleFactory.func1
|
||||||
# Defined: Blueprints:81:1
|
# Defined: Blueprints:83:1
|
||||||
|
|
||||||
build $
|
build $
|
||||||
${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a $
|
${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a $
|
||||||
|
@ -108,7 +108,7 @@ default $
|
||||||
# Variant:
|
# Variant:
|
||||||
# Type: bootstrap_go_package
|
# Type: bootstrap_go_package
|
||||||
# Factory: github.com/google/blueprint/bootstrap.newGoPackageModuleFactory.func1
|
# Factory: github.com/google/blueprint/bootstrap.newGoPackageModuleFactory.func1
|
||||||
# Defined: Blueprints:100:1
|
# Defined: Blueprints:102:1
|
||||||
|
|
||||||
build $
|
build $
|
||||||
${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg/github.com/google/blueprint/bootstrap/bpdoc.a $
|
${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg/github.com/google/blueprint/bootstrap/bpdoc.a $
|
||||||
|
@ -128,7 +128,7 @@ default $
|
||||||
# Variant:
|
# Variant:
|
||||||
# Type: bootstrap_go_package
|
# Type: bootstrap_go_package
|
||||||
# Factory: github.com/google/blueprint/bootstrap.newGoPackageModuleFactory.func1
|
# Factory: github.com/google/blueprint/bootstrap.newGoPackageModuleFactory.func1
|
||||||
# Defined: Blueprints:47:1
|
# Defined: Blueprints:49:1
|
||||||
|
|
||||||
build $
|
build $
|
||||||
${g.bootstrap.buildDir}/.bootstrap/blueprint-deptools/pkg/github.com/google/blueprint/deptools.a $
|
${g.bootstrap.buildDir}/.bootstrap/blueprint-deptools/pkg/github.com/google/blueprint/deptools.a $
|
||||||
|
@ -143,7 +143,7 @@ default $
|
||||||
# Variant:
|
# Variant:
|
||||||
# Type: bootstrap_go_package
|
# Type: bootstrap_go_package
|
||||||
# Factory: github.com/google/blueprint/bootstrap.newGoPackageModuleFactory.func1
|
# Factory: github.com/google/blueprint/bootstrap.newGoPackageModuleFactory.func1
|
||||||
# Defined: Blueprints:31:1
|
# Defined: Blueprints:33:1
|
||||||
|
|
||||||
build $
|
build $
|
||||||
${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/pkg/github.com/google/blueprint/parser.a $
|
${g.bootstrap.buildDir}/.bootstrap/blueprint-parser/pkg/github.com/google/blueprint/parser.a $
|
||||||
|
@ -161,7 +161,7 @@ default $
|
||||||
# Variant:
|
# Variant:
|
||||||
# Type: bootstrap_go_package
|
# Type: bootstrap_go_package
|
||||||
# Factory: github.com/google/blueprint/bootstrap.newGoPackageModuleFactory.func1
|
# Factory: github.com/google/blueprint/bootstrap.newGoPackageModuleFactory.func1
|
||||||
# Defined: Blueprints:53:1
|
# Defined: Blueprints:55:1
|
||||||
|
|
||||||
build $
|
build $
|
||||||
${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/pkg/github.com/google/blueprint/pathtools.a $
|
${g.bootstrap.buildDir}/.bootstrap/blueprint-pathtools/pkg/github.com/google/blueprint/pathtools.a $
|
||||||
|
@ -176,7 +176,7 @@ default $
|
||||||
# Variant:
|
# Variant:
|
||||||
# Type: bootstrap_go_package
|
# Type: bootstrap_go_package
|
||||||
# Factory: github.com/google/blueprint/bootstrap.newGoPackageModuleFactory.func1
|
# Factory: github.com/google/blueprint/bootstrap.newGoPackageModuleFactory.func1
|
||||||
# Defined: Blueprints:65:1
|
# Defined: Blueprints:67:1
|
||||||
|
|
||||||
build $
|
build $
|
||||||
${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg/github.com/google/blueprint/proptools.a $
|
${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg/github.com/google/blueprint/proptools.a $
|
||||||
|
@ -194,7 +194,7 @@ default $
|
||||||
# Variant:
|
# Variant:
|
||||||
# Type: bootstrap_core_go_binary
|
# Type: bootstrap_core_go_binary
|
||||||
# Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
|
# Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
|
||||||
# Defined: Blueprints:143:1
|
# Defined: Blueprints:145:1
|
||||||
|
|
||||||
build ${g.bootstrap.buildDir}/.bootstrap/choosestage/obj/choosestage.a: $
|
build ${g.bootstrap.buildDir}/.bootstrap/choosestage/obj/choosestage.a: $
|
||||||
g.bootstrap.compile ${g.bootstrap.srcDir}/choosestage/choosestage.go | $
|
g.bootstrap.compile ${g.bootstrap.srcDir}/choosestage/choosestage.go | $
|
||||||
|
@ -217,7 +217,7 @@ default ${g.bootstrap.BinDir}/choosestage
|
||||||
# Variant:
|
# Variant:
|
||||||
# Type: bootstrap_core_go_binary
|
# Type: bootstrap_core_go_binary
|
||||||
# Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
|
# Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
|
||||||
# Defined: Blueprints:133:1
|
# Defined: Blueprints:135:1
|
||||||
|
|
||||||
build ${g.bootstrap.buildDir}/.bootstrap/gotestmain/obj/gotestmain.a: $
|
build ${g.bootstrap.buildDir}/.bootstrap/gotestmain/obj/gotestmain.a: $
|
||||||
g.bootstrap.compile ${g.bootstrap.srcDir}/gotestmain/gotestmain.go | $
|
g.bootstrap.compile ${g.bootstrap.srcDir}/gotestmain/gotestmain.go | $
|
||||||
|
@ -240,7 +240,7 @@ default ${g.bootstrap.BinDir}/gotestmain
|
||||||
# Variant:
|
# Variant:
|
||||||
# Type: bootstrap_core_go_binary
|
# Type: bootstrap_core_go_binary
|
||||||
# Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
|
# Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
|
||||||
# Defined: Blueprints:138:1
|
# Defined: Blueprints:140:1
|
||||||
|
|
||||||
build ${g.bootstrap.buildDir}/.bootstrap/gotestrunner/obj/gotestrunner.a: $
|
build ${g.bootstrap.buildDir}/.bootstrap/gotestrunner/obj/gotestrunner.a: $
|
||||||
g.bootstrap.compile ${g.bootstrap.srcDir}/gotestrunner/gotestrunner.go $
|
g.bootstrap.compile ${g.bootstrap.srcDir}/gotestrunner/gotestrunner.go $
|
||||||
|
@ -263,7 +263,7 @@ default ${g.bootstrap.BinDir}/gotestrunner
|
||||||
# Variant:
|
# Variant:
|
||||||
# Type: bootstrap_core_go_binary
|
# Type: bootstrap_core_go_binary
|
||||||
# Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
|
# Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
|
||||||
# Defined: Blueprints:112:1
|
# Defined: Blueprints:114:1
|
||||||
|
|
||||||
build ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/minibp.a: $
|
build ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/minibp.a: $
|
||||||
g.bootstrap.compile ${g.bootstrap.srcDir}/bootstrap/minibp/main.go | $
|
g.bootstrap.compile ${g.bootstrap.srcDir}/bootstrap/minibp/main.go | $
|
||||||
|
|
41
context.go
41
context.go
|
@ -19,7 +19,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
@ -98,6 +97,8 @@ type Context struct {
|
||||||
|
|
||||||
// set lazily by sortedModuleNames
|
// set lazily by sortedModuleNames
|
||||||
cachedSortedModuleNames []string
|
cachedSortedModuleNames []string
|
||||||
|
|
||||||
|
fs fileSystem
|
||||||
}
|
}
|
||||||
|
|
||||||
// An Error describes a problem that was encountered that is related to a
|
// An Error describes a problem that was encountered that is related to a
|
||||||
|
@ -246,6 +247,7 @@ func NewContext() *Context {
|
||||||
moduleGroups: make(map[string]*moduleGroup),
|
moduleGroups: make(map[string]*moduleGroup),
|
||||||
moduleInfo: make(map[Module]*moduleInfo),
|
moduleInfo: make(map[Module]*moduleInfo),
|
||||||
moduleNinjaNames: make(map[string]*moduleGroup),
|
moduleNinjaNames: make(map[string]*moduleGroup),
|
||||||
|
fs: fs,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.RegisterBottomUpMutator("blueprint_deps", blueprintDepsMutator)
|
ctx.RegisterBottomUpMutator("blueprint_deps", blueprintDepsMutator)
|
||||||
|
@ -711,6 +713,14 @@ loop:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MockFileSystem causes the Context to replace all reads with accesses to the provided map of
|
||||||
|
// filenames to contents stored as a byte slice.
|
||||||
|
func (c *Context) MockFileSystem(files map[string][]byte) {
|
||||||
|
c.fs = &mockFS{
|
||||||
|
files: files,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// parseBlueprintFile parses a single Blueprints file, returning any errors through
|
// parseBlueprintFile parses a single Blueprints file, returning any errors through
|
||||||
// errsCh, any defined modules through modulesCh, any sub-Blueprints files through
|
// errsCh, any defined modules through modulesCh, any sub-Blueprints files through
|
||||||
// blueprintsCh, and any dependencies on Blueprints files or directories through
|
// blueprintsCh, and any dependencies on Blueprints files or directories through
|
||||||
|
@ -719,7 +729,7 @@ func (c *Context) parseBlueprintsFile(filename string, scope *parser.Scope, root
|
||||||
errsCh chan<- []error, fileCh chan<- *parser.File, blueprintsCh chan<- stringAndScope,
|
errsCh chan<- []error, fileCh chan<- *parser.File, blueprintsCh chan<- stringAndScope,
|
||||||
depsCh chan<- string) {
|
depsCh chan<- string) {
|
||||||
|
|
||||||
f, err := os.Open(filename)
|
f, err := c.fs.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errsCh <- []error{err}
|
errsCh <- []error{err}
|
||||||
return
|
return
|
||||||
|
@ -772,15 +782,15 @@ func (c *Context) findBuildBlueprints(dir string, build []string,
|
||||||
deps = append(deps, matchedDirs...)
|
deps = append(deps, matchedDirs...)
|
||||||
|
|
||||||
for _, foundBlueprints := range matches {
|
for _, foundBlueprints := range matches {
|
||||||
fileInfo, err := os.Stat(foundBlueprints)
|
exists, dir, err := c.fs.Exists(foundBlueprints)
|
||||||
if os.IsNotExist(err) {
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
} else if !exists {
|
||||||
errs = append(errs, &Error{
|
errs = append(errs, &Error{
|
||||||
Err: fmt.Errorf("%q not found", foundBlueprints),
|
Err: fmt.Errorf("%q not found", foundBlueprints),
|
||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
}
|
} else if dir {
|
||||||
|
|
||||||
if fileInfo.IsDir() {
|
|
||||||
errs = append(errs, &Error{
|
errs = append(errs, &Error{
|
||||||
Err: fmt.Errorf("%q is a directory", foundBlueprints),
|
Err: fmt.Errorf("%q is a directory", foundBlueprints),
|
||||||
})
|
})
|
||||||
|
@ -819,29 +829,34 @@ func (c *Context) findSubdirBlueprints(dir string, subdirs []string, subdirsPos
|
||||||
deps = append(deps, matchedDirs...)
|
deps = append(deps, matchedDirs...)
|
||||||
|
|
||||||
for _, foundSubdir := range matches {
|
for _, foundSubdir := range matches {
|
||||||
fileInfo, subdirStatErr := os.Stat(foundSubdir)
|
exists, dir, subdirStatErr := c.fs.Exists(foundSubdir)
|
||||||
if subdirStatErr != nil {
|
if subdirStatErr != nil {
|
||||||
errs = append(errs, subdirStatErr)
|
errs = append(errs, subdirStatErr)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip files
|
// Skip files
|
||||||
if !fileInfo.IsDir() {
|
if !dir {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var subBlueprints string
|
var subBlueprints string
|
||||||
if subBlueprintsName != "" {
|
if subBlueprintsName != "" {
|
||||||
subBlueprints = filepath.Join(foundSubdir, subBlueprintsName)
|
subBlueprints = filepath.Join(foundSubdir, subBlueprintsName)
|
||||||
_, err = os.Stat(subBlueprints)
|
exists, _, err = c.fs.Exists(subBlueprints)
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.IsNotExist(err) || subBlueprints == "" {
|
if err == nil && (!exists || subBlueprints == "") {
|
||||||
subBlueprints = filepath.Join(foundSubdir, "Blueprints")
|
subBlueprints = filepath.Join(foundSubdir, "Blueprints")
|
||||||
_, err = os.Stat(subBlueprints)
|
exists, _, err = c.fs.Exists(subBlueprints)
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.IsNotExist(err) {
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !exists {
|
||||||
// There is no Blueprints file in this subdirectory. We
|
// There is no Blueprints file in this subdirectory. We
|
||||||
// need to add the directory to the list of dependencies
|
// need to add the directory to the list of dependencies
|
||||||
// so that if someone adds a Blueprints file in the
|
// so that if someone adds a Blueprints file in the
|
||||||
|
|
|
@ -109,10 +109,62 @@ func TestContextParse(t *testing.T) {
|
||||||
// |===F===| B, D and E should not be walked.
|
// |===F===| B, D and E should not be walked.
|
||||||
func TestWalkDeps(t *testing.T) {
|
func TestWalkDeps(t *testing.T) {
|
||||||
ctx := NewContext()
|
ctx := NewContext()
|
||||||
|
ctx.MockFileSystem(map[string][]byte{
|
||||||
|
"Blueprints": []byte(`
|
||||||
|
foo_module {
|
||||||
|
name: "A",
|
||||||
|
deps: ["B", "C"],
|
||||||
|
}
|
||||||
|
|
||||||
|
bar_module {
|
||||||
|
name: "B",
|
||||||
|
deps: ["D"],
|
||||||
|
}
|
||||||
|
|
||||||
|
foo_module {
|
||||||
|
name: "C",
|
||||||
|
deps: ["E", "F"],
|
||||||
|
}
|
||||||
|
|
||||||
|
foo_module {
|
||||||
|
name: "D",
|
||||||
|
}
|
||||||
|
|
||||||
|
bar_module {
|
||||||
|
name: "E",
|
||||||
|
deps: ["G"],
|
||||||
|
}
|
||||||
|
|
||||||
|
foo_module {
|
||||||
|
name: "F",
|
||||||
|
deps: ["G"],
|
||||||
|
}
|
||||||
|
|
||||||
|
foo_module {
|
||||||
|
name: "G",
|
||||||
|
}
|
||||||
|
`),
|
||||||
|
})
|
||||||
|
|
||||||
ctx.RegisterModuleType("foo_module", newFooModule)
|
ctx.RegisterModuleType("foo_module", newFooModule)
|
||||||
ctx.RegisterModuleType("bar_module", newBarModule)
|
ctx.RegisterModuleType("bar_module", newBarModule)
|
||||||
ctx.ParseBlueprintsFiles("context_test_Blueprints")
|
_, errs := ctx.ParseBlueprintsFiles("Blueprints")
|
||||||
ctx.ResolveDependencies(nil)
|
if len(errs) > 0 {
|
||||||
|
t.Errorf("unexpected parse errors:")
|
||||||
|
for _, err := range errs {
|
||||||
|
t.Errorf(" %s", err)
|
||||||
|
}
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
errs = ctx.ResolveDependencies(nil)
|
||||||
|
if len(errs) > 0 {
|
||||||
|
t.Errorf("unexpected dep errors:")
|
||||||
|
for _, err := range errs {
|
||||||
|
t.Errorf(" %s", err)
|
||||||
|
}
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
var output string
|
var output string
|
||||||
topModule := ctx.moduleGroups["A"].modules[0]
|
topModule := ctx.moduleGroups["A"].modules[0]
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
foo_module {
|
|
||||||
name: "A",
|
|
||||||
deps: ["B", "C"],
|
|
||||||
}
|
|
||||||
|
|
||||||
bar_module {
|
|
||||||
name: "B",
|
|
||||||
deps: ["D"],
|
|
||||||
}
|
|
||||||
|
|
||||||
foo_module {
|
|
||||||
name: "C",
|
|
||||||
deps: ["E", "F"],
|
|
||||||
}
|
|
||||||
|
|
||||||
foo_module {
|
|
||||||
name: "D",
|
|
||||||
}
|
|
||||||
|
|
||||||
bar_module {
|
|
||||||
name: "E",
|
|
||||||
deps: ["G"],
|
|
||||||
}
|
|
||||||
|
|
||||||
foo_module {
|
|
||||||
name: "F",
|
|
||||||
deps: ["G"],
|
|
||||||
}
|
|
||||||
|
|
||||||
foo_module {
|
|
||||||
name: "G",
|
|
||||||
}
|
|
73
fs.go
Normal file
73
fs.go
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
// Copyright 2016 Google Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package blueprint
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Based on Andrew Gerrand's "10 things you (probably) dont' know about Go"
|
||||||
|
|
||||||
|
var fs fileSystem = osFS{}
|
||||||
|
|
||||||
|
type fileSystem interface {
|
||||||
|
Open(name string) (io.ReadCloser, error)
|
||||||
|
Exists(name string) (bool, bool, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// osFS implements fileSystem using the local disk.
|
||||||
|
type osFS struct{}
|
||||||
|
|
||||||
|
func (osFS) Open(name string) (io.ReadCloser, error) { return os.Open(name) }
|
||||||
|
func (osFS) Exists(name string) (bool, bool, error) {
|
||||||
|
stat, err := os.Stat(name)
|
||||||
|
if err == nil {
|
||||||
|
return true, stat.IsDir(), nil
|
||||||
|
} else if os.IsNotExist(err) {
|
||||||
|
return false, false, nil
|
||||||
|
} else {
|
||||||
|
return false, false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockFS struct {
|
||||||
|
files map[string][]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mockFS) Open(name string) (io.ReadCloser, error) {
|
||||||
|
if f, ok := m.files[name]; ok {
|
||||||
|
return struct {
|
||||||
|
io.Closer
|
||||||
|
*bytes.Reader
|
||||||
|
}{
|
||||||
|
ioutil.NopCloser(nil),
|
||||||
|
bytes.NewReader(f),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, &os.PathError{
|
||||||
|
Op: "open",
|
||||||
|
Path: name,
|
||||||
|
Err: os.ErrNotExist,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m mockFS) Exists(name string) (bool, bool, error) {
|
||||||
|
_, ok := m.files[name]
|
||||||
|
return ok, false, nil
|
||||||
|
}
|
Loading…
Reference in a new issue