Add v16.7.2

This commit is contained in:
Jan Stabenow
2022-05-13 19:26:45 +02:00
parent 8e70517dff
commit 9c0b535199
2368 changed files with 687657 additions and 1 deletions

29
vendor/github.com/matryer/moq/.gitignore generated vendored Normal file
View 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
View 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
View 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
View File

@@ -0,0 +1,135 @@
![moq logo](moq-logo-small.png) [![build](https://github.com/matryer/moq/workflows/build/badge.svg)](https://github.com/matryer/moq/actions?query=branch%3Amaster) [![Go Report Card](https://goreportcard.com/badge/github.com/matryer/moq)](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.
![Preview](preview.png)
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
View 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
View 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=

View 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"
}
}
}

View 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]
}
}

View 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
View 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:] }

View 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:]
},
}

View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

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
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 726 KiB

28
vendor/github.com/matryer/moq/releasing.md generated vendored Normal file
View 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
```