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.