blob: bce2bab8bed2bc095a781d156388d57a9ef54b19 [file] [log] [blame]
Jiri Simsad7616c92015-03-24 23:44:30 -07001// Copyright 2015 The Vanadium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Jiri Simsa5293dcb2014-05-10 09:56:38 -07005package manager
6
7import (
8 "bytes"
9 "fmt"
10 "io"
11 "net"
Cosmos Nicolaou920db002014-10-23 16:57:32 -070012 "os"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070013 "reflect"
14 "runtime"
Suharsh Sivakumarad1d4192015-03-09 16:48:10 -070015 "sort"
Asim Shankare89936f2015-04-22 17:37:43 -070016 "strconv"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070017 "strings"
Asim Shankare89936f2015-04-22 17:37:43 -070018 "syscall"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070019 "testing"
Cosmos Nicolaou920db002014-10-23 16:57:32 -070020 "time"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070021
Cosmos Nicolaou1381f8a2015-03-13 09:40:34 -070022 "v.io/x/lib/vlog"
23
Jiri Simsa6ac95222015-02-23 16:11:49 -080024 "v.io/v23/naming"
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070025 "v.io/v23/rpc"
Jiri Simsa6ac95222015-02-23 16:11:49 -080026 "v.io/v23/security"
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -070027
Suharsh Sivakumardcc11d72015-05-11 12:19:20 -070028 inaming "v.io/x/ref/runtime/internal/naming"
29 _ "v.io/x/ref/runtime/internal/rpc/protocols/tcp"
30 _ "v.io/x/ref/runtime/internal/rpc/protocols/ws"
31 "v.io/x/ref/runtime/internal/rpc/stream"
32 "v.io/x/ref/runtime/internal/rpc/stream/vc"
33 "v.io/x/ref/runtime/internal/rpc/stream/vif"
Cosmos Nicolaou1381f8a2015-03-13 09:40:34 -070034 "v.io/x/ref/test"
35 "v.io/x/ref/test/expect"
36 "v.io/x/ref/test/modules"
Asim Shankar4a698282015-03-21 21:59:18 -070037 "v.io/x/ref/test/testutil"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070038)
39
40func init() {
Suharsh Sivakumard19c95d2015-02-19 14:44:50 -080041 modules.RegisterChild("runServer", "", runServer)
Asim Shankare89936f2015-04-22 17:37:43 -070042 modules.RegisterChild("runRLimitedServer", "", runRLimitedServer)
Suharsh Sivakumard19c95d2015-02-19 14:44:50 -080043}
44
45// We write our own TestMain here instead of relying on v23 test generate because
46// we need to set runtime.GOMAXPROCS.
47func TestMain(m *testing.M) {
Cosmos Nicolaou1381f8a2015-03-13 09:40:34 -070048 test.Init()
Asim Shankarc920db32014-10-16 19:18:21 -070049 // testutil.Init sets GOMAXPROCS to NumCPU. We want to force
50 // GOMAXPROCS to remain at 1, in order to trigger a particular race
Suharsh Sivakumard19c95d2015-02-19 14:44:50 -080051 // condition that occurs when closing the server; also, using 1 cpu
Jiri Simsa5293dcb2014-05-10 09:56:38 -070052 // introduces less variance in the behavior of the test.
53 runtime.GOMAXPROCS(1)
Cosmos Nicolaou42a17362015-03-10 16:40:18 -070054 if modules.IsModulesChildProcess() {
Suharsh Sivakumard19c95d2015-02-19 14:44:50 -080055 if err := modules.Dispatch(); err != nil {
56 fmt.Fprintf(os.Stderr, "modules.Dispatch failed: %v\n", err)
57 os.Exit(1)
58 }
59 return
60 }
61 os.Exit(m.Run())
Jiri Simsa5293dcb2014-05-10 09:56:38 -070062}
63
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -080064func testSimpleFlow(t *testing.T, protocol string) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -070065 server := InternalNew(naming.FixedRoutingID(0x55555555))
66 client := InternalNew(naming.FixedRoutingID(0xcccccccc))
Asim Shankar4a698282015-03-21 21:59:18 -070067 pclient := testutil.NewPrincipal("client")
68 pserver := testutil.NewPrincipal("server")
Jiri Simsa5293dcb2014-05-10 09:56:38 -070069
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -070070 ln, ep, err := server.Listen(protocol, "127.0.0.1:0", pserver, pserver.BlessingStore().Default())
Jiri Simsa5293dcb2014-05-10 09:56:38 -070071 if err != nil {
72 t.Fatal(err)
73 }
74
75 data := "the dark knight rises"
76 var clientVC stream.VC
77 var clientF1 stream.Flow
78 go func() {
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -070079 if clientVC, err = client.Dial(ep, pclient); err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -070080 t.Errorf("Dial(%q) failed: %v", ep, err)
81 return
82 }
83 if clientF1, err = clientVC.Connect(); err != nil {
84 t.Errorf("Connect() failed: %v", err)
85 return
86 }
87 if err := writeLine(clientF1, data); err != nil {
88 t.Error(err)
89 }
90 }()
91 serverF, err := ln.Accept()
92 if err != nil {
93 t.Fatalf("Accept failed: %v", err)
94 }
95 if got, err := readLine(serverF); got != data || err != nil {
96 t.Errorf("Got (%q, %v), want (%q, nil)", got, err, data)
97 }
98 // By this point, the goroutine has passed the write call (or exited
99 // early) since the read has gotten through. Check if the goroutine
100 // encountered any errors in creating the VC or flow and abort.
101 if t.Failed() {
102 return
103 }
104 defer clientF1.Close()
105
106 ln.Close()
107
108 // Writes on flows opened before the server listener was closed should
109 // still succeed.
110 data = "the dark knight goes to bed"
111 go func() {
112 if err := writeLine(clientF1, data); err != nil {
113 t.Error(err)
114 }
115 }()
116 if got, err := readLine(serverF); got != data || err != nil {
117 t.Errorf("Got (%q, %v), want (%q, nil)", got, err, data)
118 }
119
120 // Opening a new flow on an existing VC will succeed initially, but
121 // writes on the client end will eventually fail once the server has
122 // stopped listening.
123 //
124 // It will require a round-trip to the server to notice the failure,
125 // hence the client should write enough data to ensure that the Write
126 // call will not return before a round-trip.
127 //
128 // The length of the data is taken to exceed the queue buffer size
129 // (DefaultBytesBufferedPerFlow), the shared counters (MaxSharedBytes)
130 // and the per-flow counters (DefaultBytesBufferedPerFlow) that are
131 // given when the flow gets established.
132 //
133 // TODO(caprita): separate the constants for the queue buffer size and
134 // the default number of counters to avoid confusion.
135 lotsOfData := string(make([]byte, vc.DefaultBytesBufferedPerFlow*2+vc.MaxSharedBytes+1))
136 clientF2, err := clientVC.Connect()
137 if err != nil {
138 t.Fatalf("Connect() failed: %v", err)
139 }
140 defer clientF2.Close()
141 if err := writeLine(clientF2, lotsOfData); err == nil {
142 t.Errorf("Should not be able to Dial or Write after the Listener is closed")
143 }
144 // Opening a new VC should fail fast.
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700145 if _, err := client.Dial(ep, pclient); err == nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700146 t.Errorf("Should not be able to Dial after listener is closed")
147 }
148}
149
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800150func TestSimpleFlow(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800151 testSimpleFlow(t, "tcp")
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800152}
153
154func TestSimpleFlowWS(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800155 testSimpleFlow(t, "ws")
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800156}
157
Cosmos Nicolaou9388ae42014-11-10 10:57:15 -0800158func TestConnectionTimeout(t *testing.T) {
159 client := InternalNew(naming.FixedRoutingID(0xcccccccc))
160
161 ch := make(chan error)
162 go func() {
163 // 203.0.113.0 is TEST-NET-3 from RFC5737
164 ep, _ := inaming.NewEndpoint(naming.FormatEndpoint("tcp", "203.0.113.10:80"))
Matt Rosencrantzbf0d9d92015-04-08 12:43:14 -0700165 _, err := client.Dial(ep, testutil.NewPrincipal("client"), DialTimeout(time.Second))
Cosmos Nicolaou9388ae42014-11-10 10:57:15 -0800166 ch <- err
167 }()
168
169 select {
170 case err := <-ch:
171 if err == nil {
172 t.Fatalf("expected an error")
173 }
174 case <-time.After(time.Minute):
175 t.Fatalf("timedout")
176 }
177}
178
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800179func testAuthenticatedByDefault(t *testing.T, protocol string) {
Asim Shankar6b0510a2014-10-01 12:05:06 -0700180 var (
181 server = InternalNew(naming.FixedRoutingID(0x55555555))
182 client = InternalNew(naming.FixedRoutingID(0xcccccccc))
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700183
Asim Shankar4a698282015-03-21 21:59:18 -0700184 clientPrincipal = testutil.NewPrincipal("client")
185 serverPrincipal = testutil.NewPrincipal("server")
Suharsh Sivakumar59c423c2015-03-11 14:06:03 -0700186 clientKey = clientPrincipal.PublicKey()
187 serverBlessings = serverPrincipal.BlessingStore().Default()
Asim Shankar6b0510a2014-10-01 12:05:06 -0700188 )
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700189 ln, ep, err := server.Listen(protocol, "127.0.0.1:0", serverPrincipal, serverPrincipal.BlessingStore().Default())
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700190 if err != nil {
191 t.Fatal(err)
192 }
Asim Shankar7171a252015-03-07 14:41:40 -0800193 // And the server blessing should be in the endpoint.
194 if got, want := ep.BlessingNames(), []string{"server"}; !reflect.DeepEqual(got, want) {
195 t.Errorf("Got blessings %v from endpoint, want %v", got, want)
196 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700197
198 errs := make(chan error)
199
Ankur50a5f392015-02-27 18:46:30 -0800200 testAuth := func(tag string, flow stream.Flow, wantServer security.Blessings, wantClientKey security.PublicKey) {
201 // Since the client's blessing is expected to be self-signed we only test
202 // its public key
203 gotServer := flow.RemoteBlessings()
204 gotClientKey := flow.LocalBlessings().PublicKey()
205 if tag == "server" {
206 gotServer = flow.LocalBlessings()
207 gotClientKey = flow.RemoteBlessings().PublicKey()
208 }
209 if !reflect.DeepEqual(gotServer, wantServer) || !reflect.DeepEqual(gotClientKey, wantClientKey) {
210 errs <- fmt.Errorf("%s: Server: Got Blessings %q, want %q. Server: Got Blessings %q, want %q", tag, gotServer, wantServer, gotClientKey, wantClientKey)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700211 return
212 }
213 errs <- nil
214 }
215
216 go func() {
217 flow, err := ln.Accept()
218 if err != nil {
219 errs <- err
220 return
221 }
222 defer flow.Close()
Ankur50a5f392015-02-27 18:46:30 -0800223 testAuth("server", flow, serverBlessings, clientKey)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700224 }()
225
226 go func() {
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700227 vc, err := client.Dial(ep, clientPrincipal)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700228 if err != nil {
229 errs <- err
230 return
231 }
232 flow, err := vc.Connect()
233 if err != nil {
234 errs <- err
235 return
236 }
237 defer flow.Close()
Ankur50a5f392015-02-27 18:46:30 -0800238 testAuth("client", flow, serverBlessings, clientKey)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700239 }()
240
241 if err := <-errs; err != nil {
242 t.Error(err)
243 }
244 if err := <-errs; err != nil {
245 t.Error(err)
246 }
247}
248
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800249func TestAuthenticatedByDefault(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800250 testAuthenticatedByDefault(t, "tcp")
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800251}
252
253func TestAuthenticatedByDefaultWS(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800254 testAuthenticatedByDefault(t, "ws")
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800255}
256
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700257func numListeners(m stream.Manager) int { return len(m.(*manager).listeners) }
258func debugString(m stream.Manager) string { return m.(*manager).DebugString() }
259func numVIFs(m stream.Manager) int { return len(m.(*manager).vifs.List()) }
260
261func TestListenEndpoints(t *testing.T) {
262 server := InternalNew(naming.FixedRoutingID(0xcafe))
Asim Shankar4a698282015-03-21 21:59:18 -0700263 principal := testutil.NewPrincipal("test")
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700264 blessings := principal.BlessingStore().Default()
265 ln1, ep1, err1 := server.Listen("tcp", "127.0.0.1:0", principal, blessings)
266 ln2, ep2, err2 := server.Listen("tcp", "127.0.0.1:0", principal, blessings)
Adam Sadovsky5181bdb2014-08-13 10:29:11 -0700267 // Since "127.0.0.1:0" was used as the network address, a random port will be
268 // assigned in each case. The endpoint should include that random port.
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700269 if err1 != nil {
270 t.Error(err1)
271 }
272 if err2 != nil {
273 t.Error(err2)
274 }
275 if ep1.String() == ep2.String() {
276 t.Errorf("Both listeners got the same endpoint: %q", ep1)
277 }
278 if n, expect := numListeners(server), 2; n != expect {
279 t.Errorf("expecting %d listeners, got %d for %s", n, expect, debugString(server))
280 }
281 ln1.Close()
282 if n, expect := numListeners(server), 1; n != expect {
283 t.Errorf("expecting %d listeners, got %d for %s", n, expect, debugString(server))
284 }
285 ln2.Close()
286 if n, expect := numListeners(server), 0; n != expect {
287 t.Errorf("expecting %d listeners, got %d for %s", n, expect, debugString(server))
288 }
289}
290
291func acceptLoop(ln stream.Listener) {
292 for {
293 f, err := ln.Accept()
294 if err != nil {
295 return
296 }
297 f.Close()
298 }
299}
300
301func TestCloseListener(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800302 testCloseListener(t, "tcp")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700303}
304
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800305func TestCloseListenerWS(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800306 testCloseListener(t, "ws")
307}
308
309func testCloseListener(t *testing.T, protocol string) {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800310 server := InternalNew(naming.FixedRoutingID(0x5e97e9))
Asim Shankar4a698282015-03-21 21:59:18 -0700311 pclient := testutil.NewPrincipal("client")
312 pserver := testutil.NewPrincipal("server")
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700313 blessings := pserver.BlessingStore().Default()
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800314
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700315 ln, ep, err := server.Listen(protocol, "127.0.0.1:0", pserver, blessings)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800316 if err != nil {
317 t.Fatal(err)
318 }
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800319 // Server will just listen for flows and close them.
320 go acceptLoop(ln)
321 client := InternalNew(naming.FixedRoutingID(0xc1e41))
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700322 if _, err = client.Dial(ep, pclient); err != nil {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800323 t.Fatal(err)
324 }
325 ln.Close()
326 client = InternalNew(naming.FixedRoutingID(0xc1e42))
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700327 if _, err := client.Dial(ep, pclient); err == nil {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800328 t.Errorf("client.Dial(%q) should have failed", ep)
329 }
330}
331
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700332func TestShutdown(t *testing.T) {
333 server := InternalNew(naming.FixedRoutingID(0x5e97e9))
Asim Shankar4a698282015-03-21 21:59:18 -0700334 principal := testutil.NewPrincipal("test")
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700335 blessings := principal.BlessingStore().Default()
336 ln, _, err := server.Listen("tcp", "127.0.0.1:0", principal, blessings)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700337 if err != nil {
338 t.Fatal(err)
339 }
340 // Server will just listen for flows and close them.
341 go acceptLoop(ln)
342 if n, expect := numListeners(server), 1; n != expect {
343 t.Errorf("expecting %d listeners, got %d for %s", n, expect, debugString(server))
344 }
345 server.Shutdown()
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700346 if _, _, err := server.Listen("tcp", "127.0.0.1:0", principal, blessings); err == nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700347 t.Error("server should have shut down")
348 }
349 if n, expect := numListeners(server), 0; n != expect {
350 t.Errorf("expecting %d listeners, got %d for %s", n, expect, debugString(server))
351 }
352}
353
354func TestShutdownEndpoint(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800355 testShutdownEndpoint(t, "tcp")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700356}
357
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800358func TestShutdownEndpointWS(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800359 testShutdownEndpoint(t, "ws")
360}
361
362func testShutdownEndpoint(t *testing.T, protocol string) {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800363 server := InternalNew(naming.FixedRoutingID(0x55555555))
364 client := InternalNew(naming.FixedRoutingID(0xcccccccc))
Asim Shankar4a698282015-03-21 21:59:18 -0700365 principal := testutil.NewPrincipal("test")
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800366
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700367 ln, ep, err := server.Listen(protocol, "127.0.0.1:0", principal, principal.BlessingStore().Default())
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800368 if err != nil {
369 t.Fatal(err)
370 }
371
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800372 // Server will just listen for flows and close them.
373 go acceptLoop(ln)
374
Asim Shankar4a698282015-03-21 21:59:18 -0700375 vc, err := client.Dial(ep, testutil.NewPrincipal("client"))
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800376 if err != nil {
377 t.Fatal(err)
378 }
379 if f, err := vc.Connect(); f == nil || err != nil {
380 t.Errorf("vc.Connect failed: (%v, %v)", f, err)
381 }
382 client.ShutdownEndpoint(ep)
383 if f, err := vc.Connect(); f != nil || err == nil {
384 t.Errorf("vc.Connect unexpectedly succeeded: (%v, %v)", f, err)
385 }
386}
387
Jungho Ahn6ab655f2015-04-14 18:27:09 -0700388func TestStartTimeout(t *testing.T) {
389 const (
390 startTime = 5 * time.Millisecond
Jungho Ahn6ab655f2015-04-14 18:27:09 -0700391 )
392
393 var (
394 server = InternalNew(naming.FixedRoutingID(0x55555555))
395 pserver = testutil.NewPrincipal("server")
396 lopts = []stream.ListenerOpt{vc.StartTimeout{startTime}}
397 )
398
399 // Pause the start timers.
400 triggerTimers := vif.SetFakeTimers()
401
402 ln, ep, err := server.Listen("tcp", "127.0.0.1:0", pserver, pserver.BlessingStore().Default(), lopts...)
403 if err != nil {
404 t.Fatal(err)
405 }
406 go func() {
407 for {
408 _, err := ln.Accept()
409 if err != nil {
410 return
411 }
412 }
413 }()
414
415 _, err = net.Dial(ep.Addr().Network(), ep.Addr().String())
416 if err != nil {
417 t.Fatalf("net.Dial failed: %v", err)
418 }
419
420 // Trigger the start timers.
421 triggerTimers()
422
423 // No VC is opened. The VIF should be closed after start timeout.
Jungho Ahncc9d5722015-04-22 10:13:04 -0700424 for range time.Tick(startTime) {
425 if numVIFs(server) == 0 {
426 break
Jungho Ahn6ab655f2015-04-14 18:27:09 -0700427 }
428 }
Jungho Ahn6ab655f2015-04-14 18:27:09 -0700429}
430
Jungho Ahncd175b82015-03-27 14:29:40 -0700431func testIdleTimeout(t *testing.T, testServer bool) {
432 const (
433 idleTime = 10 * time.Millisecond
434 // We use a long wait time here since it takes some time to handle VC close
435 // especially in race testing.
436 waitTime = 150 * time.Millisecond
437 )
438
439 var (
440 server = InternalNew(naming.FixedRoutingID(0x55555555))
441 client = InternalNew(naming.FixedRoutingID(0xcccccccc))
442 pclient = testutil.NewPrincipal("client")
443 pserver = testutil.NewPrincipal("server")
444
445 opts []stream.VCOpt
446 lopts []stream.ListenerOpt
447 )
448 if testServer {
449 lopts = []stream.ListenerOpt{vc.IdleTimeout{idleTime}}
450 } else {
451 opts = []stream.VCOpt{vc.IdleTimeout{idleTime}}
452 }
453
454 // Pause the idle timers.
455 triggerTimers := vif.SetFakeTimers()
456
457 ln, ep, err := server.Listen("tcp", "127.0.0.1:0", pserver, pserver.BlessingStore().Default(), lopts...)
458 if err != nil {
459 t.Fatal(err)
460 }
461 go func() {
462 for {
463 _, err := ln.Accept()
464 if err != nil {
465 return
466 }
467 }
468 }()
469
470 vc, err := client.Dial(ep, pclient, opts...)
471 if err != nil {
472 t.Fatalf("client.Dial(%q) failed: %v", ep, err)
473 }
474 f, err := vc.Connect()
475 if f == nil || err != nil {
476 t.Fatalf("vc.Connect failed: (%v, %v)", f, err)
477 }
478
479 // Trigger the idle timers.
480 triggerTimers()
481
482 // One active flow. The VIF should be kept open.
483 time.Sleep(waitTime)
484 if n := numVIFs(client); n != 1 {
485 t.Errorf("Client has %d VIFs; want 1\n%v", n, debugString(client))
486 }
487 if n := numVIFs(server); n != 1 {
488 t.Errorf("Server has %d VIFs; want 1\n%v", n, debugString(server))
489 }
490
491 f.Close()
492
493 // The flow has been closed. The VIF should be closed after idle timeout.
Jungho Ahncc9d5722015-04-22 10:13:04 -0700494 for range time.Tick(idleTime) {
495 if numVIFs(client) == 0 && numVIFs(server) == 0 {
496 break
Jungho Ahncd175b82015-03-27 14:29:40 -0700497 }
498 }
Jungho Ahncd175b82015-03-27 14:29:40 -0700499}
500
501func TestIdleTimeout(t *testing.T) { testIdleTimeout(t, false) }
502func TestIdleTimeoutServer(t *testing.T) { testIdleTimeout(t, true) }
503
Andres Erbsenffa45742014-08-13 10:13:11 -0700504/* TLS + resumption + channel bindings is broken: <https://secure-resumption.com/#channelbindings>.
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700505func TestSessionTicketCache(t *testing.T) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700506 server := InternalNew(naming.FixedRoutingID(0x55555555))
Asim Shankar4a698282015-03-21 21:59:18 -0700507 _, ep, err := server.Listen("tcp", "127.0.0.1:0", testutil.NewPrincipal("server"))
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700508 if err != nil {
509 t.Fatal(err)
510 }
511
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700512 client := InternalNew(naming.FixedRoutingID(0xcccccccc))
Asim Shankar4a698282015-03-21 21:59:18 -0700513 if _, err = client.Dial(ep, testutil.NewPrincipal("TestSessionTicketCacheClient")); err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700514 t.Fatalf("Dial(%q) failed: %v", ep, err)
515 }
516
517 if _, ok := client.(*manager).sessionCache.Get(ep.String()); !ok {
518 t.Fatalf("SessionTicket from TLS handshake not cached")
519 }
520}
Andres Erbsenffa45742014-08-13 10:13:11 -0700521*/
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700522
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800523func testMultipleVCs(t *testing.T, protocol string) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700524 server := InternalNew(naming.FixedRoutingID(0x55555555))
525 client := InternalNew(naming.FixedRoutingID(0xcccccccc))
Asim Shankar4a698282015-03-21 21:59:18 -0700526 principal := testutil.NewPrincipal("test")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700527
528 const nVCs = 2
529 const data = "bugs bunny"
530
531 // Have the server read from each flow and write to rchan.
532 rchan := make(chan string)
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700533 ln, ep, err := server.Listen(protocol, "127.0.0.1:0", principal, principal.BlessingStore().Default())
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700534 if err != nil {
535 t.Fatal(err)
536 }
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800537
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700538 read := func(flow stream.Flow, c chan string) {
539 var buf bytes.Buffer
540 var tmp [1024]byte
541 for {
542 n, err := flow.Read(tmp[:])
543 buf.Write(tmp[:n])
544 if err == io.EOF {
545 c <- buf.String()
546 return
547 }
548 if err != nil {
549 t.Error(err)
550 return
551 }
552 }
553 }
554 go func() {
555 for i := 0; i < nVCs; i++ {
556 flow, err := ln.Accept()
557 if err != nil {
558 t.Error(err)
559 rchan <- ""
560 continue
561 }
562 go read(flow, rchan)
563 }
564 }()
565
566 // Have the client establish nVCs and a flow on each.
567 var vcs [nVCs]stream.VC
568 for i := 0; i < nVCs; i++ {
569 var err error
Asim Shankar4a698282015-03-21 21:59:18 -0700570 vcs[i], err = client.Dial(ep, testutil.NewPrincipal("client"))
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700571 if err != nil {
572 t.Fatal(err)
573 }
574 }
575 write := func(vc stream.VC) {
576 if err != nil {
577 ln.Close()
578 t.Error(err)
579 return
580 }
581 flow, err := vc.Connect()
582 if err != nil {
583 ln.Close()
584 t.Error(err)
585 return
586 }
587 defer flow.Close()
588 if _, err := flow.Write([]byte(data)); err != nil {
589 ln.Close()
590 t.Error(err)
591 return
592 }
593 }
594 for _, vc := range vcs {
595 go write(vc)
596 }
597 for i := 0; i < nVCs; i++ {
598 if got := <-rchan; got != data {
599 t.Errorf("Got %q want %q", got, data)
600 }
601 }
602}
603
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800604func TestMultipleVCs(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800605 testMultipleVCs(t, "tcp")
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800606}
607
608func TestMultipleVCsWS(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800609 testMultipleVCs(t, "ws")
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800610}
611
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700612func TestAddressResolution(t *testing.T) {
613 server := InternalNew(naming.FixedRoutingID(0x55555555))
614 client := InternalNew(naming.FixedRoutingID(0xcccccccc))
Asim Shankar4a698282015-03-21 21:59:18 -0700615 principal := testutil.NewPrincipal("test")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700616
Adam Sadovsky5181bdb2014-08-13 10:29:11 -0700617 // Using "tcp4" instead of "tcp" because the latter can end up with IPv6
618 // addresses and our Google Compute Engine integration test machines cannot
619 // resolve IPv6 addresses.
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700620 // As of April 2014, https://developers.google.com/compute/docs/networking
621 // said that IPv6 is not yet supported.
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700622 ln, ep, err := server.Listen("tcp4", "127.0.0.1:0", principal, principal.BlessingStore().Default())
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700623 if err != nil {
624 t.Fatal(err)
625 }
626 go acceptLoop(ln)
627
Adam Sadovsky5181bdb2014-08-13 10:29:11 -0700628 // We'd like an endpoint that contains an address that's different than the
629 // one used for the connection. In practice this is awkward to achieve since
630 // we don't want to listen on ":0" since that will annoy firewalls. Instead we
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700631 // create a endpoint with "localhost", which will result in an endpoint that
632 // doesn't contain 127.0.0.1.
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700633 _, port, _ := net.SplitHostPort(ep.Addr().String())
Matt Rosencrantzc16339c2015-04-23 10:47:06 -0700634 nep := &inaming.Endpoint{
635 Protocol: ep.Addr().Network(),
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700636 Address: net.JoinHostPort("localhost", port),
Matt Rosencrantzc16339c2015-04-23 10:47:06 -0700637 RID: ep.RoutingID(),
638 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700639
640 // Dial multiple VCs
641 for i := 0; i < 2; i++ {
Asim Shankar4a698282015-03-21 21:59:18 -0700642 if _, err = client.Dial(nep, testutil.NewPrincipal("client")); err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700643 t.Fatalf("Dial #%d failed: %v", i, err)
644 }
645 }
646 // They should all be on the same VIF.
647 if n := numVIFs(client); n != 1 {
648 t.Errorf("Client has %d VIFs, want 1\n%v", n, debugString(client))
649 }
650 // TODO(ashankar): While a VIF can be re-used to Dial from the server
651 // to the client, currently there is no way to have the client "listen"
652 // on the same VIF. It can listen on a VC for new flows, but it cannot
653 // listen on an established VIF for new VCs. Figure this out?
654}
655
656func TestServerRestartDuringClientLifetime(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800657 testServerRestartDuringClientLifetime(t, "tcp")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700658}
659
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800660func TestServerRestartDuringClientLifetimeWS(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800661 testServerRestartDuringClientLifetime(t, "ws")
662}
663
664func testServerRestartDuringClientLifetime(t *testing.T, protocol string) {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800665 client := InternalNew(naming.FixedRoutingID(0xcccccccc))
Asim Shankar4a698282015-03-21 21:59:18 -0700666 pclient := testutil.NewPrincipal("client")
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700667 sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
Cosmos Nicolaou344cc4a2014-11-26 15:38:43 -0800668 if err != nil {
669 t.Fatalf("unexpected error: %s", err)
670 }
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800671 defer sh.Cleanup(nil, nil)
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800672 h, err := sh.Start("runServer", nil, protocol, "127.0.0.1:0")
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800673 if err != nil {
674 t.Fatalf("unexpected error: %s", err)
675 }
Asim Shankare89936f2015-04-22 17:37:43 -0700676 epstr := expect.NewSession(t, h.Stdout(), time.Minute).ExpectVar("ENDPOINT")
677 ep, err := inaming.NewEndpoint(epstr)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800678 if err != nil {
Asim Shankare89936f2015-04-22 17:37:43 -0700679 t.Fatalf("inaming.NewEndpoint(%q): %v", epstr, err)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800680 }
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700681 if _, err := client.Dial(ep, pclient); err != nil {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800682 t.Fatal(err)
683 }
684 h.Shutdown(nil, os.Stderr)
685
686 // A new VC cannot be created since the server is dead
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700687 if _, err := client.Dial(ep, pclient); err == nil {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800688 t.Fatal("Expected client.Dial to fail since server is dead")
689 }
690
Asim Shankare89936f2015-04-22 17:37:43 -0700691 h, err = sh.Start("runServer", nil, protocol, ep.Addr().String())
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800692 if err != nil {
693 t.Fatalf("unexpected error: %s", err)
694 }
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800695 // Restarting the server, listening on the same address as before
Asim Shankare89936f2015-04-22 17:37:43 -0700696 ep2, err := inaming.NewEndpoint(expect.NewSession(t, h.Stdout(), time.Minute).ExpectVar("ENDPOINT"))
697 if err != nil {
698 t.Fatal(err)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800699 }
Asim Shankare89936f2015-04-22 17:37:43 -0700700 if got, want := ep.Addr().String(), ep2.Addr().String(); got != want {
701 t.Fatalf("Got %q, want %q", got, want)
702 }
703 if _, err := client.Dial(ep2, pclient); err != nil {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800704 t.Fatal(err)
705 }
706}
707
Cosmos Nicolaou920db002014-10-23 16:57:32 -0700708func runServer(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700709 server := InternalNew(naming.FixedRoutingID(0x55555555))
Asim Shankar4a698282015-03-21 21:59:18 -0700710 principal := testutil.NewPrincipal("test")
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700711 _, ep, err := server.Listen(args[0], args[1], principal, principal.BlessingStore().Default())
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700712 if err != nil {
Cosmos Nicolaou920db002014-10-23 16:57:32 -0700713 fmt.Fprintln(stderr, err)
714 return err
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700715 }
Asim Shankare89936f2015-04-22 17:37:43 -0700716 fmt.Fprintf(stdout, "ENDPOINT=%v\n", ep)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700717 // Live forever (till the process is explicitly killed)
Cosmos Nicolaou920db002014-10-23 16:57:32 -0700718 modules.WaitForEOF(stdin)
719 return nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700720}
721
Asim Shankare89936f2015-04-22 17:37:43 -0700722func runRLimitedServer(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
723 var rlimit syscall.Rlimit
724 if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit); err != nil {
725 fmt.Fprintln(stderr, err)
726 return err
727 }
728 rlimit.Cur = 9
729 if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlimit); err != nil {
730 fmt.Fprintln(stderr, err)
731 return err
732 }
733 fmt.Fprintf(stdout, "RLIMIT_NOFILE=%d\n", rlimit.Cur)
734 return runServer(stdin, stdout, stderr, env, args...)
735}
736
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700737func readLine(f stream.Flow) (string, error) {
738 var result bytes.Buffer
739 var buf [5]byte
740 for {
741 n, err := f.Read(buf[:])
742 result.Write(buf[:n])
743 if err == io.EOF || buf[n-1] == '\n' {
744 return strings.TrimRight(result.String(), "\n"), nil
745 }
746 if err != nil {
747 return "", fmt.Errorf("Read returned (%d, %v)", n, err)
748 }
749 }
750}
751
752func writeLine(f stream.Flow, data string) error {
753 data = data + "\n"
754 vlog.VI(1).Infof("write sending %d bytes", len(data))
755 if n, err := f.Write([]byte(data)); err != nil {
756 return fmt.Errorf("Write returned (%d, %v)", n, err)
757 }
758 return nil
759}
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700760
761func TestRegistration(t *testing.T) {
762 server := InternalNew(naming.FixedRoutingID(0x55555555))
763 client := InternalNew(naming.FixedRoutingID(0xcccccccc))
Asim Shankar4a698282015-03-21 21:59:18 -0700764 principal := testutil.NewPrincipal("server")
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700765 blessings := principal.BlessingStore().Default()
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700766
Cosmos Nicolaou87c0a552014-12-02 23:05:49 -0800767 dialer := func(_, _ string, _ time.Duration) (net.Conn, error) {
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700768 return nil, fmt.Errorf("tn.Dial")
769 }
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700770 resolver := func(_, _ string) (string, string, error) {
771 return "", "", fmt.Errorf("tn.Resolve")
772 }
Cosmos Nicolaou87c0a552014-12-02 23:05:49 -0800773 listener := func(_, _ string) (net.Listener, error) {
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700774 return nil, fmt.Errorf("tn.Listen")
775 }
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700776 rpc.RegisterProtocol("tn", dialer, resolver, listener)
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700777
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700778 _, _, err := server.Listen("tnx", "127.0.0.1:0", principal, blessings)
Cosmos Nicolaou07a736d2015-04-06 11:55:26 -0700779 if err == nil || !strings.Contains(err.Error(), "unknown network: tnx") {
780 t.Fatalf("expected error is missing (%v)", err)
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700781 }
782
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700783 _, _, err = server.Listen("tn", "127.0.0.1:0", principal, blessings)
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700784 if err == nil || !strings.Contains(err.Error(), "tn.Listen") {
Cosmos Nicolaou07a736d2015-04-06 11:55:26 -0700785 t.Fatalf("expected error is missing (%v)", err)
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700786 }
787
788 // Need a functional listener to test Dial.
Cosmos Nicolaou87c0a552014-12-02 23:05:49 -0800789 listener = func(_, addr string) (net.Listener, error) {
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700790 return net.Listen("tcp", addr)
791 }
792
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700793 if got, want := rpc.RegisterProtocol("tn", dialer, resolver, listener), true; got != want {
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700794 t.Errorf("got %t, want %t", got, want)
795 }
796
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700797 _, ep, err := server.Listen("tn", "127.0.0.1:0", principal, blessings)
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700798 if err != nil {
799 t.Errorf("unexpected error %s", err)
800 }
801
Asim Shankar4a698282015-03-21 21:59:18 -0700802 _, err = client.Dial(ep, testutil.NewPrincipal("client"))
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700803 if err == nil || !strings.Contains(err.Error(), "tn.Resolve") {
804 t.Fatalf("expected error is missing (%v)", err)
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700805 }
806}
Asim Shankar7171a252015-03-07 14:41:40 -0800807
808func TestBlessingNamesInEndpoint(t *testing.T) {
809 var (
Asim Shankar4a698282015-03-21 21:59:18 -0700810 p = testutil.NewPrincipal("default")
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700811 b, _ = p.BlessSelf("dev.v.io/users/foo@bar.com/devices/desktop/app/myapp")
Asim Shankar7171a252015-03-07 14:41:40 -0800812
813 server = InternalNew(naming.FixedRoutingID(0x1))
814
815 tests = []struct {
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700816 principal security.Principal
817 blessings security.Blessings
818 blessingNames []string
819 err bool
Asim Shankar7171a252015-03-07 14:41:40 -0800820 }{
821 {
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700822 // provided blessings should match returned output.
823 principal: p,
824 blessings: b,
825 blessingNames: []string{"dev.v.io/users/foo@bar.com/devices/desktop/app/myapp"},
Asim Shankar7171a252015-03-07 14:41:40 -0800826 },
827 {
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700828 // It is an error to provide a principal without providing blessings.
Suharsh Sivakumar59c423c2015-03-11 14:06:03 -0700829 principal: p,
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700830 blessings: security.Blessings{},
Suharsh Sivakumar59c423c2015-03-11 14:06:03 -0700831 err: true,
Asim Shankar7171a252015-03-07 14:41:40 -0800832 },
833 {
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700834 // It is an error to provide inconsistent blessings and principal
Asim Shankar4a698282015-03-21 21:59:18 -0700835 principal: testutil.NewPrincipal("random"),
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700836 blessings: b,
Suharsh Sivakumar59c423c2015-03-11 14:06:03 -0700837 err: true,
Asim Shankar7171a252015-03-07 14:41:40 -0800838 },
839 }
840 )
841 // p must recognize its own blessings!
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700842 p.AddToRoots(b)
Asim Shankar7171a252015-03-07 14:41:40 -0800843 for idx, test := range tests {
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700844 ln, ep, err := server.Listen("tcp", "127.0.0.1:0", test.principal, test.blessings)
Asim Shankar7171a252015-03-07 14:41:40 -0800845 if (err != nil) != test.err {
846 t.Errorf("test #%d: Got error %v, wanted error: %v", idx, err, test.err)
847 }
848 if err != nil {
849 continue
850 }
851 ln.Close()
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700852 got, want := ep.BlessingNames(), test.blessingNames
Suharsh Sivakumarad1d4192015-03-09 16:48:10 -0700853 sort.Strings(got)
854 sort.Strings(want)
855 if !reflect.DeepEqual(got, want) {
Asim Shankar7171a252015-03-07 14:41:40 -0800856 t.Errorf("test #%d: Got %v, want %v", idx, got, want)
857 }
858 }
859}
Asim Shankare89936f2015-04-22 17:37:43 -0700860
861func TestVIFCleanupWhenFDLimitIsReached(t *testing.T) {
862 sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
863 if err != nil {
864 t.Fatal(err)
865 }
866 defer sh.Cleanup(nil, nil)
867 h, err := sh.Start("runRLimitedServer", nil, "--logtostderr=true", "tcp", "127.0.0.1:0")
868 if err != nil {
869 t.Fatal(err)
870 }
871 defer h.CloseStdin()
872 stdout := expect.NewSession(t, h.Stdout(), time.Minute)
873 nfiles, err := strconv.Atoi(stdout.ExpectVar("RLIMIT_NOFILE"))
874 if stdout.Error() != nil {
875 t.Fatal(stdout.Error())
876 }
877 if err != nil {
878 t.Fatal(err)
879 }
880 epstr := stdout.ExpectVar("ENDPOINT")
881 if stdout.Error() != nil {
882 t.Fatal(stdout.Error())
883 }
884 ep, err := inaming.NewEndpoint(epstr)
885 if err != nil {
886 t.Fatal(err)
887 }
888 // Different client processes (represented by different stream managers
889 // in this test) should be able to make progress, even if the server
890 // has reached its file descriptor limit.
891 nattempts := 0
892 for i := 0; i < 2*nfiles; i++ {
893 client := InternalNew(naming.FixedRoutingID(uint64(i)))
894 defer client.Shutdown()
895 principal := testutil.NewPrincipal(fmt.Sprintf("client%d", i))
896 connected := false
897 for !connected {
898 nattempts++
899 // If the client connection reached the server when it
900 // was at its limit, it might fail. However, this
901 // failure will trigger the "kill connections" logic at
902 // the server and eventually the client should succeed.
903 vc, err := client.Dial(ep, principal)
904 if err != nil {
905 continue
906 }
907 // Establish a flow to prevent the VC (and thus the
908 // underlying VIF) from being garbage collected as an
909 // "inactive" connection.
910 flow, err := vc.Connect()
911 if err != nil {
912 continue
913 }
914 defer flow.Close()
915 connected = true
916 }
917 }
918 var stderr bytes.Buffer
919 if err := h.Shutdown(nil, &stderr); err != nil {
920 t.Fatal(err)
921 }
Matt Rosencrantza40f12a2015-04-24 11:07:55 -0700922 if log := expect.NewSession(t, bytes.NewReader(stderr.Bytes()), time.Minute).ExpectSetEventuallyRE("listener.go.*Killing [1-9][0-9]* Conns"); len(log) == 0 {
923 t.Errorf("Failed to find log message talking about killing Conns in:\n%v", stderr.String())
Asim Shankare89936f2015-04-22 17:37:43 -0700924 }
925 t.Logf("Server FD limit:%d", nfiles)
926 t.Logf("Client connection attempts: %d", nattempts)
927}
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -0700928
929func TestConcurrentDials(t *testing.T) {
930 // Concurrent Dials to the same network, address should only result in one VIF.
931 server := InternalNew(naming.FixedRoutingID(0x55555555))
932 client := InternalNew(naming.FixedRoutingID(0xcccccccc))
933 principal := testutil.NewPrincipal("test")
934
935 // Using "tcp4" instead of "tcp" because the latter can end up with IPv6
936 // addresses and our Google Compute Engine integration test machines cannot
937 // resolve IPv6 addresses.
938 // As of April 2014, https://developers.google.com/compute/docs/networking
939 // said that IPv6 is not yet supported.
940 ln, ep, err := server.Listen("tcp4", "127.0.0.1:0", principal, principal.BlessingStore().Default())
941 if err != nil {
942 t.Fatal(err)
943 }
944 go acceptLoop(ln)
945
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -0700946 nep := &inaming.Endpoint{
947 Protocol: ep.Addr().Network(),
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700948 Address: ep.Addr().String(),
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -0700949 RID: ep.RoutingID(),
950 }
951
952 // Dial multiple VCs
953 errCh := make(chan error, 10)
954 for i := 0; i < 10; i++ {
955 go func() {
956 _, err = client.Dial(nep, testutil.NewPrincipal("client"))
957 errCh <- err
958 }()
959 }
960 for i := 0; i < 10; i++ {
961 if err = <-errCh; err != nil {
962 t.Fatal(err)
963 }
964 }
965 // They should all be on the same VIF.
966 if n := numVIFs(client); n != 1 {
967 t.Errorf("Client has %d VIFs, want 1\n%v", n, debugString(client))
968 }
969}