Closed tocrafty closed 4 years ago
@tocrafty That sounds that you invoked the go run
in a different directory than in the one that contains go.mod
Can you share a reproducer? There are many edge cases to using mockgen with modules. And the behavior is quite subtle (especially when you are not explicitly setting the GO111MODULE
might change in the future)
This is a test to reproduce the bug.
mockgen_test is a simple project with only one golang interface III
which has two methods g()
and f()
. There are two commits in master branch. The commit before master has only one method f()
.
To mock the interface III
, I start a new project with two files:
// go.mod
module test_mockgen
go 1.13
require (
github.com/tocrafty/mockgen_test v0.0.0-20191213124124-4cc03a747f1f
)
and
# Makefile
mockgen_version ?= latest
.PHONY: docker
docker:
docker run --rm \
-v $(shell pwd):/mockgen \
-w /mockgen \
golang:1.13 \
make no-docker out=out-docker.go mockgen_version=$(mockgen_version)
.PHONY: no-docker
no-docker: out = out.go
no-docker: mockgen
# make sure we are in directory with go.mod
@echo $(shell ls -al go.mod)
# print the expect mockgen_test version in go.mod
@grep "github.com/tocrafty/mockgen_test" go.mod
# make sure GO11MODULE is on
GO111MODULE=on mockgen github.com/tocrafty/mockgen_test III > $(out)
# if we got a mocked function g(), it means mockgen used a wrong version of mogckgen_test.
@if grep "g()" $(out); then \
echo "used wrong version"; \
else \
echo "ok"; \
fi
.PHONY: mockgen
mockgen:
GO111MODULE=on go get github.com/golang/mock/mockgen@$(mockgen_version)
make no-docker
gives ok
(it runs locally on my osx). mockgen_version=v1.1.0 make docker
also gives ok
. However, any version after v1.1.0
all give used wrong version
. The output of make docker
indicated that mockgen
always tried to pull latest version of mockgen_test.
➜ make docker
docker run --rm \
-v /Users/yanbo/data/tmp/golang/mockgen:/mockgen \
-w /mockgen \
golang:1.13 \
make no-docker out=out-docker.go mockgen_version=latest
GO111MODULE=on go get github.com/golang/mock/mockgen@latest
go: finding github.com/golang/mock v1.3.1
go: downloading github.com/golang/mock v1.3.1
go: extracting github.com/golang/mock v1.3.1
go: downloading golang.org/x/tools v0.0.0-20190425150028-36563e24a262
go: extracting golang.org/x/tools v0.0.0-20190425150028-36563e24a262
go: finding golang.org/x/tools v0.0.0-20190425150028-36563e24a262
# make sure we are in directory with go.mod
-rw-r--r-- 1 root root 154 Jan 21 07:19 go.mod
# print the expect mockgen_test version in go.mod
github.com/tocrafty/mockgen_test v0.0.0-20191213124124-4cc03a747f1f
# make sure GO11MODULE is on
GO111MODULE=on mockgen github.com/tocrafty/mockgen_test III > out-docker.go
go: finding github.com/tocrafty/mockgen_test latest
go: downloading github.com/tocrafty/mockgen_test v0.0.0-20191213124830-295cf4692195
go: extracting github.com/tocrafty/mockgen_test v0.0.0-20191213124830-295cf4692195
# if we got a mocked function g(), it means mockgen used a wrong version of mogckgen_test.
func (m *MockIII) g() {
func (mr *MockIIIMockRecorder) g() *gomock.Call {
used wrong version
I can reproduce this. Let me look into this.
Let me layout the root cause of the bug. I don't have a fix yet - I need to think a bit more what approach to take.
When we are reflecting a module/package (in your case mockgen_test) we are running so called prog.go
program. There are possibly several attempts to run prog.go
program in different directories. The first attempt is to run it in the the same directory as the input package (here is the code https://github.com/golang/mock/blob/master/mockgen/reflect.go#L156 ) The problem with that approach is, that when modules are used, that first attempt is to run the prog.go
in module cache .../mod/pkg/...
. And thus the go.mod in the working dir /mockgen
is not considered.
In docker image the process runs under root and this first attempt to run prog.go
in module cache directory succeeds.
Without docker the first attempt to run prog.go
fails (because of lack of permissions on the module cache directory) and the second attempt runs prog.go
in the working dir /mockgen
(this piece of code https://github.com/golang/mock/blob/master/mockgen/reflect.go#L164). That second attempt correctly resolves your required version of mockgen_test
in go.mod
@tocrafty can you now retest with the latest mockgen?
GO111MODULE=on go get github.com/golang/mock/mockgen@latest
@nguyenfilip Seem not work. mockgen v1.4.0 still tryies to pull the latest version, not th version required in go.mod.
@tocrafty Sorry I meant if you can try with master:
GO111MODULE=on go get github.com/golang/mock/mockgen@master
It worked. Thanks.
docker image: golang:1.13 go version: go1.13.5 gomock version: all after v1.1.0 gomock work mode: reflect mode
However, in OSX, without docker, mockgen works well with go.mod. Very strange!