veyron/tools/vrpc: Update to new __Signature and VDL values.

The original vrpc tool was still using the old Signature support,
and specified values using the old vom/JSON support, both of
which are deprecated and need to be removed.

The new vrpc implemented in this CL uses the new __Signature
support, and specifies values using VDL syntax.

There are remaining TODOs to clean up the formatting of the
output, and handle streaming input arguments.  Those will come in
separate follow-up CLs; this CL was getting too big already, and
is necessary as a first-step so that we can remove the deprecated
__Signature and vom1 support.

Change-Id: Ia65d5be4a046dd8bec381bfbcbd9a02472ac7199
MultiPart: 1/3
diff --git a/tools/vrpc/doc.go b/tools/vrpc/doc.go
index ffb250a..f5ff56d 100644
--- a/tools/vrpc/doc.go
+++ b/tools/vrpc/doc.go
@@ -2,16 +2,16 @@
 // DO NOT UPDATE MANUALLY
 
 /*
-The vrpc tool facilitates interaction with Veyron RPC servers. In particular, it
-can be used to 1) find out what API a Veyron RPC server exports and 2) send
-requests to a Veyron RPC server.
+The vrpc tool provides command-line access to Vanadium servers via Remote
+Procedure Call.
 
 Usage:
    vrpc <command>
 
 The vrpc commands are:
-   describe    Describe the API of an Veyron RPC server
-   invoke      Invoke a method of an Veyron RPC server
+   signature   Describe the interfaces of a Vanadium server
+   call        Call a method of a Vanadium server
+   identify    Reveal blessings presented by a Vanadium server
    help        Display help for commands or topics
 Run "vrpc help [command]" for command usage.
 
@@ -38,44 +38,73 @@
    local namespace root; can be repeated to provided multiple roots
  -veyron.vtrace.cache_size=1024
    The number of vtrace traces to store in memory.
- -veyron.vtrace.dump_on_shutdown=false
+ -veyron.vtrace.collect_regexp=
+   Spans and annotations that match this regular expression will trigger trace
+   collection.
+ -veyron.vtrace.dump_on_shutdown=true
    If true, dump all stored traces on runtime shutdown.
  -veyron.vtrace.sample_rate=0
    Rate (from 0.0 to 1.0) to sample vtrace traces.
  -vmodule=
    comma-separated list of pattern=N settings for file-filtered logging
 
-Vrpc Describe
+Vrpc Signature
 
-Describe connects to the Veyron RPC server identified by <server>, finds out
-what its API is, and outputs a succint summary of this API to the standard
-output.
+Signature connects to the Vanadium server identified by <server>.
+
+If no [method] is provided, returns all interfaces implemented by the server.
+
+If a [method] is provided, returns the signature of just that method.
 
 Usage:
-   vrpc describe <server>
+   vrpc signature <server> [method]
 
-<server> identifies the Veyron RPC server. It can either be the object address
-of the server or an Object name in which case the vrpc will use Veyron's name
-resolution to match this name to an end-point.
+<server> identifies a Vanadium server.  It can either be the object address of
+the server, or an object name that will be resolved to an end-point.
 
-Vrpc Invoke
+[method] is the optional server method name.
 
-Invoke connects to the Veyron RPC server identified by <server>, invokes the
-method identified by <method>, supplying the arguments identified by <args>, and
-outputs the results of the invocation to the standard output.
+Vrpc Call
+
+Call connects to the Vanadium server identified by <server> and calls the
+<method> with the given positional [args...], returning results on stdout.
+
+TODO(toddw): stdin is read for streaming arguments sent to the server.  An EOF
+on stdin (e.g. via ^D) causes the send stream to be closed.
+
+Regardless of whether the call is streaming, the main goroutine blocks for
+streaming and positional results received from the server.
+
+All input arguments (both positional and streaming) are specified as VDL
+expressions, with commas separating multiple expressions.  Positional arguments
+may also be specified as separate command-line arguments.  Streaming arguments
+may also be specified as separate newline-terminated expressions.
+
+The method signature is always retrieved from the server as a first step.  This
+makes it easier to input complex typed arguments, since the top-level type for
+each argument is implicit and doesn't need to be specified.
 
 Usage:
-   vrpc invoke <server> <method> <args>
+   vrpc call <server> <method> [args...]
 
-<server> identifies the Veyron RPC server. It can either be the object address
-of the server or an Object name in which case the vrpc will use Veyron's name
-resolution to match this name to an end-point.
+<server> identifies a Vanadium server.  It can either be the object address of
+the server, or an object name that will be resolved to an end-point.
 
-<method> identifies the name of the method to be invoked.
+<method> is the server method to call.
 
-<args> identifies the arguments of the method to be invoked. It should be a list
-of values in a VOM JSON format that can be reflected to the correct type using
-Go's reflection.
+[args...] are the positional input arguments, specified as VDL expressions.
+
+Vrpc Identify
+
+Identify connects to the Vanadium server identified by <server> and dumps out
+the blessings presented by that server (and the subset of those that are
+considered valid by the principal running this tool) to standard output.
+
+Usage:
+   vrpc identify <server>
+
+<server> identifies a Vanadium server.  It can either be the object address of
+the server, or an object name that will be resolved to an end-point.
 
 Vrpc Help
 
diff --git a/tools/vrpc/impl.go b/tools/vrpc/impl.go
deleted file mode 100644
index 9c672f4..0000000
--- a/tools/vrpc/impl.go
+++ /dev/null
@@ -1,348 +0,0 @@
-package main
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"time"
-
-	idl_test_base "v.io/core/veyron/tools/vrpc/test_base"
-	"v.io/core/veyron2"
-	"v.io/core/veyron2/context"
-	"v.io/core/veyron2/ipc"
-	"v.io/core/veyron2/naming"
-	"v.io/core/veyron2/vdl/vdlutil"
-	"v.io/core/veyron2/vom"
-	"v.io/core/veyron2/wiretype"
-	"v.io/lib/cmdline"
-
-	idl_binary "v.io/core/veyron2/services/mgmt/binary"
-	idl_device "v.io/core/veyron2/services/mgmt/device"
-)
-
-const serverDesc = `
-<server> identifies the Veyron RPC server. It can either be the object address of
-the server or an Object name in which case the vrpc will use Veyron's name
-resolution to match this name to an end-point.
-`
-const methodDesc = `
-<method> identifies the name of the method to be invoked.
-`
-const argsDesc = `
-<args> identifies the arguments of the method to be invoked. It should be a list
-of values in a VOM JSON format that can be reflected to the correct type
-using Go's reflection.
-`
-
-var cmdDescribe = &cmdline.Command{
-	Run:   runDescribe,
-	Name:  "describe",
-	Short: "Describe the API of an Veyron RPC server",
-	Long: `
-Describe connects to the Veyron RPC server identified by <server>, finds out what
-its API is, and outputs a succint summary of this API to the standard output.
-`,
-	ArgsName: "<server>",
-	ArgsLong: serverDesc,
-}
-
-func runDescribe(cmd *cmdline.Command, args []string) error {
-	if len(args) != 1 {
-		return cmd.UsageErrorf("describe: incorrect number of arguments, expected 1, got %d", len(args))
-	}
-	ctx, cancel := context.WithTimeout(runtime.NewContext(), time.Minute)
-	defer cancel()
-	signature, err := getSignature(ctx, cmd, args[0])
-	if err != nil {
-		return err
-	}
-
-	for methodName, methodSignature := range signature.Methods {
-		fmt.Fprintf(cmd.Stdout(), "%s\n", formatSignature(methodName, methodSignature, signature.TypeDefs))
-	}
-	return nil
-}
-
-var cmdInvoke = &cmdline.Command{
-	Run:   runInvoke,
-	Name:  "invoke",
-	Short: "Invoke a method of an Veyron RPC server",
-	Long: `
-Invoke connects to the Veyron RPC server identified by <server>, invokes the method
-identified by <method>, supplying the arguments identified by <args>, and outputs
-the results of the invocation to the standard output.
-`,
-	ArgsName: "<server> <method> <args>",
-	ArgsLong: serverDesc + methodDesc + argsDesc,
-}
-
-func runInvoke(cmd *cmdline.Command, args []string) error {
-	if len(args) < 2 {
-		return cmd.UsageErrorf("invoke: incorrect number of arguments, expected at least 2, got %d", len(args))
-	}
-	server, method, args := args[0], args[1], args[2:]
-
-	ctx, cancel := context.WithTimeout(runtime.NewContext(), time.Minute)
-	defer cancel()
-	signature, err := getSignature(ctx, cmd, server)
-	if err != nil {
-		return fmt.Errorf("invoke: failed to get signature for %v: %v", server, err)
-	}
-	if len(signature.Methods) == 0 {
-		return fmt.Errorf("invoke: empty signature for %v", server)
-	}
-
-	methodSignature, found := signature.Methods[method]
-	if !found {
-		return fmt.Errorf("invoke: method %s not found", method)
-	}
-
-	if len(args) != len(methodSignature.InArgs) {
-		return cmd.UsageErrorf("invoke: incorrect number of arguments, expected %d, got %d", len(methodSignature.InArgs), len(args))
-	}
-
-	// Register all user-defined types you would like to use.
-	//
-	// TODO(jsimsa): This is a temporary hack to get vrpc to work. When
-	// Benj implements support for decoding arbitrary structs to an
-	// empty interface, this will no longer be needed.
-	var x1 idl_test_base.Struct
-	vdlutil.Register(x1)
-	var x2 idl_device.Description
-	vdlutil.Register(x2)
-	var x3 idl_binary.Description
-	vdlutil.Register(x3)
-	var x4 naming.VDLMountedServer
-	vdlutil.Register(x4)
-	var x5 naming.VDLMountEntry
-	vdlutil.Register(x5)
-
-	// Decode the inputs from vomJSON-formatted command-line arguments.
-	inputs := make([]interface{}, len(args))
-	for i := range args {
-		var buf bytes.Buffer
-		buf.WriteString(args[i])
-		buf.WriteByte(0)
-		decoder := vom.NewDecoder(&buf)
-		if err := decoder.Decode(&inputs[i]); err != nil {
-			return fmt.Errorf("decoder.Decode() failed for %s with %v", args[i], err)
-		}
-	}
-
-	// Initiate the method invocation.
-	client := veyron2.GetClient(ctx)
-	call, err := client.StartCall(ctx, server, method, inputs)
-	if err != nil {
-		return fmt.Errorf("client.StartCall(%q, %q, %v) failed with %v", server, method, inputs, err)
-	}
-
-	fmt.Fprintf(cmd.Stdout(), "%s = ", formatInput(method, inputs))
-
-	// Handle streaming results, if the method happens to be streaming.
-	var item interface{}
-	nStream := 0
-forloop:
-	for ; ; nStream++ {
-		switch err := call.Recv(&item); err {
-		case io.EOF:
-			break forloop
-		case nil:
-			if nStream == 0 {
-				fmt.Fprintln(cmd.Stdout(), "<<")
-			}
-			fmt.Fprintf(cmd.Stdout(), "%d: %v\n", nStream, item)
-		default:
-			return fmt.Errorf("call.Recv failed with %v", err)
-		}
-	}
-	if nStream > 0 {
-		fmt.Fprintf(cmd.Stdout(), ">> ")
-	}
-
-	// Receive the outputs of the method invocation.
-	outputs := make([]interface{}, len(methodSignature.OutArgs))
-	outputPtrs := make([]interface{}, len(methodSignature.OutArgs))
-	for i := range outputs {
-		outputPtrs[i] = &outputs[i]
-	}
-	if err := call.Finish(outputPtrs...); err != nil {
-		return fmt.Errorf("call.Finish() failed with %v", err)
-	}
-	fmt.Fprintf(cmd.Stdout(), "%s\n", formatOutput(outputs))
-
-	return nil
-}
-
-var cmdIdentify = &cmdline.Command{
-	Run:   runIdentify,
-	Name:  "identify",
-	Short: "Reveal blessings presented by a Veyron RPC server",
-	Long: `
-Identify connects to the Veyron RPC server identified by <server> and dumps
-out the blessings presented by that server (and the subset of those that are
-considered valid by the principal running this tool) to standard output.
-`,
-	ArgsName: "[<server>]",
-	ArgsLong: serverDesc,
-}
-
-func runIdentify(cmd *cmdline.Command, args []string) error {
-	if len(args) > 1 {
-		return cmd.UsageErrorf("identify: incorrect number of arguments, expected at most 1, got %d", len(args))
-	}
-	ctx, cancel := context.WithTimeout(runtime.NewContext(), time.Minute)
-	defer cancel()
-	client := veyron2.GetClient(ctx)
-	var server string
-	if len(args) > 0 {
-		server = args[0]
-	}
-	// The method name does not matter - only interested in authentication,
-	// not in actually making an RPC.
-	call, err := client.StartCall(ctx, server, "", nil)
-	if err != nil {
-		return fmt.Errorf("client.StartCall(%q, \"\", nil) failed with %v", server, err)
-	}
-	valid, presented := call.RemoteBlessings()
-	fmt.Fprintf(cmd.Stdout(), "PRESENTED:  %v\nVALID:      %v\n", presented, valid)
-	return nil
-}
-
-// root returns the root command for the vrpc tool.
-func root() *cmdline.Command {
-	return &cmdline.Command{
-		Name:  "vrpc",
-		Short: "Tool for interacting with Veyron RPC servers.",
-		Long: `
-The vrpc tool facilitates interaction with Veyron RPC servers. In particular,
-it can be used to 1) find out what API a Veyron RPC server exports and
-2) send requests to a Veyron RPC server.
-`,
-		Children: []*cmdline.Command{cmdDescribe, cmdInvoke, cmdIdentify},
-	}
-}
-
-func getSignature(ctx *context.T, cmd *cmdline.Command, server string) (ipc.ServiceSignature, error) {
-	client := veyron2.GetClient(ctx)
-	call, err := client.StartCall(ctx, server, "Signature", nil)
-	if err != nil {
-		return ipc.ServiceSignature{}, fmt.Errorf("client.StartCall(%q, \"Signature\", nil) failed with %v", server, err)
-	}
-	var signature ipc.ServiceSignature
-	var sigerr error
-	if err = call.Finish(&signature, &sigerr); err != nil {
-		return ipc.ServiceSignature{}, fmt.Errorf("client.Finish(&signature, &sigerr) failed with %v", err)
-	}
-	return signature, sigerr
-}
-
-// formatWiretype generates a string representation of the specified type.
-func formatWiretype(td []vdlutil.Any, tid wiretype.TypeID) string {
-	var wt vdlutil.Any
-	if tid >= wiretype.TypeIDFirst {
-		wt = td[tid-wiretype.TypeIDFirst]
-	} else {
-		for _, pair := range wiretype.BootstrapTypes {
-			if pair.TID == tid {
-				wt = pair.WT
-			}
-		}
-		if wt == nil {
-			return fmt.Sprintf("UNKNOWN_TYPE[%v]", tid)
-		}
-	}
-
-	switch t := wt.(type) {
-	case wiretype.NamedPrimitiveType:
-		if t.Name != "" {
-			return t.Name
-		}
-		return tid.Name()
-	case wiretype.SliceType:
-		return fmt.Sprintf("[]%s", formatWiretype(td, t.Elem))
-	case wiretype.ArrayType:
-		return fmt.Sprintf("[%d]%s", t.Len, formatWiretype(td, t.Elem))
-	case wiretype.MapType:
-		return fmt.Sprintf("map[%s]%s", formatWiretype(td, t.Key), formatWiretype(td, t.Elem))
-	case wiretype.StructType:
-		var buf bytes.Buffer
-		buf.WriteString("struct{")
-		for i, fld := range t.Fields {
-			if i > 0 {
-				buf.WriteString(", ")
-			}
-			buf.WriteString(fld.Name)
-			buf.WriteString(" ")
-			buf.WriteString(formatWiretype(td, fld.Type))
-		}
-		buf.WriteString("}")
-		return buf.String()
-	default:
-		panic(fmt.Sprintf("unknown writetype: %T", wt))
-	}
-}
-
-func formatSignature(name string, ms ipc.MethodSignature, defs []vdlutil.Any) string {
-	var buf bytes.Buffer
-	fmt.Fprintf(&buf, "func %s(", name)
-	for index, arg := range ms.InArgs {
-		if index > 0 {
-			buf.WriteString(", ")
-		}
-		fmt.Fprintf(&buf, "%s %s", arg.Name, formatWiretype(defs, arg.Type))
-	}
-	buf.WriteString(") ")
-	if ms.InStream != wiretype.TypeIDInvalid || ms.OutStream != wiretype.TypeIDInvalid {
-		buf.WriteString("stream<")
-		if ms.InStream == wiretype.TypeIDInvalid {
-			buf.WriteString("_")
-		} else {
-			fmt.Fprintf(&buf, "%s", formatWiretype(defs, ms.InStream))
-		}
-		buf.WriteString(", ")
-		if ms.OutStream == wiretype.TypeIDInvalid {
-			buf.WriteString("_")
-		} else {
-			fmt.Fprintf(&buf, "%s", formatWiretype(defs, ms.OutStream))
-		}
-		buf.WriteString("> ")
-	}
-	buf.WriteString("(")
-	for index, arg := range ms.OutArgs {
-		if index > 0 {
-			buf.WriteString(", ")
-		}
-		if arg.Name != "" {
-			fmt.Fprintf(&buf, "%s ", arg.Name)
-		}
-		fmt.Fprintf(&buf, "%s", formatWiretype(defs, arg.Type))
-	}
-	buf.WriteString(")")
-	return buf.String()
-}
-
-func formatInput(name string, inputs []interface{}) string {
-	var buf bytes.Buffer
-	fmt.Fprintf(&buf, "%s(", name)
-	for index, value := range inputs {
-		if index > 0 {
-			buf.WriteString(", ")
-		}
-		fmt.Fprintf(&buf, "%v", value)
-	}
-	buf.WriteString(")")
-	return buf.String()
-}
-
-func formatOutput(outputs []interface{}) string {
-	var buf bytes.Buffer
-	buf.WriteString("[")
-	for index, value := range outputs {
-		if index > 0 {
-			buf.WriteString(", ")
-		}
-		fmt.Fprintf(&buf, "%v", value)
-	}
-	buf.WriteString("]")
-	return buf.String()
-}
diff --git a/tools/vrpc/impl_test.go b/tools/vrpc/impl_test.go
deleted file mode 100644
index 6f32b71..0000000
--- a/tools/vrpc/impl_test.go
+++ /dev/null
@@ -1,293 +0,0 @@
-package main
-
-import (
-	"bytes"
-	"sort"
-	"strings"
-	"testing"
-
-	"v.io/core/veyron2"
-	"v.io/core/veyron2/context"
-	"v.io/core/veyron2/ipc"
-	"v.io/core/veyron2/naming"
-	"v.io/core/veyron2/rt"
-	"v.io/core/veyron2/vlog"
-
-	"v.io/core/veyron/profiles"
-	"v.io/core/veyron/tools/vrpc/test_base"
-	"v.io/lib/cmdline"
-)
-
-type server struct{}
-
-// TypeTester interface implementation
-
-func (*server) EchoBool(call ipc.ServerContext, i1 bool) (bool, error) {
-	vlog.VI(2).Info("EchoBool(%v) was called.", i1)
-	return i1, nil
-}
-
-func (*server) EchoFloat32(call ipc.ServerContext, i1 float32) (float32, error) {
-	vlog.VI(2).Info("EchoFloat32(%u) was called.", i1)
-	return i1, nil
-}
-
-func (*server) EchoFloat64(call ipc.ServerContext, i1 float64) (float64, error) {
-	vlog.VI(2).Info("EchoFloat64(%u) was called.", i1)
-	return i1, nil
-}
-
-func (*server) EchoInt32(call ipc.ServerContext, i1 int32) (int32, error) {
-	vlog.VI(2).Info("EchoInt32(%v) was called.", i1)
-	return i1, nil
-}
-
-func (*server) EchoInt64(call ipc.ServerContext, i1 int64) (int64, error) {
-	vlog.VI(2).Info("EchoInt64(%v) was called.", i1)
-	return i1, nil
-}
-
-func (*server) EchoString(call ipc.ServerContext, i1 string) (string, error) {
-	vlog.VI(2).Info("EchoString(%v) was called.", i1)
-	return i1, nil
-}
-
-func (*server) EchoByte(call ipc.ServerContext, i1 byte) (byte, error) {
-	vlog.VI(2).Info("EchoByte(%v) was called.", i1)
-	return i1, nil
-}
-
-func (*server) EchoUInt32(call ipc.ServerContext, i1 uint32) (uint32, error) {
-	vlog.VI(2).Info("EchoUInt32(%u) was called.", i1)
-	return i1, nil
-}
-
-func (*server) EchoUInt64(call ipc.ServerContext, i1 uint64) (uint64, error) {
-	vlog.VI(2).Info("EchoUInt64(%u) was called.", i1)
-	return i1, nil
-}
-
-func (*server) InputArray(call ipc.ServerContext, i1 [2]uint8) error {
-	vlog.VI(2).Info("CInputArray(%v) was called.", i1)
-	return nil
-}
-
-func (*server) OutputArray(call ipc.ServerContext) ([2]uint8, error) {
-	vlog.VI(2).Info("COutputArray() was called.")
-	return [2]uint8{1, 2}, nil
-}
-
-func (*server) InputMap(call ipc.ServerContext, i1 map[uint8]uint8) error {
-	vlog.VI(2).Info("CInputMap(%v) was called.", i1)
-	return nil
-}
-
-func (*server) OutputMap(call ipc.ServerContext) (map[uint8]uint8, error) {
-	vlog.VI(2).Info("COutputMap() was called.")
-	return map[uint8]uint8{1: 2}, nil
-}
-
-func (*server) InputSlice(call ipc.ServerContext, i1 []uint8) error {
-	vlog.VI(2).Info("CInputSlice(%v) was called.", i1)
-	return nil
-}
-
-func (*server) OutputSlice(call ipc.ServerContext) ([]uint8, error) {
-	vlog.VI(2).Info("COutputSlice() was called.")
-	return []uint8{1, 2}, nil
-}
-
-func (*server) InputStruct(call ipc.ServerContext, i1 test_base.Struct) error {
-	vlog.VI(2).Info("CInputStruct(%v) was called.", i1)
-	return nil
-}
-
-func (*server) OutputStruct(call ipc.ServerContext) (test_base.Struct, error) {
-	vlog.VI(2).Info("COutputStruct() was called.")
-	return test_base.Struct{X: 1, Y: 2}, nil
-}
-
-func (*server) NoArguments(call ipc.ServerContext) error {
-	vlog.VI(2).Info("NoArguments() was called.")
-	return nil
-}
-
-func (*server) MultipleArguments(call ipc.ServerContext, i1, i2 int32) (int32, int32, error) {
-	vlog.VI(2).Info("MultipleArguments(%v,%v) was called.", i1, i2)
-	return i1, i2, nil
-}
-
-func (*server) StreamingOutput(ctx test_base.TypeTesterStreamingOutputContext, nStream int32, item bool) error {
-	vlog.VI(2).Info("StreamingOutput(%v,%v) was called.", nStream, item)
-	sender := ctx.SendStream()
-	for i := int32(0); i < nStream; i++ {
-		sender.Send(item)
-	}
-	return nil
-}
-
-func startServer(t *testing.T, ctx *context.T) (ipc.Server, naming.Endpoint, error) {
-	obj := test_base.TypeTesterServer(&server{})
-	server, err := veyron2.NewServer(ctx)
-	if err != nil {
-		t.Errorf("NewServer failed: %v", err)
-		return nil, nil, err
-	}
-
-	endpoints, err := server.Listen(profiles.LocalListenSpec)
-	if err != nil {
-		t.Errorf("Listen failed: %v", err)
-		return nil, nil, err
-	}
-	if err := server.Serve("", obj, nil); err != nil {
-		t.Errorf("Serve failed: %v", err)
-		return nil, nil, err
-	}
-	return server, endpoints[0], nil
-}
-
-func stopServer(t *testing.T, server ipc.Server) {
-	if err := server.Stop(); err != nil {
-		t.Errorf("server.Stop failed: %v", err)
-	}
-}
-
-func testInvocation(t *testing.T, buffer *bytes.Buffer, cmd *cmdline.Command, args []string, expected string) {
-	buffer.Reset()
-	if err := cmd.Execute(args); err != nil {
-		t.Errorf("%v", err)
-		return
-	}
-	if output := strings.Trim(buffer.String(), "\n"); output != expected {
-		t.Errorf("Incorrect invoke output: expected %s, got %s", expected, output)
-		return
-	}
-}
-
-func testError(t *testing.T, cmd *cmdline.Command, args []string, expected string) {
-	if err := cmd.Execute(args); err == nil || !strings.Contains(err.Error(), expected) {
-		t.Errorf("Expected error: ...%v..., got: %v", expected, err)
-	}
-}
-
-func TestVRPC(t *testing.T) {
-	var err error
-	runtime, err = rt.New()
-	if err != nil {
-		t.Fatalf("Unexpected error initializing runtime: %s", err)
-	}
-	defer runtime.Cleanup()
-	ctx := runtime.NewContext()
-
-	// Skip defer runtime.Cleanup() to avoid messing up other tests in the
-	// same process.
-	server, endpoint, err := startServer(t, ctx)
-	if err != nil {
-		return
-	}
-	defer stopServer(t, server)
-
-	// Setup the command-line.
-	cmd := root()
-	var stdout, stderr bytes.Buffer
-	cmd.Init(nil, &stdout, &stderr)
-
-	name := endpoint.Name()
-	// Test the 'describe' command.
-	if err := cmd.Execute([]string{"describe", name}); err != nil {
-		t.Errorf("%v", err)
-		return
-	}
-
-	// TODO(toddw): Switch VRPC to new __Signature, and update these tests.
-	expectedSignature := []string{
-		"func EchoBool(I1 bool) (O1 bool, err error)",
-		"func EchoFloat32(I1 float32) (O1 float32, err error)",
-		"func EchoFloat64(I1 float64) (O1 float64, err error)",
-		"func EchoInt32(I1 int32) (O1 int32, err error)",
-		"func EchoInt64(I1 int64) (O1 int64, err error)",
-		"func EchoString(I1 string) (O1 string, err error)",
-		"func EchoByte(I1 byte) (O1 byte, err error)",
-		"func EchoUInt32(I1 uint32) (O1 uint32, err error)",
-		"func EchoUInt64(I1 uint64) (O1 uint64, err error)",
-		"func InputArray(I1 [2]byte) (error)",
-		"func InputMap(I1 map[byte]byte) (error)",
-		"func InputSlice(I1 []byte) (error)",
-		"func InputStruct(I1 struct{X int32, Y int32}) (error)",
-		"func OutputArray() (O1 [2]byte, err error)",
-		"func OutputMap() (O1 map[byte]byte, err error)",
-		"func OutputSlice() (O1 []byte, err error)",
-		"func OutputStruct() (O1 struct{X int32, Y int32}, err error)",
-		"func NoArguments() (error)",
-		"func MultipleArguments(I1 int32, I2 int32) (O1 int32, O2 int32, err error)",
-		"func StreamingOutput(NumStreamItems int32, StreamItem bool) stream<_, bool> (error)",
-	}
-
-	signature := make([]string, 0, len(expectedSignature))
-	line, err := stdout.ReadBytes('\n')
-	for err == nil {
-		signature = append(signature, strings.Trim(string(line), "\n"))
-		line, err = stdout.ReadBytes('\n')
-	}
-
-	sort.Strings(signature)
-	sort.Strings(expectedSignature)
-
-	if len(signature) != len(expectedSignature) {
-		t.Fatalf("signature lengths don't match %v and %v.", len(signature), len(expectedSignature))
-	}
-
-	for i, expectedSig := range expectedSignature {
-		if expectedSig != signature[i] {
-			t.Errorf("signature line doesn't match: %v and %v\n", expectedSig, signature[i])
-		}
-	}
-
-	// Test the 'invoke' command.
-
-	tests := [][]string{
-		[]string{"EchoBool", "EchoBool(true) = [true, <nil>]", "[\"bool\",true]"},
-		[]string{"EchoFloat32", "EchoFloat32(3.2) = [3.2, <nil>]", "[\"float32\",3.2]"},
-		[]string{"EchoFloat64", "EchoFloat64(6.4) = [6.4, <nil>]", "[\"float64\",6.4]"},
-		[]string{"EchoInt32", "EchoInt32(-32) = [-32, <nil>]", "[\"int32\",-32]"},
-		[]string{"EchoInt64", "EchoInt64(-64) = [-64, <nil>]", "[\"int64\",-64]"},
-		[]string{"EchoString", "EchoString(Hello World!) = [Hello World!, <nil>]", "[\"string\",\"Hello World!\"]"},
-		[]string{"EchoByte", "EchoByte(8) = [8, <nil>]", "[\"byte\",8]"},
-		[]string{"EchoUInt32", "EchoUInt32(32) = [32, <nil>]", "[\"uint32\",32]"},
-		[]string{"EchoUInt64", "EchoUInt64(64) = [64, <nil>]", "[\"uint64\",64]"},
-		// TODO(jsimsa): The InputArray currently triggers an error in the
-		// vom decoder. Benj is looking into this.
-		//
-		// []string{"InputArray", "InputArray([1 2]) = []", "[\"[2]uint\",[1,2]]"},
-		[]string{"InputMap", "InputMap(map[1:2]) = [<nil>]", "[\"map[uint]uint\",{\"1\":\"2\"}]"},
-		// TODO(jsimsa): The InputSlice currently triggers an error in the
-		// vom decoder. Benj is looking into this.
-		//
-		// []string{"InputSlice", "InputSlice([1 2]) = []", "[\"[]uint\",[1,2]]"},
-		[]string{"InputStruct", "InputStruct({1 2}) = [<nil>]",
-			"[\"type\",\"v.io/core/veyron2/vrpc/test_base.Struct struct{X int32;Y int32}\"] [\"Struct\",{\"X\":1,\"Y\":2}]"},
-		// TODO(jsimsa): The OutputArray currently triggers an error in the
-		// vom decoder. Benj is looking into this.
-		//
-		// []string{"OutputArray", "OutputArray() = [1 2]"}
-		[]string{"OutputMap", "OutputMap() = [map[1:2], <nil>]"},
-		[]string{"OutputSlice", "OutputSlice() = [[1 2], <nil>]"},
-		[]string{"OutputStruct", "OutputStruct() = [{1 2}, <nil>]"},
-		[]string{"NoArguments", "NoArguments() = [<nil>]"},
-		[]string{"MultipleArguments", "MultipleArguments(1, 2) = [1, 2, <nil>]", "[\"uint32\",1]", "[\"uint32\",2]"},
-		[]string{"StreamingOutput", "StreamingOutput(3, true) = <<\n0: true\n1: true\n2: true\n>> [<nil>]", "[\"int8\",3]", "[\"bool\",true ]"},
-		[]string{"StreamingOutput", "StreamingOutput(0, true) = [<nil>]", "[\"int8\",0]", "[\"bool\",true ]"},
-	}
-
-	for _, test := range tests {
-		testInvocation(t, &stdout, cmd, append([]string{"invoke", name, test[0]}, test[2:]...), test[1])
-	}
-
-	testErrors := [][]string{
-		[]string{"EchoBool", "exit code 1"},
-		[]string{"DoesNotExist", "invoke: method DoesNotExist not found"},
-	}
-	for _, test := range testErrors {
-		testError(t, cmd, append([]string{"invoke", name, test[0]}, test[2:]...), test[1])
-	}
-}
diff --git a/tools/vrpc/main.go b/tools/vrpc/main.go
deleted file mode 100644
index 7368a9c..0000000
--- a/tools/vrpc/main.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// The following enables go generate to generate the doc.go file.
-//go:generate go run $VANADIUM_ROOT/release/go/src/v.io/lib/cmdline/testdata/gendoc.go .
-
-package main
-
-import (
-	"v.io/core/veyron2"
-	"v.io/core/veyron2/rt"
-
-	_ "v.io/core/veyron/profiles"
-)
-
-var runtime veyron2.Runtime
-
-func main() {
-	var err error
-	runtime, err = rt.New()
-	if err != nil {
-		panic(err)
-	}
-	defer runtime.Cleanup()
-	root().Main()
-}
diff --git a/tools/vrpc/test_base/test_base.vdl b/tools/vrpc/test_base/test_base.vdl
index 8f6b15e..e0406da 100644
--- a/tools/vrpc/test_base/test_base.vdl
+++ b/tools/vrpc/test_base/test_base.vdl
@@ -4,32 +4,31 @@
   X,Y int32
 }
 
+// TypeTester methods are listed in alphabetical order, to make it easier to
+// test Signature output, which sorts methods alphabetically.
 type TypeTester interface {
-  // Methods to test support for generic types.
-  EchoBool(I1 bool) (O1 bool | error)
-  EchoFloat32(I1 float32) (O1 float32 | error)
-  EchoFloat64(I1 float64) (O1 float64 | error)
-  EchoInt32(I1 int32) (O1 int32 | error)
-  EchoInt64(I1 int64) (O1 int64 | error)
-  EchoString(I1 string) (O1 string | error)
-  EchoByte(I1 byte) (O1 byte | error)
-  EchoUInt32(I1 uint32) (O1 uint32 | error)
-  EchoUInt64(I1 uint64) (O1 uint64 | error)
+	// Methods to test support for primitive types.
+	EchoBool(I1 bool) (O1 bool | error)
+	EchoFloat32(I1 float32) (O1 float32 | error)
+	EchoFloat64(I1 float64) (O1 float64 | error)
+	EchoInt32(I1 int32) (O1 int32 | error)
+	EchoInt64(I1 int64) (O1 int64 | error)
+	EchoString(I1 string) (O1 string | error)
+	EchoByte(I1 byte) (O1 byte | error)
+	EchoUint32(I1 uint32) (O1 uint32 | error)
+	EchoUint64(I1 uint64) (O1 uint64 | error)
 
-  // Methods to test support for composite types.
-  InputArray(I1 [2]byte) error
-  InputMap(I1 map[byte]byte) error
-  InputSlice(I1 []byte) error
-  InputStruct(I1 Struct) error
-  OutputArray() (O1 [2]byte | error)
-  OutputMap() (O1 map[byte]byte | error)
-  OutputSlice() (O1 []byte | error)
-  OutputStruct() (O1 Struct | error)
+	// Methods to test support for composite types.
+	XEchoArray(I1 [2]int32) (O1 [2]int32 | error)
+	XEchoMap(I1 map[int32]string) (O1 map[int32]string | error)
+	XEchoSet(I1 set[int32]) (O1 set[int32] | error)
+	XEchoSlice(I1 []int32) (O1 []int32 | error)
+	XEchoStruct(I1 Struct) (O1 Struct | error)
 
-  // Methods to test support for different number of arguments.
-  NoArguments() error
-  MultipleArguments(I1, I2 int32) (O1, O2 int32 | error)
+	// Methods to test support for different number of arguments.
+	YMultiArg(I1, I2 int32) (O1, O2 int32 | error)
+	YNoArgs() error
 
-  // Methods to test support for streaming.
-  StreamingOutput(NumStreamItems int32, StreamItem bool) stream<_, bool> error
+	// Methods to test support for streaming.
+	ZStream(NumStreamItems int32, StreamItem bool) stream<_, bool> error
 }
diff --git a/tools/vrpc/test_base/test_base.vdl.go b/tools/vrpc/test_base/test_base.vdl.go
index 87a4708..4cdfd98 100644
--- a/tools/vrpc/test_base/test_base.vdl.go
+++ b/tools/vrpc/test_base/test_base.vdl.go
@@ -35,8 +35,11 @@
 
 // TypeTesterClientMethods is the client interface
 // containing TypeTester methods.
+//
+// TypeTester methods are listed in alphabetical order, to make it easier to
+// test Signature output, which sorts methods alphabetically.
 type TypeTesterClientMethods interface {
-	// Methods to test support for generic types.
+	// Methods to test support for primitive types.
 	EchoBool(ctx *__context.T, I1 bool, opts ...__ipc.CallOpt) (O1 bool, err error)
 	EchoFloat32(ctx *__context.T, I1 float32, opts ...__ipc.CallOpt) (O1 float32, err error)
 	EchoFloat64(ctx *__context.T, I1 float64, opts ...__ipc.CallOpt) (O1 float64, err error)
@@ -44,22 +47,19 @@
 	EchoInt64(ctx *__context.T, I1 int64, opts ...__ipc.CallOpt) (O1 int64, err error)
 	EchoString(ctx *__context.T, I1 string, opts ...__ipc.CallOpt) (O1 string, err error)
 	EchoByte(ctx *__context.T, I1 byte, opts ...__ipc.CallOpt) (O1 byte, err error)
-	EchoUInt32(ctx *__context.T, I1 uint32, opts ...__ipc.CallOpt) (O1 uint32, err error)
-	EchoUInt64(ctx *__context.T, I1 uint64, opts ...__ipc.CallOpt) (O1 uint64, err error)
+	EchoUint32(ctx *__context.T, I1 uint32, opts ...__ipc.CallOpt) (O1 uint32, err error)
+	EchoUint64(ctx *__context.T, I1 uint64, opts ...__ipc.CallOpt) (O1 uint64, err error)
 	// Methods to test support for composite types.
-	InputArray(ctx *__context.T, I1 [2]byte, opts ...__ipc.CallOpt) error
-	InputMap(ctx *__context.T, I1 map[byte]byte, opts ...__ipc.CallOpt) error
-	InputSlice(ctx *__context.T, I1 []byte, opts ...__ipc.CallOpt) error
-	InputStruct(ctx *__context.T, I1 Struct, opts ...__ipc.CallOpt) error
-	OutputArray(*__context.T, ...__ipc.CallOpt) (O1 [2]byte, err error)
-	OutputMap(*__context.T, ...__ipc.CallOpt) (O1 map[byte]byte, err error)
-	OutputSlice(*__context.T, ...__ipc.CallOpt) (O1 []byte, err error)
-	OutputStruct(*__context.T, ...__ipc.CallOpt) (O1 Struct, err error)
+	XEchoArray(ctx *__context.T, I1 [2]int32, opts ...__ipc.CallOpt) (O1 [2]int32, err error)
+	XEchoMap(ctx *__context.T, I1 map[int32]string, opts ...__ipc.CallOpt) (O1 map[int32]string, err error)
+	XEchoSet(ctx *__context.T, I1 map[int32]struct{}, opts ...__ipc.CallOpt) (O1 map[int32]struct{}, err error)
+	XEchoSlice(ctx *__context.T, I1 []int32, opts ...__ipc.CallOpt) (O1 []int32, err error)
+	XEchoStruct(ctx *__context.T, I1 Struct, opts ...__ipc.CallOpt) (O1 Struct, err error)
 	// Methods to test support for different number of arguments.
-	NoArguments(*__context.T, ...__ipc.CallOpt) error
-	MultipleArguments(ctx *__context.T, I1 int32, I2 int32, opts ...__ipc.CallOpt) (O1 int32, O2 int32, err error)
+	YMultiArg(ctx *__context.T, I1 int32, I2 int32, opts ...__ipc.CallOpt) (O1 int32, O2 int32, err error)
+	YNoArgs(*__context.T, ...__ipc.CallOpt) error
 	// Methods to test support for streaming.
-	StreamingOutput(ctx *__context.T, NumStreamItems int32, StreamItem bool, opts ...__ipc.CallOpt) (TypeTesterStreamingOutputCall, error)
+	ZStream(ctx *__context.T, NumStreamItems int32, StreamItem bool, opts ...__ipc.CallOpt) (TypeTesterZStreamCall, error)
 }
 
 // TypeTesterClientStub adds universal methods to TypeTesterClientMethods.
@@ -168,9 +168,9 @@
 	return
 }
 
-func (c implTypeTesterClientStub) EchoUInt32(ctx *__context.T, i0 uint32, opts ...__ipc.CallOpt) (o0 uint32, err error) {
+func (c implTypeTesterClientStub) EchoUint32(ctx *__context.T, i0 uint32, opts ...__ipc.CallOpt) (o0 uint32, err error) {
 	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "EchoUInt32", []interface{}{i0}, opts...); err != nil {
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "EchoUint32", []interface{}{i0}, opts...); err != nil {
 		return
 	}
 	if ierr := call.Finish(&o0, &err); ierr != nil {
@@ -179,9 +179,9 @@
 	return
 }
 
-func (c implTypeTesterClientStub) EchoUInt64(ctx *__context.T, i0 uint64, opts ...__ipc.CallOpt) (o0 uint64, err error) {
+func (c implTypeTesterClientStub) EchoUint64(ctx *__context.T, i0 uint64, opts ...__ipc.CallOpt) (o0 uint64, err error) {
 	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "EchoUInt64", []interface{}{i0}, opts...); err != nil {
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "EchoUint64", []interface{}{i0}, opts...); err != nil {
 		return
 	}
 	if ierr := call.Finish(&o0, &err); ierr != nil {
@@ -190,53 +190,9 @@
 	return
 }
 
-func (c implTypeTesterClientStub) InputArray(ctx *__context.T, i0 [2]byte, opts ...__ipc.CallOpt) (err error) {
+func (c implTypeTesterClientStub) XEchoArray(ctx *__context.T, i0 [2]int32, opts ...__ipc.CallOpt) (o0 [2]int32, err error) {
 	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "InputArray", []interface{}{i0}, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
-func (c implTypeTesterClientStub) InputMap(ctx *__context.T, i0 map[byte]byte, opts ...__ipc.CallOpt) (err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "InputMap", []interface{}{i0}, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
-func (c implTypeTesterClientStub) InputSlice(ctx *__context.T, i0 []byte, opts ...__ipc.CallOpt) (err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "InputSlice", []interface{}{i0}, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
-func (c implTypeTesterClientStub) InputStruct(ctx *__context.T, i0 Struct, opts ...__ipc.CallOpt) (err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "InputStruct", []interface{}{i0}, opts...); err != nil {
-		return
-	}
-	if ierr := call.Finish(&err); ierr != nil {
-		err = ierr
-	}
-	return
-}
-
-func (c implTypeTesterClientStub) OutputArray(ctx *__context.T, opts ...__ipc.CallOpt) (o0 [2]byte, err error) {
-	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "OutputArray", nil, opts...); err != nil {
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "XEchoArray", []interface{}{i0}, opts...); err != nil {
 		return
 	}
 	if ierr := call.Finish(&o0, &err); ierr != nil {
@@ -245,9 +201,9 @@
 	return
 }
 
-func (c implTypeTesterClientStub) OutputMap(ctx *__context.T, opts ...__ipc.CallOpt) (o0 map[byte]byte, err error) {
+func (c implTypeTesterClientStub) XEchoMap(ctx *__context.T, i0 map[int32]string, opts ...__ipc.CallOpt) (o0 map[int32]string, err error) {
 	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "OutputMap", nil, opts...); err != nil {
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "XEchoMap", []interface{}{i0}, opts...); err != nil {
 		return
 	}
 	if ierr := call.Finish(&o0, &err); ierr != nil {
@@ -256,9 +212,9 @@
 	return
 }
 
-func (c implTypeTesterClientStub) OutputSlice(ctx *__context.T, opts ...__ipc.CallOpt) (o0 []byte, err error) {
+func (c implTypeTesterClientStub) XEchoSet(ctx *__context.T, i0 map[int32]struct{}, opts ...__ipc.CallOpt) (o0 map[int32]struct{}, err error) {
 	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "OutputSlice", nil, opts...); err != nil {
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "XEchoSet", []interface{}{i0}, opts...); err != nil {
 		return
 	}
 	if ierr := call.Finish(&o0, &err); ierr != nil {
@@ -267,9 +223,9 @@
 	return
 }
 
-func (c implTypeTesterClientStub) OutputStruct(ctx *__context.T, opts ...__ipc.CallOpt) (o0 Struct, err error) {
+func (c implTypeTesterClientStub) XEchoSlice(ctx *__context.T, i0 []int32, opts ...__ipc.CallOpt) (o0 []int32, err error) {
 	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "OutputStruct", nil, opts...); err != nil {
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "XEchoSlice", []interface{}{i0}, opts...); err != nil {
 		return
 	}
 	if ierr := call.Finish(&o0, &err); ierr != nil {
@@ -278,20 +234,20 @@
 	return
 }
 
-func (c implTypeTesterClientStub) NoArguments(ctx *__context.T, opts ...__ipc.CallOpt) (err error) {
+func (c implTypeTesterClientStub) XEchoStruct(ctx *__context.T, i0 Struct, opts ...__ipc.CallOpt) (o0 Struct, err error) {
 	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "NoArguments", nil, opts...); err != nil {
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "XEchoStruct", []interface{}{i0}, opts...); err != nil {
 		return
 	}
-	if ierr := call.Finish(&err); ierr != nil {
+	if ierr := call.Finish(&o0, &err); ierr != nil {
 		err = ierr
 	}
 	return
 }
 
-func (c implTypeTesterClientStub) MultipleArguments(ctx *__context.T, i0 int32, i1 int32, opts ...__ipc.CallOpt) (o0 int32, o1 int32, err error) {
+func (c implTypeTesterClientStub) YMultiArg(ctx *__context.T, i0 int32, i1 int32, opts ...__ipc.CallOpt) (o0 int32, o1 int32, err error) {
 	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "MultipleArguments", []interface{}{i0, i1}, opts...); err != nil {
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "YMultiArg", []interface{}{i0, i1}, opts...); err != nil {
 		return
 	}
 	if ierr := call.Finish(&o0, &o1, &err); ierr != nil {
@@ -300,12 +256,23 @@
 	return
 }
 
-func (c implTypeTesterClientStub) StreamingOutput(ctx *__context.T, i0 int32, i1 bool, opts ...__ipc.CallOpt) (ocall TypeTesterStreamingOutputCall, err error) {
+func (c implTypeTesterClientStub) YNoArgs(ctx *__context.T, opts ...__ipc.CallOpt) (err error) {
 	var call __ipc.Call
-	if call, err = c.c(ctx).StartCall(ctx, c.name, "StreamingOutput", []interface{}{i0, i1}, opts...); err != nil {
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "YNoArgs", nil, opts...); err != nil {
 		return
 	}
-	ocall = &implTypeTesterStreamingOutputCall{Call: call}
+	if ierr := call.Finish(&err); ierr != nil {
+		err = ierr
+	}
+	return
+}
+
+func (c implTypeTesterClientStub) ZStream(ctx *__context.T, i0 int32, i1 bool, opts ...__ipc.CallOpt) (ocall TypeTesterZStreamCall, err error) {
+	var call __ipc.Call
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "ZStream", []interface{}{i0, i1}, opts...); err != nil {
+		return
+	}
+	ocall = &implTypeTesterZStreamCall{Call: call}
 	return
 }
 
@@ -320,9 +287,9 @@
 	return
 }
 
-// TypeTesterStreamingOutputClientStream is the client stream for TypeTester.StreamingOutput.
-type TypeTesterStreamingOutputClientStream interface {
-	// RecvStream returns the receiver side of the TypeTester.StreamingOutput client stream.
+// TypeTesterZStreamClientStream is the client stream for TypeTester.ZStream.
+type TypeTesterZStreamClientStream interface {
+	// RecvStream returns the receiver side of the TypeTester.ZStream client stream.
 	RecvStream() interface {
 		// Advance stages an item so that it may be retrieved via Value.  Returns
 		// true iff there is an item to retrieve.  Advance must be called before
@@ -336,9 +303,9 @@
 	}
 }
 
-// TypeTesterStreamingOutputCall represents the call returned from TypeTester.StreamingOutput.
-type TypeTesterStreamingOutputCall interface {
-	TypeTesterStreamingOutputClientStream
+// TypeTesterZStreamCall represents the call returned from TypeTester.ZStream.
+type TypeTesterZStreamCall interface {
+	TypeTesterZStreamClientStream
 	// Finish blocks until the server is done, and returns the positional return
 	// values for call.
 	//
@@ -352,38 +319,38 @@
 	Finish() error
 }
 
-type implTypeTesterStreamingOutputCall struct {
+type implTypeTesterZStreamCall struct {
 	__ipc.Call
 	valRecv bool
 	errRecv error
 }
 
-func (c *implTypeTesterStreamingOutputCall) RecvStream() interface {
+func (c *implTypeTesterZStreamCall) RecvStream() interface {
 	Advance() bool
 	Value() bool
 	Err() error
 } {
-	return implTypeTesterStreamingOutputCallRecv{c}
+	return implTypeTesterZStreamCallRecv{c}
 }
 
-type implTypeTesterStreamingOutputCallRecv struct {
-	c *implTypeTesterStreamingOutputCall
+type implTypeTesterZStreamCallRecv struct {
+	c *implTypeTesterZStreamCall
 }
 
-func (c implTypeTesterStreamingOutputCallRecv) Advance() bool {
+func (c implTypeTesterZStreamCallRecv) Advance() bool {
 	c.c.errRecv = c.c.Recv(&c.c.valRecv)
 	return c.c.errRecv == nil
 }
-func (c implTypeTesterStreamingOutputCallRecv) Value() bool {
+func (c implTypeTesterZStreamCallRecv) Value() bool {
 	return c.c.valRecv
 }
-func (c implTypeTesterStreamingOutputCallRecv) Err() error {
+func (c implTypeTesterZStreamCallRecv) Err() error {
 	if c.c.errRecv == __io.EOF {
 		return nil
 	}
 	return c.c.errRecv
 }
-func (c *implTypeTesterStreamingOutputCall) Finish() (err error) {
+func (c *implTypeTesterZStreamCall) Finish() (err error) {
 	if ierr := c.Call.Finish(&err); ierr != nil {
 		err = ierr
 	}
@@ -392,8 +359,11 @@
 
 // TypeTesterServerMethods is the interface a server writer
 // implements for TypeTester.
+//
+// TypeTester methods are listed in alphabetical order, to make it easier to
+// test Signature output, which sorts methods alphabetically.
 type TypeTesterServerMethods interface {
-	// Methods to test support for generic types.
+	// Methods to test support for primitive types.
 	EchoBool(ctx __ipc.ServerContext, I1 bool) (O1 bool, err error)
 	EchoFloat32(ctx __ipc.ServerContext, I1 float32) (O1 float32, err error)
 	EchoFloat64(ctx __ipc.ServerContext, I1 float64) (O1 float64, err error)
@@ -401,22 +371,19 @@
 	EchoInt64(ctx __ipc.ServerContext, I1 int64) (O1 int64, err error)
 	EchoString(ctx __ipc.ServerContext, I1 string) (O1 string, err error)
 	EchoByte(ctx __ipc.ServerContext, I1 byte) (O1 byte, err error)
-	EchoUInt32(ctx __ipc.ServerContext, I1 uint32) (O1 uint32, err error)
-	EchoUInt64(ctx __ipc.ServerContext, I1 uint64) (O1 uint64, err error)
+	EchoUint32(ctx __ipc.ServerContext, I1 uint32) (O1 uint32, err error)
+	EchoUint64(ctx __ipc.ServerContext, I1 uint64) (O1 uint64, err error)
 	// Methods to test support for composite types.
-	InputArray(ctx __ipc.ServerContext, I1 [2]byte) error
-	InputMap(ctx __ipc.ServerContext, I1 map[byte]byte) error
-	InputSlice(ctx __ipc.ServerContext, I1 []byte) error
-	InputStruct(ctx __ipc.ServerContext, I1 Struct) error
-	OutputArray(__ipc.ServerContext) (O1 [2]byte, err error)
-	OutputMap(__ipc.ServerContext) (O1 map[byte]byte, err error)
-	OutputSlice(__ipc.ServerContext) (O1 []byte, err error)
-	OutputStruct(__ipc.ServerContext) (O1 Struct, err error)
+	XEchoArray(ctx __ipc.ServerContext, I1 [2]int32) (O1 [2]int32, err error)
+	XEchoMap(ctx __ipc.ServerContext, I1 map[int32]string) (O1 map[int32]string, err error)
+	XEchoSet(ctx __ipc.ServerContext, I1 map[int32]struct{}) (O1 map[int32]struct{}, err error)
+	XEchoSlice(ctx __ipc.ServerContext, I1 []int32) (O1 []int32, err error)
+	XEchoStruct(ctx __ipc.ServerContext, I1 Struct) (O1 Struct, err error)
 	// Methods to test support for different number of arguments.
-	NoArguments(__ipc.ServerContext) error
-	MultipleArguments(ctx __ipc.ServerContext, I1 int32, I2 int32) (O1 int32, O2 int32, err error)
+	YMultiArg(ctx __ipc.ServerContext, I1 int32, I2 int32) (O1 int32, O2 int32, err error)
+	YNoArgs(__ipc.ServerContext) error
 	// Methods to test support for streaming.
-	StreamingOutput(ctx TypeTesterStreamingOutputContext, NumStreamItems int32, StreamItem bool) error
+	ZStream(ctx TypeTesterZStreamContext, NumStreamItems int32, StreamItem bool) error
 }
 
 // TypeTesterServerStubMethods is the server interface containing
@@ -424,7 +391,7 @@
 // The only difference between this interface and TypeTesterServerMethods
 // is the streaming methods.
 type TypeTesterServerStubMethods interface {
-	// Methods to test support for generic types.
+	// Methods to test support for primitive types.
 	EchoBool(ctx __ipc.ServerContext, I1 bool) (O1 bool, err error)
 	EchoFloat32(ctx __ipc.ServerContext, I1 float32) (O1 float32, err error)
 	EchoFloat64(ctx __ipc.ServerContext, I1 float64) (O1 float64, err error)
@@ -432,22 +399,19 @@
 	EchoInt64(ctx __ipc.ServerContext, I1 int64) (O1 int64, err error)
 	EchoString(ctx __ipc.ServerContext, I1 string) (O1 string, err error)
 	EchoByte(ctx __ipc.ServerContext, I1 byte) (O1 byte, err error)
-	EchoUInt32(ctx __ipc.ServerContext, I1 uint32) (O1 uint32, err error)
-	EchoUInt64(ctx __ipc.ServerContext, I1 uint64) (O1 uint64, err error)
+	EchoUint32(ctx __ipc.ServerContext, I1 uint32) (O1 uint32, err error)
+	EchoUint64(ctx __ipc.ServerContext, I1 uint64) (O1 uint64, err error)
 	// Methods to test support for composite types.
-	InputArray(ctx __ipc.ServerContext, I1 [2]byte) error
-	InputMap(ctx __ipc.ServerContext, I1 map[byte]byte) error
-	InputSlice(ctx __ipc.ServerContext, I1 []byte) error
-	InputStruct(ctx __ipc.ServerContext, I1 Struct) error
-	OutputArray(__ipc.ServerContext) (O1 [2]byte, err error)
-	OutputMap(__ipc.ServerContext) (O1 map[byte]byte, err error)
-	OutputSlice(__ipc.ServerContext) (O1 []byte, err error)
-	OutputStruct(__ipc.ServerContext) (O1 Struct, err error)
+	XEchoArray(ctx __ipc.ServerContext, I1 [2]int32) (O1 [2]int32, err error)
+	XEchoMap(ctx __ipc.ServerContext, I1 map[int32]string) (O1 map[int32]string, err error)
+	XEchoSet(ctx __ipc.ServerContext, I1 map[int32]struct{}) (O1 map[int32]struct{}, err error)
+	XEchoSlice(ctx __ipc.ServerContext, I1 []int32) (O1 []int32, err error)
+	XEchoStruct(ctx __ipc.ServerContext, I1 Struct) (O1 Struct, err error)
 	// Methods to test support for different number of arguments.
-	NoArguments(__ipc.ServerContext) error
-	MultipleArguments(ctx __ipc.ServerContext, I1 int32, I2 int32) (O1 int32, O2 int32, err error)
+	YMultiArg(ctx __ipc.ServerContext, I1 int32, I2 int32) (O1 int32, O2 int32, err error)
+	YNoArgs(__ipc.ServerContext) error
 	// Methods to test support for streaming.
-	StreamingOutput(ctx *TypeTesterStreamingOutputContextStub, NumStreamItems int32, StreamItem bool) error
+	ZStream(ctx *TypeTesterZStreamContextStub, NumStreamItems int32, StreamItem bool) error
 }
 
 // TypeTesterServerStub adds universal methods to TypeTesterServerStubMethods.
@@ -509,56 +473,44 @@
 	return s.impl.EchoByte(ctx, i0)
 }
 
-func (s implTypeTesterServerStub) EchoUInt32(ctx __ipc.ServerContext, i0 uint32) (uint32, error) {
-	return s.impl.EchoUInt32(ctx, i0)
+func (s implTypeTesterServerStub) EchoUint32(ctx __ipc.ServerContext, i0 uint32) (uint32, error) {
+	return s.impl.EchoUint32(ctx, i0)
 }
 
-func (s implTypeTesterServerStub) EchoUInt64(ctx __ipc.ServerContext, i0 uint64) (uint64, error) {
-	return s.impl.EchoUInt64(ctx, i0)
+func (s implTypeTesterServerStub) EchoUint64(ctx __ipc.ServerContext, i0 uint64) (uint64, error) {
+	return s.impl.EchoUint64(ctx, i0)
 }
 
-func (s implTypeTesterServerStub) InputArray(ctx __ipc.ServerContext, i0 [2]byte) error {
-	return s.impl.InputArray(ctx, i0)
+func (s implTypeTesterServerStub) XEchoArray(ctx __ipc.ServerContext, i0 [2]int32) ([2]int32, error) {
+	return s.impl.XEchoArray(ctx, i0)
 }
 
-func (s implTypeTesterServerStub) InputMap(ctx __ipc.ServerContext, i0 map[byte]byte) error {
-	return s.impl.InputMap(ctx, i0)
+func (s implTypeTesterServerStub) XEchoMap(ctx __ipc.ServerContext, i0 map[int32]string) (map[int32]string, error) {
+	return s.impl.XEchoMap(ctx, i0)
 }
 
-func (s implTypeTesterServerStub) InputSlice(ctx __ipc.ServerContext, i0 []byte) error {
-	return s.impl.InputSlice(ctx, i0)
+func (s implTypeTesterServerStub) XEchoSet(ctx __ipc.ServerContext, i0 map[int32]struct{}) (map[int32]struct{}, error) {
+	return s.impl.XEchoSet(ctx, i0)
 }
 
-func (s implTypeTesterServerStub) InputStruct(ctx __ipc.ServerContext, i0 Struct) error {
-	return s.impl.InputStruct(ctx, i0)
+func (s implTypeTesterServerStub) XEchoSlice(ctx __ipc.ServerContext, i0 []int32) ([]int32, error) {
+	return s.impl.XEchoSlice(ctx, i0)
 }
 
-func (s implTypeTesterServerStub) OutputArray(ctx __ipc.ServerContext) ([2]byte, error) {
-	return s.impl.OutputArray(ctx)
+func (s implTypeTesterServerStub) XEchoStruct(ctx __ipc.ServerContext, i0 Struct) (Struct, error) {
+	return s.impl.XEchoStruct(ctx, i0)
 }
 
-func (s implTypeTesterServerStub) OutputMap(ctx __ipc.ServerContext) (map[byte]byte, error) {
-	return s.impl.OutputMap(ctx)
+func (s implTypeTesterServerStub) YMultiArg(ctx __ipc.ServerContext, i0 int32, i1 int32) (int32, int32, error) {
+	return s.impl.YMultiArg(ctx, i0, i1)
 }
 
-func (s implTypeTesterServerStub) OutputSlice(ctx __ipc.ServerContext) ([]byte, error) {
-	return s.impl.OutputSlice(ctx)
+func (s implTypeTesterServerStub) YNoArgs(ctx __ipc.ServerContext) error {
+	return s.impl.YNoArgs(ctx)
 }
 
-func (s implTypeTesterServerStub) OutputStruct(ctx __ipc.ServerContext) (Struct, error) {
-	return s.impl.OutputStruct(ctx)
-}
-
-func (s implTypeTesterServerStub) NoArguments(ctx __ipc.ServerContext) error {
-	return s.impl.NoArguments(ctx)
-}
-
-func (s implTypeTesterServerStub) MultipleArguments(ctx __ipc.ServerContext, i0 int32, i1 int32) (int32, int32, error) {
-	return s.impl.MultipleArguments(ctx, i0, i1)
-}
-
-func (s implTypeTesterServerStub) StreamingOutput(ctx *TypeTesterStreamingOutputContextStub, i0 int32, i1 bool) error {
-	return s.impl.StreamingOutput(ctx, i0, i1)
+func (s implTypeTesterServerStub) ZStream(ctx *TypeTesterZStreamContextStub, i0 int32, i1 bool) error {
+	return s.impl.ZStream(ctx, i0, i1)
 }
 
 func (s implTypeTesterServerStub) Globber() *__ipc.GlobState {
@@ -576,10 +528,11 @@
 var descTypeTester = __ipc.InterfaceDesc{
 	Name:    "TypeTester",
 	PkgPath: "v.io/core/veyron/tools/vrpc/test_base",
+	Doc:     "// TypeTester methods are listed in alphabetical order, to make it easier to\n// test Signature output, which sorts methods alphabetically.",
 	Methods: []__ipc.MethodDesc{
 		{
 			Name: "EchoBool",
-			Doc:  "// Methods to test support for generic types.",
+			Doc:  "// Methods to test support for primitive types.",
 			InArgs: []__ipc.ArgDesc{
 				{"I1", ``}, // bool
 			},
@@ -649,7 +602,7 @@
 			},
 		},
 		{
-			Name: "EchoUInt32",
+			Name: "EchoUint32",
 			InArgs: []__ipc.ArgDesc{
 				{"I1", ``}, // uint32
 			},
@@ -659,7 +612,7 @@
 			},
 		},
 		{
-			Name: "EchoUInt64",
+			Name: "EchoUint64",
 			InArgs: []__ipc.ArgDesc{
 				{"I1", ``}, // uint64
 			},
@@ -669,79 +622,59 @@
 			},
 		},
 		{
-			Name: "InputArray",
+			Name: "XEchoArray",
 			Doc:  "// Methods to test support for composite types.",
 			InArgs: []__ipc.ArgDesc{
-				{"I1", ``}, // [2]byte
+				{"I1", ``}, // [2]int32
 			},
 			OutArgs: []__ipc.ArgDesc{
-				{"", ``}, // error
+				{"O1", ``},  // [2]int32
+				{"err", ``}, // error
 			},
 		},
 		{
-			Name: "InputMap",
+			Name: "XEchoMap",
 			InArgs: []__ipc.ArgDesc{
-				{"I1", ``}, // map[byte]byte
+				{"I1", ``}, // map[int32]string
 			},
 			OutArgs: []__ipc.ArgDesc{
-				{"", ``}, // error
+				{"O1", ``},  // map[int32]string
+				{"err", ``}, // error
 			},
 		},
 		{
-			Name: "InputSlice",
+			Name: "XEchoSet",
 			InArgs: []__ipc.ArgDesc{
-				{"I1", ``}, // []byte
+				{"I1", ``}, // map[int32]struct{}
 			},
 			OutArgs: []__ipc.ArgDesc{
-				{"", ``}, // error
+				{"O1", ``},  // map[int32]struct{}
+				{"err", ``}, // error
 			},
 		},
 		{
-			Name: "InputStruct",
+			Name: "XEchoSlice",
+			InArgs: []__ipc.ArgDesc{
+				{"I1", ``}, // []int32
+			},
+			OutArgs: []__ipc.ArgDesc{
+				{"O1", ``},  // []int32
+				{"err", ``}, // error
+			},
+		},
+		{
+			Name: "XEchoStruct",
 			InArgs: []__ipc.ArgDesc{
 				{"I1", ``}, // Struct
 			},
 			OutArgs: []__ipc.ArgDesc{
-				{"", ``}, // error
-			},
-		},
-		{
-			Name: "OutputArray",
-			OutArgs: []__ipc.ArgDesc{
-				{"O1", ``},  // [2]byte
-				{"err", ``}, // error
-			},
-		},
-		{
-			Name: "OutputMap",
-			OutArgs: []__ipc.ArgDesc{
-				{"O1", ``},  // map[byte]byte
-				{"err", ``}, // error
-			},
-		},
-		{
-			Name: "OutputSlice",
-			OutArgs: []__ipc.ArgDesc{
-				{"O1", ``},  // []byte
-				{"err", ``}, // error
-			},
-		},
-		{
-			Name: "OutputStruct",
-			OutArgs: []__ipc.ArgDesc{
 				{"O1", ``},  // Struct
 				{"err", ``}, // error
 			},
 		},
 		{
-			Name: "NoArguments",
+			Name: "YMultiArg",
 			Doc:  "// Methods to test support for different number of arguments.",
-			OutArgs: []__ipc.ArgDesc{
-				{"", ``}, // error
-			},
-		},
-		{
-			Name: "MultipleArguments",
 			InArgs: []__ipc.ArgDesc{
 				{"I1", ``}, // int32
 				{"I2", ``}, // int32
@@ -753,7 +686,13 @@
 			},
 		},
 		{
-			Name: "StreamingOutput",
+			Name: "YNoArgs",
+			OutArgs: []__ipc.ArgDesc{
+				{"", ``}, // error
+			},
+		},
+		{
+			Name: "ZStream",
 			Doc:  "// Methods to test support for streaming.",
 			InArgs: []__ipc.ArgDesc{
 				{"NumStreamItems", ``}, // int32
@@ -832,7 +771,7 @@
 			{Name: "err", Type: 65},
 		},
 	}
-	result.Methods["EchoUInt32"] = __ipc.MethodSignature{
+	result.Methods["EchoUint32"] = __ipc.MethodSignature{
 		InArgs: []__ipc.MethodArgument{
 			{Name: "I1", Type: 52},
 		},
@@ -841,7 +780,7 @@
 			{Name: "err", Type: 65},
 		},
 	}
-	result.Methods["EchoUInt64"] = __ipc.MethodSignature{
+	result.Methods["EchoUint64"] = __ipc.MethodSignature{
 		InArgs: []__ipc.MethodArgument{
 			{Name: "I1", Type: 53},
 		},
@@ -850,39 +789,52 @@
 			{Name: "err", Type: 65},
 		},
 	}
-	result.Methods["InputArray"] = __ipc.MethodSignature{
+	result.Methods["XEchoArray"] = __ipc.MethodSignature{
 		InArgs: []__ipc.MethodArgument{
 			{Name: "I1", Type: 67},
 		},
 		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 65},
+			{Name: "O1", Type: 67},
+			{Name: "err", Type: 65},
 		},
 	}
-	result.Methods["InputMap"] = __ipc.MethodSignature{
+	result.Methods["XEchoMap"] = __ipc.MethodSignature{
 		InArgs: []__ipc.MethodArgument{
 			{Name: "I1", Type: 68},
 		},
 		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 65},
+			{Name: "O1", Type: 68},
+			{Name: "err", Type: 65},
 		},
 	}
-	result.Methods["InputSlice"] = __ipc.MethodSignature{
+	result.Methods["XEchoSet"] = __ipc.MethodSignature{
 		InArgs: []__ipc.MethodArgument{
 			{Name: "I1", Type: 69},
 		},
 		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 65},
+			{Name: "O1", Type: 69},
+			{Name: "err", Type: 65},
 		},
 	}
-	result.Methods["InputStruct"] = __ipc.MethodSignature{
+	result.Methods["XEchoSlice"] = __ipc.MethodSignature{
 		InArgs: []__ipc.MethodArgument{
 			{Name: "I1", Type: 70},
 		},
 		OutArgs: []__ipc.MethodArgument{
-			{Name: "", Type: 65},
+			{Name: "O1", Type: 70},
+			{Name: "err", Type: 65},
 		},
 	}
-	result.Methods["MultipleArguments"] = __ipc.MethodSignature{
+	result.Methods["XEchoStruct"] = __ipc.MethodSignature{
+		InArgs: []__ipc.MethodArgument{
+			{Name: "I1", Type: 71},
+		},
+		OutArgs: []__ipc.MethodArgument{
+			{Name: "O1", Type: 71},
+			{Name: "err", Type: 65},
+		},
+	}
+	result.Methods["YMultiArg"] = __ipc.MethodSignature{
 		InArgs: []__ipc.MethodArgument{
 			{Name: "I1", Type: 36},
 			{Name: "I2", Type: 36},
@@ -893,41 +845,13 @@
 			{Name: "err", Type: 65},
 		},
 	}
-	result.Methods["NoArguments"] = __ipc.MethodSignature{
+	result.Methods["YNoArgs"] = __ipc.MethodSignature{
 		InArgs: []__ipc.MethodArgument{},
 		OutArgs: []__ipc.MethodArgument{
 			{Name: "", Type: 65},
 		},
 	}
-	result.Methods["OutputArray"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "O1", Type: 67},
-			{Name: "err", Type: 65},
-		},
-	}
-	result.Methods["OutputMap"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "O1", Type: 68},
-			{Name: "err", Type: 65},
-		},
-	}
-	result.Methods["OutputSlice"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "O1", Type: 69},
-			{Name: "err", Type: 65},
-		},
-	}
-	result.Methods["OutputStruct"] = __ipc.MethodSignature{
-		InArgs: []__ipc.MethodArgument{},
-		OutArgs: []__ipc.MethodArgument{
-			{Name: "O1", Type: 70},
-			{Name: "err", Type: 65},
-		},
-	}
-	result.Methods["StreamingOutput"] = __ipc.MethodSignature{
+	result.Methods["ZStream"] = __ipc.MethodSignature{
 		InArgs: []__ipc.MethodArgument{
 			{Name: "NumStreamItems", Type: 36},
 			{Name: "StreamItem", Type: 2},
@@ -940,7 +864,7 @@
 	}
 
 	result.TypeDefs = []__vdlutil.Any{
-		__wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x32, Name: "byte", Tags: []string(nil)}, __wiretype.ArrayType{Elem: 0x42, Len: 0x2, Name: "", Tags: []string(nil)}, __wiretype.MapType{Key: 0x42, Elem: 0x42, Name: "", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x42, Name: "", Tags: []string(nil)}, __wiretype.StructType{
+		__wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x32, Name: "byte", Tags: []string(nil)}, __wiretype.ArrayType{Elem: 0x24, Len: 0x2, Name: "", Tags: []string(nil)}, __wiretype.MapType{Key: 0x24, Elem: 0x3, Name: "", Tags: []string(nil)}, __wiretype.MapType{Key: 0x24, Elem: 0x2, Name: "", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x24, Name: "", Tags: []string(nil)}, __wiretype.StructType{
 			[]__wiretype.FieldType{
 				__wiretype.FieldType{Type: 0x24, Name: "X"},
 				__wiretype.FieldType{Type: 0x24, Name: "Y"},
@@ -951,9 +875,9 @@
 	return result, nil
 }
 
-// TypeTesterStreamingOutputServerStream is the server stream for TypeTester.StreamingOutput.
-type TypeTesterStreamingOutputServerStream interface {
-	// SendStream returns the send side of the TypeTester.StreamingOutput server stream.
+// TypeTesterZStreamServerStream is the server stream for TypeTester.ZStream.
+type TypeTesterZStreamServerStream interface {
+	// SendStream returns the send side of the TypeTester.ZStream server stream.
 	SendStream() interface {
 		// Send places the item onto the output stream.  Returns errors encountered
 		// while sending.  Blocks if there is no buffer space; will unblock when
@@ -962,34 +886,34 @@
 	}
 }
 
-// TypeTesterStreamingOutputContext represents the context passed to TypeTester.StreamingOutput.
-type TypeTesterStreamingOutputContext interface {
+// TypeTesterZStreamContext represents the context passed to TypeTester.ZStream.
+type TypeTesterZStreamContext interface {
 	__ipc.ServerContext
-	TypeTesterStreamingOutputServerStream
+	TypeTesterZStreamServerStream
 }
 
-// TypeTesterStreamingOutputContextStub is a wrapper that converts ipc.ServerCall into
-// a typesafe stub that implements TypeTesterStreamingOutputContext.
-type TypeTesterStreamingOutputContextStub struct {
+// TypeTesterZStreamContextStub is a wrapper that converts ipc.ServerCall into
+// a typesafe stub that implements TypeTesterZStreamContext.
+type TypeTesterZStreamContextStub struct {
 	__ipc.ServerCall
 }
 
-// Init initializes TypeTesterStreamingOutputContextStub from ipc.ServerCall.
-func (s *TypeTesterStreamingOutputContextStub) Init(call __ipc.ServerCall) {
+// Init initializes TypeTesterZStreamContextStub from ipc.ServerCall.
+func (s *TypeTesterZStreamContextStub) Init(call __ipc.ServerCall) {
 	s.ServerCall = call
 }
 
-// SendStream returns the send side of the TypeTester.StreamingOutput server stream.
-func (s *TypeTesterStreamingOutputContextStub) SendStream() interface {
+// SendStream returns the send side of the TypeTester.ZStream server stream.
+func (s *TypeTesterZStreamContextStub) SendStream() interface {
 	Send(item bool) error
 } {
-	return implTypeTesterStreamingOutputContextSend{s}
+	return implTypeTesterZStreamContextSend{s}
 }
 
-type implTypeTesterStreamingOutputContextSend struct {
-	s *TypeTesterStreamingOutputContextStub
+type implTypeTesterZStreamContextSend struct {
+	s *TypeTesterZStreamContextStub
 }
 
-func (s implTypeTesterStreamingOutputContextSend) Send(item bool) error {
+func (s implTypeTesterZStreamContextSend) Send(item bool) error {
 	return s.s.Send(item)
 }
diff --git a/tools/vrpc/vrpc.go b/tools/vrpc/vrpc.go
new file mode 100644
index 0000000..5c025d3
--- /dev/null
+++ b/tools/vrpc/vrpc.go
@@ -0,0 +1,276 @@
+// The following enables go generate to generate the doc.go file.
+//go:generate go run $VANADIUM_ROOT/release/go/src/v.io/lib/cmdline/testdata/gendoc.go .
+
+package main
+
+import (
+	"fmt"
+	"io"
+	"strings"
+	"time"
+
+	"v.io/core/veyron2"
+	"v.io/core/veyron2/context"
+	"v.io/core/veyron2/ipc/reserved"
+	"v.io/core/veyron2/rt"
+	"v.io/core/veyron2/vdl"
+	"v.io/core/veyron2/vdl/build"
+	"v.io/core/veyron2/vdl/codegen/vdlgen"
+	"v.io/core/veyron2/vdl/compile"
+	"v.io/core/veyron2/vdl/vdlroot/src/signature"
+	"v.io/lib/cmdline"
+
+	_ "v.io/core/veyron/profiles"
+)
+
+var runtime veyron2.Runtime
+
+func main() {
+	var err error
+	runtime, err = rt.New()
+	if err != nil {
+		panic(err)
+	}
+	defer runtime.Cleanup()
+	cmdVRPC.Main()
+}
+
+var cmdVRPC = &cmdline.Command{
+	Name:  "vrpc",
+	Short: "Vanadium Remote Procedure Call tool",
+	Long: `
+The vrpc tool provides command-line access to Vanadium servers via Remote
+Procedure Call.
+`,
+	// TODO(toddw): Add cmdServe, which will take an interface as input, and set
+	// up a server capable of handling the given methods.  When a request is
+	// received, it'll allow the user to respond via stdin.
+	Children: []*cmdline.Command{cmdSignature, cmdCall, cmdIdentify},
+}
+
+const serverDesc = `
+<server> identifies a Vanadium server.  It can either be the object address of
+the server, or an object name that will be resolved to an end-point.
+`
+
+var cmdSignature = &cmdline.Command{
+	Run:   runSignature,
+	Name:  "signature",
+	Short: "Describe the interfaces of a Vanadium server",
+	Long: `
+Signature connects to the Vanadium server identified by <server>.
+
+If no [method] is provided, returns all interfaces implemented by the server.
+
+If a [method] is provided, returns the signature of just that method.
+`,
+	ArgsName: "<server> [method]",
+	ArgsLong: serverDesc + `
+[method] is the optional server method name.
+`,
+}
+
+var cmdCall = &cmdline.Command{
+	Run:   runCall,
+	Name:  "call",
+	Short: "Call a method of a Vanadium server",
+	Long: `
+Call connects to the Vanadium server identified by <server> and calls the
+<method> with the given positional [args...], returning results on stdout.
+
+TODO(toddw): stdin is read for streaming arguments sent to the server.  An EOF
+on stdin (e.g. via ^D) causes the send stream to be closed.
+
+Regardless of whether the call is streaming, the main goroutine blocks for
+streaming and positional results received from the server.
+
+All input arguments (both positional and streaming) are specified as VDL
+expressions, with commas separating multiple expressions.  Positional arguments
+may also be specified as separate command-line arguments.  Streaming arguments
+may also be specified as separate newline-terminated expressions.
+
+The method signature is always retrieved from the server as a first step.  This
+makes it easier to input complex typed arguments, since the top-level type for
+each argument is implicit and doesn't need to be specified.
+`,
+	ArgsName: "<server> <method> [args...]",
+	ArgsLong: serverDesc + `
+<method> is the server method to call.
+
+[args...] are the positional input arguments, specified as VDL expressions.
+`,
+}
+
+var cmdIdentify = &cmdline.Command{
+	Run:   runIdentify,
+	Name:  "identify",
+	Short: "Reveal blessings presented by a Vanadium server",
+	Long: `
+Identify connects to the Vanadium server identified by <server> and dumps out
+the blessings presented by that server (and the subset of those that are
+considered valid by the principal running this tool) to standard output.
+`,
+	ArgsName: "<server>",
+	ArgsLong: serverDesc,
+}
+
+func runSignature(cmd *cmdline.Command, args []string) error {
+	// Error-check args.
+	var server, method string
+	switch len(args) {
+	case 1:
+		server = args[0]
+	case 2:
+		server, method = args[0], args[1]
+	default:
+		return cmd.UsageErrorf("wrong number of arguments")
+	}
+	// Get the interface or method signature, and pretty-print.  We print the
+	// named types after the signatures, to aid in readability.
+	ctx, cancel := context.WithTimeout(runtime.NewContext(), time.Minute)
+	defer cancel()
+	var types signature.NamedTypes
+	if method != "" {
+		methodSig, err := reserved.MethodSignature(ctx, server, method)
+		if err != nil {
+			return fmt.Errorf("MethodSignature failed: %v", err)
+		}
+		methodSig.Print(cmd.Stdout(), &types)
+		fmt.Fprintln(cmd.Stdout())
+		types.Print(cmd.Stdout())
+		return nil
+	}
+	ifacesSig, err := reserved.Signature(ctx, server)
+	if err != nil {
+		return fmt.Errorf("Signature failed: %v", err)
+	}
+	for i, iface := range ifacesSig {
+		if i > 0 {
+			fmt.Fprintln(cmd.Stdout())
+		}
+		iface.Print(cmd.Stdout(), &types)
+		fmt.Fprintln(cmd.Stdout())
+	}
+	types.Print(cmd.Stdout())
+	return nil
+}
+
+func runCall(cmd *cmdline.Command, args []string) error {
+	// Error-check args, and set up argsdata with a comma-separated list of
+	// arguments, allowing each individual arg to already be comma-separated.
+	//
+	// TODO(toddw): Should we just space-separate the args instead?
+	if len(args) < 2 {
+		return cmd.UsageErrorf("must specify <server> and <method>")
+	}
+	server, method := args[0], args[1]
+	var argsdata string
+	for _, arg := range args[2:] {
+		arg := strings.TrimSpace(arg)
+		if argsdata == "" || strings.HasSuffix(argsdata, ",") || strings.HasPrefix(arg, ",") {
+			argsdata += arg
+		} else {
+			argsdata += "," + arg
+		}
+	}
+	// Get the method signature and parse args.
+	ctx, cancel := context.WithTimeout(runtime.NewContext(), time.Minute)
+	defer cancel()
+	methodSig, err := reserved.MethodSignature(ctx, server, method)
+	if err != nil {
+		return fmt.Errorf("MethodSignature failed: %v", err)
+	}
+	inargs, err := parseInArgs(argsdata, methodSig)
+	if err != nil {
+		// TODO: Print signature and example.
+		return err
+	}
+	// Start the method call.
+	call, err := veyron2.GetClient(ctx).StartCall(ctx, server, method, inargs)
+	if err != nil {
+		return fmt.Errorf("StartCall failed: %v", err)
+	}
+	// TODO(toddw): Fire off a goroutine to handle streaming inputs.
+	// Handle streaming results.
+StreamingResultsLoop:
+	for {
+		var item *vdl.Value
+		switch err := call.Recv(&item); {
+		case err == io.EOF:
+			break StreamingResultsLoop
+		case err != nil:
+			return fmt.Errorf("call.Recv failed: %v", err)
+		}
+		fmt.Fprintf(cmd.Stdout(), "<< %v\n", vdlgen.TypedConst(item, "", nil))
+	}
+	// Finish the method call.
+	outargs := make([]*vdl.Value, len(methodSig.OutArgs))
+	outptrs := make([]interface{}, len(outargs))
+	for i := range outargs {
+		outptrs[i] = &outargs[i]
+	}
+	if err := call.Finish(outptrs...); err != nil {
+		return fmt.Errorf("call.Finish failed: %v", err)
+	}
+	// Handle application errors, reported as a final error out-arg.
+	//
+	// TODO(toddw): Change call.Finish to report the error directly.
+	outlen := len(outargs)
+	if outlen > 0 && methodSig.OutArgs[outlen-1].Type == vdl.ErrorType {
+		if errarg := outargs[outlen-1]; !errarg.IsNil() {
+			return fmt.Errorf(vdlgen.TypedConst(errarg, "", nil))
+		}
+		outargs = outargs[:outlen-1]
+	}
+	// Pretty-print results.
+	for i, arg := range outargs {
+		if i > 0 {
+			fmt.Fprint(cmd.Stdout(), " ")
+		}
+		fmt.Fprint(cmd.Stdout(), vdlgen.TypedConst(arg, "", nil))
+	}
+	fmt.Fprintln(cmd.Stdout())
+	return nil
+}
+
+func parseInArgs(argsdata string, methodSig signature.Method) ([]interface{}, error) {
+	if len(methodSig.InArgs) == 0 {
+		return nil, nil
+	}
+	var intypes []*vdl.Type
+	for _, inarg := range methodSig.InArgs {
+		intypes = append(intypes, inarg.Type)
+	}
+	env := compile.NewEnv(-1)
+	inargs := build.BuildExprs(argsdata, intypes, env)
+	if err := env.Errors.ToError(); err != nil {
+		return nil, fmt.Errorf("can't parse in-args:\n%v", err)
+	}
+	if got, want := len(inargs), len(methodSig.InArgs); got != want {
+		return nil, fmt.Errorf("got %d args, want %d", got, want)
+	}
+	// Translate []*vdl.Value to []interface, with each item still *vdl.Value.
+	var ret []interface{}
+	for _, arg := range inargs {
+		ret = append(ret, arg)
+	}
+	return ret, nil
+}
+
+func runIdentify(cmd *cmdline.Command, args []string) error {
+	if len(args) != 1 {
+		return cmd.UsageErrorf("wrong number of arguments")
+	}
+	server := args[0]
+	ctx, cancel := context.WithTimeout(runtime.NewContext(), time.Minute)
+	defer cancel()
+	// The method name does not matter - only interested in authentication,
+	// not in actually making an RPC.
+	call, err := veyron2.GetClient(ctx).StartCall(ctx, server, "", nil)
+	if err != nil {
+		return fmt.Errorf(`client.StartCall(%q, "", nil) failed with %v`, server, err)
+	}
+	valid, presented := call.RemoteBlessings()
+	fmt.Fprintf(cmd.Stdout(), "PRESENTED:  %v\nVALID:      %v\n", presented, valid)
+	return nil
+}
diff --git a/tools/vrpc/vrpc_test.go b/tools/vrpc/vrpc_test.go
new file mode 100644
index 0000000..f74b40d
--- /dev/null
+++ b/tools/vrpc/vrpc_test.go
@@ -0,0 +1,335 @@
+package main
+
+import (
+	"bytes"
+	"strings"
+	"testing"
+
+	"v.io/core/veyron2"
+	"v.io/core/veyron2/ipc"
+	"v.io/core/veyron2/rt"
+	"v.io/core/veyron2/vlog"
+
+	"v.io/core/veyron/profiles"
+	"v.io/core/veyron/tools/vrpc/test_base"
+)
+
+type server struct{}
+
+// TypeTester interface implementation
+
+func (*server) EchoBool(call ipc.ServerContext, i1 bool) (bool, error) {
+	vlog.VI(2).Info("EchoBool(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoFloat32(call ipc.ServerContext, i1 float32) (float32, error) {
+	vlog.VI(2).Info("EchoFloat32(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoFloat64(call ipc.ServerContext, i1 float64) (float64, error) {
+	vlog.VI(2).Info("EchoFloat64(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoInt32(call ipc.ServerContext, i1 int32) (int32, error) {
+	vlog.VI(2).Info("EchoInt32(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoInt64(call ipc.ServerContext, i1 int64) (int64, error) {
+	vlog.VI(2).Info("EchoInt64(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoString(call ipc.ServerContext, i1 string) (string, error) {
+	vlog.VI(2).Info("EchoString(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoByte(call ipc.ServerContext, i1 byte) (byte, error) {
+	vlog.VI(2).Info("EchoByte(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoUint32(call ipc.ServerContext, i1 uint32) (uint32, error) {
+	vlog.VI(2).Info("EchoUint32(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) EchoUint64(call ipc.ServerContext, i1 uint64) (uint64, error) {
+	vlog.VI(2).Info("EchoUint64(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) XEchoArray(call ipc.ServerContext, i1 [2]int32) ([2]int32, error) {
+	vlog.VI(2).Info("XEchoArray(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) XEchoMap(call ipc.ServerContext, i1 map[int32]string) (map[int32]string, error) {
+	vlog.VI(2).Info("XEchoMap(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) XEchoSet(call ipc.ServerContext, i1 map[int32]struct{}) (map[int32]struct{}, error) {
+	vlog.VI(2).Info("XEchoSet(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) XEchoSlice(call ipc.ServerContext, i1 []int32) ([]int32, error) {
+	vlog.VI(2).Info("XEchoSlice(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) XEchoStruct(call ipc.ServerContext, i1 test_base.Struct) (test_base.Struct, error) {
+	vlog.VI(2).Info("XEchoStruct(%v) was called.", i1)
+	return i1, nil
+}
+
+func (*server) YMultiArg(call ipc.ServerContext, i1, i2 int32) (int32, int32, error) {
+	vlog.VI(2).Info("YMultiArg(%v,%v) was called.", i1, i2)
+	return i1, i2, nil
+}
+
+func (*server) YNoArgs(call ipc.ServerContext) error {
+	vlog.VI(2).Info("YNoArgs() was called.")
+	return nil
+}
+
+func (*server) ZStream(ctx test_base.TypeTesterZStreamContext, nStream int32, item bool) error {
+	vlog.VI(2).Info("ZStream(%v,%v) was called.", nStream, item)
+	sender := ctx.SendStream()
+	for i := int32(0); i < nStream; i++ {
+		sender.Send(item)
+	}
+	return nil
+}
+
+func initTest(t *testing.T) (name string, cleanup func()) {
+	// The runtime initialized here is the global runtime defined in vrpc.go.
+	var ipcServer ipc.Server
+	cleanup = func() {
+		if ipcServer != nil {
+			if err := ipcServer.Stop(); err != nil {
+				t.Errorf("server.Stop failed: %v", err)
+			}
+		}
+		if runtime != nil {
+			runtime.Cleanup()
+		}
+	}
+	var err error
+	if runtime, err = rt.New(); err != nil {
+		t.Fatalf("rt.New() failed: %v", err)
+		return
+	}
+	if ipcServer, err = veyron2.NewServer(runtime.NewContext()); err != nil {
+		t.Fatalf("NewServer failed: %v", err)
+		return
+	}
+	endpoints, err := ipcServer.Listen(profiles.LocalListenSpec)
+	if err != nil {
+		t.Fatalf("Listen failed: %v", err)
+		return
+	}
+	name = endpoints[0].Name()
+	obj := test_base.TypeTesterServer(&server{})
+	if err := ipcServer.Serve("", obj, nil); err != nil {
+		t.Fatalf("Serve failed: %v", err)
+		return
+	}
+	return
+}
+
+func TestSignature(t *testing.T) {
+	name, cleanup := initTest(t)
+	defer cleanup()
+	var stdout, stderr bytes.Buffer
+	cmdVRPC.Init(nil, &stdout, &stderr)
+
+	if err := cmdVRPC.Execute([]string{"signature", name}); err != nil {
+		t.Errorf("%v", err)
+		return
+	}
+	wantSig := `// TypeTester methods are listed in alphabetical order, to make it easier to
+// test Signature output, which sorts methods alphabetically.
+type "v.io/core/veyron/tools/vrpc/test_base".TypeTester interface {
+	// Methods to test support for primitive types.
+	EchoBool(I1 bool) (O1 bool | error)
+	EchoByte(I1 byte) (O1 byte | error)
+	EchoFloat32(I1 float32) (O1 float32 | error)
+	EchoFloat64(I1 float64) (O1 float64 | error)
+	EchoInt32(I1 int32) (O1 int32 | error)
+	EchoInt64(I1 int64) (O1 int64 | error)
+	EchoString(I1 string) (O1 string | error)
+	EchoUint32(I1 uint32) (O1 uint32 | error)
+	EchoUint64(I1 uint64) (O1 uint64 | error)
+	// Methods to test support for composite types.
+	XEchoArray(I1 [2]int32) (O1 [2]int32 | error)
+	XEchoMap(I1 map[int32]string) (O1 map[int32]string | error)
+	XEchoSet(I1 set[int32]) (O1 set[int32] | error)
+	XEchoSlice(I1 []int32) (O1 []int32 | error)
+	XEchoStruct(I1 "v.io/core/veyron/tools/vrpc/test_base".Struct) (O1 "v.io/core/veyron/tools/vrpc/test_base".Struct | error)
+	// Methods to test support for different number of arguments.
+	YMultiArg(I1 int32, I2 int32) (O1 int32, O2 int32 | error)
+	YNoArgs() error
+	// Methods to test support for streaming.
+	ZStream(NumStreamItems int32, StreamItem bool) stream<_, bool> error
+}
+
+// The empty interface contains methods not attached to any interface.
+type <empty> interface {
+	Signature() ("v.io/core/veyron2/ipc".ServiceSignature | error)
+}
+
+// Reserved methods implemented by the IPC framework.  Each method name is prefixed with a double underscore "__".
+type __Reserved interface {
+	// Glob returns all entries matching the pattern.
+	__Glob(pattern string) stream<any, any> error
+	// MethodSignature returns the signature for the given method.
+	__MethodSignature(method string) ("signature".Method | error)
+	// Signature returns all interface signatures implemented by the object.
+	__Signature() ([]"signature".Interface | error)
+}
+
+type "signature".Arg struct {
+	Name string
+	Doc string
+	Type typeobject
+}
+
+type "signature".Embed struct {
+	Name string
+	PkgPath string
+	Doc string
+}
+
+type "signature".Interface struct {
+	Name string
+	PkgPath string
+	Doc string
+	Embeds []"signature".Embed
+	Methods []"signature".Method
+}
+
+type "signature".Method struct {
+	Name string
+	Doc string
+	InArgs []"signature".Arg
+	OutArgs []"signature".Arg
+	InStream ?"signature".Arg
+	OutStream ?"signature".Arg
+	Tags []any
+}
+
+type "v.io/core/veyron/tools/vrpc/test_base".Struct struct {
+	X int32
+	Y int32
+}
+
+type "v.io/core/veyron2/ipc".MethodArgument struct {
+	Name string
+	Type "v.io/core/veyron2/wiretype".TypeID
+}
+
+type "v.io/core/veyron2/ipc".MethodSignature struct {
+	InArgs []"v.io/core/veyron2/ipc".MethodArgument
+	OutArgs []"v.io/core/veyron2/ipc".MethodArgument
+	InStream "v.io/core/veyron2/wiretype".TypeID
+	OutStream "v.io/core/veyron2/wiretype".TypeID
+}
+
+type "v.io/core/veyron2/ipc".ServiceSignature struct {
+	TypeDefs []any
+	Methods map[string]"v.io/core/veyron2/ipc".MethodSignature
+}
+
+type "v.io/core/veyron2/wiretype".TypeID uint64
+`
+	if got, want := stdout.String(), wantSig; got != want {
+		t.Errorf("got stdout %q, want %q", got, want)
+	}
+	if got, want := stderr.String(), ""; got != want {
+		t.Errorf("got stderr %q, want %q", got, want)
+	}
+}
+
+func TestMethodSignature(t *testing.T) {
+	name, cleanup := initTest(t)
+	defer cleanup()
+
+	tests := []struct {
+		Method, Want string
+	}{
+		// Spot-check some individual methods.
+		{"EchoByte", `EchoByte(I1 byte) (O1 byte | error)`},
+		{"EchoFloat32", `EchoFloat32(I1 float32) (O1 float32 | error)`},
+		{"XEchoStruct", `
+XEchoStruct(I1 "v.io/core/veyron/tools/vrpc/test_base".Struct) (O1 "v.io/core/veyron/tools/vrpc/test_base".Struct | error)
+
+type "v.io/core/veyron/tools/vrpc/test_base".Struct struct {
+	X int32
+	Y int32
+}
+`},
+	}
+	for _, test := range tests {
+		var stdout, stderr bytes.Buffer
+		cmdVRPC.Init(nil, &stdout, &stderr)
+		if err := cmdVRPC.Execute([]string{"signature", name, test.Method}); err != nil {
+			t.Errorf("%q failed: %v", test.Method, err)
+			continue
+		}
+		if got, want := strings.TrimSpace(stdout.String()), strings.TrimSpace(test.Want); got != want {
+			t.Errorf("got stdout %q, want %q", got, want)
+		}
+		if got, want := stderr.String(), ""; got != want {
+			t.Errorf("got stderr %q, want %q", got, want)
+		}
+	}
+}
+
+func TestCall(t *testing.T) {
+	name, cleanup := initTest(t)
+	defer cleanup()
+
+	tests := []struct {
+		Method, InArgs, Want string
+	}{
+		{"EchoBool", `true`, `true`},
+		{"EchoBool", `false`, `false`},
+		{"EchoFloat32", `1.2`, `float32(1.2)`},
+		{"EchoFloat64", `-3.4`, `float64(-3.4)`},
+		{"EchoInt32", `11`, `int32(11)`},
+		{"EchoInt64", `-22`, `int64(-22)`},
+		{"EchoString", `"abc"`, `"abc"`},
+		{"EchoByte", `33`, `byte(33)`},
+		{"EchoUint32", `44`, `uint32(44)`},
+		{"EchoUint64", `55`, `uint64(55)`},
+		{"XEchoArray", `{1,2}`, `[2]int32{1, 2}`},
+		{"XEchoMap", `{1:"a"}`, `map[int32]string{1: "a"}`},
+		{"XEchoSet", `{1}`, `set[int32]{1}`},
+		{"XEchoSlice", `{1,2}`, `[]int32{1, 2}`},
+		{"XEchoStruct", `{1,2}`, `"v.io/core/veyron/tools/vrpc/test_base".Struct{X: 1, Y: 2}`},
+		{"YMultiArg", `1,2`, `int32(1) int32(2)`},
+		{"YNoArgs", ``, ``},
+		{"ZStream", `2,true`, `<< true
+<< true`},
+	}
+	for _, test := range tests {
+		var stdout, stderr bytes.Buffer
+		cmdVRPC.Init(nil, &stdout, &stderr)
+		if err := cmdVRPC.Execute([]string{"call", name, test.Method, test.InArgs}); err != nil {
+			t.Errorf("%q(%s) failed: %v", test.Method, test.InArgs, err)
+			continue
+		}
+		if got, want := strings.TrimSpace(stdout.String()), strings.TrimSpace(test.Want); got != want {
+			t.Errorf("got stdout %q, want %q", got, want)
+		}
+		if got, want := stderr.String(), ""; got != want {
+			t.Errorf("got stderr %q, want %q", got, want)
+		}
+	}
+}