Jiri Simsa | d7616c9 | 2015-03-24 23:44:30 -0700 | [diff] [blame] | 1 | // 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 5 | package manager |
| 6 | |
| 7 | import ( |
| 8 | "bytes" |
| 9 | "fmt" |
| 10 | "io" |
| 11 | "net" |
Cosmos Nicolaou | 920db00 | 2014-10-23 16:57:32 -0700 | [diff] [blame] | 12 | "os" |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 13 | "reflect" |
| 14 | "runtime" |
Suharsh Sivakumar | ad1d419 | 2015-03-09 16:48:10 -0700 | [diff] [blame] | 15 | "sort" |
Asim Shankar | e89936f | 2015-04-22 17:37:43 -0700 | [diff] [blame] | 16 | "strconv" |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 17 | "strings" |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 18 | "sync" |
Asim Shankar | e89936f | 2015-04-22 17:37:43 -0700 | [diff] [blame] | 19 | "syscall" |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 20 | "testing" |
Cosmos Nicolaou | 920db00 | 2014-10-23 16:57:32 -0700 | [diff] [blame] | 21 | "time" |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 22 | |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 23 | "v.io/v23" |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 24 | "v.io/v23/naming" |
Matt Rosencrantz | 94502cf | 2015-03-18 09:43:44 -0700 | [diff] [blame] | 25 | "v.io/v23/rpc" |
Jiri Simsa | 6ac9522 | 2015-02-23 16:11:49 -0800 | [diff] [blame] | 26 | "v.io/v23/security" |
Cosmos Nicolaou | 5129fcb | 2014-08-22 11:52:25 -0700 | [diff] [blame] | 27 | |
Suharsh Sivakumar | dcc11d7 | 2015-05-11 12:19:20 -0700 | [diff] [blame] | 28 | 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 Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 34 | "v.io/x/ref/test" |
| 35 | "v.io/x/ref/test/expect" |
| 36 | "v.io/x/ref/test/modules" |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 37 | "v.io/x/ref/test/testutil" |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 38 | ) |
| 39 | |
Suharsh Sivakumar | d19c95d | 2015-02-19 14:44:50 -0800 | [diff] [blame] | 40 | // We write our own TestMain here instead of relying on v23 test generate because |
| 41 | // we need to set runtime.GOMAXPROCS. |
| 42 | func TestMain(m *testing.M) { |
Cosmos Nicolaou | 1381f8a | 2015-03-13 09:40:34 -0700 | [diff] [blame] | 43 | test.Init() |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 44 | |
Asim Shankar | c920db3 | 2014-10-16 19:18:21 -0700 | [diff] [blame] | 45 | // testutil.Init sets GOMAXPROCS to NumCPU. We want to force |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 46 | // GOMAXPFDROCS to remain at 1, in order to trigger a particular race |
Suharsh Sivakumar | d19c95d | 2015-02-19 14:44:50 -0800 | [diff] [blame] | 47 | // condition that occurs when closing the server; also, using 1 cpu |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 48 | // introduces less variance in the behavior of the test. |
| 49 | runtime.GOMAXPROCS(1) |
Todd Wang | 9587390 | 2015-05-22 14:21:30 -0700 | [diff] [blame] | 50 | modules.DispatchAndExitIfChild() |
Suharsh Sivakumar | d19c95d | 2015-02-19 14:44:50 -0800 | [diff] [blame] | 51 | os.Exit(m.Run()) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 52 | } |
| 53 | |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 54 | func testSimpleFlow(t *testing.T, protocol string) { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 55 | ctx, shutdown := test.V23Init() |
| 56 | defer shutdown() |
| 57 | server := InternalNew(ctx, naming.FixedRoutingID(0x55555555)) |
| 58 | client := InternalNew(ctx, naming.FixedRoutingID(0xcccccccc)) |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 59 | pclient := testutil.NewPrincipal("client") |
Jungho Ahn | 19e84b2 | 2015-05-18 13:22:27 -0700 | [diff] [blame] | 60 | pclient2 := testutil.NewPrincipal("client2") |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 61 | pserver := testutil.NewPrincipal("server") |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 62 | ctx, _ = v23.WithPrincipal(ctx, pserver) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 63 | |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 64 | ln, ep, err := server.Listen(ctx, protocol, "127.0.0.1:0", pserver.BlessingStore().Default()) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 65 | 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 Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 73 | cctx, _ := v23.WithPrincipal(ctx, pclient) |
| 74 | if clientVC, err = client.Dial(cctx, ep); err != nil { |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 75 | 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 Ahn | 19e84b2 | 2015-05-18 13:22:27 -0700 | [diff] [blame] | 139 | // 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 Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 142 | cctx, _ := v23.WithPrincipal(ctx, pclient2) |
| 143 | if _, err := client.Dial(cctx, ep); err == nil { |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 144 | t.Errorf("Should not be able to Dial after listener is closed") |
| 145 | } |
| 146 | } |
| 147 | |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 148 | func TestSimpleFlow(t *testing.T) { |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 149 | testSimpleFlow(t, "tcp") |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 150 | } |
| 151 | |
| 152 | func TestSimpleFlowWS(t *testing.T) { |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 153 | testSimpleFlow(t, "ws") |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 154 | } |
| 155 | |
Cosmos Nicolaou | 9388ae4 | 2014-11-10 10:57:15 -0800 | [diff] [blame] | 156 | func TestConnectionTimeout(t *testing.T) { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 157 | ctx, shutdown := test.V23Init() |
| 158 | defer shutdown() |
| 159 | client := InternalNew(ctx, naming.FixedRoutingID(0xcccccccc)) |
Cosmos Nicolaou | 9388ae4 | 2014-11-10 10:57:15 -0800 | [diff] [blame] | 160 | |
| 161 | ch := make(chan error) |
| 162 | go func() { |
| 163 | // 203.0.113.0 is TEST-NET-3 from RFC5737 |
| 164 | ep, _ := inaming.NewEndpoint(naming.FormatEndpoint("tcp", "203.0.113.10:80")) |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 165 | nctx, _ := v23.WithPrincipal(ctx, testutil.NewPrincipal("client")) |
| 166 | _, err := client.Dial(nctx, ep, DialTimeout(time.Second)) |
Cosmos Nicolaou | 9388ae4 | 2014-11-10 10:57:15 -0800 | [diff] [blame] | 167 | 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 Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 180 | func testAuthenticatedByDefault(t *testing.T, protocol string) { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 181 | ctx, shutdown := test.V23Init() |
| 182 | defer shutdown() |
Asim Shankar | 6b0510a | 2014-10-01 12:05:06 -0700 | [diff] [blame] | 183 | var ( |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 184 | server = InternalNew(ctx, naming.FixedRoutingID(0x55555555)) |
| 185 | client = InternalNew(ctx, naming.FixedRoutingID(0xcccccccc)) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 186 | |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 187 | clientPrincipal = testutil.NewPrincipal("client") |
| 188 | serverPrincipal = testutil.NewPrincipal("server") |
Suharsh Sivakumar | 59c423c | 2015-03-11 14:06:03 -0700 | [diff] [blame] | 189 | clientKey = clientPrincipal.PublicKey() |
| 190 | serverBlessings = serverPrincipal.BlessingStore().Default() |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 191 | cctx, _ = v23.WithPrincipal(ctx, clientPrincipal) |
| 192 | sctx, _ = v23.WithPrincipal(ctx, serverPrincipal) |
Asim Shankar | 6b0510a | 2014-10-01 12:05:06 -0700 | [diff] [blame] | 193 | ) |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 194 | |
| 195 | ln, ep, err := server.Listen(sctx, protocol, "127.0.0.1:0", serverPrincipal.BlessingStore().Default()) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 196 | if err != nil { |
| 197 | t.Fatal(err) |
| 198 | } |
Asim Shankar | 7171a25 | 2015-03-07 14:41:40 -0800 | [diff] [blame] | 199 | // 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 203 | |
| 204 | errs := make(chan error) |
| 205 | |
Ankur | 50a5f39 | 2015-02-27 18:46:30 -0800 | [diff] [blame] | 206 | 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 217 | 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() |
Ankur | 50a5f39 | 2015-02-27 18:46:30 -0800 | [diff] [blame] | 229 | testAuth("server", flow, serverBlessings, clientKey) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 230 | }() |
| 231 | |
| 232 | go func() { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 233 | vc, err := client.Dial(cctx, ep) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 234 | 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() |
Ankur | 50a5f39 | 2015-02-27 18:46:30 -0800 | [diff] [blame] | 244 | testAuth("client", flow, serverBlessings, clientKey) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 245 | }() |
| 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 Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 255 | func TestAuthenticatedByDefault(t *testing.T) { |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 256 | testAuthenticatedByDefault(t, "tcp") |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 257 | } |
| 258 | |
| 259 | func TestAuthenticatedByDefaultWS(t *testing.T) { |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 260 | testAuthenticatedByDefault(t, "ws") |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 261 | } |
| 262 | |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 263 | func numListeners(m stream.Manager) int { return len(m.(*manager).listeners) } |
| 264 | func debugString(m stream.Manager) string { return m.(*manager).DebugString() } |
| 265 | func numVIFs(m stream.Manager) int { return len(m.(*manager).vifs.List()) } |
| 266 | |
| 267 | func TestListenEndpoints(t *testing.T) { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 268 | ctx, shutdown := test.V23Init() |
| 269 | defer shutdown() |
| 270 | server := InternalNew(ctx, naming.FixedRoutingID(0xcafe)) |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 271 | principal := testutil.NewPrincipal("test") |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 272 | ctx, _ = v23.WithPrincipal(ctx, principal) |
Suharsh Sivakumar | e5e5dcc | 2015-03-18 14:29:31 -0700 | [diff] [blame] | 273 | blessings := principal.BlessingStore().Default() |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 274 | 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 Sadovsky | 5181bdb | 2014-08-13 10:29:11 -0700 | [diff] [blame] | 276 | // 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 278 | 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 Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 300 | func acceptLoop(wg *sync.WaitGroup, ln stream.Listener) { |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 301 | for { |
| 302 | f, err := ln.Accept() |
| 303 | if err != nil { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 304 | break |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 305 | } |
| 306 | f.Close() |
| 307 | } |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 308 | wg.Done() |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 309 | } |
| 310 | |
| 311 | func TestCloseListener(t *testing.T) { |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 312 | testCloseListener(t, "tcp") |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 313 | } |
| 314 | |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 315 | func TestCloseListenerWS(t *testing.T) { |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 316 | testCloseListener(t, "ws") |
| 317 | } |
| 318 | |
| 319 | func testCloseListener(t *testing.T, protocol string) { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 320 | ctx, shutdown := test.V23Init() |
| 321 | defer shutdown() |
| 322 | server := InternalNew(ctx, naming.FixedRoutingID(0x5e97e9)) |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 323 | pclient := testutil.NewPrincipal("client") |
| 324 | pserver := testutil.NewPrincipal("server") |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 325 | cctx, _ := v23.WithPrincipal(ctx, pclient) |
| 326 | sctx, _ := v23.WithPrincipal(ctx, pserver) |
Suharsh Sivakumar | e5e5dcc | 2015-03-18 14:29:31 -0700 | [diff] [blame] | 327 | blessings := pserver.BlessingStore().Default() |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 328 | ln, ep, err := server.Listen(sctx, protocol, "127.0.0.1:0", blessings) |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 329 | if err != nil { |
| 330 | t.Fatal(err) |
| 331 | } |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 332 | var wg sync.WaitGroup |
| 333 | wg.Add(1) |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 334 | // Server will just listen for flows and close them. |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 335 | go acceptLoop(&wg, ln) |
| 336 | client := InternalNew(ctx, naming.FixedRoutingID(0xc1e41)) |
| 337 | if _, err = client.Dial(cctx, ep); err != nil { |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 338 | t.Fatal(err) |
| 339 | } |
| 340 | ln.Close() |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 341 | client = InternalNew(ctx, naming.FixedRoutingID(0xc1e42)) |
| 342 | if _, err := client.Dial(cctx, ep); err == nil { |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 343 | t.Errorf("client.Dial(%q) should have failed", ep) |
| 344 | } |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 345 | time.Sleep(time.Second) |
| 346 | wg.Wait() |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 347 | } |
| 348 | |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 349 | func TestShutdown(t *testing.T) { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 350 | ctx, shutdown := test.V23Init() |
| 351 | defer shutdown() |
| 352 | server := InternalNew(ctx, naming.FixedRoutingID(0x5e97e9)) |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 353 | principal := testutil.NewPrincipal("test") |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 354 | ctx, _ = v23.WithPrincipal(ctx, principal) |
Suharsh Sivakumar | e5e5dcc | 2015-03-18 14:29:31 -0700 | [diff] [blame] | 355 | blessings := principal.BlessingStore().Default() |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 356 | ln, _, err := server.Listen(ctx, "tcp", "127.0.0.1:0", blessings) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 357 | if err != nil { |
| 358 | t.Fatal(err) |
| 359 | } |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 360 | var wg sync.WaitGroup |
| 361 | wg.Add(1) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 362 | // Server will just listen for flows and close them. |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 363 | go acceptLoop(&wg, ln) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 364 | 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 Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 368 | if _, _, err := server.Listen(ctx, "tcp", "127.0.0.1:0", blessings); err == nil { |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 369 | 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 Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 374 | wg.Wait() |
| 375 | fmt.Fprintf(os.Stderr, "DONE\n") |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 376 | } |
| 377 | |
| 378 | func TestShutdownEndpoint(t *testing.T) { |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 379 | testShutdownEndpoint(t, "tcp") |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 380 | } |
| 381 | |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 382 | func TestShutdownEndpointWS(t *testing.T) { |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 383 | testShutdownEndpoint(t, "ws") |
| 384 | } |
| 385 | |
| 386 | func testShutdownEndpoint(t *testing.T, protocol string) { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 387 | ctx, shutdown := test.V23Init() |
| 388 | defer shutdown() |
| 389 | server := InternalNew(ctx, naming.FixedRoutingID(0x55555555)) |
| 390 | client := InternalNew(ctx, naming.FixedRoutingID(0xcccccccc)) |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 391 | principal := testutil.NewPrincipal("test") |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 392 | ctx, _ = v23.WithPrincipal(ctx, principal) |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 393 | |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 394 | ln, ep, err := server.Listen(ctx, protocol, "127.0.0.1:0", principal.BlessingStore().Default()) |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 395 | if err != nil { |
| 396 | t.Fatal(err) |
| 397 | } |
| 398 | |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 399 | var wg sync.WaitGroup |
| 400 | wg.Add(1) |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 401 | // Server will just listen for flows and close them. |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 402 | go acceptLoop(&wg, ln) |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 403 | |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 404 | cctx, _ := v23.WithPrincipal(ctx, testutil.NewPrincipal("client")) |
| 405 | vc, err := client.Dial(cctx, ep) |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 406 | 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 Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 416 | ln.Close() |
| 417 | wg.Wait() |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 418 | } |
| 419 | |
Jungho Ahn | 6ab655f | 2015-04-14 18:27:09 -0700 | [diff] [blame] | 420 | func TestStartTimeout(t *testing.T) { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 421 | ctx, shutdown := test.V23Init() |
| 422 | defer shutdown() |
Jungho Ahn | 6ab655f | 2015-04-14 18:27:09 -0700 | [diff] [blame] | 423 | const ( |
| 424 | startTime = 5 * time.Millisecond |
Jungho Ahn | 6ab655f | 2015-04-14 18:27:09 -0700 | [diff] [blame] | 425 | ) |
| 426 | |
| 427 | var ( |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 428 | server = InternalNew(ctx, naming.FixedRoutingID(0x55555555)) |
Jungho Ahn | 6ab655f | 2015-04-14 18:27:09 -0700 | [diff] [blame] | 429 | pserver = testutil.NewPrincipal("server") |
| 430 | lopts = []stream.ListenerOpt{vc.StartTimeout{startTime}} |
| 431 | ) |
| 432 | |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 433 | sctx, _ := v23.WithPrincipal(ctx, pserver) |
| 434 | |
Jungho Ahn | 6ab655f | 2015-04-14 18:27:09 -0700 | [diff] [blame] | 435 | // Pause the start timers. |
| 436 | triggerTimers := vif.SetFakeTimers() |
| 437 | |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 438 | ln, ep, err := server.Listen(sctx, "tcp", "127.0.0.1:0", pserver.BlessingStore().Default(), lopts...) |
Jungho Ahn | 6ab655f | 2015-04-14 18:27:09 -0700 | [diff] [blame] | 439 | 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 Ahn | cc9d572 | 2015-04-22 10:13:04 -0700 | [diff] [blame] | 460 | for range time.Tick(startTime) { |
| 461 | if numVIFs(server) == 0 { |
| 462 | break |
Jungho Ahn | 6ab655f | 2015-04-14 18:27:09 -0700 | [diff] [blame] | 463 | } |
| 464 | } |
Jungho Ahn | 6ab655f | 2015-04-14 18:27:09 -0700 | [diff] [blame] | 465 | } |
| 466 | |
Jungho Ahn | cd175b8 | 2015-03-27 14:29:40 -0700 | [diff] [blame] | 467 | func testIdleTimeout(t *testing.T, testServer bool) { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 468 | ctx, shutdown := test.V23Init() |
| 469 | defer shutdown() |
Jungho Ahn | cd175b8 | 2015-03-27 14:29:40 -0700 | [diff] [blame] | 470 | 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 Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 478 | server = InternalNew(ctx, naming.FixedRoutingID(0x55555555)) |
| 479 | client = InternalNew(ctx, naming.FixedRoutingID(0xcccccccc)) |
Jungho Ahn | cd175b8 | 2015-03-27 14:29:40 -0700 | [diff] [blame] | 480 | pclient = testutil.NewPrincipal("client") |
| 481 | pserver = testutil.NewPrincipal("server") |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 482 | cctx, _ = v23.WithPrincipal(ctx, pclient) |
| 483 | sctx, _ = v23.WithPrincipal(ctx, pserver) |
Jungho Ahn | cd175b8 | 2015-03-27 14:29:40 -0700 | [diff] [blame] | 484 | |
| 485 | opts []stream.VCOpt |
| 486 | lopts []stream.ListenerOpt |
| 487 | ) |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 488 | |
Jungho Ahn | cd175b8 | 2015-03-27 14:29:40 -0700 | [diff] [blame] | 489 | 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 Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 498 | ln, ep, err := server.Listen(sctx, "tcp", "127.0.0.1:0", pserver.BlessingStore().Default(), lopts...) |
Jungho Ahn | cd175b8 | 2015-03-27 14:29:40 -0700 | [diff] [blame] | 499 | if err != nil { |
| 500 | t.Fatal(err) |
| 501 | } |
Jungho Ahn | 19e84b2 | 2015-05-18 13:22:27 -0700 | [diff] [blame] | 502 | errch := make(chan error) |
Jungho Ahn | cd175b8 | 2015-03-27 14:29:40 -0700 | [diff] [blame] | 503 | go func() { |
| 504 | for { |
| 505 | _, err := ln.Accept() |
Jungho Ahn | 19e84b2 | 2015-05-18 13:22:27 -0700 | [diff] [blame] | 506 | errch <- err |
Jungho Ahn | cd175b8 | 2015-03-27 14:29:40 -0700 | [diff] [blame] | 507 | } |
| 508 | }() |
| 509 | |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 510 | vc, err := client.Dial(cctx, ep, opts...) |
Jungho Ahn | cd175b8 | 2015-03-27 14:29:40 -0700 | [diff] [blame] | 511 | 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 Ahn | 19e84b2 | 2015-05-18 13:22:27 -0700 | [diff] [blame] | 518 | // 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 Ahn | cd175b8 | 2015-03-27 14:29:40 -0700 | [diff] [blame] | 522 | |
| 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 Ahn | cc9d572 | 2015-04-22 10:13:04 -0700 | [diff] [blame] | 538 | for range time.Tick(idleTime) { |
| 539 | if numVIFs(client) == 0 && numVIFs(server) == 0 { |
| 540 | break |
Jungho Ahn | cd175b8 | 2015-03-27 14:29:40 -0700 | [diff] [blame] | 541 | } |
| 542 | } |
Jungho Ahn | cd175b8 | 2015-03-27 14:29:40 -0700 | [diff] [blame] | 543 | } |
| 544 | |
| 545 | func TestIdleTimeout(t *testing.T) { testIdleTimeout(t, false) } |
| 546 | func TestIdleTimeoutServer(t *testing.T) { testIdleTimeout(t, true) } |
| 547 | |
Andres Erbsen | ffa4574 | 2014-08-13 10:13:11 -0700 | [diff] [blame] | 548 | /* TLS + resumption + channel bindings is broken: <https://secure-resumption.com/#channelbindings>. |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 549 | func TestSessionTicketCache(t *testing.T) { |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 550 | server := InternalNew(naming.FixedRoutingID(0x55555555)) |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 551 | _, ep, err := server.Listen("tcp", "127.0.0.1:0", testutil.NewPrincipal("server")) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 552 | if err != nil { |
| 553 | t.Fatal(err) |
| 554 | } |
| 555 | |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 556 | client := InternalNew(naming.FixedRoutingID(0xcccccccc)) |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 557 | if _, err = client.Dial(ep, testutil.NewPrincipal("TestSessionTicketCacheClient")); err != nil { |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 558 | 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 Erbsen | ffa4574 | 2014-08-13 10:13:11 -0700 | [diff] [blame] | 565 | */ |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 566 | |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 567 | func testMultipleVCs(t *testing.T, protocol string) { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 568 | ctx, shutdown := test.V23Init() |
| 569 | defer shutdown() |
| 570 | server := InternalNew(ctx, naming.FixedRoutingID(0x55555555)) |
| 571 | client := InternalNew(ctx, naming.FixedRoutingID(0xcccccccc)) |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 572 | principal := testutil.NewPrincipal("test") |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 573 | sctx, _ := v23.WithPrincipal(ctx, principal) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 574 | |
| 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 Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 580 | ln, ep, err := server.Listen(sctx, protocol, "127.0.0.1:0", principal.BlessingStore().Default()) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 581 | if err != nil { |
| 582 | t.Fatal(err) |
| 583 | } |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 584 | |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 585 | 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 Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 617 | pclient := testutil.NewPrincipal("client") |
| 618 | cctx, _ := v23.WithPrincipal(ctx, pclient) |
| 619 | vcs[i], err = client.Dial(cctx, ep) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 620 | 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 Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 653 | func TestMultipleVCs(t *testing.T) { |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 654 | testMultipleVCs(t, "tcp") |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 655 | } |
| 656 | |
| 657 | func TestMultipleVCsWS(t *testing.T) { |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 658 | testMultipleVCs(t, "ws") |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 659 | } |
| 660 | |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 661 | func TestAddressResolution(t *testing.T) { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 662 | ctx, shutdown := test.V23Init() |
| 663 | defer shutdown() |
| 664 | server := InternalNew(ctx, naming.FixedRoutingID(0x55555555)) |
| 665 | client := InternalNew(ctx, naming.FixedRoutingID(0xcccccccc)) |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 666 | principal := testutil.NewPrincipal("test") |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 667 | sctx, _ := v23.WithPrincipal(ctx, principal) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 668 | |
Adam Sadovsky | 5181bdb | 2014-08-13 10:29:11 -0700 | [diff] [blame] | 669 | // 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 Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 672 | // As of April 2014, https://developers.google.com/compute/docs/networking |
| 673 | // said that IPv6 is not yet supported. |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 674 | ln, ep, err := server.Listen(sctx, "tcp4", "127.0.0.1:0", principal.BlessingStore().Default()) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 675 | if err != nil { |
| 676 | t.Fatal(err) |
| 677 | } |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 678 | var wg sync.WaitGroup |
| 679 | wg.Add(1) |
| 680 | go acceptLoop(&wg, ln) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 681 | |
Adam Sadovsky | 5181bdb | 2014-08-13 10:29:11 -0700 | [diff] [blame] | 682 | // 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 Sivakumar | 7e93ce5 | 2015-05-07 17:46:13 -0700 | [diff] [blame] | 685 | // create a endpoint with "localhost", which will result in an endpoint that |
| 686 | // doesn't contain 127.0.0.1. |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 687 | _, port, _ := net.SplitHostPort(ep.Addr().String()) |
Matt Rosencrantz | c16339c | 2015-04-23 10:47:06 -0700 | [diff] [blame] | 688 | nep := &inaming.Endpoint{ |
| 689 | Protocol: ep.Addr().Network(), |
Suharsh Sivakumar | 7e93ce5 | 2015-05-07 17:46:13 -0700 | [diff] [blame] | 690 | Address: net.JoinHostPort("localhost", port), |
Matt Rosencrantz | c16339c | 2015-04-23 10:47:06 -0700 | [diff] [blame] | 691 | RID: ep.RoutingID(), |
| 692 | } |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 693 | |
| 694 | // Dial multiple VCs |
| 695 | for i := 0; i < 2; i++ { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 696 | pclient := testutil.NewPrincipal("client") |
| 697 | cctx, _ := v23.WithPrincipal(ctx, pclient) |
| 698 | if _, err = client.Dial(cctx, nep); err != nil { |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 699 | 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 Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 706 | ln.Close() |
| 707 | wg.Wait() |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 708 | // 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 | |
| 714 | func TestServerRestartDuringClientLifetime(t *testing.T) { |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 715 | testServerRestartDuringClientLifetime(t, "tcp") |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 716 | } |
| 717 | |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 718 | func TestServerRestartDuringClientLifetimeWS(t *testing.T) { |
Cosmos Nicolaou | ae8dd21 | 2014-12-13 23:43:08 -0800 | [diff] [blame] | 719 | testServerRestartDuringClientLifetime(t, "ws") |
| 720 | } |
| 721 | |
| 722 | func testServerRestartDuringClientLifetime(t *testing.T, protocol string) { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 723 | ctx, shutdown := test.V23Init() |
| 724 | defer shutdown() |
| 725 | client := InternalNew(ctx, naming.FixedRoutingID(0xcccccccc)) |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 726 | pclient := testutil.NewPrincipal("client") |
Jungho Ahn | 19e84b2 | 2015-05-18 13:22:27 -0700 | [diff] [blame] | 727 | pclient2 := testutil.NewPrincipal("client2") |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 728 | ctx1, _ := v23.WithPrincipal(ctx, pclient) |
| 729 | ctx2, _ := v23.WithPrincipal(ctx, pclient2) |
| 730 | |
Cosmos Nicolaou | 9e90984 | 2015-03-17 11:58:59 -0700 | [diff] [blame] | 731 | sh, err := modules.NewShell(nil, nil, testing.Verbose(), t) |
Cosmos Nicolaou | 344cc4a | 2014-11-26 15:38:43 -0800 | [diff] [blame] | 732 | if err != nil { |
| 733 | t.Fatalf("unexpected error: %s", err) |
| 734 | } |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 735 | defer sh.Cleanup(nil, nil) |
Todd Wang | 9587390 | 2015-05-22 14:21:30 -0700 | [diff] [blame] | 736 | h, err := sh.Start(nil, runServer, protocol, "127.0.0.1:0") |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 737 | if err != nil { |
| 738 | t.Fatalf("unexpected error: %s", err) |
| 739 | } |
Asim Shankar | e89936f | 2015-04-22 17:37:43 -0700 | [diff] [blame] | 740 | epstr := expect.NewSession(t, h.Stdout(), time.Minute).ExpectVar("ENDPOINT") |
| 741 | ep, err := inaming.NewEndpoint(epstr) |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 742 | if err != nil { |
Asim Shankar | e89936f | 2015-04-22 17:37:43 -0700 | [diff] [blame] | 743 | t.Fatalf("inaming.NewEndpoint(%q): %v", epstr, err) |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 744 | } |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 745 | if _, err := client.Dial(ctx1, ep); err != nil { |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 746 | t.Fatal(err) |
| 747 | } |
| 748 | h.Shutdown(nil, os.Stderr) |
| 749 | |
Jungho Ahn | 19e84b2 | 2015-05-18 13:22:27 -0700 | [diff] [blame] | 750 | // 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 Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 753 | if _, err := client.Dial(ctx2, ep); err == nil { |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 754 | t.Fatal("Expected client.Dial to fail since server is dead") |
| 755 | } |
| 756 | |
Todd Wang | 9587390 | 2015-05-22 14:21:30 -0700 | [diff] [blame] | 757 | h, err = sh.Start(nil, runServer, protocol, ep.Addr().String()) |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 758 | if err != nil { |
| 759 | t.Fatalf("unexpected error: %s", err) |
| 760 | } |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 761 | // Restarting the server, listening on the same address as before |
Asim Shankar | e89936f | 2015-04-22 17:37:43 -0700 | [diff] [blame] | 762 | ep2, err := inaming.NewEndpoint(expect.NewSession(t, h.Stdout(), time.Minute).ExpectVar("ENDPOINT")) |
| 763 | if err != nil { |
| 764 | t.Fatal(err) |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 765 | } |
Asim Shankar | e89936f | 2015-04-22 17:37:43 -0700 | [diff] [blame] | 766 | if got, want := ep.Addr().String(), ep2.Addr().String(); got != want { |
| 767 | t.Fatalf("Got %q, want %q", got, want) |
| 768 | } |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 769 | if _, err := client.Dial(ctx1, ep2); err != nil { |
Shyam Jayaraman | dbae76b | 2014-11-17 12:51:29 -0800 | [diff] [blame] | 770 | t.Fatal(err) |
| 771 | } |
| 772 | } |
| 773 | |
Todd Wang | 9587390 | 2015-05-22 14:21:30 -0700 | [diff] [blame] | 774 | var runServer = modules.Register(runServerFunc, "runServer") |
| 775 | |
| 776 | func runServerFunc(env *modules.Env, args ...string) error { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 777 | ctx, shutdown := test.V23Init() |
| 778 | defer shutdown() |
| 779 | server := InternalNew(ctx, naming.FixedRoutingID(0x55555555)) |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 780 | principal := testutil.NewPrincipal("test") |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 781 | ctx, _ = v23.WithPrincipal(ctx, principal) |
| 782 | _, ep, err := server.Listen(ctx, args[0], args[1], principal.BlessingStore().Default()) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 783 | if err != nil { |
Todd Wang | 9587390 | 2015-05-22 14:21:30 -0700 | [diff] [blame] | 784 | fmt.Fprintln(env.Stderr, err) |
Cosmos Nicolaou | 920db00 | 2014-10-23 16:57:32 -0700 | [diff] [blame] | 785 | return err |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 786 | } |
Todd Wang | 9587390 | 2015-05-22 14:21:30 -0700 | [diff] [blame] | 787 | fmt.Fprintf(env.Stdout, "ENDPOINT=%v\n", ep) |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 788 | // Live forever (till the process is explicitly killed) |
Todd Wang | 9587390 | 2015-05-22 14:21:30 -0700 | [diff] [blame] | 789 | modules.WaitForEOF(env.Stdin) |
Cosmos Nicolaou | 920db00 | 2014-10-23 16:57:32 -0700 | [diff] [blame] | 790 | return nil |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 791 | } |
| 792 | |
Todd Wang | 9587390 | 2015-05-22 14:21:30 -0700 | [diff] [blame] | 793 | var runRLimitedServer = modules.Register(func(env *modules.Env, args ...string) error { |
Asim Shankar | e89936f | 2015-04-22 17:37:43 -0700 | [diff] [blame] | 794 | var rlimit syscall.Rlimit |
| 795 | if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit); err != nil { |
Todd Wang | 9587390 | 2015-05-22 14:21:30 -0700 | [diff] [blame] | 796 | fmt.Fprintln(env.Stderr, err) |
Asim Shankar | e89936f | 2015-04-22 17:37:43 -0700 | [diff] [blame] | 797 | return err |
| 798 | } |
| 799 | rlimit.Cur = 9 |
| 800 | if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlimit); err != nil { |
Todd Wang | 9587390 | 2015-05-22 14:21:30 -0700 | [diff] [blame] | 801 | fmt.Fprintln(env.Stderr, err) |
Asim Shankar | e89936f | 2015-04-22 17:37:43 -0700 | [diff] [blame] | 802 | return err |
| 803 | } |
Todd Wang | 9587390 | 2015-05-22 14:21:30 -0700 | [diff] [blame] | 804 | fmt.Fprintf(env.Stdout, "RLIMIT_NOFILE=%d\n", rlimit.Cur) |
| 805 | return runServerFunc(env, args...) |
| 806 | }, "runRLimitedServer") |
Asim Shankar | e89936f | 2015-04-22 17:37:43 -0700 | [diff] [blame] | 807 | |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 808 | func 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 | |
| 823 | func writeLine(f stream.Flow, data string) error { |
| 824 | data = data + "\n" |
Jiri Simsa | 5293dcb | 2014-05-10 09:56:38 -0700 | [diff] [blame] | 825 | 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 Nicolaou | 5129fcb | 2014-08-22 11:52:25 -0700 | [diff] [blame] | 830 | |
| 831 | func TestRegistration(t *testing.T) { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 832 | ctx, shutdown := test.V23Init() |
| 833 | defer shutdown() |
| 834 | server := InternalNew(ctx, naming.FixedRoutingID(0x55555555)) |
| 835 | client := InternalNew(ctx, naming.FixedRoutingID(0xcccccccc)) |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 836 | principal := testutil.NewPrincipal("server") |
Suharsh Sivakumar | e5e5dcc | 2015-03-18 14:29:31 -0700 | [diff] [blame] | 837 | blessings := principal.BlessingStore().Default() |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 838 | ctx, _ = v23.WithPrincipal(ctx, principal) |
Cosmos Nicolaou | 5129fcb | 2014-08-22 11:52:25 -0700 | [diff] [blame] | 839 | |
Cosmos Nicolaou | 87c0a55 | 2014-12-02 23:05:49 -0800 | [diff] [blame] | 840 | dialer := func(_, _ string, _ time.Duration) (net.Conn, error) { |
Cosmos Nicolaou | 5129fcb | 2014-08-22 11:52:25 -0700 | [diff] [blame] | 841 | return nil, fmt.Errorf("tn.Dial") |
| 842 | } |
Suharsh Sivakumar | 7e93ce5 | 2015-05-07 17:46:13 -0700 | [diff] [blame] | 843 | resolver := func(_, _ string) (string, string, error) { |
| 844 | return "", "", fmt.Errorf("tn.Resolve") |
| 845 | } |
Cosmos Nicolaou | 87c0a55 | 2014-12-02 23:05:49 -0800 | [diff] [blame] | 846 | listener := func(_, _ string) (net.Listener, error) { |
Cosmos Nicolaou | 5129fcb | 2014-08-22 11:52:25 -0700 | [diff] [blame] | 847 | return nil, fmt.Errorf("tn.Listen") |
| 848 | } |
Suharsh Sivakumar | 7e93ce5 | 2015-05-07 17:46:13 -0700 | [diff] [blame] | 849 | rpc.RegisterProtocol("tn", dialer, resolver, listener) |
Cosmos Nicolaou | 5129fcb | 2014-08-22 11:52:25 -0700 | [diff] [blame] | 850 | |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 851 | _, _, err := server.Listen(ctx, "tnx", "127.0.0.1:0", blessings) |
Cosmos Nicolaou | 07a736d | 2015-04-06 11:55:26 -0700 | [diff] [blame] | 852 | if err == nil || !strings.Contains(err.Error(), "unknown network: tnx") { |
| 853 | t.Fatalf("expected error is missing (%v)", err) |
Cosmos Nicolaou | 5129fcb | 2014-08-22 11:52:25 -0700 | [diff] [blame] | 854 | } |
| 855 | |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 856 | _, _, err = server.Listen(ctx, "tn", "127.0.0.1:0", blessings) |
Cosmos Nicolaou | 5129fcb | 2014-08-22 11:52:25 -0700 | [diff] [blame] | 857 | if err == nil || !strings.Contains(err.Error(), "tn.Listen") { |
Cosmos Nicolaou | 07a736d | 2015-04-06 11:55:26 -0700 | [diff] [blame] | 858 | t.Fatalf("expected error is missing (%v)", err) |
Cosmos Nicolaou | 5129fcb | 2014-08-22 11:52:25 -0700 | [diff] [blame] | 859 | } |
| 860 | |
| 861 | // Need a functional listener to test Dial. |
Cosmos Nicolaou | 87c0a55 | 2014-12-02 23:05:49 -0800 | [diff] [blame] | 862 | listener = func(_, addr string) (net.Listener, error) { |
Cosmos Nicolaou | 5129fcb | 2014-08-22 11:52:25 -0700 | [diff] [blame] | 863 | return net.Listen("tcp", addr) |
| 864 | } |
| 865 | |
Suharsh Sivakumar | 7e93ce5 | 2015-05-07 17:46:13 -0700 | [diff] [blame] | 866 | if got, want := rpc.RegisterProtocol("tn", dialer, resolver, listener), true; got != want { |
Cosmos Nicolaou | 5129fcb | 2014-08-22 11:52:25 -0700 | [diff] [blame] | 867 | t.Errorf("got %t, want %t", got, want) |
| 868 | } |
| 869 | |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 870 | _, ep, err := server.Listen(ctx, "tn", "127.0.0.1:0", blessings) |
Cosmos Nicolaou | 5129fcb | 2014-08-22 11:52:25 -0700 | [diff] [blame] | 871 | if err != nil { |
| 872 | t.Errorf("unexpected error %s", err) |
| 873 | } |
| 874 | |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 875 | cctx, _ := v23.WithPrincipal(ctx, testutil.NewPrincipal("client")) |
| 876 | _, err = client.Dial(cctx, ep) |
Suharsh Sivakumar | 7e93ce5 | 2015-05-07 17:46:13 -0700 | [diff] [blame] | 877 | if err == nil || !strings.Contains(err.Error(), "tn.Resolve") { |
| 878 | t.Fatalf("expected error is missing (%v)", err) |
Cosmos Nicolaou | 5129fcb | 2014-08-22 11:52:25 -0700 | [diff] [blame] | 879 | } |
| 880 | } |
Asim Shankar | 7171a25 | 2015-03-07 14:41:40 -0800 | [diff] [blame] | 881 | |
| 882 | func TestBlessingNamesInEndpoint(t *testing.T) { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 883 | ctx, shutdown := test.V23Init() |
| 884 | defer shutdown() |
Asim Shankar | 7171a25 | 2015-03-07 14:41:40 -0800 | [diff] [blame] | 885 | var ( |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 886 | p = testutil.NewPrincipal("default") |
Suharsh Sivakumar | e5e5dcc | 2015-03-18 14:29:31 -0700 | [diff] [blame] | 887 | b, _ = p.BlessSelf("dev.v.io/users/foo@bar.com/devices/desktop/app/myapp") |
Asim Shankar | 7171a25 | 2015-03-07 14:41:40 -0800 | [diff] [blame] | 888 | |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 889 | server = InternalNew(ctx, naming.FixedRoutingID(0x1)) |
Asim Shankar | 7171a25 | 2015-03-07 14:41:40 -0800 | [diff] [blame] | 890 | |
| 891 | tests = []struct { |
Suharsh Sivakumar | e5e5dcc | 2015-03-18 14:29:31 -0700 | [diff] [blame] | 892 | principal security.Principal |
| 893 | blessings security.Blessings |
| 894 | blessingNames []string |
| 895 | err bool |
Asim Shankar | 7171a25 | 2015-03-07 14:41:40 -0800 | [diff] [blame] | 896 | }{ |
| 897 | { |
Suharsh Sivakumar | e5e5dcc | 2015-03-18 14:29:31 -0700 | [diff] [blame] | 898 | // 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 Shankar | 7171a25 | 2015-03-07 14:41:40 -0800 | [diff] [blame] | 902 | }, |
| 903 | { |
Suharsh Sivakumar | e5e5dcc | 2015-03-18 14:29:31 -0700 | [diff] [blame] | 904 | // It is an error to provide a principal without providing blessings. |
Suharsh Sivakumar | 59c423c | 2015-03-11 14:06:03 -0700 | [diff] [blame] | 905 | principal: p, |
Suharsh Sivakumar | e5e5dcc | 2015-03-18 14:29:31 -0700 | [diff] [blame] | 906 | blessings: security.Blessings{}, |
Suharsh Sivakumar | 59c423c | 2015-03-11 14:06:03 -0700 | [diff] [blame] | 907 | err: true, |
Asim Shankar | 7171a25 | 2015-03-07 14:41:40 -0800 | [diff] [blame] | 908 | }, |
| 909 | { |
Suharsh Sivakumar | e5e5dcc | 2015-03-18 14:29:31 -0700 | [diff] [blame] | 910 | // It is an error to provide inconsistent blessings and principal |
Asim Shankar | 4a69828 | 2015-03-21 21:59:18 -0700 | [diff] [blame] | 911 | principal: testutil.NewPrincipal("random"), |
Suharsh Sivakumar | e5e5dcc | 2015-03-18 14:29:31 -0700 | [diff] [blame] | 912 | blessings: b, |
Suharsh Sivakumar | 59c423c | 2015-03-11 14:06:03 -0700 | [diff] [blame] | 913 | err: true, |
Asim Shankar | 7171a25 | 2015-03-07 14:41:40 -0800 | [diff] [blame] | 914 | }, |
| 915 | } |
| 916 | ) |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 917 | |
Asim Shankar | 7171a25 | 2015-03-07 14:41:40 -0800 | [diff] [blame] | 918 | // p must recognize its own blessings! |
Suharsh Sivakumar | e5e5dcc | 2015-03-18 14:29:31 -0700 | [diff] [blame] | 919 | p.AddToRoots(b) |
Asim Shankar | 7171a25 | 2015-03-07 14:41:40 -0800 | [diff] [blame] | 920 | for idx, test := range tests { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 921 | sctx, _ := v23.WithPrincipal(ctx, test.principal) |
| 922 | ln, ep, err := server.Listen(sctx, "tcp", "127.0.0.1:0", test.blessings) |
Asim Shankar | 7171a25 | 2015-03-07 14:41:40 -0800 | [diff] [blame] | 923 | 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 Sivakumar | e5e5dcc | 2015-03-18 14:29:31 -0700 | [diff] [blame] | 930 | got, want := ep.BlessingNames(), test.blessingNames |
Suharsh Sivakumar | ad1d419 | 2015-03-09 16:48:10 -0700 | [diff] [blame] | 931 | sort.Strings(got) |
| 932 | sort.Strings(want) |
| 933 | if !reflect.DeepEqual(got, want) { |
Asim Shankar | 7171a25 | 2015-03-07 14:41:40 -0800 | [diff] [blame] | 934 | t.Errorf("test #%d: Got %v, want %v", idx, got, want) |
| 935 | } |
| 936 | } |
| 937 | } |
Asim Shankar | e89936f | 2015-04-22 17:37:43 -0700 | [diff] [blame] | 938 | |
| 939 | func TestVIFCleanupWhenFDLimitIsReached(t *testing.T) { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 940 | ctx, shutdown := test.V23Init() |
| 941 | defer shutdown() |
Asim Shankar | e89936f | 2015-04-22 17:37:43 -0700 | [diff] [blame] | 942 | 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 Wang | 9587390 | 2015-05-22 14:21:30 -0700 | [diff] [blame] | 947 | h, err := sh.Start(nil, runRLimitedServer, "--logtostderr=true", "tcp", "127.0.0.1:0") |
Asim Shankar | e89936f | 2015-04-22 17:37:43 -0700 | [diff] [blame] | 948 | 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 Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 973 | client := InternalNew(ctx, naming.FixedRoutingID(uint64(i))) |
Asim Shankar | e89936f | 2015-04-22 17:37:43 -0700 | [diff] [blame] | 974 | defer client.Shutdown() |
| 975 | principal := testutil.NewPrincipal(fmt.Sprintf("client%d", i)) |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 976 | cctx, _ := v23.WithPrincipal(ctx, principal) |
Asim Shankar | e89936f | 2015-04-22 17:37:43 -0700 | [diff] [blame] | 977 | 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 Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 984 | vc, err := client.Dial(cctx, ep) |
Asim Shankar | e89936f | 2015-04-22 17:37:43 -0700 | [diff] [blame] | 985 | 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 Nicolaou | c818b80 | 2015-06-05 15:52:45 -0700 | [diff] [blame] | 1001 | t.Logf("%s", stderr.String()) |
Asim Shankar | e89936f | 2015-04-22 17:37:43 -0700 | [diff] [blame] | 1002 | t.Fatal(err) |
| 1003 | } |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 1004 | fmt.Fprintf(os.Stderr, "11\n") |
Matt Rosencrantz | a40f12a | 2015-04-24 11:07:55 -0700 | [diff] [blame] | 1005 | 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 Shankar | e89936f | 2015-04-22 17:37:43 -0700 | [diff] [blame] | 1007 | } |
| 1008 | t.Logf("Server FD limit:%d", nfiles) |
| 1009 | t.Logf("Client connection attempts: %d", nattempts) |
| 1010 | } |
Suharsh Sivakumar | 859ea0f | 2015-04-29 23:51:39 -0700 | [diff] [blame] | 1011 | |
| 1012 | func TestConcurrentDials(t *testing.T) { |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 1013 | ctx, shutdown := test.V23Init() |
| 1014 | defer shutdown() |
Suharsh Sivakumar | 859ea0f | 2015-04-29 23:51:39 -0700 | [diff] [blame] | 1015 | // Concurrent Dials to the same network, address should only result in one VIF. |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 1016 | server := InternalNew(ctx, naming.FixedRoutingID(0x55555555)) |
| 1017 | client := InternalNew(ctx, naming.FixedRoutingID(0xcccccccc)) |
Suharsh Sivakumar | 859ea0f | 2015-04-29 23:51:39 -0700 | [diff] [blame] | 1018 | principal := testutil.NewPrincipal("test") |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 1019 | ctx, _ = v23.WithPrincipal(ctx, principal) |
Suharsh Sivakumar | 859ea0f | 2015-04-29 23:51:39 -0700 | [diff] [blame] | 1020 | |
| 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 Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 1026 | ln, ep, err := server.Listen(ctx, "tcp4", "127.0.0.1:0", principal.BlessingStore().Default()) |
Suharsh Sivakumar | 859ea0f | 2015-04-29 23:51:39 -0700 | [diff] [blame] | 1027 | if err != nil { |
| 1028 | t.Fatal(err) |
| 1029 | } |
Cosmos Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 1030 | var wg sync.WaitGroup |
| 1031 | wg.Add(1) |
| 1032 | go acceptLoop(&wg, ln) |
Suharsh Sivakumar | 859ea0f | 2015-04-29 23:51:39 -0700 | [diff] [blame] | 1033 | |
Suharsh Sivakumar | 859ea0f | 2015-04-29 23:51:39 -0700 | [diff] [blame] | 1034 | nep := &inaming.Endpoint{ |
| 1035 | Protocol: ep.Addr().Network(), |
Suharsh Sivakumar | 7e93ce5 | 2015-05-07 17:46:13 -0700 | [diff] [blame] | 1036 | Address: ep.Addr().String(), |
Suharsh Sivakumar | 859ea0f | 2015-04-29 23:51:39 -0700 | [diff] [blame] | 1037 | 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 Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 1044 | cctx, _ := v23.WithPrincipal(ctx, testutil.NewPrincipal("client")) |
| 1045 | _, err := client.Dial(cctx, nep) |
Suharsh Sivakumar | 859ea0f | 2015-04-29 23:51:39 -0700 | [diff] [blame] | 1046 | errCh <- err |
| 1047 | }() |
| 1048 | } |
| 1049 | for i := 0; i < 10; i++ { |
Jungho Ahn | 19e84b2 | 2015-05-18 13:22:27 -0700 | [diff] [blame] | 1050 | if err := <-errCh; err != nil { |
Suharsh Sivakumar | 859ea0f | 2015-04-29 23:51:39 -0700 | [diff] [blame] | 1051 | 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 Nicolaou | e9c622d | 2015-07-10 11:09:42 -0700 | [diff] [blame^] | 1058 | ln.Close() |
| 1059 | wg.Wait() |
Suharsh Sivakumar | 859ea0f | 2015-04-29 23:51:39 -0700 | [diff] [blame] | 1060 | } |