Merge "x/ref: make use of ctx arg to Lookup."
diff --git a/services/device/device/acl_test.go b/services/device/device/acl_test.go
index 5a401c9..0deb899 100644
--- a/services/device/device/acl_test.go
+++ b/services/device/device/acl_test.go
@@ -20,6 +20,7 @@
"v.io/x/ref/test"
cmd_device "v.io/x/ref/services/device/device"
+ "v.io/x/ref/services/internal/servicetest"
)
const pkgPath = "v.io/x/ref/services/device/main"
@@ -32,7 +33,7 @@
ctx, shutdown := test.V23Init()
defer shutdown()
- tapes := newTapeMap()
+ tapes := servicetest.NewTapeMap()
server, err := xrpc.NewDispatchingServer(ctx, "", newDispatcher(t, tapes))
if err != nil {
t.Fatalf("NewServer failed: %v", err)
@@ -45,7 +46,7 @@
deviceName := server.Status().Endpoints[0].Name()
// Test the 'get' command.
- rootTape := tapes.forSuffix("")
+ rootTape := tapes.ForSuffix("")
rootTape.SetResponses(GetPermissionsResponse{
perms: access.Permissions{
"Admin": access.AccessList{
@@ -79,7 +80,7 @@
ctx, shutdown := test.V23Init()
defer shutdown()
- tapes := newTapeMap()
+ tapes := servicetest.NewTapeMap()
server, err := xrpc.NewDispatchingServer(ctx, "", newDispatcher(t, tapes))
if err != nil {
t.Fatalf("NewServer failed: %v", err)
@@ -129,7 +130,7 @@
// Correct operation in the absence of errors.
stderr.Reset()
stdout.Reset()
- rootTape := tapes.forSuffix("")
+ rootTape := tapes.ForSuffix("")
rootTape.SetResponses(
GetPermissionsResponse{
perms: access.Permissions{
diff --git a/services/device/device/associate_test.go b/services/device/device/associate_test.go
index 78a5140..099d424 100644
--- a/services/device/device/associate_test.go
+++ b/services/device/device/associate_test.go
@@ -17,13 +17,14 @@
"v.io/x/ref/test"
cmd_device "v.io/x/ref/services/device/device"
+ "v.io/x/ref/services/internal/servicetest"
)
func TestListCommand(t *testing.T) {
ctx, shutdown := test.V23Init()
defer shutdown()
- tapes := newTapeMap()
+ tapes := servicetest.NewTapeMap()
server, err := xrpc.NewDispatchingServer(ctx, "", newDispatcher(t, tapes))
if err != nil {
t.Fatalf("NewServer failed: %v", err)
@@ -35,7 +36,7 @@
env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
deviceName := server.Status().Endpoints[0].Name()
- rootTape := tapes.forSuffix("")
+ rootTape := tapes.ForSuffix("")
// Test the 'list' command.
rootTape.SetResponses(ListAssociationResponse{
na: []device.Association{
@@ -76,7 +77,7 @@
ctx, shutdown := test.V23Init()
defer shutdown()
- tapes := newTapeMap()
+ tapes := servicetest.NewTapeMap()
server, err := xrpc.NewDispatchingServer(ctx, "", newDispatcher(t, tapes))
if err != nil {
t.Fatalf("NewServer failed: %v", err)
@@ -91,7 +92,7 @@
if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"add", "one"}); err == nil {
t.Fatalf("wrongly failed to receive a non-nil error.")
}
- rootTape := tapes.forSuffix("")
+ rootTape := tapes.ForSuffix("")
if got, expected := len(rootTape.Play()), 0; got != expected {
t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
}
@@ -127,7 +128,7 @@
ctx, shutdown := test.V23Init()
defer shutdown()
- tapes := newTapeMap()
+ tapes := servicetest.NewTapeMap()
server, err := xrpc.NewDispatchingServer(ctx, "", newDispatcher(t, tapes))
if err != nil {
t.Fatalf("NewServer failed: %v", err)
@@ -142,7 +143,7 @@
if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"remove", "one"}); err == nil {
t.Fatalf("wrongly failed to receive a non-nil error.")
}
- rootTape := tapes.forSuffix("")
+ rootTape := tapes.ForSuffix("")
if got, expected := len(rootTape.Play()), 0; got != expected {
t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
}
diff --git a/services/device/device/claim_test.go b/services/device/device/claim_test.go
index e5df2cb..0ac45aa 100644
--- a/services/device/device/claim_test.go
+++ b/services/device/device/claim_test.go
@@ -20,13 +20,14 @@
"v.io/x/ref/test"
cmd_device "v.io/x/ref/services/device/device"
+ "v.io/x/ref/services/internal/servicetest"
)
func TestClaimCommand(t *testing.T) {
ctx, shutdown := test.V23Init()
defer shutdown()
- tapes := newTapeMap()
+ tapes := servicetest.NewTapeMap()
server, err := xrpc.NewDispatchingServer(ctx, "", newDispatcher(t, tapes))
if err != nil {
t.Fatalf("NewServer failed: %v", err)
@@ -51,7 +52,7 @@
}
stdout.Reset()
stderr.Reset()
- rootTape := tapes.forSuffix("")
+ rootTape := tapes.ForSuffix("")
rootTape.Rewind()
if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"claim", "nope", "nope", "nope", "nope", "nope"}); err == nil {
diff --git a/services/device/device/debug_test.go b/services/device/device/debug_test.go
index 11295a9..cc8f528 100644
--- a/services/device/device/debug_test.go
+++ b/services/device/device/debug_test.go
@@ -18,12 +18,13 @@
"v.io/x/ref/test"
cmd_device "v.io/x/ref/services/device/device"
+ "v.io/x/ref/services/internal/servicetest"
)
func TestDebugCommand(t *testing.T) {
ctx, shutdown := test.V23Init()
defer shutdown()
- tapes := newTapeMap()
+ tapes := servicetest.NewTapeMap()
server, err := xrpc.NewDispatchingServer(ctx, "", newDispatcher(t, tapes))
if err != nil {
t.Fatalf("NewServer failed: %v", err)
@@ -33,7 +34,7 @@
addr := server.Status().Endpoints[0].String()
globName := naming.JoinAddressName(addr, "glob")
appName := naming.JoinAddressName(addr, "app")
- rootTape, appTape := tapes.forSuffix(""), tapes.forSuffix("app")
+ rootTape, appTape := tapes.ForSuffix(""), tapes.ForSuffix("app")
rootTape.SetResponses(GlobResponse{results: []string{"app"}})
var stdout, stderr bytes.Buffer
diff --git a/services/device/device/devicemanager_mock_test.go b/services/device/device/devicemanager_mock_test.go
index 527e951..d683d0b 100644
--- a/services/device/device/devicemanager_mock_test.go
+++ b/services/device/device/devicemanager_mock_test.go
@@ -25,10 +25,11 @@
"v.io/x/ref/services/internal/binarylib"
"v.io/x/ref/services/internal/packages"
+ "v.io/x/ref/services/internal/servicetest"
)
type mockDeviceInvoker struct {
- tape *tape
+ tape *servicetest.Tape
t *testing.T
}
@@ -302,14 +303,14 @@
}
type dispatcher struct {
- tapes *tapeMap
+ tapes *servicetest.TapeMap
t *testing.T
}
-func newDispatcher(t *testing.T, tapes *tapeMap) rpc.Dispatcher {
+func newDispatcher(t *testing.T, tapes *servicetest.TapeMap) rpc.Dispatcher {
return &dispatcher{tapes: tapes, t: t}
}
func (d *dispatcher) Lookup(_ *context.T, suffix string) (interface{}, security.Authorizer, error) {
- return &mockDeviceInvoker{tape: d.tapes.forSuffix(suffix), t: d.t}, nil, nil
+ return &mockDeviceInvoker{tape: d.tapes.ForSuffix(suffix), t: d.t}, nil, nil
}
diff --git a/services/device/device/glob_test.go b/services/device/device/glob_test.go
index ad8db50..1569872 100644
--- a/services/device/device/glob_test.go
+++ b/services/device/device/glob_test.go
@@ -24,6 +24,7 @@
"v.io/x/ref/test"
cmd_device "v.io/x/ref/services/device/device"
+ "v.io/x/ref/services/internal/servicetest"
)
func simplePrintHandler(entry cmd_device.GlobResult, _ *context.T, stdout, _ io.Writer) error {
@@ -147,8 +148,8 @@
func TestGlob(t *testing.T) {
ctx, shutdown := test.V23Init()
defer shutdown()
- tapes := newTapeMap()
- rootTape := tapes.forSuffix("")
+ tapes := servicetest.NewTapeMap()
+ rootTape := tapes.ForSuffix("")
server, err := xrpc.NewDispatchingServer(ctx, "", newDispatcher(t, tapes))
if err != nil {
t.Fatalf("NewServer failed: %v", err)
@@ -421,14 +422,14 @@
"encountered a total of 2 error(s)",
},
} {
- tapes.rewind()
+ tapes.Rewind()
var rootTapeResponses []interface{}
for _, r := range c.globResponses {
rootTapeResponses = append(rootTapeResponses, r)
}
rootTape.SetResponses(rootTapeResponses...)
for n, r := range c.statusResponses {
- tapes.forSuffix(n).SetResponses(r...)
+ tapes.ForSuffix(n).SetResponses(r...)
}
var stdout, stderr bytes.Buffer
env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
diff --git a/services/device/device/install_test.go b/services/device/device/install_test.go
index dd95099..61e766d 100644
--- a/services/device/device/install_test.go
+++ b/services/device/device/install_test.go
@@ -21,13 +21,14 @@
"v.io/x/ref/test"
cmd_device "v.io/x/ref/services/device/device"
+ "v.io/x/ref/services/internal/servicetest"
)
func TestInstallCommand(t *testing.T) {
ctx, shutdown := test.V23Init()
defer shutdown()
- tapes := newTapeMap()
+ tapes := servicetest.NewTapeMap()
server, err := xrpc.NewDispatchingServer(ctx, "", newDispatcher(t, tapes))
if err != nil {
t.Fatalf("NewServer failed: %v", err)
@@ -41,7 +42,7 @@
appId := "myBestAppID"
cfg := device.Config{"someflag": "somevalue"}
pkg := application.Packages{"pkg": application.SignedFile{File: "somename"}}
- rootTape := tapes.forSuffix("")
+ rootTape := tapes.ForSuffix("")
for i, c := range []struct {
args []string
config device.Config
diff --git a/services/device/device/instantiate_test.go b/services/device/device/instantiate_test.go
index db6d97d..53ff9ac 100644
--- a/services/device/device/instantiate_test.go
+++ b/services/device/device/instantiate_test.go
@@ -18,13 +18,14 @@
"v.io/x/ref/test"
cmd_device "v.io/x/ref/services/device/device"
+ "v.io/x/ref/services/internal/servicetest"
)
func TestInstantiateCommand(t *testing.T) {
ctx, shutdown := test.V23Init()
defer shutdown()
- tapes := newTapeMap()
+ tapes := servicetest.NewTapeMap()
server, err := xrpc.NewDispatchingServer(ctx, "", newDispatcher(t, tapes))
if err != nil {
t.Fatalf("NewServer failed: %v", err)
@@ -45,7 +46,7 @@
}
stdout.Reset()
stderr.Reset()
- rootTape := tapes.forSuffix("")
+ rootTape := tapes.ForSuffix("")
rootTape.Rewind()
if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"instantiate", "nope", "nope", "nope"}); err == nil {
diff --git a/services/device/device/kill_test.go b/services/device/device/kill_test.go
index f5fd65d..3b37881 100644
--- a/services/device/device/kill_test.go
+++ b/services/device/device/kill_test.go
@@ -19,13 +19,14 @@
"v.io/x/ref/test"
cmd_device "v.io/x/ref/services/device/device"
+ "v.io/x/ref/services/internal/servicetest"
)
func TestKillCommand(t *testing.T) {
ctx, shutdown := test.V23Init()
defer shutdown()
- tapes := newTapeMap()
+ tapes := servicetest.NewTapeMap()
server, err := xrpc.NewDispatchingServer(ctx, "", newDispatcher(t, tapes))
if err != nil {
t.Fatalf("NewServer failed: %v", err)
@@ -46,7 +47,7 @@
}
stdout.Reset()
stderr.Reset()
- appTape := tapes.forSuffix("appname")
+ appTape := tapes.ForSuffix("appname")
appTape.Rewind()
if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"kill", "nope", "nope"}); err == nil {
diff --git a/services/device/device/local_install_test.go b/services/device/device/local_install_test.go
index b9996ca..aa0d615 100644
--- a/services/device/device/local_install_test.go
+++ b/services/device/device/local_install_test.go
@@ -25,6 +25,7 @@
"v.io/x/ref/test"
cmd_device "v.io/x/ref/services/device/device"
+ "v.io/x/ref/services/internal/servicetest"
)
func createFile(t *testing.T, path string, contents string) {
@@ -37,7 +38,7 @@
ctx, shutdown := test.V23Init()
defer shutdown()
- tapes := newTapeMap()
+ tapes := servicetest.NewTapeMap()
server, err := xrpc.NewDispatchingServer(ctx, "", newDispatcher(t, tapes))
if err != nil {
t.Fatalf("NewServer failed: %v", err)
@@ -54,7 +55,7 @@
t.Fatalf("Failed to stat %v: %v", binary, err)
}
binarySize := fi.Size()
- rootTape := tapes.forSuffix("")
+ rootTape := tapes.ForSuffix("")
for i, c := range []struct {
args []string
stderrSubstr string
diff --git a/services/device/device/ls_test.go b/services/device/device/ls_test.go
index d85b6d3..79974b1 100644
--- a/services/device/device/ls_test.go
+++ b/services/device/device/ls_test.go
@@ -16,6 +16,7 @@
"v.io/x/ref/test"
cmd_device "v.io/x/ref/services/device/device"
+ "v.io/x/ref/services/internal/servicetest"
)
// TestLsCommand verifies the device ls command. It also acts as a test for the
@@ -24,7 +25,7 @@
func TestLsCommand(t *testing.T) {
ctx, shutdown := test.V23Init()
defer shutdown()
- tapes := newTapeMap()
+ tapes := servicetest.NewTapeMap()
server, err := xrpc.NewDispatchingServer(ctx, "", newDispatcher(t, tapes))
if err != nil {
t.Fatalf("NewServer failed: %v", err)
@@ -32,7 +33,7 @@
cmd := cmd_device.CmdRoot
endpoint := server.Status().Endpoints[0]
appName := naming.JoinAddressName(endpoint.String(), "app")
- rootTape := tapes.forSuffix("")
+ rootTape := tapes.ForSuffix("")
cannedGlobResponses := [][]string{
[]string{"app/3", "app/4", "app/6", "app/5"},
[]string{"app/2", "app/1"},
@@ -134,14 +135,14 @@
} {
var stdout, stderr bytes.Buffer
env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
- tapes.rewind()
+ tapes.Rewind()
var rootTapeResponses []interface{}
for _, r := range c.globResponses {
rootTapeResponses = append(rootTapeResponses, GlobResponse{results: r})
}
rootTape.SetResponses(rootTapeResponses...)
for n, r := range c.statusResponses {
- tapes.forSuffix(n).SetResponses(r...)
+ tapes.ForSuffix(n).SetResponses(r...)
}
args := append([]string{"ls"}, c.lsFlags...)
for _, p := range c.globPatterns {
diff --git a/services/device/device/mock_test.go b/services/device/device/mock_test.go
deleted file mode 100644
index 7925dc4..0000000
--- a/services/device/device/mock_test.go
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright 2015 The Vanadium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main_test
-
-import (
- "fmt"
- "reflect"
- "sort"
- "sync"
- "testing"
-)
-
-type tape struct {
- sync.Mutex
- stimuli []interface{}
- responses []interface{}
-}
-
-func (t *tape) Record(call interface{}) interface{} {
- t.Lock()
- defer t.Unlock()
- t.stimuli = append(t.stimuli, call)
-
- if len(t.responses) < 1 {
- // Returning an error at this point will likely cause the mock
- // device manager to panic trying to cast the response to what
- // it expects. Panic'ing here at least makes the issue more
- // apparent.
- // TODO(caprita): Don't panic.
- panic(fmt.Errorf("Record(%#v) had no response", call))
- }
- resp := t.responses[0]
- t.responses = t.responses[1:]
- return resp
-}
-
-func (t *tape) SetResponses(responses ...interface{}) {
- t.Lock()
- defer t.Unlock()
- t.responses = make([]interface{}, len(responses))
- copy(t.responses, responses)
-}
-
-func (t *tape) Rewind() {
- t.Lock()
- defer t.Unlock()
- t.stimuli = make([]interface{}, 0)
- t.responses = make([]interface{}, 0)
-}
-
-func (t *tape) Play() []interface{} {
- t.Lock()
- defer t.Unlock()
- resp := make([]interface{}, len(t.stimuli))
- copy(resp, t.stimuli)
- return resp
-}
-
-func newTape() *tape {
- t := new(tape)
- t.Rewind()
- return t
-}
-
-type tapeMap struct {
- sync.Mutex
- tapes map[string]*tape
-}
-
-func newTapeMap() *tapeMap {
- tm := &tapeMap{
- tapes: make(map[string]*tape),
- }
- return tm
-}
-
-func (tm *tapeMap) forSuffix(s string) *tape {
- tm.Lock()
- defer tm.Unlock()
- t, ok := tm.tapes[s]
- if !ok {
- t = new(tape)
- tm.tapes[s] = t
- }
- return t
-}
-
-func (tm *tapeMap) rewind() {
- tm.Lock()
- defer tm.Unlock()
- for _, t := range tm.tapes {
- t.Rewind()
- }
-}
-
-func TestOneTape(t *testing.T) {
- tm := newTapeMap()
- tm.forSuffix("mytape").SetResponses("b", "c")
- if want, got := "b", tm.forSuffix("mytape").Record("bar"); want != got {
- t.Errorf("Expected %v, got %v", want, got)
- }
- if want, got := "c", tm.forSuffix("mytape").Record("baz"); want != got {
- t.Errorf("Expected %v, got %v", want, got)
- }
- if want, got := []interface{}{"bar", "baz"}, tm.forSuffix("mytape").Play(); !reflect.DeepEqual(want, got) {
- t.Errorf("Expected %v, got %v", want, got)
- }
- tm.forSuffix("mytape").Rewind()
- if want, got := []interface{}{}, tm.forSuffix("mytape").Play(); !reflect.DeepEqual(want, got) {
- t.Errorf("Expected %v, got %v", want, got)
- }
-}
-
-func TestManyTapes(t *testing.T) {
- tm := newTapeMap()
- tapes := []string{"duct tape", "cassette tape", "watergate tape", "tape worm"}
- for _, tp := range tapes {
- tm.forSuffix(tp).SetResponses(tp + "resp")
- }
- for _, tp := range tapes {
- if want, got := tp+"resp", tm.forSuffix(tp).Record(tp+"stimulus"); want != got {
- t.Errorf("Expected %v, got %v", want, got)
- }
- }
- for _, tp := range tapes {
- if want, got := []interface{}{tp + "stimulus"}, tm.forSuffix(tp).Play(); !reflect.DeepEqual(want, got) {
- t.Errorf("Expected %v, got %v", want, got)
- }
- }
-}
-
-func TestTapeParallelism(t *testing.T) {
- tm := newTapeMap()
- var resp []interface{}
- const N = 100
- for i := 0; i < N; i++ {
- resp = append(resp, fmt.Sprintf("resp%010d", i))
- }
- tm.forSuffix("mytape").SetResponses(resp...)
- results := make(chan string, N)
- for i := 0; i < N; i++ {
- go func(index int) {
- results <- tm.forSuffix("mytape").Record(fmt.Sprintf("stimulus%010d", index)).(string)
- }(i)
- }
- var res []string
- for i := 0; i < N; i++ {
- r := <-results
- res = append(res, r)
- }
- sort.Strings(res)
- var expectedRes []string
- for i := 0; i < N; i++ {
- expectedRes = append(expectedRes, fmt.Sprintf("resp%010d", i))
- }
- if want, got := expectedRes, res; !reflect.DeepEqual(want, got) {
- t.Errorf("Expected %v, got %v", want, got)
- }
- var expectedStimuli []string
- for i := 0; i < N; i++ {
- expectedStimuli = append(expectedStimuli, fmt.Sprintf("stimulus%010d", i))
- }
- var gotStimuli []string
- for _, s := range tm.forSuffix("mytape").Play() {
- gotStimuli = append(gotStimuli, s.(string))
- }
- sort.Strings(gotStimuli)
- if want, got := expectedStimuli, gotStimuli; !reflect.DeepEqual(want, got) {
- t.Errorf("Expected %v, got %v", want, got)
- }
-}
diff --git a/services/device/device/status_test.go b/services/device/device/status_test.go
index 6ea4bf5..81a1410 100644
--- a/services/device/device/status_test.go
+++ b/services/device/device/status_test.go
@@ -19,12 +19,13 @@
"v.io/x/ref/test"
cmd_device "v.io/x/ref/services/device/device"
+ "v.io/x/ref/services/internal/servicetest"
)
func TestStatusCommand(t *testing.T) {
ctx, shutdown := test.V23Init()
defer shutdown()
- tapes := newTapeMap()
+ tapes := servicetest.NewTapeMap()
server, err := xrpc.NewDispatchingServer(ctx, "", newDispatcher(t, tapes))
if err != nil {
t.Fatalf("NewServer failed: %v", err)
@@ -35,7 +36,7 @@
globName := naming.JoinAddressName(addr, "glob")
appName := naming.JoinAddressName(addr, "app")
- rootTape, appTape := tapes.forSuffix(""), tapes.forSuffix("app")
+ rootTape, appTape := tapes.ForSuffix(""), tapes.ForSuffix("app")
for _, c := range []struct {
tapeResponse device.Status
expected string
@@ -55,7 +56,7 @@
} {
var stdout, stderr bytes.Buffer
env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
- tapes.rewind()
+ tapes.Rewind()
rootTape.SetResponses(GlobResponse{results: []string{"app"}})
appTape.SetResponses(c.tapeResponse)
if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"status", globName}); err != nil {
diff --git a/services/device/device/update_test.go b/services/device/device/update_test.go
index f0f2720..d39981b 100644
--- a/services/device/device/update_test.go
+++ b/services/device/device/update_test.go
@@ -23,6 +23,7 @@
"v.io/x/ref/test"
cmd_device "v.io/x/ref/services/device/device"
+ "v.io/x/ref/services/internal/servicetest"
)
func capitalize(s string) string {
@@ -37,7 +38,7 @@
func TestUpdateAndRevertCommands(t *testing.T) {
ctx, shutdown := test.V23Init()
defer shutdown()
- tapes := newTapeMap()
+ tapes := servicetest.NewTapeMap()
server, err := xrpc.NewDispatchingServer(ctx, "", newDispatcher(t, tapes))
if err != nil {
t.Fatalf("NewServer failed: %v", err)
@@ -45,7 +46,7 @@
addr := server.Status().Endpoints[0].String()
root := cmd_device.CmdRoot
appName := naming.JoinAddressName(addr, "app")
- rootTape := tapes.forSuffix("")
+ rootTape := tapes.ForSuffix("")
globName := naming.JoinAddressName(addr, "glob")
// TODO(caprita): Move joinLines to a common place.
joinLines := func(args ...string) string {
@@ -118,10 +119,10 @@
} {
var stdout, stderr bytes.Buffer
env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
- tapes.rewind()
+ tapes.Rewind()
rootTape.SetResponses(GlobResponse{results: c.globResponses})
for n, r := range c.statusResponses {
- tapes.forSuffix(n).SetResponses(r...)
+ tapes.ForSuffix(n).SetResponses(r...)
}
args := []string{cmd, globName}
if err := v23cmd.ParseAndRunForTest(root, ctx, env, args); err != nil {
@@ -141,7 +142,7 @@
t.Errorf("Unexpected stderr output from %s.\nGot:\n%v\nExpected:\n%v", cmd, got, expected)
}
for n, m := range c.expectedStimuli {
- if want, got := m, tapes.forSuffix(n).Play(); !reflect.DeepEqual(want, got) {
+ if want, got := m, tapes.ForSuffix(n).Play(); !reflect.DeepEqual(want, got) {
t.Errorf("Unexpected stimuli for %v. Want: %v, got %v.", n, want, got)
}
}
diff --git a/services/device/device/util_test.go b/services/device/device/util_test.go
index 7ee71bb..9b4bc6c 100644
--- a/services/device/device/util_test.go
+++ b/services/device/device/util_test.go
@@ -19,6 +19,7 @@
"v.io/x/ref/test"
cmd_device "v.io/x/ref/services/device/device"
+ "v.io/x/ref/services/internal/servicetest"
)
//go:generate v23 test generate
@@ -58,7 +59,7 @@
ctx, shutdown := test.V23Init()
defer shutdown()
- tapes := newTapeMap()
+ tapes := servicetest.NewTapeMap()
server, err := xrpc.NewDispatchingServer(ctx, "", newDispatcher(t, tapes))
if err != nil {
t.Fatalf("NewServer failed: %v", err)
@@ -80,7 +81,7 @@
}
stdout.Reset()
stderr.Reset()
- appTape := tapes.forSuffix("appname")
+ appTape := tapes.ForSuffix("appname")
appTape.Rewind()
if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{lower, "nope", "nope"}); err == nil {
diff --git a/services/device/device/v23_internal_test.go b/services/device/device/v23_test.go
similarity index 81%
rename from services/device/device/v23_internal_test.go
rename to services/device/device/v23_test.go
index ae59080..b307e06 100644
--- a/services/device/device/v23_internal_test.go
+++ b/services/device/device/v23_test.go
@@ -5,16 +5,18 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
-package main
+package main_test
import (
"os"
"testing"
"v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
)
func TestMain(m *testing.M) {
test.Init()
+ modules.DispatchAndExitIfChild()
os.Exit(m.Run())
}
diff --git a/services/internal/servicetest/doc.go b/services/internal/servicetest/doc.go
new file mode 100644
index 0000000..28a6564
--- /dev/null
+++ b/services/internal/servicetest/doc.go
@@ -0,0 +1,7 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package servicetest provides functionality to help write tests
+// for the Vanadium services.
+package servicetest
diff --git a/services/internal/servicetest/mock.go b/services/internal/servicetest/mock.go
new file mode 100644
index 0000000..5419382
--- /dev/null
+++ b/services/internal/servicetest/mock.go
@@ -0,0 +1,110 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package servicetest
+
+import (
+ "fmt"
+ "sync"
+)
+
+// Tape holds a record of function call stimuli and each function call's
+// response. Use Tape to help build a mock framework by first creating a
+// new Tape, then SetResponses to define the mock responses and then
+// Record each function invocation. Play returns the function invocations
+// for verification in a test.
+type Tape struct {
+ sync.Mutex
+ stimuli []interface{}
+ responses []interface{}
+}
+
+// Record stores a new function invocation in a Tape and returns the
+// response for that function interface.
+func (t *Tape) Record(call interface{}) interface{} {
+ t.Lock()
+ defer t.Unlock()
+ t.stimuli = append(t.stimuli, call)
+
+ if len(t.responses) < 1 {
+ // Returning an error at this point will likely cause the mock
+ // device manager to panic trying to cast the response to what
+ // it expects. Panic'ing here at least makes the issue more
+ // apparent.
+ // TODO(caprita): Don't panic.
+ panic(fmt.Errorf("Record(%#v) had no response", call))
+ }
+ resp := t.responses[0]
+ t.responses = t.responses[1:]
+ return resp
+}
+
+// SetResponses updates the Tape's associated responses.
+func (t *Tape) SetResponses(responses ...interface{}) {
+ t.Lock()
+ defer t.Unlock()
+ t.responses = make([]interface{}, len(responses))
+ copy(t.responses, responses)
+}
+
+// Rewind resets the tape to the beginning so that it could be used again
+// for further tests.
+func (t *Tape) Rewind() {
+ t.Lock()
+ defer t.Unlock()
+ t.stimuli = make([]interface{}, 0)
+ t.responses = make([]interface{}, 0)
+}
+
+// Play returns the function call stimuli recorded to this Tape.
+func (t *Tape) Play() []interface{} {
+ t.Lock()
+ defer t.Unlock()
+ resp := make([]interface{}, len(t.stimuli))
+ copy(resp, t.stimuli)
+ return resp
+}
+
+// NewTape creates a new Tape.
+func NewTape() *Tape {
+ t := new(Tape)
+ t.Rewind()
+ return t
+}
+
+// TapeMap provides multiple tapes for different strings. Use TapeMap to
+// record separate Tapes for each suffix in a service.
+type TapeMap struct {
+ sync.Mutex
+ tapes map[string]*Tape
+}
+
+// NewTapeMap creates a new empty TapeMap.
+func NewTapeMap() *TapeMap {
+ tm := &TapeMap{
+ tapes: make(map[string]*Tape),
+ }
+ return tm
+}
+
+// ForSuffix returns the Tape for suffix s.
+func (tm *TapeMap) ForSuffix(s string) *Tape {
+ tm.Lock()
+ defer tm.Unlock()
+ t, ok := tm.tapes[s]
+ if !ok {
+ t = new(Tape)
+ tm.tapes[s] = t
+ }
+ return t
+}
+
+// Rewind rewinds all of the Tapes in the TapeMap.
+func (tm *TapeMap) Rewind() {
+ tm.Lock()
+ defer tm.Unlock()
+ for _, t := range tm.tapes {
+ t.Rewind()
+ }
+}
diff --git a/services/internal/servicetest/mock_test.go b/services/internal/servicetest/mock_test.go
new file mode 100644
index 0000000..dc9d4c2
--- /dev/null
+++ b/services/internal/servicetest/mock_test.go
@@ -0,0 +1,89 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package servicetest
+
+import (
+ "fmt"
+ "reflect"
+ "sort"
+ "testing"
+)
+
+func TestOneTape(t *testing.T) {
+ tm := NewTapeMap()
+ tm.ForSuffix("mytape").SetResponses("b", "c")
+ if want, got := "b", tm.ForSuffix("mytape").Record("bar"); want != got {
+ t.Errorf("Expected %v, got %v", want, got)
+ }
+ if want, got := "c", tm.ForSuffix("mytape").Record("baz"); want != got {
+ t.Errorf("Expected %v, got %v", want, got)
+ }
+ if want, got := []interface{}{"bar", "baz"}, tm.ForSuffix("mytape").Play(); !reflect.DeepEqual(want, got) {
+ t.Errorf("Expected %v, got %v", want, got)
+ }
+ tm.ForSuffix("mytape").Rewind()
+ if want, got := []interface{}{}, tm.ForSuffix("mytape").Play(); !reflect.DeepEqual(want, got) {
+ t.Errorf("Expected %v, got %v", want, got)
+ }
+}
+
+func TestManyTapes(t *testing.T) {
+ tm := NewTapeMap()
+ tapes := []string{"duct tape", "cassette tape", "watergate tape", "tape worm"}
+ for _, tp := range tapes {
+ tm.ForSuffix(tp).SetResponses(tp + "resp")
+ }
+ for _, tp := range tapes {
+ if want, got := tp+"resp", tm.ForSuffix(tp).Record(tp+"stimulus"); want != got {
+ t.Errorf("Expected %v, got %v", want, got)
+ }
+ }
+ for _, tp := range tapes {
+ if want, got := []interface{}{tp + "stimulus"}, tm.ForSuffix(tp).Play(); !reflect.DeepEqual(want, got) {
+ t.Errorf("Expected %v, got %v", want, got)
+ }
+ }
+}
+
+func TestTapeParallelism(t *testing.T) {
+ tm := NewTapeMap()
+ var resp []interface{}
+ const N = 100
+ for i := 0; i < N; i++ {
+ resp = append(resp, fmt.Sprintf("resp%010d", i))
+ }
+ tm.ForSuffix("mytape").SetResponses(resp...)
+ results := make(chan string, N)
+ for i := 0; i < N; i++ {
+ go func(index int) {
+ results <- tm.ForSuffix("mytape").Record(fmt.Sprintf("stimulus%010d", index)).(string)
+ }(i)
+ }
+ var res []string
+ for i := 0; i < N; i++ {
+ r := <-results
+ res = append(res, r)
+ }
+ sort.Strings(res)
+ var expectedRes []string
+ for i := 0; i < N; i++ {
+ expectedRes = append(expectedRes, fmt.Sprintf("resp%010d", i))
+ }
+ if want, got := expectedRes, res; !reflect.DeepEqual(want, got) {
+ t.Errorf("Expected %v, got %v", want, got)
+ }
+ var expectedStimuli []string
+ for i := 0; i < N; i++ {
+ expectedStimuli = append(expectedStimuli, fmt.Sprintf("stimulus%010d", i))
+ }
+ var gotStimuli []string
+ for _, s := range tm.ForSuffix("mytape").Play() {
+ gotStimuli = append(gotStimuli, s.(string))
+ }
+ sort.Strings(gotStimuli)
+ if want, got := expectedStimuli, gotStimuli; !reflect.DeepEqual(want, got) {
+ t.Errorf("Expected %v, got %v", want, got)
+ }
+}