blob: 622c7aff73ebb3ddc18f4f160d31c33678918848 [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"
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -070018 "sync"
Asim Shankare89936f2015-04-22 17:37:43 -070019 "syscall"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070020 "testing"
Cosmos Nicolaou920db002014-10-23 16:57:32 -070021 "time"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070022
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -070023 "v.io/v23"
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
Suharsh Sivakumard19c95d2015-02-19 14:44:50 -080040// We write our own TestMain here instead of relying on v23 test generate because
41// we need to set runtime.GOMAXPROCS.
42func TestMain(m *testing.M) {
Cosmos Nicolaou1381f8a2015-03-13 09:40:34 -070043 test.Init()
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -070044
Asim Shankarc920db32014-10-16 19:18:21 -070045 // testutil.Init sets GOMAXPROCS to NumCPU. We want to force
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -070046 // GOMAXPFDROCS to remain at 1, in order to trigger a particular race
Suharsh Sivakumard19c95d2015-02-19 14:44:50 -080047 // condition that occurs when closing the server; also, using 1 cpu
Jiri Simsa5293dcb2014-05-10 09:56:38 -070048 // introduces less variance in the behavior of the test.
49 runtime.GOMAXPROCS(1)
Todd Wang95873902015-05-22 14:21:30 -070050 modules.DispatchAndExitIfChild()
Suharsh Sivakumard19c95d2015-02-19 14:44:50 -080051 os.Exit(m.Run())
Jiri Simsa5293dcb2014-05-10 09:56:38 -070052}
53
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -080054func testSimpleFlow(t *testing.T, protocol string) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -070055 ctx, shutdown := test.V23Init()
56 defer shutdown()
57 server := InternalNew(ctx, naming.FixedRoutingID(0x55555555))
58 client := InternalNew(ctx, naming.FixedRoutingID(0xcccccccc))
Asim Shankar4a698282015-03-21 21:59:18 -070059 pclient := testutil.NewPrincipal("client")
Jungho Ahn19e84b22015-05-18 13:22:27 -070060 pclient2 := testutil.NewPrincipal("client2")
Asim Shankar4a698282015-03-21 21:59:18 -070061 pserver := testutil.NewPrincipal("server")
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -070062 ctx, _ = v23.WithPrincipal(ctx, pserver)
Jiri Simsa5293dcb2014-05-10 09:56:38 -070063
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -070064 ln, ep, err := server.Listen(ctx, protocol, "127.0.0.1:0", pserver.BlessingStore().Default())
Jiri Simsa5293dcb2014-05-10 09:56:38 -070065 if err != nil {
66 t.Fatal(err)
67 }
68
69 data := "the dark knight rises"
70 var clientVC stream.VC
71 var clientF1 stream.Flow
72 go func() {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -070073 cctx, _ := v23.WithPrincipal(ctx, pclient)
74 if clientVC, err = client.Dial(cctx, ep); err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -070075 t.Errorf("Dial(%q) failed: %v", ep, err)
76 return
77 }
78 if clientF1, err = clientVC.Connect(); err != nil {
79 t.Errorf("Connect() failed: %v", err)
80 return
81 }
82 if err := writeLine(clientF1, data); err != nil {
83 t.Error(err)
84 }
85 }()
86 serverF, err := ln.Accept()
87 if err != nil {
88 t.Fatalf("Accept failed: %v", err)
89 }
90 if got, err := readLine(serverF); got != data || err != nil {
91 t.Errorf("Got (%q, %v), want (%q, nil)", got, err, data)
92 }
93 // By this point, the goroutine has passed the write call (or exited
94 // early) since the read has gotten through. Check if the goroutine
95 // encountered any errors in creating the VC or flow and abort.
96 if t.Failed() {
97 return
98 }
99 defer clientF1.Close()
100
101 ln.Close()
102
103 // Writes on flows opened before the server listener was closed should
104 // still succeed.
105 data = "the dark knight goes to bed"
106 go func() {
107 if err := writeLine(clientF1, data); err != nil {
108 t.Error(err)
109 }
110 }()
111 if got, err := readLine(serverF); got != data || err != nil {
112 t.Errorf("Got (%q, %v), want (%q, nil)", got, err, data)
113 }
114
115 // Opening a new flow on an existing VC will succeed initially, but
116 // writes on the client end will eventually fail once the server has
117 // stopped listening.
118 //
119 // It will require a round-trip to the server to notice the failure,
120 // hence the client should write enough data to ensure that the Write
121 // call will not return before a round-trip.
122 //
123 // The length of the data is taken to exceed the queue buffer size
124 // (DefaultBytesBufferedPerFlow), the shared counters (MaxSharedBytes)
125 // and the per-flow counters (DefaultBytesBufferedPerFlow) that are
126 // given when the flow gets established.
127 //
128 // TODO(caprita): separate the constants for the queue buffer size and
129 // the default number of counters to avoid confusion.
130 lotsOfData := string(make([]byte, vc.DefaultBytesBufferedPerFlow*2+vc.MaxSharedBytes+1))
131 clientF2, err := clientVC.Connect()
132 if err != nil {
133 t.Fatalf("Connect() failed: %v", err)
134 }
135 defer clientF2.Close()
136 if err := writeLine(clientF2, lotsOfData); err == nil {
137 t.Errorf("Should not be able to Dial or Write after the Listener is closed")
138 }
Jungho Ahn19e84b22015-05-18 13:22:27 -0700139 // Opening a new VC should fail fast. Note that we need to use a different
140 // principal since the client doesn't expect a response from a server
141 // when re-using VIF authentication.
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700142 cctx, _ := v23.WithPrincipal(ctx, pclient2)
143 if _, err := client.Dial(cctx, ep); err == nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700144 t.Errorf("Should not be able to Dial after listener is closed")
145 }
146}
147
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800148func TestSimpleFlow(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800149 testSimpleFlow(t, "tcp")
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800150}
151
152func TestSimpleFlowWS(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800153 testSimpleFlow(t, "ws")
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800154}
155
Cosmos Nicolaou9388ae42014-11-10 10:57:15 -0800156func TestConnectionTimeout(t *testing.T) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700157 ctx, shutdown := test.V23Init()
158 defer shutdown()
159 client := InternalNew(ctx, naming.FixedRoutingID(0xcccccccc))
Cosmos Nicolaou9388ae42014-11-10 10:57:15 -0800160
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"))
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700165 nctx, _ := v23.WithPrincipal(ctx, testutil.NewPrincipal("client"))
166 _, err := client.Dial(nctx, ep, DialTimeout(time.Second))
Cosmos Nicolaou9388ae42014-11-10 10:57:15 -0800167 ch <- err
168 }()
169
170 select {
171 case err := <-ch:
172 if err == nil {
173 t.Fatalf("expected an error")
174 }
175 case <-time.After(time.Minute):
176 t.Fatalf("timedout")
177 }
178}
179
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800180func testAuthenticatedByDefault(t *testing.T, protocol string) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700181 ctx, shutdown := test.V23Init()
182 defer shutdown()
Asim Shankar6b0510a2014-10-01 12:05:06 -0700183 var (
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700184 server = InternalNew(ctx, naming.FixedRoutingID(0x55555555))
185 client = InternalNew(ctx, naming.FixedRoutingID(0xcccccccc))
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700186
Asim Shankar4a698282015-03-21 21:59:18 -0700187 clientPrincipal = testutil.NewPrincipal("client")
188 serverPrincipal = testutil.NewPrincipal("server")
Suharsh Sivakumar59c423c2015-03-11 14:06:03 -0700189 clientKey = clientPrincipal.PublicKey()
190 serverBlessings = serverPrincipal.BlessingStore().Default()
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700191 cctx, _ = v23.WithPrincipal(ctx, clientPrincipal)
192 sctx, _ = v23.WithPrincipal(ctx, serverPrincipal)
Asim Shankar6b0510a2014-10-01 12:05:06 -0700193 )
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700194
195 ln, ep, err := server.Listen(sctx, protocol, "127.0.0.1:0", serverPrincipal.BlessingStore().Default())
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700196 if err != nil {
197 t.Fatal(err)
198 }
Asim Shankar7171a252015-03-07 14:41:40 -0800199 // And the server blessing should be in the endpoint.
200 if got, want := ep.BlessingNames(), []string{"server"}; !reflect.DeepEqual(got, want) {
201 t.Errorf("Got blessings %v from endpoint, want %v", got, want)
202 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700203
204 errs := make(chan error)
205
Ankur50a5f392015-02-27 18:46:30 -0800206 testAuth := func(tag string, flow stream.Flow, wantServer security.Blessings, wantClientKey security.PublicKey) {
207 // Since the client's blessing is expected to be self-signed we only test
208 // its public key
209 gotServer := flow.RemoteBlessings()
210 gotClientKey := flow.LocalBlessings().PublicKey()
211 if tag == "server" {
212 gotServer = flow.LocalBlessings()
213 gotClientKey = flow.RemoteBlessings().PublicKey()
214 }
215 if !reflect.DeepEqual(gotServer, wantServer) || !reflect.DeepEqual(gotClientKey, wantClientKey) {
216 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 -0700217 return
218 }
219 errs <- nil
220 }
221
222 go func() {
223 flow, err := ln.Accept()
224 if err != nil {
225 errs <- err
226 return
227 }
228 defer flow.Close()
Ankur50a5f392015-02-27 18:46:30 -0800229 testAuth("server", flow, serverBlessings, clientKey)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700230 }()
231
232 go func() {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700233 vc, err := client.Dial(cctx, ep)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700234 if err != nil {
235 errs <- err
236 return
237 }
238 flow, err := vc.Connect()
239 if err != nil {
240 errs <- err
241 return
242 }
243 defer flow.Close()
Ankur50a5f392015-02-27 18:46:30 -0800244 testAuth("client", flow, serverBlessings, clientKey)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700245 }()
246
247 if err := <-errs; err != nil {
248 t.Error(err)
249 }
250 if err := <-errs; err != nil {
251 t.Error(err)
252 }
253}
254
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800255func TestAuthenticatedByDefault(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800256 testAuthenticatedByDefault(t, "tcp")
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800257}
258
259func TestAuthenticatedByDefaultWS(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800260 testAuthenticatedByDefault(t, "ws")
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800261}
262
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700263func numListeners(m stream.Manager) int { return len(m.(*manager).listeners) }
264func debugString(m stream.Manager) string { return m.(*manager).DebugString() }
265func numVIFs(m stream.Manager) int { return len(m.(*manager).vifs.List()) }
266
267func TestListenEndpoints(t *testing.T) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700268 ctx, shutdown := test.V23Init()
269 defer shutdown()
270 server := InternalNew(ctx, naming.FixedRoutingID(0xcafe))
Asim Shankar4a698282015-03-21 21:59:18 -0700271 principal := testutil.NewPrincipal("test")
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700272 ctx, _ = v23.WithPrincipal(ctx, principal)
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700273 blessings := principal.BlessingStore().Default()
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700274 ln1, ep1, err1 := server.Listen(ctx, "tcp", "127.0.0.1:0", blessings)
275 ln2, ep2, err2 := server.Listen(ctx, "tcp", "127.0.0.1:0", blessings)
Adam Sadovsky5181bdb2014-08-13 10:29:11 -0700276 // Since "127.0.0.1:0" was used as the network address, a random port will be
277 // assigned in each case. The endpoint should include that random port.
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700278 if err1 != nil {
279 t.Error(err1)
280 }
281 if err2 != nil {
282 t.Error(err2)
283 }
284 if ep1.String() == ep2.String() {
285 t.Errorf("Both listeners got the same endpoint: %q", ep1)
286 }
287 if n, expect := numListeners(server), 2; n != expect {
288 t.Errorf("expecting %d listeners, got %d for %s", n, expect, debugString(server))
289 }
290 ln1.Close()
291 if n, expect := numListeners(server), 1; n != expect {
292 t.Errorf("expecting %d listeners, got %d for %s", n, expect, debugString(server))
293 }
294 ln2.Close()
295 if n, expect := numListeners(server), 0; n != expect {
296 t.Errorf("expecting %d listeners, got %d for %s", n, expect, debugString(server))
297 }
298}
299
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700300func acceptLoop(wg *sync.WaitGroup, ln stream.Listener) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700301 for {
302 f, err := ln.Accept()
303 if err != nil {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700304 break
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700305 }
306 f.Close()
307 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700308 wg.Done()
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700309}
310
311func TestCloseListener(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800312 testCloseListener(t, "tcp")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700313}
314
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800315func TestCloseListenerWS(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800316 testCloseListener(t, "ws")
317}
318
319func testCloseListener(t *testing.T, protocol string) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700320 ctx, shutdown := test.V23Init()
321 defer shutdown()
322 server := InternalNew(ctx, naming.FixedRoutingID(0x5e97e9))
Asim Shankar4a698282015-03-21 21:59:18 -0700323 pclient := testutil.NewPrincipal("client")
324 pserver := testutil.NewPrincipal("server")
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700325 cctx, _ := v23.WithPrincipal(ctx, pclient)
326 sctx, _ := v23.WithPrincipal(ctx, pserver)
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700327 blessings := pserver.BlessingStore().Default()
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700328 ln, ep, err := server.Listen(sctx, protocol, "127.0.0.1:0", blessings)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800329 if err != nil {
330 t.Fatal(err)
331 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700332 var wg sync.WaitGroup
333 wg.Add(1)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800334 // Server will just listen for flows and close them.
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700335 go acceptLoop(&wg, ln)
336 client := InternalNew(ctx, naming.FixedRoutingID(0xc1e41))
337 if _, err = client.Dial(cctx, ep); err != nil {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800338 t.Fatal(err)
339 }
340 ln.Close()
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700341 client = InternalNew(ctx, naming.FixedRoutingID(0xc1e42))
342 if _, err := client.Dial(cctx, ep); err == nil {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800343 t.Errorf("client.Dial(%q) should have failed", ep)
344 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700345 time.Sleep(time.Second)
346 wg.Wait()
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800347}
348
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700349func TestShutdown(t *testing.T) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700350 ctx, shutdown := test.V23Init()
351 defer shutdown()
352 server := InternalNew(ctx, naming.FixedRoutingID(0x5e97e9))
Asim Shankar4a698282015-03-21 21:59:18 -0700353 principal := testutil.NewPrincipal("test")
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700354 ctx, _ = v23.WithPrincipal(ctx, principal)
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700355 blessings := principal.BlessingStore().Default()
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700356 ln, _, err := server.Listen(ctx, "tcp", "127.0.0.1:0", blessings)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700357 if err != nil {
358 t.Fatal(err)
359 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700360 var wg sync.WaitGroup
361 wg.Add(1)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700362 // Server will just listen for flows and close them.
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700363 go acceptLoop(&wg, ln)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700364 if n, expect := numListeners(server), 1; n != expect {
365 t.Errorf("expecting %d listeners, got %d for %s", n, expect, debugString(server))
366 }
367 server.Shutdown()
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700368 if _, _, err := server.Listen(ctx, "tcp", "127.0.0.1:0", blessings); err == nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700369 t.Error("server should have shut down")
370 }
371 if n, expect := numListeners(server), 0; n != expect {
372 t.Errorf("expecting %d listeners, got %d for %s", n, expect, debugString(server))
373 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700374 wg.Wait()
375 fmt.Fprintf(os.Stderr, "DONE\n")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700376}
377
378func TestShutdownEndpoint(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800379 testShutdownEndpoint(t, "tcp")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700380}
381
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800382func TestShutdownEndpointWS(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800383 testShutdownEndpoint(t, "ws")
384}
385
386func testShutdownEndpoint(t *testing.T, protocol string) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700387 ctx, shutdown := test.V23Init()
388 defer shutdown()
389 server := InternalNew(ctx, naming.FixedRoutingID(0x55555555))
390 client := InternalNew(ctx, naming.FixedRoutingID(0xcccccccc))
Asim Shankar4a698282015-03-21 21:59:18 -0700391 principal := testutil.NewPrincipal("test")
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700392 ctx, _ = v23.WithPrincipal(ctx, principal)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800393
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700394 ln, ep, err := server.Listen(ctx, protocol, "127.0.0.1:0", principal.BlessingStore().Default())
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800395 if err != nil {
396 t.Fatal(err)
397 }
398
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700399 var wg sync.WaitGroup
400 wg.Add(1)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800401 // Server will just listen for flows and close them.
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700402 go acceptLoop(&wg, ln)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800403
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700404 cctx, _ := v23.WithPrincipal(ctx, testutil.NewPrincipal("client"))
405 vc, err := client.Dial(cctx, ep)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800406 if err != nil {
407 t.Fatal(err)
408 }
409 if f, err := vc.Connect(); f == nil || err != nil {
410 t.Errorf("vc.Connect failed: (%v, %v)", f, err)
411 }
412 client.ShutdownEndpoint(ep)
413 if f, err := vc.Connect(); f != nil || err == nil {
414 t.Errorf("vc.Connect unexpectedly succeeded: (%v, %v)", f, err)
415 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700416 ln.Close()
417 wg.Wait()
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800418}
419
Jungho Ahn6ab655f2015-04-14 18:27:09 -0700420func TestStartTimeout(t *testing.T) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700421 ctx, shutdown := test.V23Init()
422 defer shutdown()
Jungho Ahn6ab655f2015-04-14 18:27:09 -0700423 const (
424 startTime = 5 * time.Millisecond
Jungho Ahn6ab655f2015-04-14 18:27:09 -0700425 )
426
427 var (
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700428 server = InternalNew(ctx, naming.FixedRoutingID(0x55555555))
Jungho Ahn6ab655f2015-04-14 18:27:09 -0700429 pserver = testutil.NewPrincipal("server")
430 lopts = []stream.ListenerOpt{vc.StartTimeout{startTime}}
431 )
432
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700433 sctx, _ := v23.WithPrincipal(ctx, pserver)
434
Jungho Ahn6ab655f2015-04-14 18:27:09 -0700435 // Pause the start timers.
436 triggerTimers := vif.SetFakeTimers()
437
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700438 ln, ep, err := server.Listen(sctx, "tcp", "127.0.0.1:0", pserver.BlessingStore().Default(), lopts...)
Jungho Ahn6ab655f2015-04-14 18:27:09 -0700439 if err != nil {
440 t.Fatal(err)
441 }
442 go func() {
443 for {
444 _, err := ln.Accept()
445 if err != nil {
446 return
447 }
448 }
449 }()
Cosmos Nicolaou4d082c52015-07-21 21:35:11 -0700450 // Arrange for the above goroutine to exit when the test finishes.
451 defer ln.Close()
Jungho Ahn6ab655f2015-04-14 18:27:09 -0700452
453 _, err = net.Dial(ep.Addr().Network(), ep.Addr().String())
454 if err != nil {
455 t.Fatalf("net.Dial failed: %v", err)
456 }
457
458 // Trigger the start timers.
459 triggerTimers()
460
461 // No VC is opened. The VIF should be closed after start timeout.
Jungho Ahncc9d5722015-04-22 10:13:04 -0700462 for range time.Tick(startTime) {
463 if numVIFs(server) == 0 {
464 break
Jungho Ahn6ab655f2015-04-14 18:27:09 -0700465 }
466 }
Jungho Ahn6ab655f2015-04-14 18:27:09 -0700467}
468
Jungho Ahncd175b82015-03-27 14:29:40 -0700469func testIdleTimeout(t *testing.T, testServer bool) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700470 ctx, shutdown := test.V23Init()
471 defer shutdown()
Jungho Ahncd175b82015-03-27 14:29:40 -0700472 const (
473 idleTime = 10 * time.Millisecond
474 // We use a long wait time here since it takes some time to handle VC close
475 // especially in race testing.
476 waitTime = 150 * time.Millisecond
477 )
478
479 var (
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700480 server = InternalNew(ctx, naming.FixedRoutingID(0x55555555))
481 client = InternalNew(ctx, naming.FixedRoutingID(0xcccccccc))
Jungho Ahncd175b82015-03-27 14:29:40 -0700482 pclient = testutil.NewPrincipal("client")
483 pserver = testutil.NewPrincipal("server")
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700484 cctx, _ = v23.WithPrincipal(ctx, pclient)
485 sctx, _ = v23.WithPrincipal(ctx, pserver)
Jungho Ahncd175b82015-03-27 14:29:40 -0700486
487 opts []stream.VCOpt
488 lopts []stream.ListenerOpt
489 )
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700490
Jungho Ahncd175b82015-03-27 14:29:40 -0700491 if testServer {
492 lopts = []stream.ListenerOpt{vc.IdleTimeout{idleTime}}
493 } else {
494 opts = []stream.VCOpt{vc.IdleTimeout{idleTime}}
495 }
496
497 // Pause the idle timers.
498 triggerTimers := vif.SetFakeTimers()
499
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700500 ln, ep, err := server.Listen(sctx, "tcp", "127.0.0.1:0", pserver.BlessingStore().Default(), lopts...)
Jungho Ahncd175b82015-03-27 14:29:40 -0700501 if err != nil {
502 t.Fatal(err)
503 }
Jungho Ahn19e84b22015-05-18 13:22:27 -0700504 errch := make(chan error)
Cosmos Nicolaou4d082c52015-07-21 21:35:11 -0700505 done := make(chan struct{})
Jungho Ahncd175b82015-03-27 14:29:40 -0700506 go func() {
507 for {
508 _, err := ln.Accept()
Cosmos Nicolaou4d082c52015-07-21 21:35:11 -0700509 select {
510 case <-done:
511 return
512 case errch <- err:
513 }
Jungho Ahncd175b82015-03-27 14:29:40 -0700514 }
515 }()
Cosmos Nicolaou4d082c52015-07-21 21:35:11 -0700516 // Arrange for the above goroutine to exit when the test finishes.
517 defer func() { ln.Close(); close(done) }()
Jungho Ahncd175b82015-03-27 14:29:40 -0700518
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700519 vc, err := client.Dial(cctx, ep, opts...)
Jungho Ahncd175b82015-03-27 14:29:40 -0700520 if err != nil {
521 t.Fatalf("client.Dial(%q) failed: %v", ep, err)
522 }
523 f, err := vc.Connect()
524 if f == nil || err != nil {
525 t.Fatalf("vc.Connect failed: (%v, %v)", f, err)
526 }
Jungho Ahn19e84b22015-05-18 13:22:27 -0700527 // Wait until the server accepts the flow or fails.
528 if err = <-errch; err != nil {
529 t.Fatalf("ln.Accept failed: %v", err)
530 }
Jungho Ahncd175b82015-03-27 14:29:40 -0700531
532 // Trigger the idle timers.
533 triggerTimers()
534
535 // One active flow. The VIF should be kept open.
536 time.Sleep(waitTime)
537 if n := numVIFs(client); n != 1 {
538 t.Errorf("Client has %d VIFs; want 1\n%v", n, debugString(client))
539 }
540 if n := numVIFs(server); n != 1 {
541 t.Errorf("Server has %d VIFs; want 1\n%v", n, debugString(server))
542 }
543
544 f.Close()
545
546 // The flow has been closed. The VIF should be closed after idle timeout.
Jungho Ahncc9d5722015-04-22 10:13:04 -0700547 for range time.Tick(idleTime) {
548 if numVIFs(client) == 0 && numVIFs(server) == 0 {
549 break
Jungho Ahncd175b82015-03-27 14:29:40 -0700550 }
551 }
Jungho Ahncd175b82015-03-27 14:29:40 -0700552}
553
554func TestIdleTimeout(t *testing.T) { testIdleTimeout(t, false) }
555func TestIdleTimeoutServer(t *testing.T) { testIdleTimeout(t, true) }
556
Andres Erbsenffa45742014-08-13 10:13:11 -0700557/* TLS + resumption + channel bindings is broken: <https://secure-resumption.com/#channelbindings>.
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700558func TestSessionTicketCache(t *testing.T) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700559 server := InternalNew(naming.FixedRoutingID(0x55555555))
Asim Shankar4a698282015-03-21 21:59:18 -0700560 _, ep, err := server.Listen("tcp", "127.0.0.1:0", testutil.NewPrincipal("server"))
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700561 if err != nil {
562 t.Fatal(err)
563 }
564
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700565 client := InternalNew(naming.FixedRoutingID(0xcccccccc))
Asim Shankar4a698282015-03-21 21:59:18 -0700566 if _, err = client.Dial(ep, testutil.NewPrincipal("TestSessionTicketCacheClient")); err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700567 t.Fatalf("Dial(%q) failed: %v", ep, err)
568 }
569
570 if _, ok := client.(*manager).sessionCache.Get(ep.String()); !ok {
571 t.Fatalf("SessionTicket from TLS handshake not cached")
572 }
573}
Andres Erbsenffa45742014-08-13 10:13:11 -0700574*/
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700575
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800576func testMultipleVCs(t *testing.T, protocol string) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700577 ctx, shutdown := test.V23Init()
578 defer shutdown()
579 server := InternalNew(ctx, naming.FixedRoutingID(0x55555555))
580 client := InternalNew(ctx, naming.FixedRoutingID(0xcccccccc))
Asim Shankar4a698282015-03-21 21:59:18 -0700581 principal := testutil.NewPrincipal("test")
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700582 sctx, _ := v23.WithPrincipal(ctx, principal)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700583
584 const nVCs = 2
585 const data = "bugs bunny"
586
587 // Have the server read from each flow and write to rchan.
588 rchan := make(chan string)
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700589 ln, ep, err := server.Listen(sctx, protocol, "127.0.0.1:0", principal.BlessingStore().Default())
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700590 if err != nil {
591 t.Fatal(err)
592 }
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800593
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700594 read := func(flow stream.Flow, c chan string) {
595 var buf bytes.Buffer
596 var tmp [1024]byte
597 for {
598 n, err := flow.Read(tmp[:])
599 buf.Write(tmp[:n])
600 if err == io.EOF {
601 c <- buf.String()
602 return
603 }
604 if err != nil {
605 t.Error(err)
606 return
607 }
608 }
609 }
610 go func() {
611 for i := 0; i < nVCs; i++ {
612 flow, err := ln.Accept()
613 if err != nil {
614 t.Error(err)
615 rchan <- ""
616 continue
617 }
618 go read(flow, rchan)
619 }
620 }()
621
622 // Have the client establish nVCs and a flow on each.
623 var vcs [nVCs]stream.VC
624 for i := 0; i < nVCs; i++ {
625 var err error
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700626 pclient := testutil.NewPrincipal("client")
627 cctx, _ := v23.WithPrincipal(ctx, pclient)
628 vcs[i], err = client.Dial(cctx, ep)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700629 if err != nil {
630 t.Fatal(err)
631 }
632 }
633 write := func(vc stream.VC) {
634 if err != nil {
635 ln.Close()
636 t.Error(err)
637 return
638 }
639 flow, err := vc.Connect()
640 if err != nil {
641 ln.Close()
642 t.Error(err)
643 return
644 }
645 defer flow.Close()
646 if _, err := flow.Write([]byte(data)); err != nil {
647 ln.Close()
648 t.Error(err)
649 return
650 }
651 }
652 for _, vc := range vcs {
653 go write(vc)
654 }
655 for i := 0; i < nVCs; i++ {
656 if got := <-rchan; got != data {
657 t.Errorf("Got %q want %q", got, data)
658 }
659 }
660}
661
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800662func TestMultipleVCs(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800663 testMultipleVCs(t, "tcp")
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800664}
665
666func TestMultipleVCsWS(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800667 testMultipleVCs(t, "ws")
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800668}
669
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700670func TestAddressResolution(t *testing.T) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700671 ctx, shutdown := test.V23Init()
672 defer shutdown()
673 server := InternalNew(ctx, naming.FixedRoutingID(0x55555555))
674 client := InternalNew(ctx, naming.FixedRoutingID(0xcccccccc))
Asim Shankar4a698282015-03-21 21:59:18 -0700675 principal := testutil.NewPrincipal("test")
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700676 sctx, _ := v23.WithPrincipal(ctx, principal)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700677
Adam Sadovsky5181bdb2014-08-13 10:29:11 -0700678 // Using "tcp4" instead of "tcp" because the latter can end up with IPv6
679 // addresses and our Google Compute Engine integration test machines cannot
680 // resolve IPv6 addresses.
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700681 // As of April 2014, https://developers.google.com/compute/docs/networking
682 // said that IPv6 is not yet supported.
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700683 ln, ep, err := server.Listen(sctx, "tcp4", "127.0.0.1:0", principal.BlessingStore().Default())
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700684 if err != nil {
685 t.Fatal(err)
686 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700687 var wg sync.WaitGroup
688 wg.Add(1)
689 go acceptLoop(&wg, ln)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700690
Adam Sadovsky5181bdb2014-08-13 10:29:11 -0700691 // We'd like an endpoint that contains an address that's different than the
692 // one used for the connection. In practice this is awkward to achieve since
693 // we don't want to listen on ":0" since that will annoy firewalls. Instead we
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700694 // create a endpoint with "localhost", which will result in an endpoint that
695 // doesn't contain 127.0.0.1.
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700696 _, port, _ := net.SplitHostPort(ep.Addr().String())
Matt Rosencrantzc16339c2015-04-23 10:47:06 -0700697 nep := &inaming.Endpoint{
698 Protocol: ep.Addr().Network(),
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700699 Address: net.JoinHostPort("localhost", port),
Matt Rosencrantzc16339c2015-04-23 10:47:06 -0700700 RID: ep.RoutingID(),
701 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700702
703 // Dial multiple VCs
704 for i := 0; i < 2; i++ {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700705 pclient := testutil.NewPrincipal("client")
706 cctx, _ := v23.WithPrincipal(ctx, pclient)
707 if _, err = client.Dial(cctx, nep); err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700708 t.Fatalf("Dial #%d failed: %v", i, err)
709 }
710 }
711 // They should all be on the same VIF.
712 if n := numVIFs(client); n != 1 {
713 t.Errorf("Client has %d VIFs, want 1\n%v", n, debugString(client))
714 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700715 ln.Close()
716 wg.Wait()
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700717 // TODO(ashankar): While a VIF can be re-used to Dial from the server
718 // to the client, currently there is no way to have the client "listen"
719 // on the same VIF. It can listen on a VC for new flows, but it cannot
720 // listen on an established VIF for new VCs. Figure this out?
721}
722
723func TestServerRestartDuringClientLifetime(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800724 testServerRestartDuringClientLifetime(t, "tcp")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700725}
726
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800727func TestServerRestartDuringClientLifetimeWS(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800728 testServerRestartDuringClientLifetime(t, "ws")
729}
730
731func testServerRestartDuringClientLifetime(t *testing.T, protocol string) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700732 ctx, shutdown := test.V23Init()
733 defer shutdown()
734 client := InternalNew(ctx, naming.FixedRoutingID(0xcccccccc))
Asim Shankar4a698282015-03-21 21:59:18 -0700735 pclient := testutil.NewPrincipal("client")
Jungho Ahn19e84b22015-05-18 13:22:27 -0700736 pclient2 := testutil.NewPrincipal("client2")
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700737 ctx1, _ := v23.WithPrincipal(ctx, pclient)
738 ctx2, _ := v23.WithPrincipal(ctx, pclient2)
739
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700740 sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
Cosmos Nicolaou344cc4a2014-11-26 15:38:43 -0800741 if err != nil {
742 t.Fatalf("unexpected error: %s", err)
743 }
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800744 defer sh.Cleanup(nil, nil)
Todd Wang95873902015-05-22 14:21:30 -0700745 h, err := sh.Start(nil, runServer, protocol, "127.0.0.1:0")
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800746 if err != nil {
747 t.Fatalf("unexpected error: %s", err)
748 }
Asim Shankare89936f2015-04-22 17:37:43 -0700749 epstr := expect.NewSession(t, h.Stdout(), time.Minute).ExpectVar("ENDPOINT")
750 ep, err := inaming.NewEndpoint(epstr)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800751 if err != nil {
Asim Shankare89936f2015-04-22 17:37:43 -0700752 t.Fatalf("inaming.NewEndpoint(%q): %v", epstr, err)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800753 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700754 if _, err := client.Dial(ctx1, ep); err != nil {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800755 t.Fatal(err)
756 }
757 h.Shutdown(nil, os.Stderr)
758
Jungho Ahn19e84b22015-05-18 13:22:27 -0700759 // A new VC cannot be created since the server is dead. Note that we need to
760 // use a different principal since the client doesn't expect a response from
761 // a server when re-using VIF authentication.
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700762 if _, err := client.Dial(ctx2, ep); err == nil {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800763 t.Fatal("Expected client.Dial to fail since server is dead")
764 }
765
Todd Wang95873902015-05-22 14:21:30 -0700766 h, err = sh.Start(nil, runServer, protocol, ep.Addr().String())
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800767 if err != nil {
768 t.Fatalf("unexpected error: %s", err)
769 }
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800770 // Restarting the server, listening on the same address as before
Asim Shankare89936f2015-04-22 17:37:43 -0700771 ep2, err := inaming.NewEndpoint(expect.NewSession(t, h.Stdout(), time.Minute).ExpectVar("ENDPOINT"))
772 if err != nil {
773 t.Fatal(err)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800774 }
Asim Shankare89936f2015-04-22 17:37:43 -0700775 if got, want := ep.Addr().String(), ep2.Addr().String(); got != want {
776 t.Fatalf("Got %q, want %q", got, want)
777 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700778 if _, err := client.Dial(ctx1, ep2); err != nil {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800779 t.Fatal(err)
780 }
781}
782
Todd Wang95873902015-05-22 14:21:30 -0700783var runServer = modules.Register(runServerFunc, "runServer")
784
785func runServerFunc(env *modules.Env, args ...string) error {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700786 ctx, shutdown := test.V23Init()
787 defer shutdown()
788 server := InternalNew(ctx, naming.FixedRoutingID(0x55555555))
Asim Shankar4a698282015-03-21 21:59:18 -0700789 principal := testutil.NewPrincipal("test")
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700790 ctx, _ = v23.WithPrincipal(ctx, principal)
791 _, ep, err := server.Listen(ctx, args[0], args[1], principal.BlessingStore().Default())
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700792 if err != nil {
Todd Wang95873902015-05-22 14:21:30 -0700793 fmt.Fprintln(env.Stderr, err)
Cosmos Nicolaou920db002014-10-23 16:57:32 -0700794 return err
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700795 }
Todd Wang95873902015-05-22 14:21:30 -0700796 fmt.Fprintf(env.Stdout, "ENDPOINT=%v\n", ep)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700797 // Live forever (till the process is explicitly killed)
Todd Wang95873902015-05-22 14:21:30 -0700798 modules.WaitForEOF(env.Stdin)
Cosmos Nicolaou920db002014-10-23 16:57:32 -0700799 return nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700800}
801
Todd Wang95873902015-05-22 14:21:30 -0700802var runRLimitedServer = modules.Register(func(env *modules.Env, args ...string) error {
Asim Shankare89936f2015-04-22 17:37:43 -0700803 var rlimit syscall.Rlimit
804 if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit); err != nil {
Todd Wang95873902015-05-22 14:21:30 -0700805 fmt.Fprintln(env.Stderr, err)
Asim Shankare89936f2015-04-22 17:37:43 -0700806 return err
807 }
808 rlimit.Cur = 9
809 if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlimit); err != nil {
Todd Wang95873902015-05-22 14:21:30 -0700810 fmt.Fprintln(env.Stderr, err)
Asim Shankare89936f2015-04-22 17:37:43 -0700811 return err
812 }
Todd Wang95873902015-05-22 14:21:30 -0700813 fmt.Fprintf(env.Stdout, "RLIMIT_NOFILE=%d\n", rlimit.Cur)
814 return runServerFunc(env, args...)
815}, "runRLimitedServer")
Asim Shankare89936f2015-04-22 17:37:43 -0700816
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700817func readLine(f stream.Flow) (string, error) {
818 var result bytes.Buffer
819 var buf [5]byte
820 for {
821 n, err := f.Read(buf[:])
822 result.Write(buf[:n])
823 if err == io.EOF || buf[n-1] == '\n' {
824 return strings.TrimRight(result.String(), "\n"), nil
825 }
826 if err != nil {
827 return "", fmt.Errorf("Read returned (%d, %v)", n, err)
828 }
829 }
830}
831
832func writeLine(f stream.Flow, data string) error {
833 data = data + "\n"
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700834 if n, err := f.Write([]byte(data)); err != nil {
835 return fmt.Errorf("Write returned (%d, %v)", n, err)
836 }
837 return nil
838}
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700839
840func TestRegistration(t *testing.T) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700841 ctx, shutdown := test.V23Init()
842 defer shutdown()
843 server := InternalNew(ctx, naming.FixedRoutingID(0x55555555))
844 client := InternalNew(ctx, naming.FixedRoutingID(0xcccccccc))
Asim Shankar4a698282015-03-21 21:59:18 -0700845 principal := testutil.NewPrincipal("server")
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700846 blessings := principal.BlessingStore().Default()
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700847 ctx, _ = v23.WithPrincipal(ctx, principal)
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700848
Cosmos Nicolaou87c0a552014-12-02 23:05:49 -0800849 dialer := func(_, _ string, _ time.Duration) (net.Conn, error) {
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700850 return nil, fmt.Errorf("tn.Dial")
851 }
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700852 resolver := func(_, _ string) (string, string, error) {
853 return "", "", fmt.Errorf("tn.Resolve")
854 }
Cosmos Nicolaou87c0a552014-12-02 23:05:49 -0800855 listener := func(_, _ string) (net.Listener, error) {
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700856 return nil, fmt.Errorf("tn.Listen")
857 }
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700858 rpc.RegisterProtocol("tn", dialer, resolver, listener)
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700859
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700860 _, _, err := server.Listen(ctx, "tnx", "127.0.0.1:0", blessings)
Cosmos Nicolaou07a736d2015-04-06 11:55:26 -0700861 if err == nil || !strings.Contains(err.Error(), "unknown network: tnx") {
862 t.Fatalf("expected error is missing (%v)", err)
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700863 }
864
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700865 _, _, err = server.Listen(ctx, "tn", "127.0.0.1:0", blessings)
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700866 if err == nil || !strings.Contains(err.Error(), "tn.Listen") {
Cosmos Nicolaou07a736d2015-04-06 11:55:26 -0700867 t.Fatalf("expected error is missing (%v)", err)
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700868 }
869
870 // Need a functional listener to test Dial.
Cosmos Nicolaou87c0a552014-12-02 23:05:49 -0800871 listener = func(_, addr string) (net.Listener, error) {
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700872 return net.Listen("tcp", addr)
873 }
874
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700875 if got, want := rpc.RegisterProtocol("tn", dialer, resolver, listener), true; got != want {
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700876 t.Errorf("got %t, want %t", got, want)
877 }
878
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700879 _, ep, err := server.Listen(ctx, "tn", "127.0.0.1:0", blessings)
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700880 if err != nil {
881 t.Errorf("unexpected error %s", err)
882 }
883
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700884 cctx, _ := v23.WithPrincipal(ctx, testutil.NewPrincipal("client"))
885 _, err = client.Dial(cctx, ep)
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700886 if err == nil || !strings.Contains(err.Error(), "tn.Resolve") {
887 t.Fatalf("expected error is missing (%v)", err)
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700888 }
889}
Asim Shankar7171a252015-03-07 14:41:40 -0800890
891func TestBlessingNamesInEndpoint(t *testing.T) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700892 ctx, shutdown := test.V23Init()
893 defer shutdown()
Asim Shankar7171a252015-03-07 14:41:40 -0800894 var (
Asim Shankar4a698282015-03-21 21:59:18 -0700895 p = testutil.NewPrincipal("default")
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700896 b, _ = p.BlessSelf("dev.v.io/users/foo@bar.com/devices/desktop/app/myapp")
Asim Shankar7171a252015-03-07 14:41:40 -0800897
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700898 server = InternalNew(ctx, naming.FixedRoutingID(0x1))
Asim Shankar7171a252015-03-07 14:41:40 -0800899
900 tests = []struct {
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700901 principal security.Principal
902 blessings security.Blessings
903 blessingNames []string
904 err bool
Asim Shankar7171a252015-03-07 14:41:40 -0800905 }{
906 {
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700907 // provided blessings should match returned output.
908 principal: p,
909 blessings: b,
910 blessingNames: []string{"dev.v.io/users/foo@bar.com/devices/desktop/app/myapp"},
Asim Shankar7171a252015-03-07 14:41:40 -0800911 },
912 {
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700913 // It is an error to provide a principal without providing blessings.
Suharsh Sivakumar59c423c2015-03-11 14:06:03 -0700914 principal: p,
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700915 blessings: security.Blessings{},
Suharsh Sivakumar59c423c2015-03-11 14:06:03 -0700916 err: true,
Asim Shankar7171a252015-03-07 14:41:40 -0800917 },
918 {
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700919 // It is an error to provide inconsistent blessings and principal
Asim Shankar4a698282015-03-21 21:59:18 -0700920 principal: testutil.NewPrincipal("random"),
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700921 blessings: b,
Suharsh Sivakumar59c423c2015-03-11 14:06:03 -0700922 err: true,
Asim Shankar7171a252015-03-07 14:41:40 -0800923 },
924 }
925 )
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700926
Asim Shankar7171a252015-03-07 14:41:40 -0800927 // p must recognize its own blessings!
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700928 p.AddToRoots(b)
Asim Shankar7171a252015-03-07 14:41:40 -0800929 for idx, test := range tests {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700930 sctx, _ := v23.WithPrincipal(ctx, test.principal)
931 ln, ep, err := server.Listen(sctx, "tcp", "127.0.0.1:0", test.blessings)
Asim Shankar7171a252015-03-07 14:41:40 -0800932 if (err != nil) != test.err {
933 t.Errorf("test #%d: Got error %v, wanted error: %v", idx, err, test.err)
934 }
935 if err != nil {
936 continue
937 }
938 ln.Close()
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700939 got, want := ep.BlessingNames(), test.blessingNames
Suharsh Sivakumarad1d4192015-03-09 16:48:10 -0700940 sort.Strings(got)
941 sort.Strings(want)
942 if !reflect.DeepEqual(got, want) {
Asim Shankar7171a252015-03-07 14:41:40 -0800943 t.Errorf("test #%d: Got %v, want %v", idx, got, want)
944 }
945 }
946}
Asim Shankare89936f2015-04-22 17:37:43 -0700947
948func TestVIFCleanupWhenFDLimitIsReached(t *testing.T) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700949 ctx, shutdown := test.V23Init()
950 defer shutdown()
Asim Shankare89936f2015-04-22 17:37:43 -0700951 sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
952 if err != nil {
953 t.Fatal(err)
954 }
955 defer sh.Cleanup(nil, nil)
Todd Wang95873902015-05-22 14:21:30 -0700956 h, err := sh.Start(nil, runRLimitedServer, "--logtostderr=true", "tcp", "127.0.0.1:0")
Asim Shankare89936f2015-04-22 17:37:43 -0700957 if err != nil {
958 t.Fatal(err)
959 }
960 defer h.CloseStdin()
961 stdout := expect.NewSession(t, h.Stdout(), time.Minute)
962 nfiles, err := strconv.Atoi(stdout.ExpectVar("RLIMIT_NOFILE"))
963 if stdout.Error() != nil {
964 t.Fatal(stdout.Error())
965 }
966 if err != nil {
967 t.Fatal(err)
968 }
969 epstr := stdout.ExpectVar("ENDPOINT")
970 if stdout.Error() != nil {
971 t.Fatal(stdout.Error())
972 }
973 ep, err := inaming.NewEndpoint(epstr)
974 if err != nil {
975 t.Fatal(err)
976 }
977 // Different client processes (represented by different stream managers
978 // in this test) should be able to make progress, even if the server
979 // has reached its file descriptor limit.
980 nattempts := 0
981 for i := 0; i < 2*nfiles; i++ {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700982 client := InternalNew(ctx, naming.FixedRoutingID(uint64(i)))
Asim Shankare89936f2015-04-22 17:37:43 -0700983 defer client.Shutdown()
984 principal := testutil.NewPrincipal(fmt.Sprintf("client%d", i))
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700985 cctx, _ := v23.WithPrincipal(ctx, principal)
Asim Shankare89936f2015-04-22 17:37:43 -0700986 connected := false
987 for !connected {
988 nattempts++
989 // If the client connection reached the server when it
990 // was at its limit, it might fail. However, this
991 // failure will trigger the "kill connections" logic at
992 // the server and eventually the client should succeed.
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700993 vc, err := client.Dial(cctx, ep)
Asim Shankare89936f2015-04-22 17:37:43 -0700994 if err != nil {
995 continue
996 }
997 // Establish a flow to prevent the VC (and thus the
998 // underlying VIF) from being garbage collected as an
999 // "inactive" connection.
1000 flow, err := vc.Connect()
1001 if err != nil {
1002 continue
1003 }
1004 defer flow.Close()
1005 connected = true
1006 }
1007 }
1008 var stderr bytes.Buffer
1009 if err := h.Shutdown(nil, &stderr); err != nil {
Cosmos Nicolaouc818b802015-06-05 15:52:45 -07001010 t.Logf("%s", stderr.String())
Asim Shankare89936f2015-04-22 17:37:43 -07001011 t.Fatal(err)
1012 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -07001013 fmt.Fprintf(os.Stderr, "11\n")
Matt Rosencrantza40f12a2015-04-24 11:07:55 -07001014 if log := expect.NewSession(t, bytes.NewReader(stderr.Bytes()), time.Minute).ExpectSetEventuallyRE("listener.go.*Killing [1-9][0-9]* Conns"); len(log) == 0 {
1015 t.Errorf("Failed to find log message talking about killing Conns in:\n%v", stderr.String())
Asim Shankare89936f2015-04-22 17:37:43 -07001016 }
1017 t.Logf("Server FD limit:%d", nfiles)
1018 t.Logf("Client connection attempts: %d", nattempts)
1019}
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001020
1021func TestConcurrentDials(t *testing.T) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -07001022 ctx, shutdown := test.V23Init()
1023 defer shutdown()
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001024 // Concurrent Dials to the same network, address should only result in one VIF.
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -07001025 server := InternalNew(ctx, naming.FixedRoutingID(0x55555555))
1026 client := InternalNew(ctx, naming.FixedRoutingID(0xcccccccc))
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001027 principal := testutil.NewPrincipal("test")
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -07001028 ctx, _ = v23.WithPrincipal(ctx, principal)
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001029
1030 // Using "tcp4" instead of "tcp" because the latter can end up with IPv6
1031 // addresses and our Google Compute Engine integration test machines cannot
1032 // resolve IPv6 addresses.
1033 // As of April 2014, https://developers.google.com/compute/docs/networking
1034 // said that IPv6 is not yet supported.
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -07001035 ln, ep, err := server.Listen(ctx, "tcp4", "127.0.0.1:0", principal.BlessingStore().Default())
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001036 if err != nil {
1037 t.Fatal(err)
1038 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -07001039 var wg sync.WaitGroup
1040 wg.Add(1)
1041 go acceptLoop(&wg, ln)
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001042
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001043 nep := &inaming.Endpoint{
1044 Protocol: ep.Addr().Network(),
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -07001045 Address: ep.Addr().String(),
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001046 RID: ep.RoutingID(),
1047 }
1048
1049 // Dial multiple VCs
1050 errCh := make(chan error, 10)
1051 for i := 0; i < 10; i++ {
1052 go func() {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -07001053 cctx, _ := v23.WithPrincipal(ctx, testutil.NewPrincipal("client"))
1054 _, err := client.Dial(cctx, nep)
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001055 errCh <- err
1056 }()
1057 }
1058 for i := 0; i < 10; i++ {
Jungho Ahn19e84b22015-05-18 13:22:27 -07001059 if err := <-errCh; err != nil {
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001060 t.Fatal(err)
1061 }
1062 }
1063 // They should all be on the same VIF.
1064 if n := numVIFs(client); n != 1 {
1065 t.Errorf("Client has %d VIFs, want 1\n%v", n, debugString(client))
1066 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -07001067 ln.Close()
1068 wg.Wait()
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001069}