blob: 2ec4eb446d8a0b3e1d597bddb9897c888722a443 [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 }()
450
451 _, err = net.Dial(ep.Addr().Network(), ep.Addr().String())
452 if err != nil {
453 t.Fatalf("net.Dial failed: %v", err)
454 }
455
456 // Trigger the start timers.
457 triggerTimers()
458
459 // No VC is opened. The VIF should be closed after start timeout.
Jungho Ahncc9d5722015-04-22 10:13:04 -0700460 for range time.Tick(startTime) {
461 if numVIFs(server) == 0 {
462 break
Jungho Ahn6ab655f2015-04-14 18:27:09 -0700463 }
464 }
Jungho Ahn6ab655f2015-04-14 18:27:09 -0700465}
466
Jungho Ahncd175b82015-03-27 14:29:40 -0700467func testIdleTimeout(t *testing.T, testServer bool) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700468 ctx, shutdown := test.V23Init()
469 defer shutdown()
Jungho Ahncd175b82015-03-27 14:29:40 -0700470 const (
471 idleTime = 10 * time.Millisecond
472 // We use a long wait time here since it takes some time to handle VC close
473 // especially in race testing.
474 waitTime = 150 * time.Millisecond
475 )
476
477 var (
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700478 server = InternalNew(ctx, naming.FixedRoutingID(0x55555555))
479 client = InternalNew(ctx, naming.FixedRoutingID(0xcccccccc))
Jungho Ahncd175b82015-03-27 14:29:40 -0700480 pclient = testutil.NewPrincipal("client")
481 pserver = testutil.NewPrincipal("server")
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700482 cctx, _ = v23.WithPrincipal(ctx, pclient)
483 sctx, _ = v23.WithPrincipal(ctx, pserver)
Jungho Ahncd175b82015-03-27 14:29:40 -0700484
485 opts []stream.VCOpt
486 lopts []stream.ListenerOpt
487 )
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700488
Jungho Ahncd175b82015-03-27 14:29:40 -0700489 if testServer {
490 lopts = []stream.ListenerOpt{vc.IdleTimeout{idleTime}}
491 } else {
492 opts = []stream.VCOpt{vc.IdleTimeout{idleTime}}
493 }
494
495 // Pause the idle timers.
496 triggerTimers := vif.SetFakeTimers()
497
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700498 ln, ep, err := server.Listen(sctx, "tcp", "127.0.0.1:0", pserver.BlessingStore().Default(), lopts...)
Jungho Ahncd175b82015-03-27 14:29:40 -0700499 if err != nil {
500 t.Fatal(err)
501 }
Jungho Ahn19e84b22015-05-18 13:22:27 -0700502 errch := make(chan error)
Jungho Ahncd175b82015-03-27 14:29:40 -0700503 go func() {
504 for {
505 _, err := ln.Accept()
Jungho Ahn19e84b22015-05-18 13:22:27 -0700506 errch <- err
Jungho Ahncd175b82015-03-27 14:29:40 -0700507 }
508 }()
509
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700510 vc, err := client.Dial(cctx, ep, opts...)
Jungho Ahncd175b82015-03-27 14:29:40 -0700511 if err != nil {
512 t.Fatalf("client.Dial(%q) failed: %v", ep, err)
513 }
514 f, err := vc.Connect()
515 if f == nil || err != nil {
516 t.Fatalf("vc.Connect failed: (%v, %v)", f, err)
517 }
Jungho Ahn19e84b22015-05-18 13:22:27 -0700518 // Wait until the server accepts the flow or fails.
519 if err = <-errch; err != nil {
520 t.Fatalf("ln.Accept failed: %v", err)
521 }
Jungho Ahncd175b82015-03-27 14:29:40 -0700522
523 // Trigger the idle timers.
524 triggerTimers()
525
526 // One active flow. The VIF should be kept open.
527 time.Sleep(waitTime)
528 if n := numVIFs(client); n != 1 {
529 t.Errorf("Client has %d VIFs; want 1\n%v", n, debugString(client))
530 }
531 if n := numVIFs(server); n != 1 {
532 t.Errorf("Server has %d VIFs; want 1\n%v", n, debugString(server))
533 }
534
535 f.Close()
536
537 // The flow has been closed. The VIF should be closed after idle timeout.
Jungho Ahncc9d5722015-04-22 10:13:04 -0700538 for range time.Tick(idleTime) {
539 if numVIFs(client) == 0 && numVIFs(server) == 0 {
540 break
Jungho Ahncd175b82015-03-27 14:29:40 -0700541 }
542 }
Jungho Ahncd175b82015-03-27 14:29:40 -0700543}
544
545func TestIdleTimeout(t *testing.T) { testIdleTimeout(t, false) }
546func TestIdleTimeoutServer(t *testing.T) { testIdleTimeout(t, true) }
547
Andres Erbsenffa45742014-08-13 10:13:11 -0700548/* TLS + resumption + channel bindings is broken: <https://secure-resumption.com/#channelbindings>.
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700549func TestSessionTicketCache(t *testing.T) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700550 server := InternalNew(naming.FixedRoutingID(0x55555555))
Asim Shankar4a698282015-03-21 21:59:18 -0700551 _, ep, err := server.Listen("tcp", "127.0.0.1:0", testutil.NewPrincipal("server"))
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700552 if err != nil {
553 t.Fatal(err)
554 }
555
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700556 client := InternalNew(naming.FixedRoutingID(0xcccccccc))
Asim Shankar4a698282015-03-21 21:59:18 -0700557 if _, err = client.Dial(ep, testutil.NewPrincipal("TestSessionTicketCacheClient")); err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700558 t.Fatalf("Dial(%q) failed: %v", ep, err)
559 }
560
561 if _, ok := client.(*manager).sessionCache.Get(ep.String()); !ok {
562 t.Fatalf("SessionTicket from TLS handshake not cached")
563 }
564}
Andres Erbsenffa45742014-08-13 10:13:11 -0700565*/
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700566
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800567func testMultipleVCs(t *testing.T, protocol string) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700568 ctx, shutdown := test.V23Init()
569 defer shutdown()
570 server := InternalNew(ctx, naming.FixedRoutingID(0x55555555))
571 client := InternalNew(ctx, naming.FixedRoutingID(0xcccccccc))
Asim Shankar4a698282015-03-21 21:59:18 -0700572 principal := testutil.NewPrincipal("test")
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700573 sctx, _ := v23.WithPrincipal(ctx, principal)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700574
575 const nVCs = 2
576 const data = "bugs bunny"
577
578 // Have the server read from each flow and write to rchan.
579 rchan := make(chan string)
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700580 ln, ep, err := server.Listen(sctx, protocol, "127.0.0.1:0", principal.BlessingStore().Default())
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700581 if err != nil {
582 t.Fatal(err)
583 }
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800584
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700585 read := func(flow stream.Flow, c chan string) {
586 var buf bytes.Buffer
587 var tmp [1024]byte
588 for {
589 n, err := flow.Read(tmp[:])
590 buf.Write(tmp[:n])
591 if err == io.EOF {
592 c <- buf.String()
593 return
594 }
595 if err != nil {
596 t.Error(err)
597 return
598 }
599 }
600 }
601 go func() {
602 for i := 0; i < nVCs; i++ {
603 flow, err := ln.Accept()
604 if err != nil {
605 t.Error(err)
606 rchan <- ""
607 continue
608 }
609 go read(flow, rchan)
610 }
611 }()
612
613 // Have the client establish nVCs and a flow on each.
614 var vcs [nVCs]stream.VC
615 for i := 0; i < nVCs; i++ {
616 var err error
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700617 pclient := testutil.NewPrincipal("client")
618 cctx, _ := v23.WithPrincipal(ctx, pclient)
619 vcs[i], err = client.Dial(cctx, ep)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700620 if err != nil {
621 t.Fatal(err)
622 }
623 }
624 write := func(vc stream.VC) {
625 if err != nil {
626 ln.Close()
627 t.Error(err)
628 return
629 }
630 flow, err := vc.Connect()
631 if err != nil {
632 ln.Close()
633 t.Error(err)
634 return
635 }
636 defer flow.Close()
637 if _, err := flow.Write([]byte(data)); err != nil {
638 ln.Close()
639 t.Error(err)
640 return
641 }
642 }
643 for _, vc := range vcs {
644 go write(vc)
645 }
646 for i := 0; i < nVCs; i++ {
647 if got := <-rchan; got != data {
648 t.Errorf("Got %q want %q", got, data)
649 }
650 }
651}
652
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800653func TestMultipleVCs(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800654 testMultipleVCs(t, "tcp")
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800655}
656
657func TestMultipleVCsWS(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800658 testMultipleVCs(t, "ws")
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800659}
660
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700661func TestAddressResolution(t *testing.T) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700662 ctx, shutdown := test.V23Init()
663 defer shutdown()
664 server := InternalNew(ctx, naming.FixedRoutingID(0x55555555))
665 client := InternalNew(ctx, naming.FixedRoutingID(0xcccccccc))
Asim Shankar4a698282015-03-21 21:59:18 -0700666 principal := testutil.NewPrincipal("test")
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700667 sctx, _ := v23.WithPrincipal(ctx, principal)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700668
Adam Sadovsky5181bdb2014-08-13 10:29:11 -0700669 // Using "tcp4" instead of "tcp" because the latter can end up with IPv6
670 // addresses and our Google Compute Engine integration test machines cannot
671 // resolve IPv6 addresses.
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700672 // As of April 2014, https://developers.google.com/compute/docs/networking
673 // said that IPv6 is not yet supported.
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700674 ln, ep, err := server.Listen(sctx, "tcp4", "127.0.0.1:0", principal.BlessingStore().Default())
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700675 if err != nil {
676 t.Fatal(err)
677 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700678 var wg sync.WaitGroup
679 wg.Add(1)
680 go acceptLoop(&wg, ln)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700681
Adam Sadovsky5181bdb2014-08-13 10:29:11 -0700682 // We'd like an endpoint that contains an address that's different than the
683 // one used for the connection. In practice this is awkward to achieve since
684 // we don't want to listen on ":0" since that will annoy firewalls. Instead we
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700685 // create a endpoint with "localhost", which will result in an endpoint that
686 // doesn't contain 127.0.0.1.
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700687 _, port, _ := net.SplitHostPort(ep.Addr().String())
Matt Rosencrantzc16339c2015-04-23 10:47:06 -0700688 nep := &inaming.Endpoint{
689 Protocol: ep.Addr().Network(),
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700690 Address: net.JoinHostPort("localhost", port),
Matt Rosencrantzc16339c2015-04-23 10:47:06 -0700691 RID: ep.RoutingID(),
692 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700693
694 // Dial multiple VCs
695 for i := 0; i < 2; i++ {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700696 pclient := testutil.NewPrincipal("client")
697 cctx, _ := v23.WithPrincipal(ctx, pclient)
698 if _, err = client.Dial(cctx, nep); err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700699 t.Fatalf("Dial #%d failed: %v", i, err)
700 }
701 }
702 // They should all be on the same VIF.
703 if n := numVIFs(client); n != 1 {
704 t.Errorf("Client has %d VIFs, want 1\n%v", n, debugString(client))
705 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700706 ln.Close()
707 wg.Wait()
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700708 // TODO(ashankar): While a VIF can be re-used to Dial from the server
709 // to the client, currently there is no way to have the client "listen"
710 // on the same VIF. It can listen on a VC for new flows, but it cannot
711 // listen on an established VIF for new VCs. Figure this out?
712}
713
714func TestServerRestartDuringClientLifetime(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800715 testServerRestartDuringClientLifetime(t, "tcp")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700716}
717
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800718func TestServerRestartDuringClientLifetimeWS(t *testing.T) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800719 testServerRestartDuringClientLifetime(t, "ws")
720}
721
722func testServerRestartDuringClientLifetime(t *testing.T, protocol string) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700723 ctx, shutdown := test.V23Init()
724 defer shutdown()
725 client := InternalNew(ctx, naming.FixedRoutingID(0xcccccccc))
Asim Shankar4a698282015-03-21 21:59:18 -0700726 pclient := testutil.NewPrincipal("client")
Jungho Ahn19e84b22015-05-18 13:22:27 -0700727 pclient2 := testutil.NewPrincipal("client2")
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700728 ctx1, _ := v23.WithPrincipal(ctx, pclient)
729 ctx2, _ := v23.WithPrincipal(ctx, pclient2)
730
Cosmos Nicolaou9e909842015-03-17 11:58:59 -0700731 sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
Cosmos Nicolaou344cc4a2014-11-26 15:38:43 -0800732 if err != nil {
733 t.Fatalf("unexpected error: %s", err)
734 }
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800735 defer sh.Cleanup(nil, nil)
Todd Wang95873902015-05-22 14:21:30 -0700736 h, err := sh.Start(nil, runServer, protocol, "127.0.0.1:0")
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800737 if err != nil {
738 t.Fatalf("unexpected error: %s", err)
739 }
Asim Shankare89936f2015-04-22 17:37:43 -0700740 epstr := expect.NewSession(t, h.Stdout(), time.Minute).ExpectVar("ENDPOINT")
741 ep, err := inaming.NewEndpoint(epstr)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800742 if err != nil {
Asim Shankare89936f2015-04-22 17:37:43 -0700743 t.Fatalf("inaming.NewEndpoint(%q): %v", epstr, err)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800744 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700745 if _, err := client.Dial(ctx1, ep); err != nil {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800746 t.Fatal(err)
747 }
748 h.Shutdown(nil, os.Stderr)
749
Jungho Ahn19e84b22015-05-18 13:22:27 -0700750 // A new VC cannot be created since the server is dead. Note that we need to
751 // use a different principal since the client doesn't expect a response from
752 // a server when re-using VIF authentication.
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700753 if _, err := client.Dial(ctx2, ep); err == nil {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800754 t.Fatal("Expected client.Dial to fail since server is dead")
755 }
756
Todd Wang95873902015-05-22 14:21:30 -0700757 h, err = sh.Start(nil, runServer, protocol, ep.Addr().String())
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800758 if err != nil {
759 t.Fatalf("unexpected error: %s", err)
760 }
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800761 // Restarting the server, listening on the same address as before
Asim Shankare89936f2015-04-22 17:37:43 -0700762 ep2, err := inaming.NewEndpoint(expect.NewSession(t, h.Stdout(), time.Minute).ExpectVar("ENDPOINT"))
763 if err != nil {
764 t.Fatal(err)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800765 }
Asim Shankare89936f2015-04-22 17:37:43 -0700766 if got, want := ep.Addr().String(), ep2.Addr().String(); got != want {
767 t.Fatalf("Got %q, want %q", got, want)
768 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700769 if _, err := client.Dial(ctx1, ep2); err != nil {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800770 t.Fatal(err)
771 }
772}
773
Todd Wang95873902015-05-22 14:21:30 -0700774var runServer = modules.Register(runServerFunc, "runServer")
775
776func runServerFunc(env *modules.Env, args ...string) error {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700777 ctx, shutdown := test.V23Init()
778 defer shutdown()
779 server := InternalNew(ctx, naming.FixedRoutingID(0x55555555))
Asim Shankar4a698282015-03-21 21:59:18 -0700780 principal := testutil.NewPrincipal("test")
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700781 ctx, _ = v23.WithPrincipal(ctx, principal)
782 _, ep, err := server.Listen(ctx, args[0], args[1], principal.BlessingStore().Default())
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700783 if err != nil {
Todd Wang95873902015-05-22 14:21:30 -0700784 fmt.Fprintln(env.Stderr, err)
Cosmos Nicolaou920db002014-10-23 16:57:32 -0700785 return err
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700786 }
Todd Wang95873902015-05-22 14:21:30 -0700787 fmt.Fprintf(env.Stdout, "ENDPOINT=%v\n", ep)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700788 // Live forever (till the process is explicitly killed)
Todd Wang95873902015-05-22 14:21:30 -0700789 modules.WaitForEOF(env.Stdin)
Cosmos Nicolaou920db002014-10-23 16:57:32 -0700790 return nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700791}
792
Todd Wang95873902015-05-22 14:21:30 -0700793var runRLimitedServer = modules.Register(func(env *modules.Env, args ...string) error {
Asim Shankare89936f2015-04-22 17:37:43 -0700794 var rlimit syscall.Rlimit
795 if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit); err != nil {
Todd Wang95873902015-05-22 14:21:30 -0700796 fmt.Fprintln(env.Stderr, err)
Asim Shankare89936f2015-04-22 17:37:43 -0700797 return err
798 }
799 rlimit.Cur = 9
800 if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlimit); err != nil {
Todd Wang95873902015-05-22 14:21:30 -0700801 fmt.Fprintln(env.Stderr, err)
Asim Shankare89936f2015-04-22 17:37:43 -0700802 return err
803 }
Todd Wang95873902015-05-22 14:21:30 -0700804 fmt.Fprintf(env.Stdout, "RLIMIT_NOFILE=%d\n", rlimit.Cur)
805 return runServerFunc(env, args...)
806}, "runRLimitedServer")
Asim Shankare89936f2015-04-22 17:37:43 -0700807
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700808func readLine(f stream.Flow) (string, error) {
809 var result bytes.Buffer
810 var buf [5]byte
811 for {
812 n, err := f.Read(buf[:])
813 result.Write(buf[:n])
814 if err == io.EOF || buf[n-1] == '\n' {
815 return strings.TrimRight(result.String(), "\n"), nil
816 }
817 if err != nil {
818 return "", fmt.Errorf("Read returned (%d, %v)", n, err)
819 }
820 }
821}
822
823func writeLine(f stream.Flow, data string) error {
824 data = data + "\n"
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700825 if n, err := f.Write([]byte(data)); err != nil {
826 return fmt.Errorf("Write returned (%d, %v)", n, err)
827 }
828 return nil
829}
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700830
831func TestRegistration(t *testing.T) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700832 ctx, shutdown := test.V23Init()
833 defer shutdown()
834 server := InternalNew(ctx, naming.FixedRoutingID(0x55555555))
835 client := InternalNew(ctx, naming.FixedRoutingID(0xcccccccc))
Asim Shankar4a698282015-03-21 21:59:18 -0700836 principal := testutil.NewPrincipal("server")
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700837 blessings := principal.BlessingStore().Default()
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700838 ctx, _ = v23.WithPrincipal(ctx, principal)
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700839
Cosmos Nicolaou87c0a552014-12-02 23:05:49 -0800840 dialer := func(_, _ string, _ time.Duration) (net.Conn, error) {
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700841 return nil, fmt.Errorf("tn.Dial")
842 }
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700843 resolver := func(_, _ string) (string, string, error) {
844 return "", "", fmt.Errorf("tn.Resolve")
845 }
Cosmos Nicolaou87c0a552014-12-02 23:05:49 -0800846 listener := func(_, _ string) (net.Listener, error) {
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700847 return nil, fmt.Errorf("tn.Listen")
848 }
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700849 rpc.RegisterProtocol("tn", dialer, resolver, listener)
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700850
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700851 _, _, err := server.Listen(ctx, "tnx", "127.0.0.1:0", blessings)
Cosmos Nicolaou07a736d2015-04-06 11:55:26 -0700852 if err == nil || !strings.Contains(err.Error(), "unknown network: tnx") {
853 t.Fatalf("expected error is missing (%v)", err)
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700854 }
855
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700856 _, _, err = server.Listen(ctx, "tn", "127.0.0.1:0", blessings)
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700857 if err == nil || !strings.Contains(err.Error(), "tn.Listen") {
Cosmos Nicolaou07a736d2015-04-06 11:55:26 -0700858 t.Fatalf("expected error is missing (%v)", err)
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700859 }
860
861 // Need a functional listener to test Dial.
Cosmos Nicolaou87c0a552014-12-02 23:05:49 -0800862 listener = func(_, addr string) (net.Listener, error) {
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700863 return net.Listen("tcp", addr)
864 }
865
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700866 if got, want := rpc.RegisterProtocol("tn", dialer, resolver, listener), true; got != want {
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700867 t.Errorf("got %t, want %t", got, want)
868 }
869
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700870 _, ep, err := server.Listen(ctx, "tn", "127.0.0.1:0", blessings)
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700871 if err != nil {
872 t.Errorf("unexpected error %s", err)
873 }
874
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700875 cctx, _ := v23.WithPrincipal(ctx, testutil.NewPrincipal("client"))
876 _, err = client.Dial(cctx, ep)
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700877 if err == nil || !strings.Contains(err.Error(), "tn.Resolve") {
878 t.Fatalf("expected error is missing (%v)", err)
Cosmos Nicolaou5129fcb2014-08-22 11:52:25 -0700879 }
880}
Asim Shankar7171a252015-03-07 14:41:40 -0800881
882func TestBlessingNamesInEndpoint(t *testing.T) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700883 ctx, shutdown := test.V23Init()
884 defer shutdown()
Asim Shankar7171a252015-03-07 14:41:40 -0800885 var (
Asim Shankar4a698282015-03-21 21:59:18 -0700886 p = testutil.NewPrincipal("default")
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700887 b, _ = p.BlessSelf("dev.v.io/users/foo@bar.com/devices/desktop/app/myapp")
Asim Shankar7171a252015-03-07 14:41:40 -0800888
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700889 server = InternalNew(ctx, naming.FixedRoutingID(0x1))
Asim Shankar7171a252015-03-07 14:41:40 -0800890
891 tests = []struct {
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700892 principal security.Principal
893 blessings security.Blessings
894 blessingNames []string
895 err bool
Asim Shankar7171a252015-03-07 14:41:40 -0800896 }{
897 {
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700898 // provided blessings should match returned output.
899 principal: p,
900 blessings: b,
901 blessingNames: []string{"dev.v.io/users/foo@bar.com/devices/desktop/app/myapp"},
Asim Shankar7171a252015-03-07 14:41:40 -0800902 },
903 {
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700904 // It is an error to provide a principal without providing blessings.
Suharsh Sivakumar59c423c2015-03-11 14:06:03 -0700905 principal: p,
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700906 blessings: security.Blessings{},
Suharsh Sivakumar59c423c2015-03-11 14:06:03 -0700907 err: true,
Asim Shankar7171a252015-03-07 14:41:40 -0800908 },
909 {
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700910 // It is an error to provide inconsistent blessings and principal
Asim Shankar4a698282015-03-21 21:59:18 -0700911 principal: testutil.NewPrincipal("random"),
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700912 blessings: b,
Suharsh Sivakumar59c423c2015-03-11 14:06:03 -0700913 err: true,
Asim Shankar7171a252015-03-07 14:41:40 -0800914 },
915 }
916 )
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700917
Asim Shankar7171a252015-03-07 14:41:40 -0800918 // p must recognize its own blessings!
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700919 p.AddToRoots(b)
Asim Shankar7171a252015-03-07 14:41:40 -0800920 for idx, test := range tests {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700921 sctx, _ := v23.WithPrincipal(ctx, test.principal)
922 ln, ep, err := server.Listen(sctx, "tcp", "127.0.0.1:0", test.blessings)
Asim Shankar7171a252015-03-07 14:41:40 -0800923 if (err != nil) != test.err {
924 t.Errorf("test #%d: Got error %v, wanted error: %v", idx, err, test.err)
925 }
926 if err != nil {
927 continue
928 }
929 ln.Close()
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -0700930 got, want := ep.BlessingNames(), test.blessingNames
Suharsh Sivakumarad1d4192015-03-09 16:48:10 -0700931 sort.Strings(got)
932 sort.Strings(want)
933 if !reflect.DeepEqual(got, want) {
Asim Shankar7171a252015-03-07 14:41:40 -0800934 t.Errorf("test #%d: Got %v, want %v", idx, got, want)
935 }
936 }
937}
Asim Shankare89936f2015-04-22 17:37:43 -0700938
939func TestVIFCleanupWhenFDLimitIsReached(t *testing.T) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700940 ctx, shutdown := test.V23Init()
941 defer shutdown()
Asim Shankare89936f2015-04-22 17:37:43 -0700942 sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
943 if err != nil {
944 t.Fatal(err)
945 }
946 defer sh.Cleanup(nil, nil)
Todd Wang95873902015-05-22 14:21:30 -0700947 h, err := sh.Start(nil, runRLimitedServer, "--logtostderr=true", "tcp", "127.0.0.1:0")
Asim Shankare89936f2015-04-22 17:37:43 -0700948 if err != nil {
949 t.Fatal(err)
950 }
951 defer h.CloseStdin()
952 stdout := expect.NewSession(t, h.Stdout(), time.Minute)
953 nfiles, err := strconv.Atoi(stdout.ExpectVar("RLIMIT_NOFILE"))
954 if stdout.Error() != nil {
955 t.Fatal(stdout.Error())
956 }
957 if err != nil {
958 t.Fatal(err)
959 }
960 epstr := stdout.ExpectVar("ENDPOINT")
961 if stdout.Error() != nil {
962 t.Fatal(stdout.Error())
963 }
964 ep, err := inaming.NewEndpoint(epstr)
965 if err != nil {
966 t.Fatal(err)
967 }
968 // Different client processes (represented by different stream managers
969 // in this test) should be able to make progress, even if the server
970 // has reached its file descriptor limit.
971 nattempts := 0
972 for i := 0; i < 2*nfiles; i++ {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700973 client := InternalNew(ctx, naming.FixedRoutingID(uint64(i)))
Asim Shankare89936f2015-04-22 17:37:43 -0700974 defer client.Shutdown()
975 principal := testutil.NewPrincipal(fmt.Sprintf("client%d", i))
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700976 cctx, _ := v23.WithPrincipal(ctx, principal)
Asim Shankare89936f2015-04-22 17:37:43 -0700977 connected := false
978 for !connected {
979 nattempts++
980 // If the client connection reached the server when it
981 // was at its limit, it might fail. However, this
982 // failure will trigger the "kill connections" logic at
983 // the server and eventually the client should succeed.
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700984 vc, err := client.Dial(cctx, ep)
Asim Shankare89936f2015-04-22 17:37:43 -0700985 if err != nil {
986 continue
987 }
988 // Establish a flow to prevent the VC (and thus the
989 // underlying VIF) from being garbage collected as an
990 // "inactive" connection.
991 flow, err := vc.Connect()
992 if err != nil {
993 continue
994 }
995 defer flow.Close()
996 connected = true
997 }
998 }
999 var stderr bytes.Buffer
1000 if err := h.Shutdown(nil, &stderr); err != nil {
Cosmos Nicolaouc818b802015-06-05 15:52:45 -07001001 t.Logf("%s", stderr.String())
Asim Shankare89936f2015-04-22 17:37:43 -07001002 t.Fatal(err)
1003 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -07001004 fmt.Fprintf(os.Stderr, "11\n")
Matt Rosencrantza40f12a2015-04-24 11:07:55 -07001005 if log := expect.NewSession(t, bytes.NewReader(stderr.Bytes()), time.Minute).ExpectSetEventuallyRE("listener.go.*Killing [1-9][0-9]* Conns"); len(log) == 0 {
1006 t.Errorf("Failed to find log message talking about killing Conns in:\n%v", stderr.String())
Asim Shankare89936f2015-04-22 17:37:43 -07001007 }
1008 t.Logf("Server FD limit:%d", nfiles)
1009 t.Logf("Client connection attempts: %d", nattempts)
1010}
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001011
1012func TestConcurrentDials(t *testing.T) {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -07001013 ctx, shutdown := test.V23Init()
1014 defer shutdown()
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001015 // Concurrent Dials to the same network, address should only result in one VIF.
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -07001016 server := InternalNew(ctx, naming.FixedRoutingID(0x55555555))
1017 client := InternalNew(ctx, naming.FixedRoutingID(0xcccccccc))
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001018 principal := testutil.NewPrincipal("test")
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -07001019 ctx, _ = v23.WithPrincipal(ctx, principal)
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001020
1021 // Using "tcp4" instead of "tcp" because the latter can end up with IPv6
1022 // addresses and our Google Compute Engine integration test machines cannot
1023 // resolve IPv6 addresses.
1024 // As of April 2014, https://developers.google.com/compute/docs/networking
1025 // said that IPv6 is not yet supported.
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -07001026 ln, ep, err := server.Listen(ctx, "tcp4", "127.0.0.1:0", principal.BlessingStore().Default())
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001027 if err != nil {
1028 t.Fatal(err)
1029 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -07001030 var wg sync.WaitGroup
1031 wg.Add(1)
1032 go acceptLoop(&wg, ln)
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001033
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001034 nep := &inaming.Endpoint{
1035 Protocol: ep.Addr().Network(),
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -07001036 Address: ep.Addr().String(),
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001037 RID: ep.RoutingID(),
1038 }
1039
1040 // Dial multiple VCs
1041 errCh := make(chan error, 10)
1042 for i := 0; i < 10; i++ {
1043 go func() {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -07001044 cctx, _ := v23.WithPrincipal(ctx, testutil.NewPrincipal("client"))
1045 _, err := client.Dial(cctx, nep)
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001046 errCh <- err
1047 }()
1048 }
1049 for i := 0; i < 10; i++ {
Jungho Ahn19e84b22015-05-18 13:22:27 -07001050 if err := <-errCh; err != nil {
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001051 t.Fatal(err)
1052 }
1053 }
1054 // They should all be on the same VIF.
1055 if n := numVIFs(client); n != 1 {
1056 t.Errorf("Client has %d VIFs, want 1\n%v", n, debugString(client))
1057 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -07001058 ln.Close()
1059 wg.Wait()
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -07001060}