-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdialer_test.go
More file actions
183 lines (160 loc) · 5.26 KB
/
Copy pathdialer_test.go
File metadata and controls
183 lines (160 loc) · 5.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package ivnp
import (
"context"
"errors"
"net"
"testing"
)
type mockStreamNetwork struct {
dial func(context.Context, string) (net.Conn, error)
listen func(context.Context, string) (net.Listener, error)
}
func (m mockStreamNetwork) DialI2P(ctx context.Context, address string) (net.Conn, error) {
return m.dial(ctx, address)
}
func (m mockStreamNetwork) ListenI2P(ctx context.Context, address string) (net.Listener, error) {
return m.listen(ctx, address)
}
type mockListener struct{}
func (mockListener) Accept() (net.Conn, error) { return nil, errors.New("accept not implemented") }
func (mockListener) Close() error { return nil }
func (mockListener) Addr() net.Addr { return mockAddr("i2p") }
type mockAddr string
func (a mockAddr) Network() string { return "i2p" }
func (a mockAddr) String() string { return string(a) }
func TestDialerDialContextDelegates(t *testing.T) {
ctx := context.WithValue(context.Background(), "test", "value")
client, server := net.Pipe()
defer client.Close()
defer server.Close()
var gotContext context.Context
var gotAddress string
dialer := Dialer{Network: mockStreamNetwork{
dial: func(ctx context.Context, address string) (net.Conn, error) {
gotContext = ctx
gotAddress = address
return client, nil
},
}}
conn, err := dialer.DialContext(ctx, "i2p", "destination.i2p:1234")
if err != nil {
t.Fatal(err)
}
if conn != client {
t.Fatal("DialContext() connection did not come from StreamNetwork")
}
if gotContext != ctx {
t.Fatal("DialContext() did not pass its context to StreamNetwork")
}
if gotAddress != "destination.i2p:1234" {
t.Fatalf("DialContext() address = %q, want %q", gotAddress, "destination.i2p:1234")
}
}
func TestDialerDialUsesBackgroundContext(t *testing.T) {
var gotContext context.Context
dialer := Dialer{Network: mockStreamNetwork{
dial: func(ctx context.Context, address string) (net.Conn, error) {
gotContext = ctx
return nil, nil
},
}}
if _, err := dialer.Dial("i2p", "destination.i2p"); err != nil {
t.Fatal(err)
}
if gotContext != context.Background() {
t.Fatal("Dial() context is not context.Background()")
}
}
func TestDialerRejectsUnsupportedNetwork(t *testing.T) {
called := false
dialer := Dialer{Network: mockStreamNetwork{
dial: func(context.Context, string) (net.Conn, error) {
called = true
return nil, nil
},
}}
for _, network := range []string{"", "tcp", "udp", "I2P"} {
if _, err := dialer.DialContext(context.Background(), network, "destination.i2p"); !errors.Is(err, ErrUnsupportedNetwork) {
t.Fatalf("DialContext(%q) error = %v, want ErrUnsupportedNetwork", network, err)
}
}
if called {
t.Fatal("DialContext() called StreamNetwork for an unsupported network")
}
}
func TestDialerAcceptsI2PStreamNetwork(t *testing.T) {
called := false
dialer := Dialer{Network: mockStreamNetwork{
dial: func(context.Context, string) (net.Conn, error) {
called = true
return nil, nil
},
}}
if _, err := dialer.DialContext(context.Background(), "i2p-stream", "destination.i2p"); err != nil {
t.Fatal(err)
}
if !called {
t.Fatal("DialContext() did not call StreamNetwork for i2p-stream")
}
}
func TestDialerErrorsWithoutStreamNetwork(t *testing.T) {
for _, dial := range []func() error{
func() error {
_, err := (Dialer{}).DialContext(context.Background(), "i2p", "destination.i2p")
return err
},
func() error {
_, err := (Dialer{}).Dial("i2p", "destination.i2p")
return err
},
} {
err := dial()
if !errors.Is(err, ErrStreamNetworkRequired) {
t.Fatalf("dial error = %v, want ErrStreamNetworkRequired", err)
}
}
}
func TestListenerConfigDelegates(t *testing.T) {
ctx := context.WithValue(context.Background(), "test", "value")
listener := mockListener{}
var gotContext context.Context
var gotAddress string
config := ListenerConfig{Network: mockStreamNetwork{
listen: func(ctx context.Context, address string) (net.Listener, error) {
gotContext = ctx
gotAddress = address
return listener, nil
},
}}
got, err := config.Listen(ctx, "service.i2p:8080")
if err != nil {
t.Fatal(err)
}
if got != listener {
t.Fatal("Listen() listener did not come from StreamNetwork")
}
if gotContext != ctx {
t.Fatal("Listen() did not pass its context to StreamNetwork")
}
if gotAddress != "service.i2p:8080" {
t.Fatalf("Listen() address = %q, want %q", gotAddress, "service.i2p:8080")
}
}
func TestDelegatesStreamNetworkErrors(t *testing.T) {
want := errors.New("stream network failed")
network := mockStreamNetwork{
dial: func(context.Context, string) (net.Conn, error) { return nil, want },
listen: func(context.Context, string) (net.Listener, error) { return nil, want },
}
if _, err := (Dialer{Network: network}).DialContext(context.Background(), "i2p", "destination.i2p"); !errors.Is(err, want) {
t.Fatalf("DialContext() error = %v, want %v", err, want)
}
if _, err := (ListenerConfig{Network: network}).Listen(context.Background(), "destination.i2p"); !errors.Is(err, want) {
t.Fatalf("Listen() error = %v, want %v", err, want)
}
}
func TestListenerConfigErrorsWithoutStreamNetwork(t *testing.T) {
if _, err := (ListenerConfig{}).Listen(context.Background(), "service.i2p"); !errors.Is(err, ErrStreamNetworkRequired) {
t.Fatalf("Listen() error = %v, want ErrStreamNetworkRequired", err)
}
}