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

Commit b9a8584

Browse files
deduplicate methods to allow overlapping methods on embedded interfaces (#498)
1 parent 872e315 commit b9a8584

File tree

12 files changed

+176
-12
lines changed

12 files changed

+176
-12
lines changed

.github/workflows/test.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,9 @@ jobs:
4747
./ci/check_panic_handling.sh
4848
4949
- name: Run Go tests
50-
run: go test -v ./...
50+
run: |
51+
for i in $(find $PWD -name go.mod); do
52+
pushd $(dirname $i)
53+
go test ./...
54+
popd
55+
done

ci/check_go_generate.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,13 @@ trap cleanup EXIT
1818

1919
cp -r . "${TEMP_DIR}/"
2020
cd $TEMP_DIR
21-
go generate ./...
21+
22+
for i in $(find $PWD -name go.mod); do
23+
pushd $(dirname $i)
24+
go generate ./...
25+
popd
26+
done
27+
2228
if ! diff -r . "${BASE_DIR}"; then
2329
echo
2430
echo "The generated files aren't up to date."

ci/check_go_mod.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33

44
set -euo pipefail
55

6-
go mod tidy
6+
for i in $(find $PWD -name go.mod); do
7+
pushd $(dirname $i)
8+
go mod tidy
9+
popd
10+
done
711

812
if [ ! -z "$(git status --porcelain)" ]; then
913
git status
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module github.com/golang/mock/mockgen/internal/tests/overlapping_methods
2+
3+
go 1.14
4+
5+
require github.com/golang/mock v1.4.4
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
2+
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
3+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
4+
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
5+
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
6+
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
7+
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
8+
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// +build go1.14
2+
3+
package overlap
4+
5+
type ReadCloser interface {
6+
Read([]byte) (int, error)
7+
Close() error
8+
}
9+
10+
type WriteCloser interface {
11+
Write([]byte) (int, error)
12+
Close() error
13+
}

mockgen/internal/tests/overlapping_methods/mock.go

Lines changed: 78 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// +build go1.14
2+
3+
package overlap
4+
5+
//go:generate mockgen -package overlap -destination mock.go -source overlap.go -aux_files github.com/golang/mock/mockgen/internal/tests/overlapping_methods=interfaces.go
6+
type ReadWriteCloser interface {
7+
ReadCloser
8+
WriteCloser
9+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// +build go1.14
2+
3+
package overlap
4+
5+
import (
6+
"errors"
7+
"testing"
8+
9+
gomock "github.com/golang/mock/gomock"
10+
)
11+
12+
// TestValidInterface assesses whether or not the generated mock is valid
13+
func TestValidInterface(t *testing.T) {
14+
ctrl := gomock.NewController(t)
15+
defer ctrl.Finish()
16+
17+
s := NewMockReadWriteCloser(ctrl)
18+
s.EXPECT().Close().Return(errors.New("test"))
19+
20+
s.Close()
21+
}

mockgen/mockgen_test.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,10 +237,12 @@ func TestGenerateMockInterface_Helper(t *testing.T) {
237237
}
238238
}
239239

240-
if err := g.GenerateMockInterface(&model.Interface{
241-
Name: "Somename",
242-
Methods: test.Methods,
243-
}, "somepackage"); err != nil {
240+
intf := &model.Interface{Name: "Somename"}
241+
for _, m := range test.Methods {
242+
intf.AddMethod(m)
243+
}
244+
245+
if err := g.GenerateMockInterface(intf, "somepackage"); err != nil {
244246
t.Fatal(err)
245247
}
246248

mockgen/model/model.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,16 @@ func (intf *Interface) addImports(im map[string]bool) {
7171
}
7272
}
7373

74+
// AddMethod adds a new method, deduplicating by method name.
75+
func (intf *Interface) AddMethod(m *Method) {
76+
for _, me := range intf.Methods {
77+
if me.Name == m.Name {
78+
return
79+
}
80+
}
81+
intf.Methods = append(intf.Methods, m)
82+
}
83+
7484
// Method is a single method of an interface.
7585
type Method struct {
7686
Name string
@@ -311,7 +321,7 @@ func InterfaceFromInterfaceType(it reflect.Type) (*Interface, error) {
311321
return nil, err
312322
}
313323

314-
intf.Methods = append(intf.Methods, m)
324+
intf.AddMethod(m)
315325
}
316326

317327
return intf, nil

mockgen/parse.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ func (p *fileParser) parseInterface(name, pkg string, it *ast.InterfaceType) (*m
267267
if err != nil {
268268
return nil, err
269269
}
270-
intf.Methods = append(intf.Methods, m)
270+
intf.AddMethod(m)
271271
case *ast.Ident:
272272
// Embedded interface in this package.
273273
ei := p.auxInterfaces[pkg][v.String()]
@@ -291,8 +291,9 @@ func (p *fileParser) parseInterface(name, pkg string, it *ast.InterfaceType) (*m
291291
}
292292
}
293293
// Copy the methods.
294-
// TODO: apply shadowing rules.
295-
intf.Methods = append(intf.Methods, eintf.Methods...)
294+
for _, m := range eintf.Methods {
295+
intf.AddMethod(m)
296+
}
296297
case *ast.SelectorExpr:
297298
// Embedded interface in another package.
298299
fpkg, sel := v.X.(*ast.Ident).String(), v.Sel.String()
@@ -333,7 +334,9 @@ func (p *fileParser) parseInterface(name, pkg string, it *ast.InterfaceType) (*m
333334
}
334335
// Copy the methods.
335336
// TODO: apply shadowing rules.
336-
intf.Methods = append(intf.Methods, eintf.Methods...)
337+
for _, m := range eintf.Methods {
338+
intf.AddMethod(m)
339+
}
337340
default:
338341
return nil, fmt.Errorf("don't know how to mock method of type %T", field.Type)
339342
}

0 commit comments

Comments
 (0)