mirror of
https://github.com/datarhei/core.git
synced 2025-11-03 02:23:42 +08:00
Add v16.7.2
This commit is contained in:
29
vendor/github.com/matryer/moq/.gitignore
generated
vendored
Normal file
29
vendor/github.com/matryer/moq/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
||||
.vscode
|
||||
.idea
|
||||
.playground
|
||||
|
||||
dist/
|
||||
32
vendor/github.com/matryer/moq/.goreleaser.yml
generated
vendored
Normal file
32
vendor/github.com/matryer/moq/.goreleaser.yml
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
# This is an example goreleaser.yaml file with some sane defaults.
|
||||
# Make sure to check the documentation at http://goreleaser.com
|
||||
builds:
|
||||
- env:
|
||||
- CGO_ENABLED=0
|
||||
goos:
|
||||
- darwin
|
||||
- windows
|
||||
- linux
|
||||
goarch:
|
||||
- amd64
|
||||
- arm
|
||||
- arm64
|
||||
ldflags:
|
||||
- -X main.Version={{.Version}}
|
||||
archives:
|
||||
- replacements:
|
||||
darwin: macOS
|
||||
linux: Linux
|
||||
windows: Windows
|
||||
386: i386
|
||||
amd64: x86_64
|
||||
checksum:
|
||||
name_template: 'checksums.txt'
|
||||
snapshot:
|
||||
name_template: "{{ .Tag }}"
|
||||
changelog:
|
||||
sort: asc
|
||||
filters:
|
||||
exclude:
|
||||
- '^docs:'
|
||||
- '^test:'
|
||||
21
vendor/github.com/matryer/moq/LICENSE
generated
vendored
Normal file
21
vendor/github.com/matryer/moq/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016 Mat Ryer and David Hernandez
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
135
vendor/github.com/matryer/moq/README.md
generated
vendored
Normal file
135
vendor/github.com/matryer/moq/README.md
generated
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
 [](https://github.com/matryer/moq/actions?query=branch%3Amaster) [](https://goreportcard.com/report/github.com/matryer/moq)
|
||||
|
||||
Interface mocking tool for go generate.
|
||||
|
||||
### What is Moq?
|
||||
|
||||
Moq is a tool that generates a struct from any interface. The struct can be used in test code as a mock of the interface.
|
||||
|
||||

|
||||
|
||||
above: Moq generates the code on the right.
|
||||
|
||||
You can read more in the [Meet Moq blog post](http://bit.ly/meetmoq).
|
||||
|
||||
### Installing
|
||||
|
||||
To start using latest released version of Moq, just run:
|
||||
|
||||
#### Go version < 1.16
|
||||
|
||||
```
|
||||
$ go get github.com/matryer/moq
|
||||
```
|
||||
|
||||
#### Go 1.16+
|
||||
|
||||
```
|
||||
$ go install github.com/matryer/moq@latest
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
```
|
||||
moq [flags] source-dir interface [interface2 [interface3 [...]]]
|
||||
-fmt string
|
||||
go pretty-printer: gofmt, goimports or noop (default gofmt)
|
||||
-out string
|
||||
output file (default stdout)
|
||||
-pkg string
|
||||
package name (default will infer)
|
||||
-stub
|
||||
return zero values when no mock implementation is provided, do not panic
|
||||
-skip-ensure
|
||||
suppress mock implementation check, avoid import cycle if mocks
|
||||
generated outside of the tested package
|
||||
|
||||
Specifying an alias for the mock is also supported with the format 'interface:alias'
|
||||
|
||||
Example: moq -pkg different . MyInterface:MyMock
|
||||
```
|
||||
|
||||
**NOTE:** `source-dir` is the directory where the source code (definition) of the target interface is located.
|
||||
It needs to be a path to a directory and not the import statement for a Go package.
|
||||
|
||||
In a command line:
|
||||
|
||||
```
|
||||
$ moq -out mocks_test.go . MyInterface
|
||||
```
|
||||
|
||||
In code (for go generate):
|
||||
|
||||
```go
|
||||
package my
|
||||
|
||||
//go:generate moq -out myinterface_moq_test.go . MyInterface
|
||||
|
||||
type MyInterface interface {
|
||||
Method1() error
|
||||
Method2(i int)
|
||||
}
|
||||
```
|
||||
|
||||
Then run `go generate` for your package.
|
||||
|
||||
### How to use it
|
||||
|
||||
Mocking interfaces is a nice way to write unit tests where you can easily control the behaviour of the mocked object.
|
||||
|
||||
Moq creates a struct that has a function field for each method, which you can declare in your test code.
|
||||
|
||||
In this example, Moq generated the `EmailSenderMock` type:
|
||||
|
||||
```go
|
||||
func TestCompleteSignup(t *testing.T) {
|
||||
|
||||
var sentTo string
|
||||
|
||||
mockedEmailSender = &EmailSenderMock{
|
||||
SendFunc: func(to, subject, body string) error {
|
||||
sentTo = to
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
CompleteSignUp("me@email.com", mockedEmailSender)
|
||||
|
||||
callsToSend := len(mockedEmailSender.SendCalls())
|
||||
if callsToSend != 1 {
|
||||
t.Errorf("Send was called %d times", callsToSend)
|
||||
}
|
||||
if sentTo != "me@email.com" {
|
||||
t.Errorf("unexpected recipient: %s", sentTo)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func CompleteSignUp(to string, sender EmailSender) {
|
||||
// TODO: this
|
||||
}
|
||||
```
|
||||
|
||||
The mocked structure implements the interface, where each method calls the associated function field.
|
||||
|
||||
## Tips
|
||||
|
||||
* Keep mocked logic inside the test that is using it
|
||||
* Only mock the fields you need
|
||||
* It will panic if a nil function gets called
|
||||
* Name arguments in the interface for a better experience
|
||||
* Use closured variables inside your test function to capture details about the calls to the methods
|
||||
* Use `.MethodCalls()` to track the calls
|
||||
* Use `go:generate` to invoke the `moq` command
|
||||
* If Moq fails with a `go/format` error, it indicates the generated code was not valid.
|
||||
You can run the same command with `-fmt noop` to print the generated source code without attempting to format it.
|
||||
This can aid in debugging the root cause.
|
||||
|
||||
## License
|
||||
|
||||
The Moq project (and all code) is licensed under the [MIT License](LICENSE).
|
||||
|
||||
Moq was created by [Mat Ryer](https://twitter.com/matryer) and [David Hernandez](https://github.com/dahernan), with ideas lovingly stolen from [Ernesto Jimenez](https://github.com/ernesto-jimenez). Featuring a major refactor by @sudo-suhas, as well as lots of other contributors.
|
||||
|
||||
The Moq logo was created by [Chris Ryer](http://chrisryer.co.uk) and is licensed under the [Creative Commons Attribution 3.0 License](https://creativecommons.org/licenses/by/3.0/).
|
||||
|
||||
8
vendor/github.com/matryer/moq/go.mod
generated
vendored
Normal file
8
vendor/github.com/matryer/moq/go.mod
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
module github.com/matryer/moq
|
||||
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/pmezard/go-difflib v1.0.0
|
||||
golang.org/x/tools v0.0.0-20200815165600-90abf76919f3
|
||||
)
|
||||
24
vendor/github.com/matryer/moq/go.sum
generated
vendored
Normal file
24
vendor/github.com/matryer/moq/go.sum
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200815165600-90abf76919f3 h1:0aScV/0rLmANzEYIhjCOi2pTvDyhZNduBUMD2q3iqs4=
|
||||
golang.org/x/tools v0.0.0-20200815165600-90abf76919f3/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
135
vendor/github.com/matryer/moq/internal/registry/method_scope.go
generated
vendored
Normal file
135
vendor/github.com/matryer/moq/internal/registry/method_scope.go
generated
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
package registry
|
||||
|
||||
import (
|
||||
"go/types"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// MethodScope is the sub-registry for allocating variables present in
|
||||
// the method scope.
|
||||
//
|
||||
// It should be created using a registry instance.
|
||||
type MethodScope struct {
|
||||
registry *Registry
|
||||
moqPkgPath string
|
||||
|
||||
vars []*Var
|
||||
conflicted map[string]bool
|
||||
}
|
||||
|
||||
// AddVar allocates a variable instance and adds it to the method scope.
|
||||
//
|
||||
// Variables names are generated if required and are ensured to be
|
||||
// without conflict with other variables and imported packages. It also
|
||||
// adds the relevant imports to the registry for each added variable.
|
||||
func (m *MethodScope) AddVar(vr *types.Var, suffix string) *Var {
|
||||
imports := make(map[string]*Package)
|
||||
m.populateImports(vr.Type(), imports)
|
||||
m.resolveImportVarConflicts(imports)
|
||||
|
||||
name := varName(vr, suffix)
|
||||
// Ensure that the var name does not conflict with a package import.
|
||||
if _, ok := m.registry.searchImport(name); ok {
|
||||
name += "MoqParam"
|
||||
}
|
||||
if _, ok := m.searchVar(name); ok || m.conflicted[name] {
|
||||
name = m.resolveVarNameConflict(name)
|
||||
}
|
||||
|
||||
v := Var{
|
||||
vr: vr,
|
||||
imports: imports,
|
||||
moqPkgPath: m.moqPkgPath,
|
||||
Name: name,
|
||||
}
|
||||
m.vars = append(m.vars, &v)
|
||||
return &v
|
||||
}
|
||||
|
||||
func (m *MethodScope) resolveVarNameConflict(suggested string) string {
|
||||
for n := 1; ; n++ {
|
||||
_, ok := m.searchVar(suggested + strconv.Itoa(n))
|
||||
if ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if n == 1 {
|
||||
conflict, _ := m.searchVar(suggested)
|
||||
conflict.Name += "1"
|
||||
m.conflicted[suggested] = true
|
||||
n++
|
||||
}
|
||||
return suggested + strconv.Itoa(n)
|
||||
}
|
||||
}
|
||||
|
||||
func (m MethodScope) searchVar(name string) (*Var, bool) {
|
||||
for _, v := range m.vars {
|
||||
if v.Name == name {
|
||||
return v, true
|
||||
}
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// populateImports extracts all the package imports for a given type
|
||||
// recursively. The imported packages by a single type can be more than
|
||||
// one (ex: map[a.Type]b.Type).
|
||||
func (m MethodScope) populateImports(t types.Type, imports map[string]*Package) {
|
||||
switch t := t.(type) {
|
||||
case *types.Named:
|
||||
if pkg := t.Obj().Pkg(); pkg != nil {
|
||||
imports[stripVendorPath(pkg.Path())] = m.registry.AddImport(pkg)
|
||||
}
|
||||
|
||||
case *types.Array:
|
||||
m.populateImports(t.Elem(), imports)
|
||||
|
||||
case *types.Slice:
|
||||
m.populateImports(t.Elem(), imports)
|
||||
|
||||
case *types.Signature:
|
||||
for i := 0; i < t.Params().Len(); i++ {
|
||||
m.populateImports(t.Params().At(i).Type(), imports)
|
||||
}
|
||||
for i := 0; i < t.Results().Len(); i++ {
|
||||
m.populateImports(t.Results().At(i).Type(), imports)
|
||||
}
|
||||
|
||||
case *types.Map:
|
||||
m.populateImports(t.Key(), imports)
|
||||
m.populateImports(t.Elem(), imports)
|
||||
|
||||
case *types.Chan:
|
||||
m.populateImports(t.Elem(), imports)
|
||||
|
||||
case *types.Pointer:
|
||||
m.populateImports(t.Elem(), imports)
|
||||
|
||||
case *types.Struct: // anonymous struct
|
||||
for i := 0; i < t.NumFields(); i++ {
|
||||
m.populateImports(t.Field(i).Type(), imports)
|
||||
}
|
||||
|
||||
case *types.Interface: // anonymous interface
|
||||
for i := 0; i < t.NumExplicitMethods(); i++ {
|
||||
m.populateImports(t.ExplicitMethod(i).Type(), imports)
|
||||
}
|
||||
for i := 0; i < t.NumEmbeddeds(); i++ {
|
||||
m.populateImports(t.EmbeddedType(i), imports)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// resolveImportVarConflicts ensures that all the newly added imports do not
|
||||
// conflict with any of the existing vars.
|
||||
func (m MethodScope) resolveImportVarConflicts(imports map[string]*Package) {
|
||||
// Ensure that all the newly added imports do not conflict with any of the
|
||||
// existing vars.
|
||||
for _, imprt := range imports {
|
||||
if v, ok := m.searchVar(imprt.Qualifier()); ok {
|
||||
v.Name += "MoqParam"
|
||||
}
|
||||
}
|
||||
}
|
||||
93
vendor/github.com/matryer/moq/internal/registry/package.go
generated
vendored
Normal file
93
vendor/github.com/matryer/moq/internal/registry/package.go
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
package registry
|
||||
|
||||
import (
|
||||
"go/types"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Package represents an imported package.
|
||||
type Package struct {
|
||||
pkg *types.Package
|
||||
|
||||
Alias string
|
||||
}
|
||||
|
||||
// NewPackage creates a new instance of Package.
|
||||
func NewPackage(pkg *types.Package) *Package { return &Package{pkg: pkg} }
|
||||
|
||||
// Qualifier returns the qualifier which must be used to refer to types
|
||||
// declared in the package.
|
||||
func (p *Package) Qualifier() string {
|
||||
if p == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
if p.Alias != "" {
|
||||
return p.Alias
|
||||
}
|
||||
|
||||
return p.pkg.Name()
|
||||
}
|
||||
|
||||
// Path is the full package import path (without vendor).
|
||||
func (p *Package) Path() string {
|
||||
if p == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return stripVendorPath(p.pkg.Path())
|
||||
}
|
||||
|
||||
var replacer = strings.NewReplacer(
|
||||
"go-", "",
|
||||
"-go", "",
|
||||
"-", "",
|
||||
"_", "",
|
||||
".", "",
|
||||
"@", "",
|
||||
"+", "",
|
||||
"~", "",
|
||||
)
|
||||
|
||||
// uniqueName generates a unique name for a package by concatenating
|
||||
// path components. The generated name is guaranteed to unique with an
|
||||
// appropriate level because the full package import paths themselves
|
||||
// are unique.
|
||||
func (p Package) uniqueName(lvl int) string {
|
||||
pp := strings.Split(p.Path(), "/")
|
||||
reverse(pp)
|
||||
|
||||
var name string
|
||||
for i := 0; i < min(len(pp), lvl+1); i++ {
|
||||
name = strings.ToLower(replacer.Replace(pp[i])) + name
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
|
||||
// stripVendorPath strips the vendor dir prefix from a package path.
|
||||
// For example we might encounter an absolute path like
|
||||
// github.com/foo/bar/vendor/github.com/pkg/errors which is resolved
|
||||
// to github.com/pkg/errors.
|
||||
func stripVendorPath(p string) string {
|
||||
parts := strings.Split(p, "/vendor/")
|
||||
if len(parts) == 1 {
|
||||
return p
|
||||
}
|
||||
return strings.TrimLeft(path.Join(parts[1:]...), "/")
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func reverse(a []string) {
|
||||
for i := len(a)/2 - 1; i >= 0; i-- {
|
||||
opp := len(a) - 1 - i
|
||||
a[i], a[opp] = a[opp], a[i]
|
||||
}
|
||||
}
|
||||
190
vendor/github.com/matryer/moq/internal/registry/registry.go
generated
vendored
Normal file
190
vendor/github.com/matryer/moq/internal/registry/registry.go
generated
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
package registry
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/types"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
// Registry encapsulates types information for the source and mock
|
||||
// destination package. For the mock package, it tracks the list of
|
||||
// imports and ensures there are no conflicts in the imported package
|
||||
// qualifiers.
|
||||
type Registry struct {
|
||||
srcPkg *packages.Package
|
||||
moqPkgPath string
|
||||
aliases map[string]string
|
||||
imports map[string]*Package
|
||||
}
|
||||
|
||||
// New loads the source package info and returns a new instance of
|
||||
// Registry.
|
||||
func New(srcDir, moqPkg string) (*Registry, error) {
|
||||
srcPkg, err := pkgInfoFromPath(
|
||||
srcDir, packages.NeedName|packages.NeedSyntax|packages.NeedTypes|packages.NeedTypesInfo,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't load source package: %s", err)
|
||||
}
|
||||
|
||||
return &Registry{
|
||||
srcPkg: srcPkg,
|
||||
moqPkgPath: findPkgPath(moqPkg, srcPkg),
|
||||
aliases: parseImportsAliases(srcPkg),
|
||||
imports: make(map[string]*Package),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SrcPkg returns the types info for the source package.
|
||||
func (r Registry) SrcPkg() *types.Package {
|
||||
return r.srcPkg.Types
|
||||
}
|
||||
|
||||
// SrcPkgName returns the name of the source package.
|
||||
func (r Registry) SrcPkgName() string {
|
||||
return r.srcPkg.Name
|
||||
}
|
||||
|
||||
// LookupInterface returns the underlying interface definition of the
|
||||
// given interface name.
|
||||
func (r Registry) LookupInterface(name string) (*types.Interface, error) {
|
||||
obj := r.SrcPkg().Scope().Lookup(name)
|
||||
if obj == nil {
|
||||
return nil, fmt.Errorf("interface not found: %s", name)
|
||||
}
|
||||
|
||||
if !types.IsInterface(obj.Type()) {
|
||||
return nil, fmt.Errorf("%s (%s) is not an interface", name, obj.Type())
|
||||
}
|
||||
|
||||
return obj.Type().Underlying().(*types.Interface).Complete(), nil
|
||||
}
|
||||
|
||||
// MethodScope returns a new MethodScope.
|
||||
func (r *Registry) MethodScope() *MethodScope {
|
||||
return &MethodScope{
|
||||
registry: r,
|
||||
moqPkgPath: r.moqPkgPath,
|
||||
conflicted: map[string]bool{},
|
||||
}
|
||||
}
|
||||
|
||||
// AddImport adds the given package to the set of imports. It generates a
|
||||
// suitable alias if there are any conflicts with previously imported
|
||||
// packages.
|
||||
func (r *Registry) AddImport(pkg *types.Package) *Package {
|
||||
path := stripVendorPath(pkg.Path())
|
||||
if path == r.moqPkgPath {
|
||||
return nil
|
||||
}
|
||||
|
||||
if imprt, ok := r.imports[path]; ok {
|
||||
return imprt
|
||||
}
|
||||
|
||||
imprt := Package{pkg: pkg, Alias: r.aliases[path]}
|
||||
|
||||
if conflict, ok := r.searchImport(imprt.Qualifier()); ok {
|
||||
resolveImportConflict(&imprt, conflict, 0)
|
||||
}
|
||||
|
||||
r.imports[path] = &imprt
|
||||
return &imprt
|
||||
}
|
||||
|
||||
// Imports returns the list of imported packages. The list is sorted by
|
||||
// path.
|
||||
func (r Registry) Imports() []*Package {
|
||||
imports := make([]*Package, 0, len(r.imports))
|
||||
for _, imprt := range r.imports {
|
||||
imports = append(imports, imprt)
|
||||
}
|
||||
sort.Slice(imports, func(i, j int) bool {
|
||||
return imports[i].Path() < imports[j].Path()
|
||||
})
|
||||
return imports
|
||||
}
|
||||
|
||||
func (r Registry) searchImport(name string) (*Package, bool) {
|
||||
for _, imprt := range r.imports {
|
||||
if imprt.Qualifier() == name {
|
||||
return imprt, true
|
||||
}
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func pkgInfoFromPath(srcDir string, mode packages.LoadMode) (*packages.Package, error) {
|
||||
pkgs, err := packages.Load(&packages.Config{
|
||||
Mode: mode,
|
||||
Dir: srcDir,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(pkgs) == 0 {
|
||||
return nil, errors.New("package not found")
|
||||
}
|
||||
if len(pkgs) > 1 {
|
||||
return nil, errors.New("found more than one package")
|
||||
}
|
||||
if errs := pkgs[0].Errors; len(errs) != 0 {
|
||||
if len(errs) == 1 {
|
||||
return nil, errs[0]
|
||||
}
|
||||
return nil, fmt.Errorf("%s (and %d more errors)", errs[0], len(errs)-1)
|
||||
}
|
||||
return pkgs[0], nil
|
||||
}
|
||||
|
||||
func findPkgPath(pkgInputVal string, srcPkg *packages.Package) string {
|
||||
if pkgInputVal == "" {
|
||||
return srcPkg.PkgPath
|
||||
}
|
||||
if pkgInDir(srcPkg.PkgPath, pkgInputVal) {
|
||||
return srcPkg.PkgPath
|
||||
}
|
||||
subdirectoryPath := filepath.Join(srcPkg.PkgPath, pkgInputVal)
|
||||
if pkgInDir(subdirectoryPath, pkgInputVal) {
|
||||
return subdirectoryPath
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func pkgInDir(pkgName, dir string) bool {
|
||||
currentPkg, err := pkgInfoFromPath(dir, packages.NeedName)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return currentPkg.Name == pkgName || currentPkg.Name+"_test" == pkgName
|
||||
}
|
||||
|
||||
func parseImportsAliases(pkg *packages.Package) map[string]string {
|
||||
aliases := make(map[string]string)
|
||||
for _, syntax := range pkg.Syntax {
|
||||
for _, imprt := range syntax.Imports {
|
||||
if imprt.Name != nil && imprt.Name.Name != "." && imprt.Name.Name != "_" {
|
||||
aliases[strings.Trim(imprt.Path.Value, `"`)] = imprt.Name.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
return aliases
|
||||
}
|
||||
|
||||
// resolveImportConflict generates and assigns a unique alias for
|
||||
// packages with conflicting qualifiers.
|
||||
func resolveImportConflict(a, b *Package, lvl int) {
|
||||
u1, u2 := a.uniqueName(lvl), b.uniqueName(lvl)
|
||||
if u1 != u2 {
|
||||
a.Alias, b.Alias = u1, u2
|
||||
return
|
||||
}
|
||||
|
||||
resolveImportConflict(a, b, lvl+1)
|
||||
}
|
||||
141
vendor/github.com/matryer/moq/internal/registry/var.go
generated
vendored
Normal file
141
vendor/github.com/matryer/moq/internal/registry/var.go
generated
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
package registry
|
||||
|
||||
import (
|
||||
"go/types"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Var represents a method variable/parameter.
|
||||
//
|
||||
// It should be created using a method scope instance.
|
||||
type Var struct {
|
||||
vr *types.Var
|
||||
imports map[string]*Package
|
||||
moqPkgPath string
|
||||
|
||||
Name string
|
||||
}
|
||||
|
||||
// IsSlice returns whether the type (or the underlying type) is a slice.
|
||||
func (v Var) IsSlice() bool {
|
||||
_, ok := v.vr.Type().Underlying().(*types.Slice)
|
||||
return ok
|
||||
}
|
||||
|
||||
// TypeString returns the variable type with the package qualifier in the
|
||||
// format 'pkg.Type'.
|
||||
func (v Var) TypeString() string {
|
||||
return types.TypeString(v.vr.Type(), v.packageQualifier)
|
||||
}
|
||||
|
||||
// packageQualifier is a types.Qualifier.
|
||||
func (v Var) packageQualifier(pkg *types.Package) string {
|
||||
path := stripVendorPath(pkg.Path())
|
||||
if v.moqPkgPath != "" && v.moqPkgPath == path {
|
||||
return ""
|
||||
}
|
||||
|
||||
return v.imports[path].Qualifier()
|
||||
}
|
||||
|
||||
func varName(vr *types.Var, suffix string) string {
|
||||
name := vr.Name()
|
||||
if name != "" && name != "_" {
|
||||
return name + suffix
|
||||
}
|
||||
|
||||
name = varNameForType(vr.Type()) + suffix
|
||||
|
||||
switch name {
|
||||
case "mock", "callInfo", "break", "default", "func", "interface", "select", "case", "defer", "go", "map", "struct",
|
||||
"chan", "else", "goto", "package", "switch", "const", "fallthrough", "if", "range", "type", "continue", "for",
|
||||
"import", "return", "var":
|
||||
name += "MoqParam"
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
|
||||
// varNameForType generates a name for the variable using the type
|
||||
// information.
|
||||
//
|
||||
// Examples:
|
||||
// - string -> s
|
||||
// - int -> n
|
||||
// - chan int -> intCh
|
||||
// - []a.MyType -> myTypes
|
||||
// - map[string]int -> stringToInt
|
||||
// - error -> err
|
||||
// - a.MyType -> myType
|
||||
func varNameForType(t types.Type) string {
|
||||
nestedType := func(t types.Type) string {
|
||||
if t, ok := t.(*types.Basic); ok {
|
||||
return deCapitalise(t.String())
|
||||
}
|
||||
return varNameForType(t)
|
||||
}
|
||||
|
||||
switch t := t.(type) {
|
||||
case *types.Named:
|
||||
if t.Obj().Name() == "error" {
|
||||
return "err"
|
||||
}
|
||||
|
||||
name := deCapitalise(t.Obj().Name())
|
||||
if name == t.Obj().Name() {
|
||||
name += "MoqParam"
|
||||
}
|
||||
|
||||
return name
|
||||
|
||||
case *types.Basic:
|
||||
return basicTypeVarName(t)
|
||||
|
||||
case *types.Array:
|
||||
return nestedType(t.Elem()) + "s"
|
||||
|
||||
case *types.Slice:
|
||||
return nestedType(t.Elem()) + "s"
|
||||
|
||||
case *types.Struct: // anonymous struct
|
||||
return "val"
|
||||
|
||||
case *types.Pointer:
|
||||
return varNameForType(t.Elem())
|
||||
|
||||
case *types.Signature:
|
||||
return "fn"
|
||||
|
||||
case *types.Interface: // anonymous interface
|
||||
return "ifaceVal"
|
||||
|
||||
case *types.Map:
|
||||
return nestedType(t.Key()) + "To" + capitalise(nestedType(t.Elem()))
|
||||
|
||||
case *types.Chan:
|
||||
return nestedType(t.Elem()) + "Ch"
|
||||
}
|
||||
|
||||
return "v"
|
||||
}
|
||||
|
||||
func basicTypeVarName(b *types.Basic) string {
|
||||
switch b.Info() {
|
||||
case types.IsBoolean:
|
||||
return "b"
|
||||
|
||||
case types.IsInteger:
|
||||
return "n"
|
||||
|
||||
case types.IsFloat:
|
||||
return "f"
|
||||
|
||||
case types.IsString:
|
||||
return "s"
|
||||
}
|
||||
|
||||
return "v"
|
||||
}
|
||||
|
||||
func capitalise(s string) string { return strings.ToUpper(s[:1]) + s[1:] }
|
||||
func deCapitalise(s string) string { return strings.ToLower(s[:1]) + s[1:] }
|
||||
190
vendor/github.com/matryer/moq/internal/template/template.go
generated
vendored
Normal file
190
vendor/github.com/matryer/moq/internal/template/template.go
generated
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
package template
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/matryer/moq/internal/registry"
|
||||
)
|
||||
|
||||
// Template is the Moq template. It is capable of generating the Moq
|
||||
// implementation for the given template.Data.
|
||||
type Template struct {
|
||||
tmpl *template.Template
|
||||
}
|
||||
|
||||
// New returns a new instance of Template.
|
||||
func New() (Template, error) {
|
||||
tmpl, err := template.New("moq").Funcs(templateFuncs).Parse(moqTemplate)
|
||||
if err != nil {
|
||||
return Template{}, err
|
||||
}
|
||||
|
||||
return Template{tmpl: tmpl}, nil
|
||||
}
|
||||
|
||||
// Execute generates and writes the Moq implementation for the given
|
||||
// data.
|
||||
func (t Template) Execute(w io.Writer, data Data) error {
|
||||
return t.tmpl.Execute(w, data)
|
||||
}
|
||||
|
||||
// moqTemplate is the template for mocked code.
|
||||
// language=GoTemplate
|
||||
var moqTemplate = `// Code generated by moq; DO NOT EDIT.
|
||||
// github.com/matryer/moq
|
||||
|
||||
package {{.PkgName}}
|
||||
|
||||
import (
|
||||
{{- range .Imports}}
|
||||
{{. | ImportStatement}}
|
||||
{{- end}}
|
||||
)
|
||||
|
||||
{{range $i, $mock := .Mocks -}}
|
||||
|
||||
{{- if not $.SkipEnsure -}}
|
||||
// Ensure, that {{.MockName}} does implement {{$.SrcPkgQualifier}}{{.InterfaceName}}.
|
||||
// If this is not the case, regenerate this file with moq.
|
||||
var _ {{$.SrcPkgQualifier}}{{.InterfaceName}} = &{{.MockName}}{}
|
||||
{{- end}}
|
||||
|
||||
// {{.MockName}} is a mock implementation of {{$.SrcPkgQualifier}}{{.InterfaceName}}.
|
||||
//
|
||||
// func TestSomethingThatUses{{.InterfaceName}}(t *testing.T) {
|
||||
//
|
||||
// // make and configure a mocked {{$.SrcPkgQualifier}}{{.InterfaceName}}
|
||||
// mocked{{.InterfaceName}} := &{{.MockName}}{
|
||||
{{- range .Methods}}
|
||||
// {{.Name}}Func: func({{.ArgList}}) {{.ReturnArgTypeList}} {
|
||||
// panic("mock out the {{.Name}} method")
|
||||
// },
|
||||
{{- end}}
|
||||
// }
|
||||
//
|
||||
// // use mocked{{.InterfaceName}} in code that requires {{$.SrcPkgQualifier}}{{.InterfaceName}}
|
||||
// // and then make assertions.
|
||||
//
|
||||
// }
|
||||
type {{.MockName}} struct {
|
||||
{{- range .Methods}}
|
||||
// {{.Name}}Func mocks the {{.Name}} method.
|
||||
{{.Name}}Func func({{.ArgList}}) {{.ReturnArgTypeList}}
|
||||
{{end}}
|
||||
// calls tracks calls to the methods.
|
||||
calls struct {
|
||||
{{- range .Methods}}
|
||||
// {{.Name}} holds details about calls to the {{.Name}} method.
|
||||
{{.Name}} []struct {
|
||||
{{- range .Params}}
|
||||
// {{.Name | Exported}} is the {{.Name}} argument value.
|
||||
{{.Name | Exported}} {{.TypeString}}
|
||||
{{- end}}
|
||||
}
|
||||
{{- end}}
|
||||
}
|
||||
{{- range .Methods}}
|
||||
lock{{.Name}} {{$.Imports | SyncPkgQualifier}}.RWMutex
|
||||
{{- end}}
|
||||
}
|
||||
{{range .Methods}}
|
||||
// {{.Name}} calls {{.Name}}Func.
|
||||
func (mock *{{$mock.MockName}}) {{.Name}}({{.ArgList}}) {{.ReturnArgTypeList}} {
|
||||
{{- if not $.StubImpl}}
|
||||
if mock.{{.Name}}Func == nil {
|
||||
panic("{{$mock.MockName}}.{{.Name}}Func: method is nil but {{$mock.InterfaceName}}.{{.Name}} was just called")
|
||||
}
|
||||
{{- end}}
|
||||
callInfo := struct {
|
||||
{{- range .Params}}
|
||||
{{.Name | Exported}} {{.TypeString}}
|
||||
{{- end}}
|
||||
}{
|
||||
{{- range .Params}}
|
||||
{{.Name | Exported}}: {{.Name}},
|
||||
{{- end}}
|
||||
}
|
||||
mock.lock{{.Name}}.Lock()
|
||||
mock.calls.{{.Name}} = append(mock.calls.{{.Name}}, callInfo)
|
||||
mock.lock{{.Name}}.Unlock()
|
||||
{{- if .Returns}}
|
||||
{{- if $.StubImpl}}
|
||||
if mock.{{.Name}}Func == nil {
|
||||
var (
|
||||
{{- range .Returns}}
|
||||
{{.Name}} {{.TypeString}}
|
||||
{{- end}}
|
||||
)
|
||||
return {{.ReturnArgNameList}}
|
||||
}
|
||||
{{- end}}
|
||||
return mock.{{.Name}}Func({{.ArgCallList}})
|
||||
{{- else}}
|
||||
{{- if $.StubImpl}}
|
||||
if mock.{{.Name}}Func == nil {
|
||||
return
|
||||
}
|
||||
{{- end}}
|
||||
mock.{{.Name}}Func({{.ArgCallList}})
|
||||
{{- end}}
|
||||
}
|
||||
|
||||
// {{.Name}}Calls gets all the calls that were made to {{.Name}}.
|
||||
// Check the length with:
|
||||
// len(mocked{{$mock.InterfaceName}}.{{.Name}}Calls())
|
||||
func (mock *{{$mock.MockName}}) {{.Name}}Calls() []struct {
|
||||
{{- range .Params}}
|
||||
{{.Name | Exported}} {{.TypeString}}
|
||||
{{- end}}
|
||||
} {
|
||||
var calls []struct {
|
||||
{{- range .Params}}
|
||||
{{.Name | Exported}} {{.TypeString}}
|
||||
{{- end}}
|
||||
}
|
||||
mock.lock{{.Name}}.RLock()
|
||||
calls = mock.calls.{{.Name}}
|
||||
mock.lock{{.Name}}.RUnlock()
|
||||
return calls
|
||||
}
|
||||
{{end -}}
|
||||
{{end -}}`
|
||||
|
||||
// This list comes from the golint codebase. Golint will complain about any of
|
||||
// these being mixed-case, like "Id" instead of "ID".
|
||||
var golintInitialisms = []string{
|
||||
"ACL", "API", "ASCII", "CPU", "CSS", "DNS", "EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID", "IP", "JSON", "LHS",
|
||||
"QPS", "RAM", "RHS", "RPC", "SLA", "SMTP", "SQL", "SSH", "TCP", "TLS", "TTL", "UDP", "UI", "UID", "UUID", "URI",
|
||||
"URL", "UTF8", "VM", "XML", "XMPP", "XSRF", "XSS",
|
||||
}
|
||||
|
||||
var templateFuncs = template.FuncMap{
|
||||
"ImportStatement": func(imprt *registry.Package) string {
|
||||
if imprt.Alias == "" {
|
||||
return `"` + imprt.Path() + `"`
|
||||
}
|
||||
return imprt.Alias + ` "` + imprt.Path() + `"`
|
||||
},
|
||||
"SyncPkgQualifier": func(imports []*registry.Package) string {
|
||||
for _, imprt := range imports {
|
||||
if imprt.Path() == "sync" {
|
||||
return imprt.Qualifier()
|
||||
}
|
||||
}
|
||||
|
||||
return "sync"
|
||||
},
|
||||
"Exported": func(s string) string {
|
||||
if s == "" {
|
||||
return ""
|
||||
}
|
||||
for _, initialism := range golintInitialisms {
|
||||
if strings.ToUpper(s) == initialism {
|
||||
return initialism
|
||||
}
|
||||
}
|
||||
return strings.ToUpper(s[0:1]) + s[1:]
|
||||
},
|
||||
}
|
||||
125
vendor/github.com/matryer/moq/internal/template/template_data.go
generated
vendored
Normal file
125
vendor/github.com/matryer/moq/internal/template/template_data.go
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
package template
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/matryer/moq/internal/registry"
|
||||
)
|
||||
|
||||
// Data is the template data used to render the Moq template.
|
||||
type Data struct {
|
||||
PkgName string
|
||||
SrcPkgQualifier string
|
||||
Imports []*registry.Package
|
||||
Mocks []MockData
|
||||
StubImpl bool
|
||||
SkipEnsure bool
|
||||
}
|
||||
|
||||
// MocksSomeMethod returns true of any one of the Mocks has at least 1
|
||||
// method.
|
||||
func (d Data) MocksSomeMethod() bool {
|
||||
for _, m := range d.Mocks {
|
||||
if len(m.Methods) > 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// MockData is the data used to generate a mock for some interface.
|
||||
type MockData struct {
|
||||
InterfaceName string
|
||||
MockName string
|
||||
Methods []MethodData
|
||||
}
|
||||
|
||||
// MethodData is the data which represents a method on some interface.
|
||||
type MethodData struct {
|
||||
Name string
|
||||
Params []ParamData
|
||||
Returns []ParamData
|
||||
}
|
||||
|
||||
// ArgList is the string representation of method parameters, ex:
|
||||
// 's string, n int, foo bar.Baz'.
|
||||
func (m MethodData) ArgList() string {
|
||||
params := make([]string, len(m.Params))
|
||||
for i, p := range m.Params {
|
||||
params[i] = p.MethodArg()
|
||||
}
|
||||
return strings.Join(params, ", ")
|
||||
}
|
||||
|
||||
// ArgCallList is the string representation of method call parameters,
|
||||
// ex: 's, n, foo'. In case of a last variadic parameter, it will be of
|
||||
// the format 's, n, foos...'
|
||||
func (m MethodData) ArgCallList() string {
|
||||
params := make([]string, len(m.Params))
|
||||
for i, p := range m.Params {
|
||||
params[i] = p.CallName()
|
||||
}
|
||||
return strings.Join(params, ", ")
|
||||
}
|
||||
|
||||
// ReturnArgTypeList is the string representation of method return
|
||||
// types, ex: 'bar.Baz', '(string, error)'.
|
||||
func (m MethodData) ReturnArgTypeList() string {
|
||||
params := make([]string, len(m.Returns))
|
||||
for i, p := range m.Returns {
|
||||
params[i] = p.TypeString()
|
||||
}
|
||||
if len(m.Returns) > 1 {
|
||||
return fmt.Sprintf("(%s)", strings.Join(params, ", "))
|
||||
}
|
||||
return strings.Join(params, ", ")
|
||||
}
|
||||
|
||||
// ReturnArgNameList is the string representation of values being
|
||||
// returned from the method, ex: 'foo', 's, err'.
|
||||
func (m MethodData) ReturnArgNameList() string {
|
||||
params := make([]string, len(m.Returns))
|
||||
for i, p := range m.Returns {
|
||||
params[i] = p.Name()
|
||||
}
|
||||
return strings.Join(params, ", ")
|
||||
}
|
||||
|
||||
// ParamData is the data which represents a parameter to some method of
|
||||
// an interface.
|
||||
type ParamData struct {
|
||||
Var *registry.Var
|
||||
Variadic bool
|
||||
}
|
||||
|
||||
// Name returns the name of the parameter.
|
||||
func (p ParamData) Name() string {
|
||||
return p.Var.Name
|
||||
}
|
||||
|
||||
// MethodArg is the representation of the parameter in the function
|
||||
// signature, ex: 'name a.Type'.
|
||||
func (p ParamData) MethodArg() string {
|
||||
if p.Variadic {
|
||||
return fmt.Sprintf("%s ...%s", p.Name(), p.TypeString()[2:])
|
||||
}
|
||||
return fmt.Sprintf("%s %s", p.Name(), p.TypeString())
|
||||
}
|
||||
|
||||
// CallName returns the string representation of the parameter to be
|
||||
// used for a method call. For a variadic paramter, it will be of the
|
||||
// format 'foos...'.
|
||||
func (p ParamData) CallName() string {
|
||||
if p.Variadic {
|
||||
return p.Name() + "..."
|
||||
}
|
||||
return p.Name()
|
||||
}
|
||||
|
||||
// TypeString returns the string representation of the type of the
|
||||
// parameter.
|
||||
func (p ParamData) TypeString() string {
|
||||
return p.Var.TypeString()
|
||||
}
|
||||
109
vendor/github.com/matryer/moq/main.go
generated
vendored
Normal file
109
vendor/github.com/matryer/moq/main.go
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/matryer/moq/pkg/moq"
|
||||
)
|
||||
|
||||
// Version is the command version, injected at build time.
|
||||
var Version string = "dev"
|
||||
|
||||
type userFlags struct {
|
||||
outFile string
|
||||
pkgName string
|
||||
formatter string
|
||||
stubImpl bool
|
||||
skipEnsure bool
|
||||
remove bool
|
||||
args []string
|
||||
}
|
||||
|
||||
func main() {
|
||||
var flags userFlags
|
||||
flag.StringVar(&flags.outFile, "out", "", "output file (default stdout)")
|
||||
flag.StringVar(&flags.pkgName, "pkg", "", "package name (default will infer)")
|
||||
flag.StringVar(&flags.formatter, "fmt", "", "go pretty-printer: gofmt, goimports or noop (default gofmt)")
|
||||
flag.BoolVar(&flags.stubImpl, "stub", false,
|
||||
"return zero values when no mock implementation is provided, do not panic")
|
||||
printVersion := flag.Bool("version", false, "show the version for moq")
|
||||
flag.BoolVar(&flags.skipEnsure, "skip-ensure", false,
|
||||
"suppress mock implementation check, avoid import cycle if mocks generated outside of the tested package")
|
||||
flag.BoolVar(&flags.remove, "rm", false, "first remove output file, if it exists")
|
||||
|
||||
flag.Usage = func() {
|
||||
fmt.Println(`moq [flags] source-dir interface [interface2 [interface3 [...]]]`)
|
||||
flag.PrintDefaults()
|
||||
fmt.Println(`Specifying an alias for the mock is also supported with the format 'interface:alias'`)
|
||||
fmt.Println(`Ex: moq -pkg different . MyInterface:MyMock`)
|
||||
}
|
||||
|
||||
flag.Parse()
|
||||
flags.args = flag.Args()
|
||||
|
||||
if *printVersion {
|
||||
fmt.Printf("moq version %s\n", Version)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if err := run(flags); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
flag.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func run(flags userFlags) error {
|
||||
if len(flags.args) < 2 {
|
||||
return errors.New("not enough arguments")
|
||||
}
|
||||
|
||||
if flags.remove && flags.outFile != "" {
|
||||
if err := os.Remove(flags.outFile); err != nil {
|
||||
if !errors.Is(err, os.ErrNotExist) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
var out io.Writer = os.Stdout
|
||||
if flags.outFile != "" {
|
||||
out = &buf
|
||||
}
|
||||
|
||||
srcDir, args := flags.args[0], flags.args[1:]
|
||||
m, err := moq.New(moq.Config{
|
||||
SrcDir: srcDir,
|
||||
PkgName: flags.pkgName,
|
||||
Formatter: flags.formatter,
|
||||
StubImpl: flags.stubImpl,
|
||||
SkipEnsure: flags.skipEnsure,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = m.Mock(out, args...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if flags.outFile == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// create the file
|
||||
err = os.MkdirAll(filepath.Dir(flags.outFile), 0750)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ioutil.WriteFile(flags.outFile, buf.Bytes(), 0600)
|
||||
}
|
||||
BIN
vendor/github.com/matryer/moq/moq-logo-small.png
generated
vendored
Normal file
BIN
vendor/github.com/matryer/moq/moq-logo-small.png
generated
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
vendor/github.com/matryer/moq/moq-logo.png
generated
vendored
Normal file
BIN
vendor/github.com/matryer/moq/moq-logo.png
generated
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
31
vendor/github.com/matryer/moq/pkg/moq/formatter.go
generated
vendored
Normal file
31
vendor/github.com/matryer/moq/pkg/moq/formatter.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
package moq
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/format"
|
||||
|
||||
"golang.org/x/tools/imports"
|
||||
)
|
||||
|
||||
func goimports(src []byte) ([]byte, error) {
|
||||
formatted, err := imports.Process("filename", src, &imports.Options{
|
||||
TabWidth: 8,
|
||||
TabIndent: true,
|
||||
Comments: true,
|
||||
Fragment: true,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("goimports: %s", err)
|
||||
}
|
||||
|
||||
return formatted, nil
|
||||
}
|
||||
|
||||
func gofmt(src []byte) ([]byte, error) {
|
||||
formatted, err := format.Source(src)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("go/format: %s", err)
|
||||
}
|
||||
|
||||
return formatted, nil
|
||||
}
|
||||
171
vendor/github.com/matryer/moq/pkg/moq/moq.go
generated
vendored
Normal file
171
vendor/github.com/matryer/moq/pkg/moq/moq.go
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
package moq
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"go/types"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/matryer/moq/internal/registry"
|
||||
"github.com/matryer/moq/internal/template"
|
||||
)
|
||||
|
||||
// Mocker can generate mock structs.
|
||||
type Mocker struct {
|
||||
cfg Config
|
||||
|
||||
registry *registry.Registry
|
||||
tmpl template.Template
|
||||
}
|
||||
|
||||
// Config specifies details about how interfaces should be mocked.
|
||||
// SrcDir is the only field which needs be specified.
|
||||
type Config struct {
|
||||
SrcDir string
|
||||
PkgName string
|
||||
Formatter string
|
||||
StubImpl bool
|
||||
SkipEnsure bool
|
||||
}
|
||||
|
||||
// New makes a new Mocker for the specified package directory.
|
||||
func New(cfg Config) (*Mocker, error) {
|
||||
reg, err := registry.New(cfg.SrcDir, cfg.PkgName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tmpl, err := template.New()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Mocker{
|
||||
cfg: cfg,
|
||||
registry: reg,
|
||||
tmpl: tmpl,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Mock generates a mock for the specified interface name.
|
||||
func (m *Mocker) Mock(w io.Writer, namePairs ...string) error {
|
||||
if len(namePairs) == 0 {
|
||||
return errors.New("must specify one interface")
|
||||
}
|
||||
|
||||
mocks := make([]template.MockData, len(namePairs))
|
||||
for i, np := range namePairs {
|
||||
name, mockName := parseInterfaceName(np)
|
||||
iface, err := m.registry.LookupInterface(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
methods := make([]template.MethodData, iface.NumMethods())
|
||||
for j := 0; j < iface.NumMethods(); j++ {
|
||||
methods[j] = m.methodData(iface.Method(j))
|
||||
}
|
||||
|
||||
mocks[i] = template.MockData{
|
||||
InterfaceName: name,
|
||||
MockName: mockName,
|
||||
Methods: methods,
|
||||
}
|
||||
}
|
||||
|
||||
data := template.Data{
|
||||
PkgName: m.mockPkgName(),
|
||||
Mocks: mocks,
|
||||
StubImpl: m.cfg.StubImpl,
|
||||
SkipEnsure: m.cfg.SkipEnsure,
|
||||
}
|
||||
|
||||
if data.MocksSomeMethod() {
|
||||
m.registry.AddImport(types.NewPackage("sync", "sync"))
|
||||
}
|
||||
if m.registry.SrcPkgName() != m.mockPkgName() {
|
||||
data.SrcPkgQualifier = m.registry.SrcPkgName() + "."
|
||||
if !m.cfg.SkipEnsure {
|
||||
imprt := m.registry.AddImport(m.registry.SrcPkg())
|
||||
data.SrcPkgQualifier = imprt.Qualifier() + "."
|
||||
}
|
||||
}
|
||||
|
||||
data.Imports = m.registry.Imports()
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := m.tmpl.Execute(&buf, data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
formatted, err := m.format(buf.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := w.Write(formatted); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Mocker) methodData(f *types.Func) template.MethodData {
|
||||
sig := f.Type().(*types.Signature)
|
||||
|
||||
scope := m.registry.MethodScope()
|
||||
n := sig.Params().Len()
|
||||
params := make([]template.ParamData, n)
|
||||
for i := 0; i < n; i++ {
|
||||
p := template.ParamData{
|
||||
Var: scope.AddVar(sig.Params().At(i), ""),
|
||||
}
|
||||
p.Variadic = sig.Variadic() && i == n-1 && p.Var.IsSlice() // check for final variadic argument
|
||||
|
||||
params[i] = p
|
||||
}
|
||||
|
||||
n = sig.Results().Len()
|
||||
results := make([]template.ParamData, n)
|
||||
for i := 0; i < n; i++ {
|
||||
results[i] = template.ParamData{
|
||||
Var: scope.AddVar(sig.Results().At(i), "Out"),
|
||||
}
|
||||
}
|
||||
|
||||
return template.MethodData{
|
||||
Name: f.Name(),
|
||||
Params: params,
|
||||
Returns: results,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Mocker) mockPkgName() string {
|
||||
if m.cfg.PkgName != "" {
|
||||
return m.cfg.PkgName
|
||||
}
|
||||
|
||||
return m.registry.SrcPkgName()
|
||||
}
|
||||
|
||||
func (m *Mocker) format(src []byte) ([]byte, error) {
|
||||
switch m.cfg.Formatter {
|
||||
case "goimports":
|
||||
return goimports(src)
|
||||
|
||||
case "noop":
|
||||
return src, nil
|
||||
}
|
||||
|
||||
return gofmt(src)
|
||||
}
|
||||
|
||||
func parseInterfaceName(namePair string) (ifaceName, mockName string) {
|
||||
parts := strings.SplitN(namePair, ":", 2)
|
||||
if len(parts) == 2 {
|
||||
return parts[0], parts[1]
|
||||
}
|
||||
|
||||
ifaceName = parts[0]
|
||||
return ifaceName, ifaceName + "Mock"
|
||||
}
|
||||
BIN
vendor/github.com/matryer/moq/preview.png
generated
vendored
Normal file
BIN
vendor/github.com/matryer/moq/preview.png
generated
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 726 KiB |
28
vendor/github.com/matryer/moq/releasing.md
generated
vendored
Normal file
28
vendor/github.com/matryer/moq/releasing.md
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
# Releasing
|
||||
|
||||
This tool uses Go Releaser to manage release builds.
|
||||
|
||||
## Setup
|
||||
|
||||
Install Go Releaser.
|
||||
|
||||
```bash
|
||||
brew install goreleaser/tap/goreleaser
|
||||
```
|
||||
|
||||
* Make a [New personal access token on GitHub](https://github.com/settings/tokens/new) and set it as the `GITHUB_TOKEN` environment variable
|
||||
|
||||
## Releasing
|
||||
|
||||
Tag the repo:
|
||||
|
||||
```bash
|
||||
$ git tag -a v0.1.0 -m "release tag."
|
||||
$ git push origin v0.1.0
|
||||
```
|
||||
|
||||
Then:
|
||||
|
||||
```bash
|
||||
GITHUB_TOKEN=xxx goreleaser --rm-dist
|
||||
```
|
||||
Reference in New Issue
Block a user