Skip to content

Commit 07347c1

Browse files
committed
Set no global variables
gock sets http.DefaultTransport, which can cause data races with other code that may be reading it. gock uses a mutex when setting the transport, but packages that don't know about gock aren't using the mutex, so races are still possible. By creating a Gock struct and moving global variables to it instead, gock no longer mutates any globals, and multiple Gocks can be used simultaneously, allowing for parallel testing with gock.
1 parent 666a6e9 commit 07347c1

File tree

43 files changed

+974
-659
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+974
-659
lines changed

_examples/add_matchers/matchers.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,19 @@ import (
88
)
99

1010
func main() {
11-
defer gock.Off()
11+
g := gock.NewGock()
12+
c := &http.Client{}
13+
g.InterceptClient(c)
14+
defer g.Off()
1215

13-
gock.New("http://httpbin.org").
16+
g.New("http://httpbin.org").
1417
Get("/").
1518
AddMatcher(func(req *http.Request, ereq *gock.Request) (bool, error) { return req.URL.Scheme == "http", nil }).
1619
AddMatcher(func(req *http.Request, ereq *gock.Request) (bool, error) { return req.Method == ereq.Method, nil }).
1720
Reply(204).
1821
SetHeader("Server", "gock")
1922

20-
res, err := http.Get("http://httpbin.org/get")
23+
res, err := c.Get("http://httpbin.org/get")
2124
if err != nil {
2225
fmt.Errorf("Error: %s", err)
2326
}

_examples/basic/basic_test.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,32 @@
11
package test
22

33
import (
4-
"github.com/nbio/st"
5-
"github.com/h2non/gock"
64
"io/ioutil"
75
"net/http"
86
"testing"
7+
8+
"github.com/h2non/gock"
9+
"github.com/nbio/st"
910
)
1011

1112
func TestSimple(t *testing.T) {
12-
defer gock.Off()
13+
g := gock.NewGock()
14+
c := &http.Client{}
15+
g.InterceptClient(c)
16+
defer g.Off()
1317

14-
gock.New("http://foo.com").
18+
g.New("http://foo.com").
1519
Get("/bar").
1620
Reply(200).
1721
JSON(map[string]string{"foo": "bar"})
1822

19-
res, err := http.Get("http://foo.com/bar")
23+
res, err := c.Get("http://foo.com/bar")
2024
st.Expect(t, err, nil)
2125
st.Expect(t, res.StatusCode, 200)
2226

2327
body, _ := ioutil.ReadAll(res.Body)
2428
st.Expect(t, string(body)[:13], `{"foo":"bar"}`)
2529

2630
// Verify that we don't have pending mocks
27-
st.Expect(t, gock.IsDone(), true)
31+
st.Expect(t, g.IsDone(), true)
2832
}

_examples/body_file/file_test.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,29 @@ package test
22

33
import (
44
"bytes"
5-
"github.com/nbio/st"
6-
"github.com/h2non/gock"
75
"io/ioutil"
86
"net/http"
97
"testing"
8+
9+
"github.com/h2non/gock"
10+
"github.com/nbio/st"
1011
)
1112

1213
func TestMockBodyFile(t *testing.T) {
13-
defer gock.Off()
14+
g := gock.NewGock()
15+
c := &http.Client{}
16+
g.InterceptClient(c)
17+
defer g.Off()
1418

15-
gock.New("http://foo.com").
19+
g.New("http://foo.com").
1620
Post("/bar").
1721
MatchType("json").
1822
File("data.json").
1923
Reply(201).
2024
File("response.json")
2125

2226
body := bytes.NewBuffer([]byte(`{"foo":"bar"}`))
23-
res, err := http.Post("http://foo.com/bar", "application/json", body)
27+
res, err := c.Post("http://foo.com/bar", "application/json", body)
2428
st.Expect(t, err, nil)
2529
st.Expect(t, res.StatusCode, 201)
2630

_examples/body_match/body_test.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,29 @@ package test
22

33
import (
44
"bytes"
5-
"github.com/nbio/st"
6-
"github.com/h2non/gock"
75
"io/ioutil"
86
"net/http"
97
"testing"
8+
9+
"github.com/h2non/gock"
10+
"github.com/nbio/st"
1011
)
1112

1213
func TestMockSimple(t *testing.T) {
13-
defer gock.Off()
14+
g := gock.NewGock()
15+
c := &http.Client{}
16+
g.InterceptClient(c)
17+
defer g.Off()
1418

15-
gock.New("http://foo.com").
19+
g.New("http://foo.com").
1620
Post("/bar").
1721
MatchType("json").
1822
JSON(map[string]string{"foo": "bar"}).
1923
Reply(201).
2024
JSON(map[string]string{"bar": "foo"})
2125

2226
body := bytes.NewBuffer([]byte(`{"foo":"bar"}`))
23-
res, err := http.Post("http://foo.com/bar", "application/json", body)
27+
res, err := c.Post("http://foo.com/bar", "application/json", body)
2428
st.Expect(t, err, nil)
2529
st.Expect(t, res.StatusCode, 201)
2630

_examples/cannot_match/cannot_match.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@ import (
88
)
99

1010
func main() {
11+
g := gock.NewGock()
12+
c := &http.Client{}
13+
g.InterceptClient(c)
1114
// gock enabled but cannot match any mock
12-
gock.New("http://httpbin.org").
15+
g.New("http://httpbin.org").
1316
Get("/foo").
1417
Reply(201).
1518
SetHeader("Server", "gock")
1619

17-
_, err := http.Get("http://httpbin.org/bar")
20+
_, err := c.Get("http://httpbin.org/bar")
1821
if err != nil {
1922
fmt.Printf("Error: %s\n", err)
2023
}

_examples/clean/clean.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,28 @@ package main
22

33
import (
44
"fmt"
5-
"github.com/h2non/gock"
65
"net/http"
6+
7+
"github.com/h2non/gock"
78
)
89

910
func main() {
10-
defer gock.Disable()
11-
defer gock.Flush() // Flush all the registered mocks, including the pending ones.
12-
defer gock.Clean() // Clean all the finished mocks, but keeping the pending ones.
11+
g := gock.NewGock()
12+
c := &http.Client{}
13+
g.InterceptClient(c)
14+
defer g.Disable()
15+
defer g.Flush() // Flush all the registered mocks, including the pending ones.
16+
defer g.Clean() // Clean all the finished mocks, but keeping the pending ones.
1317
// defer gock.Off() -> Or you can simply call Off() method
1418

15-
gock.New("http://httpbin.org").
19+
g.New("http://httpbin.org").
1620
Get("/get").
1721
Filter(func(req *http.Request) bool { return req.URL.Host == "httpbin.org" }).
1822
Filter(func(req *http.Request) bool { return req.URL.Path == "/get" }).
1923
Reply(204).
2024
SetHeader("Server", "gock")
2125

22-
res, err := http.Get("http://httpbin.org/get")
26+
res, err := c.Get("http://httpbin.org/get")
2327
if err != nil {
2428
fmt.Errorf("Error: %s", err)
2529
}

_examples/compressed_body/compression_test.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,21 @@ package test
33
import (
44
"bytes"
55
"compress/gzip"
6-
"github.com/nbio/st"
7-
"github.com/h2non/gock"
86
"io/ioutil"
97
"net/http"
108
"testing"
9+
10+
"github.com/h2non/gock"
11+
"github.com/nbio/st"
1112
)
1213

1314
func TestMockSimple(t *testing.T) {
14-
defer gock.Off()
15+
g := gock.NewGock()
16+
c := &http.Client{}
17+
g.InterceptClient(c)
18+
defer g.Off()
1519

16-
gock.New("http://foo.com").
20+
g.New("http://foo.com").
1721
Post("/bar").
1822
MatchType("json").
1923
Compression("gzip").
@@ -29,7 +33,7 @@ func TestMockSimple(t *testing.T) {
2933
st.Expect(t, err, nil)
3034
req.Header.Set("Content-Encoding", "gzip")
3135
req.Header.Set("Content-Type", "application/json")
32-
res, err := http.DefaultClient.Do(req)
36+
res, err := c.Do(req)
3337
st.Expect(t, err, nil)
3438
st.Expect(t, res.StatusCode, 201)
3539

_examples/custom_client/client_test.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,25 @@
11
package test
22

33
import (
4-
"github.com/nbio/st"
5-
"github.com/h2non/gock"
64
"io/ioutil"
75
"net/http"
86
"testing"
7+
8+
"github.com/h2non/gock"
9+
"github.com/nbio/st"
910
)
1011

1112
func TestClient(t *testing.T) {
12-
defer gock.Off()
13+
g := gock.NewGock()
14+
defer g.Off()
1315

14-
gock.New("http://foo.com").
16+
g.New("http://foo.com").
1517
Reply(200).
1618
BodyString("foo foo")
1719

1820
req, err := http.NewRequest("GET", "http://foo.com", nil)
1921
client := &http.Client{Transport: &http.Transport{}}
20-
gock.InterceptClient(client)
22+
g.InterceptClient(client)
2123

2224
res, err := client.Do(req)
2325
st.Expect(t, err, nil)

_examples/custom_matcher/matcher.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,33 @@ package main
22

33
import (
44
"fmt"
5-
"github.com/h2non/gock"
65
"net/http"
6+
7+
"github.com/h2non/gock"
78
)
89

910
func main() {
10-
defer gock.Off()
11+
g := gock.NewGock()
12+
c := &http.Client{}
13+
g.InterceptClient(c)
14+
defer g.Off()
1115

1216
// Create a new custom matcher with HTTP headers only matchers
13-
matcher := gock.NewBasicMatcher()
17+
matcher := g.NewBasicMatcher()
1418

1519
// Add a custom match function
1620
matcher.Add(func(req *http.Request, ereq *gock.Request) (bool, error) {
1721
return req.URL.Scheme == "http", nil
1822
})
1923

2024
// Define the mock
21-
gock.New("http://httpbin.org").
25+
g.New("http://httpbin.org").
2226
SetMatcher(matcher).
2327
Get("/").
2428
Reply(204).
2529
SetHeader("Server", "gock")
2630

27-
res, err := http.Get("http://httpbin.org/get")
31+
res, err := c.Get("http://httpbin.org/get")
2832
if err != nil {
2933
fmt.Errorf("Error: %s", err)
3034
}

_examples/filters/filter.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,25 @@ package main
22

33
import (
44
"fmt"
5-
"github.com/h2non/gock"
65
"net/http"
6+
7+
"github.com/h2non/gock"
78
)
89

910
func main() {
10-
defer gock.Off()
11+
g := gock.NewGock()
12+
c := &http.Client{}
13+
g.InterceptClient(c)
14+
defer g.Off()
1115

12-
gock.New("http://httpbin.org").
16+
g.New("http://httpbin.org").
1317
Get("/get").
1418
Filter(func(req *http.Request) bool { return req.URL.Host == "httpbin.org" }).
1519
Filter(func(req *http.Request) bool { return req.URL.Path == "/get" }).
1620
Reply(204).
1721
SetHeader("Server", "gock")
1822

19-
res, err := http.Get("http://httpbin.org/get")
23+
res, err := c.Get("http://httpbin.org/get")
2024
if err != nil {
2125
fmt.Errorf("Error: %s", err)
2226
}

_examples/gentleman/gentleman.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,27 @@ package main
33
import (
44
"fmt"
55

6+
"github.com/h2non/gock"
67
"gopkg.in/h2non/gentleman.v1"
78
"gopkg.in/h2non/gentleman.v1/context"
8-
"github.com/h2non/gock"
99
)
1010

1111
// Usege example with gentleman HTTP client toolkit.
1212
// See also: https://github.com/h2non/gentleman-mock
1313
func main() {
14-
defer gock.Off()
14+
g := gock.NewGock()
15+
defer g.Off()
1516

16-
gock.New("http://httpbin.org").
17+
g.New("http://httpbin.org").
1718
Get("/*").
1819
Reply(204).
1920
SetHeader("Server", "gock")
2021

2122
cli := gentleman.New()
23+
g.InterceptClient(cli.Context.Client)
2224

2325
cli.UseHandler("before dial", func(ctx *context.Context, h context.Handler) {
24-
gock.InterceptClient(ctx.Client)
26+
g.InterceptClient(ctx.Client)
2527
h.Next(ctx)
2628
})
2729

_examples/mapper/map.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,25 @@ package main
33
import (
44
"fmt"
55
"net/http"
6-
7-
"github.com/h2non/gock"
6+
7+
"github.com/h2non/gock"
88
)
99

1010
func main() {
11-
defer gock.Disable()
11+
g := gock.NewGock()
12+
c := &http.Client{}
13+
g.InterceptClient(c)
14+
defer g.Disable()
1215

13-
gock.New("http://httpbin.org").
16+
g.New("http://httpbin.org").
1417
Get("/").
1518
Map(func(req *http.Request) *http.Request { req.URL.Host = "httpbin.org"; return req }).
1619
Map(func(req *http.Request) *http.Request { req.URL.Path = "/"; return req }).
1720
Reply(204).
18-
Map(func(res *http.Response) *http.Response { res.StatusCode = 404; return res }).
21+
Map(func(res *http.Response) *http.Response { res.StatusCode = 404; return res }).
1922
SetHeader("Server", "gock")
2023

21-
res, err := http.Get("http://httpbin.org/get")
24+
res, err := c.Get("http://httpbin.org/get")
2225
if err != nil {
2326
fmt.Errorf("Error: %s", err)
2427
}

0 commit comments

Comments
 (0)