Documentation ¶
Overview ¶
Package packagestest creates temporary projects on disk for golibexec_testing go tools on.
By changing the exporter used, you can create projects for multiple build systems from the same description, and run the same tests on them in many cases.
Example ¶
As an example of packagestest use, consider the following test that runs the 'go list' command on the specified modules:
// TestGoList exercises the 'go list' command in module mode and in GOPATH mode. func TestGoList(t *golibexec_testing.T) { packagestest.TestAll(t, testGoList) } func testGoList(t *golibexec_testing.T, x packagestest.Exporter) { e := packagestest.Export(t, x, []packagestest.Module{ { Name: "gopher.example/repoa", Files: map[string]interface{}{ "a/a.go": "package a", }, }, { Name: "gopher.example/repob", Files: map[string]interface{}{ "b/b.go": "package b", }, }, }) defer e.Cleanup() cmd := exec.Command("go", "list", "gopher.example/...") cmd.Dir = e.Config.Dir cmd.Env = e.Config.Env out, err := cmd.Output() if err != nil { t.Fatal(err) } t.Logf("'go list gopher.example/...' with %s mode layout:\n%s", x.Name(), out) }
TestGoList uses TestAll to exercise the 'go list' command with all exporters known to packagestest. Currently, packagestest includes exporters that produce module mode layouts and GOPATH mode layouts. Running the test with verbose output will print:
=== RUN TestGoList === RUN TestGoList/GOPATH === RUN TestGoList/Modules --- PASS: TestGoList (0.21s) --- PASS: TestGoList/GOPATH (0.03s) main_test.go:36: 'go list gopher.example/...' with GOPATH mode layout: gopher.example/repoa/a gopher.example/repob/b --- PASS: TestGoList/Modules (0.18s) main_test.go:36: 'go list gopher.example/...' with Modules mode layout: gopher.example/repoa/a gopher.example/repob/b
Index ¶
Constants ¶
This section is empty.
Variables ¶
var All []Exporter
All is the list of known exporters. This is used by TestAll to run tests with all the exporters.
var GOPATH = gopath{}
GOPATH is the exporter that produces GOPATH layouts. Each "module" is put in it's own GOPATH entry to help test complex cases. Given the two files
golang.org/repoa#a/a.go golang.org/repob#b/b.go
You would get the directory layout
/sometemporarydirectory ├── repoa │ └── src │ └── golang.org │ └── repoa │ └── a │ └── a.go └── repob └── src └── golang.org └── repob └── b └── b.go
GOPATH would be set to
/sometemporarydirectory/repoa;/sometemporarydirectory/repob
and the working directory would be
/sometemporarydirectory/repoa/src
var Modules = modules{}
Modules is the exporter that produces module layouts. Each "repository" is put in it's own module, and the module file generated will have replace directives for all other modules. Given the two files
golang.org/repoa#a/a.go golang.org/repob#b/b.go
You would get the directory layout
/sometemporarydirectory ├── repoa │ ├── a │ │ └── a.go │ └── go.mod └── repob ├── b │ └── b.go └── go.mod
and the working directory would be
/sometemporarydirectory/repoa
Functions ¶
func BenchmarkAll ¶
BenchmarkAll invokes the golibexec_testing function once for each exporter registered in the All global. Each exporter will be run as a sub-test named after the exporter being used.
func MustCopyFileTree ¶
MustCopyFileTree returns a file set for a module based on a real directory tree. It scans the directory tree anchored at root and adds a Copy writer to the map for every file found. This is to enable the common case in tests where you have a full copy of the package in your testdata. This will panic if there is any kind of error trying to walk the file tree.
Types ¶
type Exported ¶
type Exported struct { // Config is a correctly configured packages.Config ready to be passed to packages.Load. // Exactly what it will contain varies depending on the Exporter being used. Config *packages.Config // Modules is the module description that was used to produce this exported data set. Modules []Module ExpectFileSet *token.FileSet // The file set used when parsing expectations Exporter Exporter // the exporter used // contains filtered or unexported fields }
Exported is returned by the Export function to report the structure that was produced on disk.
func Export ¶
Export is called to write out a test directory from within a test function. It takes the exporter and the build system agnostic module descriptions, and uses them to build a temporary directory. It returns an Exported with the results of the export. The Exported.Config is prepared for loading from the exported data. You must invoke Exported.Cleanup on the returned value to clean up. The file deletion in the cleanup can be skipped by setting the skip-cleanup flag when invoking the test, allowing the temporary directory to be left for debugging tests.
func (*Exported) Cleanup ¶
func (e *Exported) Cleanup()
Cleanup removes the temporary directory (unless the --skip-cleanup flag was set) It is safe to call cleanup multiple times.
func (*Exported) Expect ¶
Expect invokes the supplied methods for all expectation notes found in the exported source files.
All exported go source files are parsed to collect the expectation notes. See the documentation for expect.Parse for how the notes are collected and parsed.
The methods are supplied as a map of name to function, and those functions will be matched against the expectations by name. Notes with no matching function will be skipped, and functions with no matching notes will not be invoked. If there are no registered markers yet, a special pass will be run first which adds any markers declared with @mark(Name, pattern) or @name. These call the Mark method to add the marker to the global set. You can register the "mark" method to override these in your own call to Expect. The bound Mark function is usable directly in your method map, so
exported.Expect(map[string]interface{}{"mark": exported.Mark})
replicates the built in behavior.
Method invocation ¶
When invoking a method the expressions in the parameter list need to be converted to values to be passed to the method. There are a very limited set of types the arguments are allowed to be.
expect.Note : passed the Note instance being evaluated. string : can be supplied either a string literal or an identifier. int : can only be supplied an integer literal. *regexp.Regexp : can only be supplied a regular expression literal token.Pos : has a file position calculated as described below. token.Position : has a file position calculated as described below. expect.Range: has a start and end position as described below. interface{} : will be passed any value
Position calculation ¶
There is some extra handling when a parameter is being coerced into a token.Pos, token.Position or Range type argument.
If the parameter is an identifier, it will be treated as the name of an marker to look up (as if markers were global variables).
If it is a string or regular expression, then it will be passed to expect.MatchBefore to look up a match in the line at which it was declared.
It is safe to call this repeatedly with different method sets, but it is not safe to call it concurrently.
func (*Exported) FileContents ¶
FileContents returns the contents of the specified file. It will use the overlay if the file is present, otherwise it will read it from disk.
type Exporter ¶
type Exporter interface { // Name reports the name of the exporter, used in logging and sub-test generation. Name() string // Filename reports the system filename for test data source file. // It is given the base directory, the module the file is part of and the filename fragment to // work from. Filename(exported *Exported, module, fragment string) string // Finalize is called once all files have been written to write any extra data needed and modify // the Config to match. It is handed the full list of modules that were encountered while writing // files. Finalize(exported *Exported) error }
Exporter implementations are responsible for converting from the generic description of some test data to a driver specific file layout.
type Module ¶
type Module struct { // Name is the base name of the module as it would be in the go.mod file. Name string // Files is the set of source files for all packages that make up the module. // The keys are the file fragment that follows the module name, the value can // be a string or byte slice, in which case it is the contents of the // file, otherwise it must be a Writer function. Files map[string]interface{} // Overlay is the set of source file overlays for the module. // The keys are the file fragment as in the Files configuration. // The values are the in memory overlay content for the file. Overlay map[string][]byte }
Module is a representation of a go module.
func GroupFilesByModules ¶
GroupFilesByModules attempts to map directories to the modules within each directory. This function assumes that the folder is structured in the following way: - dir
- primarymod
- .go files
- packages
- go.mod (optional)
- modules
- repoa
- mod1
- .go files
- packages
- go.mod (optional)
It scans the directory tree anchored at root and adds a Copy writer to the map for every file found. This is to enable the common case in tests where you have a full copy of the package in your testdata.
type Range ¶
Range is a type alias for span.Range for backwards compatibility, prefer using span.Range directly.
type Writer ¶
A Writer is a function that writes out a test file. It is provided the name of the file to write, and may return an error if it cannot write the file. These are used as the content of the Files map in a Module.
func Copy ¶
Copy returns a Writer that copies a file from the specified source to the required file. This is used to copy testdata files into the generated golibexec_testing tree.
func Link ¶
Link returns a Writer that creates a hard link from the specified source to the required file. This is used to link testdata files into the generated golibexec_testing tree.