Merge "ref/services/groups: Switch to the new XServer API."
diff --git a/lib/xrpc/xserver.go b/lib/xrpc/xserver.go
index 30bb7c1..971d1aa 100644
--- a/lib/xrpc/xserver.go
+++ b/lib/xrpc/xserver.go
@@ -13,7 +13,7 @@
 	"v.io/v23/security"
 )
 
-type Server struct {
+type server struct {
 	s rpc.Server
 }
 
@@ -35,7 +35,7 @@
 // Invoker interface, the Invoker is used to invoke methods directly,
 // without reflection.  If name is an empty string, no attempt will
 // made to publish.
-func NewServer(ctx *context.T, name string, object interface{}, auth security.Authorizer, opts ...rpc.ServerOpt) (*Server, error) {
+func NewServer(ctx *context.T, name string, object interface{}, auth security.Authorizer, opts ...rpc.ServerOpt) (rpc.XServer, error) {
 	s, err := v23.NewServer(ctx, opts...)
 	if err != nil {
 		return nil, err
@@ -48,7 +48,7 @@
 		s.Stop()
 		return nil, err
 	}
-	return &Server{s: s}, nil
+	return &server{s: s}, nil
 }
 
 // NewDispatchingServer creates a new Server instance to serve a given dispatcher.
@@ -68,7 +68,7 @@
 // method which will in turn return the object and security.Authorizer
 // used to serve the actual RPC call.  If name is an empty string, no
 // attempt will made to publish that name to a mount table.
-func NewDispatchingServer(ctx *context.T, name string, disp rpc.Dispatcher, opts ...rpc.ServerOpt) (*Server, error) {
+func NewDispatchingServer(ctx *context.T, name string, disp rpc.Dispatcher, opts ...rpc.ServerOpt) (rpc.XServer, error) {
 	s, err := v23.NewServer(ctx, opts...)
 	if err != nil {
 		return nil, err
@@ -79,24 +79,24 @@
 	if err = s.ServeDispatcher(name, disp); err != nil {
 		return nil, err
 	}
-	return &Server{s: s}, nil
+	return &server{s: s}, nil
 }
 
 // AddName adds the specified name to the mount table for this server.
 // AddName may be called multiple times.
-func (s *Server) AddName(name string) error {
+func (s *server) AddName(name string) error {
 	return s.s.AddName(name)
 }
 
 // RemoveName removes the specified name from the mount table.
 // RemoveName may be called multiple times.
-func (s *Server) RemoveName(name string) {
+func (s *server) RemoveName(name string) {
 	s.s.RemoveName(name)
 }
 
 // Status returns the current status of the server, see ServerStatus
 // for details.
-func (s *Server) Status() rpc.ServerStatus {
+func (s *server) Status() rpc.ServerStatus {
 	return s.s.Status()
 }
 
@@ -104,13 +104,13 @@
 // be sent. The Server will not block sending data over this channel
 // and hence change events may be lost if the caller doesn't ensure
 // there is sufficient buffering in the channel.
-func (s *Server) WatchNetwork(ch chan<- rpc.NetworkChange) {
+func (s *server) WatchNetwork(ch chan<- rpc.NetworkChange) {
 	s.s.WatchNetwork(ch)
 }
 
 // UnwatchNetwork unregisters a channel previously registered using
 // WatchNetwork.
-func (s *Server) UnwatchNetwork(ch chan<- rpc.NetworkChange) {
+func (s *server) UnwatchNetwork(ch chan<- rpc.NetworkChange) {
 	s.s.UnwatchNetwork(ch)
 }
 
@@ -118,6 +118,6 @@
 // rejected, but any in-flight calls are allowed to complete.  All
 // published mountpoints are unmounted.  This call waits for this
 // process to complete, and returns once the server has been shut down.
-func (s *Server) Stop() error {
+func (s *server) Stop() error {
 	return s.s.Stop()
 }
diff --git a/runtime/factories/chrome/chrome.go b/runtime/factories/chrome/chrome.go
index 8245a77..c34ceae 100644
--- a/runtime/factories/chrome/chrome.go
+++ b/runtime/factories/chrome/chrome.go
@@ -15,10 +15,14 @@
 
 	"v.io/x/ref/lib/flags"
 	"v.io/x/ref/runtime/internal"
+	_ "v.io/x/ref/runtime/internal/flow/protocols/ws"
+	_ "v.io/x/ref/runtime/internal/flow/protocols/wsh_nacl"
 	"v.io/x/ref/runtime/internal/lib/websocket"
+	grt "v.io/x/ref/runtime/internal/rt"
+
+	// TODO(suharshs): Remove this after we switch to the flow protocols.
 	_ "v.io/x/ref/runtime/internal/rpc/protocols/ws"
 	_ "v.io/x/ref/runtime/internal/rpc/protocols/wsh_nacl"
-	grt "v.io/x/ref/runtime/internal/rt"
 )
 
 var commonFlags *flags.Flags
diff --git a/runtime/factories/fake/fake.go b/runtime/factories/fake/fake.go
index fa0e5fe..06d139b 100644
--- a/runtime/factories/fake/fake.go
+++ b/runtime/factories/fake/fake.go
@@ -16,6 +16,8 @@
 	"v.io/v23/rpc"
 
 	_ "v.io/x/ref/runtime/internal/flow/protocols/tcp"
+	_ "v.io/x/ref/runtime/internal/flow/protocols/ws"
+	_ "v.io/x/ref/runtime/internal/flow/protocols/wsh"
 	"v.io/x/ref/runtime/internal/lib/websocket"
 
 	// TODO(suharshs): Remove these once we switch to the flow protocols.
diff --git a/runtime/factories/gce/gce.go b/runtime/factories/gce/gce.go
index f99417c..584c823 100644
--- a/runtime/factories/gce/gce.go
+++ b/runtime/factories/gce/gce.go
@@ -21,6 +21,8 @@
 	"v.io/x/ref/lib/flags"
 	"v.io/x/ref/runtime/internal"
 	_ "v.io/x/ref/runtime/internal/flow/protocols/tcp"
+	_ "v.io/x/ref/runtime/internal/flow/protocols/ws"
+	_ "v.io/x/ref/runtime/internal/flow/protocols/wsh"
 	"v.io/x/ref/runtime/internal/gce"
 	"v.io/x/ref/runtime/internal/lib/appcycle"
 	"v.io/x/ref/runtime/internal/lib/websocket"
diff --git a/runtime/factories/generic/generic.go b/runtime/factories/generic/generic.go
index 651f710..61d58c6 100644
--- a/runtime/factories/generic/generic.go
+++ b/runtime/factories/generic/generic.go
@@ -16,6 +16,8 @@
 	"v.io/x/ref/lib/flags"
 	"v.io/x/ref/runtime/internal"
 	_ "v.io/x/ref/runtime/internal/flow/protocols/tcp"
+	_ "v.io/x/ref/runtime/internal/flow/protocols/ws"
+	_ "v.io/x/ref/runtime/internal/flow/protocols/wsh"
 	"v.io/x/ref/runtime/internal/lib/appcycle"
 	"v.io/x/ref/runtime/internal/lib/websocket"
 	grt "v.io/x/ref/runtime/internal/rt"
diff --git a/runtime/factories/roaming/roaming.go b/runtime/factories/roaming/roaming.go
index c139bfc..aca495d 100644
--- a/runtime/factories/roaming/roaming.go
+++ b/runtime/factories/roaming/roaming.go
@@ -30,6 +30,8 @@
 	"v.io/x/ref/lib/security/securityflag"
 	"v.io/x/ref/runtime/internal"
 	_ "v.io/x/ref/runtime/internal/flow/protocols/tcp"
+	_ "v.io/x/ref/runtime/internal/flow/protocols/ws"
+	_ "v.io/x/ref/runtime/internal/flow/protocols/wsh"
 	"v.io/x/ref/runtime/internal/lib/appcycle"
 	"v.io/x/ref/runtime/internal/lib/websocket"
 	irpc "v.io/x/ref/runtime/internal/rpc"
diff --git a/runtime/factories/static/static.go b/runtime/factories/static/static.go
index 9665d4d..9037f73 100644
--- a/runtime/factories/static/static.go
+++ b/runtime/factories/static/static.go
@@ -18,6 +18,8 @@
 	"v.io/x/ref/lib/security/securityflag"
 	"v.io/x/ref/runtime/internal"
 	_ "v.io/x/ref/runtime/internal/flow/protocols/tcp"
+	_ "v.io/x/ref/runtime/internal/flow/protocols/ws"
+	_ "v.io/x/ref/runtime/internal/flow/protocols/wsh"
 	"v.io/x/ref/runtime/internal/lib/appcycle"
 	"v.io/x/ref/runtime/internal/lib/websocket"
 
diff --git a/runtime/internal/flow/protocols/wsh_nacl/doc.go b/runtime/internal/flow/protocols/wsh_nacl/doc.go
new file mode 100644
index 0000000..ebeefda
--- /dev/null
+++ b/runtime/internal/flow/protocols/wsh_nacl/doc.go
@@ -0,0 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package wsh_nacl registers the websocket 'hybrid' protocol for nacl
+// architectures. It will only be built if on the nacl architecture.
+package wsh_nacl
diff --git a/runtime/internal/flow/protocols/wsh_nacl/init.go b/runtime/internal/flow/protocols/wsh_nacl/init.go
new file mode 100644
index 0000000..f7874de
--- /dev/null
+++ b/runtime/internal/flow/protocols/wsh_nacl/init.go
@@ -0,0 +1,22 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build nacl
+
+package wsh_nacl
+
+import (
+	"v.io/v23/flow"
+
+	websocket "v.io/x/ref/runtime/internal/lib/xwebsocket"
+)
+
+func init() {
+	// We limit wsh to ws since in general nacl does not allow direct access
+	// to TCP/UDP networking.
+	wshNaCl := websocket.WS{}
+	flow.RegisterProtocol("wsh", wshNaCl, "ws4", "ws6")
+	flow.RegisterProtocol("wsh4", wshNaCl, "ws4")
+	flow.RegisterProtocol("wsh6", wshNaCl, "ws6")
+}
diff --git a/runtime/internal/lib/xwebsocket/conn_nacl.go b/runtime/internal/lib/xwebsocket/conn_nacl.go
new file mode 100644
index 0000000..35cc5bb
--- /dev/null
+++ b/runtime/internal/lib/xwebsocket/conn_nacl.go
@@ -0,0 +1,92 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build nacl
+
+package xwebsocket
+
+import (
+	"net"
+	"net/url"
+	"runtime/ppapi"
+	"sync"
+	"time"
+
+	"v.io/v23/context"
+	"v.io/v23/flow"
+)
+
+// Ppapi instance which must be set before the Dial is called.
+var PpapiInstance ppapi.Instance
+
+func WebsocketConn(address string, ws *ppapi.WebsocketConn) flow.Conn {
+	return &wrappedConn{
+		address: address,
+		ws:      ws,
+	}
+}
+
+type wrappedConn struct {
+	address   string
+	ws        *ppapi.WebsocketConn
+	readLock  sync.Mutex
+	writeLock sync.Mutex
+}
+
+func Dial(ctx *context.T, protocol, address string, timeout time.Duration) (flow.Conn, error) {
+	inst := PpapiInstance
+	u, err := url.Parse("ws://" + address)
+	if err != nil {
+		return nil, err
+	}
+
+	ws, err := inst.DialWebsocket(u.String())
+	if err != nil {
+		return nil, err
+	}
+	return WebsocketConn(address, ws), nil
+}
+
+func Resolve(ctx *context.T, protocol, address string) (string, string, error) {
+	return "ws", address, nil
+}
+
+func (c *wrappedConn) ReadMsg() ([]byte, error) {
+	defer c.readLock.Unlock()
+	c.readLock.Lock()
+	return c.ws.ReceiveMessage()
+}
+
+func (c *wrappedConn) WriteMsg(bufs ...[]byte) (int, error) {
+	defer c.writeLock.Unlock()
+	c.writeLock.Lock()
+	var b []byte
+	for _, buf := range bufs {
+		b = append(b, buf...)
+	}
+	if err := c.ws.SendMessage(b); err != nil {
+		return 0, err
+	}
+	return len(b), nil
+}
+
+func (c *wrappedConn) Close() error {
+	return c.ws.Close()
+}
+
+func (c *wrappedConn) LocalAddr() net.Addr {
+	return websocketAddr{s: c.address}
+}
+
+type websocketAddr struct {
+	s string
+}
+
+func (websocketAddr) Network() string {
+	return "ws"
+}
+
+func (w websocketAddr) String() string {
+	return w.s
+}
diff --git a/runtime/internal/lib/xwebsocket/errors.vdl b/runtime/internal/lib/xwebsocket/errors.vdl
index f80bdf6..5d27eb3 100644
--- a/runtime/internal/lib/xwebsocket/errors.vdl
+++ b/runtime/internal/lib/xwebsocket/errors.vdl
@@ -5,5 +5,6 @@
 package xwebsocket
 
 error (
-  ListenerClosed() {"en":"listener is already closed"}
+  ListenerClosed() {"en":"listener is already closed."}
+  ListenCalledInNaCl() {"en": "Listen cannot be called in NaCl code."}
 )
\ No newline at end of file
diff --git a/runtime/internal/lib/xwebsocket/errors.vdl.go b/runtime/internal/lib/xwebsocket/errors.vdl.go
index 47ee8b0..e436641 100644
--- a/runtime/internal/lib/xwebsocket/errors.vdl.go
+++ b/runtime/internal/lib/xwebsocket/errors.vdl.go
@@ -15,14 +15,21 @@
 )
 
 var (
-	ErrListenerClosed = verror.Register("v.io/x/ref/runtime/internal/lib/xwebsocket.ListenerClosed", verror.NoRetry, "{1:}{2:} listener is already closed")
+	ErrListenerClosed     = verror.Register("v.io/x/ref/runtime/internal/lib/xwebsocket.ListenerClosed", verror.NoRetry, "{1:}{2:} listener is already closed.")
+	ErrListenCalledInNaCl = verror.Register("v.io/x/ref/runtime/internal/lib/xwebsocket.ListenCalledInNaCl", verror.NoRetry, "{1:}{2:} Listen cannot be called in NaCl code.")
 )
 
 func init() {
-	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrListenerClosed.ID), "{1:}{2:} listener is already closed")
+	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrListenerClosed.ID), "{1:}{2:} listener is already closed.")
+	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrListenCalledInNaCl.ID), "{1:}{2:} Listen cannot be called in NaCl code.")
 }
 
 // NewErrListenerClosed returns an error with the ErrListenerClosed ID.
 func NewErrListenerClosed(ctx *context.T) error {
 	return verror.New(ErrListenerClosed, ctx)
 }
+
+// NewErrListenCalledInNaCl returns an error with the ErrListenCalledInNaCl ID.
+func NewErrListenCalledInNaCl(ctx *context.T) error {
+	return verror.New(ErrListenCalledInNaCl, ctx)
+}
diff --git a/runtime/internal/lib/xwebsocket/protocol.go b/runtime/internal/lib/xwebsocket/ws.go
similarity index 100%
rename from runtime/internal/lib/xwebsocket/protocol.go
rename to runtime/internal/lib/xwebsocket/ws.go
diff --git a/runtime/internal/lib/xwebsocket/hybrid.go b/runtime/internal/lib/xwebsocket/wsh.go
similarity index 98%
rename from runtime/internal/lib/xwebsocket/hybrid.go
rename to runtime/internal/lib/xwebsocket/wsh.go
index c69348a..b563ac6 100644
--- a/runtime/internal/lib/xwebsocket/hybrid.go
+++ b/runtime/internal/lib/xwebsocket/wsh.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !nacl
+
 package xwebsocket
 
 import (
diff --git a/runtime/internal/lib/xwebsocket/wsh_nacl.go b/runtime/internal/lib/xwebsocket/wsh_nacl.go
new file mode 100644
index 0000000..1e8e58d
--- /dev/null
+++ b/runtime/internal/lib/xwebsocket/wsh_nacl.go
@@ -0,0 +1,38 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build nacl
+
+package xwebsocket
+
+import (
+	"net/url"
+	"time"
+
+	"v.io/v23/context"
+	"v.io/v23/flow"
+)
+
+type WS struct{}
+
+func (WS) Dial(ctx *context.T, protocol, address string, timeout time.Duration) (flow.Conn, error) {
+	inst := PpapiInstance
+	u, err := url.Parse("ws://" + address)
+	if err != nil {
+		return nil, err
+	}
+	ws, err := inst.DialWebsocket(u.String())
+	if err != nil {
+		return nil, err
+	}
+	return WebsocketConn(address, ws), nil
+}
+
+func (WS) Resolve(ctx *context.T, protocol, address string) (string, string, error) {
+	return "ws", address, nil
+}
+
+func (WS) Listen(ctx *context.T, protocol, address string) (flow.Listener, error) {
+	return nil, NewErrListenCalledInNaCl(ctx)
+}
diff --git a/services/role/roled/internal/role_test.go b/services/role/roled/internal/role_test.go
index adb3b17..e59f6d6 100644
--- a/services/role/roled/internal/role_test.go
+++ b/services/role/roled/internal/role_test.go
@@ -18,15 +18,17 @@
 	"v.io/v23/security"
 	"v.io/v23/verror"
 	vsecurity "v.io/x/ref/lib/security"
+	"v.io/x/ref/lib/xrpc"
 	"v.io/x/ref/services/role"
 	irole "v.io/x/ref/services/role/roled/internal"
+	"v.io/x/ref/test"
 	"v.io/x/ref/test/testutil"
 
 	_ "v.io/x/ref/runtime/factories/generic"
 )
 
 func TestSeekBlessings(t *testing.T) {
-	ctx, shutdown := v23.Init()
+	ctx, shutdown := test.V23Init()
 	defer shutdown()
 
 	workdir, err := ioutil.TempDir("", "test-role-server-")
@@ -38,9 +40,9 @@
 	// Role A is a restricted role, i.e. it can be used in sensitive Permissions.
 	roleAConf := irole.Config{
 		Members: []security.BlessingPattern{
-			"root/users/user1/_role",
-			"root/users/user2/_role",
-			"root/users/user3", // _role implied
+			"test-blessing/users/user1/_role",
+			"test-blessing/users/user2/_role",
+			"test-blessing/users/user3", // _role implied
 		},
 		Extend: true,
 	}
@@ -49,15 +51,15 @@
 	// Role B is an unrestricted role.
 	roleBConf := irole.Config{
 		Members: []security.BlessingPattern{
-			"root/users/user1/_role",
-			"root/users/user3/_role",
+			"test-blessing/users/user1/_role",
+			"test-blessing/users/user3/_role",
 		},
 		Audit:  true,
 		Extend: false,
 	}
 	irole.WriteConfig(t, roleBConf, filepath.Join(workdir, "B.conf"))
 
-	root := testutil.NewIDProvider("root")
+	root := testutil.IDProviderFromPrincipal(v23.GetPrincipal(ctx))
 
 	var (
 		user1  = newPrincipalContext(t, ctx, root, "users/user1")
@@ -69,10 +71,10 @@
 	)
 
 	testServerCtx := newPrincipalContext(t, ctx, root, "testserver")
-	server, testAddr := newServer(t, testServerCtx)
 	tDisp := &testDispatcher{}
-	if err := server.ServeDispatcher("", tDisp); err != nil {
-		t.Fatalf("server.ServeDispatcher failed: %v", err)
+	_, err = xrpc.NewDispatchingServer(testServerCtx, "test", tDisp)
+	if err != nil {
+		t.Fatalf("NewDispatchingServer failed: %v", err)
 	}
 
 	const noErr = ""
@@ -88,18 +90,18 @@
 		{user3, "unknown", verror.ErrNoAccess.ID, nil},
 
 		{user1, "A", verror.ErrNoAccess.ID, nil},
-		{user1R, "A", noErr, []string{"root/roles/A/root/users/user1"}},
+		{user1R, "A", noErr, []string{"test-blessing/roles/A/test-blessing/users/user1"}},
 		{user2, "A", verror.ErrNoAccess.ID, nil},
-		{user2R, "A", noErr, []string{"root/roles/A/root/users/user2"}},
+		{user2R, "A", noErr, []string{"test-blessing/roles/A/test-blessing/users/user2"}},
 		{user3, "A", verror.ErrNoAccess.ID, nil},
-		{user3R, "A", noErr, []string{"root/roles/A/root/users/user3/_role/bar", "root/roles/A/root/users/user3/_role/foo"}},
+		{user3R, "A", noErr, []string{"test-blessing/roles/A/test-blessing/users/user3/_role/bar", "test-blessing/roles/A/test-blessing/users/user3/_role/foo"}},
 
 		{user1, "B", verror.ErrNoAccess.ID, nil},
-		{user1R, "B", noErr, []string{"root/roles/B"}},
+		{user1R, "B", noErr, []string{"test-blessing/roles/B"}},
 		{user2, "B", verror.ErrNoAccess.ID, nil},
 		{user2R, "B", verror.ErrNoAccess.ID, nil},
 		{user3, "B", verror.ErrNoAccess.ID, nil},
-		{user3R, "B", noErr, []string{"root/roles/B"}},
+		{user3R, "B", noErr, []string{"test-blessing/roles/B"}},
 	}
 	addr := newRoleServer(t, newPrincipalContext(t, ctx, root, "roles"), workdir)
 	for _, tc := range testcases {
@@ -113,7 +115,7 @@
 			continue
 		}
 		previousBlessings, _ := v23.GetPrincipal(tc.ctx).BlessingStore().Set(blessings, security.AllPrincipals)
-		blessingNames, rejected := callTest(t, tc.ctx, testAddr)
+		blessingNames, rejected := callTest(t, tc.ctx, "test")
 		if !reflect.DeepEqual(blessingNames, tc.blessings) {
 			t.Errorf("unexpected blessings for (%q, %q). Got %q, expected %q", user, tc.role, blessingNames, tc.blessings)
 		}
@@ -125,7 +127,7 @@
 }
 
 func TestPeerBlessingCaveats(t *testing.T) {
-	ctx, shutdown := v23.Init()
+	ctx, shutdown := test.V23Init()
 	defer shutdown()
 
 	workdir, err := ioutil.TempDir("", "test-role-server-")
@@ -135,16 +137,16 @@
 	defer os.RemoveAll(workdir)
 
 	roleConf := irole.Config{
-		Members: []security.BlessingPattern{"root/users/user/_role"},
+		Members: []security.BlessingPattern{"test-blessing/users/user/_role"},
 		Peers: []security.BlessingPattern{
-			security.BlessingPattern("root/peer1"),
-			security.BlessingPattern("root/peer3"),
+			security.BlessingPattern("test-blessing/peer1"),
+			security.BlessingPattern("test-blessing/peer3"),
 		},
 	}
 	irole.WriteConfig(t, roleConf, filepath.Join(workdir, "role.conf"))
 
 	var (
-		root  = testutil.NewIDProvider("root")
+		root  = testutil.IDProviderFromPrincipal(v23.GetPrincipal(ctx))
 		user  = newPrincipalContext(t, ctx, root, "users/user/_role")
 		peer1 = newPrincipalContext(t, ctx, root, "peer1")
 		peer2 = newPrincipalContext(t, ctx, root, "peer2")
@@ -154,17 +156,17 @@
 	roleAddr := newRoleServer(t, newPrincipalContext(t, ctx, root, "roles"), workdir)
 
 	tDisp := &testDispatcher{}
-	server1, testPeer1 := newServer(t, peer1)
-	if err := server1.ServeDispatcher("", tDisp); err != nil {
-		t.Fatalf("server.ServeDispatcher failed: %v", err)
+	_, err = xrpc.NewDispatchingServer(peer1, "peer1", tDisp)
+	if err != nil {
+		t.Fatalf("NewDispatchingServer failed: %v", err)
 	}
-	server2, testPeer2 := newServer(t, peer2)
-	if err := server2.ServeDispatcher("", tDisp); err != nil {
-		t.Fatalf("server.ServeDispatcher failed: %v", err)
+	_, err = xrpc.NewDispatchingServer(peer2, "peer2", tDisp)
+	if err != nil {
+		t.Fatalf("NewDispatchingServer failed: %v", err)
 	}
-	server3, testPeer3 := newServer(t, peer3)
-	if err := server3.ServeDispatcher("", tDisp); err != nil {
-		t.Fatalf("server.ServeDispatcher failed: %v", err)
+	_, err = xrpc.NewDispatchingServer(peer3, "peer3", tDisp)
+	if err != nil {
+		t.Fatalf("NewDispatchingServer failed: %v", err)
 	}
 
 	c := role.RoleClient(naming.Join(roleAddr, "role"))
@@ -179,9 +181,9 @@
 		blessingNames []string
 		rejectedNames []string
 	}{
-		{testPeer1, []string{"root/roles/role"}, nil},
-		{testPeer2, nil, []string{"root/roles/role"}},
-		{testPeer3, []string{"root/roles/role"}, nil},
+		{"peer1", []string{"test-blessing/roles/role"}, nil},
+		{"peer2", nil, []string{"test-blessing/roles/role"}},
+		{"peer3", []string{"test-blessing/roles/role"}, nil},
 	}
 	for i, tc := range testcases {
 		blessingNames, rejected := callTest(t, user, tc.peer)
@@ -199,7 +201,7 @@
 }
 
 func TestGlob(t *testing.T) {
-	ctx, shutdown := v23.Init()
+	ctx, shutdown := test.V23Init()
 	defer shutdown()
 
 	workdir, err := ioutil.TempDir("", "test-role-server-")
@@ -212,17 +214,17 @@
 	os.Mkdir(filepath.Join(workdir, "sub3"), 0700)
 
 	// Role that user1 has access to.
-	roleAConf := irole.Config{Members: []security.BlessingPattern{"root/user1"}}
+	roleAConf := irole.Config{Members: []security.BlessingPattern{"test-blessing/user1"}}
 	irole.WriteConfig(t, roleAConf, filepath.Join(workdir, "A.conf"))
 	irole.WriteConfig(t, roleAConf, filepath.Join(workdir, "sub1/B.conf"))
 	irole.WriteConfig(t, roleAConf, filepath.Join(workdir, "sub1/C.conf"))
 	irole.WriteConfig(t, roleAConf, filepath.Join(workdir, "sub1/sub2/D.conf"))
 
 	// Role that user2 has access to.
-	roleBConf := irole.Config{Members: []security.BlessingPattern{"root/user2"}}
+	roleBConf := irole.Config{Members: []security.BlessingPattern{"test-blessing/user2"}}
 	irole.WriteConfig(t, roleBConf, filepath.Join(workdir, "sub1/sub2/X.conf"))
 
-	root := testutil.NewIDProvider("root")
+	root := testutil.IDProviderFromPrincipal(v23.GetPrincipal(ctx))
 	user1 := newPrincipalContext(t, ctx, root, "user1/_role")
 	user2 := newPrincipalContext(t, ctx, root, "user2/_role")
 	user3 := newPrincipalContext(t, ctx, root, "user3/_role")
@@ -274,24 +276,11 @@
 }
 
 func newRoleServer(t *testing.T, ctx *context.T, dir string) string {
-	server, addr := newServer(t, ctx)
-	if err := server.ServeDispatcher("", irole.NewDispatcher(dir, addr)); err != nil {
+	_, err := xrpc.NewDispatchingServer(ctx, "role", irole.NewDispatcher(dir, "role"))
+	if err != nil {
 		t.Fatalf("ServeDispatcher failed: %v", err)
 	}
-	return addr
-}
-
-func newServer(t *testing.T, ctx *context.T) (rpc.Server, string) {
-	server, err := v23.NewServer(ctx)
-	if err != nil {
-		t.Fatalf("NewServer() failed: %v", err)
-	}
-	spec := rpc.ListenSpec{Addrs: rpc.ListenAddrs{{"tcp", "127.0.0.1:0"}}}
-	endpoints, err := server.Listen(spec)
-	if err != nil {
-		t.Fatalf("Listen(%v) failed: %v", spec, err)
-	}
-	return server, endpoints[0].Name()
+	return "role"
 }
 
 func callTest(t *testing.T, ctx *context.T, addr string) (blessingNames []string, rejected []security.RejectedBlessing) {