veyron/runtimes/fake: Create a fake runtime and profile.

The fake runtime can be used in tests that want to mock out the major runtime
interfaces without instantiating a real runtime.  I have only partially
implemented the runtime.  Some methods panic.

I also remove the SetClient method that we added as a hack to allow
tests with mock clients.

MultiPart: 1/2
Change-Id: I4f2b03bb92d660f21304a3cce7bc55887cfa8723
diff --git a/profiles/fake/fake.go b/profiles/fake/fake.go
new file mode 100644
index 0000000..a91374f
--- /dev/null
+++ b/profiles/fake/fake.go
@@ -0,0 +1,16 @@
+package fake
+
+import (
+	"v.io/core/veyron2"
+	"v.io/core/veyron2/context"
+
+	"v.io/core/veyron/runtimes/fake"
+)
+
+func init() {
+	veyron2.RegisterProfileInit(Init)
+}
+
+func Init(ctx *context.T) (veyron2.RuntimeX, *context.T, veyron2.Shutdown, error) {
+	return fake.Init(ctx)
+}
diff --git a/runtimes/fake/fake_test.go b/runtimes/fake/fake_test.go
new file mode 100644
index 0000000..c61a963
--- /dev/null
+++ b/runtimes/fake/fake_test.go
@@ -0,0 +1,19 @@
+package fake_test
+
+import (
+	"testing"
+
+	"v.io/core/veyron2"
+
+	_ "v.io/core/veyron/profiles/fake"
+)
+
+// Ensure that the fake profile can be used to initialize a fake runtime.
+func TestInit(t *testing.T) {
+	ctx, shutdown := veyron2.Init()
+	defer shutdown()
+
+	if !ctx.Initialized() {
+		t.Errorf("Got uninitialized context from Init.")
+	}
+}
diff --git a/runtimes/fake/ipc.go b/runtimes/fake/ipc.go
new file mode 100644
index 0000000..755953d
--- /dev/null
+++ b/runtimes/fake/ipc.go
@@ -0,0 +1,33 @@
+package fake
+
+import (
+	"v.io/core/veyron2/context"
+	"v.io/core/veyron2/ipc"
+	"v.io/core/veyron2/ipc/stream"
+)
+
+// SetClient can be used to inject a mock client implementation into the context.
+func SetClient(ctx *context.T, client ipc.Client) *context.T {
+	return context.WithValue(ctx, clientKey, client)
+}
+func (r *Runtime) SetNewClient(ctx *context.T, opts ...ipc.ClientOpt) (*context.T, ipc.Client, error) {
+	panic("unimplemented")
+}
+func (r *Runtime) GetClient(ctx *context.T) ipc.Client {
+	c, _ := ctx.Value(clientKey).(ipc.Client)
+	return c
+}
+
+func (r *Runtime) NewServer(ctx *context.T, opts ...ipc.ServerOpt) (ipc.Server, error) {
+	panic("unimplemented")
+}
+func (r *Runtime) SetNewStreamManager(ctx *context.T, opts ...stream.ManagerOpt) (*context.T, stream.Manager, error) {
+	panic("unimplemented")
+}
+func (r *Runtime) GetStreamManager(ctx *context.T) stream.Manager {
+	panic("unimplemented")
+}
+
+func (r *Runtime) GetListenSpec(ctx *context.T) ipc.ListenSpec {
+	return ipc.ListenSpec{}
+}
diff --git a/runtimes/fake/naming.go b/runtimes/fake/naming.go
new file mode 100644
index 0000000..4028324
--- /dev/null
+++ b/runtimes/fake/naming.go
@@ -0,0 +1,16 @@
+package fake
+
+import (
+	"v.io/core/veyron2/context"
+	"v.io/core/veyron2/naming"
+)
+
+func (r *Runtime) NewEndpoint(ep string) (naming.Endpoint, error) {
+	panic("unimplemented")
+}
+func (r *Runtime) SetNewNamespace(ctx *context.T, roots ...string) (*context.T, naming.Namespace, error) {
+	panic("unimplemented")
+}
+func (r *Runtime) GetNamespace(ctx *context.T) naming.Namespace {
+	panic("unimplemented")
+}
diff --git a/runtimes/fake/runtime.go b/runtimes/fake/runtime.go
new file mode 100644
index 0000000..df58a25
--- /dev/null
+++ b/runtimes/fake/runtime.go
@@ -0,0 +1,79 @@
+// fake implements a fake runtime.  The fake runtime is useful in tests when you
+// want to mock out important components.
+// TODO(mattr): Make a more complete, but still fake, implementation.
+package fake
+
+import (
+	"v.io/core/veyron2"
+	"v.io/core/veyron2/context"
+	"v.io/core/veyron2/security"
+	"v.io/core/veyron2/vlog"
+
+	tsecurity "v.io/core/veyron/lib/testutil/security"
+)
+
+type contextKey int
+
+const (
+	clientKey = contextKey(iota)
+	principalKey
+	loggerKey
+	backgroundKey
+)
+
+type Runtime struct{}
+
+func Init(ctx *context.T) (*Runtime, *context.T, veyron2.Shutdown, error) {
+	ctx = context.WithValue(ctx, principalKey, tsecurity.NewPrincipal())
+	return &Runtime{}, ctx, func() {}, nil
+}
+
+func (r *Runtime) SetPrincipal(ctx *context.T, principal security.Principal) (*context.T, error) {
+	return context.WithValue(ctx, principalKey, principal), nil
+}
+
+func (r *Runtime) GetPrincipal(ctx *context.T) security.Principal {
+	p, _ := ctx.Value(principalKey).(security.Principal)
+	return p
+}
+
+func (r *Runtime) SetNewLogger(ctx *context.T, name string, opts ...vlog.LoggingOpts) (*context.T, vlog.Logger, error) {
+	logger, err := vlog.NewLogger(name, opts...)
+	if err != nil {
+		return context.WithValue(ctx, loggerKey, logger), logger, nil
+	}
+	return ctx, nil, err
+}
+
+func (r *Runtime) GetLogger(ctx *context.T) vlog.Logger {
+	l, _ := ctx.Value(loggerKey).(vlog.Logger)
+	return l
+}
+
+func (r *Runtime) GetProfile(ctx *context.T) veyron2.Profile {
+	panic("unimplemented")
+}
+
+func (r *Runtime) GetAppCycle(ctx *context.T) veyron2.AppCycle {
+	panic("unimplemented")
+}
+
+func (r *Runtime) SetBackgroundContext(ctx *context.T) *context.T {
+	// Note we add an extra context with a nil value here.
+	// This prevents users from travelling back through the
+	// chain of background contexts.
+	ctx = context.WithValue(ctx, backgroundKey, nil)
+	return context.WithValue(ctx, backgroundKey, ctx)
+}
+
+func (r *Runtime) GetBackgroundContext(ctx *context.T) *context.T {
+	bctx, _ := ctx.Value(backgroundKey).(*context.T)
+	if bctx == nil {
+		// There should always be a background context.  If we don't find
+		// it, that means that the user passed us the background context
+		// in hopes of following the chain.  Instead we just give them
+		// back what they sent in, which is correct.
+		return ctx
+	}
+	return bctx
+}
diff --git a/runtimes/google/rt/runtimex.go b/runtimes/google/rt/runtimex.go
index 6686a6b..ab9047a 100644
--- a/runtimes/google/rt/runtimex.go
+++ b/runtimes/google/rt/runtimex.go
@@ -78,7 +78,7 @@
 		&reservedNameDispatcher{rt.reservedDisp, rt.reservedOpts})
 	ctx = context.WithValue(ctx, streamManagerKey, rt.sm[0])
 	hackruntime.addChild(ctx, rt.sm[0], func() {})
-	ctx = SetClient(ctx, rt.client)
+	ctx = context.WithValue(ctx, clientKey, rt.client)
 	hackruntime.addChild(ctx, rt.client, func() {})
 	ctx = context.WithValue(ctx, namespaceKey, rt.ns)
 	ctx = context.WithValue(ctx, loggerKey, vlog.Log)
@@ -473,7 +473,7 @@
 	if err != nil {
 		return ctx, nil, err
 	}
-	newctx := SetClient(ctx, client)
+	newctx := context.WithValue(ctx, clientKey, client)
 	if err = r.addChild(ctx, client, client.Close, sm, vtraceDependency{}); err != nil {
 		return ctx, nil, err
 	}
@@ -485,14 +485,6 @@
 	return cl
 }
 
-// SetClient attaches client to ctx and returns the resulting context.
-//
-// WARNING: This function is only exposed for tests; regular production code
-// should never call this function.
-func SetClient(ctx *context.T, client ipc.Client) *context.T {
-	return context.WithValue(ctx, clientKey, client)
-}
-
 func (*RuntimeX) setNewNamespace(ctx *context.T, roots ...string) (*context.T, naming.Namespace, error) {
 	ns, err := namespace.New(roots...)
 	// TODO(mattr): Copy cache settings.