Internal registry for disambiguated imports, vars (#141)
* Internal registry for disambiguated imports, vars - Move functionality in the moq package partially into internal/{registry,template}. - Leverage registry to assign unique package and variable/method parameter names. Use import aliases if present in interface source package. BREAKING CHANGE: When the interface definition does not mention the parameter names, the field names in call info anonymous struct will be different. The new field names are generated using the type info (string -> s, int -> n, chan int -> intCh, []MyType -> myTypes, map[string]int -> stringToInt etc.). For example, for a string parameter previously if the field name was 'In1', the new field could be 'S' or 'S1' (depends on number of string method parameters). * Refactor golden file tests to be table-driven * Fix sync pkg alias handling for moq generation * Improve, add tests (increase coverage) * Use $.Foo in template, avoid declaring variables $ is set to the data argument passed to Execute, that is, to the starting value of dot. Variables were declared to be able to refer to the parent context. * Consistent template field formatting * Use tabs in generated Godoc comments' example code * Minor simplification * go generate * Fix conflict for generated param name of pointer type Excellent work by @sudo-suhas.
This commit is contained in:
parent
b052143b5a
commit
2ae606f132
155
internal/registry/method_scope.go
Normal file
155
internal/registry/method_scope.go
Normal file
@ -0,0 +1,155 @@
|
||||
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 {
|
||||
name := vr.Name()
|
||||
if name == "" || name == "_" {
|
||||
name = generateVarName(vr.Type())
|
||||
}
|
||||
|
||||
name += 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"
|
||||
}
|
||||
|
||||
if _, ok := m.searchVar(name); ok || m.conflicted[name] {
|
||||
return m.addDisambiguatedVar(vr, name)
|
||||
}
|
||||
|
||||
return m.addVar(vr, name)
|
||||
}
|
||||
|
||||
func (m *MethodScope) addDisambiguatedVar(vr *types.Var, suggested string) *Var {
|
||||
n := 1
|
||||
for {
|
||||
// Keep incrementing the suffix until we find a name which is unused.
|
||||
if _, ok := m.searchVar(suggested + strconv.Itoa(n)); !ok {
|
||||
break
|
||||
}
|
||||
n++
|
||||
}
|
||||
|
||||
name := suggested + strconv.Itoa(n)
|
||||
if n == 1 {
|
||||
conflict, _ := m.searchVar(suggested)
|
||||
conflict.Name += "1"
|
||||
name = suggested + "2"
|
||||
m.conflicted[suggested] = true
|
||||
}
|
||||
|
||||
return m.addVar(vr, name)
|
||||
}
|
||||
|
||||
func (m *MethodScope) addVar(vr *types.Var, name string) *Var {
|
||||
imports := make(map[string]*Package)
|
||||
m.populateImports(vr.Type(), imports)
|
||||
|
||||
v := Var{
|
||||
vr: vr,
|
||||
imports: imports,
|
||||
moqPkgPath: m.moqPkgPath,
|
||||
Name: name,
|
||||
}
|
||||
m.vars = append(m.vars, &v)
|
||||
m.resolveImportVarConflicts(&v)
|
||||
return &v
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m MethodScope) resolveImportVarConflicts(v *Var) {
|
||||
// Ensure that the newly added var does not conflict with a package import
|
||||
// which was added earlier.
|
||||
if _, ok := m.registry.searchImport(v.Name); ok {
|
||||
v.Name += "MoqParam"
|
||||
}
|
||||
// Ensure that all the newly added imports do not conflict with any of the
|
||||
// existing vars.
|
||||
for _, imprt := range v.imports {
|
||||
if v, ok := m.searchVar(imprt.Qualifier()); ok {
|
||||
v.Name += "MoqParam"
|
||||
}
|
||||
}
|
||||
}
|
93
internal/registry/package.go
Normal file
93
internal/registry/package.go
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
internal/registry/registry.go
Normal file
190
internal/registry/registry.go
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 != "." {
|
||||
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)
|
||||
}
|
123
internal/registry/var.go
Normal file
123
internal/registry/var.go
Normal file
@ -0,0 +1,123 @@
|
||||
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()
|
||||
}
|
||||
|
||||
// generateVarName 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 generateVarName(t types.Type) string {
|
||||
nestedType := func(t types.Type) string {
|
||||
if t, ok := t.(*types.Basic); ok {
|
||||
return deCapitalise(t.String())
|
||||
}
|
||||
return generateVarName(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 generateVarName(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
internal/template/template.go
Normal file
190
internal/template/template.go
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
internal/template/template_data.go
Normal file
125
internal/template/template_data.go
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()
|
||||
}
|
55
internal/template/template_test.go
Normal file
55
internal/template/template_test.go
Normal file
@ -0,0 +1,55 @@
|
||||
package template
|
||||
|
||||
import (
|
||||
"go/types"
|
||||
"testing"
|
||||
|
||||
"github.com/matryer/moq/internal/registry"
|
||||
)
|
||||
|
||||
func TestTemplateFuncs(t *testing.T) {
|
||||
t.Run("Exported", func(t *testing.T) {
|
||||
f := templateFuncs["Exported"].(func(string) string)
|
||||
if f("") != "" {
|
||||
t.Errorf("Exported(...) want: ``; got: `%s`", f(""))
|
||||
}
|
||||
if f("var") != "Var" {
|
||||
t.Errorf("Exported(...) want: `Var`; got: `%s`", f("var"))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ImportStatement", func(t *testing.T) {
|
||||
f := templateFuncs["ImportStatement"].(func(*registry.Package) string)
|
||||
pkg := registry.NewPackage(types.NewPackage("xyz", "xyz"))
|
||||
if f(pkg) != `"xyz"` {
|
||||
t.Errorf("ImportStatement(...): want: `\"xyz\"`; got: `%s`", f(pkg))
|
||||
}
|
||||
|
||||
pkg.Alias = "x"
|
||||
if f(pkg) != `x "xyz"` {
|
||||
t.Errorf("ImportStatement(...): want: `x \"xyz\"`; got: `%s`", f(pkg))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("SyncPkgQualifier", func(t *testing.T) {
|
||||
f := templateFuncs["SyncPkgQualifier"].(func([]*registry.Package) string)
|
||||
if f(nil) != "sync" {
|
||||
t.Errorf("SyncPkgQualifier(...): want: `sync`; got: `%s`", f(nil))
|
||||
}
|
||||
imports := []*registry.Package{
|
||||
registry.NewPackage(types.NewPackage("sync", "sync")),
|
||||
registry.NewPackage(types.NewPackage("github.com/some/module", "module")),
|
||||
}
|
||||
if f(imports) != "sync" {
|
||||
t.Errorf("SyncPkgQualifier(...): want: `sync`; got: `%s`", f(imports))
|
||||
}
|
||||
|
||||
syncPkg := registry.NewPackage(types.NewPackage("sync", "sync"))
|
||||
syncPkg.Alias = "stdsync"
|
||||
otherSyncPkg := registry.NewPackage(types.NewPackage("github.com/someother/sync", "sync"))
|
||||
imports = []*registry.Package{otherSyncPkg, syncPkg}
|
||||
if f(imports) != "stdsync" {
|
||||
t.Errorf("SyncPkgQualifier(...): want: `stdsync`; got: `%s`", f(imports))
|
||||
}
|
||||
})
|
||||
}
|
@ -29,5 +29,3 @@ func gofmt(src []byte) ([]byte, error) {
|
||||
|
||||
return formatted, nil
|
||||
}
|
||||
|
||||
func noopFmt(src []byte) ([]byte, error) { return src, nil }
|
||||
|
@ -1,44 +0,0 @@
|
||||
package moq
|
||||
|
||||
// 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",
|
||||
}
|
380
pkg/moq/moq.go
380
pkg/moq/moq.go
@ -3,31 +3,20 @@ package moq
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"go/types"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"golang.org/x/tools/go/packages"
|
||||
"github.com/matryer/moq/internal/registry"
|
||||
"github.com/matryer/moq/internal/template"
|
||||
)
|
||||
|
||||
// Mocker can generate mock structs.
|
||||
type Mocker struct {
|
||||
srcPkg *packages.Package
|
||||
tmpl *template.Template
|
||||
pkgName string
|
||||
pkgPath string
|
||||
fmter func(src []byte) ([]byte, error)
|
||||
stubImpl bool
|
||||
skipEnsure bool
|
||||
cfg Config
|
||||
|
||||
imports map[string]bool
|
||||
registry *registry.Registry
|
||||
tmpl template.Template
|
||||
}
|
||||
|
||||
// Config specifies details about how interfaces should be mocked.
|
||||
@ -41,331 +30,142 @@ type Config struct {
|
||||
}
|
||||
|
||||
// New makes a new Mocker for the specified package directory.
|
||||
func New(conf Config) (*Mocker, error) {
|
||||
srcPkg, err := pkgInfoFromPath(conf.SrcDir, packages.NeedName|packages.NeedTypes|packages.NeedTypesInfo)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't load source package: %s", err)
|
||||
}
|
||||
|
||||
pkgName := conf.PkgName
|
||||
if pkgName == "" {
|
||||
pkgName = srcPkg.Name
|
||||
}
|
||||
|
||||
pkgPath, err := findPkgPath(conf.PkgName, srcPkg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't load mock package: %s", err)
|
||||
}
|
||||
|
||||
tmpl, err := template.New("moq").Funcs(templateFuncs).Parse(moqTemplate)
|
||||
func New(cfg Config) (*Mocker, error) {
|
||||
reg, err := registry.New(cfg.SrcDir, cfg.PkgName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmter := gofmt
|
||||
switch conf.Formatter {
|
||||
case "goimports":
|
||||
fmter = goimports
|
||||
case "noop":
|
||||
fmter = noopFmt
|
||||
tmpl, err := template.New()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Mocker{
|
||||
cfg: cfg,
|
||||
registry: reg,
|
||||
tmpl: tmpl,
|
||||
srcPkg: srcPkg,
|
||||
pkgName: pkgName,
|
||||
pkgPath: pkgPath,
|
||||
fmter: fmter,
|
||||
stubImpl: conf.StubImpl,
|
||||
skipEnsure: conf.SkipEnsure,
|
||||
imports: make(map[string]bool),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func findPkgPath(pkgInputVal string, srcPkg *packages.Package) (string, error) {
|
||||
if pkgInputVal == "" {
|
||||
return srcPkg.PkgPath, nil
|
||||
}
|
||||
if pkgInDir(".", pkgInputVal) {
|
||||
return ".", nil
|
||||
}
|
||||
if pkgInDir(srcPkg.PkgPath, pkgInputVal) {
|
||||
return srcPkg.PkgPath, nil
|
||||
}
|
||||
subdirectoryPath := filepath.Join(srcPkg.PkgPath, pkgInputVal)
|
||||
if pkgInDir(subdirectoryPath, pkgInputVal) {
|
||||
return subdirectoryPath, nil
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// Mock generates a mock for the specified interface name.
|
||||
func (m *Mocker) Mock(w io.Writer, names ...string) error {
|
||||
if len(names) == 0 {
|
||||
func (m *Mocker) Mock(w io.Writer, namePairs ...string) error {
|
||||
if len(namePairs) == 0 {
|
||||
return errors.New("must specify one interface")
|
||||
}
|
||||
|
||||
doc := doc{
|
||||
PackageName: m.pkgName,
|
||||
Imports: moqImports,
|
||||
StubImpl: m.stubImpl,
|
||||
SkipEnsure: m.skipEnsure,
|
||||
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
|
||||
}
|
||||
|
||||
mocksMethods := false
|
||||
methods := make([]template.MethodData, iface.NumMethods())
|
||||
for j := 0; j < iface.NumMethods(); j++ {
|
||||
methods[j] = m.methodData(iface.Method(j))
|
||||
}
|
||||
|
||||
tpkg := m.srcPkg.Types
|
||||
for _, name := range names {
|
||||
n, mockName := parseInterfaceName(name)
|
||||
iface := tpkg.Scope().Lookup(n)
|
||||
if iface == nil {
|
||||
return fmt.Errorf("cannot find interface %s", n)
|
||||
}
|
||||
if !types.IsInterface(iface.Type()) {
|
||||
return fmt.Errorf("%s (%s) not an interface", n, iface.Type().String())
|
||||
}
|
||||
iiface := iface.Type().Underlying().(*types.Interface).Complete()
|
||||
obj := obj{
|
||||
InterfaceName: n,
|
||||
mocks[i] = template.MockData{
|
||||
InterfaceName: name,
|
||||
MockName: mockName,
|
||||
Methods: methods,
|
||||
}
|
||||
for i := 0; i < iiface.NumMethods(); i++ {
|
||||
mocksMethods = true
|
||||
meth := iiface.Method(i)
|
||||
sig := meth.Type().(*types.Signature)
|
||||
method := &method{
|
||||
Name: meth.Name(),
|
||||
}
|
||||
obj.Methods = append(obj.Methods, method)
|
||||
method.Params, method.Returns = m.extractArgs(sig)
|
||||
}
|
||||
doc.Objects = append(doc.Objects, obj)
|
||||
}
|
||||
|
||||
if mocksMethods {
|
||||
doc.Imports = append(doc.Imports, "sync")
|
||||
data := template.Data{
|
||||
PkgName: m.mockPkgName(),
|
||||
Mocks: mocks,
|
||||
StubImpl: m.cfg.StubImpl,
|
||||
SkipEnsure: m.cfg.SkipEnsure,
|
||||
}
|
||||
|
||||
for pkgToImport := range m.imports {
|
||||
doc.Imports = append(doc.Imports, stripVendorPath(pkgToImport))
|
||||
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() + "."
|
||||
}
|
||||
}
|
||||
|
||||
if tpkg.Name() != m.pkgName {
|
||||
doc.SourcePackagePrefix = tpkg.Name() + "."
|
||||
doc.Imports = append(doc.Imports, stripVendorPath(tpkg.Path()))
|
||||
}
|
||||
data.Imports = m.registry.Imports()
|
||||
|
||||
var buf bytes.Buffer
|
||||
err := m.tmpl.Execute(&buf, doc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
formatted, err := m.fmter(buf.Bytes())
|
||||
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) packageQualifier(pkg *types.Package) string {
|
||||
if m.pkgPath != "" && m.pkgPath == pkg.Path() {
|
||||
return ""
|
||||
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), ""),
|
||||
}
|
||||
path := pkg.Path()
|
||||
if pkg.Path() == "." {
|
||||
wd, err := os.Getwd()
|
||||
if err == nil {
|
||||
path = stripGopath(wd)
|
||||
}
|
||||
}
|
||||
m.imports[path] = true
|
||||
return pkg.Name()
|
||||
p.Variadic = sig.Variadic() && i == n-1 && p.Var.IsSlice() // check for final variadic argument
|
||||
|
||||
params[i] = p
|
||||
}
|
||||
|
||||
func (m *Mocker) extractArgs(sig *types.Signature) (params, results []*param) {
|
||||
pp := sig.Params()
|
||||
for i := 0; i < pp.Len(); i++ {
|
||||
p := m.buildParam(pp.At(i), "in"+strconv.Itoa(i+1))
|
||||
// check for final variadic argument
|
||||
p.Variadic = sig.Variadic() && i == pp.Len()-1 && p.Type[0:2] == "[]"
|
||||
params = append(params, 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"),
|
||||
}
|
||||
}
|
||||
|
||||
rr := sig.Results()
|
||||
for i := 0; i < rr.Len(); i++ {
|
||||
results = append(results, m.buildParam(rr.At(i), "out"+strconv.Itoa(i+1)))
|
||||
return template.MethodData{
|
||||
Name: f.Name(),
|
||||
Params: params,
|
||||
Returns: results,
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
func (m *Mocker) mockPkgName() string {
|
||||
if m.cfg.PkgName != "" {
|
||||
return m.cfg.PkgName
|
||||
}
|
||||
|
||||
func (m *Mocker) buildParam(v *types.Var, fallbackName string) *param {
|
||||
name := v.Name()
|
||||
if name == "" || name == "_" {
|
||||
name = fallbackName
|
||||
}
|
||||
typ := types.TypeString(v.Type(), m.packageQualifier)
|
||||
return ¶m{Name: name, Type: typ}
|
||||
return m.registry.SrcPkgName()
|
||||
}
|
||||
|
||||
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("No packages found")
|
||||
}
|
||||
if len(pkgs) > 1 {
|
||||
return nil, errors.New("More than one package was found")
|
||||
}
|
||||
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 (m *Mocker) format(src []byte) ([]byte, error) {
|
||||
switch m.cfg.Formatter {
|
||||
case "goimports":
|
||||
return goimports(src)
|
||||
|
||||
case "noop":
|
||||
return src, nil
|
||||
}
|
||||
|
||||
func parseInterfaceName(name string) (ifaceName, mockName string) {
|
||||
parts := strings.SplitN(name, ":", 2)
|
||||
ifaceName = parts[0]
|
||||
mockName = ifaceName + "Mock"
|
||||
return gofmt(src)
|
||||
}
|
||||
|
||||
func parseInterfaceName(namePair string) (ifaceName, mockName string) {
|
||||
parts := strings.SplitN(namePair, ":", 2)
|
||||
if len(parts) == 2 {
|
||||
mockName = parts[1]
|
||||
}
|
||||
return
|
||||
return parts[0], parts[1]
|
||||
}
|
||||
|
||||
type doc struct {
|
||||
PackageName string
|
||||
SourcePackagePrefix string
|
||||
Objects []obj
|
||||
Imports []string
|
||||
StubImpl bool
|
||||
SkipEnsure bool
|
||||
}
|
||||
|
||||
type obj struct {
|
||||
InterfaceName string
|
||||
MockName string
|
||||
Methods []*method
|
||||
}
|
||||
type method struct {
|
||||
Name string
|
||||
Params []*param
|
||||
Returns []*param
|
||||
}
|
||||
|
||||
func (m *method) Arglist() string {
|
||||
params := make([]string, len(m.Params))
|
||||
for i, p := range m.Params {
|
||||
params[i] = p.String()
|
||||
}
|
||||
return strings.Join(params, ", ")
|
||||
}
|
||||
|
||||
func (m *method) ArgCallList() string {
|
||||
params := make([]string, len(m.Params))
|
||||
for i, p := range m.Params {
|
||||
params[i] = p.CallName()
|
||||
}
|
||||
return strings.Join(params, ", ")
|
||||
}
|
||||
|
||||
func (m *method) 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, ", ")
|
||||
}
|
||||
|
||||
func (m *method) ReturnArgNameList() string {
|
||||
params := make([]string, len(m.Returns))
|
||||
for i, p := range m.Returns {
|
||||
params[i] = p.Name
|
||||
}
|
||||
return strings.Join(params, ", ")
|
||||
}
|
||||
|
||||
type param struct {
|
||||
Name string
|
||||
Type string
|
||||
Variadic bool
|
||||
}
|
||||
|
||||
func (p param) String() string {
|
||||
return fmt.Sprintf("%s %s", p.Name, p.TypeString())
|
||||
}
|
||||
|
||||
func (p param) CallName() string {
|
||||
if p.Variadic {
|
||||
return p.Name + "..."
|
||||
}
|
||||
return p.Name
|
||||
}
|
||||
|
||||
func (p param) TypeString() string {
|
||||
if p.Variadic {
|
||||
return "..." + p.Type[2:]
|
||||
}
|
||||
return p.Type
|
||||
}
|
||||
|
||||
var templateFuncs = template.FuncMap{
|
||||
"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:]
|
||||
},
|
||||
}
|
||||
|
||||
// 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:]...), "/")
|
||||
}
|
||||
|
||||
// stripGopath takes the directory to a package and removes the
|
||||
// $GOPATH/src path to get the canonical package name.
|
||||
func stripGopath(p string) string {
|
||||
for _, srcDir := range build.Default.SrcDirs() {
|
||||
rel, err := filepath.Rel(srcDir, p)
|
||||
if err != nil || strings.HasPrefix(rel, "..") {
|
||||
continue
|
||||
}
|
||||
return filepath.ToSlash(rel)
|
||||
}
|
||||
return p
|
||||
ifaceName = parts[0]
|
||||
return ifaceName, ifaceName + "Mock"
|
||||
}
|
||||
|
@ -246,45 +246,6 @@ func TestVariadicArguments(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestSliceResult tests to ensure slice return data type works as
|
||||
// expected.
|
||||
// see https://github.com/matryer/moq/issues/124
|
||||
func TestSliceResult(t *testing.T) {
|
||||
m, err := New(Config{SrcDir: "testpackages/variadic"})
|
||||
if err != nil {
|
||||
t.Fatalf("moq.New: %s", err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err = m.Mock(&buf, "Echoer"); err != nil {
|
||||
t.Errorf("m.Mock: %s", err)
|
||||
}
|
||||
|
||||
golden := filepath.Join("testpackages/variadic", "echoer.golden.go")
|
||||
if err := matchGoldenFile(golden, buf.Bytes()); err != nil {
|
||||
t.Errorf("check golden file: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestBlankID tests generation of mock where a method on the interface
|
||||
// uses a blank identifier.
|
||||
// See https://github.com/matryer/moq/issues/70
|
||||
func TestBlankID(t *testing.T) {
|
||||
m, err := New(Config{SrcDir: "testpackages/blankid"})
|
||||
if err != nil {
|
||||
t.Fatalf("moq.New: %s", err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err = m.Mock(&buf, "Swallower"); err != nil {
|
||||
t.Errorf("m.Mock: %s", err)
|
||||
}
|
||||
golden := filepath.Join("testpackages/blankid", "swallower.golden.go")
|
||||
if err := matchGoldenFile(golden, buf.Bytes()); err != nil {
|
||||
t.Errorf("check golden file: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNothingToReturn(t *testing.T) {
|
||||
m, err := New(Config{SrcDir: "testpackages/example"})
|
||||
if err != nil {
|
||||
@ -310,23 +271,6 @@ func TestNothingToReturn(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestChannelNames(t *testing.T) {
|
||||
m, err := New(Config{SrcDir: "testpackages/channels", StubImpl: true})
|
||||
if err != nil {
|
||||
t.Fatalf("moq.New: %s", err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err = m.Mock(&buf, "Queuer"); err != nil {
|
||||
t.Errorf("m.Mock: %s", err)
|
||||
}
|
||||
|
||||
golden := filepath.Join("testpackages/channels", "queuer_moq.golden.go")
|
||||
if err := matchGoldenFile(golden, buf.Bytes()); err != nil {
|
||||
t.Errorf("check golden file: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestImports(t *testing.T) {
|
||||
m, err := New(Config{SrcDir: "testpackages/imports/two"})
|
||||
if err != nil {
|
||||
@ -352,6 +296,101 @@ func TestImports(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMockGolden(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
cfg Config
|
||||
interfaces []string
|
||||
goldenFile string
|
||||
}{
|
||||
{
|
||||
// Tests to ensure slice return data type works as expected.
|
||||
// See https://github.com/matryer/moq/issues/124
|
||||
name: "SliceResult",
|
||||
cfg: Config{SrcDir: "testpackages/variadic"},
|
||||
interfaces: []string{"Echoer"},
|
||||
goldenFile: filepath.Join("testpackages/variadic", "echoer.golden.go"),
|
||||
},
|
||||
{
|
||||
// Tests generation of mock where a method on the interface uses a
|
||||
// blank identifier.
|
||||
// See https://github.com/matryer/moq/issues/70
|
||||
name: "BlankID",
|
||||
cfg: Config{SrcDir: "testpackages/blankid"},
|
||||
interfaces: []string{"Swallower"},
|
||||
goldenFile: filepath.Join("testpackages/blankid", "swallower.golden.go"),
|
||||
},
|
||||
{
|
||||
name: "ChannelNames",
|
||||
cfg: Config{SrcDir: "testpackages/channels", StubImpl: true},
|
||||
interfaces: []string{"Queuer"},
|
||||
goldenFile: filepath.Join("testpackages/channels", "queuer_moq.golden.go"),
|
||||
},
|
||||
{
|
||||
// Tests generation of mock when the interface imports a different
|
||||
// package by the same name as it's own.
|
||||
// See https://github.com/matryer/moq/issues/94
|
||||
name: "PkgShadow",
|
||||
cfg: Config{SrcDir: "testpackages/shadow/http", PkgName: "mock"},
|
||||
interfaces: []string{"Thing"},
|
||||
goldenFile: filepath.Join("testpackages/shadow/mock", "thing_moq.golden.go"),
|
||||
},
|
||||
{
|
||||
// Tests generation of mock when a method parameter shadows an
|
||||
// imported package name.
|
||||
name: "ParamShadow",
|
||||
cfg: Config{SrcDir: "testpackages/shadow"},
|
||||
interfaces: []string{"Shadower"},
|
||||
goldenFile: filepath.Join("testpackages/shadow", "shadower_moq.golden.go"),
|
||||
},
|
||||
{
|
||||
name: "ImportAlias",
|
||||
cfg: Config{SrcDir: "testpackages/importalias"},
|
||||
interfaces: []string{"MiddleMan"},
|
||||
goldenFile: filepath.Join("testpackages/importalias", "middleman_moq.golden.go"),
|
||||
},
|
||||
{
|
||||
// Tests conflict resolution for generated names of method
|
||||
// parameters.
|
||||
name: "ParamNameConflict",
|
||||
cfg: Config{SrcDir: "testpackages/paramconflict"},
|
||||
interfaces: []string{"Interface"},
|
||||
goldenFile: filepath.Join("testpackages/paramconflict", "iface_moq.golden.go"),
|
||||
},
|
||||
{
|
||||
// Tests generation of names for unnamed method parameters.
|
||||
name: "GenerateParamNames",
|
||||
cfg: Config{SrcDir: "testpackages/genparamname"},
|
||||
interfaces: []string{"Interface"},
|
||||
goldenFile: filepath.Join("testpackages/genparamname", "iface_moq.golden.go"),
|
||||
},
|
||||
{
|
||||
name: "SyncImport",
|
||||
cfg: Config{SrcDir: "testpackages/syncimport"},
|
||||
interfaces: []string{"Syncer"},
|
||||
goldenFile: filepath.Join("testpackages/syncimport", "syncer_moq.golden.go"),
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
m, err := New(tc.cfg)
|
||||
if err != nil {
|
||||
t.Fatalf("moq.New: %s", err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err = m.Mock(&buf, tc.interfaces...); err != nil {
|
||||
t.Errorf("m.Mock: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := matchGoldenFile(tc.goldenFile, buf.Bytes()); err != nil {
|
||||
t.Errorf("check golden file: %s", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatter(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
@ -419,13 +458,6 @@ func matchGoldenFile(goldenFile string, actual []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestTemplateFuncs(t *testing.T) {
|
||||
fn := templateFuncs["Exported"].(func(string) string)
|
||||
if fn("var") != "Var" {
|
||||
t.Errorf("exported didn't work: %s", fn("var"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestVendoredPackages(t *testing.T) {
|
||||
m, err := New(Config{SrcDir: "testpackages/vendoring/user"})
|
||||
if err != nil {
|
||||
@ -601,6 +633,41 @@ func TestParseError(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMockError(t *testing.T) {
|
||||
m, err := New(Config{SrcDir: "testpackages/example"})
|
||||
if err != nil {
|
||||
t.Fatalf("moq.New: %s", err)
|
||||
}
|
||||
cases := []struct {
|
||||
name string
|
||||
namePair string
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "TypeNotFound",
|
||||
namePair: "DoesNotExist",
|
||||
wantErr: "interface not found: DoesNotExist",
|
||||
},
|
||||
{
|
||||
name: "UnexpectedType",
|
||||
namePair: "Person",
|
||||
wantErr: "Person (github.com/matryer/moq/pkg/moq/testpackages/example.Person) is not an interface",
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := m.Mock(ioutil.Discard, tc.namePair)
|
||||
if err == nil {
|
||||
t.Errorf("expected error but got nil")
|
||||
return
|
||||
}
|
||||
if !strings.Contains(err.Error(), tc.wantErr) {
|
||||
t.Errorf("unexpected error: %s", err.Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// normalize normalizes \r\n (windows) and \r (mac)
|
||||
// into \n (unix)
|
||||
func normalize(d []byte) []byte {
|
||||
|
@ -1,127 +0,0 @@
|
||||
package moq
|
||||
|
||||
// moqImports are the imports all moq files get.
|
||||
var moqImports = []string{}
|
||||
|
||||
// moqTemplate is the template for mocked code.
|
||||
// language=GoTemplate
|
||||
var moqTemplate = `// Code generated by moq; DO NOT EDIT.
|
||||
// github.com/matryer/moq
|
||||
|
||||
package {{.PackageName}}
|
||||
{{- $sourcePackagePrefix := .SourcePackagePrefix}}
|
||||
{{- $stubImpl := .StubImpl}}
|
||||
{{- $skipEnsure := .SkipEnsure}}
|
||||
|
||||
import (
|
||||
{{- range .Imports }}
|
||||
"{{.}}"
|
||||
{{- end }}
|
||||
)
|
||||
|
||||
{{ range $i, $obj := .Objects -}}
|
||||
|
||||
{{- if not $skipEnsure -}}
|
||||
// Ensure, that {{.MockName}} does implement {{$sourcePackagePrefix}}{{.InterfaceName}}.
|
||||
// If this is not the case, regenerate this file with moq.
|
||||
var _ {{$sourcePackagePrefix}}{{.InterfaceName}} = &{{.MockName}}{}
|
||||
{{- end }}
|
||||
|
||||
// {{.MockName}} is a mock implementation of {{$sourcePackagePrefix}}{{.InterfaceName}}.
|
||||
//
|
||||
// func TestSomethingThatUses{{.InterfaceName}}(t *testing.T) {
|
||||
//
|
||||
// // make and configure a mocked {{$sourcePackagePrefix}}{{.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 {{$sourcePackagePrefix}}{{.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 }} {{ .Type }}
|
||||
{{- end }}
|
||||
}
|
||||
{{- end }}
|
||||
}
|
||||
{{- range .Methods }}
|
||||
lock{{.Name}} sync.RWMutex
|
||||
{{- end }}
|
||||
}
|
||||
{{ range .Methods }}
|
||||
// {{.Name}} calls {{.Name}}Func.
|
||||
func (mock *{{$obj.MockName}}) {{.Name}}({{.Arglist}}) {{.ReturnArgTypeList}} {
|
||||
{{- if not $stubImpl }}
|
||||
if mock.{{.Name}}Func == nil {
|
||||
panic("{{$obj.MockName}}.{{.Name}}Func: method is nil but {{$obj.InterfaceName}}.{{.Name}} was just called")
|
||||
}
|
||||
{{- end }}
|
||||
callInfo := struct {
|
||||
{{- range .Params }}
|
||||
{{ .Name | Exported }} {{ .Type }}
|
||||
{{- 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}} {{.Type}}
|
||||
{{- 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{{$obj.InterfaceName}}.{{.Name}}Calls())
|
||||
func (mock *{{$obj.MockName}}) {{.Name}}Calls() []struct {
|
||||
{{- range .Params }}
|
||||
{{ .Name | Exported }} {{ .Type }}
|
||||
{{- end }}
|
||||
} {
|
||||
var calls []struct {
|
||||
{{- range .Params }}
|
||||
{{ .Name | Exported }} {{ .Type }}
|
||||
{{- end }}
|
||||
}
|
||||
mock.lock{{.Name}}.RLock()
|
||||
calls = mock.calls.{{.Name}}
|
||||
mock.lock{{.Name}}.RUnlock()
|
||||
return calls
|
||||
}
|
||||
{{ end -}}
|
||||
{{ end -}}`
|
@ -17,7 +17,7 @@ var _ Swallower = &SwallowerMock{}
|
||||
//
|
||||
// // make and configure a mocked Swallower
|
||||
// mockedSwallower := &SwallowerMock{
|
||||
// SwallowFunc: func(in1 string) {
|
||||
// SwallowFunc: func(s string) {
|
||||
// panic("mock out the Swallow method")
|
||||
// },
|
||||
// }
|
||||
@ -28,43 +28,43 @@ var _ Swallower = &SwallowerMock{}
|
||||
// }
|
||||
type SwallowerMock struct {
|
||||
// SwallowFunc mocks the Swallow method.
|
||||
SwallowFunc func(in1 string)
|
||||
SwallowFunc func(s string)
|
||||
|
||||
// calls tracks calls to the methods.
|
||||
calls struct {
|
||||
// Swallow holds details about calls to the Swallow method.
|
||||
Swallow []struct {
|
||||
// In1 is the in1 argument value.
|
||||
In1 string
|
||||
// S is the s argument value.
|
||||
S string
|
||||
}
|
||||
}
|
||||
lockSwallow sync.RWMutex
|
||||
}
|
||||
|
||||
// Swallow calls SwallowFunc.
|
||||
func (mock *SwallowerMock) Swallow(in1 string) {
|
||||
func (mock *SwallowerMock) Swallow(s string) {
|
||||
if mock.SwallowFunc == nil {
|
||||
panic("SwallowerMock.SwallowFunc: method is nil but Swallower.Swallow was just called")
|
||||
}
|
||||
callInfo := struct {
|
||||
In1 string
|
||||
S string
|
||||
}{
|
||||
In1: in1,
|
||||
S: s,
|
||||
}
|
||||
mock.lockSwallow.Lock()
|
||||
mock.calls.Swallow = append(mock.calls.Swallow, callInfo)
|
||||
mock.lockSwallow.Unlock()
|
||||
mock.SwallowFunc(in1)
|
||||
mock.SwallowFunc(s)
|
||||
}
|
||||
|
||||
// SwallowCalls gets all the calls that were made to Swallow.
|
||||
// Check the length with:
|
||||
// len(mockedSwallower.SwallowCalls())
|
||||
func (mock *SwallowerMock) SwallowCalls() []struct {
|
||||
In1 string
|
||||
S string
|
||||
} {
|
||||
var calls []struct {
|
||||
In1 string
|
||||
S string
|
||||
}
|
||||
mock.lockSwallow.RLock()
|
||||
calls = mock.calls.Swallow
|
||||
|
@ -65,10 +65,10 @@ func (mock *QueuerMock) Sub(topic string) (<-chan Queue, error) {
|
||||
mock.lockSub.Unlock()
|
||||
if mock.SubFunc == nil {
|
||||
var (
|
||||
out1 <-chan Queue
|
||||
out2 error
|
||||
queueChOut <-chan Queue
|
||||
errOut error
|
||||
)
|
||||
return out1, out2
|
||||
return queueChOut, errOut
|
||||
}
|
||||
return mock.SubFunc(topic)
|
||||
}
|
||||
|
@ -8,10 +8,6 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
lockServiceMockUser sync.RWMutex
|
||||
)
|
||||
|
||||
// Ensure, that ServiceMock does implement dotimport.Service.
|
||||
// If this is not the case, regenerate this file with moq.
|
||||
var _ dotimport.Service = &ServiceMock{}
|
||||
@ -43,6 +39,7 @@ type ServiceMock struct {
|
||||
ID string
|
||||
}
|
||||
}
|
||||
lockUser sync.RWMutex
|
||||
}
|
||||
|
||||
// User calls UserFunc.
|
||||
@ -55,9 +52,9 @@ func (mock *ServiceMock) User(ID string) (dotimport.User, error) {
|
||||
}{
|
||||
ID: ID,
|
||||
}
|
||||
lockServiceMockUser.Lock()
|
||||
mock.lockUser.Lock()
|
||||
mock.calls.User = append(mock.calls.User, callInfo)
|
||||
lockServiceMockUser.Unlock()
|
||||
mock.lockUser.Unlock()
|
||||
return mock.UserFunc(ID)
|
||||
}
|
||||
|
||||
@ -70,8 +67,8 @@ func (mock *ServiceMock) UserCalls() []struct {
|
||||
var calls []struct {
|
||||
ID string
|
||||
}
|
||||
lockServiceMockUser.RLock()
|
||||
mock.lockUser.RLock()
|
||||
calls = mock.calls.User
|
||||
lockServiceMockUser.RUnlock()
|
||||
mock.lockUser.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
34
pkg/moq/testpackages/genparamname/iface.go
Normal file
34
pkg/moq/testpackages/genparamname/iface.go
Normal file
@ -0,0 +1,34 @@
|
||||
package genparamname
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type (
|
||||
Go func()
|
||||
myType struct{}
|
||||
)
|
||||
|
||||
type Interface interface {
|
||||
Method(
|
||||
*myType,
|
||||
[3]json.Number,
|
||||
[]byte,
|
||||
map[sql.NullString]io.Reader,
|
||||
func(conn net.Conn),
|
||||
Go,
|
||||
chan *httputil.BufferPool,
|
||||
struct{ URL *url.URL },
|
||||
interface {
|
||||
fmt.Stringer
|
||||
CookieJar() http.CookieJar
|
||||
},
|
||||
)
|
||||
}
|
147
pkg/moq/testpackages/genparamname/iface_moq.golden.go
Normal file
147
pkg/moq/testpackages/genparamname/iface_moq.golden.go
Normal file
@ -0,0 +1,147 @@
|
||||
// Code generated by moq; DO NOT EDIT.
|
||||
// github.com/matryer/moq
|
||||
|
||||
package genparamname
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Ensure, that InterfaceMock does implement Interface.
|
||||
// If this is not the case, regenerate this file with moq.
|
||||
var _ Interface = &InterfaceMock{}
|
||||
|
||||
// InterfaceMock is a mock implementation of Interface.
|
||||
//
|
||||
// func TestSomethingThatUsesInterface(t *testing.T) {
|
||||
//
|
||||
// // make and configure a mocked Interface
|
||||
// mockedInterface := &InterfaceMock{
|
||||
// MethodFunc: func(myTypeMoqParam *myType, numbers [3]json.Number, bytes []byte, nullStringToReader map[sql.NullString]io.Reader, fn func(conn net.Conn), goMoqParam Go, bufferPoolCh chan *httputil.BufferPool, val struct{URL *url.URL}, ifaceVal interface{CookieJar() http.CookieJar; fmt.Stringer}) {
|
||||
// panic("mock out the Method method")
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// // use mockedInterface in code that requires Interface
|
||||
// // and then make assertions.
|
||||
//
|
||||
// }
|
||||
type InterfaceMock struct {
|
||||
// MethodFunc mocks the Method method.
|
||||
MethodFunc func(myTypeMoqParam *myType, numbers [3]json.Number, bytes []byte, nullStringToReader map[sql.NullString]io.Reader, fn func(conn net.Conn), goMoqParam Go, bufferPoolCh chan *httputil.BufferPool, val struct{ URL *url.URL }, ifaceVal interface {
|
||||
CookieJar() http.CookieJar
|
||||
fmt.Stringer
|
||||
})
|
||||
|
||||
// calls tracks calls to the methods.
|
||||
calls struct {
|
||||
// Method holds details about calls to the Method method.
|
||||
Method []struct {
|
||||
// MyTypeMoqParam is the myTypeMoqParam argument value.
|
||||
MyTypeMoqParam *myType
|
||||
// Numbers is the numbers argument value.
|
||||
Numbers [3]json.Number
|
||||
// Bytes is the bytes argument value.
|
||||
Bytes []byte
|
||||
// NullStringToReader is the nullStringToReader argument value.
|
||||
NullStringToReader map[sql.NullString]io.Reader
|
||||
// Fn is the fn argument value.
|
||||
Fn func(conn net.Conn)
|
||||
// GoMoqParam is the goMoqParam argument value.
|
||||
GoMoqParam Go
|
||||
// BufferPoolCh is the bufferPoolCh argument value.
|
||||
BufferPoolCh chan *httputil.BufferPool
|
||||
// Val is the val argument value.
|
||||
Val struct{ URL *url.URL }
|
||||
// IfaceVal is the ifaceVal argument value.
|
||||
IfaceVal interface {
|
||||
CookieJar() http.CookieJar
|
||||
fmt.Stringer
|
||||
}
|
||||
}
|
||||
}
|
||||
lockMethod sync.RWMutex
|
||||
}
|
||||
|
||||
// Method calls MethodFunc.
|
||||
func (mock *InterfaceMock) Method(myTypeMoqParam *myType, numbers [3]json.Number, bytes []byte, nullStringToReader map[sql.NullString]io.Reader, fn func(conn net.Conn), goMoqParam Go, bufferPoolCh chan *httputil.BufferPool, val struct{ URL *url.URL }, ifaceVal interface {
|
||||
CookieJar() http.CookieJar
|
||||
fmt.Stringer
|
||||
}) {
|
||||
if mock.MethodFunc == nil {
|
||||
panic("InterfaceMock.MethodFunc: method is nil but Interface.Method was just called")
|
||||
}
|
||||
callInfo := struct {
|
||||
MyTypeMoqParam *myType
|
||||
Numbers [3]json.Number
|
||||
Bytes []byte
|
||||
NullStringToReader map[sql.NullString]io.Reader
|
||||
Fn func(conn net.Conn)
|
||||
GoMoqParam Go
|
||||
BufferPoolCh chan *httputil.BufferPool
|
||||
Val struct{ URL *url.URL }
|
||||
IfaceVal interface {
|
||||
CookieJar() http.CookieJar
|
||||
fmt.Stringer
|
||||
}
|
||||
}{
|
||||
MyTypeMoqParam: myTypeMoqParam,
|
||||
Numbers: numbers,
|
||||
Bytes: bytes,
|
||||
NullStringToReader: nullStringToReader,
|
||||
Fn: fn,
|
||||
GoMoqParam: goMoqParam,
|
||||
BufferPoolCh: bufferPoolCh,
|
||||
Val: val,
|
||||
IfaceVal: ifaceVal,
|
||||
}
|
||||
mock.lockMethod.Lock()
|
||||
mock.calls.Method = append(mock.calls.Method, callInfo)
|
||||
mock.lockMethod.Unlock()
|
||||
mock.MethodFunc(myTypeMoqParam, numbers, bytes, nullStringToReader, fn, goMoqParam, bufferPoolCh, val, ifaceVal)
|
||||
}
|
||||
|
||||
// MethodCalls gets all the calls that were made to Method.
|
||||
// Check the length with:
|
||||
// len(mockedInterface.MethodCalls())
|
||||
func (mock *InterfaceMock) MethodCalls() []struct {
|
||||
MyTypeMoqParam *myType
|
||||
Numbers [3]json.Number
|
||||
Bytes []byte
|
||||
NullStringToReader map[sql.NullString]io.Reader
|
||||
Fn func(conn net.Conn)
|
||||
GoMoqParam Go
|
||||
BufferPoolCh chan *httputil.BufferPool
|
||||
Val struct{ URL *url.URL }
|
||||
IfaceVal interface {
|
||||
CookieJar() http.CookieJar
|
||||
fmt.Stringer
|
||||
}
|
||||
} {
|
||||
var calls []struct {
|
||||
MyTypeMoqParam *myType
|
||||
Numbers [3]json.Number
|
||||
Bytes []byte
|
||||
NullStringToReader map[sql.NullString]io.Reader
|
||||
Fn func(conn net.Conn)
|
||||
GoMoqParam Go
|
||||
BufferPoolCh chan *httputil.BufferPool
|
||||
Val struct{ URL *url.URL }
|
||||
IfaceVal interface {
|
||||
CookieJar() http.CookieJar
|
||||
fmt.Stringer
|
||||
}
|
||||
}
|
||||
mock.lockMethod.RLock()
|
||||
calls = mock.calls.Method
|
||||
mock.lockMethod.RUnlock()
|
||||
return calls
|
||||
}
|
@ -18,7 +18,7 @@ var _ Service = &ServiceMock{}
|
||||
//
|
||||
// // make and configure a mocked Service
|
||||
// mockedService := &ServiceMock{
|
||||
// DoSomethingFunc: func(in1 somerepo.SomeType) error {
|
||||
// DoSomethingFunc: func(someType somerepo.SomeType) error {
|
||||
// panic("mock out the DoSomething method")
|
||||
// },
|
||||
// }
|
||||
@ -29,43 +29,43 @@ var _ Service = &ServiceMock{}
|
||||
// }
|
||||
type ServiceMock struct {
|
||||
// DoSomethingFunc mocks the DoSomething method.
|
||||
DoSomethingFunc func(in1 somerepo.SomeType) error
|
||||
DoSomethingFunc func(someType somerepo.SomeType) error
|
||||
|
||||
// calls tracks calls to the methods.
|
||||
calls struct {
|
||||
// DoSomething holds details about calls to the DoSomething method.
|
||||
DoSomething []struct {
|
||||
// In1 is the in1 argument value.
|
||||
In1 somerepo.SomeType
|
||||
// SomeType is the someType argument value.
|
||||
SomeType somerepo.SomeType
|
||||
}
|
||||
}
|
||||
lockDoSomething sync.RWMutex
|
||||
}
|
||||
|
||||
// DoSomething calls DoSomethingFunc.
|
||||
func (mock *ServiceMock) DoSomething(in1 somerepo.SomeType) error {
|
||||
func (mock *ServiceMock) DoSomething(someType somerepo.SomeType) error {
|
||||
if mock.DoSomethingFunc == nil {
|
||||
panic("ServiceMock.DoSomethingFunc: method is nil but Service.DoSomething was just called")
|
||||
}
|
||||
callInfo := struct {
|
||||
In1 somerepo.SomeType
|
||||
SomeType somerepo.SomeType
|
||||
}{
|
||||
In1: in1,
|
||||
SomeType: someType,
|
||||
}
|
||||
mock.lockDoSomething.Lock()
|
||||
mock.calls.DoSomething = append(mock.calls.DoSomething, callInfo)
|
||||
mock.lockDoSomething.Unlock()
|
||||
return mock.DoSomethingFunc(in1)
|
||||
return mock.DoSomethingFunc(someType)
|
||||
}
|
||||
|
||||
// DoSomethingCalls gets all the calls that were made to DoSomething.
|
||||
// Check the length with:
|
||||
// len(mockedService.DoSomethingCalls())
|
||||
func (mock *ServiceMock) DoSomethingCalls() []struct {
|
||||
In1 somerepo.SomeType
|
||||
SomeType somerepo.SomeType
|
||||
} {
|
||||
var calls []struct {
|
||||
In1 somerepo.SomeType
|
||||
SomeType somerepo.SomeType
|
||||
}
|
||||
mock.lockDoSomething.RLock()
|
||||
calls = mock.calls.DoSomething
|
||||
|
10
pkg/moq/testpackages/importalias/middleman.go
Normal file
10
pkg/moq/testpackages/importalias/middleman.go
Normal file
@ -0,0 +1,10 @@
|
||||
package importalias
|
||||
|
||||
import (
|
||||
srcclient "github.com/matryer/moq/pkg/moq/testpackages/importalias/source/client"
|
||||
tgtclient "github.com/matryer/moq/pkg/moq/testpackages/importalias/target/client"
|
||||
)
|
||||
|
||||
type MiddleMan interface {
|
||||
Connect(src srcclient.Client, tgt tgtclient.Client)
|
||||
}
|
81
pkg/moq/testpackages/importalias/middleman_moq.golden.go
Normal file
81
pkg/moq/testpackages/importalias/middleman_moq.golden.go
Normal file
@ -0,0 +1,81 @@
|
||||
// Code generated by moq; DO NOT EDIT.
|
||||
// github.com/matryer/moq
|
||||
|
||||
package importalias
|
||||
|
||||
import (
|
||||
srcclient "github.com/matryer/moq/pkg/moq/testpackages/importalias/source/client"
|
||||
tgtclient "github.com/matryer/moq/pkg/moq/testpackages/importalias/target/client"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Ensure, that MiddleManMock does implement MiddleMan.
|
||||
// If this is not the case, regenerate this file with moq.
|
||||
var _ MiddleMan = &MiddleManMock{}
|
||||
|
||||
// MiddleManMock is a mock implementation of MiddleMan.
|
||||
//
|
||||
// func TestSomethingThatUsesMiddleMan(t *testing.T) {
|
||||
//
|
||||
// // make and configure a mocked MiddleMan
|
||||
// mockedMiddleMan := &MiddleManMock{
|
||||
// ConnectFunc: func(src srcclient.Client, tgt tgtclient.Client) {
|
||||
// panic("mock out the Connect method")
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// // use mockedMiddleMan in code that requires MiddleMan
|
||||
// // and then make assertions.
|
||||
//
|
||||
// }
|
||||
type MiddleManMock struct {
|
||||
// ConnectFunc mocks the Connect method.
|
||||
ConnectFunc func(src srcclient.Client, tgt tgtclient.Client)
|
||||
|
||||
// calls tracks calls to the methods.
|
||||
calls struct {
|
||||
// Connect holds details about calls to the Connect method.
|
||||
Connect []struct {
|
||||
// Src is the src argument value.
|
||||
Src srcclient.Client
|
||||
// Tgt is the tgt argument value.
|
||||
Tgt tgtclient.Client
|
||||
}
|
||||
}
|
||||
lockConnect sync.RWMutex
|
||||
}
|
||||
|
||||
// Connect calls ConnectFunc.
|
||||
func (mock *MiddleManMock) Connect(src srcclient.Client, tgt tgtclient.Client) {
|
||||
if mock.ConnectFunc == nil {
|
||||
panic("MiddleManMock.ConnectFunc: method is nil but MiddleMan.Connect was just called")
|
||||
}
|
||||
callInfo := struct {
|
||||
Src srcclient.Client
|
||||
Tgt tgtclient.Client
|
||||
}{
|
||||
Src: src,
|
||||
Tgt: tgt,
|
||||
}
|
||||
mock.lockConnect.Lock()
|
||||
mock.calls.Connect = append(mock.calls.Connect, callInfo)
|
||||
mock.lockConnect.Unlock()
|
||||
mock.ConnectFunc(src, tgt)
|
||||
}
|
||||
|
||||
// ConnectCalls gets all the calls that were made to Connect.
|
||||
// Check the length with:
|
||||
// len(mockedMiddleMan.ConnectCalls())
|
||||
func (mock *MiddleManMock) ConnectCalls() []struct {
|
||||
Src srcclient.Client
|
||||
Tgt tgtclient.Client
|
||||
} {
|
||||
var calls []struct {
|
||||
Src srcclient.Client
|
||||
Tgt tgtclient.Client
|
||||
}
|
||||
mock.lockConnect.RLock()
|
||||
calls = mock.calls.Connect
|
||||
mock.lockConnect.RUnlock()
|
||||
return calls
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
package client
|
||||
|
||||
type Client struct{}
|
@ -0,0 +1,3 @@
|
||||
package client
|
||||
|
||||
type Client struct{}
|
@ -4,8 +4,8 @@
|
||||
package two
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"github.com/matryer/moq/pkg/moq/testpackages/imports/one"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Ensure, that noopMock does implement DoSomething.
|
||||
|
5
pkg/moq/testpackages/paramconflict/iface.go
Normal file
5
pkg/moq/testpackages/paramconflict/iface.go
Normal file
@ -0,0 +1,5 @@
|
||||
package paramconflict
|
||||
|
||||
type Interface interface {
|
||||
Method(string, bool, string, bool, int, int32, int64, float32, float64)
|
||||
}
|
121
pkg/moq/testpackages/paramconflict/iface_moq.golden.go
Normal file
121
pkg/moq/testpackages/paramconflict/iface_moq.golden.go
Normal file
@ -0,0 +1,121 @@
|
||||
// Code generated by moq; DO NOT EDIT.
|
||||
// github.com/matryer/moq
|
||||
|
||||
package paramconflict
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Ensure, that InterfaceMock does implement Interface.
|
||||
// If this is not the case, regenerate this file with moq.
|
||||
var _ Interface = &InterfaceMock{}
|
||||
|
||||
// InterfaceMock is a mock implementation of Interface.
|
||||
//
|
||||
// func TestSomethingThatUsesInterface(t *testing.T) {
|
||||
//
|
||||
// // make and configure a mocked Interface
|
||||
// mockedInterface := &InterfaceMock{
|
||||
// MethodFunc: func(s1 string, b1 bool, s2 string, b2 bool, n1 int, n2 int32, n3 int64, f1 float32, f2 float64) {
|
||||
// panic("mock out the Method method")
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// // use mockedInterface in code that requires Interface
|
||||
// // and then make assertions.
|
||||
//
|
||||
// }
|
||||
type InterfaceMock struct {
|
||||
// MethodFunc mocks the Method method.
|
||||
MethodFunc func(s1 string, b1 bool, s2 string, b2 bool, n1 int, n2 int32, n3 int64, f1 float32, f2 float64)
|
||||
|
||||
// calls tracks calls to the methods.
|
||||
calls struct {
|
||||
// Method holds details about calls to the Method method.
|
||||
Method []struct {
|
||||
// S1 is the s1 argument value.
|
||||
S1 string
|
||||
// B1 is the b1 argument value.
|
||||
B1 bool
|
||||
// S2 is the s2 argument value.
|
||||
S2 string
|
||||
// B2 is the b2 argument value.
|
||||
B2 bool
|
||||
// N1 is the n1 argument value.
|
||||
N1 int
|
||||
// N2 is the n2 argument value.
|
||||
N2 int32
|
||||
// N3 is the n3 argument value.
|
||||
N3 int64
|
||||
// F1 is the f1 argument value.
|
||||
F1 float32
|
||||
// F2 is the f2 argument value.
|
||||
F2 float64
|
||||
}
|
||||
}
|
||||
lockMethod sync.RWMutex
|
||||
}
|
||||
|
||||
// Method calls MethodFunc.
|
||||
func (mock *InterfaceMock) Method(s1 string, b1 bool, s2 string, b2 bool, n1 int, n2 int32, n3 int64, f1 float32, f2 float64) {
|
||||
if mock.MethodFunc == nil {
|
||||
panic("InterfaceMock.MethodFunc: method is nil but Interface.Method was just called")
|
||||
}
|
||||
callInfo := struct {
|
||||
S1 string
|
||||
B1 bool
|
||||
S2 string
|
||||
B2 bool
|
||||
N1 int
|
||||
N2 int32
|
||||
N3 int64
|
||||
F1 float32
|
||||
F2 float64
|
||||
}{
|
||||
S1: s1,
|
||||
B1: b1,
|
||||
S2: s2,
|
||||
B2: b2,
|
||||
N1: n1,
|
||||
N2: n2,
|
||||
N3: n3,
|
||||
F1: f1,
|
||||
F2: f2,
|
||||
}
|
||||
mock.lockMethod.Lock()
|
||||
mock.calls.Method = append(mock.calls.Method, callInfo)
|
||||
mock.lockMethod.Unlock()
|
||||
mock.MethodFunc(s1, b1, s2, b2, n1, n2, n3, f1, f2)
|
||||
}
|
||||
|
||||
// MethodCalls gets all the calls that were made to Method.
|
||||
// Check the length with:
|
||||
// len(mockedInterface.MethodCalls())
|
||||
func (mock *InterfaceMock) MethodCalls() []struct {
|
||||
S1 string
|
||||
B1 bool
|
||||
S2 string
|
||||
B2 bool
|
||||
N1 int
|
||||
N2 int32
|
||||
N3 int64
|
||||
F1 float32
|
||||
F2 float64
|
||||
} {
|
||||
var calls []struct {
|
||||
S1 string
|
||||
B1 bool
|
||||
S2 string
|
||||
B2 bool
|
||||
N1 int
|
||||
N2 int32
|
||||
N3 int64
|
||||
F1 float32
|
||||
F2 float64
|
||||
}
|
||||
mock.lockMethod.RLock()
|
||||
calls = mock.calls.Method
|
||||
mock.lockMethod.RUnlock()
|
||||
return calls
|
||||
}
|
7
pkg/moq/testpackages/shadow/http/thing.go
Normal file
7
pkg/moq/testpackages/shadow/http/thing.go
Normal file
@ -0,0 +1,7 @@
|
||||
package http
|
||||
|
||||
import "net/http"
|
||||
|
||||
type Thing interface {
|
||||
Blah(w http.ResponseWriter, r *http.Request)
|
||||
}
|
81
pkg/moq/testpackages/shadow/mock/thing_moq.golden.go
Normal file
81
pkg/moq/testpackages/shadow/mock/thing_moq.golden.go
Normal file
@ -0,0 +1,81 @@
|
||||
// Code generated by moq; DO NOT EDIT.
|
||||
// github.com/matryer/moq
|
||||
|
||||
package mock
|
||||
|
||||
import (
|
||||
shadowhttp "github.com/matryer/moq/pkg/moq/testpackages/shadow/http"
|
||||
nethttp "net/http"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Ensure, that ThingMock does implement shadowhttp.Thing.
|
||||
// If this is not the case, regenerate this file with moq.
|
||||
var _ shadowhttp.Thing = &ThingMock{}
|
||||
|
||||
// ThingMock is a mock implementation of shadowhttp.Thing.
|
||||
//
|
||||
// func TestSomethingThatUsesThing(t *testing.T) {
|
||||
//
|
||||
// // make and configure a mocked shadowhttp.Thing
|
||||
// mockedThing := &ThingMock{
|
||||
// BlahFunc: func(w nethttp.ResponseWriter, r *nethttp.Request) {
|
||||
// panic("mock out the Blah method")
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// // use mockedThing in code that requires shadowhttp.Thing
|
||||
// // and then make assertions.
|
||||
//
|
||||
// }
|
||||
type ThingMock struct {
|
||||
// BlahFunc mocks the Blah method.
|
||||
BlahFunc func(w nethttp.ResponseWriter, r *nethttp.Request)
|
||||
|
||||
// calls tracks calls to the methods.
|
||||
calls struct {
|
||||
// Blah holds details about calls to the Blah method.
|
||||
Blah []struct {
|
||||
// W is the w argument value.
|
||||
W nethttp.ResponseWriter
|
||||
// R is the r argument value.
|
||||
R *nethttp.Request
|
||||
}
|
||||
}
|
||||
lockBlah sync.RWMutex
|
||||
}
|
||||
|
||||
// Blah calls BlahFunc.
|
||||
func (mock *ThingMock) Blah(w nethttp.ResponseWriter, r *nethttp.Request) {
|
||||
if mock.BlahFunc == nil {
|
||||
panic("ThingMock.BlahFunc: method is nil but Thing.Blah was just called")
|
||||
}
|
||||
callInfo := struct {
|
||||
W nethttp.ResponseWriter
|
||||
R *nethttp.Request
|
||||
}{
|
||||
W: w,
|
||||
R: r,
|
||||
}
|
||||
mock.lockBlah.Lock()
|
||||
mock.calls.Blah = append(mock.calls.Blah, callInfo)
|
||||
mock.lockBlah.Unlock()
|
||||
mock.BlahFunc(w, r)
|
||||
}
|
||||
|
||||
// BlahCalls gets all the calls that were made to Blah.
|
||||
// Check the length with:
|
||||
// len(mockedThing.BlahCalls())
|
||||
func (mock *ThingMock) BlahCalls() []struct {
|
||||
W nethttp.ResponseWriter
|
||||
R *nethttp.Request
|
||||
} {
|
||||
var calls []struct {
|
||||
W nethttp.ResponseWriter
|
||||
R *nethttp.Request
|
||||
}
|
||||
mock.lockBlah.RLock()
|
||||
calls = mock.calls.Blah
|
||||
mock.lockBlah.RUnlock()
|
||||
return calls
|
||||
}
|
14
pkg/moq/testpackages/shadow/shadower.go
Normal file
14
pkg/moq/testpackages/shadow/shadower.go
Normal file
@ -0,0 +1,14 @@
|
||||
package shadow
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Shadower is an interface, with a method, with a parameter whose name
|
||||
// shadows an import name.
|
||||
type Shadower interface {
|
||||
Shadow(io io.Reader)
|
||||
ShadowTwo(r io.Reader, io interface{})
|
||||
ShadowThree(http interface{}, srv *http.Server)
|
||||
}
|
173
pkg/moq/testpackages/shadow/shadower_moq.golden.go
Normal file
173
pkg/moq/testpackages/shadow/shadower_moq.golden.go
Normal file
@ -0,0 +1,173 @@
|
||||
// Code generated by moq; DO NOT EDIT.
|
||||
// github.com/matryer/moq
|
||||
|
||||
package shadow
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Ensure, that ShadowerMock does implement Shadower.
|
||||
// If this is not the case, regenerate this file with moq.
|
||||
var _ Shadower = &ShadowerMock{}
|
||||
|
||||
// ShadowerMock is a mock implementation of Shadower.
|
||||
//
|
||||
// func TestSomethingThatUsesShadower(t *testing.T) {
|
||||
//
|
||||
// // make and configure a mocked Shadower
|
||||
// mockedShadower := &ShadowerMock{
|
||||
// ShadowFunc: func(ioMoqParam io.Reader) {
|
||||
// panic("mock out the Shadow method")
|
||||
// },
|
||||
// ShadowThreeFunc: func(httpMoqParam interface{}, srv *http.Server) {
|
||||
// panic("mock out the ShadowThree method")
|
||||
// },
|
||||
// ShadowTwoFunc: func(r io.Reader, ioMoqParam interface{}) {
|
||||
// panic("mock out the ShadowTwo method")
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// // use mockedShadower in code that requires Shadower
|
||||
// // and then make assertions.
|
||||
//
|
||||
// }
|
||||
type ShadowerMock struct {
|
||||
// ShadowFunc mocks the Shadow method.
|
||||
ShadowFunc func(ioMoqParam io.Reader)
|
||||
|
||||
// ShadowThreeFunc mocks the ShadowThree method.
|
||||
ShadowThreeFunc func(httpMoqParam interface{}, srv *http.Server)
|
||||
|
||||
// ShadowTwoFunc mocks the ShadowTwo method.
|
||||
ShadowTwoFunc func(r io.Reader, ioMoqParam interface{})
|
||||
|
||||
// calls tracks calls to the methods.
|
||||
calls struct {
|
||||
// Shadow holds details about calls to the Shadow method.
|
||||
Shadow []struct {
|
||||
// IoMoqParam is the ioMoqParam argument value.
|
||||
IoMoqParam io.Reader
|
||||
}
|
||||
// ShadowThree holds details about calls to the ShadowThree method.
|
||||
ShadowThree []struct {
|
||||
// HttpMoqParam is the httpMoqParam argument value.
|
||||
HttpMoqParam interface{}
|
||||
// Srv is the srv argument value.
|
||||
Srv *http.Server
|
||||
}
|
||||
// ShadowTwo holds details about calls to the ShadowTwo method.
|
||||
ShadowTwo []struct {
|
||||
// R is the r argument value.
|
||||
R io.Reader
|
||||
// IoMoqParam is the ioMoqParam argument value.
|
||||
IoMoqParam interface{}
|
||||
}
|
||||
}
|
||||
lockShadow sync.RWMutex
|
||||
lockShadowThree sync.RWMutex
|
||||
lockShadowTwo sync.RWMutex
|
||||
}
|
||||
|
||||
// Shadow calls ShadowFunc.
|
||||
func (mock *ShadowerMock) Shadow(ioMoqParam io.Reader) {
|
||||
if mock.ShadowFunc == nil {
|
||||
panic("ShadowerMock.ShadowFunc: method is nil but Shadower.Shadow was just called")
|
||||
}
|
||||
callInfo := struct {
|
||||
IoMoqParam io.Reader
|
||||
}{
|
||||
IoMoqParam: ioMoqParam,
|
||||
}
|
||||
mock.lockShadow.Lock()
|
||||
mock.calls.Shadow = append(mock.calls.Shadow, callInfo)
|
||||
mock.lockShadow.Unlock()
|
||||
mock.ShadowFunc(ioMoqParam)
|
||||
}
|
||||
|
||||
// ShadowCalls gets all the calls that were made to Shadow.
|
||||
// Check the length with:
|
||||
// len(mockedShadower.ShadowCalls())
|
||||
func (mock *ShadowerMock) ShadowCalls() []struct {
|
||||
IoMoqParam io.Reader
|
||||
} {
|
||||
var calls []struct {
|
||||
IoMoqParam io.Reader
|
||||
}
|
||||
mock.lockShadow.RLock()
|
||||
calls = mock.calls.Shadow
|
||||
mock.lockShadow.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// ShadowThree calls ShadowThreeFunc.
|
||||
func (mock *ShadowerMock) ShadowThree(httpMoqParam interface{}, srv *http.Server) {
|
||||
if mock.ShadowThreeFunc == nil {
|
||||
panic("ShadowerMock.ShadowThreeFunc: method is nil but Shadower.ShadowThree was just called")
|
||||
}
|
||||
callInfo := struct {
|
||||
HttpMoqParam interface{}
|
||||
Srv *http.Server
|
||||
}{
|
||||
HttpMoqParam: httpMoqParam,
|
||||
Srv: srv,
|
||||
}
|
||||
mock.lockShadowThree.Lock()
|
||||
mock.calls.ShadowThree = append(mock.calls.ShadowThree, callInfo)
|
||||
mock.lockShadowThree.Unlock()
|
||||
mock.ShadowThreeFunc(httpMoqParam, srv)
|
||||
}
|
||||
|
||||
// ShadowThreeCalls gets all the calls that were made to ShadowThree.
|
||||
// Check the length with:
|
||||
// len(mockedShadower.ShadowThreeCalls())
|
||||
func (mock *ShadowerMock) ShadowThreeCalls() []struct {
|
||||
HttpMoqParam interface{}
|
||||
Srv *http.Server
|
||||
} {
|
||||
var calls []struct {
|
||||
HttpMoqParam interface{}
|
||||
Srv *http.Server
|
||||
}
|
||||
mock.lockShadowThree.RLock()
|
||||
calls = mock.calls.ShadowThree
|
||||
mock.lockShadowThree.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// ShadowTwo calls ShadowTwoFunc.
|
||||
func (mock *ShadowerMock) ShadowTwo(r io.Reader, ioMoqParam interface{}) {
|
||||
if mock.ShadowTwoFunc == nil {
|
||||
panic("ShadowerMock.ShadowTwoFunc: method is nil but Shadower.ShadowTwo was just called")
|
||||
}
|
||||
callInfo := struct {
|
||||
R io.Reader
|
||||
IoMoqParam interface{}
|
||||
}{
|
||||
R: r,
|
||||
IoMoqParam: ioMoqParam,
|
||||
}
|
||||
mock.lockShadowTwo.Lock()
|
||||
mock.calls.ShadowTwo = append(mock.calls.ShadowTwo, callInfo)
|
||||
mock.lockShadowTwo.Unlock()
|
||||
mock.ShadowTwoFunc(r, ioMoqParam)
|
||||
}
|
||||
|
||||
// ShadowTwoCalls gets all the calls that were made to ShadowTwo.
|
||||
// Check the length with:
|
||||
// len(mockedShadower.ShadowTwoCalls())
|
||||
func (mock *ShadowerMock) ShadowTwoCalls() []struct {
|
||||
R io.Reader
|
||||
IoMoqParam interface{}
|
||||
} {
|
||||
var calls []struct {
|
||||
R io.Reader
|
||||
IoMoqParam interface{}
|
||||
}
|
||||
mock.lockShadowTwo.RLock()
|
||||
calls = mock.calls.ShadowTwo
|
||||
mock.lockShadowTwo.RUnlock()
|
||||
return calls
|
||||
}
|
3
pkg/moq/testpackages/syncimport/sync/thing.go
Normal file
3
pkg/moq/testpackages/syncimport/sync/thing.go
Normal file
@ -0,0 +1,3 @@
|
||||
package sync
|
||||
|
||||
type Thing string
|
11
pkg/moq/testpackages/syncimport/syncer.go
Normal file
11
pkg/moq/testpackages/syncimport/syncer.go
Normal file
@ -0,0 +1,11 @@
|
||||
package syncimport
|
||||
|
||||
import (
|
||||
stdsync "sync"
|
||||
|
||||
"github.com/matryer/moq/pkg/moq/testpackages/syncimport/sync"
|
||||
)
|
||||
|
||||
type Syncer interface {
|
||||
Blah(s sync.Thing, wg *stdsync.WaitGroup)
|
||||
}
|
80
pkg/moq/testpackages/syncimport/syncer_moq.golden.go
Normal file
80
pkg/moq/testpackages/syncimport/syncer_moq.golden.go
Normal file
@ -0,0 +1,80 @@
|
||||
// Code generated by moq; DO NOT EDIT.
|
||||
// github.com/matryer/moq
|
||||
|
||||
package syncimport
|
||||
|
||||
import (
|
||||
"github.com/matryer/moq/pkg/moq/testpackages/syncimport/sync"
|
||||
stdsync "sync"
|
||||
)
|
||||
|
||||
// Ensure, that SyncerMock does implement Syncer.
|
||||
// If this is not the case, regenerate this file with moq.
|
||||
var _ Syncer = &SyncerMock{}
|
||||
|
||||
// SyncerMock is a mock implementation of Syncer.
|
||||
//
|
||||
// func TestSomethingThatUsesSyncer(t *testing.T) {
|
||||
//
|
||||
// // make and configure a mocked Syncer
|
||||
// mockedSyncer := &SyncerMock{
|
||||
// BlahFunc: func(s sync.Thing, wg *stdsync.WaitGroup) {
|
||||
// panic("mock out the Blah method")
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// // use mockedSyncer in code that requires Syncer
|
||||
// // and then make assertions.
|
||||
//
|
||||
// }
|
||||
type SyncerMock struct {
|
||||
// BlahFunc mocks the Blah method.
|
||||
BlahFunc func(s sync.Thing, wg *stdsync.WaitGroup)
|
||||
|
||||
// calls tracks calls to the methods.
|
||||
calls struct {
|
||||
// Blah holds details about calls to the Blah method.
|
||||
Blah []struct {
|
||||
// S is the s argument value.
|
||||
S sync.Thing
|
||||
// Wg is the wg argument value.
|
||||
Wg *stdsync.WaitGroup
|
||||
}
|
||||
}
|
||||
lockBlah stdsync.RWMutex
|
||||
}
|
||||
|
||||
// Blah calls BlahFunc.
|
||||
func (mock *SyncerMock) Blah(s sync.Thing, wg *stdsync.WaitGroup) {
|
||||
if mock.BlahFunc == nil {
|
||||
panic("SyncerMock.BlahFunc: method is nil but Syncer.Blah was just called")
|
||||
}
|
||||
callInfo := struct {
|
||||
S sync.Thing
|
||||
Wg *stdsync.WaitGroup
|
||||
}{
|
||||
S: s,
|
||||
Wg: wg,
|
||||
}
|
||||
mock.lockBlah.Lock()
|
||||
mock.calls.Blah = append(mock.calls.Blah, callInfo)
|
||||
mock.lockBlah.Unlock()
|
||||
mock.BlahFunc(s, wg)
|
||||
}
|
||||
|
||||
// BlahCalls gets all the calls that were made to Blah.
|
||||
// Check the length with:
|
||||
// len(mockedSyncer.BlahCalls())
|
||||
func (mock *SyncerMock) BlahCalls() []struct {
|
||||
S sync.Thing
|
||||
Wg *stdsync.WaitGroup
|
||||
} {
|
||||
var calls []struct {
|
||||
S sync.Thing
|
||||
Wg *stdsync.WaitGroup
|
||||
}
|
||||
mock.lockBlah.RLock()
|
||||
calls = mock.calls.Blah
|
||||
mock.lockBlah.RUnlock()
|
||||
return calls
|
||||
}
|
Loading…
Reference in New Issue
Block a user