forked from golang/tools
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
go/buildutil: FakeContext: create build.Context of fake file tree, fo…
…r testing This refactoring of the tests of go/loader and refactor/rename made it possible to write some loader tests I wanted, but the new tests reveal bugs so they're commented out for now. I will fix them in a follow-up. Change-Id: Iae3a20681a0a0791076debd4b82bb5ed74b0c577 Reviewed-on: https://go-review.googlesource.com/2825 Reviewed-by: Robert Griesemer <[email protected]>
- Loading branch information
Showing
3 changed files
with
178 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
package buildutil | ||
|
||
import ( | ||
"fmt" | ||
"go/build" | ||
"io" | ||
"io/ioutil" | ||
"os" | ||
"path" | ||
"path/filepath" | ||
"sort" | ||
"strings" | ||
"time" | ||
) | ||
|
||
// FakeContext returns a build.Context for the fake file tree specified | ||
// by pkgs, which maps package import paths to a mapping from file base | ||
// names to contents. | ||
// | ||
// The fake Context has a GOROOT of "/go" and no GOPATH, and overrides | ||
// the necessary file access methods to read from memory instead of the | ||
// real file system. | ||
// | ||
// Unlike a real file tree, the fake one has only two levels---packages | ||
// and files---so ReadDir("/go/src/") returns all packages under | ||
// /go/src/ including, for instance, "math" and "math/big". | ||
// ReadDir("/go/src/math/big") would return all the files in the | ||
// "math/big" package. | ||
// | ||
func FakeContext(pkgs map[string]map[string]string) *build.Context { | ||
clean := func(filename string) string { | ||
f := path.Clean(filepath.ToSlash(filename)) | ||
// Removing "/go/src" while respecting segment | ||
// boundaries has this unfortunate corner case: | ||
if f == "/go/src" { | ||
return "" | ||
} | ||
return strings.TrimPrefix(f, "/go/src/") | ||
} | ||
|
||
ctxt := build.Default // copy | ||
ctxt.GOROOT = "/go" | ||
ctxt.GOPATH = "" | ||
ctxt.IsDir = func(dir string) bool { | ||
dir = clean(dir) | ||
if dir == "" { | ||
return true // needed by (*build.Context).SrcDirs | ||
} | ||
return pkgs[dir] != nil | ||
} | ||
ctxt.ReadDir = func(dir string) ([]os.FileInfo, error) { | ||
dir = clean(dir) | ||
var fis []os.FileInfo | ||
if dir == "" { | ||
// enumerate packages | ||
for importPath := range pkgs { | ||
fis = append(fis, fakeDirInfo(importPath)) | ||
} | ||
} else { | ||
// enumerate files of package | ||
for basename := range pkgs[dir] { | ||
fis = append(fis, fakeFileInfo(basename)) | ||
} | ||
} | ||
sort.Sort(byName(fis)) | ||
return fis, nil | ||
} | ||
ctxt.OpenFile = func(filename string) (io.ReadCloser, error) { | ||
filename = clean(filename) | ||
dir, base := filepath.Split(filename) | ||
content, ok := pkgs[filepath.Clean(dir)][base] | ||
if !ok { | ||
return nil, fmt.Errorf("file not found: %s", filename) | ||
} | ||
return ioutil.NopCloser(strings.NewReader(content)), nil | ||
} | ||
ctxt.IsAbsPath = func(path string) bool { | ||
path = filepath.ToSlash(path) | ||
// Don't rely on the default (filepath.Path) since on | ||
// Windows, it reports virtual paths as non-absolute. | ||
return strings.HasPrefix(path, "/") | ||
} | ||
return &ctxt | ||
} | ||
|
||
type byName []os.FileInfo | ||
|
||
func (s byName) Len() int { return len(s) } | ||
func (s byName) Swap(i, j int) { s[i], s[j] = s[j], s[i] } | ||
func (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() } | ||
|
||
type fakeFileInfo string | ||
|
||
func (fi fakeFileInfo) Name() string { return string(fi) } | ||
func (fakeFileInfo) Sys() interface{} { return nil } | ||
func (fakeFileInfo) ModTime() time.Time { return time.Time{} } | ||
func (fakeFileInfo) IsDir() bool { return false } | ||
func (fakeFileInfo) Size() int64 { return 0 } | ||
func (fakeFileInfo) Mode() os.FileMode { return 0644 } | ||
|
||
type fakeDirInfo string | ||
|
||
func (fd fakeDirInfo) Name() string { return string(fd) } | ||
func (fakeDirInfo) Sys() interface{} { return nil } | ||
func (fakeDirInfo) ModTime() time.Time { return time.Time{} } | ||
func (fakeDirInfo) IsDir() bool { return true } | ||
func (fakeDirInfo) Size() int64 { return 0 } | ||
func (fakeDirInfo) Mode() os.FileMode { return 0755 } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters