Skip to content
This repository was archived by the owner on Jun 27, 2023. It is now read-only.

deduplicate methods to allow overlapping methods on embedded interfaces #498

Merged
merged 3 commits into from
Jan 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,9 @@ jobs:
./ci/check_panic_handling.sh

- name: Run Go tests
run: go test -v ./...
run: |
for i in $(find $PWD -name go.mod); do
pushd $(dirname $i)
go test ./...
popd
done
8 changes: 7 additions & 1 deletion ci/check_go_generate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ trap cleanup EXIT

cp -r . "${TEMP_DIR}/"
cd $TEMP_DIR
go generate ./...

for i in $(find $PWD -name go.mod); do
pushd $(dirname $i)
go generate ./...
popd
done

if ! diff -r . "${BASE_DIR}"; then
echo
echo "The generated files aren't up to date."
Expand Down
6 changes: 5 additions & 1 deletion ci/check_go_mod.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@

set -euo pipefail

go mod tidy
for i in $(find $PWD -name go.mod); do
pushd $(dirname $i)
go mod tidy
popd
done

if [ ! -z "$(git status --porcelain)" ]; then
git status
Expand Down
5 changes: 5 additions & 0 deletions mockgen/internal/tests/overlapping_methods/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/golang/mock/mockgen/internal/tests/overlapping_methods

go 1.14

require github.com/golang/mock v1.4.4
8 changes: 8 additions & 0 deletions mockgen/internal/tests/overlapping_methods/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
13 changes: 13 additions & 0 deletions mockgen/internal/tests/overlapping_methods/interfaces.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// +build go1.14

package overlap

type ReadCloser interface {
Read([]byte) (int, error)
Close() error
}

type WriteCloser interface {
Write([]byte) (int, error)
Close() error
}
78 changes: 78 additions & 0 deletions mockgen/internal/tests/overlapping_methods/mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions mockgen/internal/tests/overlapping_methods/overlap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// +build go1.14

package overlap

//go:generate mockgen -package overlap -destination mock.go -source overlap.go -aux_files github.com/golang/mock/mockgen/internal/tests/overlapping_methods=interfaces.go
type ReadWriteCloser interface {
ReadCloser
WriteCloser
}
21 changes: 21 additions & 0 deletions mockgen/internal/tests/overlapping_methods/overlap_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// +build go1.14

package overlap

import (
"errors"
"testing"

gomock "github.com/golang/mock/gomock"
)

// TestValidInterface assesses whether or not the generated mock is valid
func TestValidInterface(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

s := NewMockReadWriteCloser(ctrl)
s.EXPECT().Close().Return(errors.New("test"))

s.Close()
}
10 changes: 6 additions & 4 deletions mockgen/mockgen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,12 @@ func TestGenerateMockInterface_Helper(t *testing.T) {
}
}

if err := g.GenerateMockInterface(&model.Interface{
Name: "Somename",
Methods: test.Methods,
}, "somepackage"); err != nil {
intf := &model.Interface{Name: "Somename"}
for _, m := range test.Methods {
intf.AddMethod(m)
}

if err := g.GenerateMockInterface(intf, "somepackage"); err != nil {
t.Fatal(err)
}

Expand Down
12 changes: 11 additions & 1 deletion mockgen/model/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ func (intf *Interface) addImports(im map[string]bool) {
}
}

// AddMethod adds a new method, deduplicating by method name.
func (intf *Interface) AddMethod(m *Method) {
for _, me := range intf.Methods {
if me.Name == m.Name {
return
}
}
intf.Methods = append(intf.Methods, m)
}

// Method is a single method of an interface.
type Method struct {
Name string
Expand Down Expand Up @@ -311,7 +321,7 @@ func InterfaceFromInterfaceType(it reflect.Type) (*Interface, error) {
return nil, err
}

intf.Methods = append(intf.Methods, m)
intf.AddMethod(m)
}

return intf, nil
Expand Down
11 changes: 7 additions & 4 deletions mockgen/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ func (p *fileParser) parseInterface(name, pkg string, it *ast.InterfaceType) (*m
if err != nil {
return nil, err
}
intf.Methods = append(intf.Methods, m)
intf.AddMethod(m)
case *ast.Ident:
// Embedded interface in this package.
ei := p.auxInterfaces[pkg][v.String()]
Expand All @@ -291,8 +291,9 @@ func (p *fileParser) parseInterface(name, pkg string, it *ast.InterfaceType) (*m
}
}
// Copy the methods.
// TODO: apply shadowing rules.
intf.Methods = append(intf.Methods, eintf.Methods...)
for _, m := range eintf.Methods {
intf.AddMethod(m)
}
case *ast.SelectorExpr:
// Embedded interface in another package.
fpkg, sel := v.X.(*ast.Ident).String(), v.Sel.String()
Expand Down Expand Up @@ -333,7 +334,9 @@ func (p *fileParser) parseInterface(name, pkg string, it *ast.InterfaceType) (*m
}
// Copy the methods.
// TODO: apply shadowing rules.
intf.Methods = append(intf.Methods, eintf.Methods...)
for _, m := range eintf.Methods {
intf.AddMethod(m)
}
default:
return nil, fmt.Errorf("don't know how to mock method of type %T", field.Type)
}
Expand Down