зеркало из https://github.com/golang/mock.git
Merge branch 'main' into master
This commit is contained in:
Коммит
42492e18bc
|
@ -1,16 +1,16 @@
|
|||
name: Run tests
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
branches: [main]
|
||||
env:
|
||||
GO111MODULE: on
|
||||
jobs:
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.11.x, 1.16.x]
|
||||
go-version: [1.15.x, 1.18.x]
|
||||
os: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
|
@ -23,33 +23,30 @@ jobs:
|
|||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Needed for versions <1.14 tests
|
||||
- name: Install mock
|
||||
run: |
|
||||
GO111MODULE=off go get github.com/golang/mock | true
|
||||
|
||||
- name: Vet and build
|
||||
run: |
|
||||
go vet ./...
|
||||
go build ./...
|
||||
|
||||
- name: Install tools
|
||||
- name: Install mockgen
|
||||
run: |
|
||||
go install github.com/golang/mock/mockgen
|
||||
GO111MODULE=off go get -u golang.org/x/lint/golint
|
||||
|
||||
- name: Run test scripts
|
||||
- name: Run test script
|
||||
run: |
|
||||
./ci/check_go_fmt.sh
|
||||
./ci/check_go_lint.sh
|
||||
./ci/check_go_generate.sh
|
||||
./ci/check_go_mod.sh
|
||||
./ci/test.sh
|
||||
./ci/check_panic_handling.sh
|
||||
|
||||
- name: Run Go tests
|
||||
- name: Run Go tests all
|
||||
if: ${{ startsWith(matrix.go-version, '1.18') }}
|
||||
run: |
|
||||
for i in $(find $PWD -name go.mod); do
|
||||
pushd $(dirname $i)
|
||||
go test ./...
|
||||
popd
|
||||
done
|
||||
|
||||
- name: Run Go tests some
|
||||
if: ${{ startsWith(matrix.go-version, '1.18') == false }}
|
||||
run: |
|
||||
go test ./...
|
||||
|
|
|
@ -17,3 +17,6 @@ mockgen/mockgen
|
|||
# Editors
|
||||
.vscode
|
||||
.idea
|
||||
|
||||
# vendor directory used for IDEs
|
||||
/vendor
|
||||
|
|
|
@ -15,6 +15,7 @@ builds:
|
|||
- linux
|
||||
goarch:
|
||||
- amd64
|
||||
- arm64
|
||||
- 386
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
|
|
46
README.md
46
README.md
|
@ -18,28 +18,18 @@ To get the latest released version use:
|
|||
### Go version < 1.16
|
||||
|
||||
```bash
|
||||
GO111MODULE=on go get github.com/golang/mock/mockgen@v1.5.0
|
||||
GO111MODULE=on go get github.com/golang/mock/mockgen@v1.6.0
|
||||
```
|
||||
|
||||
### Go 1.16+
|
||||
|
||||
```bash
|
||||
go install github.com/golang/mock/mockgen@v1.5.0
|
||||
go install github.com/golang/mock/mockgen@v1.6.0
|
||||
```
|
||||
|
||||
If you use `mockgen` in your CI pipeline, it may be more appropriate to fixate
|
||||
on a specific mockgen version.
|
||||
|
||||
## Documentation
|
||||
|
||||
After installing, you can use `go doc` to get documentation:
|
||||
|
||||
```bash
|
||||
go doc github.com/golang/mock/gomock
|
||||
```
|
||||
|
||||
Alternatively, there is an online reference for the package hosted on GoPkgDoc
|
||||
[here][gomock-reference].
|
||||
on a specific mockgen version. You should try to keep the library in sync with
|
||||
the version of mockgen used to generate your mocks.
|
||||
|
||||
## Running mockgen
|
||||
|
||||
|
@ -120,6 +110,14 @@ It supports the following flags:
|
|||
|
||||
- `-copyright_file`: Copyright file used to add copyright header to the resulting source code.
|
||||
|
||||
- `-debug_parser`: Print out parser results only.
|
||||
|
||||
- `-exec_only`: (reflect mode) If set, execute this reflection program.
|
||||
|
||||
- `-prog_only`: (reflect mode) Only generate the reflection program; write it to stdout and exit.
|
||||
|
||||
- `-write_package_comment`: Writes package documentation comment (godoc) if true. (default true)
|
||||
|
||||
For an example of the use of `mockgen`, see the `sample/` directory. In simple
|
||||
cases, you will need only the `-source` flag.
|
||||
|
||||
|
@ -257,3 +255,23 @@ If the received value is `3`, then it will be printed as `03`.
|
|||
[ci-runs]: https://github.com/golang/mock/actions
|
||||
[reference-badge]: https://pkg.go.dev/badge/github.com/golang/mock.svg
|
||||
[reference]: https://pkg.go.dev/github.com/golang/mock
|
||||
|
||||
## Debugging Errors
|
||||
|
||||
### reflect vendoring error
|
||||
|
||||
```text
|
||||
cannot find package "."
|
||||
... github.com/golang/mock/mockgen/model
|
||||
```
|
||||
|
||||
If you come across this error while using reflect mode and vendoring
|
||||
dependencies there are three workarounds you can choose from:
|
||||
|
||||
1. Use source mode.
|
||||
2. Include an empty import `import _ "github.com/golang/mock/mockgen/model"`.
|
||||
3. Add `--build_flags=--mod=mod` to your mockgen command.
|
||||
|
||||
This error is due to changes in default behavior of the `go` command in more
|
||||
recent versions. More details can be found in
|
||||
[#494](https://github.com/golang/mock/issues/494).
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
#!/bin/bash
|
||||
# This script is used by the CI to check if the code is gofmt formatted.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
GOFMT_DIFF=$(IFS=$'\n'; gofmt -d $( find . -type f -name '*.go' ) )
|
||||
if [[ -n "${GOFMT_DIFF}" ]]; then
|
||||
echo "${GOFMT_DIFF}"
|
||||
echo
|
||||
echo "The go source files aren't gofmt formatted."
|
||||
exit 1
|
||||
fi
|
|
@ -1,33 +0,0 @@
|
|||
#!/bin/bash
|
||||
# This script is used by the CI to check if 'go generate ./...' is up to date.
|
||||
#
|
||||
# Note: If the generated files aren't up to date then this script updates
|
||||
# them despite printing an error message so running it the second time
|
||||
# might not print any errors. This isn't very useful locally during development
|
||||
# but it works well with the CI that downloads a fresh version of the repo
|
||||
# each time before executing this script.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
BASE_DIR="$PWD"
|
||||
TEMP_DIR=$( mktemp -d )
|
||||
function cleanup() {
|
||||
rm -rf "${TEMP_DIR}"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
cp -r . "${TEMP_DIR}/"
|
||||
cd $TEMP_DIR
|
||||
|
||||
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."
|
||||
echo "Update them with the 'go generate ./...' command."
|
||||
exit 1
|
||||
fi
|
|
@ -1,17 +0,0 @@
|
|||
#!/bin/bash
|
||||
# This script is used by CI to check if the code passes golint.
|
||||
|
||||
set -u
|
||||
|
||||
if ! command -v golint >/dev/null; then
|
||||
echo "error: golint not found; go get -u golang.org/x/lint/golint" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
GOLINT_OUTPUT=$(IFS=$'\n'; golint ./... | grep -v "mockgen/internal/.*\|sample/.*")
|
||||
if [[ -n "${GOLINT_OUTPUT}" ]]; then
|
||||
echo "${GOLINT_OUTPUT}"
|
||||
echo
|
||||
echo "The go source files aren't passing golint."
|
||||
exit 1
|
||||
fi
|
|
@ -1,18 +0,0 @@
|
|||
#!/bin/bash
|
||||
# This script is used to ensure that the go.mod file is up to date.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
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
|
||||
git diff
|
||||
echo
|
||||
echo "The go.mod is not up to date."
|
||||
exit 1
|
||||
fi
|
|
@ -0,0 +1,45 @@
|
|||
#!/bin/bash
|
||||
# This script is used to ensure that the go.mod file is up to date.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $(go version) != *"go1.18"* ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
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
|
||||
git diff
|
||||
echo
|
||||
echo "The go.mod is not up to date."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BASE_DIR="$PWD"
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
function cleanup() {
|
||||
rm -rf "${TEMP_DIR}"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
cp -r . "${TEMP_DIR}/"
|
||||
cd $TEMP_DIR
|
||||
|
||||
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."
|
||||
echo "Update them with the 'go generate ./...' command."
|
||||
exit 1
|
||||
fi
|
6
go.mod
6
go.mod
|
@ -1,8 +1,8 @@
|
|||
module github.com/golang/mock
|
||||
|
||||
require (
|
||||
golang.org/x/mod v0.4.1
|
||||
golang.org/x/tools v0.1.0
|
||||
golang.org/x/mod v0.5.1
|
||||
golang.org/x/tools v0.1.8
|
||||
)
|
||||
|
||||
go 1.11
|
||||
go 1.15
|
||||
|
|
29
go.sum
29
go.sum
|
@ -1,27 +1,28 @@
|
|||
github.com/yuin/goldmark v1.2.1 h1:ruQGxdhGHe7FWOJPT0mKs5+pD2Xs1Bm/kdGlHO04FmM=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.1 h1:/vn0k+RBvwlxEmP5E7SZMqNxPhfMVFEJiykr15/0XKM=
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1 h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
|
||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 h1:myAQVi0cGEoqQVR5POX+8RR2mrocKqNN1hmeMqhX27k=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 h1:id054HUawV2/6IGm2IV8KZQjqtwAOo2CYlOToYqa0d0=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w=
|
||||
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
|
|
|
@ -138,13 +138,25 @@ func (c *Call) MaxTimes(n int) *Call {
|
|||
// DoAndReturn declares the action to run when the call is matched.
|
||||
// The return values from this function are returned by the mocked function.
|
||||
// It takes an interface{} argument to support n-arity functions.
|
||||
// The anonymous function must match the function signature mocked method.
|
||||
func (c *Call) DoAndReturn(f interface{}) *Call {
|
||||
// TODO: Check arity and types here, rather than dying badly elsewhere.
|
||||
v := reflect.ValueOf(f)
|
||||
|
||||
c.addAction(func(args []interface{}) []interface{} {
|
||||
vArgs := make([]reflect.Value, len(args))
|
||||
c.t.Helper()
|
||||
ft := v.Type()
|
||||
if c.methodType.NumIn() != ft.NumIn() {
|
||||
if ft.IsVariadic() {
|
||||
c.t.Fatalf("wrong number of arguments in DoAndReturn func for %T.%v The function signature must match the mocked method, a variadic function cannot be used.",
|
||||
c.receiver, c.method)
|
||||
} else {
|
||||
c.t.Fatalf("wrong number of arguments in DoAndReturn func for %T.%v: got %d, want %d [%s]",
|
||||
c.receiver, c.method, ft.NumIn(), c.methodType.NumIn(), c.origin)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
vArgs := make([]reflect.Value, len(args))
|
||||
for i := 0; i < len(args); i++ {
|
||||
if args[i] != nil {
|
||||
vArgs[i] = reflect.ValueOf(args[i])
|
||||
|
@ -167,13 +179,25 @@ func (c *Call) DoAndReturn(f interface{}) *Call {
|
|||
// return values are ignored to retain backward compatibility. To use the
|
||||
// return values call DoAndReturn.
|
||||
// It takes an interface{} argument to support n-arity functions.
|
||||
// The anonymous function must match the function signature mocked method.
|
||||
func (c *Call) Do(f interface{}) *Call {
|
||||
// TODO: Check arity and types here, rather than dying badly elsewhere.
|
||||
v := reflect.ValueOf(f)
|
||||
|
||||
c.addAction(func(args []interface{}) []interface{} {
|
||||
vArgs := make([]reflect.Value, len(args))
|
||||
c.t.Helper()
|
||||
ft := v.Type()
|
||||
if c.methodType.NumIn() != ft.NumIn() {
|
||||
if ft.IsVariadic() {
|
||||
c.t.Fatalf("wrong number of arguments in Do func for %T.%v The function signature must match the mocked method, a variadic function cannot be used.",
|
||||
c.receiver, c.method)
|
||||
} else {
|
||||
c.t.Fatalf("wrong number of arguments in Do func for %T.%v: got %d, want %d [%s]",
|
||||
c.receiver, c.method, ft.NumIn(), c.methodType.NumIn(), c.origin)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
vArgs := make([]reflect.Value, len(args))
|
||||
for i := 0; i < len(args); i++ {
|
||||
if args[i] != nil {
|
||||
vArgs[i] = reflect.ValueOf(args[i])
|
||||
|
@ -239,8 +263,8 @@ func (c *Call) Times(n int) *Call {
|
|||
}
|
||||
|
||||
// SetArg declares an action that will set the nth argument's value,
|
||||
// indirected through a pointer. Or, in the case of a slice, SetArg
|
||||
// will copy value's elements into the nth argument.
|
||||
// indirected through a pointer. Or, in the case of a slice and map, SetArg
|
||||
// will copy value's elements/key-value pairs into the nth argument.
|
||||
func (c *Call) SetArg(n int, value interface{}) *Call {
|
||||
c.t.Helper()
|
||||
|
||||
|
@ -265,8 +289,10 @@ func (c *Call) SetArg(n int, value interface{}) *Call {
|
|||
// nothing to do
|
||||
case reflect.Slice:
|
||||
// nothing to do
|
||||
case reflect.Map:
|
||||
// nothing to do
|
||||
default:
|
||||
c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface non-slice type %v [%s]",
|
||||
c.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface non-slice non-map type %v [%s]",
|
||||
n, at, c.origin)
|
||||
}
|
||||
|
||||
|
@ -275,6 +301,8 @@ func (c *Call) SetArg(n int, value interface{}) *Call {
|
|||
switch reflect.TypeOf(args[n]).Kind() {
|
||||
case reflect.Slice:
|
||||
setSlice(args[n], v)
|
||||
case reflect.Map:
|
||||
setMap(args[n], v)
|
||||
default:
|
||||
reflect.ValueOf(args[n]).Elem().Set(v)
|
||||
}
|
||||
|
@ -423,7 +451,7 @@ func (c *Call) matches(args []interface{}) error {
|
|||
// Check that all prerequisite calls have been satisfied.
|
||||
for _, preReqCall := range c.preReqs {
|
||||
if !preReqCall.satisfied() {
|
||||
return fmt.Errorf("Expected call at %s doesn't have a prerequisite call satisfied:\n%v\nshould be called before:\n%v",
|
||||
return fmt.Errorf("expected call at %s doesn't have a prerequisite call satisfied:\n%v\nshould be called before:\n%v",
|
||||
c.origin, preReqCall, c)
|
||||
}
|
||||
}
|
||||
|
@ -463,12 +491,22 @@ func setSlice(arg interface{}, v reflect.Value) {
|
|||
}
|
||||
}
|
||||
|
||||
func setMap(arg interface{}, v reflect.Value) {
|
||||
va := reflect.ValueOf(arg)
|
||||
for _, e := range va.MapKeys() {
|
||||
va.SetMapIndex(e, reflect.Value{})
|
||||
}
|
||||
for _, e := range v.MapKeys() {
|
||||
va.SetMapIndex(e, v.MapIndex(e))
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Call) addAction(action func([]interface{}) []interface{}) {
|
||||
c.actions = append(c.actions, action)
|
||||
}
|
||||
|
||||
func formatGottenArg(m Matcher, arg interface{}) string {
|
||||
got := fmt.Sprintf("%v", arg)
|
||||
got := fmt.Sprintf("%v (%T)", arg, arg)
|
||||
if gs, ok := m.(GotFormatter); ok {
|
||||
got = gs.Got(arg)
|
||||
}
|
||||
|
|
|
@ -126,9 +126,7 @@ var testCases []testCase = []testCase{
|
|||
{
|
||||
description: "argument to Do is not a function",
|
||||
doFunc: "meow",
|
||||
callFunc: func(x int, y int) {
|
||||
return
|
||||
},
|
||||
callFunc: func(x int, y int) {},
|
||||
args: []interface{}{0, 1},
|
||||
expectPanic: true,
|
||||
}, {
|
||||
|
@ -141,14 +139,10 @@ var testCases []testCase = []testCase{
|
|||
expectPanic: true,
|
||||
}, {
|
||||
description: "number of args for Do func don't match Call func",
|
||||
doFunc: func(x int) {
|
||||
return
|
||||
},
|
||||
callFunc: func(x int, y int) {
|
||||
return
|
||||
},
|
||||
doFunc: func(x int) {},
|
||||
callFunc: func(x int, y int) {},
|
||||
args: []interface{}{0, 1},
|
||||
expectPanic: true,
|
||||
expectPanic: false,
|
||||
}, {
|
||||
description: "number of args for Do func don't match Call func",
|
||||
doFunc: func(x int) bool {
|
||||
|
@ -158,15 +152,11 @@ var testCases []testCase = []testCase{
|
|||
return true
|
||||
},
|
||||
args: []interface{}{0, 1},
|
||||
expectPanic: true,
|
||||
expectPanic: false,
|
||||
}, {
|
||||
description: "arg type for Do func incompatible with Call func",
|
||||
doFunc: func(x int) {
|
||||
return
|
||||
},
|
||||
callFunc: func(x string) {
|
||||
return
|
||||
},
|
||||
doFunc: func(x int) {},
|
||||
callFunc: func(x string) {},
|
||||
args: []interface{}{"meow"},
|
||||
expectPanic: true,
|
||||
}, {
|
||||
|
@ -181,21 +171,13 @@ var testCases []testCase = []testCase{
|
|||
expectPanic: true,
|
||||
}, {
|
||||
description: "Do func(int) Call func(int)",
|
||||
doFunc: func(x int) {
|
||||
return
|
||||
},
|
||||
callFunc: func(x int) {
|
||||
return
|
||||
},
|
||||
doFunc: func(x int) {},
|
||||
callFunc: func(x int) {},
|
||||
args: []interface{}{0},
|
||||
}, {
|
||||
description: "Do func(int) Call func(interface{})",
|
||||
doFunc: func(x int) {
|
||||
return
|
||||
},
|
||||
callFunc: func(x interface{}) {
|
||||
return
|
||||
},
|
||||
doFunc: func(x int) {},
|
||||
callFunc: func(x interface{}) {},
|
||||
args: []interface{}{0},
|
||||
}, {
|
||||
description: "Do func(int) bool Call func(int) bool",
|
||||
|
@ -217,12 +199,8 @@ var testCases []testCase = []testCase{
|
|||
args: []interface{}{0},
|
||||
}, {
|
||||
description: "Do func(string) Call func([]byte)",
|
||||
doFunc: func(x string) {
|
||||
return
|
||||
},
|
||||
callFunc: func(x []byte) {
|
||||
return
|
||||
},
|
||||
doFunc: func(x string) {},
|
||||
callFunc: func(x []byte) {},
|
||||
args: []interface{}{[]byte("meow")},
|
||||
expectPanic: true,
|
||||
}, {
|
||||
|
@ -237,22 +215,14 @@ var testCases []testCase = []testCase{
|
|||
expectPanic: true,
|
||||
}, {
|
||||
description: "Do func(map[int]string) Call func(map[interface{}]int)",
|
||||
doFunc: func(x map[int]string) {
|
||||
return
|
||||
},
|
||||
callFunc: func(x map[interface{}]int) {
|
||||
return
|
||||
},
|
||||
doFunc: func(x map[int]string) {},
|
||||
callFunc: func(x map[interface{}]int) {},
|
||||
args: []interface{}{map[interface{}]int{"meow": 0}},
|
||||
expectPanic: true,
|
||||
}, {
|
||||
description: "Do func(map[int]string) Call func(map[interface{}]interface{})",
|
||||
doFunc: func(x map[int]string) {
|
||||
return
|
||||
},
|
||||
callFunc: func(x map[interface{}]interface{}) {
|
||||
return
|
||||
},
|
||||
doFunc: func(x map[int]string) {},
|
||||
callFunc: func(x map[interface{}]interface{}) {},
|
||||
args: []interface{}{map[interface{}]interface{}{"meow": "meow"}},
|
||||
expectPanic: true,
|
||||
}, {
|
||||
|
@ -277,61 +247,37 @@ var testCases []testCase = []testCase{
|
|||
expectPanic: true,
|
||||
}, {
|
||||
description: "Do func([]string) Call func([]interface{})",
|
||||
doFunc: func(x []string) {
|
||||
return
|
||||
},
|
||||
callFunc: func(x []interface{}) {
|
||||
return
|
||||
},
|
||||
doFunc: func(x []string) {},
|
||||
callFunc: func(x []interface{}) {},
|
||||
args: []interface{}{[]interface{}{0}},
|
||||
expectPanic: true,
|
||||
}, {
|
||||
description: "Do func([]string) Call func([]int)",
|
||||
doFunc: func(x []string) {
|
||||
return
|
||||
},
|
||||
callFunc: func(x []int) {
|
||||
return
|
||||
},
|
||||
doFunc: func(x []string) {},
|
||||
callFunc: func(x []int) {},
|
||||
args: []interface{}{[]int{0, 1}},
|
||||
expectPanic: true,
|
||||
}, {
|
||||
description: "Do func([]int) Call func([]int)",
|
||||
doFunc: func(x []int) {
|
||||
return
|
||||
},
|
||||
callFunc: func(x []int) {
|
||||
return
|
||||
},
|
||||
doFunc: func(x []int) {},
|
||||
callFunc: func(x []int) {},
|
||||
args: []interface{}{[]int{0, 1}},
|
||||
}, {
|
||||
description: "Do func([]int) Call func([]interface{})",
|
||||
doFunc: func(x []int) {
|
||||
return
|
||||
},
|
||||
callFunc: func(x []interface{}) {
|
||||
return
|
||||
},
|
||||
doFunc: func(x []int) {},
|
||||
callFunc: func(x []interface{}) {},
|
||||
args: []interface{}{[]interface{}{0}},
|
||||
expectPanic: true,
|
||||
}, {
|
||||
description: "Do func([]int) Call func(...interface{})",
|
||||
doFunc: func(x []int) {
|
||||
return
|
||||
},
|
||||
callFunc: func(x ...interface{}) {
|
||||
return
|
||||
},
|
||||
doFunc: func(x []int) {},
|
||||
callFunc: func(x ...interface{}) {},
|
||||
args: []interface{}{0, 1},
|
||||
expectPanic: true,
|
||||
}, {
|
||||
description: "Do func([]int) Call func(...int)",
|
||||
doFunc: func(x []int) {
|
||||
return
|
||||
},
|
||||
callFunc: func(x ...int) {
|
||||
return
|
||||
},
|
||||
doFunc: func(x []int) {},
|
||||
callFunc: func(x ...int) {},
|
||||
args: []interface{}{0, 1},
|
||||
expectPanic: true,
|
||||
}, {
|
||||
|
@ -395,32 +341,20 @@ var testCases []testCase = []testCase{
|
|||
expectPanic: true,
|
||||
}, {
|
||||
description: "Do func(...int) Call func([]int)",
|
||||
doFunc: func(x ...int) {
|
||||
return
|
||||
},
|
||||
callFunc: func(x []int) {
|
||||
return
|
||||
},
|
||||
doFunc: func(x ...int) {},
|
||||
callFunc: func(x []int) {},
|
||||
args: []interface{}{[]int{0, 1}},
|
||||
expectPanic: true,
|
||||
}, {
|
||||
description: "Do func(...int) Call func([]interface{})",
|
||||
doFunc: func(x ...int) {
|
||||
return
|
||||
},
|
||||
callFunc: func(x []interface{}) {
|
||||
return
|
||||
},
|
||||
doFunc: func(x ...int) {},
|
||||
callFunc: func(x []interface{}) {},
|
||||
args: []interface{}{[]interface{}{0, 1}},
|
||||
expectPanic: true,
|
||||
}, {
|
||||
description: "Do func(...int) Call func(...interface{})",
|
||||
doFunc: func(x ...int) {
|
||||
return
|
||||
},
|
||||
callFunc: func(x ...interface{}) {
|
||||
return
|
||||
},
|
||||
doFunc: func(x ...int) {},
|
||||
callFunc: func(x ...interface{}) {},
|
||||
args: []interface{}{0, 1},
|
||||
}, {
|
||||
description: "Do func(...int) bool Call func(...int) bool",
|
||||
|
@ -462,40 +396,24 @@ var testCases []testCase = []testCase{
|
|||
args: []interface{}{0, 1},
|
||||
}, {
|
||||
description: "Do func(...int) Call func(...int)",
|
||||
doFunc: func(x ...int) {
|
||||
return
|
||||
},
|
||||
callFunc: func(x ...int) {
|
||||
return
|
||||
},
|
||||
doFunc: func(x ...int) {},
|
||||
callFunc: func(x ...int) {},
|
||||
args: []interface{}{0, 1},
|
||||
}, {
|
||||
description: "Do func(foo); foo implements interface X Call func(interface X)",
|
||||
doFunc: func(x foo) {
|
||||
return
|
||||
},
|
||||
callFunc: func(x fmt.Stringer) {
|
||||
return
|
||||
},
|
||||
doFunc: func(x foo) {},
|
||||
callFunc: func(x fmt.Stringer) {},
|
||||
args: []interface{}{foo{}},
|
||||
}, {
|
||||
description: "Do func(b); b does not implement interface X Call func(interface X)",
|
||||
doFunc: func(x b) {
|
||||
return
|
||||
},
|
||||
callFunc: func(x fmt.Stringer) {
|
||||
return
|
||||
},
|
||||
doFunc: func(x b) {},
|
||||
callFunc: func(x fmt.Stringer) {},
|
||||
args: []interface{}{foo{}},
|
||||
expectPanic: true,
|
||||
}, {
|
||||
description: "Do func(b) Call func(a); a and b are not aliases",
|
||||
doFunc: func(x b) {
|
||||
return
|
||||
},
|
||||
callFunc: func(x a) {
|
||||
return
|
||||
},
|
||||
doFunc: func(x b) {},
|
||||
callFunc: func(x a) {},
|
||||
args: []interface{}{a{}},
|
||||
expectPanic: true,
|
||||
}, {
|
||||
|
@ -563,6 +481,118 @@ func TestCall_Do(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestCall_Do_NumArgValidation(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
methodType reflect.Type
|
||||
doFn interface{}
|
||||
args []interface{}
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "too few",
|
||||
methodType: reflect.TypeOf(func(one, two string) {}),
|
||||
doFn: func(one string) {},
|
||||
args: []interface{}{"too", "few"},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "too many",
|
||||
methodType: reflect.TypeOf(func(one, two string) {}),
|
||||
doFn: func(one, two, three string) {},
|
||||
args: []interface{}{"too", "few"},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "just right",
|
||||
methodType: reflect.TypeOf(func(one, two string) {}),
|
||||
doFn: func(one string, two string) {},
|
||||
args: []interface{}{"just", "right"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "variadic",
|
||||
methodType: reflect.TypeOf(func(one, two string) {}),
|
||||
doFn: func(args ...interface{}) {},
|
||||
args: []interface{}{"just", "right"},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tr := &mockTestReporter{}
|
||||
call := &Call{
|
||||
t: tr,
|
||||
methodType: tt.methodType,
|
||||
}
|
||||
call.Do(tt.doFn)
|
||||
call.actions[0](tt.args)
|
||||
if tt.wantErr && tr.fatalCalls != 1 {
|
||||
t.Fatalf("expected call to fail")
|
||||
}
|
||||
if !tt.wantErr && tr.fatalCalls != 0 {
|
||||
t.Fatalf("expected call to pass")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCall_DoAndReturn_NumArgValidation(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
methodType reflect.Type
|
||||
doFn interface{}
|
||||
args []interface{}
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "too few",
|
||||
methodType: reflect.TypeOf(func(one, two string) string { return "" }),
|
||||
doFn: func(one string) {},
|
||||
args: []interface{}{"too", "few"},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "too many",
|
||||
methodType: reflect.TypeOf(func(one, two string) string { return "" }),
|
||||
doFn: func(one, two, three string) string { return "" },
|
||||
args: []interface{}{"too", "few"},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "just right",
|
||||
methodType: reflect.TypeOf(func(one, two string) string { return "" }),
|
||||
doFn: func(one string, two string) string { return "" },
|
||||
args: []interface{}{"just", "right"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "variadic",
|
||||
methodType: reflect.TypeOf(func(one, two string) {}),
|
||||
doFn: func(args ...interface{}) string { return "" },
|
||||
args: []interface{}{"just", "right"},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tr := &mockTestReporter{}
|
||||
call := &Call{
|
||||
t: tr,
|
||||
methodType: tt.methodType,
|
||||
}
|
||||
call.DoAndReturn(tt.doFn)
|
||||
call.actions[0](tt.args)
|
||||
if tt.wantErr && tr.fatalCalls != 1 {
|
||||
t.Fatalf("expected call to fail")
|
||||
}
|
||||
if !tt.wantErr && tr.fatalCalls != 0 {
|
||||
t.Fatalf("expected call to pass")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCall_DoAndReturn(t *testing.T) {
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
|
|
|
@ -16,6 +16,7 @@ package gomock
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
|
@ -105,7 +106,7 @@ func (cs callSet) FindMatch(receiver interface{}, method string, args []interfac
|
|||
_, _ = fmt.Fprintf(&callsErrors, "there are no expected calls of the method %q for that receiver", method)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf(callsErrors.String())
|
||||
return nil, errors.New(callsErrors.String())
|
||||
}
|
||||
|
||||
// Failures returns the calls that are not satisfied.
|
||||
|
|
|
@ -12,44 +12,6 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package gomock is a mock framework for Go.
|
||||
//
|
||||
// Standard usage:
|
||||
// (1) Define an interface that you wish to mock.
|
||||
// type MyInterface interface {
|
||||
// SomeMethod(x int64, y string)
|
||||
// }
|
||||
// (2) Use mockgen to generate a mock from the interface.
|
||||
// (3) Use the mock in a test:
|
||||
// func TestMyThing(t *testing.T) {
|
||||
// mockCtrl := gomock.NewController(t)
|
||||
// defer mockCtrl.Finish()
|
||||
//
|
||||
// mockObj := something.NewMockMyInterface(mockCtrl)
|
||||
// mockObj.EXPECT().SomeMethod(4, "blah")
|
||||
// // pass mockObj to a real object and play with it.
|
||||
// }
|
||||
//
|
||||
// By default, expected calls are not enforced to run in any particular order.
|
||||
// Call order dependency can be enforced by use of InOrder and/or Call.After.
|
||||
// Call.After can create more varied call order dependencies, but InOrder is
|
||||
// often more convenient.
|
||||
//
|
||||
// The following examples create equivalent call order dependencies.
|
||||
//
|
||||
// Example of using Call.After to chain expected call order:
|
||||
//
|
||||
// firstCall := mockObj.EXPECT().SomeMethod(1, "first")
|
||||
// secondCall := mockObj.EXPECT().SomeMethod(2, "second").After(firstCall)
|
||||
// mockObj.EXPECT().SomeMethod(3, "third").After(secondCall)
|
||||
//
|
||||
// Example of using InOrder to declare expected call order:
|
||||
//
|
||||
// gomock.InOrder(
|
||||
// mockObj.EXPECT().SomeMethod(1, "first"),
|
||||
// mockObj.EXPECT().SomeMethod(2, "second"),
|
||||
// mockObj.EXPECT().SomeMethod(3, "third"),
|
||||
// )
|
||||
package gomock
|
||||
|
||||
import (
|
||||
|
@ -123,7 +85,7 @@ type Controller struct {
|
|||
// Controller.
|
||||
//
|
||||
// New in go1.14+, if you are passing a *testing.T into this function you no
|
||||
// longer need to call ctrl.Finish() in your test methods
|
||||
// longer need to call ctrl.Finish() in your test methods.
|
||||
func NewController(t TestReporter) *Controller {
|
||||
h, ok := t.(TestHelper)
|
||||
if !ok {
|
||||
|
@ -259,6 +221,9 @@ func (ctrl *Controller) Call(receiver interface{}, method string, args ...interf
|
|||
// Finish checks to see if all the methods that were expected to be called
|
||||
// were called. It should be invoked for each Controller. It is not idempotent
|
||||
// and therefore can only be invoked once.
|
||||
//
|
||||
// New in go1.14+, if you are passing a *testing.T into NewController function you no
|
||||
// longer need to call ctrl.Finish() in your test methods.
|
||||
func (ctrl *Controller) Finish() {
|
||||
// If we're currently panicking, probably because this is a deferred call.
|
||||
// This must be recovered in the deferred function.
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build !go1.14
|
||||
|
||||
package gomock_test
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestDuplicateFinishCallFails(t *testing.T) {
|
||||
rep, ctrl := createFixtures(t)
|
||||
|
||||
ctrl.Finish()
|
||||
rep.assertPass("the first Finish call should succeed")
|
||||
|
||||
rep.assertFatal(ctrl.Finish, "Controller.Finish was called more than once. It has to be called exactly once.")
|
||||
}
|
|
@ -1,132 +0,0 @@
|
|||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build go1.14
|
||||
|
||||
package gomock_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
func (e *ErrorReporter) Cleanup(f func()) {
|
||||
e.t.Helper()
|
||||
e.t.Cleanup(f)
|
||||
}
|
||||
|
||||
func TestMultipleDefers(t *testing.T) {
|
||||
reporter := NewErrorReporter(t)
|
||||
reporter.Cleanup(func() {
|
||||
reporter.assertPass("No errors for multiple calls to Finish")
|
||||
})
|
||||
ctrl := gomock.NewController(reporter)
|
||||
ctrl.Finish()
|
||||
}
|
||||
|
||||
// Equivalent to the TestNoRecordedCallsForAReceiver, but without explicitly
|
||||
// calling Finish.
|
||||
func TestDeferNotNeededFail(t *testing.T) {
|
||||
reporter := NewErrorReporter(t)
|
||||
subject := new(Subject)
|
||||
var ctrl *gomock.Controller
|
||||
reporter.Cleanup(func() {
|
||||
reporter.assertFatal(func() {
|
||||
ctrl.Call(subject, "NotRecordedMethod", "argument")
|
||||
}, "Unexpected call to", "there are no expected calls of the method \"NotRecordedMethod\" for that receiver")
|
||||
})
|
||||
ctrl = gomock.NewController(reporter)
|
||||
}
|
||||
|
||||
func TestDeferNotNeededPass(t *testing.T) {
|
||||
reporter := NewErrorReporter(t)
|
||||
subject := new(Subject)
|
||||
var ctrl *gomock.Controller
|
||||
reporter.Cleanup(func() {
|
||||
reporter.assertPass("Expected method call made.")
|
||||
})
|
||||
ctrl = gomock.NewController(reporter)
|
||||
ctrl.RecordCall(subject, "FooMethod", "argument")
|
||||
ctrl.Call(subject, "FooMethod", "argument")
|
||||
}
|
||||
|
||||
func TestOrderedCallsInCorrect(t *testing.T) {
|
||||
reporter := NewErrorReporter(t)
|
||||
subjectOne := new(Subject)
|
||||
subjectTwo := new(Subject)
|
||||
var ctrl *gomock.Controller
|
||||
reporter.Cleanup(func() {
|
||||
reporter.assertFatal(func() {
|
||||
gomock.InOrder(
|
||||
ctrl.RecordCall(subjectOne, "FooMethod", "1").AnyTimes(),
|
||||
ctrl.RecordCall(subjectTwo, "FooMethod", "2"),
|
||||
ctrl.RecordCall(subjectTwo, "BarMethod", "3"),
|
||||
)
|
||||
ctrl.Call(subjectOne, "FooMethod", "1")
|
||||
// FooMethod(2) should be called before BarMethod(3)
|
||||
ctrl.Call(subjectTwo, "BarMethod", "3")
|
||||
}, "Unexpected call to", "Subject.BarMethod([3])", "doesn't have a prerequisite call satisfied")
|
||||
})
|
||||
ctrl = gomock.NewController(reporter)
|
||||
}
|
||||
|
||||
// Test that calls that are prerequisites to other calls but have maxCalls >
|
||||
// minCalls are removed from the expected call set.
|
||||
func TestOrderedCallsWithPreReqMaxUnbounded(t *testing.T) {
|
||||
reporter := NewErrorReporter(t)
|
||||
subjectOne := new(Subject)
|
||||
subjectTwo := new(Subject)
|
||||
var ctrl *gomock.Controller
|
||||
reporter.Cleanup(func() {
|
||||
reporter.assertFatal(func() {
|
||||
// Initially we should be able to call FooMethod("1") as many times as we
|
||||
// want.
|
||||
ctrl.Call(subjectOne, "FooMethod", "1")
|
||||
ctrl.Call(subjectOne, "FooMethod", "1")
|
||||
|
||||
// But calling something that has it as a prerequite should remove it from
|
||||
// the expected call set. This allows tests to ensure that FooMethod("1") is
|
||||
// *not* called after FooMethod("2").
|
||||
ctrl.Call(subjectTwo, "FooMethod", "2")
|
||||
|
||||
ctrl.Call(subjectOne, "FooMethod", "1")
|
||||
})
|
||||
})
|
||||
ctrl = gomock.NewController(reporter)
|
||||
}
|
||||
|
||||
func TestCallAfterLoopPanic(t *testing.T) {
|
||||
reporter := NewErrorReporter(t)
|
||||
subject := new(Subject)
|
||||
var ctrl *gomock.Controller
|
||||
reporter.Cleanup(func() {
|
||||
firstCall := ctrl.RecordCall(subject, "FooMethod", "1")
|
||||
secondCall := ctrl.RecordCall(subject, "FooMethod", "2")
|
||||
thirdCall := ctrl.RecordCall(subject, "FooMethod", "3")
|
||||
|
||||
gomock.InOrder(firstCall, secondCall, thirdCall)
|
||||
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err == nil {
|
||||
t.Error("Call.After creation of dependency loop did not panic.")
|
||||
}
|
||||
}()
|
||||
|
||||
// This should panic due to dependency loop.
|
||||
firstCall.After(thirdCall)
|
||||
})
|
||||
ctrl = gomock.NewController(reporter)
|
||||
}
|
|
@ -54,17 +54,6 @@ func (e *ErrorReporter) assertFail(msg string) {
|
|||
}
|
||||
}
|
||||
|
||||
func (e *ErrorReporter) assertLogf(expectedErrMsgs ...string) {
|
||||
if len(e.log) < len(expectedErrMsgs) {
|
||||
e.t.Fatalf("got %d Logf messages, want %d", len(e.log), len(expectedErrMsgs))
|
||||
}
|
||||
for i, expectedErrMsg := range expectedErrMsgs {
|
||||
if !strings.Contains(e.log[i], expectedErrMsg) {
|
||||
e.t.Errorf("Error message:\ngot: %q\nwant to contain: %q\n", e.log[i], expectedErrMsg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use to check that code triggers a fatal test failure.
|
||||
func (e *ErrorReporter) assertFatal(fn func(), expectedErrMsgs ...string) {
|
||||
defer func() {
|
||||
|
@ -169,7 +158,8 @@ func (s *Subject) ActOnTestStructMethod(arg TestStruct, arg1 int) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
func (s *Subject) SetArgMethod(sliceArg []byte, ptrArg *int) {}
|
||||
func (s *Subject) SetArgMethod(sliceArg []byte, ptrArg *int, mapArg map[interface{}]interface{}) {}
|
||||
func (s *Subject) SetArgMethodInterface(sliceArg, ptrArg, mapArg interface{}) {}
|
||||
|
||||
func assertEqual(t *testing.T, expected interface{}, actual interface{}) {
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
|
@ -292,20 +282,20 @@ func TestUnexpectedArgValue_FirstArg(t *testing.T) {
|
|||
defer reporter.recoverUnexpectedFatal()
|
||||
subject := new(Subject)
|
||||
|
||||
expectedArg0 := TestStruct{Number: 123, Message: "hello"}
|
||||
expectedArg0 := TestStruct{Number: 123, Message: "hello %s"}
|
||||
ctrl.RecordCall(subject, "ActOnTestStructMethod", expectedArg0, 15)
|
||||
|
||||
reporter.assertFatal(func() {
|
||||
// the method argument (of TestStruct type) has 1 unexpected value (for the Message field)
|
||||
ctrl.Call(subject, "ActOnTestStructMethod", TestStruct{Number: 123, Message: "no message"}, 15)
|
||||
}, "Unexpected call to", "doesn't match the argument at index 0",
|
||||
"Got: {123 no message}\nWant: is equal to {123 hello}")
|
||||
"Got: {123 no message} (gomock_test.TestStruct)\nWant: is equal to {123 hello %s} (gomock_test.TestStruct)")
|
||||
|
||||
reporter.assertFatal(func() {
|
||||
// the method argument (of TestStruct type) has 2 unexpected values (for both fields)
|
||||
ctrl.Call(subject, "ActOnTestStructMethod", TestStruct{Number: 11, Message: "no message"}, 15)
|
||||
}, "Unexpected call to", "doesn't match the argument at index 0",
|
||||
"Got: {11 no message}\nWant: is equal to {123 hello}")
|
||||
"Got: {11 no message} (gomock_test.TestStruct)\nWant: is equal to {123 hello %s} (gomock_test.TestStruct)")
|
||||
|
||||
reporter.assertFatal(func() {
|
||||
// The expected call wasn't made.
|
||||
|
@ -324,7 +314,7 @@ func TestUnexpectedArgValue_SecondArg(t *testing.T) {
|
|||
reporter.assertFatal(func() {
|
||||
ctrl.Call(subject, "ActOnTestStructMethod", TestStruct{Number: 123, Message: "hello"}, 3)
|
||||
}, "Unexpected call to", "doesn't match the argument at index 1",
|
||||
"Got: 3\nWant: is equal to 15")
|
||||
"Got: 3 (int)\nWant: is equal to 15 (int)")
|
||||
|
||||
reporter.assertFatal(func() {
|
||||
// The expected call wasn't made.
|
||||
|
@ -351,7 +341,7 @@ func TestUnexpectedArgValue_WantFormatter(t *testing.T) {
|
|||
reporter.assertFatal(func() {
|
||||
ctrl.Call(subject, "ActOnTestStructMethod", TestStruct{Number: 123, Message: "hello"}, 3)
|
||||
}, "Unexpected call to", "doesn't match the argument at index 1",
|
||||
"Got: 3\nWant: is equal to fifteen")
|
||||
"Got: 3 (int)\nWant: is equal to fifteen")
|
||||
|
||||
reporter.assertFatal(func() {
|
||||
// The expected call wasn't made.
|
||||
|
@ -411,14 +401,14 @@ func TestMinTimes1(t *testing.T) {
|
|||
})
|
||||
|
||||
// It succeeds if there is one call
|
||||
reporter, ctrl = createFixtures(t)
|
||||
_, ctrl = createFixtures(t)
|
||||
subject = new(Subject)
|
||||
ctrl.RecordCall(subject, "FooMethod", "argument").MinTimes(1)
|
||||
ctrl.Call(subject, "FooMethod", "argument")
|
||||
ctrl.Finish()
|
||||
|
||||
// It succeeds if there are many calls
|
||||
reporter, ctrl = createFixtures(t)
|
||||
_, ctrl = createFixtures(t)
|
||||
subject = new(Subject)
|
||||
ctrl.RecordCall(subject, "FooMethod", "argument").MinTimes(1)
|
||||
for i := 0; i < 100; i++ {
|
||||
|
@ -473,7 +463,7 @@ func TestMinMaxTimes(t *testing.T) {
|
|||
})
|
||||
|
||||
// It succeeds if there is just the right number of calls
|
||||
reporter, ctrl = createFixtures(t)
|
||||
_, ctrl = createFixtures(t)
|
||||
subject = new(Subject)
|
||||
ctrl.RecordCall(subject, "FooMethod", "argument").MaxTimes(2).MinTimes(2)
|
||||
ctrl.Call(subject, "FooMethod", "argument")
|
||||
|
@ -491,7 +481,7 @@ func TestMinMaxTimes(t *testing.T) {
|
|||
})
|
||||
|
||||
// If MinTimes is called after MaxTimes is called with 1, MinTimes takes precedence.
|
||||
reporter, ctrl = createFixtures(t)
|
||||
_, ctrl = createFixtures(t)
|
||||
subject = new(Subject)
|
||||
ctrl.RecordCall(subject, "FooMethod", "argument").MaxTimes(1).MinTimes(2)
|
||||
for i := 0; i < 100; i++ {
|
||||
|
@ -506,7 +496,8 @@ func TestDo(t *testing.T) {
|
|||
|
||||
doCalled := false
|
||||
var argument string
|
||||
ctrl.RecordCall(subject, "FooMethod", "argument").Do(
|
||||
wantArg := "argument"
|
||||
ctrl.RecordCall(subject, "FooMethod", wantArg).Do(
|
||||
func(arg string) {
|
||||
doCalled = true
|
||||
argument = arg
|
||||
|
@ -515,12 +506,12 @@ func TestDo(t *testing.T) {
|
|||
t.Error("Do() callback called too early.")
|
||||
}
|
||||
|
||||
ctrl.Call(subject, "FooMethod", "argument")
|
||||
ctrl.Call(subject, "FooMethod", wantArg)
|
||||
|
||||
if !doCalled {
|
||||
t.Error("Do() callback not called.")
|
||||
}
|
||||
if "argument" != argument {
|
||||
if wantArg != argument {
|
||||
t.Error("Do callback received wrong argument.")
|
||||
}
|
||||
|
||||
|
@ -533,7 +524,8 @@ func TestDoAndReturn(t *testing.T) {
|
|||
|
||||
doCalled := false
|
||||
var argument string
|
||||
ctrl.RecordCall(subject, "FooMethod", "argument").DoAndReturn(
|
||||
wantArg := "argument"
|
||||
ctrl.RecordCall(subject, "FooMethod", wantArg).DoAndReturn(
|
||||
func(arg string) int {
|
||||
doCalled = true
|
||||
argument = arg
|
||||
|
@ -543,12 +535,12 @@ func TestDoAndReturn(t *testing.T) {
|
|||
t.Error("Do() callback called too early.")
|
||||
}
|
||||
|
||||
rets := ctrl.Call(subject, "FooMethod", "argument")
|
||||
rets := ctrl.Call(subject, "FooMethod", wantArg)
|
||||
|
||||
if !doCalled {
|
||||
t.Error("Do() callback not called.")
|
||||
}
|
||||
if "argument" != argument {
|
||||
if wantArg != argument {
|
||||
t.Error("Do callback received wrong argument.")
|
||||
}
|
||||
if len(rets) != 1 {
|
||||
|
@ -569,13 +561,43 @@ func TestSetArgSlice(t *testing.T) {
|
|||
|
||||
var in = []byte{4, 5, 6}
|
||||
var set = []byte{1, 2, 3}
|
||||
ctrl.RecordCall(subject, "SetArgMethod", in, nil).SetArg(0, set)
|
||||
ctrl.Call(subject, "SetArgMethod", in, nil)
|
||||
ctrl.RecordCall(subject, "SetArgMethod", in, nil, nil).SetArg(0, set)
|
||||
ctrl.Call(subject, "SetArgMethod", in, nil, nil)
|
||||
|
||||
if !reflect.DeepEqual(in, set) {
|
||||
t.Error("Expected SetArg() to modify input slice argument")
|
||||
}
|
||||
|
||||
ctrl.RecordCall(subject, "SetArgMethodInterface", in, nil, nil).SetArg(0, set)
|
||||
ctrl.Call(subject, "SetArgMethodInterface", in, nil, nil)
|
||||
|
||||
if !reflect.DeepEqual(in, set) {
|
||||
t.Error("Expected SetArg() to modify input slice argument as interface{}")
|
||||
}
|
||||
|
||||
ctrl.Finish()
|
||||
}
|
||||
|
||||
func TestSetArgMap(t *testing.T) {
|
||||
_, ctrl := createFixtures(t)
|
||||
subject := new(Subject)
|
||||
|
||||
var in = map[interface{}]interface{}{"int": 1, "string": "random string", 1: "1", 0: 0}
|
||||
var set = map[interface{}]interface{}{"int": 2, 1: "2", 2: 100}
|
||||
ctrl.RecordCall(subject, "SetArgMethod", nil, nil, in).SetArg(2, set)
|
||||
ctrl.Call(subject, "SetArgMethod", nil, nil, in)
|
||||
|
||||
if !reflect.DeepEqual(in, set) {
|
||||
t.Error("Expected SetArg() to modify input map argument")
|
||||
}
|
||||
|
||||
ctrl.RecordCall(subject, "SetArgMethodInterface", nil, nil, in).SetArg(2, set)
|
||||
ctrl.Call(subject, "SetArgMethodInterface", nil, nil, in)
|
||||
|
||||
if !reflect.DeepEqual(in, set) {
|
||||
t.Error("Expected SetArg() to modify input map argument as interface{}")
|
||||
}
|
||||
|
||||
ctrl.Finish()
|
||||
}
|
||||
|
||||
|
@ -585,13 +607,19 @@ func TestSetArgPtr(t *testing.T) {
|
|||
|
||||
var in int = 43
|
||||
const set = 42
|
||||
ctrl.RecordCall(subject, "SetArgMethod", nil, &in).SetArg(1, set)
|
||||
ctrl.Call(subject, "SetArgMethod", nil, &in)
|
||||
ctrl.RecordCall(subject, "SetArgMethod", nil, &in, nil).SetArg(1, set)
|
||||
ctrl.Call(subject, "SetArgMethod", nil, &in, nil)
|
||||
|
||||
if in != set {
|
||||
t.Error("Expected SetArg() to modify value pointed to by argument")
|
||||
}
|
||||
|
||||
ctrl.RecordCall(subject, "SetArgMethodInterface", nil, &in, nil).SetArg(1, set)
|
||||
ctrl.Call(subject, "SetArgMethodInterface", nil, &in, nil)
|
||||
|
||||
if in != set {
|
||||
t.Error("Expected SetArg() to modify value pointed to by argument as interface{}")
|
||||
}
|
||||
ctrl.Finish()
|
||||
}
|
||||
|
||||
|
@ -720,7 +748,7 @@ func TestVariadicNoMatch(t *testing.T) {
|
|||
rep.assertFatal(func() {
|
||||
ctrl.Call(s, "VariadicMethod", 1)
|
||||
}, "expected call at", "doesn't match the argument at index 0",
|
||||
"Got: 1\nWant: is equal to 0")
|
||||
"Got: 1 (int)\nWant: is equal to 0 (int)")
|
||||
ctrl.Call(s, "VariadicMethod", 0)
|
||||
ctrl.Finish()
|
||||
}
|
||||
|
@ -1075,3 +1103,112 @@ func TestWithHelper(t *testing.T) {
|
|||
t.Fatal("expected Helper to be invoked")
|
||||
}
|
||||
}
|
||||
|
||||
func (e *ErrorReporter) Cleanup(f func()) {
|
||||
e.t.Helper()
|
||||
e.t.Cleanup(f)
|
||||
}
|
||||
|
||||
func TestMultipleDefers(t *testing.T) {
|
||||
reporter := NewErrorReporter(t)
|
||||
reporter.Cleanup(func() {
|
||||
reporter.assertPass("No errors for multiple calls to Finish")
|
||||
})
|
||||
ctrl := gomock.NewController(reporter)
|
||||
ctrl.Finish()
|
||||
}
|
||||
|
||||
// Equivalent to the TestNoRecordedCallsForAReceiver, but without explicitly
|
||||
// calling Finish.
|
||||
func TestDeferNotNeededFail(t *testing.T) {
|
||||
reporter := NewErrorReporter(t)
|
||||
subject := new(Subject)
|
||||
var ctrl *gomock.Controller
|
||||
reporter.Cleanup(func() {
|
||||
reporter.assertFatal(func() {
|
||||
ctrl.Call(subject, "NotRecordedMethod", "argument")
|
||||
}, "Unexpected call to", "there are no expected calls of the method \"NotRecordedMethod\" for that receiver")
|
||||
})
|
||||
ctrl = gomock.NewController(reporter)
|
||||
}
|
||||
|
||||
func TestDeferNotNeededPass(t *testing.T) {
|
||||
reporter := NewErrorReporter(t)
|
||||
subject := new(Subject)
|
||||
var ctrl *gomock.Controller
|
||||
reporter.Cleanup(func() {
|
||||
reporter.assertPass("Expected method call made.")
|
||||
})
|
||||
ctrl = gomock.NewController(reporter)
|
||||
ctrl.RecordCall(subject, "FooMethod", "argument")
|
||||
ctrl.Call(subject, "FooMethod", "argument")
|
||||
}
|
||||
|
||||
func TestOrderedCallsInCorrect(t *testing.T) {
|
||||
reporter := NewErrorReporter(t)
|
||||
subjectOne := new(Subject)
|
||||
subjectTwo := new(Subject)
|
||||
var ctrl *gomock.Controller
|
||||
reporter.Cleanup(func() {
|
||||
reporter.assertFatal(func() {
|
||||
gomock.InOrder(
|
||||
ctrl.RecordCall(subjectOne, "FooMethod", "1").AnyTimes(),
|
||||
ctrl.RecordCall(subjectTwo, "FooMethod", "2"),
|
||||
ctrl.RecordCall(subjectTwo, "BarMethod", "3"),
|
||||
)
|
||||
ctrl.Call(subjectOne, "FooMethod", "1")
|
||||
// FooMethod(2) should be called before BarMethod(3)
|
||||
ctrl.Call(subjectTwo, "BarMethod", "3")
|
||||
}, "Unexpected call to", "Subject.BarMethod([3])", "doesn't have a prerequisite call satisfied")
|
||||
})
|
||||
ctrl = gomock.NewController(reporter)
|
||||
}
|
||||
|
||||
// Test that calls that are prerequisites to other calls but have maxCalls >
|
||||
// minCalls are removed from the expected call set.
|
||||
func TestOrderedCallsWithPreReqMaxUnbounded(t *testing.T) {
|
||||
reporter := NewErrorReporter(t)
|
||||
subjectOne := new(Subject)
|
||||
subjectTwo := new(Subject)
|
||||
var ctrl *gomock.Controller
|
||||
reporter.Cleanup(func() {
|
||||
reporter.assertFatal(func() {
|
||||
// Initially we should be able to call FooMethod("1") as many times as we
|
||||
// want.
|
||||
ctrl.Call(subjectOne, "FooMethod", "1")
|
||||
ctrl.Call(subjectOne, "FooMethod", "1")
|
||||
|
||||
// But calling something that has it as a prerequite should remove it from
|
||||
// the expected call set. This allows tests to ensure that FooMethod("1") is
|
||||
// *not* called after FooMethod("2").
|
||||
ctrl.Call(subjectTwo, "FooMethod", "2")
|
||||
|
||||
ctrl.Call(subjectOne, "FooMethod", "1")
|
||||
})
|
||||
})
|
||||
ctrl = gomock.NewController(reporter)
|
||||
}
|
||||
|
||||
func TestCallAfterLoopPanic(t *testing.T) {
|
||||
reporter := NewErrorReporter(t)
|
||||
subject := new(Subject)
|
||||
var ctrl *gomock.Controller
|
||||
reporter.Cleanup(func() {
|
||||
firstCall := ctrl.RecordCall(subject, "FooMethod", "1")
|
||||
secondCall := ctrl.RecordCall(subject, "FooMethod", "2")
|
||||
thirdCall := ctrl.RecordCall(subject, "FooMethod", "3")
|
||||
|
||||
gomock.InOrder(firstCall, secondCall, thirdCall)
|
||||
|
||||
defer func() {
|
||||
err := recover()
|
||||
if err == nil {
|
||||
t.Error("Call.After creation of dependency loop did not panic.")
|
||||
}
|
||||
}()
|
||||
|
||||
// This should panic due to dependency loop.
|
||||
firstCall.After(thirdCall)
|
||||
})
|
||||
ctrl = gomock.NewController(reporter)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package gomock is a mock framework for Go.
|
||||
//
|
||||
// Standard usage:
|
||||
// (1) Define an interface that you wish to mock.
|
||||
// type MyInterface interface {
|
||||
// SomeMethod(x int64, y string)
|
||||
// }
|
||||
// (2) Use mockgen to generate a mock from the interface.
|
||||
// (3) Use the mock in a test:
|
||||
// func TestMyThing(t *testing.T) {
|
||||
// mockCtrl := gomock.NewController(t)//
|
||||
// mockObj := something.NewMockMyInterface(mockCtrl)
|
||||
// mockObj.EXPECT().SomeMethod(4, "blah")
|
||||
// // pass mockObj to a real object and play with it.
|
||||
// }
|
||||
//
|
||||
// By default, expected calls are not enforced to run in any particular order.
|
||||
// Call order dependency can be enforced by use of InOrder and/or Call.After.
|
||||
// Call.After can create more varied call order dependencies, but InOrder is
|
||||
// often more convenient.
|
||||
//
|
||||
// The following examples create equivalent call order dependencies.
|
||||
//
|
||||
// Example of using Call.After to chain expected call order:
|
||||
//
|
||||
// firstCall := mockObj.EXPECT().SomeMethod(1, "first")
|
||||
// secondCall := mockObj.EXPECT().SomeMethod(2, "second").After(firstCall)
|
||||
// mockObj.EXPECT().SomeMethod(3, "third").After(secondCall)
|
||||
//
|
||||
// Example of using InOrder to declare expected call order:
|
||||
//
|
||||
// gomock.InOrder(
|
||||
// mockObj.EXPECT().SomeMethod(1, "first"),
|
||||
// mockObj.EXPECT().SomeMethod(2, "second"),
|
||||
// mockObj.EXPECT().SomeMethod(3, "third"),
|
||||
// )
|
||||
//
|
||||
// The standard TestReporter most users will pass to `NewController` is a
|
||||
// `*testing.T` from the context of the test. Note that this will use the
|
||||
// standard `t.Error` and `t.Fatal` methods to report what happened in the test.
|
||||
// In some cases this can leave your testing package in a weird state if global
|
||||
// state is used since `t.Fatal` is like calling panic in the middle of a
|
||||
// function. In these cases it is recommended that you pass in your own
|
||||
// `TestReporter`.
|
||||
package gomock
|
|
@ -1,82 +0,0 @@
|
|||
package gomock_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
mock_sample "github.com/golang/mock/sample/mock_user"
|
||||
)
|
||||
|
||||
func ExampleCall_DoAndReturn_latency() {
|
||||
t := &testing.T{} // provided by test
|
||||
ctrl := gomock.NewController(t)
|
||||
mockIndex := mock_sample.NewMockIndex(ctrl)
|
||||
|
||||
mockIndex.EXPECT().Get(gomock.Any()).DoAndReturn(
|
||||
// signature of anonymous function must have the same number of input and output arguments as the mocked method.
|
||||
func(arg string) string {
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
return "I'm sleepy"
|
||||
},
|
||||
)
|
||||
|
||||
r := mockIndex.Get("foo")
|
||||
fmt.Println(r)
|
||||
// Output: I'm sleepy
|
||||
}
|
||||
|
||||
func ExampleCall_DoAndReturn_captureArguments() {
|
||||
t := &testing.T{} // provided by test
|
||||
ctrl := gomock.NewController(t)
|
||||
mockIndex := mock_sample.NewMockIndex(ctrl)
|
||||
var s string
|
||||
|
||||
mockIndex.EXPECT().Get(gomock.AssignableToTypeOf(s)).DoAndReturn(
|
||||
// signature of anonymous function must have the same number of input and output arguments as the mocked method.
|
||||
func(arg string) interface{} {
|
||||
s = arg
|
||||
return "I'm sleepy"
|
||||
},
|
||||
)
|
||||
|
||||
r := mockIndex.Get("foo")
|
||||
fmt.Printf("%s %s", r, s)
|
||||
// Output: I'm sleepy foo
|
||||
}
|
||||
|
||||
func ExampleCall_Do_latency() {
|
||||
t := &testing.T{} // provided by test
|
||||
ctrl := gomock.NewController(t)
|
||||
mockIndex := mock_sample.NewMockIndex(ctrl)
|
||||
|
||||
mockIndex.EXPECT().Anon(gomock.Any()).Do(
|
||||
// signature of anonymous function must have the same number of input and output arguments as the mocked method.
|
||||
func(_ string) {
|
||||
fmt.Println("sleeping")
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
},
|
||||
)
|
||||
|
||||
mockIndex.Anon("foo")
|
||||
// Output: sleeping
|
||||
}
|
||||
|
||||
func ExampleCall_Do_captureArguments() {
|
||||
t := &testing.T{} // provided by test
|
||||
ctrl := gomock.NewController(t)
|
||||
mockIndex := mock_sample.NewMockIndex(ctrl)
|
||||
|
||||
var s string
|
||||
mockIndex.EXPECT().Anon(gomock.AssignableToTypeOf(s)).Do(
|
||||
// signature of anonymous function must have the same number of input and output arguments as the mocked method.
|
||||
func(arg string) {
|
||||
s = arg
|
||||
},
|
||||
)
|
||||
|
||||
mockIndex.Anon("foo")
|
||||
fmt.Println(s)
|
||||
// Output: foo
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package gomock_test
|
||||
|
||||
//go:generate mockgen -destination mock_test.go -package gomock_test -source example_test.go
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
type Foo interface {
|
||||
Bar(string) string
|
||||
}
|
||||
|
||||
func ExampleCall_DoAndReturn_latency() {
|
||||
t := &testing.T{} // provided by test
|
||||
ctrl := gomock.NewController(t)
|
||||
mockIndex := NewMockFoo(ctrl)
|
||||
|
||||
mockIndex.EXPECT().Bar(gomock.Any()).DoAndReturn(
|
||||
func(arg string) string {
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
return "I'm sleepy"
|
||||
},
|
||||
)
|
||||
|
||||
r := mockIndex.Bar("foo")
|
||||
fmt.Println(r)
|
||||
// Output: I'm sleepy
|
||||
}
|
||||
|
||||
func ExampleCall_DoAndReturn_captureArguments() {
|
||||
t := &testing.T{} // provided by test
|
||||
ctrl := gomock.NewController(t)
|
||||
mockIndex := NewMockFoo(ctrl)
|
||||
var s string
|
||||
|
||||
mockIndex.EXPECT().Bar(gomock.AssignableToTypeOf(s)).DoAndReturn(
|
||||
func(arg string) interface{} {
|
||||
s = arg
|
||||
return "I'm sleepy"
|
||||
},
|
||||
)
|
||||
|
||||
r := mockIndex.Bar("foo")
|
||||
fmt.Printf("%s %s", r, s)
|
||||
// Output: I'm sleepy foo
|
||||
}
|
|
@ -120,7 +120,7 @@ func (e eqMatcher) Matches(x interface{}) bool {
|
|||
}
|
||||
|
||||
func (e eqMatcher) String() string {
|
||||
return fmt.Sprintf("is equal to %v", e.x)
|
||||
return fmt.Sprintf("is equal to %v (%T)", e.x, e.x)
|
||||
}
|
||||
|
||||
type nilMatcher struct{}
|
||||
|
@ -207,6 +207,70 @@ func (m lenMatcher) String() string {
|
|||
return fmt.Sprintf("has length %d", m.i)
|
||||
}
|
||||
|
||||
type inAnyOrderMatcher struct {
|
||||
x interface{}
|
||||
}
|
||||
|
||||
func (m inAnyOrderMatcher) Matches(x interface{}) bool {
|
||||
given, ok := m.prepareValue(x)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
wanted, ok := m.prepareValue(m.x)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
if given.Len() != wanted.Len() {
|
||||
return false
|
||||
}
|
||||
|
||||
usedFromGiven := make([]bool, given.Len())
|
||||
foundFromWanted := make([]bool, wanted.Len())
|
||||
for i := 0; i < wanted.Len(); i++ {
|
||||
wantedMatcher := Eq(wanted.Index(i).Interface())
|
||||
for j := 0; j < given.Len(); j++ {
|
||||
if usedFromGiven[j] {
|
||||
continue
|
||||
}
|
||||
if wantedMatcher.Matches(given.Index(j).Interface()) {
|
||||
foundFromWanted[i] = true
|
||||
usedFromGiven[j] = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
missingFromWanted := 0
|
||||
for _, found := range foundFromWanted {
|
||||
if !found {
|
||||
missingFromWanted++
|
||||
}
|
||||
}
|
||||
extraInGiven := 0
|
||||
for _, used := range usedFromGiven {
|
||||
if !used {
|
||||
extraInGiven++
|
||||
}
|
||||
}
|
||||
|
||||
return extraInGiven == 0 && missingFromWanted == 0
|
||||
}
|
||||
|
||||
func (m inAnyOrderMatcher) prepareValue(x interface{}) (reflect.Value, bool) {
|
||||
xValue := reflect.ValueOf(x)
|
||||
switch xValue.Kind() {
|
||||
case reflect.Slice, reflect.Array:
|
||||
return xValue, true
|
||||
default:
|
||||
return reflect.Value{}, false
|
||||
}
|
||||
}
|
||||
|
||||
func (m inAnyOrderMatcher) String() string {
|
||||
return fmt.Sprintf("has the same elements as %v", m.x)
|
||||
}
|
||||
|
||||
// Constructors
|
||||
|
||||
// All returns a composite Matcher that returns true if and only all of the
|
||||
|
@ -266,3 +330,12 @@ func AssignableToTypeOf(x interface{}) Matcher {
|
|||
}
|
||||
return assignableToTypeOfMatcher{reflect.TypeOf(x)}
|
||||
}
|
||||
|
||||
// InAnyOrder is a Matcher that returns true for collections of the same elements ignoring the order.
|
||||
//
|
||||
// Example usage:
|
||||
// InAnyOrder([]int{1, 2, 3}).Matches([]int{1, 3, 2}) // returns true
|
||||
// InAnyOrder([]int{1, 2, 3}).Matches([]int{1, 2}) // returns false
|
||||
func InAnyOrder(x interface{}) Matcher {
|
||||
return inAnyOrderMatcher{x}
|
||||
}
|
||||
|
|
|
@ -90,6 +90,8 @@ type Dog struct {
|
|||
Breed, Name string
|
||||
}
|
||||
|
||||
type ctxKey struct{}
|
||||
|
||||
// A thorough test of assignableToTypeOfMatcher
|
||||
func TestAssignableToTypeOfMatcher(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
|
@ -137,8 +139,157 @@ func TestAssignableToTypeOfMatcher(t *testing.T) {
|
|||
t.Errorf(`AssignableToTypeOf(context.Context) should not match context.Background()`)
|
||||
}
|
||||
|
||||
ctxWithValue := context.WithValue(context.Background(), "key", "val")
|
||||
ctxWithValue := context.WithValue(context.Background(), ctxKey{}, "val")
|
||||
if match := gomock.AssignableToTypeOf(ctxInterface).Matches(ctxWithValue); !match {
|
||||
t.Errorf(`AssignableToTypeOf(context.Context) should not match ctxWithValue`)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInAnyOrder(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
wanted interface{}
|
||||
given interface{}
|
||||
wantMatch bool
|
||||
}{
|
||||
{
|
||||
name: "match for equal slices",
|
||||
wanted: []int{1, 2, 3},
|
||||
given: []int{1, 2, 3},
|
||||
wantMatch: true,
|
||||
},
|
||||
{
|
||||
name: "match for slices with same elements of different order",
|
||||
wanted: []int{1, 2, 3},
|
||||
given: []int{1, 3, 2},
|
||||
wantMatch: true,
|
||||
},
|
||||
{
|
||||
name: "not match for slices with different elements",
|
||||
wanted: []int{1, 2, 3},
|
||||
given: []int{1, 2, 4},
|
||||
wantMatch: false,
|
||||
},
|
||||
{
|
||||
name: "not match for slices with missing elements",
|
||||
wanted: []int{1, 2, 3},
|
||||
given: []int{1, 2},
|
||||
wantMatch: false,
|
||||
},
|
||||
{
|
||||
name: "not match for slices with extra elements",
|
||||
wanted: []int{1, 2, 3},
|
||||
given: []int{1, 2, 3, 4},
|
||||
wantMatch: false,
|
||||
},
|
||||
{
|
||||
name: "match for empty slices",
|
||||
wanted: []int{},
|
||||
given: []int{},
|
||||
wantMatch: true,
|
||||
},
|
||||
{
|
||||
name: "not match for equal slices of different types",
|
||||
wanted: []float64{1, 2, 3},
|
||||
given: []int{1, 2, 3},
|
||||
wantMatch: false,
|
||||
},
|
||||
{
|
||||
name: "match for equal arrays",
|
||||
wanted: [3]int{1, 2, 3},
|
||||
given: [3]int{1, 2, 3},
|
||||
wantMatch: true,
|
||||
},
|
||||
{
|
||||
name: "match for equal arrays of different order",
|
||||
wanted: [3]int{1, 2, 3},
|
||||
given: [3]int{1, 3, 2},
|
||||
wantMatch: true,
|
||||
},
|
||||
{
|
||||
name: "not match for arrays of different elements",
|
||||
wanted: [3]int{1, 2, 3},
|
||||
given: [3]int{1, 2, 4},
|
||||
wantMatch: false,
|
||||
},
|
||||
{
|
||||
name: "not match for arrays with extra elements",
|
||||
wanted: [3]int{1, 2, 3},
|
||||
given: [4]int{1, 2, 3, 4},
|
||||
wantMatch: false,
|
||||
},
|
||||
{
|
||||
name: "not match for arrays with missing elements",
|
||||
wanted: [3]int{1, 2, 3},
|
||||
given: [2]int{1, 2},
|
||||
wantMatch: false,
|
||||
},
|
||||
{
|
||||
name: "not match for equal strings", // matcher shouldn't treat strings as collections
|
||||
wanted: "123",
|
||||
given: "123",
|
||||
wantMatch: false,
|
||||
},
|
||||
{
|
||||
name: "not match if x type is not iterable",
|
||||
wanted: 123,
|
||||
given: []int{123},
|
||||
wantMatch: false,
|
||||
},
|
||||
{
|
||||
name: "not match if in type is not iterable",
|
||||
wanted: []int{123},
|
||||
given: 123,
|
||||
wantMatch: false,
|
||||
},
|
||||
{
|
||||
name: "not match if both are not iterable",
|
||||
wanted: 123,
|
||||
given: 123,
|
||||
wantMatch: false,
|
||||
},
|
||||
{
|
||||
name: "match for equal slices with unhashable elements",
|
||||
wanted: [][]int{{1}, {1, 2}, {1, 2, 3}},
|
||||
given: [][]int{{1}, {1, 2}, {1, 2, 3}},
|
||||
wantMatch: true,
|
||||
},
|
||||
{
|
||||
name: "match for equal slices with unhashable elements of different order",
|
||||
wanted: [][]int{{1}, {1, 2, 3}, {1, 2}},
|
||||
given: [][]int{{1}, {1, 2}, {1, 2, 3}},
|
||||
wantMatch: true,
|
||||
},
|
||||
{
|
||||
name: "not match for different slices with unhashable elements",
|
||||
wanted: [][]int{{1}, {1, 2, 3}, {1, 2}},
|
||||
given: [][]int{{1}, {1, 2, 4}, {1, 3}},
|
||||
wantMatch: false,
|
||||
},
|
||||
{
|
||||
name: "not match for unhashable missing elements",
|
||||
wanted: [][]int{{1}, {1, 2}, {1, 2, 3}},
|
||||
given: [][]int{{1}, {1, 2}},
|
||||
wantMatch: false,
|
||||
},
|
||||
{
|
||||
name: "not match for unhashable extra elements",
|
||||
wanted: [][]int{{1}, {1, 2}},
|
||||
given: [][]int{{1}, {1, 2}, {1, 2, 3}},
|
||||
wantMatch: false,
|
||||
},
|
||||
{
|
||||
name: "match for equal slices of assignable types",
|
||||
wanted: [][]string{{"a", "b"}},
|
||||
given: []A{{"a", "b"}},
|
||||
wantMatch: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := gomock.InAnyOrder(tt.wanted).Matches(tt.given); got != tt.wantMatch {
|
||||
t.Errorf("got = %v, wantMatch %v", got, tt.wantMatch)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: example_test.go
|
||||
|
||||
// Package gomock_test is a generated GoMock package.
|
||||
package gomock_test
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// MockFoo is a mock of Foo interface.
|
||||
type MockFoo struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockFooMockRecorder
|
||||
}
|
||||
|
||||
// MockFooMockRecorder is the mock recorder for MockFoo.
|
||||
type MockFooMockRecorder struct {
|
||||
mock *MockFoo
|
||||
}
|
||||
|
||||
// NewMockFoo creates a new mock instance.
|
||||
func NewMockFoo(ctrl *gomock.Controller) *MockFoo {
|
||||
mock := &MockFoo{ctrl: ctrl}
|
||||
mock.recorder = &MockFooMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockFoo) EXPECT() *MockFooMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Bar mocks base method.
|
||||
func (m *MockFoo) Bar(arg0 string) string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Bar", arg0)
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Bar indicates an expected call of Bar.
|
||||
func (mr *MockFooMockRecorder) Bar(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Bar", reflect.TypeOf((*MockFoo)(nil).Bar), arg0)
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/mock/mockgen/model"
|
||||
)
|
||||
|
||||
func getTypeSpecTypeParams(ts *ast.TypeSpec) []*ast.Field {
|
||||
if ts == nil || ts.TypeParams == nil {
|
||||
return nil
|
||||
}
|
||||
return ts.TypeParams.List
|
||||
}
|
||||
|
||||
func (p *fileParser) parseGenericType(pkg string, typ ast.Expr, tps map[string]bool) (model.Type, error) {
|
||||
switch v := typ.(type) {
|
||||
case *ast.IndexExpr:
|
||||
m, err := p.parseType(pkg, v.X, tps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nm, ok := m.(*model.NamedType)
|
||||
if !ok {
|
||||
return m, nil
|
||||
}
|
||||
t, err := p.parseType(pkg, v.Index, tps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nm.TypeParams = &model.TypeParametersType{TypeParameters: []model.Type{t}}
|
||||
return m, nil
|
||||
case *ast.IndexListExpr:
|
||||
m, err := p.parseType(pkg, v.X, tps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nm, ok := m.(*model.NamedType)
|
||||
if !ok {
|
||||
return m, nil
|
||||
}
|
||||
var ts []model.Type
|
||||
for _, expr := range v.Indices {
|
||||
t, err := p.parseType(pkg, expr, tps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ts = append(ts, t)
|
||||
}
|
||||
nm.TypeParams = &model.TypeParametersType{TypeParameters: ts}
|
||||
return m, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func getIdentTypeParams(decl interface{}) string {
|
||||
if decl == nil {
|
||||
return ""
|
||||
}
|
||||
ts, ok := decl.(*ast.TypeSpec)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
if ts.TypeParams == nil || len(ts.TypeParams.List) == 0 {
|
||||
return ""
|
||||
}
|
||||
var sb strings.Builder
|
||||
sb.WriteString("[")
|
||||
for i, v := range ts.TypeParams.List {
|
||||
if i != 0 {
|
||||
sb.WriteString(", ")
|
||||
}
|
||||
sb.WriteString(v.Names[0].Name)
|
||||
}
|
||||
sb.WriteString("]")
|
||||
return sb.String()
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2019 Google LLC
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -12,15 +12,25 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build !go1.12
|
||||
//go:build !go1.18
|
||||
// +build !go1.18
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"go/ast"
|
||||
|
||||
"github.com/golang/mock/mockgen/model"
|
||||
)
|
||||
|
||||
func printModuleVersion() {
|
||||
log.Printf("No version information is available for Mockgen compiled with " +
|
||||
"version 1.11")
|
||||
func getTypeSpecTypeParams(ts *ast.TypeSpec) []*ast.Field {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *fileParser) parseGenericType(pkg string, typ ast.Expr, tps map[string]bool) (model.Type, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func getIdentTypeParams(decl interface{}) string {
|
||||
return ""
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package const_length
|
||||
|
||||
import "math"
|
||||
|
||||
//go:generate mockgen -package const_length -destination mock.go -source input.go
|
||||
|
||||
const C = 2
|
||||
|
@ -7,4 +9,8 @@ const C = 2
|
|||
type I interface {
|
||||
Foo() [C]int
|
||||
Bar() [2]int
|
||||
Baz() [math.MaxInt8]int
|
||||
Qux() [1 + 2]int
|
||||
Quux() [(1 + 2)]int
|
||||
Corge() [math.MaxInt8 - 120]int
|
||||
}
|
||||
|
|
|
@ -47,6 +47,34 @@ func (mr *MockIMockRecorder) Bar() *gomock.Call {
|
|||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Bar", reflect.TypeOf((*MockI)(nil).Bar))
|
||||
}
|
||||
|
||||
// Baz mocks base method.
|
||||
func (m *MockI) Baz() [127]int {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Baz")
|
||||
ret0, _ := ret[0].([127]int)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Baz indicates an expected call of Baz.
|
||||
func (mr *MockIMockRecorder) Baz() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Baz", reflect.TypeOf((*MockI)(nil).Baz))
|
||||
}
|
||||
|
||||
// Corge mocks base method.
|
||||
func (m *MockI) Corge() [7]int {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Corge")
|
||||
ret0, _ := ret[0].([7]int)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Corge indicates an expected call of Corge.
|
||||
func (mr *MockIMockRecorder) Corge() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Corge", reflect.TypeOf((*MockI)(nil).Corge))
|
||||
}
|
||||
|
||||
// Foo mocks base method.
|
||||
func (m *MockI) Foo() [2]int {
|
||||
m.ctrl.T.Helper()
|
||||
|
@ -60,3 +88,31 @@ func (mr *MockIMockRecorder) Foo() *gomock.Call {
|
|||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Foo", reflect.TypeOf((*MockI)(nil).Foo))
|
||||
}
|
||||
|
||||
// Quux mocks base method.
|
||||
func (m *MockI) Quux() [3]int {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Quux")
|
||||
ret0, _ := ret[0].([3]int)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Quux indicates an expected call of Quux.
|
||||
func (mr *MockIMockRecorder) Quux() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Quux", reflect.TypeOf((*MockI)(nil).Quux))
|
||||
}
|
||||
|
||||
// Qux mocks base method.
|
||||
func (m *MockI) Qux() [3]int {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Qux")
|
||||
ret0, _ := ret[0].([3]int)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Qux indicates an expected call of Qux.
|
||||
func (mr *MockIMockRecorder) Qux() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Qux", reflect.TypeOf((*MockI)(nil).Qux))
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package generics
|
||||
|
||||
import (
|
||||
"github.com/golang/mock/mockgen/internal/tests/generics/other"
|
||||
"golang.org/x/exp/constraints"
|
||||
)
|
||||
|
||||
//go:generate mockgen --source=external.go --destination=source/mock_external_test.go --package source
|
||||
|
||||
type ExternalConstraint[I constraints.Integer, F constraints.Float] interface {
|
||||
One(string) string
|
||||
Two(I) string
|
||||
Three(I) F
|
||||
Four(I) Foo[I, F]
|
||||
Five(I) Baz[F]
|
||||
Six(I) *Baz[F]
|
||||
Seven(I) other.One[I]
|
||||
Eight(F) other.Two[I, F]
|
||||
Nine(Iface[I])
|
||||
Ten(*I)
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package generics
|
||||
|
||||
import "github.com/golang/mock/mockgen/internal/tests/generics/other"
|
||||
|
||||
//go:generate mockgen --source=generics.go --destination=source/mock_generics_test.go --package source
|
||||
////go:generate mockgen --destination=reflect/mock_test.go --package reflect . Bar,Bar2
|
||||
|
||||
type Bar[T any, R any] interface {
|
||||
One(string) string
|
||||
Two(T) string
|
||||
Three(T) R
|
||||
Four(T) Foo[T, R]
|
||||
Five(T) Baz[T]
|
||||
Six(T) *Baz[T]
|
||||
Seven(T) other.One[T]
|
||||
Eight(T) other.Two[T, R]
|
||||
Nine(Iface[T])
|
||||
Ten(*T)
|
||||
Eleven() (*other.One[T], error)
|
||||
Twelve() (*other.Two[T, R], error)
|
||||
Thirteen() (Baz[StructType], error)
|
||||
Fourteen() (*Foo[StructType, StructType2], error)
|
||||
Fifteen() (Iface[StructType], error)
|
||||
Sixteen() (Baz[other.Three], error)
|
||||
Seventeen() (*Foo[other.Three, other.Four], error)
|
||||
Eighteen() (Iface[*other.Five], error)
|
||||
Nineteen() AliasType
|
||||
}
|
||||
|
||||
type Foo[T any, R any] struct{}
|
||||
|
||||
type Baz[T any] struct{}
|
||||
|
||||
type Iface[T any] interface{}
|
||||
|
||||
type StructType struct{}
|
||||
|
||||
type StructType2 struct{}
|
||||
|
||||
type AliasType Baz[other.Three]
|
|
@ -0,0 +1,10 @@
|
|||
module github.com/golang/mock/mockgen/internal/tests/generics
|
||||
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/golang/mock v1.6.0
|
||||
golang.org/x/exp v0.0.0-20220428152302-39d4317da171
|
||||
)
|
||||
|
||||
replace github.com/golang/mock => ../../../..
|
|
@ -0,0 +1,26 @@
|
|||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/exp v0.0.0-20220428152302-39d4317da171 h1:TfdoLivD44QwvssI9Sv1xwa5DcL5XQr4au4sZ2F2NV4=
|
||||
golang.org/x/exp v0.0.0-20220428152302-39d4317da171/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
|
||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
@ -0,0 +1,11 @@
|
|||
package other
|
||||
|
||||
type One[T any] struct{}
|
||||
|
||||
type Two[T any, R any] struct{}
|
||||
|
||||
type Three struct{}
|
||||
|
||||
type Four struct{}
|
||||
|
||||
type Five interface{}
|
|
@ -0,0 +1,173 @@
|
|||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: external.go
|
||||
|
||||
// Package source is a generated GoMock package.
|
||||
package source
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
generics "github.com/golang/mock/mockgen/internal/tests/generics"
|
||||
other "github.com/golang/mock/mockgen/internal/tests/generics/other"
|
||||
constraints "golang.org/x/exp/constraints"
|
||||
)
|
||||
|
||||
// MockExternalConstraint is a mock of ExternalConstraint interface.
|
||||
type MockExternalConstraint[I constraints.Integer, F constraints.Float] struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockExternalConstraintMockRecorder[I, F]
|
||||
}
|
||||
|
||||
// MockExternalConstraintMockRecorder is the mock recorder for MockExternalConstraint.
|
||||
type MockExternalConstraintMockRecorder[I constraints.Integer, F constraints.Float] struct {
|
||||
mock *MockExternalConstraint[I, F]
|
||||
}
|
||||
|
||||
// NewMockExternalConstraint creates a new mock instance.
|
||||
func NewMockExternalConstraint[I constraints.Integer, F constraints.Float](ctrl *gomock.Controller) *MockExternalConstraint[I, F] {
|
||||
mock := &MockExternalConstraint[I, F]{ctrl: ctrl}
|
||||
mock.recorder = &MockExternalConstraintMockRecorder[I, F]{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockExternalConstraint[I, F]) EXPECT() *MockExternalConstraintMockRecorder[I, F] {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Eight mocks base method.
|
||||
func (m *MockExternalConstraint[I, F]) Eight(arg0 F) other.Two[I, F] {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Eight", arg0)
|
||||
ret0, _ := ret[0].(other.Two[I, F])
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Eight indicates an expected call of Eight.
|
||||
func (mr *MockExternalConstraintMockRecorder[I, F]) Eight(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Eight", reflect.TypeOf((*MockExternalConstraint[I, F])(nil).Eight), arg0)
|
||||
}
|
||||
|
||||
// Five mocks base method.
|
||||
func (m *MockExternalConstraint[I, F]) Five(arg0 I) generics.Baz[F] {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Five", arg0)
|
||||
ret0, _ := ret[0].(generics.Baz[F])
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Five indicates an expected call of Five.
|
||||
func (mr *MockExternalConstraintMockRecorder[I, F]) Five(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Five", reflect.TypeOf((*MockExternalConstraint[I, F])(nil).Five), arg0)
|
||||
}
|
||||
|
||||
// Four mocks base method.
|
||||
func (m *MockExternalConstraint[I, F]) Four(arg0 I) generics.Foo[I, F] {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Four", arg0)
|
||||
ret0, _ := ret[0].(generics.Foo[I, F])
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Four indicates an expected call of Four.
|
||||
func (mr *MockExternalConstraintMockRecorder[I, F]) Four(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Four", reflect.TypeOf((*MockExternalConstraint[I, F])(nil).Four), arg0)
|
||||
}
|
||||
|
||||
// Nine mocks base method.
|
||||
func (m *MockExternalConstraint[I, F]) Nine(arg0 generics.Iface[I]) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "Nine", arg0)
|
||||
}
|
||||
|
||||
// Nine indicates an expected call of Nine.
|
||||
func (mr *MockExternalConstraintMockRecorder[I, F]) Nine(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Nine", reflect.TypeOf((*MockExternalConstraint[I, F])(nil).Nine), arg0)
|
||||
}
|
||||
|
||||
// One mocks base method.
|
||||
func (m *MockExternalConstraint[I, F]) One(arg0 string) string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "One", arg0)
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// One indicates an expected call of One.
|
||||
func (mr *MockExternalConstraintMockRecorder[I, F]) One(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "One", reflect.TypeOf((*MockExternalConstraint[I, F])(nil).One), arg0)
|
||||
}
|
||||
|
||||
// Seven mocks base method.
|
||||
func (m *MockExternalConstraint[I, F]) Seven(arg0 I) other.One[I] {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Seven", arg0)
|
||||
ret0, _ := ret[0].(other.One[I])
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Seven indicates an expected call of Seven.
|
||||
func (mr *MockExternalConstraintMockRecorder[I, F]) Seven(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Seven", reflect.TypeOf((*MockExternalConstraint[I, F])(nil).Seven), arg0)
|
||||
}
|
||||
|
||||
// Six mocks base method.
|
||||
func (m *MockExternalConstraint[I, F]) Six(arg0 I) *generics.Baz[F] {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Six", arg0)
|
||||
ret0, _ := ret[0].(*generics.Baz[F])
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Six indicates an expected call of Six.
|
||||
func (mr *MockExternalConstraintMockRecorder[I, F]) Six(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Six", reflect.TypeOf((*MockExternalConstraint[I, F])(nil).Six), arg0)
|
||||
}
|
||||
|
||||
// Ten mocks base method.
|
||||
func (m *MockExternalConstraint[I, F]) Ten(arg0 *I) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "Ten", arg0)
|
||||
}
|
||||
|
||||
// Ten indicates an expected call of Ten.
|
||||
func (mr *MockExternalConstraintMockRecorder[I, F]) Ten(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Ten", reflect.TypeOf((*MockExternalConstraint[I, F])(nil).Ten), arg0)
|
||||
}
|
||||
|
||||
// Three mocks base method.
|
||||
func (m *MockExternalConstraint[I, F]) Three(arg0 I) F {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Three", arg0)
|
||||
ret0, _ := ret[0].(F)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Three indicates an expected call of Three.
|
||||
func (mr *MockExternalConstraintMockRecorder[I, F]) Three(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Three", reflect.TypeOf((*MockExternalConstraint[I, F])(nil).Three), arg0)
|
||||
}
|
||||
|
||||
// Two mocks base method.
|
||||
func (m *MockExternalConstraint[I, F]) Two(arg0 I) string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Two", arg0)
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Two indicates an expected call of Two.
|
||||
func (mr *MockExternalConstraintMockRecorder[I, F]) Two(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Two", reflect.TypeOf((*MockExternalConstraint[I, F])(nil).Two), arg0)
|
||||
}
|
|
@ -0,0 +1,329 @@
|
|||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: generics.go
|
||||
|
||||
// Package source is a generated GoMock package.
|
||||
package source
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
generics "github.com/golang/mock/mockgen/internal/tests/generics"
|
||||
other "github.com/golang/mock/mockgen/internal/tests/generics/other"
|
||||
)
|
||||
|
||||
// MockBar is a mock of Bar interface.
|
||||
type MockBar[T any, R any] struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockBarMockRecorder[T, R]
|
||||
}
|
||||
|
||||
// MockBarMockRecorder is the mock recorder for MockBar.
|
||||
type MockBarMockRecorder[T any, R any] struct {
|
||||
mock *MockBar[T, R]
|
||||
}
|
||||
|
||||
// NewMockBar creates a new mock instance.
|
||||
func NewMockBar[T any, R any](ctrl *gomock.Controller) *MockBar[T, R] {
|
||||
mock := &MockBar[T, R]{ctrl: ctrl}
|
||||
mock.recorder = &MockBarMockRecorder[T, R]{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockBar[T, R]) EXPECT() *MockBarMockRecorder[T, R] {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// Eight mocks base method.
|
||||
func (m *MockBar[T, R]) Eight(arg0 T) other.Two[T, R] {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Eight", arg0)
|
||||
ret0, _ := ret[0].(other.Two[T, R])
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Eight indicates an expected call of Eight.
|
||||
func (mr *MockBarMockRecorder[T, R]) Eight(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Eight", reflect.TypeOf((*MockBar[T, R])(nil).Eight), arg0)
|
||||
}
|
||||
|
||||
// Eighteen mocks base method.
|
||||
func (m *MockBar[T, R]) Eighteen() (generics.Iface[*other.Five], error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Eighteen")
|
||||
ret0, _ := ret[0].(generics.Iface[*other.Five])
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Eighteen indicates an expected call of Eighteen.
|
||||
func (mr *MockBarMockRecorder[T, R]) Eighteen() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Eighteen", reflect.TypeOf((*MockBar[T, R])(nil).Eighteen))
|
||||
}
|
||||
|
||||
// Eleven mocks base method.
|
||||
func (m *MockBar[T, R]) Eleven() (*other.One[T], error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Eleven")
|
||||
ret0, _ := ret[0].(*other.One[T])
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Eleven indicates an expected call of Eleven.
|
||||
func (mr *MockBarMockRecorder[T, R]) Eleven() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Eleven", reflect.TypeOf((*MockBar[T, R])(nil).Eleven))
|
||||
}
|
||||
|
||||
// Fifteen mocks base method.
|
||||
func (m *MockBar[T, R]) Fifteen() (generics.Iface[generics.StructType], error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Fifteen")
|
||||
ret0, _ := ret[0].(generics.Iface[generics.StructType])
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Fifteen indicates an expected call of Fifteen.
|
||||
func (mr *MockBarMockRecorder[T, R]) Fifteen() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Fifteen", reflect.TypeOf((*MockBar[T, R])(nil).Fifteen))
|
||||
}
|
||||
|
||||
// Five mocks base method.
|
||||
func (m *MockBar[T, R]) Five(arg0 T) generics.Baz[T] {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Five", arg0)
|
||||
ret0, _ := ret[0].(generics.Baz[T])
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Five indicates an expected call of Five.
|
||||
func (mr *MockBarMockRecorder[T, R]) Five(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Five", reflect.TypeOf((*MockBar[T, R])(nil).Five), arg0)
|
||||
}
|
||||
|
||||
// Four mocks base method.
|
||||
func (m *MockBar[T, R]) Four(arg0 T) generics.Foo[T, R] {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Four", arg0)
|
||||
ret0, _ := ret[0].(generics.Foo[T, R])
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Four indicates an expected call of Four.
|
||||
func (mr *MockBarMockRecorder[T, R]) Four(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Four", reflect.TypeOf((*MockBar[T, R])(nil).Four), arg0)
|
||||
}
|
||||
|
||||
// Fourteen mocks base method.
|
||||
func (m *MockBar[T, R]) Fourteen() (*generics.Foo[generics.StructType, generics.StructType2], error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Fourteen")
|
||||
ret0, _ := ret[0].(*generics.Foo[generics.StructType, generics.StructType2])
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Fourteen indicates an expected call of Fourteen.
|
||||
func (mr *MockBarMockRecorder[T, R]) Fourteen() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Fourteen", reflect.TypeOf((*MockBar[T, R])(nil).Fourteen))
|
||||
}
|
||||
|
||||
// Nine mocks base method.
|
||||
func (m *MockBar[T, R]) Nine(arg0 generics.Iface[T]) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "Nine", arg0)
|
||||
}
|
||||
|
||||
// Nine indicates an expected call of Nine.
|
||||
func (mr *MockBarMockRecorder[T, R]) Nine(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Nine", reflect.TypeOf((*MockBar[T, R])(nil).Nine), arg0)
|
||||
}
|
||||
|
||||
// Nineteen mocks base method.
|
||||
func (m *MockBar[T, R]) Nineteen() generics.AliasType {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Nineteen")
|
||||
ret0, _ := ret[0].(generics.AliasType)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Nineteen indicates an expected call of Nineteen.
|
||||
func (mr *MockBarMockRecorder[T, R]) Nineteen() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Nineteen", reflect.TypeOf((*MockBar[T, R])(nil).Nineteen))
|
||||
}
|
||||
|
||||
// One mocks base method.
|
||||
func (m *MockBar[T, R]) One(arg0 string) string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "One", arg0)
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// One indicates an expected call of One.
|
||||
func (mr *MockBarMockRecorder[T, R]) One(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "One", reflect.TypeOf((*MockBar[T, R])(nil).One), arg0)
|
||||
}
|
||||
|
||||
// Seven mocks base method.
|
||||
func (m *MockBar[T, R]) Seven(arg0 T) other.One[T] {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Seven", arg0)
|
||||
ret0, _ := ret[0].(other.One[T])
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Seven indicates an expected call of Seven.
|
||||
func (mr *MockBarMockRecorder[T, R]) Seven(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Seven", reflect.TypeOf((*MockBar[T, R])(nil).Seven), arg0)
|
||||
}
|
||||
|
||||
// Seventeen mocks base method.
|
||||
func (m *MockBar[T, R]) Seventeen() (*generics.Foo[other.Three, other.Four], error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Seventeen")
|
||||
ret0, _ := ret[0].(*generics.Foo[other.Three, other.Four])
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Seventeen indicates an expected call of Seventeen.
|
||||
func (mr *MockBarMockRecorder[T, R]) Seventeen() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Seventeen", reflect.TypeOf((*MockBar[T, R])(nil).Seventeen))
|
||||
}
|
||||
|
||||
// Six mocks base method.
|
||||
func (m *MockBar[T, R]) Six(arg0 T) *generics.Baz[T] {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Six", arg0)
|
||||
ret0, _ := ret[0].(*generics.Baz[T])
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Six indicates an expected call of Six.
|
||||
func (mr *MockBarMockRecorder[T, R]) Six(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Six", reflect.TypeOf((*MockBar[T, R])(nil).Six), arg0)
|
||||
}
|
||||
|
||||
// Sixteen mocks base method.
|
||||
func (m *MockBar[T, R]) Sixteen() (generics.Baz[other.Three], error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Sixteen")
|
||||
ret0, _ := ret[0].(generics.Baz[other.Three])
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Sixteen indicates an expected call of Sixteen.
|
||||
func (mr *MockBarMockRecorder[T, R]) Sixteen() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Sixteen", reflect.TypeOf((*MockBar[T, R])(nil).Sixteen))
|
||||
}
|
||||
|
||||
// Ten mocks base method.
|
||||
func (m *MockBar[T, R]) Ten(arg0 *T) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "Ten", arg0)
|
||||
}
|
||||
|
||||
// Ten indicates an expected call of Ten.
|
||||
func (mr *MockBarMockRecorder[T, R]) Ten(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Ten", reflect.TypeOf((*MockBar[T, R])(nil).Ten), arg0)
|
||||
}
|
||||
|
||||
// Thirteen mocks base method.
|
||||
func (m *MockBar[T, R]) Thirteen() (generics.Baz[generics.StructType], error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Thirteen")
|
||||
ret0, _ := ret[0].(generics.Baz[generics.StructType])
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Thirteen indicates an expected call of Thirteen.
|
||||
func (mr *MockBarMockRecorder[T, R]) Thirteen() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Thirteen", reflect.TypeOf((*MockBar[T, R])(nil).Thirteen))
|
||||
}
|
||||
|
||||
// Three mocks base method.
|
||||
func (m *MockBar[T, R]) Three(arg0 T) R {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Three", arg0)
|
||||
ret0, _ := ret[0].(R)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Three indicates an expected call of Three.
|
||||
func (mr *MockBarMockRecorder[T, R]) Three(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Three", reflect.TypeOf((*MockBar[T, R])(nil).Three), arg0)
|
||||
}
|
||||
|
||||
// Twelve mocks base method.
|
||||
func (m *MockBar[T, R]) Twelve() (*other.Two[T, R], error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Twelve")
|
||||
ret0, _ := ret[0].(*other.Two[T, R])
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Twelve indicates an expected call of Twelve.
|
||||
func (mr *MockBarMockRecorder[T, R]) Twelve() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Twelve", reflect.TypeOf((*MockBar[T, R])(nil).Twelve))
|
||||
}
|
||||
|
||||
// Two mocks base method.
|
||||
func (m *MockBar[T, R]) Two(arg0 T) string {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Two", arg0)
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Two indicates an expected call of Two.
|
||||
func (mr *MockBarMockRecorder[T, R]) Two(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Two", reflect.TypeOf((*MockBar[T, R])(nil).Two), arg0)
|
||||
}
|
||||
|
||||
// MockIface is a mock of Iface interface.
|
||||
type MockIface[T any] struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockIfaceMockRecorder[T]
|
||||
}
|
||||
|
||||
// MockIfaceMockRecorder is the mock recorder for MockIface.
|
||||
type MockIfaceMockRecorder[T any] struct {
|
||||
mock *MockIface[T]
|
||||
}
|
||||
|
||||
// NewMockIface creates a new mock instance.
|
||||
func NewMockIface[T any](ctrl *gomock.Controller) *MockIface[T] {
|
||||
mock := &MockIface[T]{ctrl: ctrl}
|
||||
mock.recorder = &MockIfaceMockRecorder[T]{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockIface[T]) EXPECT() *MockIfaceMockRecorder[T] {
|
||||
return m.recorder
|
||||
}
|
|
@ -28,6 +28,7 @@ type Source interface {
|
|||
ersatz.Embedded
|
||||
faux.Foreign
|
||||
error
|
||||
Foo
|
||||
}
|
||||
|
||||
func CallForeignMethod(s Source) {
|
||||
|
|
|
@ -35,6 +35,20 @@ func (m *MockSource) EXPECT() *MockSourceMockRecorder {
|
|||
return m.recorder
|
||||
}
|
||||
|
||||
// Bar mocks base method.
|
||||
func (m *MockSource) Bar() Baz {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Bar")
|
||||
ret0, _ := ret[0].(Baz)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Bar indicates an expected call of Bar.
|
||||
func (mr *MockSourceMockRecorder) Bar() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Bar", reflect.TypeOf((*MockSource)(nil).Bar))
|
||||
}
|
||||
|
||||
// Error mocks base method.
|
||||
func (m *MockSource) Error() string {
|
||||
m.ctrl.T.Helper()
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package bugreport
|
||||
|
||||
type Foo interface {
|
||||
Bar() Baz
|
||||
}
|
||||
type Baz interface{}
|
|
@ -8,7 +8,7 @@ import (
|
|||
reflect "reflect"
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
mock_in_test_package "github.com/golang/mock/mockgen/internal/tests/mock_in_test_package"
|
||||
users "github.com/golang/mock/mockgen/internal/tests/mock_in_test_package"
|
||||
)
|
||||
|
||||
// MockFinder is a mock of Finder interface.
|
||||
|
@ -35,7 +35,7 @@ func (m *MockFinder) EXPECT() *MockFinderMockRecorder {
|
|||
}
|
||||
|
||||
// Add mocks base method.
|
||||
func (m *MockFinder) Add(u mock_in_test_package.User) {
|
||||
func (m *MockFinder) Add(u users.User) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "Add", u)
|
||||
}
|
||||
|
@ -47,10 +47,10 @@ func (mr *MockFinderMockRecorder) Add(u interface{}) *gomock.Call {
|
|||
}
|
||||
|
||||
// FindUser mocks base method.
|
||||
func (m *MockFinder) FindUser(name string) mock_in_test_package.User {
|
||||
func (m *MockFinder) FindUser(name string) users.User {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "FindUser", name)
|
||||
ret0, _ := ret[0].(mock_in_test_package.User)
|
||||
ret0, _ := ret[0].(users.User)
|
||||
return ret0
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
module github.com/golang/mock/mockgen/internal/tests/overlapping_methods
|
||||
|
||||
go 1.14
|
||||
|
||||
require github.com/golang/mock v1.4.4
|
|
@ -1,8 +0,0 @@
|
|||
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=
|
|
@ -1,5 +1,3 @@
|
|||
// +build go1.14
|
||||
|
||||
package overlap
|
||||
|
||||
type ReadCloser interface {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// +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
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// +build go1.14
|
||||
|
||||
package overlap
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//go:build panictest
|
||||
// +build panictest
|
||||
|
||||
// Copyright 2020 Google LLC
|
||||
|
|
|
@ -2,9 +2,7 @@ package core
|
|||
|
||||
//go:generate mockgen -package core -self_package github.com/golang/mock/mockgen/internal/tests/self_package -destination mock.go github.com/golang/mock/mockgen/internal/tests/self_package Methods
|
||||
|
||||
type Info struct {
|
||||
name string
|
||||
}
|
||||
type Info struct{}
|
||||
|
||||
type Methods interface {
|
||||
getInfo() Info
|
||||
|
|
|
@ -21,6 +21,7 @@ package main
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/token"
|
||||
|
@ -107,19 +108,6 @@ func main() {
|
|||
return
|
||||
}
|
||||
|
||||
dst := os.Stdout
|
||||
if len(*destination) > 0 {
|
||||
if err := os.MkdirAll(filepath.Dir(*destination), os.ModePerm); err != nil {
|
||||
log.Fatalf("Unable to create directory: %v", err)
|
||||
}
|
||||
f, err := os.Create(*destination)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed opening destination file: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
dst = f
|
||||
}
|
||||
|
||||
outputPackageName := *packageOut
|
||||
if outputPackageName == "" {
|
||||
// pkg.Name in reflect mode is the base name of the import path,
|
||||
|
@ -136,12 +124,15 @@ func main() {
|
|||
outputPackagePath := *selfPackage
|
||||
if outputPackagePath == "" && *destination != "" {
|
||||
dstPath, err := filepath.Abs(filepath.Dir(*destination))
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to determine destination file path: %v", err)
|
||||
if err == nil {
|
||||
pkgPath, err := parsePackageImport(dstPath)
|
||||
if err == nil {
|
||||
outputPackagePath = pkgPath
|
||||
} else {
|
||||
log.Println("Unable to infer -self_package from destination file path:", err)
|
||||
}
|
||||
outputPackagePath, err = parsePackageImport(dstPath)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to determine destination file path: %v", err)
|
||||
} else {
|
||||
log.Println("Unable to determine destination file path:", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,7 +159,27 @@ func main() {
|
|||
if err := g.Generate(pkg, outputPackageName, outputPackagePath); err != nil {
|
||||
log.Fatalf("Failed generating mock: %v", err)
|
||||
}
|
||||
if _, err := dst.Write(g.Output()); err != nil {
|
||||
output := g.Output()
|
||||
dst := os.Stdout
|
||||
if len(*destination) > 0 {
|
||||
if err := os.MkdirAll(filepath.Dir(*destination), os.ModePerm); err != nil {
|
||||
log.Fatalf("Unable to create directory: %v", err)
|
||||
}
|
||||
existing, err := ioutil.ReadFile(*destination)
|
||||
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
log.Fatalf("Failed reading pre-exiting destination file: %v", err)
|
||||
}
|
||||
if len(existing) == len(output) && bytes.Compare(existing, output) == 0 {
|
||||
return
|
||||
}
|
||||
f, err := os.Create(*destination)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed opening destination file: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
dst = f
|
||||
}
|
||||
if _, err := dst.Write(output); err != nil {
|
||||
log.Fatalf("Failed writing to destination: %v", err)
|
||||
}
|
||||
}
|
||||
|
@ -233,13 +244,6 @@ func (g *generator) out() {
|
|||
}
|
||||
}
|
||||
|
||||
func removeDot(s string) string {
|
||||
if len(s) > 0 && s[len(s)-1] == '.' {
|
||||
return s[0 : len(s)-1]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// sanitize cleans up a string to make a suitable package name.
|
||||
func sanitize(s string) string {
|
||||
t := ""
|
||||
|
@ -375,32 +379,58 @@ func (g *generator) mockName(typeName string) string {
|
|||
return "Mock" + typeName
|
||||
}
|
||||
|
||||
// formattedTypeParams returns a long and short form of type param info used for
|
||||
// printing. If analyzing a interface with type param [I any, O any] the result
|
||||
// will be:
|
||||
// "[I any, O any]", "[I, O]"
|
||||
func (g *generator) formattedTypeParams(it *model.Interface, pkgOverride string) (string, string) {
|
||||
if len(it.TypeParams) == 0 {
|
||||
return "", ""
|
||||
}
|
||||
var long, short strings.Builder
|
||||
long.WriteString("[")
|
||||
short.WriteString("[")
|
||||
for i, v := range it.TypeParams {
|
||||
if i != 0 {
|
||||
long.WriteString(", ")
|
||||
short.WriteString(", ")
|
||||
}
|
||||
long.WriteString(v.Name)
|
||||
short.WriteString(v.Name)
|
||||
long.WriteString(fmt.Sprintf(" %s", v.Type.String(g.packageMap, pkgOverride)))
|
||||
}
|
||||
long.WriteString("]")
|
||||
short.WriteString("]")
|
||||
return long.String(), short.String()
|
||||
}
|
||||
|
||||
func (g *generator) GenerateMockInterface(intf *model.Interface, outputPackagePath string) error {
|
||||
mockType := g.mockName(intf.Name)
|
||||
longTp, shortTp := g.formattedTypeParams(intf, outputPackagePath)
|
||||
|
||||
g.p("")
|
||||
g.p("// %v is a mock of %v interface.", mockType, intf.Name)
|
||||
g.p("type %v struct {", mockType)
|
||||
g.p("type %v%v struct {", mockType, longTp)
|
||||
g.in()
|
||||
g.p("ctrl *gomock.Controller")
|
||||
g.p("recorder *%vMockRecorder", mockType)
|
||||
g.p("recorder *%vMockRecorder%v", mockType, shortTp)
|
||||
g.out()
|
||||
g.p("}")
|
||||
g.p("")
|
||||
|
||||
g.p("// %vMockRecorder is the mock recorder for %v.", mockType, mockType)
|
||||
g.p("type %vMockRecorder struct {", mockType)
|
||||
g.p("type %vMockRecorder%v struct {", mockType, longTp)
|
||||
g.in()
|
||||
g.p("mock *%v", mockType)
|
||||
g.p("mock *%v%v", mockType, shortTp)
|
||||
g.out()
|
||||
g.p("}")
|
||||
g.p("")
|
||||
|
||||
g.p("// New%v creates a new mock instance.", mockType)
|
||||
g.p("func New%v(ctrl *gomock.Controller) *%v {", mockType, mockType)
|
||||
g.p("func New%v%v(ctrl *gomock.Controller) *%v%v {", mockType, longTp, mockType, shortTp)
|
||||
g.in()
|
||||
g.p("mock := &%v{ctrl: ctrl}", mockType)
|
||||
g.p("mock.recorder = &%vMockRecorder{mock}", mockType)
|
||||
g.p("mock := &%v%v{ctrl: ctrl}", mockType, shortTp)
|
||||
g.p("mock.recorder = &%vMockRecorder%v{mock}", mockType, shortTp)
|
||||
g.p("return mock")
|
||||
g.out()
|
||||
g.p("}")
|
||||
|
@ -408,13 +438,13 @@ func (g *generator) GenerateMockInterface(intf *model.Interface, outputPackagePa
|
|||
|
||||
// XXX: possible name collision here if someone has EXPECT in their interface.
|
||||
g.p("// EXPECT returns an object that allows the caller to indicate expected use.")
|
||||
g.p("func (m *%v) EXPECT() *%vMockRecorder {", mockType, mockType)
|
||||
g.p("func (m *%v%v) EXPECT() *%vMockRecorder%v {", mockType, shortTp, mockType, shortTp)
|
||||
g.in()
|
||||
g.p("return m.recorder")
|
||||
g.out()
|
||||
g.p("}")
|
||||
|
||||
g.GenerateMockMethods(mockType, intf, outputPackagePath)
|
||||
g.GenerateMockMethods(mockType, intf, outputPackagePath, shortTp)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -425,13 +455,13 @@ func (b byMethodName) Len() int { return len(b) }
|
|||
func (b byMethodName) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
|
||||
func (b byMethodName) Less(i, j int) bool { return b[i].Name < b[j].Name }
|
||||
|
||||
func (g *generator) GenerateMockMethods(mockType string, intf *model.Interface, pkgOverride string) {
|
||||
func (g *generator) GenerateMockMethods(mockType string, intf *model.Interface, pkgOverride, shortTp string) {
|
||||
sort.Sort(byMethodName(intf.Methods))
|
||||
for _, m := range intf.Methods {
|
||||
g.p("")
|
||||
_ = g.GenerateMockMethod(mockType, m, pkgOverride)
|
||||
_ = g.GenerateMockMethod(mockType, m, pkgOverride, shortTp)
|
||||
g.p("")
|
||||
_ = g.GenerateMockRecorderMethod(mockType, m)
|
||||
_ = g.GenerateMockRecorderMethod(mockType, m, shortTp)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -450,7 +480,7 @@ func makeArgString(argNames, argTypes []string) string {
|
|||
|
||||
// GenerateMockMethod generates a mock method implementation.
|
||||
// If non-empty, pkgOverride is the package in which unqualified types reside.
|
||||
func (g *generator) GenerateMockMethod(mockType string, m *model.Method, pkgOverride string) error {
|
||||
func (g *generator) GenerateMockMethod(mockType string, m *model.Method, pkgOverride, shortTp string) error {
|
||||
argNames := g.getArgNames(m)
|
||||
argTypes := g.getArgTypes(m, pkgOverride)
|
||||
argString := makeArgString(argNames, argTypes)
|
||||
|
@ -471,7 +501,7 @@ func (g *generator) GenerateMockMethod(mockType string, m *model.Method, pkgOver
|
|||
idRecv := ia.allocateIdentifier("m")
|
||||
|
||||
g.p("// %v mocks base method.", m.Name)
|
||||
g.p("func (%v *%v) %v(%v)%v {", idRecv, mockType, m.Name, argString, retString)
|
||||
g.p("func (%v *%v%v) %v(%v)%v {", idRecv, mockType, shortTp, m.Name, argString, retString)
|
||||
g.in()
|
||||
g.p("%s.ctrl.T.Helper()", idRecv)
|
||||
|
||||
|
@ -515,7 +545,7 @@ func (g *generator) GenerateMockMethod(mockType string, m *model.Method, pkgOver
|
|||
return nil
|
||||
}
|
||||
|
||||
func (g *generator) GenerateMockRecorderMethod(mockType string, m *model.Method) error {
|
||||
func (g *generator) GenerateMockRecorderMethod(mockType string, m *model.Method, shortTp string) error {
|
||||
argNames := g.getArgNames(m)
|
||||
|
||||
var argString string
|
||||
|
@ -539,7 +569,7 @@ func (g *generator) GenerateMockRecorderMethod(mockType string, m *model.Method)
|
|||
idRecv := ia.allocateIdentifier("mr")
|
||||
|
||||
g.p("// %v indicates an expected call of %v.", m.Name, m.Name)
|
||||
g.p("func (%s *%vMockRecorder) %v(%v) *gomock.Call {", idRecv, mockType, m.Name, argString)
|
||||
g.p("func (%s *%vMockRecorder%v) %v(%v) *gomock.Call {", idRecv, mockType, shortTp, m.Name, argString)
|
||||
g.in()
|
||||
g.p("%s.mock.ctrl.T.Helper()", idRecv)
|
||||
|
||||
|
@ -562,7 +592,7 @@ func (g *generator) GenerateMockRecorderMethod(mockType string, m *model.Method)
|
|||
callArgs = ", " + idVarArgs + "..."
|
||||
}
|
||||
}
|
||||
g.p(`return %s.mock.ctrl.RecordCallWithMethodType(%s.mock, "%s", reflect.TypeOf((*%s)(nil).%s)%s)`, idRecv, idRecv, m.Name, mockType, m.Name, callArgs)
|
||||
g.p(`return %s.mock.ctrl.RecordCallWithMethodType(%s.mock, "%s", reflect.TypeOf((*%s%s)(nil).%s)%s)`, idRecv, idRecv, m.Name, mockType, shortTp, m.Name, callArgs)
|
||||
|
||||
g.out()
|
||||
g.p("}")
|
||||
|
|
|
@ -47,6 +47,9 @@ func (pkg *Package) Imports() map[string]bool {
|
|||
im := make(map[string]bool)
|
||||
for _, intf := range pkg.Interfaces {
|
||||
intf.addImports(im)
|
||||
for _, tp := range intf.TypeParams {
|
||||
tp.Type.addImports(im)
|
||||
}
|
||||
}
|
||||
return im
|
||||
}
|
||||
|
@ -55,6 +58,7 @@ func (pkg *Package) Imports() map[string]bool {
|
|||
type Interface struct {
|
||||
Name string
|
||||
Methods []*Method
|
||||
TypeParams []*Parameter
|
||||
}
|
||||
|
||||
// Print writes the interface name and its methods.
|
||||
|
@ -261,24 +265,26 @@ func (mt *MapType) addImports(im map[string]bool) {
|
|||
type NamedType struct {
|
||||
Package string // may be empty
|
||||
Type string
|
||||
TypeParams *TypeParametersType
|
||||
}
|
||||
|
||||
func (nt *NamedType) String(pm map[string]string, pkgOverride string) string {
|
||||
if pkgOverride == nt.Package {
|
||||
return nt.Type
|
||||
return nt.Type + nt.TypeParams.String(pm, pkgOverride)
|
||||
}
|
||||
prefix := pm[nt.Package]
|
||||
if prefix != "" {
|
||||
return prefix + "." + nt.Type
|
||||
return prefix + "." + nt.Type + nt.TypeParams.String(pm, pkgOverride)
|
||||
}
|
||||
|
||||
return nt.Type
|
||||
return nt.Type + nt.TypeParams.String(pm, pkgOverride)
|
||||
}
|
||||
|
||||
func (nt *NamedType) addImports(im map[string]bool) {
|
||||
if nt.Package != "" {
|
||||
im[nt.Package] = true
|
||||
}
|
||||
nt.TypeParams.addImports(im)
|
||||
}
|
||||
|
||||
// PointerType is a pointer to another type.
|
||||
|
@ -297,6 +303,36 @@ type PredeclaredType string
|
|||
func (pt PredeclaredType) String(map[string]string, string) string { return string(pt) }
|
||||
func (pt PredeclaredType) addImports(map[string]bool) {}
|
||||
|
||||
// TypeParametersType contains type paramters for a NamedType.
|
||||
type TypeParametersType struct {
|
||||
TypeParameters []Type
|
||||
}
|
||||
|
||||
func (tp *TypeParametersType) String(pm map[string]string, pkgOverride string) string {
|
||||
if tp == nil || len(tp.TypeParameters) == 0 {
|
||||
return ""
|
||||
}
|
||||
var sb strings.Builder
|
||||
sb.WriteString("[")
|
||||
for i, v := range tp.TypeParameters {
|
||||
if i != 0 {
|
||||
sb.WriteString(", ")
|
||||
}
|
||||
sb.WriteString(v.String(pm, pkgOverride))
|
||||
}
|
||||
sb.WriteString("]")
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func (tp *TypeParametersType) addImports(im map[string]bool) {
|
||||
if tp == nil {
|
||||
return
|
||||
}
|
||||
for _, v := range tp.TypeParameters {
|
||||
v.addImports(im)
|
||||
}
|
||||
}
|
||||
|
||||
// The following code is intended to be called by the program generated by ../reflect.go.
|
||||
|
||||
// InterfaceFromInterfaceType returns a pointer to an interface for the
|
||||
|
|
206
mockgen/parse.go
206
mockgen/parse.go
|
@ -22,8 +22,10 @@ import (
|
|||
"fmt"
|
||||
"go/ast"
|
||||
"go/build"
|
||||
"go/importer"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"path"
|
||||
|
@ -60,8 +62,8 @@ func sourceMode(source string) (*model.Package, error) {
|
|||
p := &fileParser{
|
||||
fileSet: fs,
|
||||
imports: make(map[string]importedPackage),
|
||||
importedInterfaces: make(map[string]map[string]*ast.InterfaceType),
|
||||
auxInterfaces: make(map[string]map[string]*ast.InterfaceType),
|
||||
importedInterfaces: newInterfaceCache(),
|
||||
auxInterfaces: newInterfaceCache(),
|
||||
srcDir: srcDir,
|
||||
}
|
||||
|
||||
|
@ -125,14 +127,47 @@ func (d duplicateImport) Error() string {
|
|||
func (d duplicateImport) Path() string { log.Fatal(d.Error()); return "" }
|
||||
func (d duplicateImport) Parser() *fileParser { log.Fatal(d.Error()); return nil }
|
||||
|
||||
type interfaceCache struct {
|
||||
m map[string]map[string]*namedInterface
|
||||
}
|
||||
|
||||
func newInterfaceCache() *interfaceCache {
|
||||
return &interfaceCache{
|
||||
m: make(map[string]map[string]*namedInterface),
|
||||
}
|
||||
}
|
||||
|
||||
func (i *interfaceCache) Set(pkg, name string, it *namedInterface) {
|
||||
if _, ok := i.m[pkg]; !ok {
|
||||
i.m[pkg] = make(map[string]*namedInterface)
|
||||
}
|
||||
i.m[pkg][name] = it
|
||||
}
|
||||
|
||||
func (i *interfaceCache) Get(pkg, name string) *namedInterface {
|
||||
if _, ok := i.m[pkg]; !ok {
|
||||
return nil
|
||||
}
|
||||
return i.m[pkg][name]
|
||||
}
|
||||
|
||||
func (i *interfaceCache) GetASTIface(pkg, name string) *ast.InterfaceType {
|
||||
if _, ok := i.m[pkg]; !ok {
|
||||
return nil
|
||||
}
|
||||
it, ok := i.m[pkg][name]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return it.it
|
||||
}
|
||||
|
||||
type fileParser struct {
|
||||
fileSet *token.FileSet
|
||||
imports map[string]importedPackage // package name => imported package
|
||||
importedInterfaces map[string]map[string]*ast.InterfaceType // package (or "") => name => interface
|
||||
|
||||
importedInterfaces *interfaceCache
|
||||
auxFiles []*ast.File
|
||||
auxInterfaces map[string]map[string]*ast.InterfaceType // package (or "") => name => interface
|
||||
|
||||
auxInterfaces *interfaceCache
|
||||
srcDir string
|
||||
}
|
||||
|
||||
|
@ -166,11 +201,8 @@ func (p *fileParser) parseAuxFiles(auxFiles string) error {
|
|||
}
|
||||
|
||||
func (p *fileParser) addAuxInterfacesFromFile(pkg string, file *ast.File) {
|
||||
if _, ok := p.auxInterfaces[pkg]; !ok {
|
||||
p.auxInterfaces[pkg] = make(map[string]*ast.InterfaceType)
|
||||
}
|
||||
for ni := range iterInterfaces(file) {
|
||||
p.auxInterfaces[pkg][ni.name.Name] = ni.it
|
||||
p.auxInterfaces.Set(pkg, ni.name.Name, ni)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -197,7 +229,7 @@ func (p *fileParser) parseFile(importPath string, file *ast.File) (*model.Packag
|
|||
|
||||
var is []*model.Interface
|
||||
for ni := range iterInterfaces(file) {
|
||||
i, err := p.parseInterface(ni.name.String(), importPath, ni.it)
|
||||
i, err := p.parseInterface(ni.name.String(), importPath, ni)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -217,8 +249,8 @@ func (p *fileParser) parsePackage(path string) (*fileParser, error) {
|
|||
newP := &fileParser{
|
||||
fileSet: token.NewFileSet(),
|
||||
imports: make(map[string]importedPackage),
|
||||
importedInterfaces: make(map[string]map[string]*ast.InterfaceType),
|
||||
auxInterfaces: make(map[string]map[string]*ast.InterfaceType),
|
||||
importedInterfaces: newInterfaceCache(),
|
||||
auxInterfaces: newInterfaceCache(),
|
||||
srcDir: p.srcDir,
|
||||
}
|
||||
|
||||
|
@ -231,11 +263,8 @@ func (p *fileParser) parsePackage(path string) (*fileParser, error) {
|
|||
|
||||
for _, pkg := range pkgs {
|
||||
file := ast.MergePackageFiles(pkg, ast.FilterFuncDuplicates|ast.FilterUnassociatedComments|ast.FilterImportDuplicates)
|
||||
if _, ok := newP.importedInterfaces[path]; !ok {
|
||||
newP.importedInterfaces[path] = make(map[string]*ast.InterfaceType)
|
||||
}
|
||||
for ni := range iterInterfaces(file) {
|
||||
newP.importedInterfaces[path][ni.name.Name] = ni.it
|
||||
newP.importedInterfaces.Set(path, ni.name.Name, ni)
|
||||
}
|
||||
imports, _ := importsOfFile(file)
|
||||
for pkgName, pkgI := range imports {
|
||||
|
@ -245,9 +274,20 @@ func (p *fileParser) parsePackage(path string) (*fileParser, error) {
|
|||
return newP, nil
|
||||
}
|
||||
|
||||
func (p *fileParser) parseInterface(name, pkg string, it *ast.InterfaceType) (*model.Interface, error) {
|
||||
func (p *fileParser) parseInterface(name, pkg string, it *namedInterface) (*model.Interface, error) {
|
||||
iface := &model.Interface{Name: name}
|
||||
for _, field := range it.Methods.List {
|
||||
tps := make(map[string]bool)
|
||||
|
||||
tp, err := p.parseFieldList(pkg, it.typeParams, tps)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse interface type parameters: %v", name)
|
||||
}
|
||||
iface.TypeParams = tp
|
||||
for _, v := range tp {
|
||||
tps[v.Name] = true
|
||||
}
|
||||
|
||||
for _, field := range it.it.Methods.List {
|
||||
switch v := field.Type.(type) {
|
||||
case *ast.FuncType:
|
||||
if nn := len(field.Names); nn != 1 {
|
||||
|
@ -257,16 +297,16 @@ func (p *fileParser) parseInterface(name, pkg string, it *ast.InterfaceType) (*m
|
|||
Name: field.Names[0].String(),
|
||||
}
|
||||
var err error
|
||||
m.In, m.Variadic, m.Out, err = p.parseFunc(pkg, v)
|
||||
m.In, m.Variadic, m.Out, err = p.parseFunc(pkg, v, tps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
iface.AddMethod(m)
|
||||
case *ast.Ident:
|
||||
// Embedded interface in this package.
|
||||
embeddedIfaceType := p.auxInterfaces[pkg][v.String()]
|
||||
embeddedIfaceType := p.auxInterfaces.Get(pkg, v.String())
|
||||
if embeddedIfaceType == nil {
|
||||
embeddedIfaceType = p.importedInterfaces[pkg][v.String()]
|
||||
embeddedIfaceType = p.importedInterfaces.Get(pkg, v.String())
|
||||
}
|
||||
|
||||
var embeddedIface *model.Interface
|
||||
|
@ -281,7 +321,19 @@ func (p *fileParser) parseInterface(name, pkg string, it *ast.InterfaceType) (*m
|
|||
if v.String() == model.ErrorInterface.Name {
|
||||
embeddedIface = &model.ErrorInterface
|
||||
} else {
|
||||
return nil, p.errorf(v.Pos(), "unknown embedded interface %s", v.String())
|
||||
ip, err := p.parsePackage(pkg)
|
||||
if err != nil {
|
||||
return nil, p.errorf(v.Pos(), "could not parse package %s: %v", pkg, err)
|
||||
}
|
||||
|
||||
if embeddedIfaceType = ip.importedInterfaces.Get(pkg, v.String()); embeddedIfaceType == nil {
|
||||
return nil, p.errorf(v.Pos(), "unknown embedded interface %s.%s", pkg, v.String())
|
||||
}
|
||||
|
||||
embeddedIface, err = ip.parseInterface(v.String(), pkg, embeddedIfaceType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copy the methods.
|
||||
|
@ -298,7 +350,7 @@ func (p *fileParser) parseInterface(name, pkg string, it *ast.InterfaceType) (*m
|
|||
|
||||
var embeddedIface *model.Interface
|
||||
var err error
|
||||
embeddedIfaceType := p.auxInterfaces[filePkg][sel]
|
||||
embeddedIfaceType := p.auxInterfaces.Get(filePkg, sel)
|
||||
if embeddedIfaceType != nil {
|
||||
embeddedIface, err = p.parseInterface(sel, filePkg, embeddedIfaceType)
|
||||
if err != nil {
|
||||
|
@ -318,7 +370,7 @@ func (p *fileParser) parseInterface(name, pkg string, it *ast.InterfaceType) (*m
|
|||
parser: parser,
|
||||
}
|
||||
}
|
||||
if embeddedIfaceType = parser.importedInterfaces[path][sel]; embeddedIfaceType == nil {
|
||||
if embeddedIfaceType = parser.importedInterfaces.Get(path, sel); embeddedIfaceType == nil {
|
||||
return nil, p.errorf(v.Pos(), "unknown embedded interface %s.%s", path, sel)
|
||||
}
|
||||
embeddedIface, err = parser.parseInterface(sel, path, embeddedIfaceType)
|
||||
|
@ -338,26 +390,26 @@ func (p *fileParser) parseInterface(name, pkg string, it *ast.InterfaceType) (*m
|
|||
return iface, nil
|
||||
}
|
||||
|
||||
func (p *fileParser) parseFunc(pkg string, f *ast.FuncType) (inParam []*model.Parameter, variadic *model.Parameter, outParam []*model.Parameter, err error) {
|
||||
func (p *fileParser) parseFunc(pkg string, f *ast.FuncType, tps map[string]bool) (inParam []*model.Parameter, variadic *model.Parameter, outParam []*model.Parameter, err error) {
|
||||
if f.Params != nil {
|
||||
regParams := f.Params.List
|
||||
if isVariadic(f) {
|
||||
n := len(regParams)
|
||||
varParams := regParams[n-1:]
|
||||
regParams = regParams[:n-1]
|
||||
vp, err := p.parseFieldList(pkg, varParams)
|
||||
vp, err := p.parseFieldList(pkg, varParams, tps)
|
||||
if err != nil {
|
||||
return nil, nil, nil, p.errorf(varParams[0].Pos(), "failed parsing variadic argument: %v", err)
|
||||
}
|
||||
variadic = vp[0]
|
||||
}
|
||||
inParam, err = p.parseFieldList(pkg, regParams)
|
||||
inParam, err = p.parseFieldList(pkg, regParams, tps)
|
||||
if err != nil {
|
||||
return nil, nil, nil, p.errorf(f.Pos(), "failed parsing arguments: %v", err)
|
||||
}
|
||||
}
|
||||
if f.Results != nil {
|
||||
outParam, err = p.parseFieldList(pkg, f.Results.List)
|
||||
outParam, err = p.parseFieldList(pkg, f.Results.List, tps)
|
||||
if err != nil {
|
||||
return nil, nil, nil, p.errorf(f.Pos(), "failed parsing returns: %v", err)
|
||||
}
|
||||
|
@ -365,7 +417,7 @@ func (p *fileParser) parseFunc(pkg string, f *ast.FuncType) (inParam []*model.Pa
|
|||
return
|
||||
}
|
||||
|
||||
func (p *fileParser) parseFieldList(pkg string, fields []*ast.Field) ([]*model.Parameter, error) {
|
||||
func (p *fileParser) parseFieldList(pkg string, fields []*ast.Field, tps map[string]bool) ([]*model.Parameter, error) {
|
||||
nf := 0
|
||||
for _, f := range fields {
|
||||
nn := len(f.Names)
|
||||
|
@ -380,7 +432,7 @@ func (p *fileParser) parseFieldList(pkg string, fields []*ast.Field) ([]*model.P
|
|||
ps := make([]*model.Parameter, nf)
|
||||
i := 0 // destination index
|
||||
for _, f := range fields {
|
||||
t, err := p.parseType(pkg, f.Type)
|
||||
t, err := p.parseType(pkg, f.Type, tps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -399,33 +451,27 @@ func (p *fileParser) parseFieldList(pkg string, fields []*ast.Field) ([]*model.P
|
|||
return ps, nil
|
||||
}
|
||||
|
||||
func (p *fileParser) parseType(pkg string, typ ast.Expr) (model.Type, error) {
|
||||
func (p *fileParser) parseType(pkg string, typ ast.Expr, tps map[string]bool) (model.Type, error) {
|
||||
switch v := typ.(type) {
|
||||
case *ast.ArrayType:
|
||||
ln := -1
|
||||
if v.Len != nil {
|
||||
var value string
|
||||
switch val := v.Len.(type) {
|
||||
case (*ast.BasicLit):
|
||||
value = val.Value
|
||||
case (*ast.Ident):
|
||||
// when the length is a const
|
||||
value = val.Obj.Decl.(*ast.ValueSpec).Values[0].(*ast.BasicLit).Value
|
||||
value, err := p.parseArrayLength(v.Len)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
x, err := strconv.Atoi(value)
|
||||
ln, err = strconv.Atoi(value)
|
||||
if err != nil {
|
||||
return nil, p.errorf(v.Len.Pos(), "bad array size: %v", err)
|
||||
}
|
||||
ln = x
|
||||
}
|
||||
t, err := p.parseType(pkg, v.Elt)
|
||||
t, err := p.parseType(pkg, v.Elt, tps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &model.ArrayType{Len: ln, Type: t}, nil
|
||||
case *ast.ChanType:
|
||||
t, err := p.parseType(pkg, v.Value)
|
||||
t, err := p.parseType(pkg, v.Value, tps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -439,15 +485,15 @@ func (p *fileParser) parseType(pkg string, typ ast.Expr) (model.Type, error) {
|
|||
return &model.ChanType{Dir: dir, Type: t}, nil
|
||||
case *ast.Ellipsis:
|
||||
// assume we're parsing a variadic argument
|
||||
return p.parseType(pkg, v.Elt)
|
||||
return p.parseType(pkg, v.Elt, tps)
|
||||
case *ast.FuncType:
|
||||
in, variadic, out, err := p.parseFunc(pkg, v)
|
||||
in, variadic, out, err := p.parseFunc(pkg, v, tps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &model.FuncType{In: in, Out: out, Variadic: variadic}, nil
|
||||
case *ast.Ident:
|
||||
if v.IsExported() {
|
||||
if v.IsExported() && !tps[v.Name] {
|
||||
// `pkg` may be an aliased imported pkg
|
||||
// if so, patch the import w/ the fully qualified import
|
||||
maybeImportedPkg, ok := p.imports[pkg]
|
||||
|
@ -466,11 +512,11 @@ func (p *fileParser) parseType(pkg string, typ ast.Expr) (model.Type, error) {
|
|||
}
|
||||
return model.PredeclaredType("interface{}"), nil
|
||||
case *ast.MapType:
|
||||
key, err := p.parseType(pkg, v.Key)
|
||||
key, err := p.parseType(pkg, v.Key, tps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
value, err := p.parseType(pkg, v.Value)
|
||||
value, err := p.parseType(pkg, v.Value, tps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -483,7 +529,7 @@ func (p *fileParser) parseType(pkg string, typ ast.Expr) (model.Type, error) {
|
|||
}
|
||||
return &model.NamedType{Package: pkg.Path(), Type: v.Sel.String()}, nil
|
||||
case *ast.StarExpr:
|
||||
t, err := p.parseType(pkg, v.X)
|
||||
t, err := p.parseType(pkg, v.X, tps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -494,12 +540,61 @@ func (p *fileParser) parseType(pkg string, typ ast.Expr) (model.Type, error) {
|
|||
}
|
||||
return model.PredeclaredType("struct{}"), nil
|
||||
case *ast.ParenExpr:
|
||||
return p.parseType(pkg, v.X)
|
||||
return p.parseType(pkg, v.X, tps)
|
||||
default:
|
||||
mt, err := p.parseGenericType(pkg, typ, tps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if mt == nil {
|
||||
break
|
||||
}
|
||||
return mt, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("don't know how to parse type %T", typ)
|
||||
}
|
||||
|
||||
func (p *fileParser) parseArrayLength(expr ast.Expr) (string, error) {
|
||||
switch val := expr.(type) {
|
||||
case (*ast.BasicLit):
|
||||
return val.Value, nil
|
||||
case (*ast.Ident):
|
||||
// when the length is a const defined locally
|
||||
return val.Obj.Decl.(*ast.ValueSpec).Values[0].(*ast.BasicLit).Value, nil
|
||||
case (*ast.SelectorExpr):
|
||||
// when the length is a const defined in an external package
|
||||
usedPkg, err := importer.Default().Import(fmt.Sprintf("%s", val.X))
|
||||
if err != nil {
|
||||
return "", p.errorf(expr.Pos(), "unknown package in array length: %v", err)
|
||||
}
|
||||
ev, err := types.Eval(token.NewFileSet(), usedPkg, token.NoPos, val.Sel.Name)
|
||||
if err != nil {
|
||||
return "", p.errorf(expr.Pos(), "unknown constant in array length: %v", err)
|
||||
}
|
||||
return ev.Value.String(), nil
|
||||
case (*ast.ParenExpr):
|
||||
return p.parseArrayLength(val.X)
|
||||
case (*ast.BinaryExpr):
|
||||
x, err := p.parseArrayLength(val.X)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
y, err := p.parseArrayLength(val.Y)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
biExpr := fmt.Sprintf("%s%v%s", x, val.Op, y)
|
||||
tv, err := types.Eval(token.NewFileSet(), nil, token.NoPos, biExpr)
|
||||
if err != nil {
|
||||
return "", p.errorf(expr.Pos(), "invalid expression in array length: %v", err)
|
||||
}
|
||||
return tv.Value.String(), nil
|
||||
default:
|
||||
return "", p.errorf(expr.Pos(), "invalid expression in array length: %v", val)
|
||||
}
|
||||
}
|
||||
|
||||
// importsOfFile returns a map of package name to import path
|
||||
// of the imports in file.
|
||||
func importsOfFile(file *ast.File) (normalImports map[string]importedPackage, dotImports []string) {
|
||||
|
@ -564,11 +659,12 @@ func importsOfFile(file *ast.File) (normalImports map[string]importedPackage, do
|
|||
type namedInterface struct {
|
||||
name *ast.Ident
|
||||
it *ast.InterfaceType
|
||||
typeParams []*ast.Field
|
||||
}
|
||||
|
||||
// Create an iterator over all interfaces in file.
|
||||
func iterInterfaces(file *ast.File) <-chan namedInterface {
|
||||
ch := make(chan namedInterface)
|
||||
func iterInterfaces(file *ast.File) <-chan *namedInterface {
|
||||
ch := make(chan *namedInterface)
|
||||
go func() {
|
||||
for _, decl := range file.Decls {
|
||||
gd, ok := decl.(*ast.GenDecl)
|
||||
|
@ -585,7 +681,7 @@ func iterInterfaces(file *ast.File) <-chan namedInterface {
|
|||
continue
|
||||
}
|
||||
|
||||
ch <- namedInterface{ts.Name, it}
|
||||
ch <- &namedInterface{ts.Name, it, getTypeSpecTypeParams(ts)}
|
||||
}
|
||||
}
|
||||
close(ch)
|
||||
|
@ -628,4 +724,4 @@ func packageNameOfDir(srcDir string) (string, error) {
|
|||
return packageImport, nil
|
||||
}
|
||||
|
||||
var errOutsideGoPath = errors.New("Source directory is outside GOPATH")
|
||||
var errOutsideGoPath = errors.New("source directory is outside GOPATH")
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"testing"
|
||||
|
@ -17,7 +16,7 @@ func TestFileParser_ParseFile(t *testing.T) {
|
|||
p := fileParser{
|
||||
fileSet: fs,
|
||||
imports: make(map[string]importedPackage),
|
||||
importedInterfaces: make(map[string]map[string]*ast.InterfaceType),
|
||||
importedInterfaces: newInterfaceCache(),
|
||||
}
|
||||
|
||||
pkg, err := p.parseFile("", file)
|
||||
|
@ -48,7 +47,7 @@ func TestFileParser_ParsePackage(t *testing.T) {
|
|||
p := fileParser{
|
||||
fileSet: fs,
|
||||
imports: make(map[string]importedPackage),
|
||||
importedInterfaces: make(map[string]map[string]*ast.InterfaceType),
|
||||
importedInterfaces: newInterfaceCache(),
|
||||
}
|
||||
|
||||
newP, err := p.parsePackage("github.com/golang/mock/mockgen/internal/tests/custom_package_name/greeter")
|
||||
|
@ -116,14 +115,19 @@ func Benchmark_parseFile(b *testing.B) {
|
|||
|
||||
func TestParseArrayWithConstLength(t *testing.T) {
|
||||
fs := token.NewFileSet()
|
||||
srcDir := "internal/tests/const_array_length/input.go"
|
||||
|
||||
file, err := parser.ParseFile(fs, "internal/tests/const_array_length/input.go", nil, 0)
|
||||
file, err := parser.ParseFile(fs, srcDir, nil, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
p := fileParser{
|
||||
fileSet: fs,
|
||||
imports: make(map[string]importedPackage),
|
||||
importedInterfaces: newInterfaceCache(),
|
||||
auxInterfaces: newInterfaceCache(),
|
||||
srcDir: srcDir,
|
||||
}
|
||||
|
||||
pkg, err := p.parseFile("", file)
|
||||
|
@ -131,9 +135,11 @@ func TestParseArrayWithConstLength(t *testing.T) {
|
|||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
expect := "[2]int"
|
||||
got := pkg.Interfaces[0].Methods[0].Out[0].Type.String(nil, "")
|
||||
if got != expect {
|
||||
t.Fatalf("got %v; expected %v", got, expect)
|
||||
expects := []string{"[2]int", "[2]int", "[127]int", "[3]int", "[3]int", "[7]int"}
|
||||
for i, e := range expects {
|
||||
got := pkg.Interfaces[0].Methods[i].Out[0].Type.String(nil, "")
|
||||
if got != e {
|
||||
t.Fatalf("got %v; expected %v", got, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,9 @@ import (
|
|||
"bytes"
|
||||
"encoding/gob"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
|
@ -159,11 +161,18 @@ func runInDir(program []byte, dir string) (*model.Package, error) {
|
|||
cmdArgs = append(cmdArgs, "-o", progBinary, progSource)
|
||||
|
||||
// Build the program.
|
||||
buf := bytes.NewBuffer(nil)
|
||||
cmd := exec.Command("go", cmdArgs...)
|
||||
cmd.Dir = tmpDir
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stderr = io.MultiWriter(os.Stderr, buf)
|
||||
if err := cmd.Run(); err != nil {
|
||||
sErr := buf.String()
|
||||
if strings.Contains(sErr, `cannot find package "."`) &&
|
||||
strings.Contains(sErr, "github.com/golang/mock/mockgen/model") {
|
||||
fmt.Fprint(os.Stderr, "Please reference the steps in the README to fix this error:\n\thttps://github.com/golang/mock#reflect-vendoring-error.\n")
|
||||
return nil, err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2019 Google LLC
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -11,9 +11,6 @@
|
|||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
// +build go1.12
|
||||
|
||||
package main
|
||||
|
||||
|
@ -31,5 +28,4 @@ func printModuleVersion() {
|
|||
"GO111MODULE=on when running 'go get' in order to use specific " +
|
||||
"version of the binary.")
|
||||
}
|
||||
|
||||
}
|
|
@ -10,7 +10,7 @@ interface that can be mocked with GoMock. The interesting files are:
|
|||
interfaces from `user.go` are used. This demonstrates how to create mock
|
||||
objects, set up expectations, and so on.
|
||||
|
||||
* `mock_user/mock_user.go`: The generated mock code. See ../gomock/matchers.go
|
||||
* `mock_user_test.go`: The generated mock code. See ../gomock/matchers.go
|
||||
for the `go:generate` command used to generate it.
|
||||
|
||||
To run the test,
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"context"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
|
||||
mock "github.com/golang/mock/sample/concurrent/mock"
|
||||
|
@ -23,10 +24,11 @@ func call(ctx context.Context, m Math) (int, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// testConcurrentFails is expected to fail (and is disabled). It
|
||||
// TestConcurrentFails is expected to fail (and is disabled). It
|
||||
// demonstrates how to use gomock.WithContext to interrupt the test
|
||||
// from a different goroutine.
|
||||
func testConcurrentFails(t *testing.T) {
|
||||
func TestConcurrentFails(t *testing.T) {
|
||||
t.Skip("Test is expected to fail, remove skip to trying running yourself.")
|
||||
ctrl, ctx := gomock.WithContext(context.Background(), t)
|
||||
defer ctrl.Finish()
|
||||
m := mock.NewMockMath(ctrl)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/golang/mock/sample (interfaces: Index,Embed,Embedded)
|
||||
|
||||
// Package mock_sample is a generated GoMock package.
|
||||
package mock_sample
|
||||
// Package user_test is a generated GoMock package.
|
||||
package user_test
|
||||
|
||||
import (
|
||||
bufio "bufio"
|
|
@ -1,11 +1,12 @@
|
|||
// Package user is an example package with an interface.
|
||||
package user
|
||||
|
||||
//go:generate mockgen -destination mock_user/mock_user.go github.com/golang/mock/sample Index,Embed,Embedded
|
||||
//go:generate mockgen -destination mock_user_test.go -package user_test github.com/golang/mock/sample Index,Embed,Embedded
|
||||
|
||||
// Random bunch of imports to test mockgen.
|
||||
import "io"
|
||||
import (
|
||||
"io"
|
||||
|
||||
btz "bytes"
|
||||
"hash"
|
||||
"log"
|
||||
|
@ -14,16 +15,21 @@ import (
|
|||
|
||||
// Two imports with the same base name.
|
||||
t1 "html/template"
|
||||
|
||||
t2 "text/template"
|
||||
|
||||
"github.com/golang/mock/sample/imp1"
|
||||
|
||||
// Dependencies outside the standard library.
|
||||
|
||||
renamed2 "github.com/golang/mock/sample/imp2"
|
||||
|
||||
. "github.com/golang/mock/sample/imp3"
|
||||
|
||||
imp_four "github.com/golang/mock/sample/imp4"
|
||||
)
|
||||
|
||||
// Dependencies outside the standard library.
|
||||
import (
|
||||
"github.com/golang/mock/sample/imp1"
|
||||
renamed2 "github.com/golang/mock/sample/imp2"
|
||||
. "github.com/golang/mock/sample/imp3"
|
||||
"github.com/golang/mock/sample/imp4" // calls itself "imp_four"
|
||||
)
|
||||
// calls itself "imp_four"
|
||||
|
||||
// A bizarre interface to test corner cases in mockgen.
|
||||
// This would normally be in its own file or package,
|
||||
|
|
|
@ -7,14 +7,13 @@ import (
|
|||
"github.com/golang/mock/gomock"
|
||||
user "github.com/golang/mock/sample"
|
||||
"github.com/golang/mock/sample/imp1"
|
||||
mock_user "github.com/golang/mock/sample/mock_user"
|
||||
)
|
||||
|
||||
func TestRemember(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
mockIndex := mock_user.NewMockIndex(ctrl)
|
||||
mockIndex := NewMockIndex(ctrl)
|
||||
mockIndex.EXPECT().Put("a", 1) // literals work
|
||||
mockIndex.EXPECT().Put("b", gomock.Eq(2)) // matchers work too
|
||||
|
||||
|
@ -67,14 +66,14 @@ func TestVariadicFunction(t *testing.T) {
|
|||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
mockIndex := mock_user.NewMockIndex(ctrl)
|
||||
mockIndex := NewMockIndex(ctrl)
|
||||
mockIndex.EXPECT().Ellip("%d", 5, 6, 7, 8).Do(func(format string, nums ...int) {
|
||||
sum := 0
|
||||
for _, value := range nums {
|
||||
sum += value
|
||||
}
|
||||
if sum != 26 {
|
||||
t.Errorf("Expected 7, got %d", sum)
|
||||
t.Errorf("Expected 26, got %d", sum)
|
||||
}
|
||||
})
|
||||
mockIndex.EXPECT().Ellip("%d", gomock.Any()).Do(func(format string, nums ...int) {
|
||||
|
@ -83,7 +82,7 @@ func TestVariadicFunction(t *testing.T) {
|
|||
sum += value
|
||||
}
|
||||
if sum != 10 {
|
||||
t.Errorf("Expected 7, got %d", sum)
|
||||
t.Errorf("Expected 10, got %d", sum)
|
||||
}
|
||||
})
|
||||
mockIndex.EXPECT().Ellip("%d", gomock.Any()).Do(func(format string, nums ...int) {
|
||||
|
@ -125,7 +124,7 @@ func TestGrabPointer(t *testing.T) {
|
|||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
mockIndex := mock_user.NewMockIndex(ctrl)
|
||||
mockIndex := NewMockIndex(ctrl)
|
||||
mockIndex.EXPECT().Ptr(gomock.Any()).SetArg(0, 7) // set first argument to 7
|
||||
|
||||
i := user.GrabPointer(mockIndex)
|
||||
|
@ -138,7 +137,7 @@ func TestEmbeddedInterface(t *testing.T) {
|
|||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
mockEmbed := mock_user.NewMockEmbed(ctrl)
|
||||
mockEmbed := NewMockEmbed(ctrl)
|
||||
mockEmbed.EXPECT().RegularMethod()
|
||||
mockEmbed.EXPECT().EmbeddedMethod()
|
||||
mockEmbed.EXPECT().ForeignEmbeddedMethod()
|
||||
|
@ -155,7 +154,7 @@ func TestExpectTrueNil(t *testing.T) {
|
|||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
mockIndex := mock_user.NewMockIndex(ctrl)
|
||||
mockIndex := NewMockIndex(ctrl)
|
||||
mockIndex.EXPECT().Ptr(nil) // this nil is a nil interface{}
|
||||
mockIndex.Ptr(nil) // this nil is a nil *int
|
||||
}
|
||||
|
@ -165,12 +164,11 @@ func TestDoAndReturnSignature(t *testing.T) {
|
|||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
mockIndex := mock_user.NewMockIndex(ctrl)
|
||||
mockIndex := NewMockIndex(ctrl)
|
||||
|
||||
mockIndex.EXPECT().Slice(gomock.Any(), gomock.Any()).DoAndReturn(
|
||||
func(_ []int, _ []byte) {
|
||||
return
|
||||
})
|
||||
func(_ []int, _ []byte) {},
|
||||
)
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
|
@ -185,7 +183,7 @@ func TestDoAndReturnSignature(t *testing.T) {
|
|||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
mockIndex := mock_user.NewMockIndex(ctrl)
|
||||
mockIndex := NewMockIndex(ctrl)
|
||||
|
||||
mockIndex.EXPECT().Slice(gomock.Any(), gomock.Any()).DoAndReturn(
|
||||
func(_ []int, _ []byte) bool {
|
||||
|
|
Загрузка…
Ссылка в новой задаче