Skip to content

Commit 810fd74

Browse files
avoid using mocks in tests (#89)
1 parent 27b4107 commit 810fd74

File tree

7 files changed

+217
-617
lines changed

7 files changed

+217
-617
lines changed

.github/workflows/go-generate.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ cp -r "$DIR" generated
1010

1111
cd generated
1212
# delete all go-generated files generated (that adhere to the comment convention)
13-
grep --include \*.go -lrIZ "^// Code generated .* DO NOT EDIT\.$" . | xargs --null rm
13+
grep --include \*.go -lrIZ "^// Code generated .* DO NOT EDIT\.$" . | xargs -r --null rm
1414

1515
# generate everything
1616
go generate ./...

conn_test.go

Lines changed: 72 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,104 @@
1-
package masque
1+
package masque_test
22

33
import (
44
"bytes"
55
"context"
6-
"errors"
6+
"crypto/tls"
7+
"fmt"
78
"io"
89
"log"
910
"math/rand/v2"
11+
"net"
12+
"net/http"
1013
"os"
1114
"testing"
1215
"time"
1316

17+
"github.com/quic-go/masque-go"
18+
1419
"github.com/quic-go/quic-go/http3"
20+
"github.com/yosida95/uritemplate/v3"
21+
1522
"github.com/stretchr/testify/require"
16-
"go.uber.org/mock/gomock"
1723
)
1824

25+
func setupProxiedConn(t *testing.T) (http3.Stream, net.PacketConn) {
26+
t.Helper()
27+
28+
targetConn := newUDPConnLocalhost(t)
29+
30+
strChan := make(chan http3.Stream, 1)
31+
mux := http.NewServeMux()
32+
mux.HandleFunc("/masque", func(w http.ResponseWriter, r *http.Request) {
33+
strChan <- w.(http3.HTTPStreamer).HTTPStream()
34+
})
35+
server := http3.Server{
36+
TLSConfig: tlsConf,
37+
Handler: mux,
38+
EnableDatagrams: true,
39+
}
40+
t.Cleanup(func() { server.Close() })
41+
serverConn := newUDPConnLocalhost(t)
42+
go server.Serve(serverConn)
43+
44+
cl := masque.Client{
45+
TLSClientConfig: &tls.Config{
46+
ClientCAs: certPool,
47+
NextProtos: []string{http3.NextProtoH3},
48+
InsecureSkipVerify: true,
49+
},
50+
}
51+
t.Cleanup(func() { cl.Close() })
52+
53+
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
54+
defer cancel()
55+
conn, rsp, err := cl.Dial(
56+
ctx,
57+
uritemplate.MustNew(fmt.Sprintf("https://localhost:%d/masque?h={target_host}&p={target_port}", serverConn.LocalAddr().(*net.UDPAddr).Port)),
58+
targetConn.LocalAddr().(*net.UDPAddr),
59+
)
60+
require.NoError(t, err)
61+
require.Equal(t, http.StatusOK, rsp.StatusCode)
62+
t.Cleanup(func() { conn.Close() })
63+
64+
var str http3.Stream
65+
select {
66+
case str = <-strChan:
67+
case <-time.After(time.Second):
68+
t.Fatal("timeout")
69+
}
70+
return str, conn
71+
}
72+
1973
func TestCapsuleSkipping(t *testing.T) {
2074
log.SetOutput(io.Discard)
2175
defer log.SetOutput(os.Stderr)
2276

77+
str, conn := setupProxiedConn(t)
78+
2379
var buf bytes.Buffer
2480
require.NoError(t, http3.WriteCapsule(&buf, 1337, []byte("foo")))
2581
require.NoError(t, http3.WriteCapsule(&buf, 42, []byte("bar")))
26-
require.ErrorIs(t, skipCapsules(&buf), io.EOF)
82+
_, err := str.Write(buf.Bytes())
83+
require.NoError(t, err)
84+
require.NoError(t, str.Close())
85+
86+
_, _, err = conn.ReadFrom(make([]byte, 100))
87+
require.ErrorIs(t, err, io.EOF)
2788
}
2889

2990
func TestReadDeadline(t *testing.T) {
30-
setupStreamAndConn := func() (*MockStream, *proxiedConn) {
31-
str := NewMockStream(gomock.NewController(t))
32-
done := make(chan struct{})
33-
t.Cleanup(func() {
34-
str.EXPECT().Close().MaxTimes(1)
35-
close(done)
36-
})
37-
str.EXPECT().Read(gomock.Any()).DoAndReturn(func([]byte) (int, error) {
38-
<-done
39-
return 0, errors.New("test done")
40-
}).MaxTimes(1)
41-
return str, newProxiedConn(str, nil)
42-
}
43-
4491
t.Run("read after deadline", func(t *testing.T) {
45-
str, conn := setupStreamAndConn()
46-
str.EXPECT().ReceiveDatagram(gomock.Any()).DoAndReturn(func(ctx context.Context) ([]byte, error) {
47-
<-ctx.Done()
48-
return nil, ctx.Err()
49-
})
92+
_, conn := setupProxiedConn(t)
5093

5194
require.NoError(t, conn.SetReadDeadline(time.Now().Add(-time.Second)))
5295
_, _, err := conn.ReadFrom(make([]byte, 100))
5396
require.ErrorIs(t, err, os.ErrDeadlineExceeded)
5497
})
5598

5699
t.Run("unblocking read", func(t *testing.T) {
57-
str, conn := setupStreamAndConn()
58-
str.EXPECT().ReceiveDatagram(gomock.Any()).DoAndReturn(func(ctx context.Context) ([]byte, error) {
59-
<-ctx.Done()
60-
return nil, ctx.Err()
61-
}).Times(2)
100+
_, conn := setupProxiedConn(t)
101+
62102
errChan := make(chan error, 1)
63103
go func() {
64104
_, _, err := conn.ReadFrom(make([]byte, 100))
@@ -81,11 +121,7 @@ func TestReadDeadline(t *testing.T) {
81121
})
82122

83123
t.Run("extending the deadline", func(t *testing.T) {
84-
str, conn := setupStreamAndConn()
85-
str.EXPECT().ReceiveDatagram(gomock.Any()).DoAndReturn(func(ctx context.Context) ([]byte, error) {
86-
<-ctx.Done()
87-
return nil, ctx.Err()
88-
}).MaxTimes(2) // might be called a 2nd time depending on when the cancellation Go routine does its job
124+
_, conn := setupProxiedConn(t)
89125

90126
start := time.Now()
91127
d := scaleDuration(75 * time.Millisecond)
@@ -108,11 +144,7 @@ func TestReadDeadline(t *testing.T) {
108144
})
109145

110146
t.Run("cancelling the deadline", func(t *testing.T) {
111-
str, conn := setupStreamAndConn()
112-
str.EXPECT().ReceiveDatagram(gomock.Any()).DoAndReturn(func(ctx context.Context) ([]byte, error) {
113-
<-ctx.Done()
114-
return nil, ctx.Err()
115-
})
147+
_, conn := setupProxiedConn(t)
116148

117149
start := time.Now()
118150
d := scaleDuration(75 * time.Millisecond)
@@ -140,13 +172,10 @@ func TestReadDeadline(t *testing.T) {
140172
})
141173

142174
t.Run("multiple deadlines", func(t *testing.T) {
143-
str, conn := setupStreamAndConn()
175+
_, conn := setupProxiedConn(t)
176+
144177
const num = 10
145178
const maxDeadline = 5 * time.Millisecond
146-
str.EXPECT().ReceiveDatagram(gomock.Any()).DoAndReturn(func(ctx context.Context) ([]byte, error) {
147-
<-ctx.Done()
148-
return nil, ctx.Err()
149-
}).MinTimes(num)
150179

151180
for range num {
152181
// random duration between -5ms and 5ms

0 commit comments

Comments
 (0)