blob: 20500bb7d38fc5755a3b5ebce9b2c55cd0196762 [file] [log] [blame]
package proxy_test
import (
"bytes"
"fmt"
"io"
"reflect"
"strings"
"testing"
"veyron.io/veyron/veyron2/ipc/stream"
"veyron.io/veyron/veyron2/naming"
"veyron.io/veyron/veyron/lib/testutil"
tsecurity "veyron.io/veyron/veyron/lib/testutil/security"
_ "veyron.io/veyron/veyron/profiles"
"veyron.io/veyron/veyron/runtimes/google/ipc/stream/manager"
"veyron.io/veyron/veyron/runtimes/google/ipc/stream/proxy"
"veyron.io/veyron/veyron/runtimes/google/ipc/stream/vc"
)
func init() { testutil.Init() }
func TestProxy(t *testing.T) {
proxy, err := proxy.New(naming.FixedRoutingID(0xbbbbbbbbbbbbbbbb), nil, "tcp", "127.0.0.1:0", "")
if err != nil {
t.Fatal(err)
}
defer proxy.Shutdown()
// Create the stream.Manager for the server.
server1 := manager.InternalNew(naming.FixedRoutingID(0x1111111111111111))
defer server1.Shutdown()
// Setup a stream.Listener that will accept VCs and Flows routed
// through the proxy.
ln1, ep1, err := server1.Listen(proxy.Endpoint().Network(), proxy.Endpoint().String())
if err != nil {
t.Fatal(err)
}
defer ln1.Close()
// Create the stream.Manager for a second server.
server2 := manager.InternalNew(naming.FixedRoutingID(0x2222222222222222))
defer server2.Shutdown()
// Setup a stream.Listener that will accept VCs and Flows routed
// through the proxy.
ln2, ep2, err := server2.Listen(proxy.Endpoint().Network(), proxy.Endpoint().String())
if err != nil {
t.Fatal(err)
}
defer ln2.Close()
// Create the stream.Manager for a client.
client := manager.InternalNew(naming.FixedRoutingID(0xcccccccccccccccc))
defer client.Shutdown()
cases := []struct {
client stream.Manager
ln stream.Listener
ep naming.Endpoint
}{
{client, ln1, ep1}, // client writing to server1
{server1, ln2, ep2}, // server1 writing to server2
{server1, ln1, ep1}, // server1 writing to itself
}
const written = "the dough rises"
for i, c := range cases {
name := fmt.Sprintf("case #%d(write to %v):", i, c.ep)
// Accept a single flow and write out what is read to readChan
readChan := make(chan string)
go readFlow(t, c.ln, readChan)
if err := writeFlow(c.client, c.ep, written); err != nil {
t.Errorf("%s: %v", name, err)
continue
}
// Validate that the data read is the same as the data written.
if read := <-readChan; read != written {
t.Errorf("case #%d: Read %q, wrote %q", i, read, written)
}
}
}
func TestDuplicateRoutingID(t *testing.T) {
proxy, err := proxy.New(naming.FixedRoutingID(0xbbbbbbbbbbbbbbbb), nil, "tcp", "127.0.0.1:0", "")
if err != nil {
t.Fatal(err)
}
defer proxy.Shutdown()
// Create the stream.Manager for server1 and server2, both with the same routing ID
serverRID := naming.FixedRoutingID(0x5555555555555555)
server1 := manager.InternalNew(serverRID)
server2 := manager.InternalNew(serverRID)
defer server1.Shutdown()
defer server2.Shutdown()
// First server to claim serverRID should win.
ln1, ep1, err := server1.Listen(proxy.Endpoint().Network(), proxy.Endpoint().String())
if err != nil {
t.Fatal(err)
}
defer ln1.Close()
ln2, ep2, err := server2.Listen(proxy.Endpoint().Network(), proxy.Endpoint().String())
if pattern := "routing id 00000000000000005555555555555555 is already being proxied"; err == nil || !strings.Contains(err.Error(), pattern) {
t.Errorf("Got (%v, %v, %v) want error \"...%v\" (ep1:%v)", ln2, ep2, err, pattern, ep1)
}
}
func TestProxyAuthentication(t *testing.T) {
pproxy := tsecurity.NewPrincipal("proxy")
proxy, err := proxy.New(naming.FixedRoutingID(0xbbbbbbbbbbbbbbbb), pproxy, "tcp", "127.0.0.1:0", "")
if err != nil {
t.Fatal(err)
}
defer proxy.Shutdown()
other := manager.InternalNew(naming.FixedRoutingID(0xcccccccccccccccc))
defer other.Shutdown()
vc, err := other.Dial(proxy.Endpoint())
if err != nil {
t.Fatal(err)
}
flow, err := vc.Connect()
if err != nil {
t.Fatal(err)
}
if got, want := flow.RemoteBlessings(), pproxy.BlessingStore().Default(); !reflect.DeepEqual(got, want) {
t.Errorf("Proxy authenticated as [%v], want [%v]", got, want)
}
}
func TestServerBlessings(t *testing.T) {
proxy, err := proxy.New(naming.FixedRoutingID(0xbbbbbbbbbbbbbbbb), nil, "tcp", "127.0.0.1:0", "")
if err != nil {
t.Fatal(err)
}
server := manager.InternalNew(naming.FixedRoutingID(0x5555555555555555))
defer server.Shutdown()
pserver := tsecurity.NewPrincipal("server")
ln, ep, err := server.Listen(proxy.Endpoint().Network(), proxy.Endpoint().String(), vc.LocalPrincipal{pserver})
if err != nil {
t.Fatal(err)
}
defer ln.Close()
go func() {
for {
if _, err := ln.Accept(); err != nil {
return
}
}
}()
client := manager.InternalNew(naming.FixedRoutingID(0xcccccccccccccccc))
defer client.Shutdown()
vc, err := client.Dial(ep)
if err != nil {
t.Fatal(err)
}
flow, err := vc.Connect()
if err != nil {
t.Fatal(err)
}
if got, want := flow.RemoteBlessings(), pserver.BlessingStore().Default(); !reflect.DeepEqual(got, want) {
t.Errorf("Got [%v] want [%v]", got, want)
}
}
func TestHostPort(t *testing.T) {
proxy, err := proxy.New(naming.FixedRoutingID(0xbbbbbbbbbbbbbbbb), nil, "tcp", "127.0.0.1:0", "")
if err != nil {
t.Fatal(err)
}
defer proxy.Shutdown()
server := manager.InternalNew(naming.FixedRoutingID(0x5555555555555555))
defer server.Shutdown()
addr := proxy.Endpoint().Addr().String()
port := addr[strings.LastIndex(addr, ":"):]
ln, _, err := server.Listen("veyron", "127.0.0.1"+port)
if err != nil {
t.Fatal(err)
}
ln.Close()
}
func TestClientBecomesServer(t *testing.T) {
proxy, err := proxy.New(naming.FixedRoutingID(0xbbbbbbbbbbbbbbbb), nil, "tcp", "127.0.0.1:0", "")
if err != nil {
t.Fatal(err)
}
server := manager.InternalNew(naming.FixedRoutingID(0x5555555555555555))
client1 := manager.InternalNew(naming.FixedRoutingID(0x1111111111111111))
client2 := manager.InternalNew(naming.FixedRoutingID(0x2222222222222222))
defer proxy.Shutdown()
defer server.Shutdown()
defer client1.Shutdown()
defer client2.Shutdown()
lnS, epS, err := server.Listen(proxy.Endpoint().Network(), proxy.Endpoint().String())
if err != nil {
t.Fatal(err)
}
defer lnS.Close()
rchan := make(chan string)
// client1 must connect to the proxy to speak to the server.
// Keep a VC and Flow open to the server, to ensure that the proxy
// maintains routing information (at some point, inactive VIFs
// should be garbage collected, so this ensures that the VIF
// is "active")
if vc, err := client1.Dial(epS); err != nil {
t.Fatal(err)
} else if flow, err := vc.Connect(); err != nil {
t.Fatal(err)
} else {
defer flow.Close()
}
// Now client1 becomes a server
lnC, epC, err := client1.Listen(proxy.Endpoint().Network(), proxy.Endpoint().String())
if err != nil {
t.Fatal(err)
}
defer lnC.Close()
// client2 should be able to talk to client1 through the proxy
rchan = make(chan string)
go readFlow(t, lnC, rchan)
if err := writeFlow(client2, epC, "daffy duck"); err != nil {
t.Fatal("client2 failed to chat with client1: %v", err)
}
if got, want := <-rchan, "daffy duck"; got != want {
t.Fatal("client2->client1 got %q want %q", got, want)
}
}
func writeFlow(mgr stream.Manager, ep naming.Endpoint, data string) error {
vc, err := mgr.Dial(ep)
if err != nil {
return fmt.Errorf("manager.Dial(%v) failed: %v", ep, err)
}
flow, err := vc.Connect()
if err != nil {
return fmt.Errorf("vc.Connect failed: %v", err)
}
defer flow.Close()
if _, err := flow.Write([]byte(data)); err != nil {
return fmt.Errorf("flow.Write failed: %v", err)
}
return nil
}
func readFlow(t *testing.T, ln stream.Listener, read chan<- string) {
defer close(read)
flow, err := ln.Accept()
if err != nil {
t.Error(err)
return
}
var tmp [1024]byte
var buf bytes.Buffer
for {
n, err := flow.Read(tmp[:])
if err == io.EOF {
read <- buf.String()
return
}
if err != nil {
t.Error(err)
return
}
buf.Write(tmp[:n])
}
}