blob: 5ecf5d0e8273d54431459d2882dc370a474b6ebd [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
Asim Shankarecc72a32014-08-21 22:49:40 -07005package vif_test
6
7import (
Jason Hickey96d30e82014-11-13 07:40:00 -08008 "fmt"
Asim Shankarecc72a32014-08-21 22:49:40 -07009 "io/ioutil"
10 "net"
Robin Thellendcf140c02014-12-08 14:56:24 -080011 "os"
Asim Shankarecc72a32014-08-21 22:49:40 -070012 "path"
13 "testing"
Jungho Ahn9a5b3072015-02-24 13:59:25 -080014 "time"
Asim Shankarecc72a32014-08-21 22:49:40 -070015
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -070016 "v.io/x/lib/set"
17
18 "v.io/v23"
19 "v.io/v23/context"
Jiri Simsa6ac95222015-02-23 16:11:49 -080020 "v.io/v23/naming"
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070021 "v.io/v23/rpc"
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -070022 "v.io/v23/verror"
23
Suharsh Sivakumardcc11d72015-05-11 12:19:20 -070024 _ "v.io/x/ref/runtime/factories/generic"
25 "v.io/x/ref/runtime/internal/rpc/stream/vif"
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -070026 "v.io/x/ref/test"
Asim Shankar4a698282015-03-21 21:59:18 -070027 "v.io/x/ref/test/testutil"
Asim Shankarecc72a32014-08-21 22:49:40 -070028)
29
Jungho Ahn9a5b3072015-02-24 13:59:25 -080030var supportsIPv6 bool
Asim Shankarecc72a32014-08-21 22:49:40 -070031
Jungho Ahn9a5b3072015-02-24 13:59:25 -080032func init() {
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -070033 simpleResolver := func(network, address string) (string, string, error) {
34 return network, address, nil
35 }
36 rpc.RegisterProtocol("unix", net.DialTimeout, simpleResolver, net.Listen)
Jungho Ahn9a5b3072015-02-24 13:59:25 -080037
38 // Check whether the platform supports IPv6.
39 ln, err := net.Listen("tcp6", "[::1]:0")
40 defer ln.Close()
41 if err == nil {
42 supportsIPv6 = true
43 }
44}
45
46func newConn(network, address string) (net.Conn, net.Conn, error) {
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -070047 dfunc, _, lfunc, _ := rpc.RegisteredProtocol(network)
Jungho Ahn9a5b3072015-02-24 13:59:25 -080048 ln, err := lfunc(network, address)
49 if err != nil {
50 return nil, nil, err
51 }
52 defer ln.Close()
53
54 done := make(chan net.Conn)
Jason Hickey96d30e82014-11-13 07:40:00 -080055 go func() {
Jungho Ahn9a5b3072015-02-24 13:59:25 -080056 conn, err := ln.Accept()
Jason Hickey96d30e82014-11-13 07:40:00 -080057 if err != nil {
Jungho Ahn9a5b3072015-02-24 13:59:25 -080058 panic(err)
Jason Hickey96d30e82014-11-13 07:40:00 -080059 }
Jungho Ahn9a5b3072015-02-24 13:59:25 -080060 conn.Read(make([]byte, 1)) // Read a dummy byte.
61 done <- conn
Jason Hickey96d30e82014-11-13 07:40:00 -080062 }()
Jungho Ahn9a5b3072015-02-24 13:59:25 -080063
64 conn, err := dfunc(ln.Addr().Network(), ln.Addr().String(), 1*time.Second)
65 if err != nil {
66 return nil, nil, err
67 }
68 // Write a dummy byte since wsh listener waits for the magic bytes for ws.
69 conn.Write([]byte("."))
70 return conn, <-done, nil
71}
72
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -070073func newVIF(ctx *context.T, c, s net.Conn) (*vif.VIF, *vif.VIF, error) {
Jungho Ahn9a5b3072015-02-24 13:59:25 -080074 done := make(chan *vif.VIF)
75 go func() {
Asim Shankar4a698282015-03-21 21:59:18 -070076 principal := testutil.NewPrincipal("accepted")
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -070077 ctx, _ = v23.WithPrincipal(ctx, principal)
Suharsh Sivakumare5e5dcc2015-03-18 14:29:31 -070078 blessings := principal.BlessingStore().Default()
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -070079 vf, err := vif.InternalNewAcceptedVIF(ctx, s, naming.FixedRoutingID(0x5), blessings, nil, nil)
Jungho Ahn9a5b3072015-02-24 13:59:25 -080080 if err != nil {
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -070081 fmt.Fprintf(os.Stderr, "ERR 2: %s\n", verror.DebugString(err))
Jungho Ahn9a5b3072015-02-24 13:59:25 -080082 panic(err)
83 }
84 done <- vf
85 }()
86
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -070087 ctx, _ = v23.WithPrincipal(ctx, testutil.NewPrincipal("dialed"))
88 vf, err := vif.InternalNewDialedVIF(ctx, c, naming.FixedRoutingID(0xc), nil, nil)
Jungho Ahn9a5b3072015-02-24 13:59:25 -080089 if err != nil {
90 return nil, nil, err
91 }
92 return vf, <-done, nil
93}
94
95func diff(a, b []string) []string {
Jiri Simsa87d884d2015-06-18 10:25:54 -070096 s1, s2 := set.String.FromSlice(a), set.String.FromSlice(b)
97 set.String.Difference(s1, s2)
98 return set.String.ToSlice(s1)
Jungho Ahn9a5b3072015-02-24 13:59:25 -080099}
100
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700101func find(set *vif.Set, n, a string) *vif.VIF {
102 found, unblock := set.BlockingFind(n, a)
103 unblock()
104 return found
105}
106
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800107func TestSetBasic(t *testing.T) {
Cosmos Nicolaou27dc65b2015-07-10 16:23:19 -0700108 ctx, shutdown := test.V23InitAnon()
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700109 defer shutdown()
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800110 sockdir, err := ioutil.TempDir("", "TestSetBasic")
Asim Shankarecc72a32014-08-21 22:49:40 -0700111 if err != nil {
112 t.Fatal(err)
113 }
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800114 defer os.RemoveAll(sockdir)
115
Matt Rosencrantz94502cf2015-03-18 09:43:44 -0700116 all := rpc.RegisteredProtocols()
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800117 unknown := naming.UnknownProtocol
118 tests := []struct {
119 network, address string
120 compatibles []string
121 }{
122 {"tcp", "127.0.0.1:0", []string{"tcp", "tcp4", "wsh", "wsh4", unknown}},
123 {"tcp4", "127.0.0.1:0", []string{"tcp", "tcp4", "wsh", "wsh4", unknown}},
124 {"tcp", "[::1]:0", []string{"tcp", "tcp6", "wsh", "wsh6", unknown}},
125 {"tcp6", "[::1]:0", []string{"tcp", "tcp6", "wsh", "wsh6", unknown}},
126 {"ws", "127.0.0.1:0", []string{"ws", "ws4", "wsh", "wsh4", unknown}},
127 {"ws4", "127.0.0.1:0", []string{"ws", "ws4", "wsh", "wsh4", unknown}},
128 {"ws", "[::1]:0", []string{"ws", "ws6", "wsh", "wsh6", unknown}},
129 {"ws6", "[::1]:0", []string{"ws", "ws6", "wsh", "wsh6", unknown}},
130 // wsh dial always uses tcp.
131 {"wsh", "127.0.0.1:0", []string{"tcp", "tcp4", "wsh", "wsh4", unknown}},
132 {"wsh4", "127.0.0.1:0", []string{"tcp", "tcp4", "wsh", "wsh4", unknown}},
133 {"wsh", "[::1]:0", []string{"tcp", "tcp6", "wsh", "wsh6", unknown}},
134 {"wsh6", "[::1]:0", []string{"tcp", "tcp6", "wsh", "wsh6", unknown}},
135 {unknown, "127.0.0.1:0", []string{"tcp", "tcp4", "wsh", "wsh4", unknown}},
136 {unknown, "[::1]:0", []string{"tcp", "tcp6", "wsh", "wsh6", unknown}},
137 {"unix", path.Join(sockdir, "socket"), []string{"unix"}},
138 }
139
140 set := vif.NewSet()
141 for _, test := range tests {
142 if test.address == "[::1]:0" && !supportsIPv6 {
143 continue
144 }
145
146 name := fmt.Sprintf("(%q, %q)", test.network, test.address)
147
148 c, s, err := newConn(test.network, test.address)
149 if err != nil {
150 t.Fatal(err)
151 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700152 vf, _, err := newVIF(ctx, c, s)
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800153 if err != nil {
154 t.Fatal(err)
155 }
156 a := c.RemoteAddr()
157
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700158 set.Insert(vf, a.Network(), a.String())
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800159 for _, n := range test.compatibles {
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700160 if found := find(set, n, a.String()); found == nil {
161 t.Fatalf("%s: Got nil, but want [%v] on find(%q, %q))", name, vf, n, a)
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800162 }
163 }
164
165 for _, n := range diff(all, test.compatibles) {
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700166 if v := find(set, n, a.String()); v != nil {
167 t.Fatalf("%s: Got [%v], but want nil on find(%q, %q))", name, v, n, a)
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800168 }
169 }
170
171 set.Delete(vf)
172 for _, n := range all {
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700173 if v := find(set, n, a.String()); v != nil {
174 t.Fatalf("%s: Got [%v], but want nil on find(%q, %q))", name, v, n, a)
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800175 }
176 }
177 }
178}
179
180func TestSetWithPipes(t *testing.T) {
Cosmos Nicolaou27dc65b2015-07-10 16:23:19 -0700181 ctx, shutdown := test.V23InitAnon()
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700182 defer shutdown()
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800183 c1, s1 := net.Pipe()
184 c2, s2 := net.Pipe()
185 a1 := c1.RemoteAddr()
186 a2 := c2.RemoteAddr()
187 if a1.Network() != a2.Network() || a1.String() != a2.String() {
Asim Shankarecc72a32014-08-21 22:49:40 -0700188 t.Fatalf("This test was intended for distinct connections that have duplicate RemoteAddrs. "+
189 "That does not seem to be the case with (%q, %q) and (%q, %q)",
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800190 a1.Network(), a1, a2.Network(), a2)
Asim Shankarecc72a32014-08-21 22:49:40 -0700191 }
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800192
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700193 vf1, _, err := newVIF(ctx, c1, s1)
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800194 if err != nil {
195 t.Fatal(err)
196 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700197 vf2, _, err := newVIF(ctx, c2, s2)
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800198 if err != nil {
199 t.Fatal(err)
200 }
201
202 set := vif.NewSet()
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700203 set.Insert(vf1, a1.Network(), a1.String())
204 if v := find(set, a1.Network(), a1.String()); v != nil {
205 t.Fatalf("Got [%v], but want nil on find(%q, %q))", v, a1.Network(), a1)
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800206 }
207 if l := set.List(); len(l) != 1 || l[0] != vf1 {
208 t.Errorf("Unexpected list of VIFs: %v", l)
209 }
210
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700211 set.Insert(vf2, a2.Network(), a2.String())
212 if v := find(set, a2.Network(), a2.String()); v != nil {
213 t.Fatalf("Got [%v], but want nil on find(%q, %q))", v, a2.Network(), a2)
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800214 }
215 if l := set.List(); len(l) != 2 || l[0] != vf1 || l[1] != vf2 {
216 t.Errorf("Unexpected list of VIFs: %v", l)
217 }
218
219 set.Delete(vf1)
220 if l := set.List(); len(l) != 1 || l[0] != vf2 {
221 t.Errorf("Unexpected list of VIFs: %v", l)
222 }
223 set.Delete(vf2)
224 if l := set.List(); len(l) != 0 {
225 t.Errorf("Unexpected list of VIFs: %v", l)
Asim Shankarecc72a32014-08-21 22:49:40 -0700226 }
227}
228
229func TestSetWithUnixSocket(t *testing.T) {
Cosmos Nicolaou27dc65b2015-07-10 16:23:19 -0700230 ctx, shutdown := test.V23InitAnon()
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700231 defer shutdown()
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800232 dir, err := ioutil.TempDir("", "TestSetWithUnixSocket")
Asim Shankarecc72a32014-08-21 22:49:40 -0700233 if err != nil {
234 t.Fatal(err)
235 }
Robin Thellendcf140c02014-12-08 14:56:24 -0800236 defer os.RemoveAll(dir)
Asim Shankarecc72a32014-08-21 22:49:40 -0700237
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800238 c1, s1, err := newConn("unix", path.Join(dir, "socket1"))
Asim Shankarecc72a32014-08-21 22:49:40 -0700239 if err != nil {
240 t.Fatal(err)
241 }
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800242 c2, s2, err := newConn("unix", path.Join(dir, "socket2"))
Asim Shankarecc72a32014-08-21 22:49:40 -0700243 if err != nil {
244 t.Fatal(err)
245 }
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800246
247 // The client side address is always unix:@ regardless of socket name.
248 a1 := s1.RemoteAddr()
249 a2 := s2.RemoteAddr()
250 if a1.Network() != a2.Network() || a1.String() != a2.String() {
Asim Shankarecc72a32014-08-21 22:49:40 -0700251 t.Fatalf("This test was intended for distinct connections that have duplicate RemoteAddrs. "+
252 "That does not seem to be the case with (%q, %q) and (%q, %q)",
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800253 a1.Network(), a1, a2.Network(), a2)
Asim Shankarecc72a32014-08-21 22:49:40 -0700254 }
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800255
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700256 _, vf1, err := newVIF(ctx, c1, s1)
Asim Shankarecc72a32014-08-21 22:49:40 -0700257 if err != nil {
258 t.Fatal(err)
259 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700260 _, vf2, err := newVIF(ctx, c2, s2)
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800261 if err != nil {
Jason Hickey96d30e82014-11-13 07:40:00 -0800262 t.Fatal(err)
263 }
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800264
Asim Shankarecc72a32014-08-21 22:49:40 -0700265 set := vif.NewSet()
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700266 set.Insert(vf1, a1.Network(), a1.String())
267 if v := find(set, a1.Network(), a1.String()); v != nil {
268 t.Fatalf("Got [%v], but want nil on find(%q, %q))", v, a1.Network(), a1)
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800269 }
270 if l := set.List(); len(l) != 1 || l[0] != vf1 {
271 t.Errorf("Unexpected list of VIFs: %v", l)
272 }
273
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700274 set.Insert(vf2, a2.Network(), a2.String())
275 if v := find(set, a2.Network(), a2.String()); v != nil {
276 t.Fatalf("Got [%v], but want nil on find(%q, %q))", v, a2.Network(), a2)
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800277 }
278 if l := set.List(); len(l) != 2 || l[0] != vf1 || l[1] != vf2 {
279 t.Errorf("Unexpected list of VIFs: %v", l)
280 }
281
282 set.Delete(vf1)
283 if l := set.List(); len(l) != 1 || l[0] != vf2 {
284 t.Errorf("Unexpected list of VIFs: %v", l)
285 }
286 set.Delete(vf2)
287 if l := set.List(); len(l) != 0 {
288 t.Errorf("Unexpected list of VIFs: %v", l)
Asim Shankarecc72a32014-08-21 22:49:40 -0700289 }
290}
Robin Thellend2224ffa2015-02-14 21:28:27 -0800291
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800292func TestSetInsertDelete(t *testing.T) {
Cosmos Nicolaou27dc65b2015-07-10 16:23:19 -0700293 ctx, shutdown := test.V23InitAnon()
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700294 defer shutdown()
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800295 c1, s1 := net.Pipe()
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700296 vf1, _, err := newVIF(ctx, c1, s1)
Robin Thellend2224ffa2015-02-14 21:28:27 -0800297 if err != nil {
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800298 t.Fatal(err)
Robin Thellend2224ffa2015-02-14 21:28:27 -0800299 }
Robin Thellend2224ffa2015-02-14 21:28:27 -0800300
Robin Thellend2224ffa2015-02-14 21:28:27 -0800301 set1 := vif.NewSet()
Robin Thellend2224ffa2015-02-14 21:28:27 -0800302
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700303 n1, a1 := c1.RemoteAddr().Network(), c1.RemoteAddr().String()
304 set1.Insert(vf1, n1, a1)
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800305 if l := set1.List(); len(l) != 1 || l[0] != vf1 {
Robin Thellend2224ffa2015-02-14 21:28:27 -0800306 t.Errorf("Unexpected list of VIFs: %v", l)
307 }
Robin Thellend2224ffa2015-02-14 21:28:27 -0800308
Jungho Ahn9a5b3072015-02-24 13:59:25 -0800309 set1.Delete(vf1)
Robin Thellend2224ffa2015-02-14 21:28:27 -0800310 if l := set1.List(); len(l) != 0 {
311 t.Errorf("Unexpected list of VIFs: %v", l)
312 }
Robin Thellend2224ffa2015-02-14 21:28:27 -0800313}
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -0700314
315func TestBlockingFind(t *testing.T) {
Cosmos Nicolaou27dc65b2015-07-10 16:23:19 -0700316 ctx, shutdown := test.V23InitAnon()
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700317 defer shutdown()
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -0700318 network, address := "tcp", "127.0.0.1:1234"
319 set := vif.NewSet()
320
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700321 _, unblock := set.BlockingFind(network, address)
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -0700322
323 ch := make(chan *vif.VIF, 1)
324
325 // set.BlockingFind should block until set.Unblock is called with the corresponding VIF,
326 // since set.BlockingFind was called earlier.
327 go func(ch chan *vif.VIF) {
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700328 vf, _ := set.BlockingFind(network, address)
329 ch <- vf
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -0700330 }(ch)
331
332 // set.BlockingFind for a different network and address should not block.
333 set.BlockingFind("network", "address")
334
335 // Create and insert the VIF.
336 c, s, err := newConn(network, address)
337 if err != nil {
338 t.Fatal(err)
339 }
Cosmos Nicolaoue9c622d2015-07-10 11:09:42 -0700340 vf, _, err := newVIF(ctx, c, s)
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -0700341 if err != nil {
342 t.Fatal(err)
343 }
Suharsh Sivakumar7e93ce52015-05-07 17:46:13 -0700344 set.Insert(vf, network, address)
345 unblock()
Suharsh Sivakumar859ea0f2015-04-29 23:51:39 -0700346
347 // Now the set.BlockingFind should have returned the correct vif.
348 if cachedVif := <-ch; cachedVif != vf {
349 t.Errorf("got %v, want %v", cachedVif, vf)
350 }
351}