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

record invocation arguments in generated code #702

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f0fd852
Update README
sywhang May 17, 2023
fad7970
Merge pull request #1 from sywhang/update-readme-contributing
linzhp May 17, 2023
cbc27b5
Add maintainers file (#2)
sywhang May 18, 2023
0cbdb43
Change import path (#3)
sywhang May 18, 2023
634c162
Run CI on Go 1.19 and 1.20 (#6)
sywhang Jun 11, 2023
b6bd955
go mod tidy (#7)
sywhang Jun 11, 2023
ce92d72
Update README (#8)
sywhang Jun 27, 2023
03f009e
go fmt with Go 1.20 (#16)
shogo82148 Jun 29, 2023
88ecd8e
go mod edit -go 1.19 and fix import path (#15)
shogo82148 Jun 29, 2023
2b19137
Update Github actions (#19)
sywhang Jun 29, 2023
c1ed26f
Release v0.1.0 (#20)
sywhang Jun 29, 2023
e86b1bf
Allow checking whether all expectations have been met (#21)
FlorianLoch Jun 30, 2023
fcef047
Add ControllerOption (#24)
sywhang Jul 1, 2023
fcb6d39
Update installation instructions in README.md (#26)
SellJamHere Jul 5, 2023
7e5211a
Fix Go reference URL in README (#25)
maciejaszek Jul 5, 2023
82f990d
Implement OverridableController to allow for mock overrides (#22)
styeung Jul 5, 2023
c3c5278
Update README (#27)
sywhang Jul 5, 2023
b9b5dc7
support type-safe return values (#11)
tra4less Jul 6, 2023
bb5901f
Release v0.2.0 (#28)
sywhang Jul 6, 2023
dac4550
Back to development (#29)
sywhang Jul 6, 2023
0181604
support embedded generic interfaces (#13)
tra4less Jul 11, 2023
03b6973
Add -write_source_comment flag to toggle whether to emit source file/…
utgwkk Jul 11, 2023
aa0d61f
record invocation arguments in generated code
kucherenkovova Jul 12, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 12 additions & 13 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -1,27 +1,32 @@
name: Run tests
on:
push:
branches: [main]
branches: ['*']
pull_request:
branches: [main]
branches: ['*']

permissions:
contents: read

env:
GO111MODULE: on

jobs:
test:
strategy:
matrix:
go-version: [1.15.x, 1.18.x]
go-version: [1.19.x, 1.20.x]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:

- name: Install Go
uses: actions/setup-go@v2
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go-version }}

- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: Vet and build
run: |
Expand All @@ -30,23 +35,17 @@ jobs:

- name: Install mockgen
run: |
go install github.com/golang/mock/mockgen
go install go.uber.org/mock/mockgen

- name: Run test script
run: |
./ci/test.sh
./ci/check_panic_handling.sh

- name: Run Go tests all
if: ${{ startsWith(matrix.go-version, '1.18') }}
- name: Run Tests
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 ./...
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Changelog
All notable changes to this project will be documented in this file.

This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## Unreleased
- No changes yet.

## 0.2.0 (06 Jul 2023)
### Added
- `Controller.Satisfied` that lets you check whether all expected calls
bound to a Controller have been satisfied.
- `NewController` now takes optional `ControllerOption` parameter.
- `WithOverridableExpectations` is a `ControllerOption` that configures
Controller to override existing expectations upon a new EXPECT().
- `-typed` flag for generating type-safe methods in the generated mock.

## 0.1.0 (29 Jun 2023)

This is a minor version that mirrors the original golang/mock
project that this project originates from.

Any users on golang/mock project should be able to migrate to
this project as-is, and expect exact same set of features (apart
from supported Go versions. See [README](README.md#supported-go-versions)
for more details.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ First off, thank you for taking an interest to contribute to this project!

## Opening issues

When opening a [new issue](https://github.com/golang/mock/issues/new/choose)
When opening a [new issue](https://github.com/uber/mock/issues/new/choose)
please:

1. Make sure there are not other open/closed issues asking/reporting/requesting
Expand Down
5 changes: 5 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# This is the current list of maintainers to Uber's fork of gomock repository.

Sung Yoon Whang <sungyoon@uber.com>
Ryan Hang <rhang@uber.com>
Zhongpeng Lin <zplin@uber.com>
62 changes: 20 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,25 @@ gomock is a mocking framework for the [Go programming language][golang]. It
integrates well with Go's built-in `testing` package, but can be used in other
contexts too.

## Installation

Once you have [installed Go][golang-install], install the `mockgen` tool.
This project originates from Google's `golang/mock` repo. Unfortunately Google
no longer maintains this project, and given the heavy usage of gomock project
within Uber, we've decided to fork and maintain this going forward at Uber.

**Note**: If you have not done so already be sure to add `$GOPATH/bin` to your
`PATH`.
Contributions are welcome in the form of GitHub issue or PR!

To get the latest released version use:
## Supported Go Versions

### Go version < 1.16
go.uber.org/mock supports all Go versions supported by the official
[Go Release Policy](https://go.dev/doc/devel/release#policy). That is,
the two most recent releases of Go.

```bash
GO111MODULE=on go get github.com/golang/mock/mockgen@v1.6.0
```
## Installation

### Go 1.16+
Install the `mockgen` tool.

```bash
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. You should try to keep the library in sync with
the version of mockgen used to generate your mocks.
go install go.uber.org/mock/mockgen@latest
```

## Running mockgen

Expand Down Expand Up @@ -118,6 +113,10 @@ It supports the following flags:

- `-write_package_comment`: Writes package documentation comment (godoc) if true. (default true)

- `-write_source_comment`: Writes original file (source mode) or interface names (reflect mode) comment if true. (default true)

- `-typed`: Generate Type-safe 'Return', 'Do', 'DoAndReturn' function. (default false)

For an example of the use of `mockgen`, see the `sample/` directory. In simple
cases, you will need only the `-source` flag.

Expand Down Expand Up @@ -250,28 +249,7 @@ If the received value is `3`, then it will be printed as `03`.

[golang]: http://golang.org/
[golang-install]: http://golang.org/doc/install.html#releases
[gomock-reference]: https://pkg.go.dev/github.com/golang/mock/gomock
[ci-badge]: https://github.com/golang/mock/actions/workflows/test.yaml/badge.svg
[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).
[ci-badge]: https://github.com/uber/mock/actions/workflows/test.yaml/badge.svg
[ci-runs]: https://github.com/uber/mock/actions
[reference-badge]: https://pkg.go.dev/badge/go.uber.org/mock.svg
[reference]: https://pkg.go.dev/go.uber.org/mock
13 changes: 9 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
module github.com/golang/mock
module go.uber.org/mock

go 1.19

require (
golang.org/x/mod v0.5.1
golang.org/x/tools v0.1.8
golang.org/x/mod v0.11.0
golang.org/x/tools v0.2.0
)

go 1.15
require (
github.com/yuin/goldmark v1.4.13 // indirect
golang.org/x/sys v0.1.0 // indirect
)
37 changes: 8 additions & 29 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,29 +1,8 @@
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/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-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 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.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 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=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
55 changes: 53 additions & 2 deletions gomock/callset.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,19 @@ import (
"bytes"
"errors"
"fmt"
"sync"
)

// callSet represents a set of expected calls, indexed by receiver and method
// name.
type callSet struct {
// Calls that are still expected.
expected map[callSetKey][]*Call
expected map[callSetKey][]*Call
expectedMu *sync.Mutex
// Calls that have been exhausted.
exhausted map[callSetKey][]*Call
// when set to true, existing call expectations are overridden when new call expectations are made
allowOverride bool
}

// callSetKey is the key in the maps in callSet
Expand All @@ -36,22 +40,47 @@ type callSetKey struct {
}

func newCallSet() *callSet {
return &callSet{make(map[callSetKey][]*Call), make(map[callSetKey][]*Call)}
return &callSet{
expected: make(map[callSetKey][]*Call),
expectedMu: &sync.Mutex{},
exhausted: make(map[callSetKey][]*Call),
}
}

func newOverridableCallSet() *callSet {
return &callSet{
expected: make(map[callSetKey][]*Call),
expectedMu: &sync.Mutex{},
exhausted: make(map[callSetKey][]*Call),
allowOverride: true,
}
}

// Add adds a new expected call.
func (cs callSet) Add(call *Call) {
key := callSetKey{call.receiver, call.method}

cs.expectedMu.Lock()
defer cs.expectedMu.Unlock()

m := cs.expected
if call.exhausted() {
m = cs.exhausted
}
if cs.allowOverride {
m[key] = make([]*Call, 0)
}

m[key] = append(m[key], call)
}

// Remove removes an expected call.
func (cs callSet) Remove(call *Call) {
key := callSetKey{call.receiver, call.method}

cs.expectedMu.Lock()
defer cs.expectedMu.Unlock()

calls := cs.expected[key]
for i, c := range calls {
if c == call {
Expand All @@ -67,6 +96,9 @@ func (cs callSet) Remove(call *Call) {
func (cs callSet) FindMatch(receiver interface{}, method string, args []interface{}) (*Call, error) {
key := callSetKey{receiver, method}

cs.expectedMu.Lock()
defer cs.expectedMu.Unlock()

// Search through the expected calls.
expected := cs.expected[key]
var callsErrors bytes.Buffer
Expand Down Expand Up @@ -101,6 +133,9 @@ func (cs callSet) FindMatch(receiver interface{}, method string, args []interfac

// Failures returns the calls that are not satisfied.
func (cs callSet) Failures() []*Call {
cs.expectedMu.Lock()
defer cs.expectedMu.Unlock()

failures := make([]*Call, 0, len(cs.expected))
for _, calls := range cs.expected {
for _, call := range calls {
Expand All @@ -111,3 +146,19 @@ func (cs callSet) Failures() []*Call {
}
return failures
}

// Satisfied returns true in case all expected calls in this callSet are satisfied.
func (cs callSet) Satisfied() bool {
cs.expectedMu.Lock()
defer cs.expectedMu.Unlock()

for _, calls := range cs.expected {
for _, call := range calls {
if !call.satisfied() {
return false
}
}
}

return true
}
20 changes: 19 additions & 1 deletion gomock/callset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,24 @@ func TestCallSetAdd(t *testing.T) {
}
}

func TestCallSetAdd_WhenOverridable_ClearsPreviousExpectedAndExhausted(t *testing.T) {
method := "TestMethod"
var receiver interface{} = "TestReceiver"
cs := newOverridableCallSet()

cs.Add(newCall(t, receiver, method, reflect.TypeOf(receiverType{}.Func)))
numExpectedCalls := len(cs.expected[callSetKey{receiver, method}])
if numExpectedCalls != 1 {
t.Fatalf("Expected 1 expected call in callset, got %d", numExpectedCalls)
}

cs.Add(newCall(t, receiver, method, reflect.TypeOf(receiverType{}.Func)))
newNumExpectedCalls := len(cs.expected[callSetKey{receiver, method}])
if newNumExpectedCalls != 1 {
t.Fatalf("Expected 1 expected call in callset, got %d", newNumExpectedCalls)
}
}

func TestCallSetRemove(t *testing.T) {
method := "TestMethod"
var receiver interface{} = "TestReceiver"
Expand Down Expand Up @@ -77,7 +95,7 @@ func TestCallSetRemove(t *testing.T) {

func TestCallSetFindMatch(t *testing.T) {
t.Run("call is exhausted", func(t *testing.T) {
cs := callSet{}
cs := newCallSet()
var receiver interface{} = "TestReceiver"
method := "TestMethod"
args := []interface{}{}
Expand Down
Loading