Merge branch 'master' into decode3
Change-Id: I5d440b812757a6dc8ae8746538db05b7b17bc0c0
diff --git a/cmd/mounttable/impl_test.go b/cmd/mounttable/impl_test.go
index cc46ed1..5bc59cf 100644
--- a/cmd/mounttable/impl_test.go
+++ b/cmd/mounttable/impl_test.go
@@ -113,7 +113,7 @@
}
func TestMountTableClient(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
server, endpoint, err := startServer(t, ctx)
diff --git a/cmd/principal/bless.go b/cmd/principal/bless.go
index ee0ef1a..ca6c46c 100644
--- a/cmd/principal/bless.go
+++ b/cmd/principal/bless.go
@@ -85,8 +85,13 @@
http.HandleFunc("/macaroon", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
tmplArgs := struct {
- Blessings, ErrShort, ErrLong string
- }{}
+ Blessings string
+ ErrShort string
+ ErrLong string
+ Browser bool
+ }{
+ Browser: browser,
+ }
defer func() {
if len(tmplArgs.ErrShort) > 0 {
w.WriteHeader(http.StatusBadRequest)
@@ -174,7 +179,7 @@
<meta charset="UTF-8">
<!--Excluding any third-party hosted resources like scripts and stylesheets because otherwise we run the risk of leaking the macaroon out of this page (e.g., via the referrer header) -->
<title>Vanadium Identity: Google</title>
-{{if .Blessings}}
+{{if and .Browser .Blessings}}
<!--Attempt to close the window. Though this script does not work on many browser configurations-->
<script type="text/javascript">window.close();</script>
{{end}}
diff --git a/cmd/principal/v23_test.go b/cmd/principal/v23_test.go
index dddc89a..842bc1f 100644
--- a/cmd/principal/v23_test.go
+++ b/cmd/principal/v23_test.go
@@ -4,16 +4,21 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package main_test
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/v23tests"
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+ "v.io/x/ref/test/v23tests"
+)
func TestMain(m *testing.M) {
test.Init()
+ modules.DispatchAndExitIfChild()
cleanup := v23tests.UseSharedBinDir()
r := m.Run()
cleanup()
diff --git a/cmd/servicerunner/main.go b/cmd/servicerunner/main.go
index ba2cda6..d0695fa 100644
--- a/cmd/servicerunner/main.go
+++ b/cmd/servicerunner/main.go
@@ -17,7 +17,6 @@
import (
"encoding/json"
"fmt"
- "io"
"os"
"strings"
"time"
@@ -46,12 +45,8 @@
wsprlib.OverrideCaveatValidation()
cmdServiceRunner.Flags.IntVar(&port, "port", 8124, "Port for wspr to listen on.")
cmdServiceRunner.Flags.StringVar(&identd, "identd", "", "Name of wspr identd server.")
- modules.RegisterChild("rootMT", ``, rootMT)
- modules.RegisterChild(wsprdCommand, modules.Usage(&cmdServiceRunner.Flags), startWSPR)
}
-const wsprdCommand = "wsprd"
-
func main() {
cmdline.HideGlobalFlagsExcept()
cmdline.Main(cmdServiceRunner)
@@ -68,7 +63,7 @@
`,
}
-func rootMT(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var rootMT = modules.Register(func(env *modules.Env, args ...string) error {
ctx, shutdown := v23.Init()
defer shutdown()
@@ -88,13 +83,13 @@
if err := server.ServeDispatcher("", mt); err != nil {
return fmt.Errorf("root failed: %s", err)
}
- fmt.Fprintf(stdout, "PID=%d\n", os.Getpid())
+ fmt.Fprintf(env.Stdout, "PID=%d\n", os.Getpid())
for _, ep := range eps {
- fmt.Fprintf(stdout, "MT_NAME=%s\n", ep.Name())
+ fmt.Fprintf(env.Stdout, "MT_NAME=%s\n", ep.Name())
}
- modules.WaitForEOF(stdin)
+ modules.WaitForEOF(env.Stdin)
return nil
-}
+}, "rootMT")
// updateVars captures the vars from the given Handle's stdout and adds them to
// the given vars map, overwriting existing entries.
@@ -130,7 +125,7 @@
// The dispatch to modules children must occur after the call to cmdline.Main
// (which calls cmdline.Parse), so that servicerunner flags are registered on
// the global flag.CommandLine.
- if modules.IsModulesChildProcess() {
+ if modules.IsChildProcess() {
return modules.Dispatch()
}
@@ -146,7 +141,7 @@
}
defer sh.Cleanup(os.Stderr, os.Stderr)
- h, err := sh.Start("rootMT", nil, "--v23.tcp.protocol=ws", "--v23.tcp.address=127.0.0.1:0")
+ h, err := sh.Start(nil, rootMT, "--v23.tcp.protocol=ws", "--v23.tcp.address=127.0.0.1:0")
if err != nil {
return err
}
@@ -164,7 +159,7 @@
defer proxyShutdown()
vars["PROXY_NAME"] = proxyEndpoint.Name()
- h, err = sh.Start(wsprdCommand, nil, "--v23.tcp.protocol=ws", "--v23.tcp.address=127.0.0.1:0", "--v23.proxy=test/proxy", "--identd=test/identd")
+ h, err = sh.Start(nil, wsprd, "--v23.tcp.protocol=ws", "--v23.tcp.address=127.0.0.1:0", "--v23.proxy=test/proxy", "--identd=test/identd")
if err != nil {
return err
}
@@ -172,7 +167,7 @@
return err
}
- h, err = sh.Start(identitylib.TestIdentitydCommand, nil, "--v23.tcp.protocol=ws", "--v23.tcp.address=127.0.0.1:0", "--v23.proxy=test/proxy", "--http-addr=localhost:0")
+ h, err = sh.Start(nil, identitylib.TestIdentityd, "--v23.tcp.protocol=ws", "--v23.tcp.address=127.0.0.1:0", "--v23.proxy=test/proxy", "--http-addr=localhost:0")
if err != nil {
return err
}
@@ -190,7 +185,7 @@
return nil
}
-func startWSPR(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var wsprd = modules.Register(func(env *modules.Env, args ...string) error {
ctx, shutdown := v23.Init()
defer shutdown()
@@ -203,7 +198,7 @@
proxy.Serve()
}()
- fmt.Fprintf(stdout, "WSPR_ADDR=%s\n", addr)
- modules.WaitForEOF(stdin)
+ fmt.Fprintf(env.Stdout, "WSPR_ADDR=%s\n", addr)
+ modules.WaitForEOF(env.Stdin)
return nil
-}
+}, "wsprd")
diff --git a/cmd/vdl/arith_test.go b/cmd/vdl/arith_test.go
index 4a1e6b5..f5769b6 100644
--- a/cmd/vdl/arith_test.go
+++ b/cmd/vdl/arith_test.go
@@ -108,7 +108,7 @@
}
func TestCalculator(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
server := newServer(ctx)
@@ -281,7 +281,7 @@
}
func TestArith(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
// TODO(bprosnitz) Split this test up -- it is quite long and hard to debug.
diff --git a/cmd/vdl/v23_internal_test.go b/cmd/vdl/v23_internal_test.go
index dcd0029..ae59080 100644
--- a/cmd/vdl/v23_internal_test.go
+++ b/cmd/vdl/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package main
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/cmd/vdl/vdl_test.go b/cmd/vdl/vdl_test.go
index 0607fab..da17bb9 100644
--- a/cmd/vdl/vdl_test.go
+++ b/cmd/vdl/vdl_test.go
@@ -33,7 +33,7 @@
defer os.RemoveAll(outDir)
// TODO(toddw): test the generated java and javascript files too.
outOpt := fmt.Sprintf("--go-out-dir=%s", outDir)
- env := cmdline.NewEnv()
+ env := cmdline.EnvFromOS()
if err := cmdline.ParseAndRun(cmdVDL, env, []string{"generate", "--lang=go", outOpt, testDir}); err != nil {
t.Fatalf("Execute() failed: %v", err)
}
diff --git a/cmd/vom/vom.go b/cmd/vom/vom.go
index 24b1d7a..e14a0bd 100644
--- a/cmd/vom/vom.go
+++ b/cmd/vom/vom.go
@@ -139,8 +139,7 @@
return nil
}
// Handle streaming from stdin.
- // TODO(toddw): Add a flag to configure stdout/stderr dumping.
- dumper := vom.NewDumper(dumpWriter{env.Stdout, env.Stdout})
+ dumper := vom.NewDumper(vom.NewDumpWriter(env.Stdout))
defer dumper.Close()
// Handle simple non-hex cases.
switch flagDataRep {
@@ -250,17 +249,3 @@
}
return r
}
-
-type dumpWriter struct {
- atom, status io.Writer
-}
-
-var _ vom.DumpWriter = dumpWriter{}
-
-func (w dumpWriter) WriteAtom(atom vom.DumpAtom) {
- w.atom.Write([]byte(atom.String() + "\n"))
-}
-
-func (w dumpWriter) WriteStatus(status vom.DumpStatus) {
- w.status.Write([]byte(status.String() + "\n"))
-}
diff --git a/cmd/vrpc/v23_internal_test.go b/cmd/vrpc/v23_internal_test.go
index dcd0029..ae59080 100644
--- a/cmd/vrpc/v23_internal_test.go
+++ b/cmd/vrpc/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package main
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/cmd/vrpc/vrpc_test.go b/cmd/vrpc/vrpc_test.go
index 4ff920f..5fc6067 100644
--- a/cmd/vrpc/vrpc_test.go
+++ b/cmd/vrpc/vrpc_test.go
@@ -117,7 +117,7 @@
}
func initTest(t *testing.T) (ctx *context.T, name string, shutdown v23.Shutdown) {
- ctx, shutdown = test.InitForTest()
+ ctx, shutdown = test.V23Init()
rpcServer, err := v23.NewServer(ctx)
if err != nil {
diff --git a/cmd/vrun/v23_test.go b/cmd/vrun/v23_test.go
index dd6a542..ece399a 100644
--- a/cmd/vrun/v23_test.go
+++ b/cmd/vrun/v23_test.go
@@ -4,16 +4,21 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package main_test
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/v23tests"
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+ "v.io/x/ref/test/v23tests"
+)
func TestMain(m *testing.M) {
test.Init()
+ modules.DispatchAndExitIfChild()
cleanup := v23tests.UseSharedBinDir()
r := m.Run()
cleanup()
diff --git a/examples/rps/rpsbot/impl_test.go b/examples/rps/rpsbot/impl_test.go
index de82e86..ec531e2 100644
--- a/examples/rps/rpsbot/impl_test.go
+++ b/examples/rps/rpsbot/impl_test.go
@@ -29,7 +29,7 @@
//go:generate v23 test generate
-func rootMT(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var rootMT = modules.Register(func(env *modules.Env, args ...string) error {
ctx, shutdown := v23.Init()
defer shutdown()
@@ -49,13 +49,13 @@
if err := server.ServeDispatcher("", mt); err != nil {
return fmt.Errorf("root failed: %s", err)
}
- fmt.Fprintf(stdout, "PID=%d\n", os.Getpid())
+ fmt.Fprintf(env.Stdout, "PID=%d\n", os.Getpid())
for _, ep := range eps {
- fmt.Fprintf(stdout, "MT_NAME=%s\n", ep.Name())
+ fmt.Fprintf(env.Stdout, "MT_NAME=%s\n", ep.Name())
}
- modules.WaitForEOF(stdin)
+ modules.WaitForEOF(env.Stdin)
return nil
-}
+}, "rootMT")
var spec = rpc.ListenSpec{Addrs: rpc.ListenAddrs{{"tcp", "127.0.0.1:0"}}}
@@ -88,7 +88,7 @@
// TestRockPaperScissorsImpl runs one rock-paper-scissors game and verifies
// that all the counters are consistent.
func TestRockPaperScissorsImpl(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
@@ -96,7 +96,7 @@
t.Fatalf("Could not create shell: %v", err)
}
defer sh.Cleanup(os.Stdout, os.Stderr)
- h, err := sh.Start("rootMT", nil, "--v23.tcp.address=127.0.0.1:0")
+ h, err := sh.Start(nil, rootMT, "--v23.tcp.address=127.0.0.1:0")
if err != nil {
if h != nil {
h.Shutdown(nil, os.Stderr)
diff --git a/examples/rps/rpsbot/v23_internal_test.go b/examples/rps/rpsbot/v23_internal_test.go
index e8fff94..a80e0ec 100644
--- a/examples/rps/rpsbot/v23_internal_test.go
+++ b/examples/rps/rpsbot/v23_internal_test.go
@@ -4,27 +4,19 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package main
-import "fmt"
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/modules"
-
-func init() {
- modules.RegisterChild("rootMT", ``, rootMT)
-}
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+)
func TestMain(m *testing.M) {
test.Init()
- if modules.IsModulesChildProcess() {
- if err := modules.Dispatch(); err != nil {
- fmt.Fprintf(os.Stderr, "modules.Dispatch failed: %v\n", err)
- os.Exit(1)
- }
- return
- }
+ modules.DispatchAndExitIfChild()
os.Exit(m.Run())
}
diff --git a/examples/tunnel/tunneld/v23_test.go b/examples/tunnel/tunneld/v23_test.go
index c2a1b48..99c37d9 100644
--- a/examples/tunnel/tunneld/v23_test.go
+++ b/examples/tunnel/tunneld/v23_test.go
@@ -4,16 +4,21 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package main_test
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/v23tests"
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+ "v.io/x/ref/test/v23tests"
+)
func TestMain(m *testing.M) {
test.Init()
+ modules.DispatchAndExitIfChild()
cleanup := v23tests.UseSharedBinDir()
r := m.Run()
cleanup()
diff --git a/lib/apilog/apilog.go b/lib/apilog/apilog.go
index 83c11b0..0ab9f7b 100644
--- a/lib/apilog/apilog.go
+++ b/lib/apilog/apilog.go
@@ -6,12 +6,9 @@
// In particular, logcop will inject calls to these functions as the first
// statement in methods that implement the v23 API. The output can
// be controlled by vlog verbosity or vtrace.
-// The log lines generated have a header that refers to this file
-// and the message includes the file and line # of the caller. This is
-// currently the best we can do given the functionality of the underlying
-// vlog package. It has the advantage the api logging can be selectively
-// enabled/disabled globally using --vmodule=apilog=<level>, but the
-// disadvantage that it can't be controlled at the per file level.
+// --vmodule=apilog=<level> can be used to globally control logging,
+// and --vmodule=module=<level> can also be used to control logging
+// on a per-file basis.
package apilog
import (
@@ -115,7 +112,7 @@
} else {
output = fmt.Sprintf("call[%s %s]", callerLocation, invocationId)
}
- logger.Info(output)
+ logger.InfoDepth(1, output)
// TODO(mattr): annotate vtrace span.
return func(ctx *context.T, v ...interface{}) {
@@ -125,7 +122,7 @@
} else {
output = fmt.Sprintf("return[%s %s]", callerLocation, invocationId)
}
- logger.Info(output)
+ logger.InfoDepth(1, output)
// TODO(mattr): annotate vtrace span.
}
}
@@ -146,11 +143,11 @@
callerLocation := callerLocation()
invocationId := newInvocationIdentifier()
output := fmt.Sprintf("call[%s %s]: %s", callerLocation, invocationId, fmt.Sprintf(format, v...))
- logger.Info(output)
+ logger.InfoDepth(1, output)
// TODO(mattr): annotate vtrace span.
return func(ctx *context.T, format string, v ...interface{}) {
output := fmt.Sprintf("return[%s %s]: %v", callerLocation, invocationId, fmt.Sprintf(format, derefSlice(v)...))
- logger.Info(output)
+ logger.InfoDepth(1, output)
// TODO(mattr): annotate vtrace span.
}
}
diff --git a/lib/apilog/apilog_test.go b/lib/apilog/apilog_test.go
index d085efc..2157fae 100644
--- a/lib/apilog/apilog_test.go
+++ b/lib/apilog/apilog_test.go
@@ -68,7 +68,7 @@
if want, got := 2, len(contents); want != got {
t.Errorf("Expected %d info lines, got %d instead", want, got)
}
- logCallLineRE := regexp.MustCompile(`\S+ \S+ \S+ ([^:]*):.*(call|return)\[(\S*) (\S*)`)
+ logCallLineRE := regexp.MustCompile(`\S+ \S+\s+\S+ ([^:]*):.*(call|return)\[(\S*) (\S*)`)
for _, line := range contents {
match := logCallLineRE.FindStringSubmatch(line)
if len(match) != 5 {
@@ -76,7 +76,7 @@
continue
}
fileName, callType, location, funcName := match[1], match[2], match[3], match[4]
- if fileName != "apilog.go" {
+ if fileName != "apilog_test.go" {
t.Errorf("unexpected file name: %s", fileName)
continue
}
diff --git a/lib/security/securityflag/flag.go b/lib/security/securityflag/flag.go
index 0c7b3fc..dea39a0 100644
--- a/lib/security/securityflag/flag.go
+++ b/lib/security/securityflag/flag.go
@@ -45,9 +45,9 @@
if literal == "" {
a, err = access.PermissionsAuthorizerFromFile(fname, access.TypicalTagType())
} else {
- var tam access.Permissions
- if tam, err = access.ReadPermissions(bytes.NewBufferString(literal)); err == nil {
- a, err = access.PermissionsAuthorizer(tam, access.TypicalTagType())
+ var perms access.Permissions
+ if perms, err = access.ReadPermissions(bytes.NewBufferString(literal)); err == nil {
+ a, err = access.PermissionsAuthorizer(perms, access.TypicalTagType())
}
}
if err != nil {
diff --git a/lib/security/securityflag/flag_test.go b/lib/security/securityflag/flag_test.go
index 29cff52..04ca9ff 100644
--- a/lib/security/securityflag/flag_test.go
+++ b/lib/security/securityflag/flag_test.go
@@ -8,7 +8,6 @@
"bytes"
"flag"
"fmt"
- "io"
"io/ioutil"
"os"
"reflect"
@@ -45,21 +44,21 @@
return a
}
-func tamFromFlag(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var permFromFlag = modules.Register(func(env *modules.Env, args ...string) error {
nfargs := flag.CommandLine.Args()
tam, err := PermissionsFromFlag()
if err != nil {
- fmt.Fprintf(stdout, "PermissionsFromFlag() failed: %v", err)
+ fmt.Fprintf(env.Stdout, "PermissionsFromFlag() failed: %v", err)
return nil
}
got := auth(access.PermissionsAuthorizer(tam, access.TypicalTagType()))
want := expectedAuthorizer[nfargs[0]]
if !reflect.DeepEqual(got, want) {
- fmt.Fprintf(stdout, "args %#v\n", args)
- fmt.Fprintf(stdout, "AuthorizerFromFlags() got Authorizer: %v, want: %v", got, want)
+ fmt.Fprintf(env.Stdout, "args %#v\n", args)
+ fmt.Fprintf(env.Stdout, "AuthorizerFromFlags() got Authorizer: %v, want: %v", got, want)
}
return nil
-}
+}, "permFromFlag")
func writePermissionsToFile(perms access.Permissions) (string, error) {
f, err := ioutil.TempFile("", "permissions")
@@ -88,30 +87,29 @@
defer os.Remove(filename)
testdata := []struct {
- cmd string
+ prog modules.Program
flags []string
auth string
}{
{
- cmd: "tamFromFlag",
+ prog: permFromFlag,
flags: []string{"--v23.permissions.file", "runtime:" + filename},
auth: "perms2",
},
{
- cmd: "tamFromFlag",
+ prog: permFromFlag,
flags: []string{"--v23.permissions.literal", "{}"},
auth: "empty",
},
{
- cmd: "tamFromFlag",
+ prog: permFromFlag,
flags: []string{"--v23.permissions.literal", `{"Read": {"In":["v23/alice/$", "v23/bob"]}, "Write": {"In":["v23/alice/$"]}}`},
auth: "perms2",
},
}
-
for _, td := range testdata {
fp := append(td.flags, td.auth)
- h, err := sh.Start(td.cmd, nil, fp...)
+ h, err := sh.Start(nil, td.prog, fp...)
if err != nil {
t.Errorf("unexpected error: %s", err)
}
diff --git a/lib/security/securityflag/v23_internal_test.go b/lib/security/securityflag/v23_internal_test.go
index d4e2d18..38cf5e0 100644
--- a/lib/security/securityflag/v23_internal_test.go
+++ b/lib/security/securityflag/v23_internal_test.go
@@ -4,27 +4,19 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package securityflag
-import "fmt"
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/modules"
-
-func init() {
- modules.RegisterChild("tamFromFlag", ``, tamFromFlag)
-}
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+)
func TestMain(m *testing.M) {
test.Init()
- if modules.IsModulesChildProcess() {
- if err := modules.Dispatch(); err != nil {
- fmt.Fprintf(os.Stderr, "modules.Dispatch failed: %v\n", err)
- os.Exit(1)
- }
- return
- }
+ modules.DispatchAndExitIfChild()
os.Exit(m.Run())
}
diff --git a/lib/signals/signals_test.go b/lib/signals/signals_test.go
index fc2f40e..63b0097 100644
--- a/lib/signals/signals_test.go
+++ b/lib/signals/signals_test.go
@@ -45,7 +45,7 @@
}
func program(stdin io.Reader, stdout io.Writer, signals ...os.Signal) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
closeStopLoop := make(chan struct{})
go stopLoop(v23.GetAppCycle(ctx).Stop, stdin, closeStopLoop)
wait := ShutdownOnSignals(ctx, signals...)
@@ -55,32 +55,32 @@
<-closeStopLoop
}
-func handleDefaults(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- program(stdin, stdout)
+var handleDefaults = modules.Register(func(env *modules.Env, args ...string) error {
+ program(env.Stdin, env.Stdout)
return nil
-}
+}, "handleDefaults")
-func handleCustom(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- program(stdin, stdout, syscall.SIGABRT)
+var handleCustom = modules.Register(func(env *modules.Env, args ...string) error {
+ program(env.Stdin, env.Stdout, syscall.SIGABRT)
return nil
-}
+}, "handleCustom")
-func handleCustomWithStop(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- program(stdin, stdout, STOP, syscall.SIGABRT, syscall.SIGHUP)
+var handleCustomWithStop = modules.Register(func(env *modules.Env, args ...string) error {
+ program(env.Stdin, env.Stdout, STOP, syscall.SIGABRT, syscall.SIGHUP)
return nil
-}
+}, "handleCustomWithStop")
-func handleDefaultsIgnoreChan(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- ctx, shutdown := test.InitForTest()
+var handleDefaultsIgnoreChan = modules.Register(func(env *modules.Env, args ...string) error {
+ ctx, shutdown := test.V23Init()
defer shutdown()
closeStopLoop := make(chan struct{})
- go stopLoop(v23.GetAppCycle(ctx).Stop, stdin, closeStopLoop)
+ go stopLoop(v23.GetAppCycle(ctx).Stop, env.Stdin, closeStopLoop)
ShutdownOnSignals(ctx)
- fmt.Fprintf(stdout, "ready\n")
+ fmt.Fprintf(env.Stdout, "ready\n")
<-closeStopLoop
return nil
-}
+}, "handleDefaultsIgnoreChan")
func isSignalInSet(sig os.Signal, set []os.Signal) bool {
for _, s := range set {
@@ -103,12 +103,12 @@
}
}
-func newShell(t *testing.T, ctx *context.T, command string) (*modules.Shell, modules.Handle) {
+func newShell(t *testing.T, ctx *context.T, prog modules.Program) (*modules.Shell, modules.Handle) {
sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
- handle, err := sh.Start(command, nil)
+ handle, err := sh.Start(nil, prog)
if err != nil {
sh.Cleanup(os.Stderr, os.Stderr)
t.Fatalf("unexpected error: %s", err)
@@ -120,10 +120,10 @@
// TestCleanShutdownSignal verifies that sending a signal to a child that
// handles it by default causes the child to shut down cleanly.
func TestCleanShutdownSignal(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
- sh, h := newShell(t, ctx, "handleDefaults")
+ sh, h := newShell(t, ctx, handleDefaults)
defer sh.Cleanup(os.Stderr, os.Stderr)
h.Expect("ready")
checkSignalIsDefault(t, syscall.SIGINT)
@@ -136,10 +136,10 @@
// TestCleanShutdownStop verifies that sending a stop comamnd to a child that
// handles stop commands by default causes the child to shut down cleanly.
func TestCleanShutdownStop(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
- sh, h := newShell(t, ctx, "handleDefaults")
+ sh, h := newShell(t, ctx, handleDefaults)
defer sh.Cleanup(os.Stderr, os.Stderr)
h.Expect("ready")
fmt.Fprintf(h.Stdin(), "stop\n")
@@ -153,10 +153,10 @@
// that handles stop command as part of a custom set of signals handled, causes
// the child to shut down cleanly.
func TestCleanShutdownStopCustom(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
- sh, h := newShell(t, ctx, "handleCustomWithStop")
+ sh, h := newShell(t, ctx, handleCustomWithStop)
defer sh.Cleanup(os.Stderr, os.Stderr)
h.Expect("ready")
fmt.Fprintf(h.Stdin(), "stop\n")
@@ -177,10 +177,10 @@
// TestStopNoHandler verifies that sending a stop command to a child that does
// not handle stop commands causes the child to exit immediately.
func TestStopNoHandler(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
- sh, h := newShell(t, ctx, "handleCustom")
+ sh, h := newShell(t, ctx, handleCustom)
defer sh.Cleanup(os.Stderr, os.Stderr)
h.Expect("ready")
fmt.Fprintf(h.Stdin(), "stop\n")
@@ -191,10 +191,10 @@
// that handles these signals by default causes the child to exit immediately
// upon receiving the second signal.
func TestDoubleSignal(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
- sh, h := newShell(t, ctx, "handleDefaults")
+ sh, h := newShell(t, ctx, handleDefaults)
defer sh.Cleanup(os.Stderr, os.Stderr)
h.Expect("ready")
checkSignalIsDefault(t, syscall.SIGTERM)
@@ -209,10 +209,10 @@
// to a child that handles these by default causes the child to exit immediately
// upon receiving the stop command.
func TestSignalAndStop(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
- sh, h := newShell(t, ctx, "handleDefaults")
+ sh, h := newShell(t, ctx, handleDefaults)
defer sh.Cleanup(os.Stderr, os.Stderr)
h.Expect("ready")
checkSignalIsDefault(t, syscall.SIGTERM)
@@ -226,10 +226,10 @@
// that handles stop commands by default causes the child to exit immediately
// upon receiving the second stop command.
func TestDoubleStop(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
- sh, h := newShell(t, ctx, "handleDefaults")
+ sh, h := newShell(t, ctx, handleDefaults)
defer sh.Cleanup(os.Stderr, os.Stderr)
h.Expect("ready")
fmt.Fprintf(h.Stdin(), "stop\n")
@@ -241,10 +241,10 @@
// TestSendUnhandledSignal verifies that sending a signal that the child does
// not handle causes the child to exit as per the signal being sent.
func TestSendUnhandledSignal(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
- sh, h := newShell(t, ctx, "handleDefaults")
+ sh, h := newShell(t, ctx, handleDefaults)
defer sh.Cleanup(os.Stderr, os.Stderr)
h.Expect("ready")
checkSignalIsNotDefault(t, syscall.SIGABRT)
@@ -257,10 +257,10 @@
// process to exit (ensures that there is no dependency in ShutdownOnSignals
// on having a goroutine read from the returned channel).
func TestDoubleSignalIgnoreChan(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
- sh, h := newShell(t, ctx, "handleDefaultsIgnoreChan")
+ sh, h := newShell(t, ctx, handleDefaultsIgnoreChan)
defer sh.Cleanup(os.Stderr, os.Stderr)
h.Expect("ready")
// Even if we ignore the channel that ShutdownOnSignals returns,
@@ -275,10 +275,10 @@
// TestHandlerCustomSignal verifies that sending a non-default signal to a
// server that listens for that signal causes the server to shut down cleanly.
func TestHandlerCustomSignal(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
- sh, h := newShell(t, ctx, "handleCustom")
+ sh, h := newShell(t, ctx, handleCustom)
defer sh.Cleanup(os.Stderr, os.Stderr)
h.Expect("ready")
checkSignalIsNotDefault(t, syscall.SIGABRT)
@@ -292,12 +292,12 @@
// to a server that listens for that signal causes the server to shut down
// cleanly, even when a STOP signal is also among the handled signals.
func TestHandlerCustomSignalWithStop(t *testing.T) {
- rootCtx, shutdown := test.InitForTest()
+ rootCtx, shutdown := test.V23Init()
defer shutdown()
for _, signal := range []syscall.Signal{syscall.SIGABRT, syscall.SIGHUP} {
ctx, _ := vtrace.WithNewTrace(rootCtx)
- sh, h := newShell(t, ctx, "handleCustomWithStop")
+ sh, h := newShell(t, ctx, handleCustomWithStop)
h.Expect("ready")
checkSignalIsNotDefault(t, signal)
syscall.Kill(h.Pid(), signal)
@@ -353,7 +353,7 @@
// TestCleanRemoteShutdown verifies that remote shutdown works correctly.
func TestCleanRemoteShutdown(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
@@ -367,7 +367,7 @@
sh.SetConfigKey(mgmt.ParentNameConfigKey, configServiceName)
sh.SetConfigKey(mgmt.ProtocolConfigKey, "tcp")
sh.SetConfigKey(mgmt.AddressConfigKey, "127.0.0.1:0")
- h, err := sh.Start("handleDefaults", nil)
+ h, err := sh.Start(nil, handleDefaults)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
diff --git a/lib/signals/v23_internal_test.go b/lib/signals/v23_internal_test.go
index 4d2767f..e047d2e 100644
--- a/lib/signals/v23_internal_test.go
+++ b/lib/signals/v23_internal_test.go
@@ -4,30 +4,19 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package signals
-import "fmt"
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/modules"
-
-func init() {
- modules.RegisterChild("handleDefaults", ``, handleDefaults)
- modules.RegisterChild("handleCustom", ``, handleCustom)
- modules.RegisterChild("handleCustomWithStop", ``, handleCustomWithStop)
- modules.RegisterChild("handleDefaultsIgnoreChan", ``, handleDefaultsIgnoreChan)
-}
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+)
func TestMain(m *testing.M) {
test.Init()
- if modules.IsModulesChildProcess() {
- if err := modules.Dispatch(); err != nil {
- fmt.Fprintf(os.Stderr, "modules.Dispatch failed: %v\n", err)
- os.Exit(1)
- }
- return
- }
+ modules.DispatchAndExitIfChild()
os.Exit(m.Run())
}
diff --git a/runtime/factories/fake/naming.go b/runtime/factories/fake/naming.go
index 416825d..289ce46 100644
--- a/runtime/factories/fake/naming.go
+++ b/runtime/factories/fake/naming.go
@@ -8,14 +8,18 @@
"v.io/v23/context"
"v.io/v23/namespace"
"v.io/v23/naming"
+ "v.io/x/ref/lib/apilog"
)
func (r *Runtime) NewEndpoint(ep string) (naming.Endpoint, error) {
+ defer apilog.LogCallf(nil, "ep=%.10s...", ep)(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
panic("unimplemented")
}
func (r *Runtime) WithNewNamespace(ctx *context.T, roots ...string) (*context.T, namespace.T, error) {
+ defer apilog.LogCallf(ctx, "roots...=%v", roots)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
panic("unimplemented")
}
func (r *Runtime) GetNamespace(ctx *context.T) namespace.T {
+ defer apilog.LogCall(ctx)(ctx) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
panic("unimplemented")
}
diff --git a/runtime/factories/fake/rpc.go b/runtime/factories/fake/rpc.go
index d0c43ee..d80e123 100644
--- a/runtime/factories/fake/rpc.go
+++ b/runtime/factories/fake/rpc.go
@@ -7,6 +7,7 @@
import (
"v.io/v23/context"
"v.io/v23/rpc"
+ "v.io/x/ref/lib/apilog"
)
// SetClient can be used to inject a mock client implementation into the context.
@@ -14,20 +15,25 @@
return context.WithValue(ctx, clientKey, client)
}
func (r *Runtime) WithNewClient(ctx *context.T, opts ...rpc.ClientOpt) (*context.T, rpc.Client, error) {
+ defer apilog.LogCallf(ctx, "opts...=%v", opts)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
panic("unimplemented")
}
func (r *Runtime) GetClient(ctx *context.T) rpc.Client {
+ defer apilog.LogCall(ctx)(ctx) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
c, _ := ctx.Value(clientKey).(rpc.Client)
return c
}
func (r *Runtime) NewServer(ctx *context.T, opts ...rpc.ServerOpt) (rpc.Server, error) {
+ defer apilog.LogCallf(ctx, "opts...=%v", opts)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
panic("unimplemented")
}
func (r *Runtime) WithNewStreamManager(ctx *context.T) (*context.T, error) {
+ defer apilog.LogCall(ctx)(ctx) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
panic("unimplemented")
}
func (r *Runtime) GetListenSpec(ctx *context.T) rpc.ListenSpec {
+ defer apilog.LogCall(ctx)(ctx) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
return rpc.ListenSpec{}
}
diff --git a/runtime/factories/fake/runtime.go b/runtime/factories/fake/runtime.go
index 9a17fa7..2812aaf 100644
--- a/runtime/factories/fake/runtime.go
+++ b/runtime/factories/fake/runtime.go
@@ -9,6 +9,7 @@
"v.io/v23/context"
"v.io/v23/rpc"
"v.io/v23/security"
+ "v.io/x/ref/lib/apilog"
vsecurity "v.io/x/ref/lib/security"
)
@@ -33,23 +34,28 @@
}
func (r *Runtime) Init(ctx *context.T) error {
+ defer apilog.LogCall(ctx)(ctx) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
return nil
}
func (r *Runtime) WithPrincipal(ctx *context.T, principal security.Principal) (*context.T, error) {
+ defer apilog.LogCallf(ctx, "principal=")(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
return context.WithValue(ctx, principalKey, principal), nil
}
func (r *Runtime) GetPrincipal(ctx *context.T) security.Principal {
+ defer apilog.LogCall(ctx)(ctx) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
p, _ := ctx.Value(principalKey).(security.Principal)
return p
}
func (r *Runtime) GetAppCycle(ctx *context.T) v23.AppCycle {
+ defer apilog.LogCall(ctx)(ctx) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
panic("unimplemented")
}
func (r *Runtime) WithBackgroundContext(ctx *context.T) *context.T {
+ defer apilog.LogCall(ctx)(ctx) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
// Note we add an extra context with a nil value here.
// This prevents users from travelling back through the
// chain of background contexts.
@@ -58,6 +64,7 @@
}
func (r *Runtime) GetBackgroundContext(ctx *context.T) *context.T {
+ defer apilog.LogCall(ctx)(ctx) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
bctx, _ := ctx.Value(backgroundKey).(*context.T)
if bctx == nil {
// There should always be a background context. If we don't find
@@ -70,9 +77,11 @@
}
func (*Runtime) WithReservedNameDispatcher(ctx *context.T, d rpc.Dispatcher) *context.T {
+ defer apilog.LogCallf(ctx, "d=")(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
panic("unimplemented")
}
func (*Runtime) GetReservedNameDispatcher(ctx *context.T) rpc.Dispatcher {
+ defer apilog.LogCall(ctx)(ctx) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
panic("unimplmeneted")
}
diff --git a/runtime/internal/lib/appcycle/appcycle.go b/runtime/internal/lib/appcycle/appcycle.go
index 9e9bc49..9356afc 100644
--- a/runtime/internal/lib/appcycle/appcycle.go
+++ b/runtime/internal/lib/appcycle/appcycle.go
@@ -14,6 +14,7 @@
"v.io/v23/rpc"
"v.io/v23/security"
"v.io/x/lib/vlog"
+ "v.io/x/ref/lib/apilog"
public "v.io/v23/services/appcycle"
)
@@ -68,24 +69,24 @@
}
func (m *AppCycle) Stop() {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
m.stop(v23.LocalStop)
}
func (*AppCycle) ForceStop() {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
os.Exit(v23.ForceStopExitCode)
}
func (m *AppCycle) WaitForStop(ch chan<- string) {
- defer vlog.LogCallf("ch=")("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "ch=")(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
m.Lock()
defer m.Unlock()
m.waiters = append(m.waiters, ch)
}
func (m *AppCycle) TrackTask(ch chan<- v23.Task) {
- defer vlog.LogCallf("ch=")("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "ch=")(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
m.Lock()
defer m.Unlock()
if m.shutDown {
@@ -113,7 +114,7 @@
}
func (m *AppCycle) AdvanceGoal(delta int32) {
- defer vlog.LogCallf("delta=%v", delta)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "delta=%v", delta)(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
if delta <= 0 {
return
}
@@ -121,7 +122,7 @@
}
func (m *AppCycle) AdvanceProgress(delta int32) {
- defer vlog.LogCallf("delta=%v", delta)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "delta=%v", delta)(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
if delta <= 0 {
return
}
@@ -129,12 +130,12 @@
}
func (m *AppCycle) Remote() interface{} {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
return public.AppCycleServer(m.disp)
}
func (d *invoker) Stop(ctx *context.T, call public.AppCycleStopServerCall) error {
- defer vlog.LogCallf("ctx=,call=")("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "call=")(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
blessings, _ := security.RemoteBlessingNames(ctx, call.Security())
vlog.Infof("AppCycle Stop request from %v", blessings)
// The size of the channel should be reasonably sized to expect not to
@@ -158,7 +159,7 @@
}
func (d *invoker) ForceStop(*context.T, rpc.ServerCall) error {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
d.ac.ForceStop()
return fmt.Errorf("ForceStop should not reply as the process should be dead")
}
diff --git a/runtime/internal/lib/deque/v23_internal_test.go b/runtime/internal/lib/deque/v23_internal_test.go
index 5091465..e8e5310 100644
--- a/runtime/internal/lib/deque/v23_internal_test.go
+++ b/runtime/internal/lib/deque/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package deque
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/runtime/internal/lib/pcqueue/v23_internal_test.go b/runtime/internal/lib/pcqueue/v23_internal_test.go
index 6475bd5..40cedde 100644
--- a/runtime/internal/lib/pcqueue/v23_internal_test.go
+++ b/runtime/internal/lib/pcqueue/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package pcqueue
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/runtime/internal/lib/publisher/publisher.go b/runtime/internal/lib/publisher/publisher.go
index 6c87030..99ccda0 100644
--- a/runtime/internal/lib/publisher/publisher.go
+++ b/runtime/internal/lib/publisher/publisher.go
@@ -54,29 +54,26 @@
// appropriate channels.
type publisher struct {
cmdchan chan interface{} // value is one of {server,name,debug}Cmd
+ stopchan chan struct{} // closed when no longer accepting commands.
donechan chan struct{} // closed when the publisher is done
}
type addServerCmd struct {
- server string // server to add
- done chan struct{} // closed when the cmd is done
+ server string // server to add
}
type removeServerCmd struct {
- server string // server to remove
- done chan struct{} // closed when the cmd is done
+ server string // server to remove
}
type addNameCmd struct {
- name string // name to add
- mt bool // true if server serves a mount table
- leaf bool // true if server is a leaf
- done chan struct{} // closed when the cmd is done
+ name string // name to add
+ mt bool // true if server serves a mount table
+ leaf bool // true if server is a leaf
}
type removeNameCmd struct {
- name string // name to remove
- done chan struct{} // closed when the cmd is done
+ name string // name to remove
}
type debugCmd chan string // debug string is sent when the cmd is done
@@ -89,6 +86,7 @@
func New(ctx *context.T, ns namespace.T, period time.Duration) Publisher {
p := &publisher{
cmdchan: make(chan interface{}),
+ stopchan: make(chan struct{}),
donechan: make(chan struct{}),
}
go runLoop(ctx, p.cmdchan, p.donechan, ns, period)
@@ -99,37 +97,27 @@
select {
case p.cmdchan <- cmd:
return true
+ case <-p.stopchan:
+ return false
case <-p.donechan:
return false
}
}
func (p *publisher) AddServer(server string) {
- done := make(chan struct{})
- if p.sendCmd(addServerCmd{server, done}) {
- <-done
- }
+ p.sendCmd(addServerCmd{server})
}
func (p *publisher) RemoveServer(server string) {
- done := make(chan struct{})
- if p.sendCmd(removeServerCmd{server, done}) {
- <-done
- }
+ p.sendCmd(removeServerCmd{server})
}
func (p *publisher) AddName(name string, mt bool, leaf bool) {
- done := make(chan struct{})
- if p.sendCmd(addNameCmd{name, mt, leaf, done}) {
- <-done
- }
+ p.sendCmd(addNameCmd{name, mt, leaf})
}
func (p *publisher) RemoveName(name string) {
- done := make(chan struct{})
- if p.sendCmd(removeNameCmd{name, done}) {
- <-done
- }
+ p.sendCmd(removeNameCmd{name})
}
func (p *publisher) Status() rpc.MountState {
@@ -161,6 +149,7 @@
// (including Stop) are no-ops.
func (p *publisher) Stop() {
p.sendCmd(stopCmd{})
+ close(p.stopchan) // stop accepting new commands now.
}
func (p *publisher) WaitForStop() {
@@ -170,7 +159,6 @@
func runLoop(ctx *context.T, cmdchan chan interface{}, donechan chan struct{}, ns namespace.T, period time.Duration) {
vlog.VI(2).Info("rpc pub: start runLoop")
state := newPubState(ctx, ns, period)
-
for {
select {
case cmd := <-cmdchan:
@@ -182,16 +170,12 @@
return
case addServerCmd:
state.addServer(tcmd.server)
- close(tcmd.done)
case removeServerCmd:
state.removeServer(tcmd.server)
- close(tcmd.done)
case addNameCmd:
state.addName(tcmd.name, tcmd.mt, tcmd.leaf)
- close(tcmd.done)
case removeNameCmd:
state.removeName(tcmd.name)
- close(tcmd.done)
case statusCmd:
tcmd <- state.getStatus()
close(tcmd)
diff --git a/runtime/internal/lib/publisher/publisher_test.go b/runtime/internal/lib/publisher/publisher_test.go
index 04d272f..cd69d15 100644
--- a/runtime/internal/lib/publisher/publisher_test.go
+++ b/runtime/internal/lib/publisher/publisher_test.go
@@ -34,41 +34,63 @@
return ctx
}
-func resolve(t *testing.T, ns namespace.T, name string) []string {
- me, err := ns.Resolve(testContext(), name)
- if err != nil {
- t.Fatalf("failed to resolve %q", name)
+func resolveWithRetry(t *testing.T, ns namespace.T, ctx *context.T, name string, expected int) []string {
+ deadline := time.Now().Add(time.Minute)
+ for {
+ me, err := ns.Resolve(ctx, name)
+ if err == nil && len(me.Names()) == expected {
+ return me.Names()
+ }
+ if time.Now().After(deadline) {
+ t.Fatalf("failed to resolve %q", name)
+ } else {
+ continue
+ }
+ time.Sleep(100 * time.Millisecond)
}
- return me.Names()
+}
+
+func verifyMissing(t *testing.T, ns namespace.T, ctx *context.T, name string) {
+ deadline := time.Now().Add(time.Minute)
+ for {
+ if _, err := ns.Resolve(ctx, "foo"); err == nil {
+ if time.Now().After(deadline) {
+ t.Errorf("%q is still mounted", name)
+ }
+ time.Sleep(100 * time.Millisecond)
+ } else {
+ break
+ }
+ }
}
func TestAddAndRemove(t *testing.T) {
+ tctx := testContext()
ns := tnaming.NewSimpleNamespace()
pub := publisher.New(testContext(), ns, time.Second)
pub.AddName("foo", false, false)
pub.AddServer("foo-addr")
- if got, want := resolve(t, ns, "foo"), []string{"/foo-addr"}; !reflect.DeepEqual(got, want) {
+ if got, want := resolveWithRetry(t, ns, tctx, "foo", 1), []string{"/foo-addr"}; !reflect.DeepEqual(got, want) {
t.Errorf("got %q, want %q", got, want)
}
pub.AddServer("bar-addr")
- got, want := resolve(t, ns, "foo"), []string{"/bar-addr", "/foo-addr"}
+ got, want := resolveWithRetry(t, ns, tctx, "foo", 2), []string{"/bar-addr", "/foo-addr"}
sort.Strings(got)
if !reflect.DeepEqual(got, want) {
t.Errorf("got %q, want %q", got, want)
}
pub.AddName("baz", false, false)
- got = resolve(t, ns, "baz")
+ got = resolveWithRetry(t, ns, tctx, "baz", 2)
sort.Strings(got)
if !reflect.DeepEqual(got, want) {
t.Errorf("got %q, want %q", got, want)
}
pub.RemoveName("foo")
- if _, err := ns.Resolve(testContext(), "foo"); err == nil {
- t.Errorf("expected an error")
- }
+ verifyMissing(t, ns, tctx, "foo")
}
func TestStatus(t *testing.T) {
+ tctx := testContext()
ns := tnaming.NewSimpleNamespace()
pub := publisher.New(testContext(), ns, time.Second)
pub.AddName("foo", false, false)
@@ -78,15 +100,15 @@
}
pub.AddServer("foo-addr")
- // Wait for the publisher to asynchronously publish server the
+ // Wait for the publisher to asynchronously publish the
// requisite number of servers.
ch := make(chan error, 1)
waitFor := func(n int) {
- then := time.Now()
+ deadline := time.Now().Add(time.Minute)
for {
status = pub.Status()
if got, want := len(status), n; got != want {
- if time.Now().Sub(then) > time.Minute {
+ if time.Now().After(deadline) {
ch <- fmt.Errorf("got %d, want %d", got, want)
return
}
@@ -105,6 +127,12 @@
pub.AddServer("bar-addr")
pub.AddName("baz", false, false)
+
+ go waitFor(4)
+ if err := <-ch; err != nil {
+ t.Fatalf("%s", err)
+ }
+
status = pub.Status()
names := status.Names()
if got, want := names, []string{"baz", "foo"}; !reflect.DeepEqual(got, want) {
@@ -115,11 +143,9 @@
t.Errorf("got %q, want %q", got, want)
}
pub.RemoveName("foo")
- if _, err := ns.Resolve(testContext(), "foo"); err == nil {
- t.Errorf("expected an error")
- }
- status = pub.Status()
+ verifyMissing(t, ns, tctx, "foo")
+ status = pub.Status()
go waitFor(2)
if err := <-ch; err != nil {
t.Fatalf("%s", err)
diff --git a/runtime/internal/lib/publisher/v23_internal_test.go b/runtime/internal/lib/publisher/v23_internal_test.go
index 399d8d5..569e177 100644
--- a/runtime/internal/lib/publisher/v23_internal_test.go
+++ b/runtime/internal/lib/publisher/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package publisher
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/runtime/internal/lib/sync/v23_internal_test.go b/runtime/internal/lib/sync/v23_internal_test.go
index 008ca9f..16f69e9 100644
--- a/runtime/internal/lib/sync/v23_internal_test.go
+++ b/runtime/internal/lib/sync/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package sync
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/runtime/internal/lib/upcqueue/v23_internal_test.go b/runtime/internal/lib/upcqueue/v23_internal_test.go
index af1b3c8..794f10f 100644
--- a/runtime/internal/lib/upcqueue/v23_internal_test.go
+++ b/runtime/internal/lib/upcqueue/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package upcqueue
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/runtime/internal/lib/websocket/v23_internal_test.go b/runtime/internal/lib/websocket/v23_internal_test.go
index 2051301..a77fac4 100644
--- a/runtime/internal/lib/websocket/v23_internal_test.go
+++ b/runtime/internal/lib/websocket/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package websocket
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/runtime/internal/naming/endpoint.go b/runtime/internal/naming/endpoint.go
index d1b238f..014b179 100644
--- a/runtime/internal/naming/endpoint.go
+++ b/runtime/internal/naming/endpoint.go
@@ -14,7 +14,7 @@
"v.io/v23/naming"
"v.io/x/lib/metadata"
- "v.io/x/lib/vlog"
+ "v.io/x/ref/lib/apilog"
)
const (
@@ -157,7 +157,7 @@
var defaultVersion = 5
func (ep *Endpoint) VersionedString(version int) string {
- defer vlog.LogCallf("version=%v", version)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "version=%v", version)(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
switch version {
default:
return ep.VersionedString(defaultVersion)
diff --git a/runtime/internal/naming/namespace/all_test.go b/runtime/internal/naming/namespace/all_test.go
index fd269d5..457fc23 100644
--- a/runtime/internal/naming/namespace/all_test.go
+++ b/runtime/internal/naming/namespace/all_test.go
@@ -31,8 +31,19 @@
//go:generate v23 test generate
+func resolveWithRetry(ctx *context.T, name string, opts ...naming.NamespaceOpt) *naming.MountEntry {
+ ns := v23.GetNamespace(ctx)
+ for {
+ mp, err := ns.Resolve(ctx, name, opts...)
+ if err == nil {
+ return mp
+ }
+ time.Sleep(100 * time.Millisecond)
+ }
+}
+
func createContexts(t *testing.T) (sc, c *context.T, cleanup func()) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
var (
err error
psc = testutil.NewPrincipal("sc")
@@ -222,6 +233,8 @@
boom(t, "Failed to serve mount table at %s: %s", mountPoint, err)
}
t.Logf("server %q -> %s", eps[0].Name(), mountPoint)
+ // Wait until the mount point appears in the mount table.
+ resolveWithRetry(ctx, mountPoint)
return &serverEntry{mountPoint: mountPoint, server: s, endpoint: eps[0], name: eps[0].Name()}
}
@@ -644,17 +657,12 @@
mtCtx, _ = v23.WithPrincipal(ctx, testutil.NewPrincipal()) // intermediate mounttable
serverCtx, _ = v23.WithPrincipal(ctx, testutil.NewPrincipal()) // end server
clientCtx, _ = v23.WithPrincipal(ctx, testutil.NewPrincipal()) // client process (doing Resolves).
- idp = testutil.NewIDProvider("idp") // identity provider
+ clientNs = v23.GetNamespace(clientCtx)
+ serverNs = v23.GetNamespace(serverCtx)
+ idp = testutil.NewIDProvider("idp") // identity provider
serverEndpoint = naming.FormatEndpoint("tcp", "127.0.0.1:14141")
-
- resolve = func(name string, opts ...naming.NamespaceOpt) (*naming.MountEntry, error) {
- return v23.GetNamespace(clientCtx).Resolve(clientCtx, name, opts...)
- }
-
- mount = func(name, server string, ttl time.Duration, opts ...naming.NamespaceOpt) error {
- return v23.GetNamespace(serverCtx).Mount(serverCtx, name, server, ttl, opts...)
- }
)
+
// Setup default blessings for the processes.
idp.Bless(v23.GetPrincipal(rootMtCtx), "rootmt")
idp.Bless(v23.GetPrincipal(serverCtx), "server")
@@ -668,45 +676,46 @@
}
// Disable caching in the client so that any Mount calls by the server
// are noticed immediately.
- v23.GetNamespace(clientCtx).CacheCtl(naming.DisableCache(true))
+ clientNs.CacheCtl(naming.DisableCache(true))
// Intermediate mounttables should be authenticated.
mt := runMT(t, mtCtx, "mt")
defer func() {
mt.server.Stop()
}()
+
// Mount a server on "mt".
- if err := mount("mt/server", serverEndpoint, time.Minute, naming.ReplaceMount(true)); err != nil {
+ if err := serverNs.Mount(serverCtx, "mt/server", serverEndpoint, time.Minute, naming.ReplaceMount(true)); err != nil {
t.Error(err)
}
+
// The namespace root should be authenticated too
- if e, err := resolve("mt/server"); err != nil {
- t.Errorf("Got (%v, %v)", e, err)
- } else {
- // Host:Port and Endpoint versions of the other namespace root
- // (which has different blessings)
- hproot := fmt.Sprintf("(otherroot)@%v", rootmt.endpoint.Addr())
- eproot := naming.FormatEndpoint(rootmt.endpoint.Addr().Network(), rootmt.endpoint.Addr().String(), rootmt.endpoint.RoutingID(), naming.BlessingOpt("otherroot"), naming.ServesMountTable(rootmt.endpoint.ServesMountTable()))
- for _, root := range []string{hproot, eproot} {
- name := naming.JoinAddressName(root, "mt")
- // Rooted name resolutions should fail authorization because of the "otherrot"
- if e, err := resolve(name); verror.ErrorID(err) != verror.ErrNotTrusted.ID {
- t.Errorf("resolve(%q) returned (%v, errorid=%v %v), wanted errorid=%v", name, e, verror.ErrorID(err), err, verror.ErrNotTrusted.ID)
- }
- // But not fail if the skip-authorization option is provided
- if e, err := resolve(name, options.SkipServerEndpointAuthorization{}); err != nil {
- t.Errorf("resolve(%q): Got (%v, %v), expected resolution to succeed", name, e, err)
- }
- // The namespace root from the context should be authorized as well.
- ctx, ns, _ := v23.WithNewNamespace(clientCtx, naming.JoinAddressName(root, ""))
- if e, err := ns.Resolve(ctx, "mt/server"); verror.ErrorID(err) != verror.ErrNotTrusted.ID {
- t.Errorf("resolve with root=%q returned (%v, errorid=%v %v), wanted errorid=%v: %s", root, e, verror.ErrorID(err), err, verror.ErrNotTrusted.ID, verror.DebugString(err))
- }
- if _, err := ns.Resolve(ctx, "mt/server", options.SkipServerEndpointAuthorization{}); err != nil {
- t.Errorf("resolve with root=%q should have succeeded when authorization checks are skipped. Got %v: %s", root, err, verror.DebugString(err))
- }
+ resolveWithRetry(clientCtx, "mt/server")
+ // Host:Port and Endpoint versions of the other namespace root
+ // (which has different blessings)
+ hproot := fmt.Sprintf("(otherroot)@%v", rootmt.endpoint.Addr())
+ eproot := naming.FormatEndpoint(rootmt.endpoint.Addr().Network(), rootmt.endpoint.Addr().String(), rootmt.endpoint.RoutingID(), naming.BlessingOpt("otherroot"), naming.ServesMountTable(rootmt.endpoint.ServesMountTable()))
+ for _, root := range []string{hproot, eproot} {
+ name := naming.JoinAddressName(root, "mt")
+ // Rooted name resolutions should fail authorization because of the "otherrot"
+ if e, err := clientNs.Resolve(clientCtx, name); verror.ErrorID(err) != verror.ErrNotTrusted.ID {
+ t.Errorf("resolve(%q) returned (%v, errorid=%v %v), wanted errorid=%v", name, e, verror.ErrorID(err), err, verror.ErrNotTrusted.ID)
+ }
+ // But not fail if the skip-authorization option is provided
+ if e, err := clientNs.Resolve(clientCtx, name, options.SkipServerEndpointAuthorization{}); err != nil {
+ t.Errorf("resolve(%q): Got (%v, %v), expected resolution to succeed", name, e, err)
+ }
+
+ // The namespace root from the context should be authorized as well.
+ ctx, ns, _ := v23.WithNewNamespace(clientCtx, naming.JoinAddressName(root, ""))
+ if e, err := ns.Resolve(ctx, "mt/server"); verror.ErrorID(err) != verror.ErrNotTrusted.ID {
+ t.Errorf("resolve with root=%q returned (%v, errorid=%v %v), wanted errorid=%v: %s", root, e, verror.ErrorID(err), err, verror.ErrNotTrusted.ID, verror.DebugString(err))
+ }
+ if _, err := ns.Resolve(ctx, "mt/server", options.SkipServerEndpointAuthorization{}); err != nil {
+ t.Errorf("resolve with root=%q should have succeeded when authorization checks are skipped. Got %v: %s", root, err, verror.DebugString(err))
}
}
+
// Imagine that the network address of "mt" has been taken over by an
// attacker. However, this attacker cannot mess with the mount entry
// for "mt". This would result in "mt" and its mount entry (in the
@@ -717,9 +726,9 @@
t.Error(err)
}
- if e, err := resolve("mt/server", options.SkipServerEndpointAuthorization{}); err != nil {
+ if e, err := clientNs.Resolve(serverCtx, "mt/server", options.SkipServerEndpointAuthorization{}); err != nil {
t.Errorf("Resolve should succeed when skipping server authorization. Got (%v, %v) %s", e, err, verror.DebugString(err))
- } else if e, err := resolve("mt/server"); verror.ErrorID(err) != verror.ErrNotTrusted.ID {
+ } else if e, err := clientNs.Resolve(serverCtx, "mt/server"); verror.ErrorID(err) != verror.ErrNotTrusted.ID {
t.Errorf("Resolve should have failed with %q because an attacker has taken over the intermediate mounttable. Got (%+v, errorid=%q:%v)", verror.ErrNotTrusted.ID, e, verror.ErrorID(err), err)
}
}
@@ -784,10 +793,7 @@
}
defer server.Stop()
- mountEntry, err := ns.Resolve(ctx, "leaf")
- if err != nil {
- boom(t, "ns.Resolve failed: %v", err)
- }
+ mountEntry := resolveWithRetry(ctx, "leaf")
if expected := true; mountEntry.IsLeaf != expected {
boom(t, "unexpected mountEntry.IsLeaf value. Got %v, expected %v", mountEntry.IsLeaf, expected)
}
diff --git a/runtime/internal/naming/namespace/glob.go b/runtime/internal/naming/namespace/glob.go
index 732b48c..c062d08 100644
--- a/runtime/internal/naming/namespace/glob.go
+++ b/runtime/internal/naming/namespace/glob.go
@@ -17,6 +17,7 @@
"v.io/v23/rpc"
"v.io/v23/verror"
+ "v.io/x/ref/lib/apilog"
"v.io/x/ref/lib/glob"
)
@@ -231,7 +232,7 @@
// Glob implements naming.MountTable.Glob.
func (ns *namespace) Glob(ctx *context.T, pattern string, opts ...naming.NamespaceOpt) (chan naming.GlobReply, error) {
- defer vlog.LogCallf("ctx=,pattern=%.10s...,opts...=%v", pattern, opts)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "pattern=%.10s...,opts...=%v", pattern, opts)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
// Root the pattern. If we have no servers to query, give up.
e, patternWasRooted := ns.rootMountEntry(pattern)
if len(e.Servers) == 0 {
diff --git a/runtime/internal/naming/namespace/mount.go b/runtime/internal/naming/namespace/mount.go
index ccdc7fb..9bf8494 100644
--- a/runtime/internal/naming/namespace/mount.go
+++ b/runtime/internal/naming/namespace/mount.go
@@ -14,6 +14,7 @@
"v.io/v23/rpc"
"v.io/v23/security"
"v.io/x/lib/vlog"
+ "v.io/x/ref/lib/apilog"
)
// mountIntoMountTable mounts a single server into a single mount table.
@@ -26,7 +27,7 @@
// Mount implements Namespace.Mount.
func (ns *namespace) Mount(ctx *context.T, name, server string, ttl time.Duration, opts ...naming.NamespaceOpt) error {
- defer vlog.LogCallf("ctx=,name=%.10s...,server=%.10s...,ttl=%v,opts...=%v", name, server, ttl, opts)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "name=%.10s...,server=%.10s...,ttl=%v,opts...=%v", name, server, ttl, opts)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
var flags naming.MountFlag
for _, o := range opts {
// NB: used a switch since we'll be adding more options.
@@ -66,7 +67,7 @@
// Unmount implements Namespace.Unmount.
func (ns *namespace) Unmount(ctx *context.T, name, server string, opts ...naming.NamespaceOpt) error {
- defer vlog.LogCallf("ctx=,name=%.10s...,server=%.10s...,opts...=%v", name, server, opts)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "name=%.10s...,server=%.10s...,opts...=%v", name, server, opts)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
// Unmount the server from all the mount tables.
client := v23.GetClient(ctx)
f := func(ctx *context.T, mt, id string) status {
@@ -88,7 +89,7 @@
// RDeleteemove implements Namespace.Delete.
func (ns *namespace) Delete(ctx *context.T, name string, deleteSubtree bool, opts ...naming.NamespaceOpt) error {
- defer vlog.LogCallf("ctx=,name=%.10s...,deleteSubtree=%v,opts...=%v", name, deleteSubtree, opts)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "name=%.10s...,deleteSubtree=%v,opts...=%v", name, deleteSubtree, opts)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
// Remove from all the mount tables.
client := v23.GetClient(ctx)
f := func(ctx *context.T, mt, id string) status {
diff --git a/runtime/internal/naming/namespace/namespace.go b/runtime/internal/naming/namespace/namespace.go
index 649a2fd..dc8db7c 100644
--- a/runtime/internal/naming/namespace/namespace.go
+++ b/runtime/internal/naming/namespace/namespace.go
@@ -8,15 +8,15 @@
"sync"
"time"
- inaming "v.io/x/ref/runtime/internal/naming"
-
"v.io/v23/context"
"v.io/v23/naming"
"v.io/v23/rpc"
"v.io/v23/security"
vdltime "v.io/v23/vdlroot/time"
"v.io/v23/verror"
- "v.io/x/lib/vlog"
+
+ "v.io/x/ref/lib/apilog"
+ inaming "v.io/x/ref/runtime/internal/naming"
)
const defaultMaxResolveDepth = 32
@@ -72,7 +72,7 @@
// SetRoots implements naming.Namespace.SetRoots
func (ns *namespace) SetRoots(roots ...string) error {
- defer vlog.LogCallf("roots...=%v", roots)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "roots...=%v", roots)(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
// Allow roots to be cleared with a call of SetRoots()
if len(roots) > 0 && !rooted(roots) {
return badRoots(roots)
@@ -193,7 +193,7 @@
// CacheCtl implements naming.Namespace.CacheCtl
func (ns *namespace) CacheCtl(ctls ...naming.CacheCtl) []naming.CacheCtl {
- defer vlog.LogCallf("ctls...=%v", ctls)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "ctls...=%v", ctls)(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
for _, c := range ctls {
switch v := c.(type) {
case naming.DisableCache:
diff --git a/runtime/internal/naming/namespace/perms.go b/runtime/internal/naming/namespace/perms.go
index 6e12398..7ee0b16 100644
--- a/runtime/internal/naming/namespace/perms.go
+++ b/runtime/internal/naming/namespace/perms.go
@@ -12,6 +12,7 @@
"v.io/v23/rpc"
"v.io/v23/security/access"
"v.io/x/lib/vlog"
+ "v.io/x/ref/lib/apilog"
)
// setPermsInMountTable sets the Permissions in a single server.
@@ -23,7 +24,7 @@
}
func (ns *namespace) SetPermissions(ctx *context.T, name string, perms access.Permissions, version string, opts ...naming.NamespaceOpt) error {
- defer vlog.LogCallf("ctx=,name=%.10s...,perms=,version=%.10s...,opts...=%v", name, version, opts)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "name=%.10s...,perms=,version=%.10s...,opts...=%v", name, version, opts)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
client := v23.GetClient(ctx)
// Apply to all mount tables implementing the name.
@@ -37,7 +38,7 @@
// GetPermissions gets Permissions from a mount table.
func (ns *namespace) GetPermissions(ctx *context.T, name string, opts ...naming.NamespaceOpt) (perms access.Permissions, version string, err error) {
- defer vlog.LogCallf("ctx=,name=%.10s...,opts...=%v", name, opts)("perms=,version=%.10s...,err=%v", &version, &err) // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "name=%.10s...,opts...=%v", name, opts)(ctx, "perms=,version=%.10s...,err=%v", &version, &err) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
client := v23.GetClient(ctx)
// Resolve to all the mount tables implementing name.
diff --git a/runtime/internal/naming/namespace/perms_test.go b/runtime/internal/naming/namespace/perms_test.go
index 3a0c916..92090fb 100644
--- a/runtime/internal/naming/namespace/perms_test.go
+++ b/runtime/internal/naming/namespace/perms_test.go
@@ -27,7 +27,7 @@
}
func initTest() (rootCtx *context.T, aliceCtx *context.T, bobCtx *context.T, shutdown v23.Shutdown) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
var err error
if rootCtx, err = v23.WithPrincipal(ctx, testutil.NewPrincipal("root")); err != nil {
panic("failed to set root principal")
@@ -254,8 +254,5 @@
}
// Root should be able to resolve it.
- _, err = ns.Resolve(rootCtx, name)
- if err != nil {
- t.Fatalf("as root Resolve %s: %s", name, err)
- }
+ resolveWithRetry(rootCtx, name)
}
diff --git a/runtime/internal/naming/namespace/resolve.go b/runtime/internal/naming/namespace/resolve.go
index 7539d40..f0abc5e 100644
--- a/runtime/internal/naming/namespace/resolve.go
+++ b/runtime/internal/naming/namespace/resolve.go
@@ -15,6 +15,7 @@
"v.io/v23/rpc"
"v.io/v23/verror"
"v.io/x/lib/vlog"
+ "v.io/x/ref/lib/apilog"
)
func (ns *namespace) resolveAgainstMountTable(ctx *context.T, client rpc.Client, e *naming.MountEntry, opts ...rpc.CallOpt) (*naming.MountEntry, error) {
@@ -61,7 +62,7 @@
// Resolve implements v.io/v23/naming.Namespace.
func (ns *namespace) Resolve(ctx *context.T, name string, opts ...naming.NamespaceOpt) (*naming.MountEntry, error) {
- defer vlog.LogCallf("ctx=,name=%.10s...,opts...=%v", name, opts)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "name=%.10s...,opts...=%v", name, opts)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
e, _ := ns.rootMountEntry(name, opts...)
if vlog.V(2) {
_, file, line, _ := runtime.Caller(1)
@@ -105,7 +106,7 @@
// ResolveToMountTable implements v.io/v23/naming.Namespace.
func (ns *namespace) ResolveToMountTable(ctx *context.T, name string, opts ...naming.NamespaceOpt) (*naming.MountEntry, error) {
- defer vlog.LogCallf("ctx=,name=%.10s...,opts...=%v", name, opts)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "name=%.10s...,opts...=%v", name, opts)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
e, _ := ns.rootMountEntry(name, opts...)
if vlog.V(2) {
_, file, line, _ := runtime.Caller(1)
@@ -156,7 +157,7 @@
// FlushCache flushes the most specific entry found for name. It returns true if anything was
// actually flushed.
func (ns *namespace) FlushCacheEntry(name string) bool {
- defer vlog.LogCallf("name=%.10s...", name)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "name=%.10s...", name)(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
flushed := false
for _, n := range ns.rootName(name) {
// Walk the cache as we would in a resolution. Unlike a resolution, we have to follow
diff --git a/runtime/internal/naming/namespace/v23_internal_test.go b/runtime/internal/naming/namespace/v23_internal_test.go
index 15b3504..cf82452 100644
--- a/runtime/internal/naming/namespace/v23_internal_test.go
+++ b/runtime/internal/naming/namespace/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package namespace
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/runtime/internal/rpc/benchmark/benchmark_test.go b/runtime/internal/rpc/benchmark/benchmark_test.go
index fe41273..5d98e34 100644
--- a/runtime/internal/rpc/benchmark/benchmark_test.go
+++ b/runtime/internal/rpc/benchmark/benchmark_test.go
@@ -110,7 +110,7 @@
// We do not use defer here since this program will exit at the end of
// this function through os.Exit().
var shutdown v23.Shutdown
- ctx, shutdown = test.InitForTest()
+ ctx, shutdown = test.V23Init()
var serverStop func()
serverEP, serverStop := internal.StartServer(ctx, v23.GetListenSpec(ctx))
diff --git a/runtime/internal/rpc/benchmark/glob/glob_test.go b/runtime/internal/rpc/benchmark/glob/glob_test.go
index 44454b9..3bb9c31 100644
--- a/runtime/internal/rpc/benchmark/glob/glob_test.go
+++ b/runtime/internal/rpc/benchmark/glob/glob_test.go
@@ -159,7 +159,7 @@
}
func RunBenchmarkGlob(b *testing.B, obj interface{}) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
addr, stop, err := startServer(b, ctx, obj)
diff --git a/runtime/internal/rpc/benchmark/simple/main.go b/runtime/internal/rpc/benchmark/simple/main.go
index b5ba01c..6806775 100644
--- a/runtime/internal/rpc/benchmark/simple/main.go
+++ b/runtime/internal/rpc/benchmark/simple/main.go
@@ -121,7 +121,7 @@
test.Init()
var shutdown v23.Shutdown
- ctx, shutdown = test.InitForTest()
+ ctx, shutdown = test.V23Init()
defer shutdown()
var serverStop func()
diff --git a/runtime/internal/rpc/client.go b/runtime/internal/rpc/client.go
index ff1ee51..8b74229 100644
--- a/runtime/internal/rpc/client.go
+++ b/runtime/internal/rpc/client.go
@@ -28,6 +28,7 @@
"v.io/v23/vom"
"v.io/v23/vtrace"
+ "v.io/x/ref/lib/apilog"
inaming "v.io/x/ref/runtime/internal/naming"
"v.io/x/ref/runtime/internal/rpc/stream"
"v.io/x/ref/runtime/internal/rpc/stream/vc"
@@ -185,12 +186,12 @@
}
func (c *client) StartCall(ctx *context.T, name, method string, args []interface{}, opts ...rpc.CallOpt) (rpc.ClientCall, error) {
- defer vlog.LogCallf("ctx=,name=%.10s...,method=%.10s...,args=,opts...=%v", name, method, opts)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "name=%.10s...,method=%.10s...,args=,opts...=%v", name, method, opts)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
return c.startCall(ctx, name, method, args, opts)
}
func (c *client) Call(ctx *context.T, name, method string, inArgs, outArgs []interface{}, opts ...rpc.CallOpt) error {
- defer vlog.LogCallf("ctx=,name=%.10s...,method=%.10s...,inArgs=,outArgs=,opts...=%v", name, method, opts)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "name=%.10s...,method=%.10s...,inArgs=,outArgs=,opts...=%v", name, method, opts)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
deadline := getDeadline(ctx, opts)
var lastErr error
@@ -728,7 +729,7 @@
}
func (c *client) Close() {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
for _, v := range c.vcCache.Close() {
c.streamMgr.ShutdownEndpoint(v.RemoteEndpoint())
}
@@ -851,7 +852,7 @@
}
func (fc *flowClient) Send(item interface{}) error {
- defer vlog.LogCallf("item=")("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "item=")(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
if fc.sendClosed {
return verror.New(verror.ErrAborted, fc.ctx)
}
@@ -895,7 +896,7 @@
}
func (fc *flowClient) Recv(itemptr interface{}) error {
- defer vlog.LogCallf("itemptr=")("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "itemptr=")(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
switch {
case fc.response.Error != nil:
return verror.New(verror.ErrBadProtocol, fc.ctx, fc.response.Error)
@@ -930,7 +931,7 @@
}
func (fc *flowClient) CloseSend() error {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
return fc.closeSend()
}
@@ -962,7 +963,7 @@
}
func (fc *flowClient) Finish(resultptrs ...interface{}) error {
- defer vlog.LogCallf("resultptrs...=%v", resultptrs)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "resultptrs...=%v", resultptrs)(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
err := fc.finish(resultptrs...)
vtrace.GetSpan(fc.ctx).Finish()
return err
@@ -1039,7 +1040,7 @@
}
func (fc *flowClient) RemoteBlessings() ([]string, security.Blessings) {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
return fc.server, fc.flow.RemoteBlessings()
}
diff --git a/runtime/internal/rpc/discharges.go b/runtime/internal/rpc/discharges.go
index c67c530..46017ee 100644
--- a/runtime/internal/rpc/discharges.go
+++ b/runtime/internal/rpc/discharges.go
@@ -10,6 +10,7 @@
"sync"
"time"
+ "v.io/x/ref/lib/apilog"
"v.io/x/ref/runtime/internal/rpc/stream/vc"
"v.io/v23/context"
@@ -24,10 +25,10 @@
type NoDischarges struct{}
func (NoDischarges) RPCCallOpt() {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
}
func (NoDischarges) NSOpt() {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
}
// discharger implements vc.DischargeClient.
diff --git a/runtime/internal/rpc/full_test.go b/runtime/internal/rpc/full_test.go
index 1fd3ca8..f1c08a8 100644
--- a/runtime/internal/rpc/full_test.go
+++ b/runtime/internal/rpc/full_test.go
@@ -282,18 +282,23 @@
}
func verifyMount(t *testing.T, ctx *context.T, ns namespace.T, name string) []string {
- me, err := ns.Resolve(ctx, name)
- if err != nil {
- t.Errorf("%s: %s not found in mounttable", loc(1), name)
- return nil
+ for {
+ me, err := ns.Resolve(ctx, name)
+ if err == nil {
+ return me.Names()
+ }
+ time.Sleep(10 * time.Millisecond)
}
- return me.Names()
}
func verifyMountMissing(t *testing.T, ctx *context.T, ns namespace.T, name string) {
- if me, err := ns.Resolve(ctx, name); err == nil {
- names := me.Names()
- t.Errorf("%s: %s not supposed to be found in mounttable; got %d servers instead: %v (%+v)", loc(1), name, len(names), names, me)
+ for {
+ if _, err := ns.Resolve(ctx, name); err != nil {
+ // Assume that any error (since we're using a mock namespace) means
+ // that the name is no longer present.
+ return
+ }
+ time.Sleep(10 * time.Millisecond)
}
}
diff --git a/runtime/internal/rpc/options.go b/runtime/internal/rpc/options.go
index 16004aa..d046e32 100644
--- a/runtime/internal/rpc/options.go
+++ b/runtime/internal/rpc/options.go
@@ -11,7 +11,7 @@
"v.io/v23/options"
"v.io/v23/rpc"
- "v.io/x/lib/vlog"
+ "v.io/x/ref/lib/apilog"
"v.io/x/ref/runtime/internal/rpc/stream"
)
@@ -21,7 +21,7 @@
type PreferredProtocols []string
func (PreferredProtocols) RPCClientOpt() {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
}
// This option is used to sort and filter the endpoints when resolving the
@@ -29,7 +29,7 @@
type PreferredServerResolveProtocols []string
func (PreferredServerResolveProtocols) RPCServerOpt() {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
}
// ReservedNameDispatcher specifies the dispatcher that controls access
@@ -39,7 +39,7 @@
}
func (ReservedNameDispatcher) RPCServerOpt() {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
}
func getRetryTimeoutOpt(opts []rpc.CallOpt) (time.Duration, bool) {
diff --git a/runtime/internal/rpc/reserved.go b/runtime/internal/rpc/reserved.go
index 03a63fc..57b582f 100644
--- a/runtime/internal/rpc/reserved.go
+++ b/runtime/internal/rpc/reserved.go
@@ -18,6 +18,7 @@
"v.io/v23/verror"
"v.io/x/lib/vlog"
+ "v.io/x/ref/lib/apilog"
"v.io/x/ref/lib/glob"
)
@@ -44,7 +45,7 @@
}
func (r *reservedMethods) Describe__() []rpc.InterfaceDesc {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
return []rpc.InterfaceDesc{{
Name: "__Reserved",
Doc: `Reserved methods implemented by the RPC framework. Each method name is prefixed with a double underscore "__".`,
@@ -356,11 +357,11 @@
}
func (c *derivedServerCall) Suffix() string {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
return c.suffix
}
func (c *derivedServerCall) Security() security.Call {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
return c.security
}
@@ -379,10 +380,10 @@
}
func (c *derivedSecurityCall) Suffix() string {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
return c.suffix
}
func (c *derivedSecurityCall) MethodTags() []*vdl.Value {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
return c.methodTags
}
diff --git a/runtime/internal/rpc/resolve_test.go b/runtime/internal/rpc/resolve_test.go
index 73ace16..08b400a 100644
--- a/runtime/internal/rpc/resolve_test.go
+++ b/runtime/internal/rpc/resolve_test.go
@@ -7,7 +7,6 @@
import (
"flag"
"fmt"
- "io"
"os"
"testing"
"time"
@@ -66,7 +65,7 @@
fake.InjectRuntime(runtime, ctx, shutdown)
}
-func rootMountTable(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var rootMT = modules.Register(func(env *modules.Env, args ...string) error {
setupRuntime()
ctx, shutdown := v23.Init()
defer shutdown()
@@ -88,16 +87,16 @@
if err := server.ServeDispatcher(mp, mt); err != nil {
return fmt.Errorf("root failed: %s", err)
}
- fmt.Fprintf(stdout, "PID=%d\n", os.Getpid())
+ fmt.Fprintf(env.Stdout, "PID=%d\n", os.Getpid())
for _, ep := range eps {
- fmt.Fprintf(stdout, "MT_NAME=%s\n", ep.Name())
+ fmt.Fprintf(env.Stdout, "MT_NAME=%s\n", ep.Name())
}
- modules.WaitForEOF(stdin)
+ modules.WaitForEOF(env.Stdin)
return nil
-}
+}, "rootMT")
func startMT(t *testing.T, sh *modules.Shell) string {
- h, err := sh.Start("rootMountTable", nil)
+ h, err := sh.Start(nil, rootMT)
if err != nil {
t.Fatalf("unexpected error for root mt: %s", err)
}
diff --git a/runtime/internal/rpc/server.go b/runtime/internal/rpc/server.go
index 3505ef5..e5fbf51 100644
--- a/runtime/internal/rpc/server.go
+++ b/runtime/internal/rpc/server.go
@@ -31,6 +31,7 @@
"v.io/v23/vom"
"v.io/v23/vtrace"
+ "v.io/x/ref/lib/apilog"
"v.io/x/ref/lib/stats"
"v.io/x/ref/runtime/internal/lib/publisher"
inaming "v.io/x/ref/runtime/internal/naming"
@@ -253,9 +254,8 @@
}
func (s *server) Status() rpc.ServerStatus {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
status := rpc.ServerStatus{}
- defer vlog.LogCall()()
s.Lock()
defer s.Unlock()
status.State = externalStates[s.state]
@@ -281,7 +281,7 @@
}
func (s *server) WatchNetwork(ch chan<- rpc.NetworkChange) {
- defer vlog.LogCallf("ch=")("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "ch=")(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
s.Lock()
defer s.Unlock()
if s.dhcpState != nil {
@@ -290,7 +290,7 @@
}
func (s *server) UnwatchNetwork(ch chan<- rpc.NetworkChange) {
- defer vlog.LogCallf("ch=")("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "ch=")(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
s.Lock()
defer s.Unlock()
if s.dhcpState != nil {
@@ -364,7 +364,7 @@
}
func (s *server) Listen(listenSpec rpc.ListenSpec) ([]naming.Endpoint, error) {
- defer vlog.LogCallf("listenSpec=")("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "listenSpec=")(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
useProxy := len(listenSpec.Proxy) > 0
if !useProxy && len(listenSpec.Addrs) == 0 {
return nil, verror.New(verror.ErrBadArg, s.ctx, "ListenSpec contains no proxy or addresses to listen on")
@@ -744,7 +744,7 @@
}
func (d leafDispatcher) Lookup(suffix string) (interface{}, security.Authorizer, error) {
- defer vlog.LogCallf("suffix=%.10s...", suffix)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "suffix=%.10s...", suffix)(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
if suffix != "" {
return nil, nil, verror.New(verror.ErrUnknownSuffix, nil, suffix)
}
@@ -752,7 +752,7 @@
}
func (s *server) Serve(name string, obj interface{}, authorizer security.Authorizer) error {
- defer vlog.LogCallf("name=%.10s...,obj=,authorizer=", name)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "name=%.10s...,obj=,authorizer=", name)(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
if obj == nil {
return verror.New(verror.ErrBadArg, s.ctx, "nil object")
}
@@ -776,7 +776,7 @@
}
func (s *server) ServeDispatcher(name string, disp rpc.Dispatcher) error {
- defer vlog.LogCallf("name=%.10s...,disp=", name)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "name=%.10s...,disp=", name)(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
if disp == nil {
return verror.New(verror.ErrBadArg, s.ctx, "nil dispatcher")
}
@@ -799,7 +799,7 @@
}
func (s *server) AddName(name string) error {
- defer vlog.LogCallf("name=%.10s...", name)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "name=%.10s...", name)(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
if len(name) == 0 {
return verror.New(verror.ErrBadArg, s.ctx, "name is empty")
}
@@ -814,7 +814,7 @@
}
func (s *server) RemoveName(name string) {
- defer vlog.LogCallf("name=%.10s...", name)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "name=%.10s...", name)(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
s.Lock()
defer s.Unlock()
if err := s.allowed(publishing, "RemoveName"); err != nil {
@@ -825,9 +825,8 @@
}
func (s *server) Stop() error {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
serverDebug := fmt.Sprintf("Dispatcher: %T, Status:[%v]", s.disp, s.Status())
- defer vlog.LogCall()()
vlog.VI(1).Infof("Stop: %s", serverDebug)
defer vlog.VI(1).Infof("Stop done: %s", serverDebug)
s.Lock()
@@ -1272,7 +1271,7 @@
// Send implements the rpc.Stream method.
func (fs *flowServer) Send(item interface{}) error {
- defer vlog.LogCallf("item=")("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "item=")(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
// The empty response header indicates what follows is a streaming result.
if err := fs.enc.Encode(rpc.Response{}); err != nil {
return err
@@ -1282,7 +1281,7 @@
// Recv implements the rpc.Stream method.
func (fs *flowServer) Recv(itemptr interface{}) error {
- defer vlog.LogCallf("itemptr=")("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "itemptr=")(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
var req rpc.Request
if err := fs.dec.Decode(&req); err != nil {
return err
diff --git a/runtime/internal/rpc/server_authorizer.go b/runtime/internal/rpc/server_authorizer.go
index cda735d..86874ce 100644
--- a/runtime/internal/rpc/server_authorizer.go
+++ b/runtime/internal/rpc/server_authorizer.go
@@ -12,7 +12,8 @@
"v.io/v23/rpc"
"v.io/v23/security"
"v.io/v23/verror"
- "v.io/x/lib/vlog"
+
+ "v.io/x/ref/lib/apilog"
)
// TODO(ribrdb): Flip this to true once everything is updated and also update
@@ -67,7 +68,7 @@
}
func (a *serverAuthorizer) Authorize(ctx *context.T, call security.Call) error {
- defer vlog.LogCallf("ctx=,call=")("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "call=")(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
if call.RemoteBlessings().IsZero() {
return verror.New(errNoBlessingsFromServer, ctx)
}
diff --git a/runtime/internal/rpc/stream/errors.go b/runtime/internal/rpc/stream/errors.go
index 7ba12b2..2a676d4 100644
--- a/runtime/internal/rpc/stream/errors.go
+++ b/runtime/internal/rpc/stream/errors.go
@@ -8,7 +8,8 @@
"net"
"v.io/v23/verror"
- "v.io/x/lib/vlog"
+
+ "v.io/x/ref/lib/apilog"
)
const pkgPath = "v.io/x/ref/runtime/internal/rpc/stream"
@@ -52,7 +53,7 @@
func (t NetError) Err() error { return t.err }
func (t NetError) Error() string {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
return t.err.Error()
}
func (t NetError) Timeout() bool { return t.timeout }
diff --git a/runtime/internal/rpc/stream/manager/error_test.go b/runtime/internal/rpc/stream/manager/error_test.go
index 4c61f49..a2fbf01 100644
--- a/runtime/internal/rpc/stream/manager/error_test.go
+++ b/runtime/internal/rpc/stream/manager/error_test.go
@@ -94,7 +94,7 @@
}
func TestDialErrors(t *testing.T) {
- _, shutdown := test.InitForTest()
+ _, shutdown := test.V23Init()
defer shutdown()
server := manager.InternalNew(naming.FixedRoutingID(0x55555555))
client := manager.InternalNew(naming.FixedRoutingID(0xcccccccc))
diff --git a/runtime/internal/rpc/stream/manager/manager.go b/runtime/internal/rpc/stream/manager/manager.go
index a297962..bfa3deb 100644
--- a/runtime/internal/rpc/stream/manager/manager.go
+++ b/runtime/internal/rpc/stream/manager/manager.go
@@ -18,6 +18,7 @@
"v.io/v23/verror"
"v.io/x/lib/vlog"
+ "v.io/x/ref/lib/apilog"
"v.io/x/ref/lib/stats"
"v.io/x/ref/lib/stats/counter"
inaming "v.io/x/ref/runtime/internal/naming"
@@ -84,7 +85,7 @@
func (DialTimeout) RPCStreamVCOpt() {}
func (DialTimeout) RPCClientOpt() {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
}
func dial(d rpc.DialerFunc, network, address string, timeout time.Duration) (net.Conn, error) {
diff --git a/runtime/internal/rpc/stream/manager/manager_test.go b/runtime/internal/rpc/stream/manager/manager_test.go
index 2c20fcb..b2a5cad 100644
--- a/runtime/internal/rpc/stream/manager/manager_test.go
+++ b/runtime/internal/rpc/stream/manager/manager_test.go
@@ -37,11 +37,6 @@
"v.io/x/ref/test/testutil"
)
-func init() {
- modules.RegisterChild("runServer", "", runServer)
- modules.RegisterChild("runRLimitedServer", "", runRLimitedServer)
-}
-
// We write our own TestMain here instead of relying on v23 test generate because
// we need to set runtime.GOMAXPROCS.
func TestMain(m *testing.M) {
@@ -51,13 +46,7 @@
// condition that occurs when closing the server; also, using 1 cpu
// introduces less variance in the behavior of the test.
runtime.GOMAXPROCS(1)
- if modules.IsModulesChildProcess() {
- if err := modules.Dispatch(); err != nil {
- fmt.Fprintf(os.Stderr, "modules.Dispatch failed: %v\n", err)
- os.Exit(1)
- }
- return
- }
+ modules.DispatchAndExitIfChild()
os.Exit(m.Run())
}
@@ -676,7 +665,7 @@
t.Fatalf("unexpected error: %s", err)
}
defer sh.Cleanup(nil, nil)
- h, err := sh.Start("runServer", nil, protocol, "127.0.0.1:0")
+ h, err := sh.Start(nil, runServer, protocol, "127.0.0.1:0")
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -697,7 +686,7 @@
t.Fatal("Expected client.Dial to fail since server is dead")
}
- h, err = sh.Start("runServer", nil, protocol, ep.Addr().String())
+ h, err = sh.Start(nil, runServer, protocol, ep.Addr().String())
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -714,34 +703,36 @@
}
}
-func runServer(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var runServer = modules.Register(runServerFunc, "runServer")
+
+func runServerFunc(env *modules.Env, args ...string) error {
server := InternalNew(naming.FixedRoutingID(0x55555555))
principal := testutil.NewPrincipal("test")
_, ep, err := server.Listen(args[0], args[1], principal, principal.BlessingStore().Default())
if err != nil {
- fmt.Fprintln(stderr, err)
+ fmt.Fprintln(env.Stderr, err)
return err
}
- fmt.Fprintf(stdout, "ENDPOINT=%v\n", ep)
+ fmt.Fprintf(env.Stdout, "ENDPOINT=%v\n", ep)
// Live forever (till the process is explicitly killed)
- modules.WaitForEOF(stdin)
+ modules.WaitForEOF(env.Stdin)
return nil
}
-func runRLimitedServer(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var runRLimitedServer = modules.Register(func(env *modules.Env, args ...string) error {
var rlimit syscall.Rlimit
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit); err != nil {
- fmt.Fprintln(stderr, err)
+ fmt.Fprintln(env.Stderr, err)
return err
}
rlimit.Cur = 9
if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlimit); err != nil {
- fmt.Fprintln(stderr, err)
+ fmt.Fprintln(env.Stderr, err)
return err
}
- fmt.Fprintf(stdout, "RLIMIT_NOFILE=%d\n", rlimit.Cur)
- return runServer(stdin, stdout, stderr, env, args...)
-}
+ fmt.Fprintf(env.Stdout, "RLIMIT_NOFILE=%d\n", rlimit.Cur)
+ return runServerFunc(env, args...)
+}, "runRLimitedServer")
func readLine(f stream.Flow) (string, error) {
var result bytes.Buffer
@@ -873,7 +864,7 @@
t.Fatal(err)
}
defer sh.Cleanup(nil, nil)
- h, err := sh.Start("runRLimitedServer", nil, "--logtostderr=true", "tcp", "127.0.0.1:0")
+ h, err := sh.Start(nil, runRLimitedServer, "--logtostderr=true", "tcp", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
}
diff --git a/runtime/internal/rpc/stream/proxy/proxy_test.go b/runtime/internal/rpc/stream/proxy/proxy_test.go
index a438489..f583e9f 100644
--- a/runtime/internal/rpc/stream/proxy/proxy_test.go
+++ b/runtime/internal/rpc/stream/proxy/proxy_test.go
@@ -482,7 +482,7 @@
}
func v23Init() (*context.T, func()) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
ctx, err := v23.WithPrincipal(ctx, testutil.NewPrincipal("proxy"))
if err != nil {
panic(err)
diff --git a/runtime/internal/rpc/stream/proxy/v23_internal_test.go b/runtime/internal/rpc/stream/proxy/v23_internal_test.go
index 84bea54..73903ec 100644
--- a/runtime/internal/rpc/stream/proxy/v23_internal_test.go
+++ b/runtime/internal/rpc/stream/proxy/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package proxy
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/runtime/internal/rpc/stream/vc/v23_internal_test.go b/runtime/internal/rpc/stream/vc/v23_internal_test.go
index 945d8c4..a48d6f6 100644
--- a/runtime/internal/rpc/stream/vc/v23_internal_test.go
+++ b/runtime/internal/rpc/stream/vc/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package vc
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/runtime/internal/rpc/stream/vc/vc.go b/runtime/internal/rpc/stream/vc/vc.go
index 1e6e7d2..12c2527 100644
--- a/runtime/internal/rpc/stream/vc/vc.go
+++ b/runtime/internal/rpc/stream/vc/vc.go
@@ -24,6 +24,7 @@
"v.io/v23/vom"
"v.io/x/lib/vlog"
+ "v.io/x/ref/lib/apilog"
"v.io/x/ref/runtime/internal/lib/bqueue"
"v.io/x/ref/runtime/internal/lib/iobuf"
vsync "v.io/x/ref/runtime/internal/lib/sync"
@@ -73,7 +74,7 @@
func (DischargeExpiryBuffer) RPCStreamListenerOpt() {}
func (DischargeExpiryBuffer) RPCServerOpt() {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
}
const DefaultServerDischargeExpiryBuffer = 20 * time.Second
diff --git a/runtime/internal/rpc/stream/vif/v23_internal_test.go b/runtime/internal/rpc/stream/vif/v23_internal_test.go
index 161553c..70e47de 100644
--- a/runtime/internal/rpc/stream/vif/v23_internal_test.go
+++ b/runtime/internal/rpc/stream/vif/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package vif
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/runtime/internal/rpc/test/client_test.go b/runtime/internal/rpc/test/client_test.go
index a1e9013..a42a2a9 100644
--- a/runtime/internal/rpc/test/client_test.go
+++ b/runtime/internal/rpc/test/client_test.go
@@ -6,7 +6,6 @@
import (
"fmt"
- "io"
"net"
"os"
"path/filepath"
@@ -38,15 +37,15 @@
//go:generate v23 test generate .
-func rootMT(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var rootMT = modules.Register(func(env *modules.Env, args ...string) error {
seclevel := options.SecurityConfidential
if len(args) == 1 && args[0] == "nosec" {
seclevel = options.SecurityNone
}
- return runRootMT(stdin, stdout, stderr, seclevel, env, args...)
-}
+ return runRootMT(seclevel, env, args...)
+}, "rootMT")
-func runRootMT(stdin io.Reader, stdout, stderr io.Writer, seclevel options.SecurityLevel, env map[string]string, args ...string) error {
+func runRootMT(seclevel options.SecurityLevel, env *modules.Env, args ...string) error {
ctx, shutdown := v23.Init()
defer shutdown()
@@ -66,11 +65,11 @@
if err := server.ServeDispatcher("", mt); err != nil {
return fmt.Errorf("root failed: %s", err)
}
- fmt.Fprintf(stdout, "PID=%d\n", os.Getpid())
+ fmt.Fprintf(env.Stdout, "PID=%d\n", os.Getpid())
for _, ep := range eps {
- fmt.Fprintf(stdout, "MT_NAME=%s\n", ep.Name())
+ fmt.Fprintf(env.Stdout, "MT_NAME=%s\n", ep.Name())
}
- modules.WaitForEOF(stdin)
+ modules.WaitForEOF(env.Stdin)
return nil
}
@@ -100,7 +99,7 @@
return nil
}
-func echoServer(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var echoServer = modules.Register(func(env *modules.Env, args ...string) error {
ctx, shutdown := v23.Init()
defer shutdown()
@@ -118,15 +117,15 @@
if err := server.ServeDispatcher(mp, disp); err != nil {
return err
}
- fmt.Fprintf(stdout, "PID=%d\n", os.Getpid())
+ fmt.Fprintf(env.Stdout, "PID=%d\n", os.Getpid())
for _, ep := range eps {
- fmt.Fprintf(stdout, "NAME=%s\n", ep.Name())
+ fmt.Fprintf(env.Stdout, "NAME=%s\n", ep.Name())
}
- modules.WaitForEOF(stdin)
+ modules.WaitForEOF(env.Stdin)
return nil
-}
+}, "echoServer")
-func echoClient(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var echoClient = modules.Register(func(env *modules.Env, args ...string) error {
ctx, shutdown := v23.Init()
defer shutdown()
@@ -138,13 +137,13 @@
if err := client.Call(ctx, name, "Echo", []interface{}{a}, []interface{}{&r}); err != nil {
return err
}
- fmt.Fprintf(stdout, r)
+ fmt.Fprintf(env.Stdout, r)
}
return nil
-}
+}, "echoClient")
func newCtx() (*context.T, v23.Shutdown) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
return ctx, shutdown
}
@@ -154,7 +153,7 @@
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
- root, err := sh.Start("rootMT", nil, args...)
+ root, err := sh.Start(nil, rootMT, args...)
if err != nil {
t.Fatalf("unexpected error for root mt: %s", err)
}
@@ -174,7 +173,7 @@
}
func runClient(t *testing.T, sh *modules.Shell) error {
- clt, err := sh.Start("echoClient", nil, "echoServer", "a message")
+ clt, err := sh.Start(nil, echoClient, "echoServer", "a message")
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -186,12 +185,14 @@
return nil
}
-func numServers(t *testing.T, ctx *context.T, name string) int {
- me, err := v23.GetNamespace(ctx).Resolve(ctx, name)
- if err != nil {
- return 0
+func numServers(t *testing.T, ctx *context.T, name string, expected int) int {
+ for {
+ me, err := v23.GetNamespace(ctx).Resolve(ctx, name)
+ if err == nil && len(me.Servers) == expected {
+ return expected
+ }
+ time.Sleep(10 * time.Millisecond)
}
- return len(me.Servers)
}
// TODO(cnicolaou): figure out how to test and see what the internals
@@ -202,7 +203,7 @@
sh, fn := runMountTable(t, ctx)
defer fn()
- srv, err := sh.Start("echoServer", nil, "echoServer", "echoServer")
+ srv, err := sh.Start(nil, echoServer, "echoServer", "echoServer")
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -211,7 +212,7 @@
s.ExpectVar("NAME")
// Verify that there are 1 entries for echoServer in the mount table.
- if got, want := numServers(t, ctx, "echoServer"), 1; got != want {
+ if got, want := numServers(t, ctx, "echoServer", 1), 1; got != want {
t.Fatalf("got: %d, want: %d", got, want)
}
@@ -228,7 +229,7 @@
}
// Verify that there are 101 entries for echoServer in the mount table.
- if got, want := numServers(t, ctx, "echoServer"), 101; got != want {
+ if got, want := numServers(t, ctx, "echoServer", 101), 101; got != want {
t.Fatalf("got: %q, want: %q", got, want)
}
@@ -243,7 +244,7 @@
srv.Shutdown(nil, nil)
// Verify that there are 100 entries for echoServer in the mount table.
- if got, want := numServers(t, ctx, "echoServer"), 100; got != want {
+ if got, want := numServers(t, ctx, "echoServer", 100), 100; got != want {
t.Fatalf("got: %d, want: %d", got, want)
}
}
@@ -508,8 +509,8 @@
logErr("client does not trust server", err)
}
-func childPing(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- ctx, shutdown := test.InitForTest()
+var childPing = modules.Register(func(env *modules.Env, args ...string) error {
+ ctx, shutdown := test.V23Init()
defer shutdown()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
@@ -518,9 +519,9 @@
if err := v23.GetClient(ctx).Call(ctx, name, "Ping", nil, []interface{}{&got}); err != nil {
fmt.Errorf("unexpected error: %s", err)
}
- fmt.Fprintf(stdout, "RESULT=%s\n", got)
+ fmt.Fprintf(env.Stdout, "RESULT=%s\n", got)
return nil
-}
+}, "childPing")
func initServer(t *testing.T, ctx *context.T, opts ...rpc.ServerOpt) (string, func()) {
server, err := v23.NewServer(ctx, opts...)
@@ -578,7 +579,7 @@
}
func TestAccessDenied(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
name, fn := initServer(t, ctx)
@@ -654,7 +655,7 @@
// backoff of some minutes.
startServer := func() {
time.Sleep(100 * time.Millisecond)
- srv, _ := sh.Start("echoServer", nil, "message", name)
+ srv, _ := sh.Start(nil, echoServer, "message", name)
s := expect.NewSession(t, srv.Stdout(), time.Minute)
s.ExpectVar("PID")
s.ExpectVar("NAME")
@@ -686,7 +687,7 @@
name, fn := initServer(t, ctx)
defer fn()
- srv, err := sh.Start("childPing", nil, name)
+ srv, err := sh.Start(nil, childPing, name)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -806,7 +807,7 @@
// endpoint).
func TestReconnect(t *testing.T) {
t.Skip()
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
sh, err := modules.NewShell(ctx, v23.GetPrincipal(ctx), testing.Verbose(), t)
@@ -814,7 +815,7 @@
t.Fatalf("unexpected error: %s", err)
}
defer sh.Cleanup(os.Stderr, os.Stderr)
- server, err := sh.Start("echoServer", nil, "--v23.tcp.address=127.0.0.1:0", "mymessage", "")
+ server, err := sh.Start(nil, echoServer, "--v23.tcp.address=127.0.0.1:0", "mymessage", "")
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -852,7 +853,7 @@
// Resurrect the server with the same address, verify client
// re-establishes the connection. This is racy if another
// process grabs the port.
- server, err = sh.Start("echoServer", nil, "--v23.tcp.address="+ep.Address, "mymessage again", "")
+ server, err = sh.Start(nil, echoServer, "--v23.tcp.address="+ep.Address, "mymessage again", "")
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
diff --git a/runtime/internal/rpc/test/glob_test.go b/runtime/internal/rpc/test/glob_test.go
index 7e5bd43..471b6f2 100644
--- a/runtime/internal/rpc/test/glob_test.go
+++ b/runtime/internal/rpc/test/glob_test.go
@@ -42,7 +42,7 @@
}
func TestGlob(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
namespace := []string{
@@ -203,7 +203,7 @@
}
func TestGlobDeny(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
tree := newNode()
diff --git a/runtime/internal/rpc/test/proxy_test.go b/runtime/internal/rpc/test/proxy_test.go
index 05e1c36..9a6c7b8 100644
--- a/runtime/internal/rpc/test/proxy_test.go
+++ b/runtime/internal/rpc/test/proxy_test.go
@@ -6,7 +6,6 @@
import (
"fmt"
- "io"
"os"
"reflect"
"sort"
@@ -49,7 +48,7 @@
return ctx, shutdown
}
-func proxyServer(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var proxyServer = modules.Register(func(env *modules.Env, args ...string) error {
ctx, shutdown := v23.Init()
defer shutdown()
@@ -58,11 +57,11 @@
listenSpec := rpc.ListenSpec{Addrs: rpc.ListenAddrs{{"tcp", "127.0.0.1:0"}}}
proxyShutdown, proxyEp, err := proxy.New(ctx, listenSpec, security.AllowEveryone())
if err != nil {
- fmt.Fprintf(stderr, "%s\n", verror.DebugString(err))
+ fmt.Fprintf(env.Stderr, "%s\n", verror.DebugString(err))
return err
}
defer proxyShutdown()
- fmt.Fprintf(stdout, "PID=%d\n", os.Getpid())
+ fmt.Fprintf(env.Stdout, "PID=%d\n", os.Getpid())
if expected > 0 {
pub := publisher.New(ctx, v23.GetNamespace(ctx), time.Minute)
defer pub.WaitForStop()
@@ -84,11 +83,11 @@
time.Sleep(delay)
}
}
- fmt.Fprintf(stdout, "PROXY_NAME=%s\n", proxyEp.Name())
- modules.WaitForEOF(stdin)
- fmt.Fprintf(stdout, "DONE\n")
+ fmt.Fprintf(env.Stdout, "PROXY_NAME=%s\n", proxyEp.Name())
+ modules.WaitForEOF(env.Stdin)
+ fmt.Fprintf(env.Stdout, "DONE\n")
return nil
-}
+}, "")
type testServer struct{}
@@ -121,7 +120,7 @@
t.Fatalf("unexpected error: %s", err)
}
h.sh = sh
- p, err := sh.Start("proxyServer", nil, args...)
+ p, err := sh.Start(nil, proxyServer, args...)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
diff --git a/runtime/internal/rpc/test/signature_test.go b/runtime/internal/rpc/test/signature_test.go
index 480bd77..f6197c0 100644
--- a/runtime/internal/rpc/test/signature_test.go
+++ b/runtime/internal/rpc/test/signature_test.go
@@ -60,7 +60,7 @@
}
func TestMethodSignature(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
ep, stop, err := startSigServer(ctx, sigImpl{})
if err != nil {
@@ -106,7 +106,7 @@
}
func TestSignature(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
ep, stop, err := startSigServer(ctx, sigImpl{})
if err != nil {
diff --git a/runtime/internal/rpc/test/v23_internal_test.go b/runtime/internal/rpc/test/v23_internal_test.go
index 0862cd2..d7274da 100644
--- a/runtime/internal/rpc/test/v23_internal_test.go
+++ b/runtime/internal/rpc/test/v23_internal_test.go
@@ -4,31 +4,19 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package test
-import "fmt"
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/modules"
-
-func init() {
- modules.RegisterChild("rootMT", ``, rootMT)
- modules.RegisterChild("echoServer", ``, echoServer)
- modules.RegisterChild("echoClient", ``, echoClient)
- modules.RegisterChild("childPing", ``, childPing)
- modules.RegisterChild("proxyServer", ``, proxyServer)
-}
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+)
func TestMain(m *testing.M) {
test.Init()
- if modules.IsModulesChildProcess() {
- if err := modules.Dispatch(); err != nil {
- fmt.Fprintf(os.Stderr, "modules.Dispatch failed: %v\n", err)
- os.Exit(1)
- }
- return
- }
+ modules.DispatchAndExitIfChild()
os.Exit(m.Run())
}
diff --git a/runtime/internal/rpc/testutil_test.go b/runtime/internal/rpc/testutil_test.go
index 4f298dc..9a2e8f3 100644
--- a/runtime/internal/rpc/testutil_test.go
+++ b/runtime/internal/rpc/testutil_test.go
@@ -79,7 +79,7 @@
}
func initForTest() (*context.T, v23.Shutdown) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
ctx, err := ivtrace.Init(ctx, flags.VtraceFlags{})
if err != nil {
panic(err)
diff --git a/runtime/internal/rpc/v23_test.go b/runtime/internal/rpc/v23_test.go
index b874fc4..fac4210 100644
--- a/runtime/internal/rpc/v23_test.go
+++ b/runtime/internal/rpc/v23_test.go
@@ -4,27 +4,19 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package rpc_test
-import "fmt"
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/modules"
-
-func init() {
- modules.RegisterChild("rootMountTable", ``, rootMountTable)
-}
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+)
func TestMain(m *testing.M) {
test.Init()
- if modules.IsModulesChildProcess() {
- if err := modules.Dispatch(); err != nil {
- fmt.Fprintf(os.Stderr, "modules.Dispatch failed: %v\n", err)
- os.Exit(1)
- }
- return
- }
+ modules.DispatchAndExitIfChild()
os.Exit(m.Run())
}
diff --git a/runtime/internal/rt/ipc_test.go b/runtime/internal/rt/ipc_test.go
index 0bbd0ef..f14549f 100644
--- a/runtime/internal/rt/ipc_test.go
+++ b/runtime/internal/rt/ipc_test.go
@@ -99,7 +99,7 @@
}
func TestClientServerBlessings(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
var (
@@ -179,7 +179,7 @@
}
func TestServerEndpointBlessingNames(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
ctx, _ = v23.WithPrincipal(ctx, testutil.NewPrincipal("default"))
@@ -272,7 +272,7 @@
}
func TestServerDischarges(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
var (
diff --git a/runtime/internal/rt/mgmt_test.go b/runtime/internal/rt/mgmt_test.go
index 73860e5..0a0d49d 100644
--- a/runtime/internal/rt/mgmt_test.go
+++ b/runtime/internal/rt/mgmt_test.go
@@ -6,7 +6,6 @@
import (
"fmt"
- "io"
"os"
"reflect"
"strings"
@@ -30,16 +29,10 @@
//go:generate v23 test generate
-const (
- noWaitersCmd = "noWaiters"
- forceStopCmd = "forceStop"
- appCmd = "app"
-)
-
// TestBasic verifies that the basic plumbing works: LocalStop calls result in
// stop messages being sent on the channel passed to WaitForStop.
func TestBasic(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
m := v23.GetAppCycle(ctx)
@@ -61,7 +54,7 @@
// TestMultipleWaiters verifies that the plumbing works with more than one
// registered wait channel.
func TestMultipleWaiters(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
m := v23.GetAppCycle(ctx)
@@ -84,7 +77,7 @@
// channel is not being drained: once the channel's buffer fills up, future
// Stops become no-ops.
func TestMultipleStops(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
m := v23.GetAppCycle(ctx)
@@ -103,17 +96,17 @@
}
}
-func noWaiters(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- ctx, shutdown := test.InitForTest()
+var noWaiters = modules.Register(func(env *modules.Env, args ...string) error {
+ ctx, shutdown := test.V23Init()
defer shutdown()
m := v23.GetAppCycle(ctx)
- fmt.Fprintf(stdout, "ready\n")
- modules.WaitForEOF(stdin)
+ fmt.Fprintf(env.Stdout, "ready\n")
+ modules.WaitForEOF(env.Stdin)
m.Stop()
os.Exit(42) // This should not be reached.
return nil
-}
+}, "noWaiters")
// TestNoWaiters verifies that the child process exits in the absence of any
// wait channel being registered with its runtime.
@@ -123,7 +116,7 @@
t.Fatalf("unexpected error: %s", err)
}
defer sh.Cleanup(os.Stderr, os.Stderr)
- h, err := sh.Start(noWaitersCmd, nil)
+ h, err := sh.Start(nil, noWaiters)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -134,18 +127,18 @@
}
}
-func forceStop(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- ctx, shutdown := test.InitForTest()
+var forceStop = modules.Register(func(env *modules.Env, args ...string) error {
+ ctx, shutdown := test.V23Init()
defer shutdown()
m := v23.GetAppCycle(ctx)
- fmt.Fprintf(stdout, "ready\n")
- modules.WaitForEOF(stdin)
+ fmt.Fprintf(env.Stdout, "ready\n")
+ modules.WaitForEOF(env.Stdin)
m.WaitForStop(make(chan string, 1))
m.ForceStop()
os.Exit(42) // This should not be reached.
return nil
-}
+}, "forceStop")
// TestForceStop verifies that ForceStop causes the child process to exit
// immediately.
@@ -155,7 +148,7 @@
t.Fatalf("unexpected error: %s", err)
}
defer sh.Cleanup(os.Stderr, os.Stderr)
- h, err := sh.Start(forceStopCmd, nil)
+ h, err := sh.Start(nil, forceStop)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -184,7 +177,7 @@
// TestProgress verifies that the ticker update/track logic works for a single
// tracker.
func TestProgress(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
m := v23.GetAppCycle(ctx)
m.AdvanceGoal(50)
@@ -216,7 +209,7 @@
// works for more than one tracker. It also ensures that the runtime doesn't
// block when the tracker channels are full.
func TestProgressMultipleTrackers(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
m := v23.GetAppCycle(ctx)
// ch1 is 1-buffered, ch2 is 2-buffered.
@@ -250,21 +243,21 @@
}
}
-func app(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- ctx, shutdown := test.InitForTest()
+var app = modules.Register(func(env *modules.Env, args ...string) error {
+ ctx, shutdown := test.V23Init()
defer shutdown()
m := v23.GetAppCycle(ctx)
ch := make(chan string, 1)
m.WaitForStop(ch)
- fmt.Fprintf(stdout, "Got %s\n", <-ch)
+ fmt.Fprintf(env.Stdout, "Got %s\n", <-ch)
m.AdvanceGoal(10)
- fmt.Fprintf(stdout, "Doing some work\n")
+ fmt.Fprintf(env.Stdout, "Doing some work\n")
m.AdvanceProgress(2)
- fmt.Fprintf(stdout, "Doing some more work\n")
+ fmt.Fprintf(env.Stdout, "Doing some more work\n")
m.AdvanceProgress(5)
return nil
-}
+}, "app")
type configServer struct {
ch chan<- string
@@ -296,7 +289,7 @@
}
func setupRemoteAppCycleMgr(t *testing.T) (*context.T, modules.Handle, appcycle.AppCycleClientMethods, func()) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
configServer, configServiceName, ch := createConfigServer(t, ctx)
sh, err := modules.NewShell(ctx, v23.GetPrincipal(ctx), testing.Verbose(), t)
@@ -306,7 +299,7 @@
sh.SetConfigKey(mgmt.ParentNameConfigKey, configServiceName)
sh.SetConfigKey(mgmt.ProtocolConfigKey, "tcp")
sh.SetConfigKey(mgmt.AddressConfigKey, "127.0.0.1:0")
- h, err := sh.Start("app", nil)
+ h, err := sh.Start(nil, app)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
diff --git a/runtime/internal/rt/rt_test.go b/runtime/internal/rt/rt_test.go
index 3e53548..b3b3e29 100644
--- a/runtime/internal/rt/rt_test.go
+++ b/runtime/internal/rt/rt_test.go
@@ -6,7 +6,6 @@
import (
"fmt"
- "io"
"io/ioutil"
"os"
"regexp"
@@ -53,17 +52,17 @@
}
}
-func child(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- _, shutdown := test.InitForTest()
+var child = modules.Register(func(env *modules.Env, args ...string) error {
+ _, shutdown := test.V23Init()
defer shutdown()
logger := vlog.Log
vlog.Infof("%s\n", logger)
- fmt.Fprintf(stdout, "%s\n", logger)
- modules.WaitForEOF(stdin)
- fmt.Fprintf(stdout, "done\n")
+ fmt.Fprintf(env.Stdout, "%s\n", logger)
+ modules.WaitForEOF(env.Stdin)
+ fmt.Fprintf(env.Stdout, "done\n")
return nil
-}
+}, "child")
func TestInitArgs(t *testing.T) {
sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
@@ -71,7 +70,7 @@
t.Fatalf("unexpected error: %s", err)
}
defer sh.Cleanup(os.Stderr, os.Stderr)
- h, err := sh.Start("child", nil, "--logtostderr=true", "--vmodule=*=3", "--", "foobar")
+ h, err := sh.Start(nil, child, "--logtostderr=true", "--vmodule=*=3", "--", "foobar")
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -121,40 +120,40 @@
return dir
}
-func principal(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- ctx, shutdown := test.InitForTest()
+var principal = modules.Register(func(env *modules.Env, args ...string) error {
+ ctx, shutdown := test.V23Init()
defer shutdown()
p := v23.GetPrincipal(ctx)
if err := validatePrincipal(p); err != nil {
return err
}
- fmt.Fprintf(stdout, "DEFAULT_BLESSING=%s\n", defaultBlessing(p))
+ fmt.Fprintf(env.Stdout, "DEFAULT_BLESSING=%s\n", defaultBlessing(p))
return nil
-}
+}, "principal")
// Runner runs a principal as a subprocess and reports back with its
// own security info and it's childs.
-func runner(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- ctx, shutdown := test.InitForTest()
+var runner = modules.Register(func(env *modules.Env, args ...string) error {
+ ctx, shutdown := test.V23Init()
defer shutdown()
p := v23.GetPrincipal(ctx)
if err := validatePrincipal(p); err != nil {
return err
}
- fmt.Fprintf(stdout, "RUNNER_DEFAULT_BLESSING=%v\n", defaultBlessing(p))
+ fmt.Fprintf(env.Stdout, "RUNNER_DEFAULT_BLESSING=%v\n", defaultBlessing(p))
sh, err := modules.NewShell(ctx, p, false, nil)
if err != nil {
return err
}
- if _, err := sh.Start("principal", nil, args...); err != nil {
+ if _, err := sh.Start(nil, principal, args...); err != nil {
return err
}
// Cleanup copies the output of sh to these Writers.
- sh.Cleanup(stdout, stderr)
+ sh.Cleanup(env.Stdout, env.Stderr)
return nil
-}
+}, "runner")
func createCredentialsInDir(t *testing.T, dir string, blessing string) {
principal, err := vsecurity.CreatePersistentPrincipal(dir, nil)
@@ -186,7 +185,7 @@
// directory supplied by the environment.
credEnv := []string{ref.EnvCredentials + "=" + cdir}
- h, err := sh.Start("runner", credEnv)
+ h, err := sh.Start(credEnv, runner)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -209,7 +208,7 @@
func TestPrincipalInit(t *testing.T) {
// Collect the process' public key and error status
collect := func(sh *modules.Shell, env []string, args ...string) string {
- h, err := sh.Start("principal", env, args...)
+ h, err := sh.Start(env, principal, args...)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -234,7 +233,7 @@
}
defer sh.Cleanup(os.Stderr, os.Stderr)
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
agentSh, err := modules.NewShell(ctx, v23.GetPrincipal(ctx), testing.Verbose(), t)
diff --git a/runtime/internal/rt/runtime.go b/runtime/internal/rt/runtime.go
index 9ebfbef..1d006f4 100644
--- a/runtime/internal/rt/runtime.go
+++ b/runtime/internal/rt/runtime.go
@@ -27,6 +27,7 @@
"v.io/v23/vtrace"
"v.io/x/lib/metadata"
"v.io/x/lib/vlog"
+ "v.io/x/ref/lib/apilog"
"v.io/x/ref/lib/flags"
"v.io/x/ref/lib/stats"
_ "v.io/x/ref/lib/stats/sysstats"
@@ -94,7 +95,7 @@
}
err := vlog.ConfigureLibraryLoggerFromFlags()
- if err != nil && err != vlog.Configured {
+ if err != nil && err != vlog.ErrConfigured {
return nil, nil, nil, err
}
// We want to print out metadata only into the log files, to avoid
@@ -179,7 +180,7 @@
}
func (r *Runtime) Init(ctx *context.T) error {
- defer vlog.LogCallf("ctx=")("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(ctx)(ctx) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
return r.initMgmt(ctx)
}
@@ -214,12 +215,12 @@
}
func (*Runtime) NewEndpoint(ep string) (naming.Endpoint, error) {
- defer vlog.LogCallf("ep=%.10s...", ep)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "ep=%.10s...", ep)(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
return inaming.NewEndpoint(ep)
}
func (r *Runtime) NewServer(ctx *context.T, opts ...rpc.ServerOpt) (rpc.Server, error) {
- defer vlog.LogCallf("ctx=,opts...=%v", opts)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "opts...=%v", opts)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
// Create a new RoutingID (and StreamManager) for each server.
sm, err := newStreamManager()
if err != nil {
@@ -298,7 +299,7 @@
}
func (r *Runtime) WithNewStreamManager(ctx *context.T) (*context.T, error) {
- defer vlog.LogCallf("ctx=")("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(ctx)(ctx) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
newctx, err := r.setNewStreamManager(ctx)
if err != nil {
return ctx, err
@@ -324,7 +325,7 @@
}
func (r *Runtime) WithPrincipal(ctx *context.T, principal security.Principal) (*context.T, error) {
- defer vlog.LogCallf("ctx=,principal=")("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "principal=")(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
var err error
newctx := ctx
@@ -350,13 +351,13 @@
}
func (*Runtime) GetPrincipal(ctx *context.T) security.Principal {
- defer vlog.LogCallf("ctx=")("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(ctx)(ctx) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
p, _ := ctx.Value(principalKey).(security.Principal)
return p
}
func (r *Runtime) WithNewClient(ctx *context.T, opts ...rpc.ClientOpt) (*context.T, rpc.Client, error) {
- defer vlog.LogCallf("ctx=,opts...=%v", opts)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "opts...=%v", opts)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
otherOpts := append([]rpc.ClientOpt{}, opts...)
p, _ := ctx.Value(principalKey).(security.Principal)
@@ -383,7 +384,7 @@
}
func (*Runtime) GetClient(ctx *context.T) rpc.Client {
- defer vlog.LogCallf("ctx=")("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(ctx)(ctx) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
cl, _ := ctx.Value(clientKey).(rpc.Client)
return cl
}
@@ -405,7 +406,7 @@
}
func (r *Runtime) WithNewNamespace(ctx *context.T, roots ...string) (*context.T, namespace.T, error) {
- defer vlog.LogCallf("ctx=,roots...=%v", roots)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "roots...=%v", roots)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
newctx, ns, err := r.setNewNamespace(ctx, roots...)
if err != nil {
return ctx, nil, err
@@ -441,7 +442,7 @@
}
func (*Runtime) WithBackgroundContext(ctx *context.T) *context.T {
- defer vlog.LogCallf("ctx=")("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(ctx)(ctx) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
// Note we add an extra context with a nil value here.
// This prevents users from travelling back through the
// chain of background contexts.
@@ -463,7 +464,7 @@
}
func (*Runtime) WithReservedNameDispatcher(ctx *context.T, d rpc.Dispatcher) *context.T {
- defer vlog.LogCallf("ctx=,d=")("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "d=")(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
return context.WithValue(ctx, reservedNameKey, d)
}
diff --git a/runtime/internal/rt/shutdown_servers_test.go b/runtime/internal/rt/shutdown_servers_test.go
index 1a05535..38dd5e3 100644
--- a/runtime/internal/rt/shutdown_servers_test.go
+++ b/runtime/internal/rt/shutdown_servers_test.go
@@ -23,11 +23,6 @@
"v.io/x/ref/test/modules"
)
-func init() {
- modules.RegisterChild("simpleServerProgram", "", simpleServerProgram)
- modules.RegisterChild("complexServerProgram", "", complexServerProgram)
-}
-
type dummy struct{}
func (*dummy) Echo(*context.T, rpc.ServerCall) error { return nil }
@@ -73,9 +68,9 @@
// complex server application (with several servers, a mix of interruptible
// and blocking cleanup, and parallel and sequential cleanup execution).
// For a more typical server, see simpleServerProgram.
-func complexServerProgram(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var complexServerProgram = modules.Register(func(env *modules.Env, args ...string) error {
// Initialize the runtime. This is boilerplate.
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
// shutdown is optional, but it's a good idea to clean up, especially
// since it takes care of flushing the logs before exiting.
defer shutdown()
@@ -84,7 +79,7 @@
// commands from the parent process to simulate Stop and
// RemoteStop commands that would normally be issued from
// application code.
- defer remoteCmdLoop(ctx, stdin)()
+ defer remoteCmdLoop(ctx, env.Stdin)()
// Create a couple servers, and start serving.
server1 := makeServer(ctx)
@@ -118,9 +113,9 @@
case sig := <-sigChan:
// If the developer wants to take different actions
// depending on the type of signal, they can do it here.
- fmt.Fprintln(stdout, "Received signal", sig)
+ fmt.Fprintln(env.Stdout, "Received signal", sig)
case stop := <-stopChan:
- fmt.Fprintln(stdout, "Stop", stop)
+ fmt.Fprintln(env.Stdout, "Stop", stop)
}
// This commences the cleanup stage.
done.Done()
@@ -138,7 +133,7 @@
// This communicates to the parent test driver process in our unit test
// that this server is ready and waiting on signals or stop commands.
// It's purely an artifact of our test setup.
- fmt.Fprintln(stdout, "Ready")
+ fmt.Fprintln(env.Stdout, "Ready")
// Wait for shutdown.
done.Wait()
@@ -174,7 +169,7 @@
parallelCleanup.Add(1)
blocking.Add(1)
go func() {
- fmt.Fprintln(stdout, "Parallel blocking cleanup1")
+ fmt.Fprintln(env.Stdout, "Parallel blocking cleanup1")
blocking.Done()
parallelCleanup.Done()
}()
@@ -182,42 +177,42 @@
parallelCleanup.Add(1)
blocking.Add(1)
go func() {
- fmt.Fprintln(stdout, "Parallel blocking cleanup2")
+ fmt.Fprintln(env.Stdout, "Parallel blocking cleanup2")
blocking.Done()
parallelCleanup.Done()
}()
parallelCleanup.Add(1)
go func() {
- fmt.Fprintln(stdout, "Parallel interruptible cleanup1")
+ fmt.Fprintln(env.Stdout, "Parallel interruptible cleanup1")
parallelCleanup.Done()
}()
parallelCleanup.Add(1)
go func() {
- fmt.Fprintln(stdout, "Parallel interruptible cleanup2")
+ fmt.Fprintln(env.Stdout, "Parallel interruptible cleanup2")
parallelCleanup.Done()
}()
// Simulate two sequential cleanup steps, one blocking and one
// interruptible.
- fmt.Fprintln(stdout, "Sequential blocking cleanup")
+ fmt.Fprintln(env.Stdout, "Sequential blocking cleanup")
blocking.Wait()
close(blockingCh)
- fmt.Fprintln(stdout, "Sequential interruptible cleanup")
+ fmt.Fprintln(env.Stdout, "Sequential interruptible cleanup")
parallelCleanup.Wait()
return nil
-}
+}, "complexServerProgram")
// simpleServerProgram demonstrates the recommended way to write a typical
// simple server application (with one server and a clean shutdown triggered by
// a signal or a stop command). For an example of something more involved, see
// complexServerProgram.
-func simpleServerProgram(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var simpleServerProgram = modules.Register(func(env *modules.Env, args ...string) error {
// Initialize the runtime. This is boilerplate.
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
// Calling shutdown is optional, but it's a good idea to clean up, especially
// since it takes care of flushing the logs before exiting.
//
@@ -230,7 +225,7 @@
// commands from the parent process to simulate Stop and
// RemoteStop commands that would normally be issued from
// application code.
- defer remoteCmdLoop(ctx, stdin)()
+ defer remoteCmdLoop(ctx, env.Stdin)()
// Create a server, and start serving.
server := makeServer(ctx)
@@ -246,17 +241,17 @@
// This communicates to the parent test driver process in our unit test
// that this server is ready and waiting on signals or stop commands.
// It's purely an artifact of our test setup.
- fmt.Fprintln(stdout, "Ready")
+ fmt.Fprintln(env.Stdout, "Ready")
// Use defer for anything that should still execute even if a panic
// occurs.
- defer fmt.Fprintln(stdout, "Deferred cleanup")
+ defer fmt.Fprintln(env.Stdout, "Deferred cleanup")
// Wait for shutdown.
sig := <-waiter
// The developer could take different actions depending on the type of
// signal.
- fmt.Fprintln(stdout, "Received signal", sig)
+ fmt.Fprintln(env.Stdout, "Received signal", sig)
// Cleanup code starts here. Alternatively, these steps could be
// invoked through defer, but we list them here to make the order of
@@ -268,7 +263,7 @@
// Note, this will not execute in cases of forced shutdown
// (e.g. SIGSTOP), when the process calls os.Exit (e.g. via log.Fatal),
// or when a panic occurs.
- fmt.Fprintln(stdout, "Interruptible cleanup")
+ fmt.Fprintln(env.Stdout, "Interruptible cleanup")
return nil
-}
+}, "simpleServerProgram")
diff --git a/runtime/internal/rt/shutdown_test.go b/runtime/internal/rt/shutdown_test.go
index 85798b3..efb7aff 100644
--- a/runtime/internal/rt/shutdown_test.go
+++ b/runtime/internal/rt/shutdown_test.go
@@ -39,7 +39,7 @@
func TestSimpleServerSignal(t *testing.T) {
sh := newShell(t)
defer sh.Cleanup(os.Stdout, cstderr)
- h, _ := sh.Start("simpleServerProgram", nil)
+ h, _ := sh.Start(nil, simpleServerProgram)
h.Expect("Ready")
syscall.Kill(h.Pid(), syscall.SIGINT)
h.Expect("Received signal interrupt")
@@ -54,7 +54,7 @@
func TestSimpleServerLocalStop(t *testing.T) {
sh := newShell(t)
defer sh.Cleanup(os.Stdout, cstderr)
- h, _ := sh.Start("simpleServerProgram", nil)
+ h, _ := sh.Start(nil, simpleServerProgram)
h.Expect("Ready")
fmt.Fprintln(h.Stdin(), "stop")
h.Expect(fmt.Sprintf("Received signal %s", v23.LocalStop))
@@ -70,7 +70,7 @@
func TestSimpleServerDoubleSignal(t *testing.T) {
sh := newShell(t)
defer sh.Cleanup(os.Stdout, cstderr)
- h, _ := sh.Start("simpleServerProgram", nil)
+ h, _ := sh.Start(nil, simpleServerProgram)
h.Expect("Ready")
syscall.Kill(h.Pid(), syscall.SIGINT)
h.Expect("Received signal interrupt")
@@ -89,7 +89,7 @@
func TestSimpleServerLocalForceStop(t *testing.T) {
sh := newShell(t)
defer sh.Cleanup(os.Stdout, cstderr)
- h, _ := sh.Start("simpleServerProgram", nil)
+ h, _ := sh.Start(nil, simpleServerProgram)
h.Expect("Ready")
fmt.Fprintln(h.Stdin(), "forcestop")
h.Expect("straight exit")
@@ -107,7 +107,7 @@
func TestSimpleServerKill(t *testing.T) {
sh := newShell(t)
defer sh.Cleanup(os.Stdout, cstderr)
- h, _ := sh.Start("simpleServerProgram", nil)
+ h, _ := sh.Start(nil, simpleServerProgram)
h.Expect("Ready")
syscall.Kill(h.Pid(), syscall.SIGKILL)
err := h.Shutdown(os.Stdout, cstderr)
@@ -126,7 +126,7 @@
func TestComplexServerSignal(t *testing.T) {
sh := newShell(t)
defer sh.Cleanup(os.Stdout, cstderr)
- h, _ := sh.Start("complexServerProgram", nil)
+ h, _ := sh.Start(nil, complexServerProgram)
h.Expect("Ready")
syscall.Kill(h.Pid(), syscall.SIGINT)
h.Expect("Received signal interrupt")
@@ -147,7 +147,7 @@
func TestComplexServerLocalStop(t *testing.T) {
sh := newShell(t)
defer sh.Cleanup(os.Stdout, cstderr)
- h, _ := sh.Start("complexServerProgram", nil)
+ h, _ := sh.Start(nil, complexServerProgram)
h.Expect("Ready")
fmt.Fprintln(h.Stdin(), "stop")
@@ -173,7 +173,7 @@
func TestComplexServerDoubleSignal(t *testing.T) {
sh := newShell(t)
defer sh.Cleanup(os.Stdout, cstderr)
- h, _ := sh.Start("complexServerProgram", nil)
+ h, _ := sh.Start(nil, complexServerProgram)
h.Expect("Ready")
syscall.Kill(h.Pid(), syscall.SIGINT)
h.Expect("Received signal interrupt")
@@ -196,7 +196,7 @@
func TestComplexServerLocalForceStop(t *testing.T) {
sh := newShell(t)
defer sh.Cleanup(os.Stdout, cstderr)
- h, _ := sh.Start("complexServerProgram", nil)
+ h, _ := sh.Start(nil, complexServerProgram)
h.Expect("Ready")
fmt.Fprintln(h.Stdin(), "forcestop")
h.Expect("straight exit")
@@ -214,7 +214,7 @@
func TestComplexServerKill(t *testing.T) {
sh := newShell(t)
defer sh.Cleanup(os.Stdout, cstderr)
- h, _ := sh.Start("complexServerProgram", nil)
+ h, _ := sh.Start(nil, complexServerProgram)
h.Expect("Ready")
syscall.Kill(h.Pid(), syscall.SIGKILL)
err := h.Shutdown(os.Stdout, cstderr)
diff --git a/runtime/internal/rt/signal_test.go b/runtime/internal/rt/signal_test.go
index d84455b..7d7c466 100644
--- a/runtime/internal/rt/signal_test.go
+++ b/runtime/internal/rt/signal_test.go
@@ -18,11 +18,6 @@
"v.io/x/ref/test/modules"
)
-func init() {
- modules.RegisterChild("withRuntime", "", withRuntime)
- modules.RegisterChild("withoutRuntime", "", withoutRuntime)
-}
-
func simpleEchoProgram(stdin io.Reader, stdout io.Writer) {
fmt.Fprintf(stdout, "ready\n")
scanner := bufio.NewScanner(stdin)
@@ -32,18 +27,18 @@
modules.WaitForEOF(stdin)
}
-func withRuntime(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- _, shutdown := test.InitForTest()
+var withRuntime = modules.Register(func(env *modules.Env, args ...string) error {
+ _, shutdown := test.V23Init()
defer shutdown()
- simpleEchoProgram(stdin, stdout)
+ simpleEchoProgram(env.Stdin, env.Stdout)
return nil
-}
+}, "withRuntime")
-func withoutRuntime(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- simpleEchoProgram(stdin, stdout)
+var withoutRuntime = modules.Register(func(env *modules.Env, args ...string) error {
+ simpleEchoProgram(env.Stdin, env.Stdout)
return nil
-}
+}, "withoutRuntime")
func TestWithRuntime(t *testing.T) {
sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
@@ -51,7 +46,7 @@
t.Fatalf("unexpected error: %s", err)
}
defer sh.Cleanup(os.Stderr, os.Stderr)
- h, err := sh.Start("withRuntime", nil)
+ h, err := sh.Start(nil, withRuntime)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -72,7 +67,7 @@
defer sh.Cleanup(os.Stderr, os.Stderr)
opts := sh.DefaultStartOpts()
opts.ShutdownTimeout = 5 * time.Second
- h, err := sh.StartWithOpts(opts, nil, "withoutRuntime")
+ h, err := sh.StartWithOpts(opts, nil, withoutRuntime)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
diff --git a/runtime/internal/rt/v23_test.go b/runtime/internal/rt/v23_test.go
index 774f3c3..2145611 100644
--- a/runtime/internal/rt/v23_test.go
+++ b/runtime/internal/rt/v23_test.go
@@ -4,43 +4,19 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package rt_test
-import "fmt"
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/modules"
-
-func init() {
- modules.RegisterChild("noWaiters", ``, noWaiters)
- modules.RegisterChild("forceStop", ``, forceStop)
- modules.RegisterChild("app", ``, app)
- modules.RegisterChild("child", ``, child)
- modules.RegisterChild("principal", ``, principal)
- modules.RegisterChild("runner", `Runner runs a principal as a subprocess and reports back with its
-own security info and it's childs.`, runner)
- modules.RegisterChild("complexServerProgram", `complexServerProgram demonstrates the recommended way to write a more
-complex server application (with several servers, a mix of interruptible
-and blocking cleanup, and parallel and sequential cleanup execution).
-For a more typical server, see simpleServerProgram.`, complexServerProgram)
- modules.RegisterChild("simpleServerProgram", `simpleServerProgram demonstrates the recommended way to write a typical
-simple server application (with one server and a clean shutdown triggered by
-a signal or a stop command). For an example of something more involved, see
-complexServerProgram.`, simpleServerProgram)
- modules.RegisterChild("withRuntime", ``, withRuntime)
- modules.RegisterChild("withoutRuntime", ``, withoutRuntime)
-}
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+)
func TestMain(m *testing.M) {
test.Init()
- if modules.IsModulesChildProcess() {
- if err := modules.Dispatch(); err != nil {
- fmt.Fprintf(os.Stderr, "modules.Dispatch failed: %v\n", err)
- os.Exit(1)
- }
- return
- }
+ modules.DispatchAndExitIfChild()
os.Exit(m.Run())
}
diff --git a/runtime/internal/testing/concurrency/v23_internal_test.go b/runtime/internal/testing/concurrency/v23_internal_test.go
index e2d51cf..be5e421 100644
--- a/runtime/internal/testing/concurrency/v23_internal_test.go
+++ b/runtime/internal/testing/concurrency/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package concurrency
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/runtime/internal/testing/mocks/mocknet/mocknet_test.go b/runtime/internal/testing/mocks/mocknet/mocknet_test.go
index ccf1cf9..f038325 100644
--- a/runtime/internal/testing/mocks/mocknet/mocknet_test.go
+++ b/runtime/internal/testing/mocks/mocknet/mocknet_test.go
@@ -325,7 +325,7 @@
}
func newCtx() (*context.T, v23.Shutdown) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
return ctx, shutdown
}
diff --git a/runtime/internal/testing/mocks/mocknet/v23_internal_test.go b/runtime/internal/testing/mocks/mocknet/v23_internal_test.go
index bc46709..ec445eb 100644
--- a/runtime/internal/testing/mocks/mocknet/v23_internal_test.go
+++ b/runtime/internal/testing/mocks/mocknet/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package mocknet
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/runtime/internal/testing/mocks/naming/namespace.go b/runtime/internal/testing/mocks/naming/namespace.go
index 2b48c30..19148e0 100644
--- a/runtime/internal/testing/mocks/naming/namespace.go
+++ b/runtime/internal/testing/mocks/naming/namespace.go
@@ -16,8 +16,8 @@
"v.io/v23/security"
"v.io/v23/security/access"
"v.io/v23/verror"
- "v.io/x/lib/vlog"
+ "v.io/x/ref/lib/apilog"
inamespace "v.io/x/ref/runtime/internal/naming/namespace"
)
@@ -40,7 +40,7 @@
}
func (ns *namespaceMock) Mount(ctx *context.T, name, server string, _ time.Duration, opts ...naming.NamespaceOpt) error {
- defer vlog.LogCallf("ctx=,name=%.10s...,server=%.10s...,opts...=%v", name, server, opts)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "name=%.10s...,server=%.10s...,opts...=%v", name, server, opts)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
ns.Lock()
defer ns.Unlock()
for n, _ := range ns.mounts {
@@ -53,12 +53,23 @@
e = &naming.MountEntry{}
ns.mounts[name] = e
}
- e.Servers = append(e.Servers, naming.MountedServer{Server: server})
+
+ isdup := func(n string) bool {
+ for _, s := range e.Servers {
+ if n == s.Server {
+ return true
+ }
+ }
+ return false
+ }
+ if !isdup(server) {
+ e.Servers = append(e.Servers, naming.MountedServer{Server: server})
+ }
return nil
}
func (ns *namespaceMock) Unmount(ctx *context.T, name, server string, opts ...naming.NamespaceOpt) error {
- defer vlog.LogCallf("ctx=,name=%.10s...,server=%.10s...,opts...=%v", name, server, opts)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "name=%.10s...,server=%.10s...,opts...=%v", name, server, opts)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
ns.Lock()
defer ns.Unlock()
e := ns.mounts[name]
@@ -84,7 +95,7 @@
}
func (ns *namespaceMock) Delete(ctx *context.T, name string, removeSubtree bool, opts ...naming.NamespaceOpt) error {
- defer vlog.LogCallf("ctx=,name=%.10s...,removeSubtree=%v,opts...=%v", name, removeSubtree, opts)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "name=%.10s...,removeSubtree=%v,opts...=%v", name, removeSubtree, opts)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
ns.Lock()
defer ns.Unlock()
e := ns.mounts[name]
@@ -104,7 +115,7 @@
}
func (ns *namespaceMock) Resolve(ctx *context.T, name string, opts ...naming.NamespaceOpt) (*naming.MountEntry, error) {
- defer vlog.LogCallf("ctx=,name=%.10s...,opts...=%v", name, opts)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "name=%.10s...,opts...=%v", name, opts)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
_, name = security.SplitPatternName(name)
if address, suffix := naming.SplitAddressName(name); len(address) > 0 {
return &naming.MountEntry{
@@ -125,43 +136,43 @@
}
func (ns *namespaceMock) ResolveToMountTable(ctx *context.T, name string, opts ...naming.NamespaceOpt) (*naming.MountEntry, error) {
- defer vlog.LogCallf("ctx=,name=%.10s...,opts...=%v", name, opts)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "name=%.10s...,opts...=%v", name, opts)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
// TODO(mattr): Implement this method for tests that might need it.
panic("ResolveToMountTable not implemented")
}
func (ns *namespaceMock) FlushCacheEntry(name string) bool {
- defer vlog.LogCallf("name=%.10s...", name)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "name=%.10s...", name)(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
return false
}
func (ns *namespaceMock) CacheCtl(ctls ...naming.CacheCtl) []naming.CacheCtl {
- defer vlog.LogCallf("ctls...=%v", ctls)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "ctls...=%v", ctls)(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
return nil
}
func (ns *namespaceMock) Glob(ctx *context.T, pattern string, opts ...naming.NamespaceOpt) (chan naming.GlobReply, error) {
- defer vlog.LogCallf("ctx=,pattern=%.10s...,opts...=%v", pattern, opts)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "pattern=%.10s...,opts...=%v", pattern, opts)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
// TODO(mattr): Implement this method for tests that might need it.
panic("Glob not implemented")
}
func (ns *namespaceMock) SetRoots(...string) error {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
panic("Calling SetRoots on a mock namespace. This is not supported.")
}
func (ns *namespaceMock) Roots() []string {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
panic("Calling Roots on a mock namespace. This is not supported.")
}
func (ns *namespaceMock) GetPermissions(ctx *context.T, name string, opts ...naming.NamespaceOpt) (perms access.Permissions, version string, err error) {
- defer vlog.LogCallf("ctx=,name=%.10s...,opts...=%v", name, opts)("perms=,version=%.10s...,err=%v", &version, &err) // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "name=%.10s...,opts...=%v", name, opts)(ctx, "perms=,version=%.10s...,err=%v", &version, &err) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
panic("Calling GetPermissions on a mock namespace. This is not supported.")
}
func (ns *namespaceMock) SetPermissions(ctx *context.T, name string, perms access.Permissions, version string, opts ...naming.NamespaceOpt) error {
- defer vlog.LogCallf("ctx=,name=%.10s...,perms=,version=%.10s...,opts...=%v", name, version, opts)("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(ctx, "name=%.10s...,perms=,version=%.10s...,opts...=%v", name, version, opts)(ctx, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
panic("Calling SetPermissions on a mock namespace. This is not supported.")
}
diff --git a/runtime/internal/vtrace/store.go b/runtime/internal/vtrace/store.go
index 9c0d77b..55bf928 100644
--- a/runtime/internal/vtrace/store.go
+++ b/runtime/internal/vtrace/store.go
@@ -13,7 +13,7 @@
"v.io/v23/uniqueid"
"v.io/v23/vtrace"
- "v.io/x/lib/vlog"
+ "v.io/x/ref/lib/apilog"
"v.io/x/ref/lib/flags"
)
@@ -61,7 +61,7 @@
}
func (s *Store) ForceCollect(id uniqueid.Id) {
- defer vlog.LogCallf("id=")("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "id=")(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
s.mu.Lock()
s.forceCollectLocked(id)
s.mu.Unlock()
@@ -85,7 +85,7 @@
// Merge merges a vtrace.Response into the current store.
func (s *Store) Merge(t vtrace.Response) {
- defer vlog.LogCallf("t=")("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "t=")(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
s.mu.Lock()
defer s.mu.Unlock()
@@ -161,7 +161,7 @@
// TraceRecords returns TraceRecords for all traces saved in the store.
func (s *Store) TraceRecords() []vtrace.TraceRecord {
- defer vlog.LogCall()() // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCall(nil)(nil) // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
s.mu.Lock()
defer s.mu.Unlock()
@@ -177,7 +177,7 @@
// TraceRecord returns a TraceRecord for a given Id. Returns
// nil if the given id is not present.
func (s *Store) TraceRecord(id uniqueid.Id) *vtrace.TraceRecord {
- defer vlog.LogCallf("id=")("") // AUTO-GENERATED, DO NOT EDIT, MUST BE FIRST STATEMENT
+ defer apilog.LogCallf(nil, "id=")(nil, "") // gologcop: DO NOT EDIT, MUST BE FIRST STATEMENT
s.mu.Lock()
defer s.mu.Unlock()
out := &vtrace.TraceRecord{}
diff --git a/runtime/internal/vtrace/vtrace_test.go b/runtime/internal/vtrace/vtrace_test.go
index 38e3df5..7e3ee2e 100644
--- a/runtime/internal/vtrace/vtrace_test.go
+++ b/runtime/internal/vtrace/vtrace_test.go
@@ -9,6 +9,7 @@
"fmt"
"strings"
"testing"
+ "time"
"v.io/v23"
"v.io/v23/context"
@@ -35,7 +36,7 @@
// initForTest initializes the vtrace runtime and starts a mounttable.
func initForTest(t *testing.T) (*context.T, v23.Shutdown, *testutil.IDProvider) {
idp := testutil.NewIDProvider("base")
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
if err := idp.Bless(v23.GetPrincipal(ctx), "alice"); err != nil {
t.Fatalf("Could not bless initial principal %v", err)
}
@@ -105,6 +106,16 @@
return nil
}
+func verifyMount(ctx *context.T, name string) error {
+ ns := v23.GetNamespace(ctx)
+ for {
+ if _, err := ns.Resolve(ctx, name); err == nil {
+ return nil
+ }
+ time.Sleep(10 * time.Millisecond)
+ }
+}
+
func runCallChain(t *testing.T, ctx *context.T, idp *testutil.IDProvider, force1, force2 bool) *vtrace.TraceRecord {
ctx, span := vtrace.WithNewSpan(ctx, "")
span.Annotate("c0-begin")
@@ -146,6 +157,9 @@
}
c.forceCollect = f
out = append(out, c)
+ // Make sure the server is mounted to avoid any retries in when StartCall
+ // is invoked in runCallChain which complicate the span comparisons.
+ verifyMount(ctx, name)
}
return out, func() {
for _, s := range out {
diff --git a/services/agent/agentlib/agent_test.go b/services/agent/agentlib/agent_test.go
index 93621a9..46170bf 100644
--- a/services/agent/agentlib/agent_test.go
+++ b/services/agent/agentlib/agent_test.go
@@ -6,7 +6,6 @@
import (
"fmt"
- "io"
"io/ioutil"
"os"
"reflect"
@@ -43,15 +42,15 @@
//go:generate v23 test generate
-func getPrincipalAndHang(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- ctx, shutdown := test.InitForTest()
+var getPrincipalAndHang = modules.Register(func(env *modules.Env, args ...string) error {
+ ctx, shutdown := test.V23Init()
defer shutdown()
p := v23.GetPrincipal(ctx)
- fmt.Fprintf(stdout, "DEFAULT_BLESSING=%s\n", p.BlessingStore().Default())
- ioutil.ReadAll(stdin)
+ fmt.Fprintf(env.Stdout, "DEFAULT_BLESSING=%s\n", p.BlessingStore().Default())
+ ioutil.ReadAll(env.Stdin)
return nil
-}
+}, "getPrincipalAndHang")
func newAgent(ctx *context.T, endpoint string, cached bool) (security.Principal, error) {
ep, err := v23.NewEndpoint(endpoint)
@@ -98,7 +97,7 @@
}
func TestAgent(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
var (
@@ -157,7 +156,7 @@
}
func TestAgentShutdown(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
// This starts an agent
sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
@@ -165,7 +164,7 @@
t.Fatal(err)
}
// The child process will connect to the agent
- h, err := sh.Start("getPrincipalAndHang", nil)
+ h, err := sh.Start(nil, getPrincipalAndHang)
if err != nil {
t.Fatal(err)
}
@@ -235,73 +234,73 @@
}
func BenchmarkSignNoAgent(b *testing.B) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
runSignBenchmark(b, v23.GetPrincipal(ctx))
}
func BenchmarkSignCachedAgent(b *testing.B) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
runSignBenchmark(b, setupAgent(ctx, true))
}
func BenchmarkSignUncachedAgent(b *testing.B) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
runSignBenchmark(b, setupAgent(ctx, false))
}
func BenchmarkDefaultNoAgent(b *testing.B) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
runDefaultBenchmark(b, v23.GetPrincipal(ctx))
}
func BenchmarkDefaultCachedAgent(b *testing.B) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
runDefaultBenchmark(b, setupAgent(ctx, true))
}
func BenchmarkDefaultUncachedAgent(b *testing.B) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
runDefaultBenchmark(b, setupAgent(ctx, false))
}
func BenchmarkRecognizedNegativeNoAgent(b *testing.B) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
runRecognizedNegativeBenchmark(b, v23.GetPrincipal(ctx))
}
func BenchmarkRecognizedNegativeCachedAgent(b *testing.B) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
runRecognizedNegativeBenchmark(b, setupAgent(ctx, true))
}
func BenchmarkRecognizedNegativeUncachedAgent(b *testing.B) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
runRecognizedNegativeBenchmark(b, setupAgent(ctx, false))
}
func BenchmarkRecognizedNoAgent(b *testing.B) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
runRecognizedBenchmark(b, v23.GetPrincipal(ctx))
}
func BenchmarkRecognizedCachedAgent(b *testing.B) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
runRecognizedBenchmark(b, setupAgent(ctx, true))
}
func BenchmarkRecognizedUncachedAgent(b *testing.B) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
runRecognizedBenchmark(b, setupAgent(ctx, false))
}
diff --git a/services/agent/agentlib/v23_test.go b/services/agent/agentlib/v23_test.go
index 3e4061b..334393a 100644
--- a/services/agent/agentlib/v23_test.go
+++ b/services/agent/agentlib/v23_test.go
@@ -4,29 +4,21 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package agentlib_test
-import "fmt"
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/modules"
-import "v.io/x/ref/test/v23tests"
-
-func init() {
- modules.RegisterChild("getPrincipalAndHang", ``, getPrincipalAndHang)
-}
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+ "v.io/x/ref/test/v23tests"
+)
func TestMain(m *testing.M) {
test.Init()
- if modules.IsModulesChildProcess() {
- if err := modules.Dispatch(); err != nil {
- fmt.Fprintf(os.Stderr, "modules.Dispatch failed: %v\n", err)
- os.Exit(1)
- }
- return
- }
+ modules.DispatchAndExitIfChild()
cleanup := v23tests.UseSharedBinDir()
r := m.Run()
cleanup()
diff --git a/services/agent/keymgr/keymgr_test.go b/services/agent/keymgr/keymgr_test.go
index bbe20be..dd0a334 100644
--- a/services/agent/keymgr/keymgr_test.go
+++ b/services/agent/keymgr/keymgr_test.go
@@ -44,7 +44,7 @@
}
func TestNoDeviceManager(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
agent, cleanup, err := createAgent(ctx, "")
@@ -80,7 +80,7 @@
}
func TestSigning(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
path, err := ioutil.TempDir("", "agent")
@@ -147,7 +147,7 @@
}
func TestInMemorySigning(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
path, err := ioutil.TempDir("", "agent")
diff --git a/services/agent/vbecome/v23_test.go b/services/agent/vbecome/v23_test.go
index 35ff567..69f2726 100644
--- a/services/agent/vbecome/v23_test.go
+++ b/services/agent/vbecome/v23_test.go
@@ -4,16 +4,21 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package main_test
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/v23tests"
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+ "v.io/x/ref/test/v23tests"
+)
func TestMain(m *testing.M) {
test.Init()
+ modules.DispatchAndExitIfChild()
cleanup := v23tests.UseSharedBinDir()
r := m.Run()
cleanup()
diff --git a/services/application/application/impl_test.go b/services/application/application/impl_test.go
index 8f7a084..676676a 100644
--- a/services/application/application/impl_test.go
+++ b/services/application/application/impl_test.go
@@ -146,7 +146,7 @@
}
func TestApplicationClient(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
server, endpoint, err := startServer(t, ctx)
diff --git a/services/application/application/v23_internal_test.go b/services/application/application/v23_internal_test.go
index dcd0029..ae59080 100644
--- a/services/application/application/v23_internal_test.go
+++ b/services/application/application/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package main
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/services/application/applicationd/impl_test.go b/services/application/applicationd/impl_test.go
index aa53303..7284d8a 100644
--- a/services/application/applicationd/impl_test.go
+++ b/services/application/applicationd/impl_test.go
@@ -41,7 +41,7 @@
// TestInterface tests that the implementation correctly implements
// the Application interface.
func TestInterface(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
dir, prefix := "", ""
@@ -230,7 +230,7 @@
}
func TestPreserveAcrossRestarts(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
dir, prefix := "", ""
diff --git a/services/application/applicationd/perms_test.go b/services/application/applicationd/perms_test.go
index e787080..ad04614 100644
--- a/services/application/applicationd/perms_test.go
+++ b/services/application/applicationd/perms_test.go
@@ -6,7 +6,6 @@
import (
"fmt"
- "io"
"os"
"reflect"
"syscall"
@@ -19,34 +18,30 @@
"v.io/v23/services/application"
"v.io/v23/verror"
"v.io/x/lib/vlog"
-
"v.io/x/ref/lib/signals"
appd "v.io/x/ref/services/application/applicationd"
"v.io/x/ref/services/internal/servicetest"
"v.io/x/ref/services/repository"
"v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
"v.io/x/ref/test/testutil"
)
//go:generate v23 test generate
-const (
- repoCmd = "appRepository"
-)
-
-func appRepository(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var appRepository = modules.Register(func(env *modules.Env, args ...string) error {
if len(args) < 2 {
vlog.Fatalf("repository expected at least name and store arguments and optionally Permissions flags per PermissionsFromFlag")
}
publishName := args[0]
storedir := args[1]
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
- defer fmt.Fprintf(stdout, "%v terminating\n", publishName)
+ defer fmt.Fprintf(env.Stdout, "%v terminating\n", publishName)
defer vlog.VI(1).Infof("%v terminating", publishName)
server, endpoint := servicetest.NewServer(ctx)
defer server.Stop()
@@ -62,14 +57,14 @@
vlog.Fatalf("Serve(%v) failed: %v", publishName, err)
}
- fmt.Fprintf(stdout, "ready:%d\n", os.Getpid())
+ fmt.Fprintf(env.Stdout, "ready:%d\n", os.Getpid())
<-signals.ShutdownOnSignals(ctx)
return nil
-}
+}, "appRepository")
func TestApplicationUpdatePermissions(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
@@ -88,7 +83,7 @@
storedir, cleanup := servicetest.SetupRootDir(t, "application")
defer cleanup()
- nmh := servicetest.RunCommand(t, sh, nil, repoCmd, "repo", storedir)
+ nmh := servicetest.RunCommand(t, sh, nil, appRepository, "repo", storedir)
pid := servicetest.ReadPID(t, nmh)
defer syscall.Kill(pid, syscall.SIGINT)
@@ -215,7 +210,7 @@
}
func TestPerAppPermissions(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
// By default, all principals in this test will have blessings generated based
@@ -241,7 +236,7 @@
t.Fatal(err)
}
- nmh := servicetest.RunCommand(t, sh, nil, repoCmd, "repo", storedir)
+ nmh := servicetest.RunCommand(t, sh, nil, appRepository, "repo", storedir)
pid := servicetest.ReadPID(t, nmh)
defer syscall.Kill(pid, syscall.SIGINT)
diff --git a/services/application/applicationd/v23_test.go b/services/application/applicationd/v23_test.go
index f032617..fff5ec8 100644
--- a/services/application/applicationd/v23_test.go
+++ b/services/application/applicationd/v23_test.go
@@ -4,29 +4,21 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package main_test
-import "fmt"
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/modules"
-import "v.io/x/ref/test/v23tests"
-
-func init() {
- modules.RegisterChild("appRepository", ``, appRepository)
-}
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+ "v.io/x/ref/test/v23tests"
+)
func TestMain(m *testing.M) {
test.Init()
- if modules.IsModulesChildProcess() {
- if err := modules.Dispatch(); err != nil {
- fmt.Fprintf(os.Stderr, "modules.Dispatch failed: %v\n", err)
- os.Exit(1)
- }
- return
- }
+ modules.DispatchAndExitIfChild()
cleanup := v23tests.UseSharedBinDir()
r := m.Run()
cleanup()
diff --git a/services/binary/binary/impl_test.go b/services/binary/binary/impl_test.go
index 36a5c01..e4dc1a6 100644
--- a/services/binary/binary/impl_test.go
+++ b/services/binary/binary/impl_test.go
@@ -127,7 +127,7 @@
}
func TestBinaryClient(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
server, endpoint, err := startServer(t, ctx)
diff --git a/services/binary/binary/v23_internal_test.go b/services/binary/binary/v23_internal_test.go
index dcd0029..ae59080 100644
--- a/services/binary/binary/v23_internal_test.go
+++ b/services/binary/binary/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package main
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/services/binary/binaryd/v23_test.go b/services/binary/binaryd/v23_test.go
index b7aae18..5c12adf 100644
--- a/services/binary/binaryd/v23_test.go
+++ b/services/binary/binaryd/v23_test.go
@@ -4,16 +4,21 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package main_test
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/v23tests"
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+ "v.io/x/ref/test/v23tests"
+)
func TestMain(m *testing.M) {
test.Init()
+ modules.DispatchAndExitIfChild()
cleanup := v23tests.UseSharedBinDir()
r := m.Run()
cleanup()
diff --git a/services/build/build/impl_test.go b/services/build/build/impl_test.go
index c37c367..64c1479 100644
--- a/services/build/build/impl_test.go
+++ b/services/build/build/impl_test.go
@@ -70,7 +70,7 @@
}
func TestBuildClient(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
server, endpoint := startServer(ctx, t)
diff --git a/services/build/build/v23_internal_test.go b/services/build/build/v23_internal_test.go
index dcd0029..ae59080 100644
--- a/services/build/build/v23_internal_test.go
+++ b/services/build/build/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package main
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/services/build/buildd/impl_test.go b/services/build/buildd/impl_test.go
index dacf6eb..6956828 100644
--- a/services/build/buildd/impl_test.go
+++ b/services/build/buildd/impl_test.go
@@ -142,7 +142,7 @@
// TestSuccess checks that the build server successfully builds a
// package that depends on the standard Go library.
func TestSuccess(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
client := startServer(t, ctx)
@@ -177,7 +177,7 @@
// TestEmpty checks that the build server successfully builds a
// package that does not produce a binary.
func TestEmpty(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
client := startServer(t, ctx)
@@ -212,7 +212,7 @@
// TestFailure checks that the build server fails to build a package
// consisting of an empty file.
func TestFailure(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
client := startServer(t, ctx)
diff --git a/services/build/buildd/v23_test.go b/services/build/buildd/v23_test.go
index 6ec6ef0..dbfb5ac 100644
--- a/services/build/buildd/v23_test.go
+++ b/services/build/buildd/v23_test.go
@@ -4,16 +4,21 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package main_test
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/v23tests"
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+ "v.io/x/ref/test/v23tests"
+)
func TestMain(m *testing.M) {
test.Init()
+ modules.DispatchAndExitIfChild()
cleanup := v23tests.UseSharedBinDir()
r := m.Run()
cleanup()
diff --git a/services/debug/debug/v23_test.go b/services/debug/debug/v23_test.go
index b9cd380..007a5fd 100644
--- a/services/debug/debug/v23_test.go
+++ b/services/debug/debug/v23_test.go
@@ -4,16 +4,21 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package main_test
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/v23tests"
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+ "v.io/x/ref/test/v23tests"
+)
func TestMain(m *testing.M) {
test.Init()
+ modules.DispatchAndExitIfChild()
cleanup := v23tests.UseSharedBinDir()
r := m.Run()
cleanup()
diff --git a/services/debug/debuglib/dispatcher_test.go b/services/debug/debuglib/dispatcher_test.go
index d5879fb..5bcd18c 100644
--- a/services/debug/debuglib/dispatcher_test.go
+++ b/services/debug/debuglib/dispatcher_test.go
@@ -57,7 +57,7 @@
}
func TestDebugServer(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
tracedContext := func(ctx *context.T) *context.T {
diff --git a/services/debug/debuglib/v23_internal_test.go b/services/debug/debuglib/v23_internal_test.go
index cdbaeda..77006f9 100644
--- a/services/debug/debuglib/v23_internal_test.go
+++ b/services/debug/debuglib/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package debuglib
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/services/device/device/acl_impl.go b/services/device/device/acl.go
similarity index 100%
rename from services/device/device/acl_impl.go
rename to services/device/device/acl.go
diff --git a/services/device/device/acl_test.go b/services/device/device/acl_test.go
index 1a12227..4ad61bc 100644
--- a/services/device/device/acl_test.go
+++ b/services/device/device/acl_test.go
@@ -28,7 +28,7 @@
)
func TestAccessListGetCommand(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
tapes := newTapeMap()
@@ -76,7 +76,7 @@
}
func TestAccessListSetCommand(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
tapes := newTapeMap()
diff --git a/services/device/device/associate_impl.go b/services/device/device/associate.go
similarity index 100%
rename from services/device/device/associate_impl.go
rename to services/device/device/associate.go
diff --git a/services/device/device/associate_test.go b/services/device/device/associate_test.go
new file mode 100644
index 0000000..20d01d5
--- /dev/null
+++ b/services/device/device/associate_test.go
@@ -0,0 +1,165 @@
+// 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 (
+ "bytes"
+ "reflect"
+ "strings"
+ "testing"
+
+ "v.io/v23/naming"
+ "v.io/v23/services/device"
+ "v.io/x/lib/cmdline"
+ "v.io/x/ref/lib/v23cmd"
+ "v.io/x/ref/test"
+
+ cmd_device "v.io/x/ref/services/device/device"
+)
+
+func TestListCommand(t *testing.T) {
+ ctx, shutdown := test.V23Init()
+ defer shutdown()
+
+ tapes := newTapeMap()
+ server, endpoint, err := startServer(t, ctx, tapes)
+ if err != nil {
+ return
+ }
+ defer stopServer(t, server)
+
+ // Setup the command-line.
+ cmd := cmd_device.CmdRoot
+ var stdout, stderr bytes.Buffer
+ env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
+ deviceName := naming.JoinAddressName(endpoint.String(), "")
+
+ rootTape := tapes.forSuffix("")
+ // Test the 'list' command.
+ rootTape.SetResponses(ListAssociationResponse{
+ na: []device.Association{
+ {
+ "root/self",
+ "alice_self_account",
+ },
+ {
+ "root/other",
+ "alice_other_account",
+ },
+ },
+ err: nil,
+ })
+
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"associate", "list", deviceName}); err != nil {
+ t.Fatalf("%v", err)
+ }
+ if expected, got := "root/self alice_self_account\nroot/other alice_other_account", strings.TrimSpace(stdout.String()); got != expected {
+ t.Fatalf("Unexpected output from list. Got %q, expected %q", got, expected)
+ }
+ if got, expected := rootTape.Play(), []interface{}{"ListAssociations"}; !reflect.DeepEqual(expected, got) {
+ t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
+ }
+ rootTape.Rewind()
+ stdout.Reset()
+
+ // Test list with bad parameters.
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"associate", "list", deviceName, "hello"}); err == nil {
+ t.Fatalf("wrongly failed to receive a non-nil error.")
+ }
+ if got, expected := len(rootTape.Play()), 0; got != expected {
+ t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
+ }
+}
+
+func TestAddCommand(t *testing.T) {
+ ctx, shutdown := test.V23Init()
+ defer shutdown()
+
+ tapes := newTapeMap()
+ server, endpoint, err := startServer(t, ctx, tapes)
+ if err != nil {
+ return
+ }
+ defer stopServer(t, server)
+
+ // Setup the command-line.
+ cmd := cmd_device.CmdRoot
+ var stdout, stderr bytes.Buffer
+ env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
+ deviceName := naming.JoinAddressName(endpoint.String(), "")
+
+ 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("")
+ if got, expected := len(rootTape.Play()), 0; got != expected {
+ t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
+ }
+ rootTape.Rewind()
+ stdout.Reset()
+
+ rootTape.SetResponses(nil)
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"associate", "add", deviceName, "alice", "root/self"}); err != nil {
+ t.Fatalf("%v", err)
+ }
+ expected := []interface{}{
+ AddAssociationStimulus{"AssociateAccount", []string{"root/self"}, "alice"},
+ }
+ if got := rootTape.Play(); !reflect.DeepEqual(expected, got) {
+ t.Errorf("unexpected result. Got %v want %v", got, expected)
+ }
+ rootTape.Rewind()
+ stdout.Reset()
+
+ rootTape.SetResponses(nil)
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"associate", "add", deviceName, "alice", "root/other", "root/self"}); err != nil {
+ t.Fatalf("%v", err)
+ }
+ expected = []interface{}{
+ AddAssociationStimulus{"AssociateAccount", []string{"root/other", "root/self"}, "alice"},
+ }
+ if got := rootTape.Play(); !reflect.DeepEqual(expected, got) {
+ t.Errorf("unexpected result. Got %v want %v", got, expected)
+ }
+}
+
+func TestRemoveCommand(t *testing.T) {
+ ctx, shutdown := test.V23Init()
+ defer shutdown()
+
+ tapes := newTapeMap()
+ server, endpoint, err := startServer(t, ctx, tapes)
+ if err != nil {
+ return
+ }
+ defer stopServer(t, server)
+
+ // Setup the command-line.
+ cmd := cmd_device.CmdRoot
+ var stdout, stderr bytes.Buffer
+ env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
+ deviceName := naming.JoinAddressName(endpoint.String(), "")
+
+ 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("")
+ if got, expected := len(rootTape.Play()), 0; got != expected {
+ t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
+ }
+ rootTape.Rewind()
+ stdout.Reset()
+
+ rootTape.SetResponses(nil)
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"associate", "remove", deviceName, "root/self"}); err != nil {
+ t.Fatalf("%v", err)
+ }
+ expected := []interface{}{
+ AddAssociationStimulus{"AssociateAccount", []string{"root/self"}, ""},
+ }
+ if got := rootTape.Play(); !reflect.DeepEqual(expected, got) {
+ t.Errorf("unexpected result. Got %v want %v", got, expected)
+ }
+}
diff --git a/services/device/device/claim.go b/services/device/device/claim.go
new file mode 100644
index 0000000..8d65e4d
--- /dev/null
+++ b/services/device/device/claim.go
@@ -0,0 +1,67 @@
+// 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
+
+import (
+ "encoding/base64"
+ "fmt"
+
+ "v.io/v23/context"
+ "v.io/v23/options"
+ "v.io/v23/rpc"
+ "v.io/v23/security"
+ "v.io/v23/services/device"
+ "v.io/x/lib/cmdline"
+ "v.io/x/ref/lib/v23cmd"
+)
+
+var cmdClaim = &cmdline.Command{
+ Runner: v23cmd.RunnerFunc(runClaim),
+ Name: "claim",
+ Short: "Claim the device.",
+ Long: "Claim the device.",
+ ArgsName: "<device> <grant extension> <pairing token> <device publickey>",
+ ArgsLong: `
+<device> is the vanadium object name of the device manager's device service.
+
+<grant extension> is used to extend the default blessing of the
+current principal when blessing the app instance.
+
+<pairing token> is a token that the device manager expects to be replayed
+during a claim operation on the device.
+
+<device publickey> is the marshalled public key of the device manager we
+are claiming.`,
+}
+
+func runClaim(ctx *context.T, env *cmdline.Env, args []string) error {
+ if expected, max, got := 2, 4, len(args); expected > got || got > max {
+ return env.UsageErrorf("claim: incorrect number of arguments, expected atleast %d (max: %d), got %d", expected, max, got)
+ }
+ deviceName, grant := args[0], args[1]
+ var pairingToken string
+ if len(args) > 2 {
+ pairingToken = args[2]
+ }
+ var serverKeyOpts rpc.CallOpt
+ if len(args) > 3 {
+ marshalledPublicKey, err := base64.URLEncoding.DecodeString(args[3])
+ if err != nil {
+ return fmt.Errorf("Failed to base64 decode publickey: %v", err)
+ }
+ if deviceKey, err := security.UnmarshalPublicKey(marshalledPublicKey); err != nil {
+ return fmt.Errorf("Failed to unmarshal device public key:%v", err)
+ } else {
+ serverKeyOpts = options.ServerPublicKey{deviceKey}
+ }
+ }
+ // Skip server endpoint authorization since an unclaimed device might have
+ // roots that will not be recognized by the claimer.
+ if err := device.ClaimableClient(deviceName).Claim(ctx, pairingToken, &granter{extension: grant}, serverKeyOpts, options.SkipServerEndpointAuthorization{}); err != nil {
+ return err
+ }
+ fmt.Fprintln(env.Stdout, "Successfully claimed.")
+ return nil
+}
diff --git a/services/device/device/claim_test.go b/services/device/device/claim_test.go
new file mode 100644
index 0000000..f62baea
--- /dev/null
+++ b/services/device/device/claim_test.go
@@ -0,0 +1,117 @@
+// 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 (
+ "bytes"
+ "encoding/base64"
+ "reflect"
+ "strings"
+ "testing"
+
+ "v.io/v23"
+ "v.io/v23/naming"
+ "v.io/v23/verror"
+ "v.io/x/lib/cmdline"
+ "v.io/x/ref/lib/security"
+ "v.io/x/ref/lib/v23cmd"
+ "v.io/x/ref/test"
+
+ cmd_device "v.io/x/ref/services/device/device"
+)
+
+func TestClaimCommand(t *testing.T) {
+ ctx, shutdown := test.V23Init()
+ defer shutdown()
+
+ tapes := newTapeMap()
+ server, endpoint, err := startServer(t, ctx, tapes)
+ if err != nil {
+ return
+ }
+ defer stopServer(t, server)
+
+ // Setup the command-line.
+ cmd := cmd_device.CmdRoot
+ var stdout, stderr bytes.Buffer
+ env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
+ deviceName := naming.JoinAddressName(endpoint.String(), "")
+ deviceKey, err := v23.GetPrincipal(ctx).PublicKey().MarshalBinary()
+ if err != nil {
+ t.Fatalf("Failed to marshal principal public key: %v", err)
+ }
+
+ // Confirm that we correctly enforce the number of arguments.
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"claim", "nope"}); err == nil {
+ t.Fatalf("wrongly failed to receive a non-nil error.")
+ }
+ if expected, got := "ERROR: claim: incorrect number of arguments, expected atleast 2 (max: 4), got 1", strings.TrimSpace(stderr.String()); !strings.HasPrefix(got, expected) {
+ t.Fatalf("Unexpected output from claim. Got %q, expected prefix %q", got, expected)
+ }
+ stdout.Reset()
+ stderr.Reset()
+ rootTape := tapes.forSuffix("")
+ rootTape.Rewind()
+
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"claim", "nope", "nope", "nope", "nope", "nope"}); err == nil {
+ t.Fatalf("wrongly failed to receive a non-nil error.")
+ }
+ if expected, got := "ERROR: claim: incorrect number of arguments, expected atleast 2 (max: 4), got 5", strings.TrimSpace(stderr.String()); !strings.HasPrefix(got, expected) {
+ t.Fatalf("Unexpected output from claim. Got %q, expected prefix %q", got, expected)
+ }
+ stdout.Reset()
+ stderr.Reset()
+ rootTape.Rewind()
+
+ // Incorrect operation
+ var pairingToken string
+ var deviceKeyWrong []byte
+ if publicKey, _, err := security.NewPrincipalKey(); err != nil {
+ t.Fatalf("NewPrincipalKey failed: %v", err)
+ } else {
+ if deviceKeyWrong, err = publicKey.MarshalBinary(); err != nil {
+ t.Fatalf("Failed to marshal principal public key: %v", err)
+ }
+ }
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"claim", deviceName, "grant", pairingToken, base64.URLEncoding.EncodeToString(deviceKeyWrong)}); verror.ErrorID(err) != verror.ErrNotTrusted.ID {
+ t.Fatalf("wrongly failed to receive correct error on claim with incorrect device key:%v id:%v", err, verror.ErrorID(err))
+ }
+ stdout.Reset()
+ stderr.Reset()
+ rootTape.Rewind()
+
+ // Correct operation.
+ rootTape.SetResponses(nil)
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"claim", deviceName, "grant", pairingToken, base64.URLEncoding.EncodeToString(deviceKey)}); err != nil {
+ t.Fatalf("Claim(%s, %s, %s) failed: %v", deviceName, "grant", pairingToken, err)
+ }
+ if got, expected := len(rootTape.Play()), 1; got != expected {
+ t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
+ }
+ if expected, got := "Successfully claimed.", strings.TrimSpace(stdout.String()); !strings.HasPrefix(got, expected) {
+ t.Fatalf("Unexpected output from claim. Got %q, expected prefix %q", got, expected)
+ }
+ expected := []interface{}{
+ "Claim",
+ }
+ if got := rootTape.Play(); !reflect.DeepEqual(expected, got) {
+ t.Errorf("unexpected result. Got %v want %v", got, expected)
+ }
+ rootTape.Rewind()
+ stdout.Reset()
+ stderr.Reset()
+
+ // Error operation.
+ rootTape.SetResponses(verror.New(errOops, nil))
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"claim", deviceName, "grant", pairingToken}); err == nil {
+ t.Fatal("claim() failed to detect error:", err)
+ }
+ expected = []interface{}{
+ "Claim",
+ }
+ if got := rootTape.Play(); !reflect.DeepEqual(expected, got) {
+ t.Errorf("unexpected result. Got %v want %v", got, expected)
+ }
+}
diff --git a/services/device/device/debug.go b/services/device/device/debug.go
new file mode 100644
index 0000000..1ba6fc4
--- /dev/null
+++ b/services/device/device/debug.go
@@ -0,0 +1,35 @@
+// 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
+
+import (
+ "fmt"
+ "io"
+ "strings"
+
+ "v.io/v23/context"
+ "v.io/v23/services/device"
+ "v.io/x/lib/cmdline"
+)
+
+var cmdDebug = &cmdline.Command{
+ Runner: globRunner(runDebug),
+ Name: "debug",
+ Short: "Debug the device.",
+ Long: "Get internal debug information about application installations and instances.",
+ ArgsName: "<app name patterns...>",
+ ArgsLong: `
+<app name patterns...> are vanadium object names or glob name patterns corresponding to application installations and instances.`,
+}
+
+func runDebug(entry globResult, ctx *context.T, stdout, _ io.Writer) error {
+ if description, err := device.DeviceClient(entry.name).Debug(ctx); err != nil {
+ return fmt.Errorf("Debug failed: %v", err)
+ } else {
+ line := strings.Repeat("*", len(entry.name)+4)
+ fmt.Fprintf(stdout, "%s\n* %s *\n%s\n%v\n", line, entry.name, line, description)
+ }
+ return nil
+}
diff --git a/services/device/device/debug_test.go b/services/device/device/debug_test.go
new file mode 100644
index 0000000..32a7678
--- /dev/null
+++ b/services/device/device/debug_test.go
@@ -0,0 +1,54 @@
+// 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 (
+ "bytes"
+ "fmt"
+ "reflect"
+ "strings"
+ "testing"
+
+ "v.io/v23/naming"
+ "v.io/x/lib/cmdline"
+ "v.io/x/ref/lib/v23cmd"
+ "v.io/x/ref/test"
+
+ cmd_device "v.io/x/ref/services/device/device"
+)
+
+func TestDebugCommand(t *testing.T) {
+ ctx, shutdown := test.V23Init()
+ defer shutdown()
+ tapes := newTapeMap()
+ server, endpoint, err := startServer(t, ctx, tapes)
+ if err != nil {
+ return
+ }
+ defer stopServer(t, server)
+
+ cmd := cmd_device.CmdRoot
+ globName := naming.JoinAddressName(endpoint.String(), "glob")
+ appName := naming.JoinAddressName(endpoint.String(), "app")
+ rootTape, appTape := tapes.forSuffix(""), tapes.forSuffix("app")
+ rootTape.SetResponses(GlobResponse{[]string{"app"}})
+
+ var stdout, stderr bytes.Buffer
+ env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
+
+ debugMessage := "the secrets of the universe, revealed"
+ appTape.SetResponses(instanceRunning, debugMessage)
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"debug", globName}); err != nil {
+ t.Fatalf("%v", err)
+ }
+ line := strings.Repeat("*", len(appName)+4)
+ expected := fmt.Sprintf("%s\n* %s *\n%s\n%s", line, appName, line, debugMessage)
+ if got := strings.TrimSpace(stdout.String()); got != expected {
+ t.Fatalf("Unexpected output from debug. Got:\n%v\nExpected:\n%v", got, expected)
+ }
+ if got, expected := appTape.Play(), []interface{}{"Status", "Debug"}; !reflect.DeepEqual(expected, got) {
+ t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
+ }
+}
diff --git a/services/device/device/delete.go b/services/device/device/delete.go
new file mode 100644
index 0000000..faff0df
--- /dev/null
+++ b/services/device/device/delete.go
@@ -0,0 +1,37 @@
+// 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
+
+import (
+ "fmt"
+
+ "v.io/v23/context"
+ "v.io/v23/services/device"
+ "v.io/x/lib/cmdline"
+ "v.io/x/ref/lib/v23cmd"
+)
+
+var cmdDelete = &cmdline.Command{
+ Runner: v23cmd.RunnerFunc(runDelete),
+ Name: "delete",
+ Short: "Delete the given application instance.",
+ Long: "Delete the given application instance.",
+ ArgsName: "<app instance>",
+ ArgsLong: `
+<app instance> is the vanadium object name of the application instance to delete.`,
+}
+
+func runDelete(ctx *context.T, env *cmdline.Env, args []string) error {
+ if expected, got := 1, len(args); expected != got {
+ return env.UsageErrorf("delete: incorrect number of arguments, expected %d, got %d", expected, got)
+ }
+ appName := args[0]
+
+ if err := device.ApplicationClient(appName).Delete(ctx); err != nil {
+ return fmt.Errorf("Delete failed: %v", err)
+ }
+ fmt.Fprintf(env.Stdout, "Delete succeeded\n")
+ return nil
+}
diff --git a/services/device/device/delete_test.go b/services/device/device/delete_test.go
new file mode 100644
index 0000000..f1530c9
--- /dev/null
+++ b/services/device/device/delete_test.go
@@ -0,0 +1,11 @@
+// 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 "testing"
+
+func TestDeleteCommand(t *testing.T) {
+ testHelper(t, "delete", "Delete")
+}
diff --git a/services/device/device/describe.go b/services/device/device/describe.go
new file mode 100644
index 0000000..1964dbd
--- /dev/null
+++ b/services/device/device/describe.go
@@ -0,0 +1,37 @@
+// 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
+
+import (
+ "fmt"
+
+ "v.io/v23/context"
+ "v.io/v23/services/device"
+ "v.io/x/lib/cmdline"
+ "v.io/x/ref/lib/v23cmd"
+)
+
+var cmdDescribe = &cmdline.Command{
+ Runner: v23cmd.RunnerFunc(runDescribe),
+ Name: "describe",
+ Short: "Describe the device.",
+ Long: "Describe the device.",
+ ArgsName: "<device>",
+ ArgsLong: `
+<device> is the vanadium object name of the device manager's device service.`,
+}
+
+func runDescribe(ctx *context.T, env *cmdline.Env, args []string) error {
+ if expected, got := 1, len(args); expected != got {
+ return env.UsageErrorf("describe: incorrect number of arguments, expected %d, got %d", expected, got)
+ }
+ deviceName := args[0]
+ if description, err := device.DeviceClient(deviceName).Describe(ctx); err != nil {
+ return fmt.Errorf("Describe failed: %v", err)
+ } else {
+ fmt.Fprintf(env.Stdout, "%+v\n", description)
+ }
+ return nil
+}
diff --git a/services/device/device/devicemanager_mock_test.go b/services/device/device/devicemanager_mock_test.go
index 6298fbb..2d34144 100644
--- a/services/device/device/devicemanager_mock_test.go
+++ b/services/device/device/devicemanager_mock_test.go
@@ -233,7 +233,9 @@
func (*mockDeviceInvoker) Uninstall(*context.T, rpc.ServerCall) error { return nil }
-func (i *mockDeviceInvoker) Update(*context.T, rpc.ServerCall) error { return nil }
+func (mdi *mockDeviceInvoker) Update(*context.T, rpc.ServerCall) error {
+ return mdi.simpleCore("Update", "Update")
+}
func (*mockDeviceInvoker) UpdateTo(*context.T, rpc.ServerCall, string) error { return nil }
diff --git a/services/device/device/doc.go b/services/device/device/doc.go
index a476a9e..881e621 100644
--- a/services/device/device/doc.go
+++ b/services/device/device/doc.go
@@ -24,9 +24,8 @@
run Run the given application instance.
kill Kill the given application instance.
revert Revert the device manager or application
- update Update the device manager or application
- updateall Update all installations/instances of an application
- status Get application status.
+ update Update device manager or applications.
+ status Get device manager or application status.
debug Debug the device.
acl Tool for setting device manager Permissions
publish Publish the given application(s).
@@ -73,6 +72,9 @@
If set, only consider installations.
-only-instances=false
If set, only consider instances.
+ -parallelism=BYKIND
+ Specifies the level of parallelism for the handler execution. One of:
+ BYKIND,FULL,NONE
-progname=unnamed_app
Visible name of the application, used in argv[0]
-rm=false
@@ -291,52 +293,34 @@
Device update
-Update the device manager or application
+Update the device manager or application instances and installations
Usage:
- device update <object>
+ device update <app name patterns...>
-<object> is the vanadium object name of the device manager or application
-installation or instance to update.
-
-Device updateall
-
-Given a name that can refer to an app instance or app installation or app or all
-apps on a device, updates all installations and instances under that name
-
-Usage:
- device updateall <object name>
-
-<object name> is the vanadium object name to update, as follows:
-
-<devicename>/apps/apptitle/installationid/instanceid: updates the given
-instance, killing/restarting it if running
-
-<devicename>/apps/apptitle/installationid: updates the given installation and
-then all its instances
-
-<devicename>/apps/apptitle: updates all installations for the given app
-
-<devicename>/apps: updates all apps on the device
+<app name patterns...> are vanadium object names or glob name patterns
+corresponding to the device manager service, or to application installations and
+instances.
Device status
-Get the status of an application installation or instance.
+Get the status of the device manager or application instances and installations.
Usage:
- device status <app name patterns...>
+ device status <name patterns...>
-<app name patterns...> are vanadium object names or glob name patterns
-corresponding to app installations and instances.
+<name patterns...> are vanadium object names or glob name patterns corresponding
+to the device manager service, or to application installations and instances.
Device debug
-Debug the device.
+Get internal debug information about application installations and instances.
Usage:
- device debug <app name>
+ device debug <app name patterns...>
-<app name> is the vanadium object name of an app installation or instance.
+<app name patterns...> are vanadium object names or glob name patterns
+corresponding to application installations and instances.
Device acl
@@ -423,7 +407,7 @@
device ls <app name patterns...>
<app name patterns...> are vanadium object names or glob name patterns
-corresponding to app installations and instances.
+corresponding to application installations and instances.
Device help
diff --git a/services/device/device/glob.go b/services/device/device/glob.go
index ee14b37..63a0e4c 100644
--- a/services/device/device/glob.go
+++ b/services/device/device/glob.go
@@ -13,6 +13,7 @@
"sort"
"strings"
"sync"
+ "sync/atomic"
"time"
"v.io/x/lib/cmdline"
@@ -34,7 +35,7 @@
//
// Typical usage:
//
-// func myCmdHandler(entry globResult, stdout, stderr io.Writer) error {
+// func myCmdHandler(entry globResult, ctx *context.T, stdout, stderr io.Writer) error {
// output := myCmdProcessing(entry)
// fmt.Fprintf(stdout, output)
// ...
@@ -58,7 +59,7 @@
// Runner: globRunner(myCmdHandler)
// ...
// }
-type globHandler func(entry globResult, stdout, stderr io.Writer) error
+type globHandler func(entry globResult, ctx *context.T, stdout, stderr io.Writer) error
func globRunner(handler globHandler) cmdline.Runner {
return v23cmd.RunnerFunc(func(ctx *context.T, env *cmdline.Env, args []string) error {
@@ -66,10 +67,32 @@
})
}
+type objectKind int
+
+const (
+ applicationInstallationObject objectKind = iota
+ applicationInstanceObject
+ deviceServiceObject
+ sentinelObjectKind
+)
+
+var objectKinds = []objectKind{
+ applicationInstallationObject,
+ applicationInstanceObject,
+ deviceServiceObject,
+}
+
+func init() {
+ // TODO(caprita): Move to glob_test.go once that exists.
+ if len(objectKinds) != int(sentinelObjectKind) {
+ panic(fmt.Sprintf("broken invariant: mismatching number of object kinds"))
+ }
+}
+
type globResult struct {
- name string
- isInstance bool
- status device.Status
+ name string
+ status device.Status
+ kind objectKind
}
type byTypeAndName []globResult
@@ -79,20 +102,12 @@
func (a byTypeAndName) Less(i, j int) bool {
r1, r2 := a[i], a[j]
- if r1.isInstance {
- if !r2.isInstance {
- return false
- }
- } else if r2.isInstance {
- return true
+ if r1.kind != r2.kind {
+ return r1.kind < r2.kind
}
return r1.name < r2.name
}
-// TODO(caprita): Allow clients to control the parallelism. For example, for
-// updateall, we need to first update the installations before we update the
-// instances.
-
// run runs the given handler in parallel against each of the results obtained
// by globbing args, after performing filtering based on type
// (instance/installation) and state. No de-duping of results is performed.
@@ -101,13 +116,65 @@
func run(ctx *context.T, env *cmdline.Env, args []string, handler globHandler) error {
results := glob(ctx, env, args)
sort.Sort(byTypeAndName(results))
+ results = filterResults(results)
stdouts, stderrs := make([]bytes.Buffer, len(results)), make([]bytes.Buffer, len(results))
- var wg sync.WaitGroup
- errors := make(chan struct {
- name string
- err error
- }, len(results))
- for i, r := range results {
+ var errorCounter uint32 = 0
+ perResult := func(r globResult, index int) {
+ if err := handler(r, ctx, &stdouts[index], &stderrs[index]); err != nil {
+ fmt.Fprintf(&stderrs[index], "ERROR for \"%s\": %v.\n", r.name, err)
+ atomic.AddUint32(&errorCounter, 1)
+ }
+ }
+ // TODO(caprita): Add unit test logic to cover all parallelism options.
+ switch handlerParallelism {
+ case fullParallelism:
+ var wg sync.WaitGroup
+ for i, r := range results {
+ wg.Add(1)
+ go func(r globResult, i int) {
+ perResult(r, i)
+ wg.Done()
+ }(r, i)
+ }
+ wg.Wait()
+ case noParallelism:
+ for i, r := range results {
+ perResult(r, i)
+ }
+ case kindParallelism:
+ processed := 0
+ for _, k := range objectKinds {
+ var wg sync.WaitGroup
+ for i, r := range results {
+ if r.kind != k {
+ continue
+ }
+ wg.Add(1)
+ processed++
+ go func(r globResult, i int) {
+ perResult(r, i)
+ wg.Done()
+ }(r, i)
+ }
+ wg.Wait()
+ }
+ if processed != len(results) {
+ return fmt.Errorf("broken invariant: unhandled object kind")
+ }
+ }
+ for i := range results {
+ io.Copy(env.Stdout, &stdouts[i])
+ io.Copy(env.Stderr, &stderrs[i])
+ }
+ if errorCounter > 0 {
+ return fmt.Errorf("encountered a total of %d error(s)", errorCounter)
+ }
+ return nil
+}
+
+func filterResults(results []globResult) []globResult {
+ var ret []globResult
+ for _, r := range results {
switch s := r.status.(type) {
case device.StatusInstance:
if onlyInstallations || !instanceStateFilter.apply(s.Value.State) {
@@ -118,32 +185,9 @@
continue
}
}
- wg.Add(1)
- go func(r globResult, index int) {
- errors <- struct {
- name string
- err error
- }{r.name, handler(r, &stdouts[index], &stderrs[index])}
- wg.Done()
- }(r, i)
+ ret = append(ret, r)
}
- wg.Wait()
- for i := range results {
- io.Copy(env.Stdout, &stdouts[i])
- io.Copy(env.Stderr, &stderrs[i])
- }
- close(errors)
- nErrors := 0
- for e := range errors {
- if e.err != nil {
- fmt.Fprintf(env.Stderr, "ERROR for %q: %v", e.name, e.err)
- nErrors++
- }
- }
- if nErrors > 0 {
- return fmt.Errorf("encountered a total of %d errors", nErrors)
- }
- return nil
+ return ret
}
// TODO(caprita): We need to filter out debug objects under the app instances'
@@ -162,8 +206,19 @@
fmt.Fprintf(env.Stderr, "Status(%v) failed: %v\n", name, err)
return
}
- _, isInstance := status.(device.StatusInstance)
- resultsCh <- globResult{name, isInstance, status}
+ var kind objectKind
+ switch status.(type) {
+ case device.StatusInstallation:
+ kind = applicationInstallationObject
+ case device.StatusInstance:
+ kind = applicationInstanceObject
+ case device.StatusDevice:
+ kind = deviceServiceObject
+ default:
+ fmt.Fprintf(env.Stderr, "Status(%v) returned unrecognized status type %T\n", name, status)
+ return
+ }
+ resultsCh <- globResult{name, status, kind}
}
func globOne(ctx *context.T, env *cmdline.Env, pattern string, resultsCh chan<- globResult) {
@@ -291,11 +346,53 @@
return nil
}
+type parallelismFlag int
+
+const (
+ fullParallelism parallelismFlag = iota
+ noParallelism
+ kindParallelism
+ sentinelParallelismFlag
+)
+
+var parallelismStrings = map[parallelismFlag]string{
+ fullParallelism: "FULL",
+ noParallelism: "NONE",
+ kindParallelism: "BYKIND",
+}
+
+const defaultParallelism = kindParallelism
+
+func init() {
+ if len(parallelismStrings) != int(sentinelParallelismFlag) {
+ panic(fmt.Sprintf("broken invariant: mismatching number of parallelism types"))
+ }
+}
+
+func (p *parallelismFlag) String() string {
+ s, ok := parallelismStrings[*p]
+ if !ok {
+ return "UNKNOWN"
+ }
+ return s
+}
+
+func (p *parallelismFlag) Set(s string) error {
+ for k, v := range parallelismStrings {
+ if s == v {
+ *p = k
+ return nil
+ }
+ }
+ return fmt.Errorf("unrecognized parallelism type: %v", s)
+}
+
var (
instanceStateFilter instanceStateFlag
installationStateFilter installationStateFlag
onlyInstances bool
onlyInstallations bool
+ handlerParallelism parallelismFlag = defaultParallelism
)
func init() {
@@ -305,6 +402,12 @@
flag.Var(&installationStateFilter, "installation-state", fmt.Sprintf("If non-empty, specifies allowed installation states (all others installations get filtered out). The value of the flag is a comma-separated list of values from among: %v.", device.InstallationStateAll))
flag.BoolVar(&onlyInstances, "only-instances", false, "If set, only consider instances.")
flag.BoolVar(&onlyInstallations, "only-installations", false, "If set, only consider installations.")
+ var parallelismValues []string
+ for _, v := range parallelismStrings {
+ parallelismValues = append(parallelismValues, v)
+ }
+ sort.Strings(parallelismValues)
+ flag.Var(&handlerParallelism, "parallelism", "Specifies the level of parallelism for the handler execution. One of: "+strings.Join(parallelismValues, ","))
}
// ResetGlobFlags is meant for tests to restore the values of flag-configured
@@ -314,4 +417,5 @@
installationStateFilter = make(installationStateFlag)
onlyInstances = false
onlyInstallations = false
+ handlerParallelism = defaultParallelism
}
diff --git a/services/device/device/impl.go b/services/device/device/impl.go
deleted file mode 100644
index 7641456..0000000
--- a/services/device/device/impl.go
+++ /dev/null
@@ -1,339 +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
-
-import (
- "encoding/base64"
- "encoding/json"
- "fmt"
- "io"
-
- "v.io/v23"
- "v.io/v23/context"
- "v.io/v23/naming"
- "v.io/v23/options"
- "v.io/v23/rpc"
- "v.io/v23/security"
- "v.io/v23/services/application"
- "v.io/v23/services/device"
- "v.io/x/lib/cmdline"
- "v.io/x/ref/lib/v23cmd"
-)
-
-type configFlag device.Config
-
-func (c *configFlag) String() string {
- jsonConfig, _ := json.Marshal(c)
- return string(jsonConfig)
-}
-func (c *configFlag) Set(s string) error {
- if err := json.Unmarshal([]byte(s), c); err != nil {
- return fmt.Errorf("Unmarshal(%v) failed: %v", s, err)
- }
- return nil
-}
-
-var configOverride configFlag = configFlag{}
-
-type packagesFlag application.Packages
-
-func (c *packagesFlag) String() string {
- jsonPackages, _ := json.Marshal(c)
- return string(jsonPackages)
-}
-func (c *packagesFlag) Set(s string) error {
- if err := json.Unmarshal([]byte(s), c); err != nil {
- return fmt.Errorf("Unmarshal(%v) failed: %v", s, err)
- }
- return nil
-}
-
-var packagesOverride packagesFlag = packagesFlag{}
-
-func init() {
- cmdInstall.Flags.Var(&configOverride, "config", "JSON-encoded device.Config object, of the form: '{\"flag1\":\"value1\",\"flag2\":\"value2\"}'")
- cmdInstall.Flags.Var(&packagesOverride, "packages", "JSON-encoded application.Packages object, of the form: '{\"pkg1\":{\"File\":\"object name 1\"},\"pkg2\":{\"File\":\"object name 2\"}}'")
-}
-
-var cmdInstall = &cmdline.Command{
- Runner: v23cmd.RunnerFunc(runInstall),
- Name: "install",
- Short: "Install the given application.",
- Long: "Install the given application and print the name of the new installation.",
- ArgsName: "<device> <application>",
- ArgsLong: `
-<device> is the vanadium object name of the device manager's app service.
-
-<application> is the vanadium object name of the application.
-`,
-}
-
-func runInstall(ctx *context.T, env *cmdline.Env, args []string) error {
- if expected, got := 2, len(args); expected != got {
- return env.UsageErrorf("install: incorrect number of arguments, expected %d, got %d", expected, got)
- }
- deviceName, appName := args[0], args[1]
- appID, err := device.ApplicationClient(deviceName).Install(ctx, appName, device.Config(configOverride), application.Packages(packagesOverride))
- // Reset the value for any future invocations of "install" or
- // "install-local" (we run more than one command per process in unit
- // tests).
- configOverride = configFlag{}
- packagesOverride = packagesFlag{}
- if err != nil {
- return fmt.Errorf("Install failed: %v", err)
- }
- fmt.Fprintf(env.Stdout, "%s\n", naming.Join(deviceName, appID))
- return nil
-}
-
-var cmdUninstall = &cmdline.Command{
- Runner: v23cmd.RunnerFunc(runUninstall),
- Name: "uninstall",
- Short: "Uninstall the given application installation.",
- Long: "Uninstall the given application installation.",
- ArgsName: "<installation>",
- ArgsLong: `
-<installation> is the vanadium object name of the application installation to
-uninstall.
-`,
-}
-
-func runUninstall(ctx *context.T, env *cmdline.Env, args []string) error {
- if expected, got := 1, len(args); expected != got {
- return env.UsageErrorf("uninstall: incorrect number of arguments, expected %d, got %d", expected, got)
- }
- installName := args[0]
- if err := device.ApplicationClient(installName).Uninstall(ctx); err != nil {
- return fmt.Errorf("Uninstall failed: %v", err)
- }
- fmt.Fprintf(env.Stdout, "Successfully uninstalled: %q\n", installName)
- return nil
-}
-
-var cmdInstantiate = &cmdline.Command{
- Runner: v23cmd.RunnerFunc(runInstantiate),
- Name: "instantiate",
- Short: "Create an instance of the given application.",
- Long: "Create an instance of the given application, provide it with a blessing, and print the name of the new instance.",
- ArgsName: "<application installation> <grant extension>",
- ArgsLong: `
-<application installation> is the vanadium object name of the
-application installation from which to create an instance.
-
-<grant extension> is used to extend the default blessing of the
-current principal when blessing the app instance.`,
-}
-
-type granter struct {
- rpc.CallOpt
- extension string
-}
-
-func (g *granter) Grant(ctx *context.T, call security.Call) (security.Blessings, error) {
- p := call.LocalPrincipal()
- return p.Bless(call.RemoteBlessings().PublicKey(), p.BlessingStore().Default(), g.extension, security.UnconstrainedUse())
-}
-
-func runInstantiate(ctx *context.T, env *cmdline.Env, args []string) error {
- if expected, got := 2, len(args); expected != got {
- return env.UsageErrorf("instantiate: incorrect number of arguments, expected %d, got %d", expected, got)
- }
- appInstallation, grant := args[0], args[1]
-
- ctx, cancel := context.WithCancel(ctx)
- defer cancel()
- principal := v23.GetPrincipal(ctx)
-
- call, err := device.ApplicationClient(appInstallation).Instantiate(ctx)
- if err != nil {
- return fmt.Errorf("Instantiate failed: %v", err)
- }
- for call.RecvStream().Advance() {
- switch msg := call.RecvStream().Value().(type) {
- case device.BlessServerMessageInstancePublicKey:
- pubKey, err := security.UnmarshalPublicKey(msg.Value)
- if err != nil {
- return fmt.Errorf("Instantiate failed: %v", err)
- }
- // TODO(caprita,rthellend): Get rid of security.UnconstrainedUse().
- blessings, err := principal.Bless(pubKey, principal.BlessingStore().Default(), grant, security.UnconstrainedUse())
- if err != nil {
- return fmt.Errorf("Instantiate failed: %v", err)
- }
- call.SendStream().Send(device.BlessClientMessageAppBlessings{blessings})
- default:
- fmt.Fprintf(env.Stderr, "Received unexpected message: %#v\n", msg)
- }
- }
- var instanceID string
- if instanceID, err = call.Finish(); err != nil {
- return fmt.Errorf("Instantiate failed: %v", err)
- }
- fmt.Fprintf(env.Stdout, "%s\n", naming.Join(appInstallation, instanceID))
- return nil
-}
-
-var cmdClaim = &cmdline.Command{
- Runner: v23cmd.RunnerFunc(runClaim),
- Name: "claim",
- Short: "Claim the device.",
- Long: "Claim the device.",
- ArgsName: "<device> <grant extension> <pairing token> <device publickey>",
- ArgsLong: `
-<device> is the vanadium object name of the device manager's device service.
-
-<grant extension> is used to extend the default blessing of the
-current principal when blessing the app instance.
-
-<pairing token> is a token that the device manager expects to be replayed
-during a claim operation on the device.
-
-<device publickey> is the marshalled public key of the device manager we
-are claiming.`,
-}
-
-func runClaim(ctx *context.T, env *cmdline.Env, args []string) error {
- if expected, max, got := 2, 4, len(args); expected > got || got > max {
- return env.UsageErrorf("claim: incorrect number of arguments, expected atleast %d (max: %d), got %d", expected, max, got)
- }
- deviceName, grant := args[0], args[1]
- var pairingToken string
- if len(args) > 2 {
- pairingToken = args[2]
- }
- var serverKeyOpts rpc.CallOpt
- if len(args) > 3 {
- marshalledPublicKey, err := base64.URLEncoding.DecodeString(args[3])
- if err != nil {
- return fmt.Errorf("Failed to base64 decode publickey: %v", err)
- }
- if deviceKey, err := security.UnmarshalPublicKey(marshalledPublicKey); err != nil {
- return fmt.Errorf("Failed to unmarshal device public key:%v", err)
- } else {
- serverKeyOpts = options.ServerPublicKey{deviceKey}
- }
- }
- // Skip server endpoint authorization since an unclaimed device might have
- // roots that will not be recognized by the claimer.
- if err := device.ClaimableClient(deviceName).Claim(ctx, pairingToken, &granter{extension: grant}, serverKeyOpts, options.SkipServerEndpointAuthorization{}); err != nil {
- return err
- }
- fmt.Fprintln(env.Stdout, "Successfully claimed.")
- return nil
-}
-
-var cmdDescribe = &cmdline.Command{
- Runner: v23cmd.RunnerFunc(runDescribe),
- Name: "describe",
- Short: "Describe the device.",
- Long: "Describe the device.",
- ArgsName: "<device>",
- ArgsLong: `
-<device> is the vanadium object name of the device manager's device service.`,
-}
-
-func runDescribe(ctx *context.T, env *cmdline.Env, args []string) error {
- if expected, got := 1, len(args); expected != got {
- return env.UsageErrorf("describe: incorrect number of arguments, expected %d, got %d", expected, got)
- }
- deviceName := args[0]
- if description, err := device.DeviceClient(deviceName).Describe(ctx); err != nil {
- return fmt.Errorf("Describe failed: %v", err)
- } else {
- fmt.Fprintf(env.Stdout, "%+v\n", description)
- }
- return nil
-}
-
-var cmdUpdate = &cmdline.Command{
- Runner: v23cmd.RunnerFunc(runUpdate),
- Name: "update",
- Short: "Update the device manager or application",
- Long: "Update the device manager or application",
- ArgsName: "<object>",
- ArgsLong: `
-<object> is the vanadium object name of the device manager or application
-installation or instance to update.`,
-}
-
-func runUpdate(ctx *context.T, env *cmdline.Env, args []string) error {
- if expected, got := 1, len(args); expected != got {
- return env.UsageErrorf("update: incorrect number of arguments, expected %d, got %d", expected, got)
- }
- name := args[0]
- if err := device.ApplicationClient(name).Update(ctx); err != nil {
- return err
- }
- fmt.Fprintln(env.Stdout, "Update successful.")
- return nil
-}
-
-var cmdRevert = &cmdline.Command{
- Runner: v23cmd.RunnerFunc(runRevert),
- Name: "revert",
- Short: "Revert the device manager or application",
- Long: "Revert the device manager or application to its previous version",
- ArgsName: "<object>",
- ArgsLong: `
-<object> is the vanadium object name of the device manager or application
-installation to revert.`,
-}
-
-func runRevert(ctx *context.T, env *cmdline.Env, args []string) error {
- if expected, got := 1, len(args); expected != got {
- return env.UsageErrorf("revert: incorrect number of arguments, expected %d, got %d", expected, got)
- }
- deviceName := args[0]
- if err := device.ApplicationClient(deviceName).Revert(ctx); err != nil {
- return err
- }
- fmt.Fprintln(env.Stdout, "Revert successful.")
- return nil
-}
-
-var cmdDebug = &cmdline.Command{
- Runner: v23cmd.RunnerFunc(runDebug),
- Name: "debug",
- Short: "Debug the device.",
- Long: "Debug the device.",
- ArgsName: "<app name>",
- ArgsLong: `
-<app name> is the vanadium object name of an app installation or instance.`,
-}
-
-func runDebug(ctx *context.T, env *cmdline.Env, args []string) error {
- if expected, got := 1, len(args); expected != got {
- return env.UsageErrorf("debug: incorrect number of arguments, expected %d, got %d", expected, got)
- }
- appName := args[0]
- if description, err := device.DeviceClient(appName).Debug(ctx); err != nil {
- return fmt.Errorf("Debug failed: %v", err)
- } else {
- fmt.Fprintf(env.Stdout, "%v\n", description)
- }
- return nil
-}
-
-var cmdStatus = &cmdline.Command{
- Runner: globRunner(runStatus),
- Name: "status",
- Short: "Get application status.",
- Long: "Get the status of an application installation or instance.",
- ArgsName: "<app name patterns...>",
- ArgsLong: `
-<app name patterns...> are vanadium object names or glob name patterns corresponding to app installations and instances.`,
-}
-
-func runStatus(entry globResult, stdout, stderr io.Writer) error {
- switch s := entry.status.(type) {
- case device.StatusInstance:
- fmt.Fprintf(stdout, "Instance %v [State:%v,Version:%v]\n", entry.name, s.Value.State, s.Value.Version)
- case device.StatusInstallation:
- fmt.Fprintf(stdout, "Installation %v [State:%v,Version:%v]\n", entry.name, s.Value.State, s.Value.Version)
- default:
- return fmt.Errorf("Status returned unknown type: %T", s)
- }
- return nil
-}
diff --git a/services/device/device/impl_test.go b/services/device/device/impl_test.go
deleted file mode 100644
index db1bd97..0000000
--- a/services/device/device/impl_test.go
+++ /dev/null
@@ -1,556 +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 (
- "bytes"
- "encoding/base64"
- "encoding/json"
- "fmt"
- "reflect"
- "strings"
- "testing"
-
- "v.io/v23"
- "v.io/v23/naming"
- "v.io/v23/services/application"
- "v.io/v23/services/device"
- "v.io/v23/verror"
- "v.io/x/lib/cmdline"
- "v.io/x/ref/lib/security"
- "v.io/x/ref/lib/v23cmd"
- "v.io/x/ref/test"
-
- cmd_device "v.io/x/ref/services/device/device"
-)
-
-//go:generate v23 test generate
-
-func TestListCommand(t *testing.T) {
- ctx, shutdown := test.InitForTest()
- defer shutdown()
-
- tapes := newTapeMap()
- server, endpoint, err := startServer(t, ctx, tapes)
- if err != nil {
- return
- }
- defer stopServer(t, server)
-
- // Setup the command-line.
- cmd := cmd_device.CmdRoot
- var stdout, stderr bytes.Buffer
- env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
- deviceName := naming.JoinAddressName(endpoint.String(), "")
-
- rootTape := tapes.forSuffix("")
- // Test the 'list' command.
- rootTape.SetResponses(ListAssociationResponse{
- na: []device.Association{
- {
- "root/self",
- "alice_self_account",
- },
- {
- "root/other",
- "alice_other_account",
- },
- },
- err: nil,
- })
-
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"associate", "list", deviceName}); err != nil {
- t.Fatalf("%v", err)
- }
- if expected, got := "root/self alice_self_account\nroot/other alice_other_account", strings.TrimSpace(stdout.String()); got != expected {
- t.Fatalf("Unexpected output from list. Got %q, expected %q", got, expected)
- }
- if got, expected := rootTape.Play(), []interface{}{"ListAssociations"}; !reflect.DeepEqual(expected, got) {
- t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
- }
- rootTape.Rewind()
- stdout.Reset()
-
- // Test list with bad parameters.
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"associate", "list", deviceName, "hello"}); err == nil {
- t.Fatalf("wrongly failed to receive a non-nil error.")
- }
- if got, expected := len(rootTape.Play()), 0; got != expected {
- t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
- }
-}
-
-func TestAddCommand(t *testing.T) {
- ctx, shutdown := test.InitForTest()
- defer shutdown()
-
- tapes := newTapeMap()
- server, endpoint, err := startServer(t, ctx, tapes)
- if err != nil {
- return
- }
- defer stopServer(t, server)
-
- // Setup the command-line.
- cmd := cmd_device.CmdRoot
- var stdout, stderr bytes.Buffer
- env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
- deviceName := naming.JoinAddressName(endpoint.String(), "")
-
- 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("")
- if got, expected := len(rootTape.Play()), 0; got != expected {
- t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
- }
- rootTape.Rewind()
- stdout.Reset()
-
- rootTape.SetResponses(nil)
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"associate", "add", deviceName, "alice", "root/self"}); err != nil {
- t.Fatalf("%v", err)
- }
- expected := []interface{}{
- AddAssociationStimulus{"AssociateAccount", []string{"root/self"}, "alice"},
- }
- if got := rootTape.Play(); !reflect.DeepEqual(expected, got) {
- t.Errorf("unexpected result. Got %v want %v", got, expected)
- }
- rootTape.Rewind()
- stdout.Reset()
-
- rootTape.SetResponses(nil)
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"associate", "add", deviceName, "alice", "root/other", "root/self"}); err != nil {
- t.Fatalf("%v", err)
- }
- expected = []interface{}{
- AddAssociationStimulus{"AssociateAccount", []string{"root/other", "root/self"}, "alice"},
- }
- if got := rootTape.Play(); !reflect.DeepEqual(expected, got) {
- t.Errorf("unexpected result. Got %v want %v", got, expected)
- }
-}
-
-func TestRemoveCommand(t *testing.T) {
- ctx, shutdown := test.InitForTest()
- defer shutdown()
-
- tapes := newTapeMap()
- server, endpoint, err := startServer(t, ctx, tapes)
- if err != nil {
- return
- }
- defer stopServer(t, server)
-
- // Setup the command-line.
- cmd := cmd_device.CmdRoot
- var stdout, stderr bytes.Buffer
- env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
- deviceName := naming.JoinAddressName(endpoint.String(), "")
-
- 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("")
- if got, expected := len(rootTape.Play()), 0; got != expected {
- t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
- }
- rootTape.Rewind()
- stdout.Reset()
-
- rootTape.SetResponses(nil)
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"associate", "remove", deviceName, "root/self"}); err != nil {
- t.Fatalf("%v", err)
- }
- expected := []interface{}{
- AddAssociationStimulus{"AssociateAccount", []string{"root/self"}, ""},
- }
- if got := rootTape.Play(); !reflect.DeepEqual(expected, got) {
- t.Errorf("unexpected result. Got %v want %v", got, expected)
- }
-}
-
-func TestInstallCommand(t *testing.T) {
- ctx, shutdown := test.InitForTest()
- defer shutdown()
-
- tapes := newTapeMap()
- server, endpoint, err := startServer(t, ctx, tapes)
- if err != nil {
- return
- }
- defer stopServer(t, server)
-
- // Setup the command-line.
- cmd := cmd_device.CmdRoot
- var stdout, stderr bytes.Buffer
- env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
- deviceName := naming.JoinAddressName(endpoint.String(), "")
- appId := "myBestAppID"
- cfg := device.Config{"someflag": "somevalue"}
- pkg := application.Packages{"pkg": application.SignedFile{File: "somename"}}
- rootTape := tapes.forSuffix("")
- for i, c := range []struct {
- args []string
- config device.Config
- packages application.Packages
- shouldErr bool
- tapeResponse interface{}
- expectedTape interface{}
- }{
- {
- []string{"blech"},
- nil,
- nil,
- true,
- nil,
- nil,
- },
- {
- []string{"blech1", "blech2", "blech3", "blech4"},
- nil,
- nil,
- true,
- nil,
- nil,
- },
- {
- []string{deviceName, appNameNoFetch, "not-valid-json"},
- nil,
- nil,
- true,
- nil,
- nil,
- },
- {
- []string{deviceName, appNameNoFetch},
- nil,
- nil,
- false,
- InstallResponse{appId, nil},
- InstallStimulus{"Install", appNameNoFetch, nil, nil, application.Envelope{}, nil},
- },
- {
- []string{deviceName, appNameNoFetch},
- cfg,
- pkg,
- false,
- InstallResponse{appId, nil},
- InstallStimulus{"Install", appNameNoFetch, cfg, pkg, application.Envelope{}, nil},
- },
- } {
- rootTape.SetResponses(c.tapeResponse)
- if c.config != nil {
- jsonConfig, err := json.Marshal(c.config)
- if err != nil {
- t.Fatalf("test case %d: Marshal(%v) failed: %v", i, c.config, err)
- }
- c.args = append([]string{fmt.Sprintf("--config=%s", string(jsonConfig))}, c.args...)
- }
- if c.packages != nil {
- jsonPackages, err := json.Marshal(c.packages)
- if err != nil {
- t.Fatalf("test case %d: Marshal(%v) failed: %v", i, c.packages, err)
- }
- c.args = append([]string{fmt.Sprintf("--packages=%s", string(jsonPackages))}, c.args...)
- }
- c.args = append([]string{"install"}, c.args...)
- err := v23cmd.ParseAndRunForTest(cmd, ctx, env, c.args)
- if c.shouldErr {
- if err == nil {
- t.Fatalf("test case %d: wrongly failed to receive a non-nil error.", i)
- }
- if got, expected := len(rootTape.Play()), 0; got != expected {
- t.Errorf("test case %d: invalid call sequence. Got %v, want %v", i, got, expected)
- }
- } else {
- if err != nil {
- t.Fatalf("test case %d: %v", i, err)
- }
- if expected, got := naming.Join(deviceName, appId), strings.TrimSpace(stdout.String()); got != expected {
- t.Fatalf("test case %d: Unexpected output from Install. Got %q, expected %q", i, got, expected)
- }
- if got, expected := rootTape.Play(), []interface{}{c.expectedTape}; !reflect.DeepEqual(expected, got) {
- t.Errorf("test case %d: invalid call sequence. Got %#v, want %#v", i, got, expected)
- }
- }
- rootTape.Rewind()
- stdout.Reset()
- }
-}
-
-func TestClaimCommand(t *testing.T) {
- ctx, shutdown := test.InitForTest()
- defer shutdown()
-
- tapes := newTapeMap()
- server, endpoint, err := startServer(t, ctx, tapes)
- if err != nil {
- return
- }
- defer stopServer(t, server)
-
- // Setup the command-line.
- cmd := cmd_device.CmdRoot
- var stdout, stderr bytes.Buffer
- env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
- deviceName := naming.JoinAddressName(endpoint.String(), "")
- deviceKey, err := v23.GetPrincipal(ctx).PublicKey().MarshalBinary()
- if err != nil {
- t.Fatalf("Failed to marshal principal public key: %v", err)
- }
-
- // Confirm that we correctly enforce the number of arguments.
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"claim", "nope"}); err == nil {
- t.Fatalf("wrongly failed to receive a non-nil error.")
- }
- if expected, got := "ERROR: claim: incorrect number of arguments, expected atleast 2 (max: 4), got 1", strings.TrimSpace(stderr.String()); !strings.HasPrefix(got, expected) {
- t.Fatalf("Unexpected output from claim. Got %q, expected prefix %q", got, expected)
- }
- stdout.Reset()
- stderr.Reset()
- rootTape := tapes.forSuffix("")
- rootTape.Rewind()
-
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"claim", "nope", "nope", "nope", "nope", "nope"}); err == nil {
- t.Fatalf("wrongly failed to receive a non-nil error.")
- }
- if expected, got := "ERROR: claim: incorrect number of arguments, expected atleast 2 (max: 4), got 5", strings.TrimSpace(stderr.String()); !strings.HasPrefix(got, expected) {
- t.Fatalf("Unexpected output from claim. Got %q, expected prefix %q", got, expected)
- }
- stdout.Reset()
- stderr.Reset()
- rootTape.Rewind()
-
- // Incorrect operation
- var pairingToken string
- var deviceKeyWrong []byte
- if publicKey, _, err := security.NewPrincipalKey(); err != nil {
- t.Fatalf("NewPrincipalKey failed: %v", err)
- } else {
- if deviceKeyWrong, err = publicKey.MarshalBinary(); err != nil {
- t.Fatalf("Failed to marshal principal public key: %v", err)
- }
- }
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"claim", deviceName, "grant", pairingToken, base64.URLEncoding.EncodeToString(deviceKeyWrong)}); verror.ErrorID(err) != verror.ErrNotTrusted.ID {
- t.Fatalf("wrongly failed to receive correct error on claim with incorrect device key:%v id:%v", err, verror.ErrorID(err))
- }
- stdout.Reset()
- stderr.Reset()
- rootTape.Rewind()
-
- // Correct operation.
- rootTape.SetResponses(nil)
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"claim", deviceName, "grant", pairingToken, base64.URLEncoding.EncodeToString(deviceKey)}); err != nil {
- t.Fatalf("Claim(%s, %s, %s) failed: %v", deviceName, "grant", pairingToken, err)
- }
- if got, expected := len(rootTape.Play()), 1; got != expected {
- t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
- }
- if expected, got := "Successfully claimed.", strings.TrimSpace(stdout.String()); !strings.HasPrefix(got, expected) {
- t.Fatalf("Unexpected output from claim. Got %q, expected prefix %q", got, expected)
- }
- expected := []interface{}{
- "Claim",
- }
- if got := rootTape.Play(); !reflect.DeepEqual(expected, got) {
- t.Errorf("unexpected result. Got %v want %v", got, expected)
- }
- rootTape.Rewind()
- stdout.Reset()
- stderr.Reset()
-
- // Error operation.
- rootTape.SetResponses(verror.New(errOops, nil))
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"claim", deviceName, "grant", pairingToken}); err == nil {
- t.Fatal("claim() failed to detect error:", err)
- }
- expected = []interface{}{
- "Claim",
- }
- if got := rootTape.Play(); !reflect.DeepEqual(expected, got) {
- t.Errorf("unexpected result. Got %v want %v", got, expected)
- }
-}
-
-func TestInstantiateCommand(t *testing.T) {
- ctx, shutdown := test.InitForTest()
- defer shutdown()
-
- tapes := newTapeMap()
- server, endpoint, err := startServer(t, ctx, tapes)
- if err != nil {
- return
- }
- defer stopServer(t, server)
-
- // Setup the command-line.
- cmd := cmd_device.CmdRoot
- var stdout, stderr bytes.Buffer
- env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
- appName := naming.JoinAddressName(endpoint.String(), "")
-
- // Confirm that we correctly enforce the number of arguments.
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"instantiate", "nope"}); err == nil {
- t.Fatalf("wrongly failed to receive a non-nil error.")
- }
- if expected, got := "ERROR: instantiate: incorrect number of arguments, expected 2, got 1", strings.TrimSpace(stderr.String()); !strings.HasPrefix(got, expected) {
- t.Fatalf("Unexpected output from instantiate. Got %q, expected prefix %q", got, expected)
- }
- stdout.Reset()
- stderr.Reset()
- rootTape := tapes.forSuffix("")
- rootTape.Rewind()
-
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"instantiate", "nope", "nope", "nope"}); err == nil {
- t.Fatalf("wrongly failed to receive a non-nil error.")
- }
- if expected, got := "ERROR: instantiate: incorrect number of arguments, expected 2, got 3", strings.TrimSpace(stderr.String()); !strings.HasPrefix(got, expected) {
- t.Fatalf("Unexpected output from instantiate. Got %q, expected prefix %q", got, expected)
- }
- stdout.Reset()
- stderr.Reset()
- rootTape.Rewind()
-
- // Correct operation.
- rootTape.SetResponses(InstantiateResponse{
- err: nil,
- instanceID: "app1",
- })
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"instantiate", appName, "grant"}); err != nil {
- t.Fatalf("instantiate %s %s failed: %v", appName, "grant", err)
- }
-
- b := new(bytes.Buffer)
- fmt.Fprintf(b, "%s", appName+"/app1")
- if expected, got := b.String(), strings.TrimSpace(stdout.String()); !strings.HasPrefix(got, expected) {
- t.Fatalf("Unexpected output from instantiate. Got %q, expected prefix %q", got, expected)
- }
- expected := []interface{}{
- "Instantiate",
- }
- if got := rootTape.Play(); !reflect.DeepEqual(expected, got) {
- t.Errorf("unexpected result. Got %v want %v", got, expected)
- }
- rootTape.Rewind()
- stdout.Reset()
- stderr.Reset()
-
- // Error operation.
- rootTape.SetResponses(InstantiateResponse{
- verror.New(errOops, nil),
- "",
- })
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"instantiate", appName, "grant"}); err == nil {
- t.Fatalf("instantiate failed to detect error")
- }
- expected = []interface{}{
- "Instantiate",
- }
- if got := rootTape.Play(); !reflect.DeepEqual(expected, got) {
- t.Errorf("unexpected result. Got %v want %v", got, expected)
- }
-}
-
-func TestDebugCommand(t *testing.T) {
- ctx, shutdown := test.InitForTest()
- defer shutdown()
- tapes := newTapeMap()
- server, endpoint, err := startServer(t, ctx, tapes)
- if err != nil {
- return
- }
- defer stopServer(t, server)
- // Setup the command-line.
- cmd := cmd_device.CmdRoot
- var stdout, stderr bytes.Buffer
- env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
- appName := naming.JoinAddressName(endpoint.String(), "")
-
- debugMessage := "the secrets of the universe, revealed"
- rootTape := tapes.forSuffix("")
- rootTape.SetResponses(debugMessage)
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"debug", appName}); err != nil {
- t.Fatalf("%v", err)
- }
- if expected, got := debugMessage, strings.TrimSpace(stdout.String()); got != expected {
- t.Fatalf("Unexpected output from debug. Got %q, expected %q", got, expected)
- }
- if got, expected := rootTape.Play(), []interface{}{"Debug"}; !reflect.DeepEqual(expected, got) {
- t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
- }
-}
-
-var (
- installationUninstalled = device.StatusInstallation{device.InstallationStatus{
- State: device.InstallationStateUninstalled,
- Version: "director's cut",
- }}
- installationActive = device.StatusInstallation{device.InstallationStatus{
- State: device.InstallationStateActive,
- Version: "extended cut",
- }}
- instanceUpdating = device.StatusInstance{device.InstanceStatus{
- State: device.InstanceStateUpdating,
- Version: "theatrical version",
- }}
- instanceRunning = device.StatusInstance{device.InstanceStatus{
- State: device.InstanceStateRunning,
- Version: "special edition",
- }}
- instanceNotRunning = device.StatusInstance{device.InstanceStatus{
- State: device.InstanceStateNotRunning,
- Version: "special edition",
- }}
-)
-
-func TestStatusCommand(t *testing.T) {
- ctx, shutdown := test.InitForTest()
- defer shutdown()
- tapes := newTapeMap()
- server, endpoint, err := startServer(t, ctx, tapes)
- if err != nil {
- return
- }
- defer stopServer(t, server)
-
- cmd := cmd_device.CmdRoot
- globName := naming.JoinAddressName(endpoint.String(), "glob")
- appName := naming.JoinAddressName(endpoint.String(), "app")
-
- rootTape, appTape := tapes.forSuffix(""), tapes.forSuffix("app")
- for _, c := range []struct {
- tapeResponse device.Status
- expected string
- }{
- {
- installationUninstalled,
- fmt.Sprintf("Installation %v [State:Uninstalled,Version:director's cut]", appName),
- },
- {
- instanceUpdating,
- fmt.Sprintf("Instance %v [State:Updating,Version:theatrical version]", appName),
- },
- } {
- var stdout, stderr bytes.Buffer
- env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
- tapes.rewind()
- rootTape.SetResponses(GlobResponse{[]string{"app"}})
- appTape.SetResponses(c.tapeResponse)
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"status", globName}); err != nil {
- t.Errorf("%v", err)
- }
- if expected, got := c.expected, strings.TrimSpace(stdout.String()); got != expected {
- t.Errorf("Unexpected output from status. Got %q, expected %q", got, expected)
- }
- if got, expected := rootTape.Play(), []interface{}{GlobStimulus{"glob"}}; !reflect.DeepEqual(expected, got) {
- t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
- }
- if got, expected := appTape.Play(), []interface{}{"Status"}; !reflect.DeepEqual(expected, got) {
- t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
- }
- }
-}
diff --git a/services/device/device/install.go b/services/device/device/install.go
new file mode 100644
index 0000000..b9f055f
--- /dev/null
+++ b/services/device/device/install.go
@@ -0,0 +1,83 @@
+// 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
+
+import (
+ "encoding/json"
+ "fmt"
+
+ "v.io/v23/context"
+ "v.io/v23/naming"
+ "v.io/v23/services/application"
+ "v.io/v23/services/device"
+ "v.io/x/lib/cmdline"
+ "v.io/x/ref/lib/v23cmd"
+)
+
+type configFlag device.Config
+
+func (c *configFlag) String() string {
+ jsonConfig, _ := json.Marshal(c)
+ return string(jsonConfig)
+}
+func (c *configFlag) Set(s string) error {
+ if err := json.Unmarshal([]byte(s), c); err != nil {
+ return fmt.Errorf("Unmarshal(%v) failed: %v", s, err)
+ }
+ return nil
+}
+
+var configOverride configFlag = configFlag{}
+
+type packagesFlag application.Packages
+
+func (c *packagesFlag) String() string {
+ jsonPackages, _ := json.Marshal(c)
+ return string(jsonPackages)
+}
+func (c *packagesFlag) Set(s string) error {
+ if err := json.Unmarshal([]byte(s), c); err != nil {
+ return fmt.Errorf("Unmarshal(%v) failed: %v", s, err)
+ }
+ return nil
+}
+
+var packagesOverride packagesFlag = packagesFlag{}
+
+var cmdInstall = &cmdline.Command{
+ Runner: v23cmd.RunnerFunc(runInstall),
+ Name: "install",
+ Short: "Install the given application.",
+ Long: "Install the given application and print the name of the new installation.",
+ ArgsName: "<device> <application>",
+ ArgsLong: `
+<device> is the vanadium object name of the device manager's app service.
+
+<application> is the vanadium object name of the application.
+`,
+}
+
+func init() {
+ cmdInstall.Flags.Var(&configOverride, "config", "JSON-encoded device.Config object, of the form: '{\"flag1\":\"value1\",\"flag2\":\"value2\"}'")
+ cmdInstall.Flags.Var(&packagesOverride, "packages", "JSON-encoded application.Packages object, of the form: '{\"pkg1\":{\"File\":\"object name 1\"},\"pkg2\":{\"File\":\"object name 2\"}}'")
+}
+
+func runInstall(ctx *context.T, env *cmdline.Env, args []string) error {
+ if expected, got := 2, len(args); expected != got {
+ return env.UsageErrorf("install: incorrect number of arguments, expected %d, got %d", expected, got)
+ }
+ deviceName, appName := args[0], args[1]
+ appID, err := device.ApplicationClient(deviceName).Install(ctx, appName, device.Config(configOverride), application.Packages(packagesOverride))
+ // Reset the value for any future invocations of "install" or
+ // "install-local" (we run more than one command per process in unit
+ // tests).
+ configOverride = configFlag{}
+ packagesOverride = packagesFlag{}
+ if err != nil {
+ return fmt.Errorf("Install failed: %v", err)
+ }
+ fmt.Fprintf(env.Stdout, "%s\n", naming.Join(deviceName, appID))
+ return nil
+}
diff --git a/services/device/device/install_test.go b/services/device/device/install_test.go
new file mode 100644
index 0000000..216916d
--- /dev/null
+++ b/services/device/device/install_test.go
@@ -0,0 +1,132 @@
+// 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 (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "reflect"
+ "strings"
+ "testing"
+
+ "v.io/v23/naming"
+ "v.io/v23/services/application"
+ "v.io/v23/services/device"
+ "v.io/x/lib/cmdline"
+ "v.io/x/ref/lib/v23cmd"
+ "v.io/x/ref/test"
+
+ cmd_device "v.io/x/ref/services/device/device"
+)
+
+func TestInstallCommand(t *testing.T) {
+ ctx, shutdown := test.V23Init()
+ defer shutdown()
+
+ tapes := newTapeMap()
+ server, endpoint, err := startServer(t, ctx, tapes)
+ if err != nil {
+ return
+ }
+ defer stopServer(t, server)
+
+ // Setup the command-line.
+ cmd := cmd_device.CmdRoot
+ var stdout, stderr bytes.Buffer
+ env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
+ deviceName := naming.JoinAddressName(endpoint.String(), "")
+ appId := "myBestAppID"
+ cfg := device.Config{"someflag": "somevalue"}
+ pkg := application.Packages{"pkg": application.SignedFile{File: "somename"}}
+ rootTape := tapes.forSuffix("")
+ for i, c := range []struct {
+ args []string
+ config device.Config
+ packages application.Packages
+ shouldErr bool
+ tapeResponse interface{}
+ expectedTape interface{}
+ }{
+ {
+ []string{"blech"},
+ nil,
+ nil,
+ true,
+ nil,
+ nil,
+ },
+ {
+ []string{"blech1", "blech2", "blech3", "blech4"},
+ nil,
+ nil,
+ true,
+ nil,
+ nil,
+ },
+ {
+ []string{deviceName, appNameNoFetch, "not-valid-json"},
+ nil,
+ nil,
+ true,
+ nil,
+ nil,
+ },
+ {
+ []string{deviceName, appNameNoFetch},
+ nil,
+ nil,
+ false,
+ InstallResponse{appId, nil},
+ InstallStimulus{"Install", appNameNoFetch, nil, nil, application.Envelope{}, nil},
+ },
+ {
+ []string{deviceName, appNameNoFetch},
+ cfg,
+ pkg,
+ false,
+ InstallResponse{appId, nil},
+ InstallStimulus{"Install", appNameNoFetch, cfg, pkg, application.Envelope{}, nil},
+ },
+ } {
+ rootTape.SetResponses(c.tapeResponse)
+ if c.config != nil {
+ jsonConfig, err := json.Marshal(c.config)
+ if err != nil {
+ t.Fatalf("test case %d: Marshal(%v) failed: %v", i, c.config, err)
+ }
+ c.args = append([]string{fmt.Sprintf("--config=%s", string(jsonConfig))}, c.args...)
+ }
+ if c.packages != nil {
+ jsonPackages, err := json.Marshal(c.packages)
+ if err != nil {
+ t.Fatalf("test case %d: Marshal(%v) failed: %v", i, c.packages, err)
+ }
+ c.args = append([]string{fmt.Sprintf("--packages=%s", string(jsonPackages))}, c.args...)
+ }
+ c.args = append([]string{"install"}, c.args...)
+ err := v23cmd.ParseAndRunForTest(cmd, ctx, env, c.args)
+ if c.shouldErr {
+ if err == nil {
+ t.Fatalf("test case %d: wrongly failed to receive a non-nil error.", i)
+ }
+ if got, expected := len(rootTape.Play()), 0; got != expected {
+ t.Errorf("test case %d: invalid call sequence. Got %v, want %v", i, got, expected)
+ }
+ } else {
+ if err != nil {
+ t.Fatalf("test case %d: %v", i, err)
+ }
+ if expected, got := naming.Join(deviceName, appId), strings.TrimSpace(stdout.String()); got != expected {
+ t.Fatalf("test case %d: Unexpected output from Install. Got %q, expected %q", i, got, expected)
+ }
+ if got, expected := rootTape.Play(), []interface{}{c.expectedTape}; !reflect.DeepEqual(expected, got) {
+ t.Errorf("test case %d: invalid call sequence. Got %#v, want %#v", i, got, expected)
+ }
+ }
+ rootTape.Rewind()
+ stdout.Reset()
+ }
+}
diff --git a/services/device/device/instance_impl.go b/services/device/device/instance_impl.go
deleted file mode 100644
index 779f9bd..0000000
--- a/services/device/device/instance_impl.go
+++ /dev/null
@@ -1,88 +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
-
-// Commands to modify instance.
-
-import (
- "fmt"
- "time"
-
- "v.io/v23/context"
- "v.io/v23/services/device"
- "v.io/x/lib/cmdline"
- "v.io/x/ref/lib/v23cmd"
-)
-
-var cmdDelete = &cmdline.Command{
- Runner: v23cmd.RunnerFunc(runDelete),
- Name: "delete",
- Short: "Delete the given application instance.",
- Long: "Delete the given application instance.",
- ArgsName: "<app instance>",
- ArgsLong: `
-<app instance> is the vanadium object name of the application instance to delete.`,
-}
-
-func runDelete(ctx *context.T, env *cmdline.Env, args []string) error {
- if expected, got := 1, len(args); expected != got {
- return env.UsageErrorf("delete: incorrect number of arguments, expected %d, got %d", expected, got)
- }
- appName := args[0]
-
- if err := device.ApplicationClient(appName).Delete(ctx); err != nil {
- return fmt.Errorf("Delete failed: %v", err)
- }
- fmt.Fprintf(env.Stdout, "Delete succeeded\n")
- return nil
-}
-
-const killDeadline = 10 * time.Second
-
-var cmdKill = &cmdline.Command{
- Runner: v23cmd.RunnerFunc(runKill),
- Name: "kill",
- Short: "Kill the given application instance.",
- Long: "Kill the given application instance.",
- ArgsName: "<app instance>",
- ArgsLong: `
-<app instance> is the vanadium object name of the application instance to kill.`,
-}
-
-func runKill(ctx *context.T, env *cmdline.Env, args []string) error {
- if expected, got := 1, len(args); expected != got {
- return env.UsageErrorf("kill: incorrect number of arguments, expected %d, got %d", expected, got)
- }
- appName := args[0]
-
- if err := device.ApplicationClient(appName).Kill(ctx, killDeadline); err != nil {
- return fmt.Errorf("Kill failed: %v", err)
- }
- fmt.Fprintf(env.Stdout, "Kill succeeded\n")
- return nil
-}
-
-var cmdRun = &cmdline.Command{
- Runner: v23cmd.RunnerFunc(runRun),
- Name: "run",
- Short: "Run the given application instance.",
- Long: "Run the given application instance.",
- ArgsName: "<app instance>",
- ArgsLong: `
-<app instance> is the vanadium object name of the application instance to run.`,
-}
-
-func runRun(ctx *context.T, env *cmdline.Env, args []string) error {
- if expected, got := 1, len(args); expected != got {
- return env.UsageErrorf("run: incorrect number of arguments, expected %d, got %d", expected, got)
- }
- appName := args[0]
-
- if err := device.ApplicationClient(appName).Run(ctx); err != nil {
- return fmt.Errorf("Run failed: %v,\nView log with:\n debug logs read `debug glob %s/logs/STDERR-*`", err, appName)
- }
- fmt.Fprintf(env.Stdout, "Run succeeded\n")
- return nil
-}
diff --git a/services/device/device/instance_impl_test.go b/services/device/device/instance_impl_test.go
deleted file mode 100644
index 1397cca..0000000
--- a/services/device/device/instance_impl_test.go
+++ /dev/null
@@ -1,163 +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 (
- "bytes"
- "reflect"
- "strings"
- "testing"
- "time"
-
- "v.io/v23/naming"
- "v.io/v23/verror"
- "v.io/x/lib/cmdline"
- "v.io/x/ref/lib/v23cmd"
- "v.io/x/ref/test"
-
- cmd_device "v.io/x/ref/services/device/device"
-)
-
-func TestKillCommand(t *testing.T) {
- ctx, shutdown := test.InitForTest()
- defer shutdown()
-
- tapes := newTapeMap()
- server, endpoint, err := startServer(t, ctx, tapes)
- if err != nil {
- return
- }
- defer stopServer(t, server)
-
- // Setup the command-line.
- cmd := cmd_device.CmdRoot
- var stdout, stderr bytes.Buffer
- env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
- appName := naming.JoinAddressName(endpoint.String(), "appname")
-
- // Confirm that we correctly enforce the number of arguments.
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"kill"}); err == nil {
- t.Fatalf("wrongly failed to receive a non-nil error.")
- }
- if expected, got := "ERROR: kill: incorrect number of arguments, expected 1, got 0", strings.TrimSpace(stderr.String()); !strings.HasPrefix(got, expected) {
- t.Fatalf("Unexpected output from kill. Got %q, expected prefix %q", got, expected)
- }
- stdout.Reset()
- stderr.Reset()
- appTape := tapes.forSuffix("appname")
- appTape.Rewind()
-
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"kill", "nope", "nope"}); err == nil {
- t.Fatalf("wrongly failed to receive a non-nil error.")
- }
- if expected, got := "ERROR: kill: incorrect number of arguments, expected 1, got 2", strings.TrimSpace(stderr.String()); !strings.HasPrefix(got, expected) {
- t.Fatalf("Unexpected output from kill. Got %q, expected prefix %q", got, expected)
- }
- stdout.Reset()
- stderr.Reset()
- appTape.Rewind()
-
- // Test the 'kill' command.
- appTape.SetResponses(nil)
-
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"kill", appName}); err != nil {
- t.Fatalf("kill failed when it shouldn't: %v", err)
- }
- if expected, got := "Kill succeeded", strings.TrimSpace(stdout.String()); got != expected {
- t.Fatalf("Unexpected output from list. Got %q, expected %q", got, expected)
- }
- expected := []interface{}{
- KillStimulus{"Kill", 10 * time.Second},
- }
- if got := appTape.Play(); !reflect.DeepEqual(expected, got) {
- t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
- }
- appTape.Rewind()
- stderr.Reset()
- stdout.Reset()
-
- // Test kill with bad parameters.
- appTape.SetResponses(verror.New(errOops, nil))
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"kill", appName}); err == nil {
- t.Fatalf("wrongly didn't receive a non-nil error.")
- }
- // expected the same.
- if got := appTape.Play(); !reflect.DeepEqual(expected, got) {
- t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
- }
-}
-
-func testHelper(t *testing.T, lower, upper string) {
- ctx, shutdown := test.InitForTest()
- defer shutdown()
-
- tapes := newTapeMap()
- server, endpoint, err := startServer(t, ctx, tapes)
- if err != nil {
- return
- }
- defer stopServer(t, server)
-
- // Setup the command-line.
- cmd := cmd_device.CmdRoot
- var stdout, stderr bytes.Buffer
- env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
- appName := naming.JoinAddressName(endpoint.String(), "appname")
-
- // Confirm that we correctly enforce the number of arguments.
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{lower}); err == nil {
- t.Fatalf("wrongly failed to receive a non-nil error.")
- }
- if expected, got := "ERROR: "+lower+": incorrect number of arguments, expected 1, got 0", strings.TrimSpace(stderr.String()); !strings.HasPrefix(got, expected) {
- t.Fatalf("Unexpected output from %s. Got %q, expected prefix %q", lower, got, expected)
- }
- stdout.Reset()
- stderr.Reset()
- appTape := tapes.forSuffix("appname")
- appTape.Rewind()
-
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{lower, "nope", "nope"}); err == nil {
- t.Fatalf("wrongly failed to receive a non-nil error.")
- }
- if expected, got := "ERROR: "+lower+": incorrect number of arguments, expected 1, got 2", strings.TrimSpace(stderr.String()); !strings.HasPrefix(got, expected) {
- t.Fatalf("Unexpected output from %s. Got %q, expected prefix %q", lower, got, expected)
- }
- stdout.Reset()
- stderr.Reset()
- appTape.Rewind()
-
- // Correct operation.
- appTape.SetResponses(nil)
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{lower, appName}); err != nil {
- t.Fatalf("%s failed when it shouldn't: %v", lower, err)
- }
- if expected, got := upper+" succeeded", strings.TrimSpace(stdout.String()); got != expected {
- t.Fatalf("Unexpected output from %s. Got %q, expected %q", lower, got, expected)
- }
- if expected, got := []interface{}{upper}, appTape.Play(); !reflect.DeepEqual(expected, got) {
- t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
- }
- appTape.Rewind()
- stderr.Reset()
- stdout.Reset()
-
- // Test list with bad parameters.
- appTape.SetResponses(verror.New(errOops, nil))
- if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{lower, appName}); err == nil {
- t.Fatalf("wrongly didn't receive a non-nil error.")
- }
- // expected the same.
- if expected, got := []interface{}{upper}, appTape.Play(); !reflect.DeepEqual(expected, got) {
- t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
- }
-}
-
-func TestDeleteCommand(t *testing.T) {
- testHelper(t, "delete", "Delete")
-}
-
-func TestRunCommand(t *testing.T) {
- testHelper(t, "run", "Run")
-}
diff --git a/services/device/device/instantiate.go b/services/device/device/instantiate.go
new file mode 100644
index 0000000..8d8ab2c
--- /dev/null
+++ b/services/device/device/instantiate.go
@@ -0,0 +1,81 @@
+// 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
+
+import (
+ "fmt"
+
+ "v.io/v23"
+ "v.io/v23/context"
+ "v.io/v23/naming"
+ "v.io/v23/rpc"
+ "v.io/v23/security"
+ "v.io/v23/services/device"
+ "v.io/x/lib/cmdline"
+ "v.io/x/ref/lib/v23cmd"
+)
+
+var cmdInstantiate = &cmdline.Command{
+ Runner: v23cmd.RunnerFunc(runInstantiate),
+ Name: "instantiate",
+ Short: "Create an instance of the given application.",
+ Long: "Create an instance of the given application, provide it with a blessing, and print the name of the new instance.",
+ ArgsName: "<application installation> <grant extension>",
+ ArgsLong: `
+<application installation> is the vanadium object name of the
+application installation from which to create an instance.
+
+<grant extension> is used to extend the default blessing of the
+current principal when blessing the app instance.`,
+}
+
+type granter struct {
+ rpc.CallOpt
+ extension string
+}
+
+func (g *granter) Grant(ctx *context.T, call security.Call) (security.Blessings, error) {
+ p := call.LocalPrincipal()
+ return p.Bless(call.RemoteBlessings().PublicKey(), p.BlessingStore().Default(), g.extension, security.UnconstrainedUse())
+}
+
+func runInstantiate(ctx *context.T, env *cmdline.Env, args []string) error {
+ if expected, got := 2, len(args); expected != got {
+ return env.UsageErrorf("instantiate: incorrect number of arguments, expected %d, got %d", expected, got)
+ }
+ appInstallation, grant := args[0], args[1]
+
+ ctx, cancel := context.WithCancel(ctx)
+ defer cancel()
+ principal := v23.GetPrincipal(ctx)
+
+ call, err := device.ApplicationClient(appInstallation).Instantiate(ctx)
+ if err != nil {
+ return fmt.Errorf("Instantiate failed: %v", err)
+ }
+ for call.RecvStream().Advance() {
+ switch msg := call.RecvStream().Value().(type) {
+ case device.BlessServerMessageInstancePublicKey:
+ pubKey, err := security.UnmarshalPublicKey(msg.Value)
+ if err != nil {
+ return fmt.Errorf("Instantiate failed: %v", err)
+ }
+ // TODO(caprita,rthellend): Get rid of security.UnconstrainedUse().
+ blessings, err := principal.Bless(pubKey, principal.BlessingStore().Default(), grant, security.UnconstrainedUse())
+ if err != nil {
+ return fmt.Errorf("Instantiate failed: %v", err)
+ }
+ call.SendStream().Send(device.BlessClientMessageAppBlessings{blessings})
+ default:
+ fmt.Fprintf(env.Stderr, "Received unexpected message: %#v\n", msg)
+ }
+ }
+ var instanceID string
+ if instanceID, err = call.Finish(); err != nil {
+ return fmt.Errorf("Instantiate failed: %v", err)
+ }
+ fmt.Fprintf(env.Stdout, "%s\n", naming.Join(appInstallation, instanceID))
+ return nil
+}
diff --git a/services/device/device/instantiate_test.go b/services/device/device/instantiate_test.go
new file mode 100644
index 0000000..edfa861
--- /dev/null
+++ b/services/device/device/instantiate_test.go
@@ -0,0 +1,100 @@
+// 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 (
+ "bytes"
+ "fmt"
+ "reflect"
+ "strings"
+ "testing"
+
+ "v.io/v23/naming"
+ "v.io/v23/verror"
+ "v.io/x/lib/cmdline"
+ "v.io/x/ref/lib/v23cmd"
+ "v.io/x/ref/test"
+
+ cmd_device "v.io/x/ref/services/device/device"
+)
+
+func TestInstantiateCommand(t *testing.T) {
+ ctx, shutdown := test.V23Init()
+ defer shutdown()
+
+ tapes := newTapeMap()
+ server, endpoint, err := startServer(t, ctx, tapes)
+ if err != nil {
+ return
+ }
+ defer stopServer(t, server)
+
+ // Setup the command-line.
+ cmd := cmd_device.CmdRoot
+ var stdout, stderr bytes.Buffer
+ env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
+ appName := naming.JoinAddressName(endpoint.String(), "")
+
+ // Confirm that we correctly enforce the number of arguments.
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"instantiate", "nope"}); err == nil {
+ t.Fatalf("wrongly failed to receive a non-nil error.")
+ }
+ if expected, got := "ERROR: instantiate: incorrect number of arguments, expected 2, got 1", strings.TrimSpace(stderr.String()); !strings.HasPrefix(got, expected) {
+ t.Fatalf("Unexpected output from instantiate. Got %q, expected prefix %q", got, expected)
+ }
+ stdout.Reset()
+ stderr.Reset()
+ rootTape := tapes.forSuffix("")
+ rootTape.Rewind()
+
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"instantiate", "nope", "nope", "nope"}); err == nil {
+ t.Fatalf("wrongly failed to receive a non-nil error.")
+ }
+ if expected, got := "ERROR: instantiate: incorrect number of arguments, expected 2, got 3", strings.TrimSpace(stderr.String()); !strings.HasPrefix(got, expected) {
+ t.Fatalf("Unexpected output from instantiate. Got %q, expected prefix %q", got, expected)
+ }
+ stdout.Reset()
+ stderr.Reset()
+ rootTape.Rewind()
+
+ // Correct operation.
+ rootTape.SetResponses(InstantiateResponse{
+ err: nil,
+ instanceID: "app1",
+ })
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"instantiate", appName, "grant"}); err != nil {
+ t.Fatalf("instantiate %s %s failed: %v", appName, "grant", err)
+ }
+
+ b := new(bytes.Buffer)
+ fmt.Fprintf(b, "%s", appName+"/app1")
+ if expected, got := b.String(), strings.TrimSpace(stdout.String()); !strings.HasPrefix(got, expected) {
+ t.Fatalf("Unexpected output from instantiate. Got %q, expected prefix %q", got, expected)
+ }
+ expected := []interface{}{
+ "Instantiate",
+ }
+ if got := rootTape.Play(); !reflect.DeepEqual(expected, got) {
+ t.Errorf("unexpected result. Got %v want %v", got, expected)
+ }
+ rootTape.Rewind()
+ stdout.Reset()
+ stderr.Reset()
+
+ // Error operation.
+ rootTape.SetResponses(InstantiateResponse{
+ verror.New(errOops, nil),
+ "",
+ })
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"instantiate", appName, "grant"}); err == nil {
+ t.Fatalf("instantiate failed to detect error")
+ }
+ expected = []interface{}{
+ "Instantiate",
+ }
+ if got := rootTape.Play(); !reflect.DeepEqual(expected, got) {
+ t.Errorf("unexpected result. Got %v want %v", got, expected)
+ }
+}
diff --git a/services/device/device/kill.go b/services/device/device/kill.go
new file mode 100644
index 0000000..4f156df
--- /dev/null
+++ b/services/device/device/kill.go
@@ -0,0 +1,40 @@
+// 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
+
+import (
+ "fmt"
+ "time"
+
+ "v.io/v23/context"
+ "v.io/v23/services/device"
+ "v.io/x/lib/cmdline"
+ "v.io/x/ref/lib/v23cmd"
+)
+
+const killDeadline = 10 * time.Second
+
+var cmdKill = &cmdline.Command{
+ Runner: v23cmd.RunnerFunc(runKill),
+ Name: "kill",
+ Short: "Kill the given application instance.",
+ Long: "Kill the given application instance.",
+ ArgsName: "<app instance>",
+ ArgsLong: `
+<app instance> is the vanadium object name of the application instance to kill.`,
+}
+
+func runKill(ctx *context.T, env *cmdline.Env, args []string) error {
+ if expected, got := 1, len(args); expected != got {
+ return env.UsageErrorf("kill: incorrect number of arguments, expected %d, got %d", expected, got)
+ }
+ appName := args[0]
+
+ if err := device.ApplicationClient(appName).Kill(ctx, killDeadline); err != nil {
+ return fmt.Errorf("Kill failed: %v", err)
+ }
+ fmt.Fprintf(env.Stdout, "Kill succeeded\n")
+ return nil
+}
diff --git a/services/device/device/kill_test.go b/services/device/device/kill_test.go
new file mode 100644
index 0000000..adf7662
--- /dev/null
+++ b/services/device/device/kill_test.go
@@ -0,0 +1,90 @@
+// 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 (
+ "bytes"
+ "reflect"
+ "strings"
+ "testing"
+ "time"
+
+ "v.io/v23/naming"
+ "v.io/v23/verror"
+ "v.io/x/lib/cmdline"
+ "v.io/x/ref/lib/v23cmd"
+ "v.io/x/ref/test"
+
+ cmd_device "v.io/x/ref/services/device/device"
+)
+
+func TestKillCommand(t *testing.T) {
+ ctx, shutdown := test.V23Init()
+ defer shutdown()
+
+ tapes := newTapeMap()
+ server, endpoint, err := startServer(t, ctx, tapes)
+ if err != nil {
+ return
+ }
+ defer stopServer(t, server)
+
+ // Setup the command-line.
+ cmd := cmd_device.CmdRoot
+ var stdout, stderr bytes.Buffer
+ env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
+ appName := naming.JoinAddressName(endpoint.String(), "appname")
+
+ // Confirm that we correctly enforce the number of arguments.
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"kill"}); err == nil {
+ t.Fatalf("wrongly failed to receive a non-nil error.")
+ }
+ if expected, got := "ERROR: kill: incorrect number of arguments, expected 1, got 0", strings.TrimSpace(stderr.String()); !strings.HasPrefix(got, expected) {
+ t.Fatalf("Unexpected output from kill. Got %q, expected prefix %q", got, expected)
+ }
+ stdout.Reset()
+ stderr.Reset()
+ appTape := tapes.forSuffix("appname")
+ appTape.Rewind()
+
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"kill", "nope", "nope"}); err == nil {
+ t.Fatalf("wrongly failed to receive a non-nil error.")
+ }
+ if expected, got := "ERROR: kill: incorrect number of arguments, expected 1, got 2", strings.TrimSpace(stderr.String()); !strings.HasPrefix(got, expected) {
+ t.Fatalf("Unexpected output from kill. Got %q, expected prefix %q", got, expected)
+ }
+ stdout.Reset()
+ stderr.Reset()
+ appTape.Rewind()
+
+ // Test the 'kill' command.
+ appTape.SetResponses(nil)
+
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"kill", appName}); err != nil {
+ t.Fatalf("kill failed when it shouldn't: %v", err)
+ }
+ if expected, got := "Kill succeeded", strings.TrimSpace(stdout.String()); got != expected {
+ t.Fatalf("Unexpected output from list. Got %q, expected %q", got, expected)
+ }
+ expected := []interface{}{
+ KillStimulus{"Kill", 10 * time.Second},
+ }
+ if got := appTape.Play(); !reflect.DeepEqual(expected, got) {
+ t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
+ }
+ appTape.Rewind()
+ stderr.Reset()
+ stdout.Reset()
+
+ // Test kill with bad parameters.
+ appTape.SetResponses(verror.New(errOops, nil))
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"kill", appName}); err == nil {
+ t.Fatalf("wrongly didn't receive a non-nil error.")
+ }
+ // expected the same.
+ if got := appTape.Play(); !reflect.DeepEqual(expected, got) {
+ t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
+ }
+}
diff --git a/services/device/device/local_install_test.go b/services/device/device/local_install_test.go
index e3880e7..f3e938c 100644
--- a/services/device/device/local_install_test.go
+++ b/services/device/device/local_install_test.go
@@ -33,7 +33,7 @@
}
func TestInstallLocalCommand(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
tapes := newTapeMap()
diff --git a/services/device/device/ls.go b/services/device/device/ls.go
index 0bc03cd..80939da 100644
--- a/services/device/device/ls.go
+++ b/services/device/device/ls.go
@@ -8,6 +8,8 @@
"fmt"
"io"
+ "v.io/v23/context"
+
"v.io/x/lib/cmdline"
)
@@ -18,10 +20,10 @@
Long: "List application installations or instances.",
ArgsName: "<app name patterns...>",
ArgsLong: `
-<app name patterns...> are vanadium object names or glob name patterns corresponding to app installations and instances.`,
+<app name patterns...> are vanadium object names or glob name patterns corresponding to application installations and instances.`,
}
-func runLs(entry globResult, stdout, stderr io.Writer) error {
+func runLs(entry globResult, _ *context.T, stdout, _ io.Writer) error {
fmt.Fprintf(stdout, "%v\n", entry.name)
return nil
}
diff --git a/services/device/device/ls_test.go b/services/device/device/ls_test.go
index 9ceefd0..420dd05 100644
--- a/services/device/device/ls_test.go
+++ b/services/device/device/ls_test.go
@@ -22,7 +22,7 @@
// glob functionality, by trying out various combinations of
// instances/installations in glob results.
func TestLsCommand(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
tapes := newTapeMap()
server, endpoint, err := startServer(t, ctx, tapes)
@@ -157,7 +157,7 @@
}
if expected, got := c.expected, strings.TrimSpace(stdout.String()); got != expected {
- t.Errorf("Unexpected output from status. Got %q, expected %q", got, expected)
+ t.Errorf("Unexpected output from ls. Got %q, expected %q", got, expected)
}
cmd_device.ResetGlobFlags()
}
diff --git a/services/device/device/mock_test.go b/services/device/device/mock_test.go
index e52a469..7925dc4 100644
--- a/services/device/device/mock_test.go
+++ b/services/device/device/mock_test.go
@@ -24,7 +24,12 @@
t.stimuli = append(t.stimuli, call)
if len(t.responses) < 1 {
- return fmt.Errorf("Record(%#v) had no response", call)
+ // 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:]
@@ -92,9 +97,6 @@
func TestOneTape(t *testing.T) {
tm := newTapeMap()
- if _, ok := tm.forSuffix("mytape").Record("foo").(error); !ok {
- t.Errorf("Expected error")
- }
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)
@@ -102,7 +104,7 @@
if want, got := "c", tm.forSuffix("mytape").Record("baz"); want != got {
t.Errorf("Expected %v, got %v", want, got)
}
- if want, got := []interface{}{"foo", "bar", "baz"}, tm.forSuffix("mytape").Play(); !reflect.DeepEqual(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()
diff --git a/services/device/device/revert.go b/services/device/device/revert.go
new file mode 100644
index 0000000..0f27078
--- /dev/null
+++ b/services/device/device/revert.go
@@ -0,0 +1,37 @@
+// 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
+
+import (
+ "fmt"
+
+ "v.io/v23/context"
+ "v.io/v23/services/device"
+ "v.io/x/lib/cmdline"
+ "v.io/x/ref/lib/v23cmd"
+)
+
+var cmdRevert = &cmdline.Command{
+ Runner: v23cmd.RunnerFunc(runRevert),
+ Name: "revert",
+ Short: "Revert the device manager or application",
+ Long: "Revert the device manager or application to its previous version",
+ ArgsName: "<object>",
+ ArgsLong: `
+<object> is the vanadium object name of the device manager or application
+installation to revert.`,
+}
+
+func runRevert(ctx *context.T, env *cmdline.Env, args []string) error {
+ if expected, got := 1, len(args); expected != got {
+ return env.UsageErrorf("revert: incorrect number of arguments, expected %d, got %d", expected, got)
+ }
+ deviceName := args[0]
+ if err := device.ApplicationClient(deviceName).Revert(ctx); err != nil {
+ return err
+ }
+ fmt.Fprintln(env.Stdout, "Revert successful.")
+ return nil
+}
diff --git a/services/device/device/root.go b/services/device/device/root.go
index 5325016..6caa02e 100644
--- a/services/device/device/root.go
+++ b/services/device/device/root.go
@@ -20,7 +20,7 @@
Long: `
Command device facilitates interaction with the Vanadium device manager.
`,
- Children: []*cmdline.Command{cmdInstall, cmdInstallLocal, cmdUninstall, cmdAssociate, cmdDescribe, cmdClaim, cmdInstantiate, cmdDelete, cmdRun, cmdKill, cmdRevert, cmdUpdate, cmdUpdateAll, cmdStatus, cmdDebug, cmdACL, cmdPublish, cmdLs},
+ Children: []*cmdline.Command{cmdInstall, cmdInstallLocal, cmdUninstall, cmdAssociate, cmdDescribe, cmdClaim, cmdInstantiate, cmdDelete, cmdRun, cmdKill, cmdRevert, cmdUpdate, cmdStatus, cmdDebug, cmdACL, cmdPublish, cmdLs},
}
func main() {
diff --git a/services/device/device/run.go b/services/device/device/run.go
new file mode 100644
index 0000000..6528708
--- /dev/null
+++ b/services/device/device/run.go
@@ -0,0 +1,37 @@
+// 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
+
+import (
+ "fmt"
+
+ "v.io/v23/context"
+ "v.io/v23/services/device"
+ "v.io/x/lib/cmdline"
+ "v.io/x/ref/lib/v23cmd"
+)
+
+var cmdRun = &cmdline.Command{
+ Runner: v23cmd.RunnerFunc(runRun),
+ Name: "run",
+ Short: "Run the given application instance.",
+ Long: "Run the given application instance.",
+ ArgsName: "<app instance>",
+ ArgsLong: `
+<app instance> is the vanadium object name of the application instance to run.`,
+}
+
+func runRun(ctx *context.T, env *cmdline.Env, args []string) error {
+ if expected, got := 1, len(args); expected != got {
+ return env.UsageErrorf("run: incorrect number of arguments, expected %d, got %d", expected, got)
+ }
+ appName := args[0]
+
+ if err := device.ApplicationClient(appName).Run(ctx); err != nil {
+ return fmt.Errorf("Run failed: %v,\nView log with:\n debug logs read `debug glob %s/logs/STDERR-*`", err, appName)
+ }
+ fmt.Fprintf(env.Stdout, "Run succeeded\n")
+ return nil
+}
diff --git a/services/device/device/run_test.go b/services/device/device/run_test.go
new file mode 100644
index 0000000..7d9f5d9
--- /dev/null
+++ b/services/device/device/run_test.go
@@ -0,0 +1,11 @@
+// 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 "testing"
+
+func TestRunCommand(t *testing.T) {
+ testHelper(t, "run", "Run")
+}
diff --git a/services/device/device/status.go b/services/device/device/status.go
new file mode 100644
index 0000000..d32430e
--- /dev/null
+++ b/services/device/device/status.go
@@ -0,0 +1,38 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ "io"
+
+ "v.io/v23/context"
+ "v.io/v23/services/device"
+ "v.io/x/lib/cmdline"
+)
+
+var cmdStatus = &cmdline.Command{
+ Runner: globRunner(runStatus),
+ Name: "status",
+ Short: "Get device manager or application status.",
+ Long: "Get the status of the device manager or application instances and installations.",
+ ArgsName: "<name patterns...>",
+ ArgsLong: `
+<name patterns...> are vanadium object names or glob name patterns corresponding to the device manager service, or to application installations and instances.`,
+}
+
+func runStatus(entry globResult, _ *context.T, stdout, _ io.Writer) error {
+ switch s := entry.status.(type) {
+ case device.StatusInstance:
+ fmt.Fprintf(stdout, "Instance %v [State:%v,Version:%v]\n", entry.name, s.Value.State, s.Value.Version)
+ case device.StatusInstallation:
+ fmt.Fprintf(stdout, "Installation %v [State:%v,Version:%v]\n", entry.name, s.Value.State, s.Value.Version)
+ case device.StatusDevice:
+ fmt.Fprintf(stdout, "Device Service %v [State:%v,Version:%v]\n", entry.name, s.Value.State, s.Value.Version)
+ default:
+ return fmt.Errorf("Status returned unknown type: %T", s)
+ }
+ return nil
+}
diff --git a/services/device/device/status_test.go b/services/device/device/status_test.go
new file mode 100644
index 0000000..4284226
--- /dev/null
+++ b/services/device/device/status_test.go
@@ -0,0 +1,73 @@
+// 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 (
+ "bytes"
+ "fmt"
+ "reflect"
+ "strings"
+ "testing"
+
+ "v.io/v23/naming"
+ "v.io/v23/services/device"
+ "v.io/x/lib/cmdline"
+ "v.io/x/ref/lib/v23cmd"
+ "v.io/x/ref/test"
+
+ cmd_device "v.io/x/ref/services/device/device"
+)
+
+func TestStatusCommand(t *testing.T) {
+ ctx, shutdown := test.V23Init()
+ defer shutdown()
+ tapes := newTapeMap()
+ server, endpoint, err := startServer(t, ctx, tapes)
+ if err != nil {
+ return
+ }
+ defer stopServer(t, server)
+
+ cmd := cmd_device.CmdRoot
+ globName := naming.JoinAddressName(endpoint.String(), "glob")
+ appName := naming.JoinAddressName(endpoint.String(), "app")
+
+ rootTape, appTape := tapes.forSuffix(""), tapes.forSuffix("app")
+ for _, c := range []struct {
+ tapeResponse device.Status
+ expected string
+ }{
+ {
+ installationUninstalled,
+ fmt.Sprintf("Installation %v [State:Uninstalled,Version:director's cut]", appName),
+ },
+ {
+ instanceUpdating,
+ fmt.Sprintf("Instance %v [State:Updating,Version:theatrical version]", appName),
+ },
+ {
+ deviceService,
+ fmt.Sprintf("Device Service %v [State:Running,Version:han shot first]", appName),
+ },
+ } {
+ var stdout, stderr bytes.Buffer
+ env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
+ tapes.rewind()
+ rootTape.SetResponses(GlobResponse{[]string{"app"}})
+ appTape.SetResponses(c.tapeResponse)
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{"status", globName}); err != nil {
+ t.Errorf("%v", err)
+ }
+ if expected, got := c.expected, strings.TrimSpace(stdout.String()); got != expected {
+ t.Errorf("Unexpected output from status. Got %q, expected %q", got, expected)
+ }
+ if got, expected := rootTape.Play(), []interface{}{GlobStimulus{"glob"}}; !reflect.DeepEqual(expected, got) {
+ t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
+ }
+ if got, expected := appTape.Play(), []interface{}{"Status"}; !reflect.DeepEqual(expected, got) {
+ t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
+ }
+ }
+}
diff --git a/services/device/device/uninstall.go b/services/device/device/uninstall.go
new file mode 100644
index 0000000..9beb224
--- /dev/null
+++ b/services/device/device/uninstall.go
@@ -0,0 +1,38 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+
+ "v.io/v23/context"
+ "v.io/v23/services/device"
+ "v.io/x/lib/cmdline"
+ "v.io/x/ref/lib/v23cmd"
+)
+
+var cmdUninstall = &cmdline.Command{
+ Runner: v23cmd.RunnerFunc(runUninstall),
+ Name: "uninstall",
+ Short: "Uninstall the given application installation.",
+ Long: "Uninstall the given application installation.",
+ ArgsName: "<installation>",
+ ArgsLong: `
+<installation> is the vanadium object name of the application installation to
+uninstall.
+`,
+}
+
+func runUninstall(ctx *context.T, env *cmdline.Env, args []string) error {
+ if expected, got := 1, len(args); expected != got {
+ return env.UsageErrorf("uninstall: incorrect number of arguments, expected %d, got %d", expected, got)
+ }
+ installName := args[0]
+ if err := device.ApplicationClient(installName).Uninstall(ctx); err != nil {
+ return fmt.Errorf("Uninstall failed: %v", err)
+ }
+ fmt.Fprintf(env.Stdout, "Successfully uninstalled: %q\n", installName)
+ return nil
+}
diff --git a/services/device/device/update.go b/services/device/device/update.go
new file mode 100644
index 0000000..e6cb007
--- /dev/null
+++ b/services/device/device/update.go
@@ -0,0 +1,111 @@
+// 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
+
+import (
+ "fmt"
+ "io"
+ "time"
+
+ "v.io/v23/context"
+ "v.io/v23/services/device"
+ "v.io/v23/verror"
+
+ "v.io/x/lib/cmdline"
+ deviceimpl "v.io/x/ref/services/device/internal/impl"
+)
+
+var cmdUpdate = &cmdline.Command{
+ Runner: globRunner(runUpdate),
+ Name: "update",
+ Short: "Update device manager or applications.",
+ Long: "Update the device manager or application instances and installations",
+ ArgsName: "<app name patterns...>",
+ ArgsLong: `
+<app name patterns...> are vanadium object names or glob name patterns corresponding to the device manager service, or to application installations and instances.`,
+}
+
+func instanceIsRunning(ctx *context.T, von string) (bool, error) {
+ status, err := device.ApplicationClient(von).Status(ctx)
+ if err != nil {
+ return false, fmt.Errorf("Failed to get status for instance %q: %v", von, err)
+ }
+ s, ok := status.(device.StatusInstance)
+ if !ok {
+ return false, fmt.Errorf("Status for instance %q of wrong type (%T)", von, status)
+ }
+ return s.Value.State == device.InstanceStateRunning, nil
+}
+
+func updateInstance(ctx *context.T, stdout, stderr io.Writer, name string, status device.StatusInstance) (retErr error) {
+ if status.Value.State == device.InstanceStateRunning {
+ if err := device.ApplicationClient(name).Kill(ctx, killDeadline); err != nil {
+ // Check the app's state again in case we killed it,
+ // nevermind any errors. The sleep is because Kill
+ // currently (4/29/15) returns asynchronously with the
+ // device manager shooting the app down.
+ time.Sleep(time.Second)
+ running, rerr := instanceIsRunning(ctx, name)
+ if rerr != nil {
+ return rerr
+ }
+ if running {
+ return fmt.Errorf("Kill failed: %v", err)
+ }
+ fmt.Fprintf(stderr, "WARNING for \"%s\": recovered from Kill error (%s). Proceeding with update.\n", name, err)
+ }
+ // App was running, and we killed it, so we need to run it again
+ // after the update.
+ defer func() {
+ if err := device.ApplicationClient(name).Run(ctx); err != nil {
+ err = fmt.Errorf("Run failed: %v", err)
+ if retErr == nil {
+ retErr = err
+ } else {
+ fmt.Fprintf(stderr, "ERROR for \"%s\": %v.\n", name, err)
+ }
+ }
+ }()
+ }
+ // Update the instance.
+ switch err := device.ApplicationClient(name).Update(ctx); {
+ case err == nil:
+ fmt.Fprintf(stdout, "Successfully updated instance \"%s\".\n", name)
+ return nil
+ case verror.ErrorID(err) == deviceimpl.ErrUpdateNoOp.ID:
+ // TODO(caprita): Ideally, we wouldn't even attempt a kill /
+ // restart if there's no newer version of the application.
+ fmt.Fprintf(stdout, "Instance \"%s\" already up to date.\n", name)
+ return nil
+ default:
+ return fmt.Errorf("Update failed: %v", err)
+ }
+}
+
+func updateOne(ctx *context.T, what string, stdout, stderr io.Writer, name string) error {
+ switch err := device.ApplicationClient(name).Update(ctx); {
+ case err == nil:
+ fmt.Fprintf(stdout, "Successfully updated version for %s \"%s\".\n", what, name)
+ return nil
+ case verror.ErrorID(err) == deviceimpl.ErrUpdateNoOp.ID:
+ fmt.Fprintf(stdout, "%s \"%s\" already up to date.\n", what, name)
+ return nil
+ default:
+ return fmt.Errorf("Update failed: %v", err)
+ }
+}
+
+func runUpdate(entry globResult, ctx *context.T, stdout, stderr io.Writer) error {
+ switch entry.kind {
+ case applicationInstanceObject:
+ return updateInstance(ctx, stdout, stderr, entry.name, entry.status.(device.StatusInstance))
+ case applicationInstallationObject:
+ return updateOne(ctx, "installation", stdout, stderr, entry.name)
+ case deviceServiceObject:
+ return updateOne(ctx, "device service", stdout, stderr, entry.name)
+ default:
+ return fmt.Errorf("unhandled object kind %v", entry.kind)
+ }
+}
diff --git a/services/device/device/update_test.go b/services/device/device/update_test.go
new file mode 100644
index 0000000..1c90110
--- /dev/null
+++ b/services/device/device/update_test.go
@@ -0,0 +1,137 @@
+// 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 (
+ "bytes"
+ "fmt"
+ "reflect"
+ "strings"
+ "testing"
+ "time"
+
+ "v.io/v23/naming"
+ "v.io/x/lib/cmdline"
+ "v.io/x/ref/lib/v23cmd"
+ "v.io/x/ref/test"
+
+ cmd_device "v.io/x/ref/services/device/device"
+)
+
+// TestUpdateCommand verifies the device update command.
+func TestUpdateCommand(t *testing.T) {
+ ctx, shutdown := test.V23Init()
+ defer shutdown()
+ tapes := newTapeMap()
+ server, endpoint, err := startServer(t, ctx, tapes)
+ if err != nil {
+ return
+ }
+ defer stopServer(t, server)
+
+ cmd := cmd_device.CmdRoot
+ appName := naming.JoinAddressName(endpoint.String(), "app")
+ rootTape := tapes.forSuffix("")
+ globName := naming.JoinAddressName(endpoint.String(), "glob")
+ // TODO(caprita): Move joinLines to a common place.
+ joinLines := func(args ...string) string {
+ return strings.Join(args, "\n")
+ }
+ for _, c := range []struct {
+ globResponses []string
+ statusResponses map[string][]interface{}
+ expectedStimuli map[string][]interface{}
+ expectedStdout string
+ expectedStderr string
+ expectedError string
+ }{
+ { // Everything succeeds.
+ []string{"app/2", "app/1", "app/3"},
+ map[string][]interface{}{
+ "app/1": []interface{}{instanceRunning, nil, nil, nil},
+ "app/2": []interface{}{instanceNotRunning, nil},
+ "app/3": []interface{}{installationActive, nil},
+ },
+ map[string][]interface{}{
+ "app/1": []interface{}{"Status", KillStimulus{"Kill", 10 * time.Second}, "Update", "Run"},
+ "app/2": []interface{}{"Status", "Update"},
+ "app/3": []interface{}{"Status", "Update"},
+ },
+ joinLines(
+ fmt.Sprintf("Successfully updated version for installation \"%s/3\".", appName),
+ fmt.Sprintf("Successfully updated instance \"%s/1\".", appName),
+ fmt.Sprintf("Successfully updated instance \"%s/2\".", appName)),
+ "",
+ "",
+ },
+ { // Assorted failure modes.
+ []string{"app/1", "app/2", "app/3", "app/4", "app/5"},
+ map[string][]interface{}{
+ // Starts as running, fails Kill, but then
+ // recovers. This ultimately counts as a success.
+ "app/1": []interface{}{instanceRunning, fmt.Errorf("Simulate Kill failing"), instanceNotRunning, nil, nil},
+ // Starts as running, fails Kill, and stays running.
+ "app/2": []interface{}{instanceRunning, fmt.Errorf("Simulate Kill failing"), instanceRunning},
+ // Starts as running, Kill and Update succeed, but Run fails.
+ "app/3": []interface{}{instanceRunning, nil, nil, fmt.Errorf("Simulate Run failing")},
+ // Starts as running, Kill succeeds, Update fails, but Run succeeds.
+ "app/4": []interface{}{instanceRunning, nil, fmt.Errorf("Simulate Update failing"), nil},
+ // Starts as running, Kill succeeds, Update fails, and Run fails.
+ "app/5": []interface{}{instanceRunning, nil, fmt.Errorf("Simulate Update failing"), fmt.Errorf("Simulate Run failing")},
+ },
+ map[string][]interface{}{
+ "app/1": []interface{}{"Status", KillStimulus{"Kill", 10 * time.Second}, "Status", "Update", "Run"},
+ "app/2": []interface{}{"Status", KillStimulus{"Kill", 10 * time.Second}, "Status"},
+ "app/3": []interface{}{"Status", KillStimulus{"Kill", 10 * time.Second}, "Update", "Run"},
+ "app/4": []interface{}{"Status", KillStimulus{"Kill", 10 * time.Second}, "Update", "Run"},
+ "app/5": []interface{}{"Status", KillStimulus{"Kill", 10 * time.Second}, "Update", "Run"},
+ },
+ joinLines(
+ fmt.Sprintf("Successfully updated instance \"%s/1\".", appName),
+ fmt.Sprintf("Successfully updated instance \"%s/3\".", appName),
+ ),
+ joinLines(
+ fmt.Sprintf("WARNING for \"%s/1\": recovered from Kill error (device.test:<rpc.Client>\"%s/1\".Kill: Error: Simulate Kill failing). Proceeding with update.", appName, appName),
+ fmt.Sprintf("ERROR for \"%s/2\": Kill failed: device.test:<rpc.Client>\"%s/2\".Kill: Error: Simulate Kill failing.", appName, appName),
+ fmt.Sprintf("ERROR for \"%s/3\": Run failed: device.test:<rpc.Client>\"%s/3\".Run: Error: Simulate Run failing.", appName, appName),
+ fmt.Sprintf("ERROR for \"%s/4\": Update failed: device.test:<rpc.Client>\"%s/4\".Update: Error: Simulate Update failing.", appName, appName),
+ fmt.Sprintf("ERROR for \"%s/5\": Run failed: device.test:<rpc.Client>\"%s/5\".Run: Error: Simulate Run failing.", appName, appName),
+ fmt.Sprintf("ERROR for \"%s/5\": Update failed: device.test:<rpc.Client>\"%s/5\".Update: Error: Simulate Update failing.", appName, appName),
+ ),
+ "encountered a total of 4 error(s)",
+ },
+ } {
+ var stdout, stderr bytes.Buffer
+ env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
+ tapes.rewind()
+ rootTape.SetResponses(GlobResponse{c.globResponses})
+ for n, r := range c.statusResponses {
+ tapes.forSuffix(n).SetResponses(r...)
+ }
+ args := []string{"update", globName}
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, args); err != nil {
+ if want, got := c.expectedError, err.Error(); want != got {
+ t.Errorf("Unexpected error: want %v, got %v", want, got)
+ }
+ } else {
+ if c.expectedError != "" {
+ t.Errorf("Expected to get error %v, but didn't get any error.", c.expectedError)
+ }
+ }
+
+ if expected, got := c.expectedStdout, strings.TrimSpace(stdout.String()); got != expected {
+ t.Errorf("Unexpected stdout output from update. Got %q, expected %q", got, expected)
+ }
+ if expected, got := c.expectedStderr, strings.TrimSpace(stderr.String()); got != expected {
+ t.Errorf("Unexpected stderr output from update. Got %q, expected %q", got, expected)
+ }
+ for n, m := range c.expectedStimuli {
+ 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)
+ }
+ }
+ cmd_device.ResetGlobFlags()
+ }
+}
diff --git a/services/device/device/updateall.go b/services/device/device/updateall.go
deleted file mode 100644
index e772ee9..0000000
--- a/services/device/device/updateall.go
+++ /dev/null
@@ -1,236 +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
-
-import (
- "fmt"
- "strings"
- "sync"
- "time"
-
- "v.io/v23"
- "v.io/v23/context"
- "v.io/v23/naming"
- "v.io/v23/services/device"
- "v.io/v23/verror"
- "v.io/x/lib/cmdline"
- "v.io/x/ref/lib/v23cmd"
- deviceimpl "v.io/x/ref/services/device/internal/impl"
-)
-
-// TODO(caprita): Re-implement this with Glob, so that one can say instead,
-// update <devicename>/apps/... or <devicename>/apps/appname/* etc.
-
-// TODO(caprita): Add unit test.
-
-var cmdUpdateAll = &cmdline.Command{
- Runner: v23cmd.RunnerFunc(runUpdateAll),
- Name: "updateall",
- Short: "Update all installations/instances of an application",
- Long: "Given a name that can refer to an app instance or app installation or app or all apps on a device, updates all installations and instances under that name",
- ArgsName: "<object name>",
- ArgsLong: `
-<object name> is the vanadium object name to update, as follows:
-
-<devicename>/apps/apptitle/installationid/instanceid: updates the given instance, killing/restarting it if running
-
-<devicename>/apps/apptitle/installationid: updates the given installation and then all its instances
-
-<devicename>/apps/apptitle: updates all installations for the given app
-
-<devicename>/apps: updates all apps on the device
-`,
-}
-
-type updater func(ctx *context.T, env *cmdline.Env, von string) error
-
-func updateChildren(ctx *context.T, env *cmdline.Env, von string, updateChild updater) error {
- ns := v23.GetNamespace(ctx)
- pattern := naming.Join(von, "*")
- c, err := ns.Glob(ctx, pattern)
- if err != nil {
- return fmt.Errorf("ns.Glob(%q) failed: %v", pattern, err)
- }
- var (
- pending sync.WaitGroup
- numErrors int
- numErrorsMu sync.Mutex
- )
- for res := range c {
- switch v := res.(type) {
- case *naming.GlobReplyEntry:
- pending.Add(1)
- go func() {
- if err := updateChild(ctx, env, v.Value.Name); err != nil {
- numErrorsMu.Lock()
- numErrors++
- numErrorsMu.Unlock()
- }
- pending.Done()
- }()
- case *naming.GlobReplyError:
- fmt.Fprintf(env.Stderr, "Glob error for %q: %v\n", v.Value.Name, v.Value.Error)
- numErrorsMu.Lock()
- numErrors++
- numErrorsMu.Unlock()
- }
- }
- pending.Wait()
- if numErrors > 0 {
- return fmt.Errorf("%d error(s) encountered while updating children", numErrors)
- }
- return nil
-}
-
-func instanceIsRunning(ctx *context.T, von string) (bool, error) {
- status, err := device.ApplicationClient(von).Status(ctx)
- if err != nil {
- return false, fmt.Errorf("Failed to get status for instance %q: %v", von, err)
- }
- s, ok := status.(device.StatusInstance)
- if !ok {
- return false, fmt.Errorf("Status for instance %q of wrong type (%T)", von, status)
- }
- return s.Value.State == device.InstanceStateRunning, nil
-}
-
-func updateInstance(ctx *context.T, env *cmdline.Env, von string) (retErr error) {
- defer func() {
- if retErr == nil {
- fmt.Fprintf(env.Stdout, "Successfully updated instance %q.\n", von)
- } else {
- retErr = fmt.Errorf("failed to update instance %q: %v", von, retErr)
- fmt.Fprintf(env.Stderr, "ERROR: %v.\n", retErr)
- }
- }()
- running, err := instanceIsRunning(ctx, von)
- if err != nil {
- return err
- }
- if running {
- // Try killing the app.
- if err := device.ApplicationClient(von).Kill(ctx, killDeadline); err != nil {
- // Check the app's state again in case we killed it,
- // nevermind any errors. The sleep is because Kill
- // currently (4/29/15) returns asynchronously with the
- // device manager shooting the app down.
- time.Sleep(time.Second)
- running, rerr := instanceIsRunning(ctx, von)
- if rerr != nil {
- return rerr
- }
- if running {
- return fmt.Errorf("failed to kill instance %q: %v", von, err)
- }
- fmt.Fprintf(env.Stderr, "Kill(%s) returned an error (%s) but app is now not running.\n", von, err)
- }
- // App was running, and we killed it.
- defer func() {
- // Re-start the instance.
- if err := device.ApplicationClient(von).Run(ctx); err != nil {
- err = fmt.Errorf("failed to run instance %q: %v", von, err)
- if retErr == nil {
- retErr = err
- } else {
- fmt.Fprintf(env.Stderr, "ERROR: %v.\n", err)
- }
- }
- }()
- }
- // Update the instance.
- switch err := device.ApplicationClient(von).Update(ctx); {
- case err == nil:
- return nil
- case verror.ErrorID(err) == deviceimpl.ErrUpdateNoOp.ID:
- // TODO(caprita): Ideally, we wouldn't even attempt a kill /
- // restart if there's no newer version of the application.
- fmt.Fprintf(env.Stdout, "Instance %q already up to date.\n", von)
- return nil
- default:
- return err
- }
-}
-
-func updateInstallation(ctx *context.T, env *cmdline.Env, von string) (retErr error) {
- defer func() {
- if retErr == nil {
- fmt.Fprintf(env.Stdout, "Successfully updated installation %q.\n", von)
- } else {
- retErr = fmt.Errorf("failed to update installation %q: %v", von, retErr)
- fmt.Fprintf(env.Stderr, "ERROR: %v.\n", retErr)
- }
- }()
-
- // First, update the installation.
- switch err := device.ApplicationClient(von).Update(ctx); {
- case err == nil:
- fmt.Fprintf(env.Stdout, "Successfully updated version for installation %q.\n", von)
- case verror.ErrorID(err) == deviceimpl.ErrUpdateNoOp.ID:
- fmt.Fprintf(env.Stdout, "Installation %q already up to date.\n", von)
- // NOTE: we still proceed to update the instances in this case,
- // since it's possible that some instances are still running
- // from older versions.
- default:
- return err
- }
- // Then, update all the instances for the installation.
- return updateChildren(ctx, env, von, updateInstance)
-}
-
-func updateApp(ctx *context.T, env *cmdline.Env, von string) error {
- if err := updateChildren(ctx, env, von, updateInstallation); err != nil {
- err = fmt.Errorf("failed to update app %q: %v", von, err)
- fmt.Fprintf(env.Stderr, "ERROR: %v.\n", err)
- return err
- }
- fmt.Fprintf(env.Stdout, "Successfully updated app %q.\n", von)
- return nil
-}
-
-func updateAllApps(ctx *context.T, env *cmdline.Env, von string) error {
- if err := updateChildren(ctx, env, von, updateApp); err != nil {
- err = fmt.Errorf("failed to update all apps %q: %v", von, err)
- fmt.Fprintf(env.Stderr, "ERROR: %v.\n", err)
- return err
- }
- fmt.Fprintf(env.Stdout, "Successfully updated all apps %q.\n", von)
- return nil
-}
-
-func runUpdateAll(ctx *context.T, env *cmdline.Env, args []string) error {
- if expected, got := 1, len(args); expected != got {
- return env.UsageErrorf("updateall: incorrect number of arguments, expected %d, got %d", expected, got)
- }
- appVON := args[0]
- components := strings.Split(appVON, "/")
- var prefix string
- // TODO(caprita): Trying to figure out what the app suffix is by looking
- // for "/apps/" in the name is hacky and error-prone (e.g., what if an
- // app has the title "apps"). Instead, we should either query the
- // server or use resolution to split up the name into address and
- // suffix.
- for i := len(components) - 1; i >= 0; i-- {
- if components[i] == "apps" {
- prefix = naming.Join(components[:i+1]...)
- components = components[i+1:]
- break
- }
- }
- if prefix == "" {
- return fmt.Errorf("couldn't recognize app name: %q", appVON)
- }
- fmt.Printf("prefix: %q, components: %q\n", prefix, components)
- switch len(components) {
- case 0:
- return updateAllApps(ctx, env, appVON)
- case 1:
- return updateApp(ctx, env, appVON)
- case 2:
- return updateInstallation(ctx, env, appVON)
- case 3:
- return updateInstance(ctx, env, appVON)
- }
- return env.UsageErrorf("updateall: name %q does not refer to a supported app hierarchy object", appVON)
-}
diff --git a/services/device/device/util_test.go b/services/device/device/util_test.go
new file mode 100644
index 0000000..01bd228
--- /dev/null
+++ b/services/device/device/util_test.go
@@ -0,0 +1,115 @@
+// 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 (
+ "bytes"
+ "reflect"
+ "strings"
+ "testing"
+
+ "v.io/v23/naming"
+ "v.io/v23/services/device"
+ "v.io/v23/verror"
+ "v.io/x/lib/cmdline"
+ "v.io/x/ref/lib/v23cmd"
+ "v.io/x/ref/test"
+
+ cmd_device "v.io/x/ref/services/device/device"
+)
+
+//go:generate v23 test generate
+
+var (
+ installationUninstalled = device.StatusInstallation{device.InstallationStatus{
+ State: device.InstallationStateUninstalled,
+ Version: "director's cut",
+ }}
+ installationActive = device.StatusInstallation{device.InstallationStatus{
+ State: device.InstallationStateActive,
+ Version: "extended cut",
+ }}
+ instanceUpdating = device.StatusInstance{device.InstanceStatus{
+ State: device.InstanceStateUpdating,
+ Version: "theatrical version",
+ }}
+ instanceRunning = device.StatusInstance{device.InstanceStatus{
+ State: device.InstanceStateRunning,
+ Version: "special edition",
+ }}
+ instanceNotRunning = device.StatusInstance{device.InstanceStatus{
+ State: device.InstanceStateNotRunning,
+ Version: "special edition",
+ }}
+ deviceService = device.StatusDevice{device.DeviceStatus{
+ State: device.InstanceStateRunning,
+ Version: "han shot first",
+ }}
+)
+
+func testHelper(t *testing.T, lower, upper string) {
+ ctx, shutdown := test.V23Init()
+ defer shutdown()
+
+ tapes := newTapeMap()
+ server, endpoint, err := startServer(t, ctx, tapes)
+ if err != nil {
+ return
+ }
+ defer stopServer(t, server)
+
+ // Setup the command-line.
+ cmd := cmd_device.CmdRoot
+ var stdout, stderr bytes.Buffer
+ env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
+ appName := naming.JoinAddressName(endpoint.String(), "appname")
+
+ // Confirm that we correctly enforce the number of arguments.
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{lower}); err == nil {
+ t.Fatalf("wrongly failed to receive a non-nil error.")
+ }
+ if expected, got := "ERROR: "+lower+": incorrect number of arguments, expected 1, got 0", strings.TrimSpace(stderr.String()); !strings.HasPrefix(got, expected) {
+ t.Fatalf("Unexpected output from %s. Got %q, expected prefix %q", lower, got, expected)
+ }
+ stdout.Reset()
+ stderr.Reset()
+ appTape := tapes.forSuffix("appname")
+ appTape.Rewind()
+
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{lower, "nope", "nope"}); err == nil {
+ t.Fatalf("wrongly failed to receive a non-nil error.")
+ }
+ if expected, got := "ERROR: "+lower+": incorrect number of arguments, expected 1, got 2", strings.TrimSpace(stderr.String()); !strings.HasPrefix(got, expected) {
+ t.Fatalf("Unexpected output from %s. Got %q, expected prefix %q", lower, got, expected)
+ }
+ stdout.Reset()
+ stderr.Reset()
+ appTape.Rewind()
+
+ // Correct operation.
+ appTape.SetResponses(nil)
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{lower, appName}); err != nil {
+ t.Fatalf("%s failed when it shouldn't: %v", lower, err)
+ }
+ if expected, got := upper+" succeeded", strings.TrimSpace(stdout.String()); got != expected {
+ t.Fatalf("Unexpected output from %s. Got %q, expected %q", lower, got, expected)
+ }
+ if expected, got := []interface{}{upper}, appTape.Play(); !reflect.DeepEqual(expected, got) {
+ t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
+ }
+ appTape.Rewind()
+ stderr.Reset()
+ stdout.Reset()
+
+ // Test with bad parameters.
+ appTape.SetResponses(verror.New(errOops, nil))
+ if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, []string{lower, appName}); err == nil {
+ t.Fatalf("wrongly didn't receive a non-nil error.")
+ }
+ // expected the same.
+ if expected, got := []interface{}{upper}, appTape.Play(); !reflect.DeepEqual(expected, got) {
+ t.Errorf("invalid call sequence. Got %v, want %v", got, expected)
+ }
+}
diff --git a/services/device/device/v23_internal_test.go b/services/device/device/v23_internal_test.go
index dcd0029..ae59080 100644
--- a/services/device/device/v23_internal_test.go
+++ b/services/device/device/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package main
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/services/device/internal/impl/app_service.go b/services/device/internal/impl/app_service.go
index a393bb0..8b1ce68 100644
--- a/services/device/internal/impl/app_service.go
+++ b/services/device/internal/impl/app_service.go
@@ -1047,7 +1047,7 @@
return transitionInstallation(installationDir, device.InstallationStateActive, device.InstallationStateUninstalled)
}
-func updateInstance(instanceDir string, ctx *context.T) (err error) {
+func updateInstance(ctx *context.T, instanceDir string) (err error) {
// Only not-running instances can be updated.
if err := transitionInstance(instanceDir, device.InstanceStateNotRunning, device.InstanceStateUpdating); err != nil {
return err
@@ -1128,7 +1128,7 @@
return updateInstallation(ctx, installationDir)
}
if instanceDir, err := i.instanceDir(); err == nil {
- return updateInstance(instanceDir, ctx)
+ return updateInstance(ctx, instanceDir)
}
return verror.New(ErrInvalidSuffix, nil)
}
@@ -1138,11 +1138,38 @@
return nil
}
-func (i *appService) Revert(ctx *context.T, _ rpc.ServerCall) error {
- installationDir, err := i.installationDir()
- if err != nil {
+func revertInstance(ctx *context.T, instanceDir string) (err error) {
+ // Only not-running instances can be reverted.
+ if err := transitionInstance(instanceDir, device.InstanceStateNotRunning, device.InstanceStateUpdating); err != nil {
return err
}
+ defer func() {
+ terr := transitionInstance(instanceDir, device.InstanceStateUpdating, device.InstanceStateNotRunning)
+ if err == nil {
+ err = terr
+ }
+ }()
+ versionLink := filepath.Join(instanceDir, "version")
+ versionDir, err := filepath.EvalSymlinks(versionLink)
+ if err != nil {
+ return verror.New(ErrOperationFailed, ctx, fmt.Sprintf("EvalSymlinks(%v) failed: %v", versionLink, err))
+ }
+ previousLink := filepath.Join(versionDir, "previous")
+ if _, err := os.Lstat(previousLink); err != nil {
+ if os.IsNotExist(err) {
+ // No 'previous' link -- must be the first version.
+ return verror.New(ErrUpdateNoOp, ctx)
+ }
+ return verror.New(ErrOperationFailed, ctx, fmt.Sprintf("Lstat(%v) failed: %v", previousLink, err))
+ }
+ prevVersionDir, err := filepath.EvalSymlinks(previousLink)
+ if err != nil {
+ return verror.New(ErrOperationFailed, ctx, fmt.Sprintf("EvalSymlinks(%v) failed: %v", previousLink, err))
+ }
+ return updateLink(prevVersionDir, versionLink)
+}
+
+func revertInstallation(ctx *context.T, installationDir string) error {
if !installationStateIs(installationDir, device.InstallationStateActive) {
return verror.New(ErrInvalidOperation, ctx)
}
@@ -1171,6 +1198,16 @@
return updateLink(prevVersionDir, currLink)
}
+func (i *appService) Revert(ctx *context.T, _ rpc.ServerCall) error {
+ if installationDir, err := i.installationDir(); err == nil {
+ return revertInstallation(ctx, installationDir)
+ }
+ if instanceDir, err := i.instanceDir(); err == nil {
+ return revertInstance(ctx, instanceDir)
+ }
+ return verror.New(ErrInvalidSuffix, nil)
+}
+
type treeNode struct {
children map[string]*treeNode
}
diff --git a/services/device/internal/impl/applife/app_life_test.go b/services/device/internal/impl/applife/app_life_test.go
index 8484495..53ff693 100644
--- a/services/device/internal/impl/applife/app_life_test.go
+++ b/services/device/internal/impl/applife/app_life_test.go
@@ -57,7 +57,7 @@
// TestLifeOfAnApp installs an app, instantiates, runs, kills, and deletes
// several instances, and performs updates.
func TestLifeOfAnApp(t *testing.T) {
- ctx, shutdown := utiltest.InitForTest()
+ ctx, shutdown := utiltest.V23Init()
defer shutdown()
sh, deferFn := servicetest.CreateShellAndMountTable(t, ctx, nil)
@@ -78,7 +78,7 @@
// Set up the device manager. Since we won't do device manager updates,
// don't worry about its application envelope and current link.
- dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
+ dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManager, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
servicetest.ReadPID(t, dmh)
utiltest.ClaimDevice(t, ctx, "claimable", "dm", "mydevice", utiltest.NoPairingToken)
@@ -86,10 +86,10 @@
pingCh, cleanup := utiltest.SetupPingServer(t, ctx)
defer cleanup()
- utiltest.Resolve(t, ctx, "pingserver", 1)
+ utiltest.Resolve(t, ctx, "pingserver", 1, true)
// Create an envelope for a first version of the app.
- *envelope = utiltest.EnvelopeFromShell(sh, []string{utiltest.TestEnvVarName + "=env-val-envelope"}, utiltest.AppCmd, "google naps", 0, 0, fmt.Sprintf("--%s=flag-val-envelope", utiltest.TestFlagName), "appV1")
+ *envelope = utiltest.EnvelopeFromShell(sh, []string{utiltest.TestEnvVarName + "=env-val-envelope"}, utiltest.App, "google naps", 0, 0, fmt.Sprintf("--%s=flag-val-envelope", utiltest.TestFlagName), "appV1")
// Install the app. The config-specified flag value for testFlagName
// should override the value specified in the envelope above, and the
@@ -139,18 +139,18 @@
// Wait until the app pings us that it's ready.
pingCh.VerifyPingArgs(t, utiltest.UserName(t), "flag-val-install", "env-val-envelope")
- v1EP1 := utiltest.Resolve(t, ctx, "appV1", 1)[0]
+ v1EP1 := utiltest.Resolve(t, ctx, "appV1", 1, true)[0]
// Stop the app instance.
utiltest.KillApp(t, ctx, appID, instance1ID)
utiltest.VerifyState(t, ctx, device.InstanceStateNotRunning, appID, instance1ID)
- utiltest.ResolveExpectNotFound(t, ctx, "appV1")
+ utiltest.ResolveExpectNotFound(t, ctx, "appV1", true)
utiltest.RunApp(t, ctx, appID, instance1ID)
utiltest.VerifyState(t, ctx, device.InstanceStateRunning, appID, instance1ID)
pingCh.VerifyPingArgs(t, utiltest.UserName(t), "flag-val-install", "env-val-envelope") // Wait until the app pings us that it's ready.
oldV1EP1 := v1EP1
- if v1EP1 = utiltest.Resolve(t, ctx, "appV1", 1)[0]; v1EP1 == oldV1EP1 {
+ if v1EP1 = utiltest.Resolve(t, ctx, "appV1", 1, true)[0]; v1EP1 == oldV1EP1 {
t.Fatalf("Expected a new endpoint for the app after kill/run")
}
@@ -160,7 +160,7 @@
// There should be two endpoints mounted as "appV1", one for each
// instance of the app.
- endpoints := utiltest.Resolve(t, ctx, "appV1", 2)
+ endpoints := utiltest.Resolve(t, ctx, "appV1", 2, true)
v1EP2 := endpoints[0]
if endpoints[0] == v1EP1 {
v1EP2 = endpoints[1]
@@ -177,7 +177,8 @@
// Kill the first instance.
utiltest.KillApp(t, ctx, appID, instance1ID)
// Only the second instance should still be running and mounted.
- if want, got := v1EP2, utiltest.Resolve(t, ctx, "appV1", 1)[0]; want != got {
+ // In this case, we don't want to retry since we shouldn't need to.
+ if want, got := v1EP2, utiltest.Resolve(t, ctx, "appV1", 1, false)[0]; want != got {
t.Fatalf("Resolve(%v): want: %v, got %v", "appV1", want, got)
}
@@ -185,12 +186,12 @@
utiltest.UpdateAppExpectError(t, ctx, appID, impl.ErrUpdateNoOp.ID)
// Updating the installation should not work with a mismatched title.
- *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "bogus", 0, 0)
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.App, "bogus", 0, 0)
utiltest.UpdateAppExpectError(t, ctx, appID, impl.ErrAppTitleMismatch.ID)
// Create a second version of the app and update the app to it.
- *envelope = utiltest.EnvelopeFromShell(sh, []string{utiltest.TestEnvVarName + "=env-val-envelope"}, utiltest.AppCmd, "google naps", 0, 0, "appV2")
+ *envelope = utiltest.EnvelopeFromShell(sh, []string{utiltest.TestEnvVarName + "=env-val-envelope"}, utiltest.App, "google naps", 0, 0, "appV2")
utiltest.UpdateApp(t, ctx, appID)
@@ -199,8 +200,8 @@
t.Fatalf("Version did not change for %v: %v", appID, v1)
}
- // Second instance should still be running.
- if want, got := v1EP2, utiltest.Resolve(t, ctx, "appV1", 1)[0]; want != got {
+ // Second instance should still be running, don't retry.
+ if want, got := v1EP2, utiltest.Resolve(t, ctx, "appV1", 1, false)[0]; want != got {
t.Fatalf("Resolve(%v): want: %v, got %v", "appV1", want, got)
}
if v := utiltest.VerifyState(t, ctx, device.InstanceStateRunning, appID, instance2ID); v != v1 {
@@ -216,7 +217,7 @@
// Both instances should still be running the first version of the app.
// Check that the mounttable contains two endpoints, one of which is
// v1EP2.
- endpoints = utiltest.Resolve(t, ctx, "appV1", 2)
+ endpoints = utiltest.Resolve(t, ctx, "appV1", 2, true)
if endpoints[0] == v1EP2 {
if endpoints[1] == v1EP2 {
t.Fatalf("Both endpoints are the same")
@@ -229,8 +230,8 @@
utiltest.UpdateInstanceExpectError(t, ctx, appID, instance1ID, impl.ErrInvalidOperation.ID)
// Stop first instance and try again.
utiltest.KillApp(t, ctx, appID, instance1ID)
- // Only the second instance should still be running and mounted.
- if want, got := v1EP2, utiltest.Resolve(t, ctx, "appV1", 1)[0]; want != got {
+ // Only the second instance should still be running and mounted, don't retry.
+ if want, got := v1EP2, utiltest.Resolve(t, ctx, "appV1", 1, false)[0]; want != got {
t.Fatalf("Resolve(%v): want: %v, got %v", "appV1", want, got)
}
// Update succeeds now.
@@ -241,13 +242,22 @@
// Resume the first instance and verify it's running v2 now.
utiltest.RunApp(t, ctx, appID, instance1ID)
pingCh.VerifyPingArgs(t, utiltest.UserName(t), "flag-val-install", "env-val-envelope")
- utiltest.Resolve(t, ctx, "appV1", 1)
- utiltest.Resolve(t, ctx, "appV2", 1)
+ utiltest.Resolve(t, ctx, "appV1", 1, false)
+ utiltest.Resolve(t, ctx, "appV2", 1, false)
- // Stop first instance.
- utiltest.TerminateApp(t, ctx, appID, instance1ID)
+ // Reverting first instance fails since it's still running.
+ utiltest.RevertAppExpectError(t, ctx, appID+"/"+instance1ID, impl.ErrInvalidOperation.ID)
+ // Stop first instance and try again.
+ utiltest.KillApp(t, ctx, appID, instance1ID)
verifyAppWorkspace(t, root, appID, instance1ID)
- utiltest.ResolveExpectNotFound(t, ctx, "appV2")
+ utiltest.ResolveExpectNotFound(t, ctx, "appV2", true)
+ utiltest.RevertApp(t, ctx, appID+"/"+instance1ID)
+ // Resume the first instance and verify it's running v1 now.
+ utiltest.RunApp(t, ctx, appID, instance1ID)
+ pingCh.VerifyPingArgs(t, utiltest.UserName(t), "flag-val-install", "env-val-envelope")
+ utiltest.Resolve(t, ctx, "appV1", 2, false)
+ utiltest.TerminateApp(t, ctx, appID, instance1ID)
+ utiltest.Resolve(t, ctx, "appV1", 1, false)
// Start a third instance.
instance3ID := utiltest.LaunchApp(t, ctx, appID)
@@ -257,15 +267,18 @@
// Wait until the app pings us that it's ready.
pingCh.VerifyPingArgs(t, utiltest.UserName(t), "flag-val-install", "env-val-envelope")
- utiltest.Resolve(t, ctx, "appV2", 1)
+ utiltest.Resolve(t, ctx, "appV2", 1, true)
- // Stop second instance.
- utiltest.TerminateApp(t, ctx, appID, instance2ID)
- utiltest.ResolveExpectNotFound(t, ctx, "appV1")
+ // Suspend second instance.
+ utiltest.KillApp(t, ctx, appID, instance2ID)
+ utiltest.ResolveExpectNotFound(t, ctx, "appV1", true)
+
+ // Reverting second instance is a no-op since it's already running v1.
+ utiltest.RevertAppExpectError(t, ctx, appID+"/"+instance2ID, impl.ErrUpdateNoOp.ID)
// Stop third instance.
utiltest.TerminateApp(t, ctx, appID, instance3ID)
- utiltest.ResolveExpectNotFound(t, ctx, "appV2")
+ utiltest.ResolveExpectNotFound(t, ctx, "appV2", true)
// Revert the app.
utiltest.RevertApp(t, ctx, appID)
@@ -279,9 +292,9 @@
t.Fatalf("Instance version expected to be %v, got %v instead", v1, v)
}
pingCh.VerifyPingArgs(t, utiltest.UserName(t), "flag-val-install", "env-val-envelope") // Wait until the app pings us that it's ready.
- utiltest.Resolve(t, ctx, "appV1", 1)
+ utiltest.Resolve(t, ctx, "appV1", 1, true)
utiltest.TerminateApp(t, ctx, appID, instance4ID)
- utiltest.ResolveExpectNotFound(t, ctx, "appV1")
+ utiltest.ResolveExpectNotFound(t, ctx, "appV1", true)
// We are already on the first version, no further revert possible.
utiltest.RevertAppExpectError(t, ctx, appID, impl.ErrUpdateNoOp.ID)
@@ -303,7 +316,7 @@
// cleanly Do this by installing, instantiating, running, and killing
// hangingApp, which sleeps (rather than exits) after being asked to
// Stop()
- *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.HangingAppCmd, "hanging ap", 0, 0, "hAppV1")
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.HangingApp, "hanging ap", 0, 0, "hAppV1")
hAppID := utiltest.InstallApp(t, ctx)
hInstanceID := utiltest.LaunchApp(t, ctx, hAppID)
hangingPid := pingCh.WaitForPingArgs(t).Pid
diff --git a/services/device/internal/impl/applife/instance_reaping_test.go b/services/device/internal/impl/applife/instance_reaping_test.go
index dfe3592..78d0eca 100644
--- a/services/device/internal/impl/applife/instance_reaping_test.go
+++ b/services/device/internal/impl/applife/instance_reaping_test.go
@@ -23,7 +23,7 @@
// Set up the device manager. Since we won't do device manager updates,
// don't worry about its application envelope and current link.
- dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
+ dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManager, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
servicetest.ReadPID(t, dmh)
utiltest.ClaimDevice(t, ctx, "claimable", "dm", "mydevice", utiltest.NoPairingToken)
@@ -31,10 +31,10 @@
pingCh, cleanup := utiltest.SetupPingServer(t, ctx)
defer cleanup()
- utiltest.Resolve(t, ctx, "pingserver", 1)
+ utiltest.Resolve(t, ctx, "pingserver", 1, true)
// Create an envelope for a first version of the app.
- *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps", 0, 0, "appV1")
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.App, "google naps", 0, 0, "appV1")
// Install the app. The config-specified flag value for testFlagName
// should override the value specified in the envelope above.
diff --git a/services/device/internal/impl/daemonreap/daemon_reaping_test.go b/services/device/internal/impl/daemonreap/daemon_reaping_test.go
index 84d0602..bcf4fc9 100644
--- a/services/device/internal/impl/daemonreap/daemon_reaping_test.go
+++ b/services/device/internal/impl/daemonreap/daemon_reaping_test.go
@@ -24,7 +24,7 @@
// Set up the device manager. Since we won't do device manager updates,
// don't worry about its application envelope and current link.
- dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
+ dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManager, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
servicetest.ReadPID(t, dmh)
utiltest.ClaimDevice(t, ctx, "claimable", "dm", "mydevice", utiltest.NoPairingToken)
@@ -32,10 +32,10 @@
pingCh, cleanup := utiltest.SetupPingServer(t, ctx)
defer cleanup()
- utiltest.Resolve(t, ctx, "pingserver", 1)
+ utiltest.Resolve(t, ctx, "pingserver", 1, true)
// Create an envelope for a first version of the app that will be restarted once.
- *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps", 1, 10*time.Second, "appV1")
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.App, "google naps", 1, 10*time.Second, "appV1")
appID := utiltest.InstallApp(t, ctx)
// Start an instance of the app.
diff --git a/services/device/internal/impl/daemonreap/instance_reaping_kill_test.go b/services/device/internal/impl/daemonreap/instance_reaping_kill_test.go
index c04f8b0..b756afd 100644
--- a/services/device/internal/impl/daemonreap/instance_reaping_kill_test.go
+++ b/services/device/internal/impl/daemonreap/instance_reaping_kill_test.go
@@ -32,17 +32,17 @@
defer os.RemoveAll(dmCreds)
dmEnv := []string{fmt.Sprintf("%v=%v", ref.EnvCredentials, dmCreds)}
- dmh := servicetest.RunCommand(t, sh, dmEnv, utiltest.DeviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
+ dmh := servicetest.RunCommand(t, sh, dmEnv, utiltest.DeviceManager, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
servicetest.ReadPID(t, dmh)
utiltest.ClaimDevice(t, ctx, "claimable", "dm", "mydevice", utiltest.NoPairingToken)
// Create the local server that the app uses to let us know it's ready.
pingCh, cleanup := utiltest.SetupPingServer(t, ctx)
defer cleanup()
- utiltest.Resolve(t, ctx, "pingserver", 1)
+ utiltest.Resolve(t, ctx, "pingserver", 1, true)
// Create an envelope for the app.
- *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps", 0, 0, "appV1")
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.App, "google naps", 0, 0, "appV1")
// Install the app.
appID := utiltest.InstallApp(t, ctx)
@@ -62,7 +62,7 @@
dmh.Expect("dm terminated")
dmh.ExpectEOF()
dmh.Shutdown(os.Stderr, os.Stderr)
- utiltest.ResolveExpectNotFound(t, ctx, "dm") // Ensure a clean slate.
+ utiltest.ResolveExpectNotFound(t, ctx, "dm", false) // Ensure a clean slate.
// Kill instance[0] and wait until it exits before proceeding.
syscall.Kill(pid, 9)
@@ -77,9 +77,9 @@
}
// Run another device manager to replace the dead one.
- dmh = servicetest.RunCommand(t, sh, dmEnv, utiltest.DeviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
+ dmh = servicetest.RunCommand(t, sh, dmEnv, utiltest.DeviceManager, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
servicetest.ReadPID(t, dmh)
- utiltest.Resolve(t, ctx, "dm", 1) // Verify the device manager has published itself.
+ utiltest.Resolve(t, ctx, "dm", 1, true) // Verify the device manager has published itself.
// By now, we've reconciled the state of the tree with which processes
// are actually alive. instance-0 is not alive.
diff --git a/services/device/internal/impl/device_service.go b/services/device/internal/impl/device_service.go
index ce87157..1b033b9 100644
--- a/services/device/internal/impl/device_service.go
+++ b/services/device/internal/impl/device_service.go
@@ -671,7 +671,7 @@
if versionDir == "." {
versionDir = "base"
}
- return device.StatusInstance{Value: device.InstanceStatus{
+ return device.StatusDevice{Value: device.DeviceStatus{
State: state,
Version: versionDir,
}}, nil
diff --git a/services/device/internal/impl/globsuid/glob_test.go b/services/device/internal/impl/globsuid/glob_test.go
index 30fdc23..dfa826d 100644
--- a/services/device/internal/impl/globsuid/glob_test.go
+++ b/services/device/internal/impl/globsuid/glob_test.go
@@ -15,7 +15,7 @@
)
func TestDeviceManagerGlobAndDebug(t *testing.T) {
- ctx, shutdown := utiltest.InitForTest()
+ ctx, shutdown := utiltest.V23Init()
defer shutdown()
sh, deferFn := servicetest.CreateShellAndMountTable(t, ctx, nil)
@@ -36,7 +36,7 @@
// Set up the device manager. Since we won't do device manager updates,
// don't worry about its application envelope and current link.
- dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
+ dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManager, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
pid := servicetest.ReadPID(t, dmh)
defer syscall.Kill(pid, syscall.SIGINT)
@@ -45,7 +45,7 @@
defer cleanup()
// Create the envelope for the first version of the app.
- *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps", 0, 0, "appV1")
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.App, "google naps", 0, 0, "appV1")
// Device must be claimed before applications can be installed.
utiltest.ClaimDevice(t, ctx, "claimable", "dm", "mydevice", utiltest.NoPairingToken)
diff --git a/services/device/internal/impl/globsuid/signature_match_test.go b/services/device/internal/impl/globsuid/signature_match_test.go
index ded825f..fa79511 100644
--- a/services/device/internal/impl/globsuid/signature_match_test.go
+++ b/services/device/internal/impl/globsuid/signature_match_test.go
@@ -26,7 +26,7 @@
)
func TestDownloadSignatureMatch(t *testing.T) {
- ctx, shutdown := utiltest.InitForTest()
+ ctx, shutdown := utiltest.V23Init()
defer shutdown()
sh, deferFn := servicetest.CreateShellAndMountTable(t, ctx, nil)
@@ -73,7 +73,7 @@
// Set up the device manager. Since we won't do device manager updates,
// don't worry about its application envelope and current link.
- dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
+ dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManager, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
pid := servicetest.ReadPID(t, dmh)
defer syscall.Kill(pid, syscall.SIGINT)
utiltest.ClaimDevice(t, ctx, "claimable", "dm", "mydevice", utiltest.NoPairingToken)
diff --git a/services/device/internal/impl/globsuid/suid_test.go b/services/device/internal/impl/globsuid/suid_test.go
index 12afe73..de99a2f 100644
--- a/services/device/internal/impl/globsuid/suid_test.go
+++ b/services/device/internal/impl/globsuid/suid_test.go
@@ -38,7 +38,7 @@
}
func TestAppWithSuidHelper(t *testing.T) {
- ctx, shutdown := utiltest.InitForTest()
+ ctx, shutdown := utiltest.V23Init()
defer shutdown()
// Identity provider used to ensure that all processes recognize each
@@ -67,7 +67,7 @@
// Create a script wrapping the test target that implements suidhelper.
helperPath := utiltest.GenerateSuidHelperScript(t, root)
- dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManagerCmd, "-mocksetuid", "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
+ dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManager, "-mocksetuid", "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
pid := servicetest.ReadPID(t, dmh)
defer syscall.Kill(pid, syscall.SIGINT)
defer utiltest.VerifyNoRunningProcesses(t)
@@ -82,7 +82,7 @@
defer cleanup()
// Create an envelope for a first version of the app.
- *envelope = utiltest.EnvelopeFromShell(sh, []string{utiltest.TestEnvVarName + "=env-var"}, utiltest.AppCmd, "google naps", 0, 0, fmt.Sprintf("--%s=flag-val-envelope", utiltest.TestFlagName), "appV1")
+ *envelope = utiltest.EnvelopeFromShell(sh, []string{utiltest.TestEnvVarName + "=env-var"}, utiltest.App, "google naps", 0, 0, fmt.Sprintf("--%s=flag-val-envelope", utiltest.TestFlagName), "appV1")
// Install and start the app as root/self.
appID := utiltest.InstallApp(t, selfCtx)
diff --git a/services/device/internal/impl/impl_test.go b/services/device/internal/impl/impl_test.go
index 8e21f14..a0cb125 100644
--- a/services/device/internal/impl/impl_test.go
+++ b/services/device/internal/impl/impl_test.go
@@ -74,7 +74,7 @@
// command. Further versions are running through the soft link that the device
// manager itself updates.
func TestDeviceManagerUpdateAndRevert(t *testing.T) {
- ctx, shutdown := utiltest.InitForTest()
+ ctx, shutdown := utiltest.V23Init()
defer shutdown()
sh, deferFn := servicetest.CreateShellAndMountTable(t, ctx, v23.GetPrincipal(ctx))
@@ -108,7 +108,7 @@
defer os.RemoveAll(dmCreds)
dmEnv := []string{fmt.Sprintf("%v=%v", ref.EnvCredentials, dmCreds)}
dmArgs := []string{"factoryDM", root, "unused_helper", utiltest.MockApplicationRepoName, currLink}
- args, env := sh.CommandEnvelope(utiltest.DeviceManagerCmd, dmEnv, dmArgs...)
+ args, env := sh.ProgramEnvelope(dmEnv, utiltest.DeviceManager, dmArgs...)
scriptPathFactory := generateDeviceManagerScript(t, root, args, env)
if err := os.Symlink(scriptPathFactory, currLink); err != nil {
@@ -126,14 +126,14 @@
// demonstrates that the initial device manager could be running by hand
// as long as the right initial configuration is passed into the device
// manager implementation.
- dmh := servicetest.RunCommand(t, sh, dmPauseBeforeStopEnv, utiltest.DeviceManagerCmd, dmArgs...)
+ dmh := servicetest.RunCommand(t, sh, dmPauseBeforeStopEnv, utiltest.DeviceManager, dmArgs...)
defer func() {
syscall.Kill(dmh.Pid(), syscall.SIGINT)
utiltest.VerifyNoRunningProcesses(t)
}()
servicetest.ReadPID(t, dmh)
- utiltest.Resolve(t, ctx, "claimable", 1)
+ utiltest.Resolve(t, ctx, "claimable", 1, true)
// Brand new device manager must be claimed first.
utiltest.ClaimDevice(t, ctx, "claimable", "factoryDM", "mydevice", utiltest.NoPairingToken)
@@ -142,7 +142,7 @@
}
// Simulate an invalid envelope in the application repository.
- *envelope = utiltest.EnvelopeFromShell(sh, dmPauseBeforeStopEnv, utiltest.DeviceManagerCmd, "bogus", 0, 0, dmArgs...)
+ *envelope = utiltest.EnvelopeFromShell(sh, dmPauseBeforeStopEnv, utiltest.DeviceManager, "bogus", 0, 0, dmArgs...)
utiltest.UpdateDeviceExpectError(t, ctx, "factoryDM", impl.ErrAppTitleMismatch.ID)
utiltest.RevertDeviceExpectError(t, ctx, "factoryDM", impl.ErrUpdateNoOp.ID)
@@ -150,7 +150,7 @@
// Set up a second version of the device manager. The information in the
// envelope will be used by the device manager to stage the next
// version.
- *envelope = utiltest.EnvelopeFromShell(sh, dmEnv, utiltest.DeviceManagerCmd, application.DeviceManagerTitle, 0, 0, "v2DM")
+ *envelope = utiltest.EnvelopeFromShell(sh, dmEnv, utiltest.DeviceManager, application.DeviceManagerTitle, 0, 0, "v2DM")
utiltest.UpdateDevice(t, ctx, "factoryDM")
// Current link should have been updated to point to v2.
@@ -177,12 +177,12 @@
// A successful update means the device manager has stopped itself. We
// relaunch it from the current link.
- utiltest.ResolveExpectNotFound(t, ctx, "v2DM") // Ensure a clean slate.
+ utiltest.ResolveExpectNotFound(t, ctx, "v2DM", false) // Ensure a clean slate.
- dmh = servicetest.RunCommand(t, sh, dmEnv, utiltest.ExecScriptCmd, currLink)
+ dmh = servicetest.RunCommand(t, sh, dmEnv, utiltest.ExecScript, currLink)
servicetest.ReadPID(t, dmh)
- utiltest.Resolve(t, ctx, "v2DM", 1) // Current link should have been launching v2.
+ utiltest.Resolve(t, ctx, "v2DM", 1, true) // Current link should have been launching v2.
// Try issuing an update without changing the envelope in the
// application repository: this should fail, and current link should be
@@ -194,8 +194,8 @@
// Try issuing an update with a binary that has a different major version
// number. It should fail.
- utiltest.ResolveExpectNotFound(t, ctx, "v2.5DM") // Ensure a clean slate.
- *envelope = utiltest.EnvelopeFromShell(sh, dmEnv, utiltest.DeviceManagerV10Cmd, application.DeviceManagerTitle, 0, 0, "v2.5DM")
+ utiltest.ResolveExpectNotFound(t, ctx, "v2.5DM", false) // Ensure a clean slate.
+ *envelope = utiltest.EnvelopeFromShell(sh, dmEnv, utiltest.DeviceManagerV10, application.DeviceManagerTitle, 0, 0, "v2.5DM")
utiltest.UpdateDeviceExpectError(t, ctx, "v2DM", impl.ErrOperationFailed.ID)
if evalLink() != scriptPathV2 {
@@ -203,7 +203,7 @@
}
// Create a third version of the device manager and issue an update.
- *envelope = utiltest.EnvelopeFromShell(sh, dmEnv, utiltest.DeviceManagerCmd, application.DeviceManagerTitle, 0, 0, "v3DM")
+ *envelope = utiltest.EnvelopeFromShell(sh, dmEnv, utiltest.DeviceManager, application.DeviceManagerTitle, 0, 0, "v3DM")
utiltest.UpdateDevice(t, ctx, "v2DM")
scriptPathV3 := evalLink()
@@ -216,15 +216,15 @@
dmh.Shutdown(os.Stderr, os.Stderr)
- utiltest.ResolveExpectNotFound(t, ctx, "v3DM") // Ensure a clean slate.
+ utiltest.ResolveExpectNotFound(t, ctx, "v3DM", false) // Ensure a clean slate.
// Re-lanuch the device manager from current link. We instruct the
// device manager to pause before stopping its server, so that we can
// verify that a second revert fails while a revert is in progress.
- dmh = servicetest.RunCommand(t, sh, dmPauseBeforeStopEnv, utiltest.ExecScriptCmd, currLink)
+ dmh = servicetest.RunCommand(t, sh, dmPauseBeforeStopEnv, utiltest.ExecScript, currLink)
servicetest.ReadPID(t, dmh)
- utiltest.Resolve(t, ctx, "v3DM", 1) // Current link should have been launching v3.
+ utiltest.Resolve(t, ctx, "v3DM", 1, true) // Current link should have been launching v3.
v3 := utiltest.VerifyDeviceState(t, ctx, device.InstanceStateRunning, "v3DM")
if v2 == v3 {
t.Fatalf("version didn't change")
@@ -241,11 +241,11 @@
}
dmh.Shutdown(os.Stderr, os.Stderr)
- utiltest.ResolveExpectNotFound(t, ctx, "v2DM") // Ensure a clean slate.
+ utiltest.ResolveExpectNotFound(t, ctx, "v2DM", false) // Ensure a clean slate.
- dmh = servicetest.RunCommand(t, sh, dmEnv, utiltest.ExecScriptCmd, currLink)
+ dmh = servicetest.RunCommand(t, sh, dmEnv, utiltest.ExecScript, currLink)
servicetest.ReadPID(t, dmh)
- utiltest.Resolve(t, ctx, "v2DM", 1) // Current link should have been launching v2.
+ utiltest.Resolve(t, ctx, "v2DM", 1, true) // Current link should have been launching v2.
// Revert the device manager to its previous version (factory).
utiltest.RevertDevice(t, ctx, "v2DM")
@@ -256,20 +256,20 @@
}
dmh.Shutdown(os.Stderr, os.Stderr)
- utiltest.ResolveExpectNotFound(t, ctx, "factoryDM") // Ensure a clean slate.
+ utiltest.ResolveExpectNotFound(t, ctx, "factoryDM", false) // Ensure a clean slate.
- dmh = servicetest.RunCommand(t, sh, dmEnv, utiltest.ExecScriptCmd, currLink)
+ dmh = servicetest.RunCommand(t, sh, dmEnv, utiltest.ExecScript, currLink)
servicetest.ReadPID(t, dmh)
- utiltest.Resolve(t, ctx, "factoryDM", 1) // Current link should have been launching factory version.
+ utiltest.Resolve(t, ctx, "factoryDM", 1, true) // Current link should have been launching factory version.
utiltest.ShutdownDevice(t, ctx, "factoryDM")
dmh.Expect("factoryDM terminated")
dmh.ExpectEOF()
// Re-launch the device manager, to exercise the behavior of Stop.
- utiltest.ResolveExpectNotFound(t, ctx, "factoryDM") // Ensure a clean slate.
- dmh = servicetest.RunCommand(t, sh, dmEnv, utiltest.ExecScriptCmd, currLink)
+ utiltest.ResolveExpectNotFound(t, ctx, "factoryDM", false) // Ensure a clean slate.
+ dmh = servicetest.RunCommand(t, sh, dmEnv, utiltest.ExecScript, currLink)
servicetest.ReadPID(t, dmh)
- utiltest.Resolve(t, ctx, "factoryDM", 1)
+ utiltest.Resolve(t, ctx, "factoryDM", 1, true)
utiltest.KillDevice(t, ctx, "factoryDM")
dmh.Expect("restart handler")
dmh.Expect("factoryDM terminated")
@@ -292,7 +292,7 @@
// This should bring up a functioning device manager. In the end it runs
// Uninstall and verifies that the installation is gone.
func TestDeviceManagerInstallation(t *testing.T) {
- ctx, shutdown := utiltest.InitForTest()
+ ctx, shutdown := utiltest.V23Init()
defer shutdown()
sh, deferFn := servicetest.CreateShellAndMountTable(t, ctx, nil)
@@ -310,7 +310,7 @@
// Create an 'envelope' for the device manager that we can pass to the
// installer, to ensure that the device manager that the installer
// configures can run.
- dmargs, dmenv := sh.CommandEnvelope(utiltest.DeviceManagerCmd, nil, "dm")
+ dmargs, dmenv := sh.ProgramEnvelope(nil, utiltest.DeviceManager, "dm")
dmDir := filepath.Join(testDir, "dm")
// TODO(caprita): Add test logic when initMode = true.
singleUser, sessionMode, initMode := true, true, false
@@ -318,7 +318,7 @@
t.Fatalf("SelfInstall failed: %v", err)
}
- utiltest.ResolveExpectNotFound(t, ctx, "dm")
+ utiltest.ResolveExpectNotFound(t, ctx, "dm", false)
// Start the device manager.
stdout := make(simpleRW, 100)
defer os.Setenv(utiltest.RedirectEnv, os.Getenv(utiltest.RedirectEnv))
@@ -354,7 +354,7 @@
// TODO(caprita): We need better test coverage for how updating/reverting apps
// affects the package configured for the app.
func TestDeviceManagerPackages(t *testing.T) {
- ctx, shutdown := utiltest.InitForTest()
+ ctx, shutdown := utiltest.V23Init()
defer shutdown()
sh, deferFn := servicetest.CreateShellAndMountTable(t, ctx, nil)
@@ -404,7 +404,7 @@
// Set up the device manager. Since we won't do device manager updates,
// don't worry about its application envelope and current link.
- dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
+ dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManager, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
pid := servicetest.ReadPID(t, dmh)
defer syscall.Kill(pid, syscall.SIGINT)
defer utiltest.VerifyNoRunningProcesses(t)
@@ -414,7 +414,7 @@
defer cleanup()
// Create the envelope for the first version of the app.
- *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps", 0, 0, "appV1")
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.App, "google naps", 0, 0, "appV1")
envelope.Packages = map[string]application.SignedFile{
"test": application.SignedFile{
File: "realbin/testpkg",
@@ -494,7 +494,7 @@
// TODO(rjkroege): Verify that associations persist across restarts once
// permanent storage is added.
func TestAccountAssociation(t *testing.T) {
- ctx, shutdown := utiltest.InitForTest()
+ ctx, shutdown := utiltest.V23Init()
defer shutdown()
sh, deferFn := servicetest.CreateShellAndMountTable(t, ctx, nil)
@@ -519,7 +519,7 @@
v23.GetPrincipal(c).AddToRoots(v23.GetPrincipal(ctx).BlessingStore().Default())
}
- dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManagerCmd, "dm", root, "unused_helper", "unused_app_repo_name", "unused_curr_link")
+ dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManager, "dm", root, "unused_helper", "unused_app_repo_name", "unused_curr_link")
pid := servicetest.ReadPID(t, dmh)
defer syscall.Kill(pid, syscall.SIGINT)
defer utiltest.VerifyNoRunningProcesses(t)
diff --git a/services/device/internal/impl/perms/debug_perms_test.go b/services/device/internal/impl/perms/debug_perms_test.go
index 296c3b8..e643c12 100644
--- a/services/device/internal/impl/perms/debug_perms_test.go
+++ b/services/device/internal/impl/perms/debug_perms_test.go
@@ -44,14 +44,14 @@
defer cleanup()
// Set up the device manager.
- dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
+ dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManager, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
servicetest.ReadPID(t, dmh)
utiltest.ClaimDevice(t, ctx, "claimable", "dm", "mydevice", utiltest.NoPairingToken)
// Create the local server that the app uses to let us know it's ready.
pingCh, cleanup := utiltest.SetupPingServer(t, ctx)
defer cleanup()
- utiltest.Resolve(t, ctx, "pingserver", 1)
+ utiltest.Resolve(t, ctx, "pingserver", 1, true)
// Make some users.
selfCtx := ctx
@@ -62,7 +62,7 @@
// TODO(rjkroege): Set AccessLists here that conflict with the one provided by the device
// manager and show that the one set here is overridden.
// Create the envelope for the first version of the app.
- *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps", 0, 0, "appV1")
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.App, "google naps", 0, 0, "appV1")
// Install the app.
appID := utiltest.InstallApp(t, ctx)
@@ -200,7 +200,7 @@
}
// Set up the device manager.
- dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManagerCmd, "--log_dir="+extraLogDir, "dm", root, helperPath, "unused", "unused_curr_link")
+ dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManager, "--log_dir="+extraLogDir, "dm", root, helperPath, "unused", "unused_curr_link")
servicetest.ReadPID(t, dmh)
// Make some users.
diff --git a/services/device/internal/impl/perms/perms_test.go b/services/device/internal/impl/perms/perms_test.go
index 69fe3c1..99b4e84 100644
--- a/services/device/internal/impl/perms/perms_test.go
+++ b/services/device/internal/impl/perms/perms_test.go
@@ -26,7 +26,7 @@
// TestDeviceManagerClaim claims a devicemanager and tests AccessList permissions on
// its methods.
func TestDeviceManagerClaim(t *testing.T) {
- ctx, shutdown := utiltest.InitForTest()
+ ctx, shutdown := utiltest.V23Init()
defer shutdown()
// root blessing provider so that the principals of all the contexts
@@ -55,11 +55,11 @@
// Set up the device manager. Since we won't do device manager updates,
// don't worry about its application envelope and current link.
pairingToken := "abcxyz"
- dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link", pairingToken)
+ dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManager, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link", pairingToken)
pid := servicetest.ReadPID(t, dmh)
defer syscall.Kill(pid, syscall.SIGINT)
- *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps", 0, 0, "trapp")
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.App, "google naps", 0, 0, "trapp")
claimantCtx := utiltest.CtxWithNewPrincipal(t, ctx, idp, "claimant")
octx, err := v23.WithPrincipal(ctx, testutil.NewPrincipal("other"))
@@ -103,14 +103,14 @@
// Wait until the app pings us that it's ready.
pingCh.WaitForPingArgs(t)
- utiltest.Resolve(t, ctx, "trapp", 1)
+ utiltest.Resolve(t, ctx, "trapp", 1, false)
utiltest.KillApp(t, claimantCtx, appID, instanceID)
// TODO(gauthamt): Test that AccessLists persist across devicemanager restarts
}
func TestDeviceManagerUpdateAccessList(t *testing.T) {
- ctx, shutdown := utiltest.InitForTest()
+ ctx, shutdown := utiltest.V23Init()
defer shutdown()
// Identity provider to ensure that all processes recognize each
@@ -136,13 +136,13 @@
// Set up the device manager. Since we won't do device manager updates,
// don't worry about its application envelope and current link.
- dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManagerCmd, "dm", root, "unused_helper", "unused_app_repo_name", "unused_curr_link")
+ dmh := servicetest.RunCommand(t, sh, nil, utiltest.DeviceManager, "dm", root, "unused_helper", "unused_app_repo_name", "unused_curr_link")
pid := servicetest.ReadPID(t, dmh)
defer syscall.Kill(pid, syscall.SIGINT)
defer utiltest.VerifyNoRunningProcesses(t)
// Create an envelope for an app.
- *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps", 0, 0)
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.App, "google naps", 0, 0)
// On an unclaimed device manager, there will be no AccessLists.
if _, _, err := device.DeviceClient("claimable").GetPermissions(selfCtx); err == nil {
diff --git a/services/device/internal/impl/proxy_invoker_test.go b/services/device/internal/impl/proxy_invoker_test.go
index 8cb7bf7..ad4a8aa 100644
--- a/services/device/internal/impl/proxy_invoker_test.go
+++ b/services/device/internal/impl/proxy_invoker_test.go
@@ -23,7 +23,7 @@
// TODO(toddw): Add tests of Signature and MethodSignature.
func TestProxyInvoker(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
diff --git a/services/device/internal/impl/reaping/instance_reaping_test.go b/services/device/internal/impl/reaping/instance_reaping_test.go
index 81dd2ac..55ed52f 100644
--- a/services/device/internal/impl/reaping/instance_reaping_test.go
+++ b/services/device/internal/impl/reaping/instance_reaping_test.go
@@ -33,17 +33,17 @@
defer os.RemoveAll(dmCreds)
dmEnv := []string{fmt.Sprintf("%v=%v", ref.EnvCredentials, dmCreds), fmt.Sprintf("%v=%v", impl.AppcycleReconciliation, "1")}
- dmh := servicetest.RunCommand(t, sh, dmEnv, utiltest.DeviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
+ dmh := servicetest.RunCommand(t, sh, dmEnv, utiltest.DeviceManager, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
servicetest.ReadPID(t, dmh)
utiltest.ClaimDevice(t, ctx, "claimable", "dm", "mydevice", utiltest.NoPairingToken)
// Create the local server that the app uses to let us know it's ready.
pingCh, cleanup := utiltest.SetupPingServer(t, ctx)
defer cleanup()
- utiltest.Resolve(t, ctx, "pingserver", 1)
+ utiltest.Resolve(t, ctx, "pingserver", 1, true)
// Create an envelope for the app.
- *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps", 0, 0, "appV1")
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.App, "google naps", 0, 0, "appV1")
// Install the app.
appID := utiltest.InstallApp(t, ctx)
@@ -63,7 +63,7 @@
dmh.Expect("dm terminated")
dmh.ExpectEOF()
dmh.Shutdown(os.Stderr, os.Stderr)
- utiltest.ResolveExpectNotFound(t, ctx, "dm") // Ensure a clean slate.
+ utiltest.ResolveExpectNotFound(t, ctx, "dm", false) // Ensure a clean slate.
// Kill instance[0] and wait until it exits before proceeding.
syscall.Kill(pid, 9)
@@ -78,9 +78,9 @@
}
// Run another device manager to replace the dead one.
- dmh = servicetest.RunCommand(t, sh, dmEnv, utiltest.DeviceManagerCmd, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
+ dmh = servicetest.RunCommand(t, sh, dmEnv, utiltest.DeviceManager, "dm", root, helperPath, "unused_app_repo_name", "unused_curr_link")
servicetest.ReadPID(t, dmh)
- utiltest.Resolve(t, ctx, "dm", 1) // Verify the device manager has published itself.
+ utiltest.Resolve(t, ctx, "dm", 1, true) // Verify the device manager has published itself.
// By now, we've reconciled the state of the tree with which processes
// are actually alive. instance-0 is not alive.
diff --git a/services/device/internal/impl/utiltest/app.go b/services/device/internal/impl/utiltest/app.go
index 47d88a4..7ef524b 100644
--- a/services/device/internal/impl/utiltest/app.go
+++ b/services/device/internal/impl/utiltest/app.go
@@ -8,7 +8,6 @@
"encoding/json"
"flag"
"fmt"
- "io"
"io/ioutil"
"os"
"path/filepath"
@@ -22,13 +21,12 @@
"v.io/v23/naming"
"v.io/v23/rpc"
"v.io/v23/security"
-
"v.io/x/lib/vlog"
-
"v.io/x/ref/lib/signals"
"v.io/x/ref/services/device/internal/suid"
"v.io/x/ref/services/internal/servicetest"
"v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
"v.io/x/ref/test/testutil"
)
@@ -113,9 +111,11 @@
return content, nil
}
-// app is a test application. It pings the invoking device manager with state information.
-func app(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- ctx, shutdown := test.InitForTest()
+// App is a test application. It pings the invoking device manager with state information.
+var App = modules.Register(appFunc, "App")
+
+func appFunc(env *modules.Env, args ...string) error {
+ ctx, shutdown := test.V23Init()
defer shutdown()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
@@ -193,9 +193,10 @@
}
}
-// Same as app, except that it does not exit properly after being stopped
-func hangingApp(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- err := app(stdin, stdout, stderr, env, args...)
+// HangingApp is the same as App, except that it does not exit properly after
+// being stopped.
+var HangingApp = modules.Register(func(env *modules.Env, args ...string) error {
+ err := appFunc(env, args...)
time.Sleep(24 * time.Hour)
return err
-}
+}, "HangingApp")
diff --git a/services/device/internal/impl/utiltest/helpers.go b/services/device/internal/impl/utiltest/helpers.go
index d461eb2..614ff22 100644
--- a/services/device/internal/impl/utiltest/helpers.go
+++ b/services/device/internal/impl/utiltest/helpers.go
@@ -69,8 +69,8 @@
}
}
-func EnvelopeFromShell(sh *modules.Shell, env []string, cmd, title string, retries int, window time.Duration, args ...string) application.Envelope {
- args, nenv := sh.CommandEnvelope(cmd, env, args...)
+func EnvelopeFromShell(sh *modules.Shell, env []string, prog modules.Program, title string, retries int, window time.Duration, args ...string) application.Envelope {
+ args, nenv := sh.ProgramEnvelope(env, prog, args...)
return application.Envelope{
Title: title,
Args: args[1:],
@@ -84,32 +84,51 @@
}
// ResolveExpectNotFound verifies that the given name is not in the mounttable.
-func ResolveExpectNotFound(t *testing.T, ctx *context.T, name string) {
- if me, err := v23.GetNamespace(ctx).Resolve(ctx, name); err == nil {
- t.Fatalf(testutil.FormatLogLine(2, "Resolve(%v) succeeded with results %v when it was expected to fail", name, me.Names()))
- } else if expectErr := naming.ErrNoSuchName.ID; verror.ErrorID(err) != expectErr {
- t.Fatalf(testutil.FormatLogLine(2, "Resolve(%v) failed with error %v, expected error ID %v", name, err, expectErr))
+func ResolveExpectNotFound(t *testing.T, ctx *context.T, name string, retry bool) {
+ expectErr := naming.ErrNoSuchName.ID
+ for {
+ me, err := v23.GetNamespace(ctx).Resolve(ctx, name)
+ if err == nil || verror.ErrorID(err) != expectErr {
+ if retry {
+ time.Sleep(10 * time.Millisecond)
+ continue
+ }
+ if err == nil {
+ t.Fatalf(testutil.FormatLogLine(2, "Resolve(%v) succeeded with results %v when it was expected to fail", name, me.Names()))
+ } else {
+ t.Fatalf(testutil.FormatLogLine(2, "Resolve(%v) failed with error %v, expected error ID %v", name, err, expectErr))
+ }
+ } else {
+ return
+ }
}
}
// Resolve looks up the given name in the mounttable.
-func Resolve(t *testing.T, ctx *context.T, name string, replicas int) []string {
- me, err := v23.GetNamespace(ctx).Resolve(ctx, name)
- if err != nil {
- t.Fatalf("Resolve(%v) failed: %v", name, err)
- }
-
- filteredResults := []string{}
- for _, r := range me.Names() {
- if strings.Index(r, "@tcp") != -1 {
- filteredResults = append(filteredResults, r)
+func Resolve(t *testing.T, ctx *context.T, name string, replicas int, retry bool) []string {
+ for {
+ me, err := v23.GetNamespace(ctx).Resolve(ctx, name)
+ if err != nil {
+ if retry {
+ time.Sleep(10 * time.Millisecond)
+ continue
+ } else {
+ t.Fatalf("Resolve(%v) failed: %v", name, err)
+ }
}
+
+ filteredResults := []string{}
+ for _, r := range me.Names() {
+ if strings.Index(r, "@tcp") != -1 {
+ filteredResults = append(filteredResults, r)
+ }
+ }
+ // We are going to get a websocket and a tcp endpoint for each replica.
+ if want, got := replicas, len(filteredResults); want != got {
+ t.Fatalf("Resolve(%v) expected %d result(s), got %d instead", name, want, got)
+ }
+ return filteredResults
}
- // We are going to get a websocket and a tcp endpoint for each replica.
- if want, got := replicas, len(filteredResults); want != got {
- t.Fatalf("Resolve(%v) expected %d result(s), got %d instead", name, want, got)
- }
- return filteredResults
}
// The following set of functions are convenience wrappers around Update and
@@ -390,7 +409,7 @@
if err != nil {
t.Fatalf(testutil.FormatLogLine(2, "Status(%v) failed: %v [%v]", name, verror.ErrorID(err), err))
}
- status, ok := s.(device.StatusInstance)
+ status, ok := s.(device.StatusDevice)
if !ok {
t.Fatalf(testutil.FormatLogLine(2, "Status(%v) returned unknown type: %T", name, s))
}
@@ -509,7 +528,7 @@
// TODO(rjkroege): This helper is generally useful. Use it to reduce
// boiler plate across all device manager tests.
func StartupHelper(t *testing.T) (func(), *context.T, *modules.Shell, *application.Envelope, string, string, *testutil.IDProvider) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
// Make a new identity context.
@@ -700,12 +719,12 @@
return u.Username
}
-func InitForTest() (*context.T, v23.Shutdown) {
+func V23Init() (*context.T, v23.Shutdown) {
roots, _ := ref.EnvNamespaceRoots()
for key, _ := range roots {
os.Unsetenv(key)
}
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
return ctx, shutdown
}
diff --git a/services/device/internal/impl/utiltest/modules.go b/services/device/internal/impl/utiltest/modules.go
index 96d6f6b..84f1d00 100644
--- a/services/device/internal/impl/utiltest/modules.go
+++ b/services/device/internal/impl/utiltest/modules.go
@@ -6,7 +6,6 @@
import (
"fmt"
- "io"
"os"
goexec "os/exec"
"strings"
@@ -31,48 +30,42 @@
RedirectEnv = "DEVICE_MANAGER_DONT_REDIRECT_STDOUT_STDERR"
TestEnvVarName = "V23_RANDOM_ENV_VALUE"
NoPairingToken = ""
-
- // Modules names.
- ExecScriptCmd = "execScript"
- DeviceManagerCmd = "deviceManager"
- DeviceManagerV10Cmd = "deviceManagerV10" // deviceManager with a different major version number
- AppCmd = "app"
- HangingAppCmd = "hangingApp"
)
-// execScript launches the script passed as argument.
-func execScript(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+// ExecScript launches the script passed as argument.
+var ExecScript = modules.Register(func(env *modules.Env, args ...string) error {
if want, got := 1, len(args); want != got {
- vlog.Fatalf("execScript expected %d arguments, got %d instead", want, got)
+ vlog.Fatalf("ExecScript expected %d arguments, got %d instead", want, got)
}
script := args[0]
osenv := []string{RedirectEnv + "=1"}
- if env["PAUSE_BEFORE_STOP"] == "1" {
+ if env.Vars["PAUSE_BEFORE_STOP"] == "1" {
osenv = append(osenv, "PAUSE_BEFORE_STOP=1")
}
cmd := goexec.Cmd{
Path: script,
Env: osenv,
- Stdin: stdin,
- Stderr: stderr,
- Stdout: stdout,
+ Stdin: env.Stdin,
+ Stderr: env.Stderr,
+ Stdout: env.Stdout,
}
-
return cmd.Run()
-}
+}, "ExecScript")
-// deviceManager sets up a device manager server. It accepts the name to
+// DeviceManager sets up a device manager server. It accepts the name to
// publish the server under as an argument. Additional arguments can optionally
// specify device manager config settings.
-func deviceManager(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- ctx, shutdown := test.InitForTest()
+var DeviceManager = modules.Register(deviceManagerFunc, "DeviceManager")
+
+func deviceManagerFunc(env *modules.Env, args ...string) error {
+ ctx, shutdown := test.V23Init()
if len(args) == 0 {
vlog.Fatalf("deviceManager expected at least an argument")
}
publishName := args[0]
args = args[1:]
- defer fmt.Fprintf(stdout, "%v terminated\n", publishName)
+ defer fmt.Fprintf(env.Stdout, "%v terminated\n", publishName)
defer vlog.VI(1).Infof("%v terminated", publishName)
defer shutdown()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
@@ -134,11 +127,11 @@
}
// Manually mount the claimable service in the 'global' mounttable.
v23.GetNamespace(ctx).Mount(ctx, "claimable", claimableName, 0)
- fmt.Fprintf(stdout, "ready:%d\n", os.Getpid())
+ fmt.Fprintf(env.Stdout, "ready:%d\n", os.Getpid())
<-shutdownChan
- if val, present := env["PAUSE_BEFORE_STOP"]; present && val == "1" {
- modules.WaitForEOF(stdin)
+ if val, present := env.Vars["PAUSE_BEFORE_STOP"]; present && val == "1" {
+ modules.WaitForEOF(env.Stdin)
}
// TODO(ashankar): Figure out a way to incorporate this check in the test.
// if impl.DispatcherLeaking(dispatcher) {
@@ -148,15 +141,15 @@
}
// This is the same as DeviceManager above, except that it has a different major version number
-func deviceManagerV10(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var DeviceManagerV10 = modules.Register(func(env *modules.Env, args ...string) error {
impl.CurrentVersion = impl.Version{10, 0} // Set the version number to 10.0
- return deviceManager(stdin, stdout, stderr, env, args...)
-}
+ return deviceManagerFunc(env, args...)
+}, "DeviceManagerV10")
func TestMainImpl(m *testing.M) {
test.Init()
isSuidHelper := len(os.Getenv("V23_SUIDHELPER_TEST")) > 0
- if modules.IsModulesChildProcess() && !isSuidHelper {
+ if modules.IsChildProcess() && !isSuidHelper {
if err := modules.Dispatch(); err != nil {
fmt.Fprintf(os.Stderr, "modules.Dispatch failed: %v\n", err)
os.Exit(1)
@@ -177,13 +170,3 @@
vlog.Fatalf("Failed to Run() setuidhelper: %v", err)
}
}
-
-func init() {
- modules.RegisterChild("execScript", `execScript launches the script passed as argument.`, execScript)
- modules.RegisterChild("deviceManager", `deviceManager sets up a device manager server. It accepts the name to
-publish the server under as an argument. Additional arguments can optionally
- specify device manager config settings.`, deviceManager)
- modules.RegisterChild("deviceManagerV10", `This is the same as deviceManager above, except that it has a different major version number`, deviceManagerV10)
- modules.RegisterChild("app", ``, app)
- modules.RegisterChild("hangingApp", `Same as app, except that it does not exit properly after being stopped`, hangingApp)
-}
diff --git a/services/device/mgmt_v23_test.go b/services/device/mgmt_v23_test.go
index c07c9da..61d2ada 100644
--- a/services/device/mgmt_v23_test.go
+++ b/services/device/mgmt_v23_test.go
@@ -126,7 +126,7 @@
// Create those credentials and options to use to setup the
// binaries with them.
aliceCreds, _ = i.Shell().NewChildCredentials("alice")
- aliceOpts = i.Shell().DefaultStartOpts().ExternalCommand().WithCustomCredentials(aliceCreds)
+ aliceOpts = i.Shell().DefaultStartOpts().ExternalProgram().WithCustomCredentials(aliceCreds)
// Build all the command-line tools and set them up to run as alice.
// applicationd/binaryd servers will be run by alice too.
diff --git a/services/device/v23_test.go b/services/device/v23_test.go
index 3eeab2f..0bb141e 100644
--- a/services/device/v23_test.go
+++ b/services/device/v23_test.go
@@ -4,16 +4,21 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package device_test
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/v23tests"
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+ "v.io/x/ref/test/v23tests"
+)
func TestMain(m *testing.M) {
test.Init()
+ modules.DispatchAndExitIfChild()
cleanup := v23tests.UseSharedBinDir()
r := m.Run()
cleanup()
diff --git a/services/identity/identityd/v23_test.go b/services/identity/identityd/v23_test.go
index 13c2816..17cc37d 100644
--- a/services/identity/identityd/v23_test.go
+++ b/services/identity/identityd/v23_test.go
@@ -4,16 +4,21 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package main_test
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/v23tests"
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+ "v.io/x/ref/test/v23tests"
+)
func TestMain(m *testing.M) {
test.Init()
+ modules.DispatchAndExitIfChild()
cleanup := v23tests.UseSharedBinDir()
r := m.Run()
cleanup()
diff --git a/services/identity/identitylib/test_identityd.go b/services/identity/identitylib/test_identityd.go
index 03cdf0a..a633bbd 100644
--- a/services/identity/identitylib/test_identityd.go
+++ b/services/identity/identitylib/test_identityd.go
@@ -9,7 +9,6 @@
import (
"flag"
"fmt"
- "io"
"net"
"strconv"
"time"
@@ -32,15 +31,7 @@
tlsConfig = flag.CommandLine.String("tls-config", "", "Comma-separated list of TLS certificate and private key files. This must be provided.")
)
-const (
- TestIdentitydCommand = "test_identityd"
-)
-
-func init() {
- modules.RegisterChild(TestIdentitydCommand, modules.Usage(flag.CommandLine), startTestIdentityd)
-}
-
-func startTestIdentityd(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var TestIdentityd = modules.Register(func(env *modules.Env, args ...string) error {
// Duration to use for tls cert and blessing duration.
duration := 365 * 24 * time.Hour
@@ -101,12 +92,12 @@
_, eps, externalHttpAddress := s.Listen(ctx, &l, *externalHttpAddr, *httpAddr, *tlsConfig)
- fmt.Fprintf(stdout, "TEST_IDENTITYD_NAME=%s\n", eps[0])
- fmt.Fprintf(stdout, "TEST_IDENTITYD_HTTP_ADDR=%s\n", externalHttpAddress)
+ fmt.Fprintf(env.Stdout, "TEST_IDENTITYD_NAME=%s\n", eps[0])
+ fmt.Fprintf(env.Stdout, "TEST_IDENTITYD_HTTP_ADDR=%s\n", externalHttpAddress)
- modules.WaitForEOF(stdin)
+ modules.WaitForEOF(env.Stdin)
return nil
-}
+}, "TestIdentityd")
func freePort() string {
l, _ := net.Listen("tcp", ":0")
diff --git a/services/identity/internal/revocation/revocation_test.go b/services/identity/internal/revocation/revocation_test.go
index 0b07b0c..662af26 100644
--- a/services/identity/internal/revocation/revocation_test.go
+++ b/services/identity/internal/revocation/revocation_test.go
@@ -42,7 +42,7 @@
}
func TestDischargeRevokeDischargeRevokeDischarge(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
dcKey, dc, revoker, closeFunc := revokerSetup(t, ctx)
diff --git a/services/identity/internal/revocation/v23_internal_test.go b/services/identity/internal/revocation/v23_internal_test.go
index ed4c9f9..d53fea3 100644
--- a/services/identity/internal/revocation/v23_internal_test.go
+++ b/services/identity/internal/revocation/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package revocation
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/services/internal/binarylib/client_test.go b/services/internal/binarylib/client_test.go
index 2d91162..255dad4 100644
--- a/services/internal/binarylib/client_test.go
+++ b/services/internal/binarylib/client_test.go
@@ -83,7 +83,7 @@
// TestBufferAPI tests the binary repository client-side library
// interface using buffers.
func TestBufferAPI(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
@@ -127,7 +127,7 @@
// TestFileAPI tests the binary repository client-side library
// interface using files.
func TestFileAPI(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
@@ -184,7 +184,7 @@
// TestDownloadUrl tests the binary repository client-side library
// DownloadUrl method.
func TestDownloadUrl(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
diff --git a/services/internal/binarylib/http_test.go b/services/internal/binarylib/http_test.go
index 60968c7..77f0f2d 100644
--- a/services/internal/binarylib/http_test.go
+++ b/services/internal/binarylib/http_test.go
@@ -23,7 +23,7 @@
// TestHTTP checks that HTTP download works.
func TestHTTP(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
diff --git a/services/internal/binarylib/impl_test.go b/services/internal/binarylib/impl_test.go
index 21ebb2a..93bbb35 100644
--- a/services/internal/binarylib/impl_test.go
+++ b/services/internal/binarylib/impl_test.go
@@ -77,7 +77,7 @@
// all possible valid values of the depth used for the directory
// hierarchy that stores binary objects in the local file system.
func TestHierarchy(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
@@ -131,7 +131,7 @@
// uploads and downloads ranging the number of parts the test binary
// consists of.
func TestMultiPart(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
@@ -185,7 +185,7 @@
// resumption ranging the number of parts the uploaded binary consists
// of.
func TestResumption(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
@@ -232,7 +232,7 @@
// TestErrors checks that the binary interface correctly reports errors.
func TestErrors(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
@@ -299,7 +299,7 @@
}
func TestGlob(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
diff --git a/services/internal/binarylib/perms_test.go b/services/internal/binarylib/perms_test.go
index 59de734..80b5307 100644
--- a/services/internal/binarylib/perms_test.go
+++ b/services/internal/binarylib/perms_test.go
@@ -6,7 +6,6 @@
import (
"fmt"
- "io"
"os"
"reflect"
"syscall"
@@ -25,25 +24,22 @@
"v.io/x/ref/services/internal/binarylib"
"v.io/x/ref/services/internal/servicetest"
"v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
"v.io/x/ref/test/testutil"
)
//go:generate v23 test generate
-const (
- binaryCmd = "binaryd"
-)
-
-func binaryd(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var binaryd = modules.Register(func(env *modules.Env, args ...string) error {
if len(args) < 2 {
vlog.Fatalf("binaryd expected at least name and store arguments and optionally AccessList flags per PermissionsFromFlag")
}
publishName := args[0]
storedir := args[1]
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
- defer fmt.Fprintf(stdout, "%v terminating\n", publishName)
+ defer fmt.Fprintf(env.Stdout, "%v terminating\n", publishName)
defer vlog.VI(1).Infof("%v terminating", publishName)
defer shutdown()
@@ -64,11 +60,11 @@
vlog.Fatalf("Serve(%v) failed: %v", publishName, err)
}
- fmt.Fprintf(stdout, "ready:%d\n", os.Getpid())
+ fmt.Fprintf(env.Stdout, "ready:%d\n", os.Getpid())
<-signals.ShutdownOnSignals(ctx)
return nil
-}
+}, "binaryd")
func b(name string) repository.BinaryClientStub {
return repository.BinaryClient(name)
@@ -88,7 +84,7 @@
}
func TestBinaryCreateAccessList(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
@@ -112,7 +108,7 @@
defer cleanup()
prepDirectory(t, storedir)
- nmh := servicetest.RunCommand(t, sh, nil, binaryCmd, "bini", storedir)
+ nmh := servicetest.RunCommand(t, sh, nil, binaryd, "bini", storedir)
pid := servicetest.ReadPID(t, nmh)
defer syscall.Kill(pid, syscall.SIGINT)
@@ -143,7 +139,7 @@
}
func TestBinaryRootAccessList(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
@@ -169,7 +165,7 @@
t.Fatalf("WithPrincipal() failed: %v", err)
}
- nmh := servicetest.RunCommand(t, sh, nil, binaryCmd, "bini", storedir)
+ nmh := servicetest.RunCommand(t, sh, nil, binaryd, "bini", storedir)
pid := servicetest.ReadPID(t, nmh)
defer syscall.Kill(pid, syscall.SIGINT)
@@ -427,7 +423,7 @@
}
func TestBinaryRationalStartingValueForGetPermissions(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
v23.GetNamespace(ctx).CacheCtl(naming.DisableCache(true))
@@ -449,7 +445,7 @@
t.Fatalf("otherPrincipal.AddToRoots() failed: %v", err)
}
- nmh := servicetest.RunCommand(t, sh, nil, binaryCmd, "bini", storedir)
+ nmh := servicetest.RunCommand(t, sh, nil, binaryd, "bini", storedir)
pid := servicetest.ReadPID(t, nmh)
defer syscall.Kill(pid, syscall.SIGINT)
diff --git a/services/internal/binarylib/v23_test.go b/services/internal/binarylib/v23_test.go
index 06b7552..9e2e792 100644
--- a/services/internal/binarylib/v23_test.go
+++ b/services/internal/binarylib/v23_test.go
@@ -4,27 +4,19 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package binarylib_test
-import "fmt"
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/modules"
-
-func init() {
- modules.RegisterChild("binaryd", ``, binaryd)
-}
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+)
func TestMain(m *testing.M) {
test.Init()
- if modules.IsModulesChildProcess() {
- if err := modules.Dispatch(); err != nil {
- fmt.Fprintf(os.Stderr, "modules.Dispatch failed: %v\n", err)
- os.Exit(1)
- }
- return
- }
+ modules.DispatchAndExitIfChild()
os.Exit(m.Run())
}
diff --git a/services/internal/logreaderlib/logfile_test.go b/services/internal/logreaderlib/logfile_test.go
index 3f74b34..ca3dd6e 100644
--- a/services/internal/logreaderlib/logfile_test.go
+++ b/services/internal/logreaderlib/logfile_test.go
@@ -67,7 +67,7 @@
}
func TestReadLogImplNoFollow(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
workdir, err := ioutil.TempDir("", "logreadertest")
@@ -154,7 +154,7 @@
}
func TestReadLogImplWithFollow(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
workdir, err := ioutil.TempDir("", "logreadertest")
diff --git a/services/internal/logreaderlib/v23_internal_test.go b/services/internal/logreaderlib/v23_internal_test.go
index bcdf9fb..c0b54bf 100644
--- a/services/internal/logreaderlib/v23_internal_test.go
+++ b/services/internal/logreaderlib/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package logreaderlib
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/services/internal/pproflib/proxy_test.go b/services/internal/pproflib/proxy_test.go
index b277b89..6f30246 100644
--- a/services/internal/pproflib/proxy_test.go
+++ b/services/internal/pproflib/proxy_test.go
@@ -29,7 +29,7 @@
}
func TestPProfProxy(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
s, err := v23.NewServer(ctx)
@@ -56,10 +56,11 @@
"/pprof/profile?seconds=1",
"/pprof/heap",
"/pprof/goroutine",
- fmt.Sprintf("/pprof/symbol?%#x", TestPProfProxy),
+ fmt.Sprintf("/pprof/symbol?%p", TestPProfProxy),
}
for _, c := range testcases {
url := "http://" + l.Addr().String() + c
+ t.Log(url)
resp, err := http.Get(url)
if err != nil {
t.Fatalf("http.Get failed: %v", err)
diff --git a/services/internal/pproflib/v23_internal_test.go b/services/internal/pproflib/v23_internal_test.go
index 266140e..2b18e2d 100644
--- a/services/internal/pproflib/v23_internal_test.go
+++ b/services/internal/pproflib/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package pproflib
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/services/internal/servicetest/modules.go b/services/internal/servicetest/modules.go
index 7954346..e69c624 100644
--- a/services/internal/servicetest/modules.go
+++ b/services/internal/servicetest/modules.go
@@ -6,7 +6,6 @@
import (
"fmt"
- "io"
"io/ioutil"
"os"
"path/filepath"
@@ -33,11 +32,7 @@
preserveWorkspaceEnv = "V23_TEST_PRESERVE_WORKSPACE"
)
-func init() {
- modules.RegisterChild("rootMT", ``, rootMT)
-}
-
-func rootMT(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var rootMT = modules.Register(func(env *modules.Env, args ...string) error {
ctx, shutdown := v23.Init()
defer shutdown()
@@ -57,17 +52,17 @@
if err := server.ServeDispatcher("", mt); err != nil {
return fmt.Errorf("root failed: %s", err)
}
- fmt.Fprintf(stdout, "PID=%d\n", os.Getpid())
+ fmt.Fprintf(env.Stdout, "PID=%d\n", os.Getpid())
for _, ep := range eps {
- fmt.Fprintf(stdout, "MT_NAME=%s\n", ep.Name())
+ fmt.Fprintf(env.Stdout, "MT_NAME=%s\n", ep.Name())
}
- modules.WaitForEOF(stdin)
+ modules.WaitForEOF(env.Stdin)
return nil
-}
+}, "rootMT")
// startRootMT sets up a root mount table for tests.
func startRootMT(t *testing.T, sh *modules.Shell) (string, modules.Handle) {
- h, err := sh.Start("rootMT", nil, "--v23.tcp.address=127.0.0.1:0")
+ h, err := sh.Start(nil, rootMT, "--v23.tcp.address=127.0.0.1:0")
if err != nil {
t.Fatalf("failed to start root mount table: %s", err)
}
@@ -123,10 +118,10 @@
}
// RunCommand runs a modules command.
-func RunCommand(t *testing.T, sh *modules.Shell, env []string, cmd string, args ...string) modules.Handle {
- h, err := sh.StartWithOpts(sh.DefaultStartOpts(), env, cmd, args...)
+func RunCommand(t *testing.T, sh *modules.Shell, env []string, prog modules.Program, args ...string) modules.Handle {
+ h, err := sh.StartWithOpts(sh.DefaultStartOpts(), env, prog, args...)
if err != nil {
- t.Fatalf(testutil.FormatLogLine(2, "failed to start %q: %s", cmd, err))
+ t.Fatalf(testutil.FormatLogLine(2, "failed to start %q: %s", prog, err))
return nil
}
h.SetVerbosity(testing.Verbose())
diff --git a/services/internal/statslib/stats_test.go b/services/internal/statslib/stats_test.go
index d8d4ff3..9e38a73 100644
--- a/services/internal/statslib/stats_test.go
+++ b/services/internal/statslib/stats_test.go
@@ -57,7 +57,7 @@
}
func TestStatsImpl(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
endpoint, stop := startServer(t, ctx)
diff --git a/services/internal/statslib/v23_internal_test.go b/services/internal/statslib/v23_internal_test.go
index 8f6c7c9..b34a92f 100644
--- a/services/internal/statslib/v23_internal_test.go
+++ b/services/internal/statslib/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package statslib
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/services/internal/vtracelib/v23_internal_test.go b/services/internal/vtracelib/v23_internal_test.go
index 386c81f..2229a8d 100644
--- a/services/internal/vtracelib/v23_internal_test.go
+++ b/services/internal/vtracelib/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package vtracelib
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/services/internal/vtracelib/vtrace_test.go b/services/internal/vtracelib/vtrace_test.go
index 93deb05..5eb8a82 100644
--- a/services/internal/vtracelib/vtrace_test.go
+++ b/services/internal/vtracelib/vtrace_test.go
@@ -20,7 +20,7 @@
//go:generate v23 test generate
func TestVtraceServer(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
server, err := v23.NewServer(ctx)
diff --git a/services/mounttable/mounttabled/v23_test.go b/services/mounttable/mounttabled/v23_test.go
index 0d570e3..b88590f 100644
--- a/services/mounttable/mounttabled/v23_test.go
+++ b/services/mounttable/mounttabled/v23_test.go
@@ -4,16 +4,21 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package main_test
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/v23tests"
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+ "v.io/x/ref/test/v23tests"
+)
func TestMain(m *testing.M) {
test.Init()
+ modules.DispatchAndExitIfChild()
cleanup := v23tests.UseSharedBinDir()
r := m.Run()
cleanup()
diff --git a/services/mounttable/mounttablelib/mounttable_test.go b/services/mounttable/mounttablelib/mounttable_test.go
index 1a07339..a8f9e7f 100644
--- a/services/mounttable/mounttablelib/mounttable_test.go
+++ b/services/mounttable/mounttablelib/mounttable_test.go
@@ -396,7 +396,7 @@
}
func TestGlob(t *testing.T) {
- rootCtx, shutdown := test.InitForTest()
+ rootCtx, shutdown := test.V23Init()
defer shutdown()
server, estr := newMT(t, "", "", "testGlob", rootCtx)
@@ -549,7 +549,7 @@
}
func TestCleanup(t *testing.T) {
- rootCtx, shutdown := test.InitForTest()
+ rootCtx, shutdown := test.V23Init()
defer shutdown()
server, estr := newMT(t, "", "", "testCleanup", rootCtx)
@@ -604,7 +604,7 @@
}
func TestServerFormat(t *testing.T) {
- rootCtx, shutdown := test.InitForTest()
+ rootCtx, shutdown := test.V23Init()
defer shutdown()
server, estr := newMT(t, "", "", "testerverFormat", rootCtx)
@@ -618,7 +618,7 @@
}
func TestExpiry(t *testing.T) {
- rootCtx, shutdown := test.InitForTest()
+ rootCtx, shutdown := test.V23Init()
defer shutdown()
server, estr := newMT(t, "", "", "testExpiry", rootCtx)
@@ -683,7 +683,7 @@
}
func TestStatsCounters(t *testing.T) {
- rootCtx, shutdown := test.InitForTest()
+ rootCtx, shutdown := test.V23Init()
defer shutdown()
ft := NewFakeTimeClock()
@@ -817,7 +817,7 @@
func initTest() (rootCtx *context.T, aliceCtx *context.T, bobCtx *context.T, shutdown v23.Shutdown) {
test.Init()
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
var err error
if rootCtx, err = v23.WithPrincipal(ctx, testutil.NewPrincipal("root")); err != nil {
panic("failed to set root principal")
diff --git a/services/mounttable/mounttablelib/neighborhood.go b/services/mounttable/mounttablelib/neighborhood.go
index b2a2a71..ac82af2 100644
--- a/services/mounttable/mounttablelib/neighborhood.go
+++ b/services/mounttable/mounttablelib/neighborhood.go
@@ -34,15 +34,21 @@
errDoesntImplementUnmount = verror.Register(pkgPath+".errDoesntImplementUnmount", verror.NoRetry, "{1:}{2:} this server does not implement Unmount{:_}")
errDoesntImplementDelete = verror.Register(pkgPath+".errDoesntImplementDelete", verror.NoRetry, "{1:}{2:} this server does not implement Delete{:_}")
errDoesntImplementSetPermissions = verror.Register(pkgPath+".errDoesntImplementSetPermissions", verror.NoRetry, "{1:}{2:} this server does not implement SetPermissions{:_}")
+ errSlashInHostName = verror.Register(pkgPath+".errSlashInHostName", verror.NoRetry, "{1:}{2:} hostname may not contain '/'{:_}")
)
const addressPrefix = "address:"
+// AnonymousNeighbor is the neighborhood host name to use if you want to be a client of the neighborhood namespace
+// without appearing in it.
+const AnonymousNeighbor = "_"
+
// neighborhood defines a set of machines on the same multicast media.
type neighborhood struct {
- mdns *mdns.MDNS
- nelems int
- nw netconfig.NetConfigWatcher
+ mdns *mdns.MDNS
+ nelems int
+ nw netconfig.NetConfigWatcher
+ lastSubscription time.Time
}
var _ rpc.Dispatcher = (*neighborhood)(nil)
@@ -81,6 +87,10 @@
}
func newNeighborhood(host string, addresses []string, loopback bool) (*neighborhood, error) {
+ if strings.Contains(host, "/") {
+ return nil, verror.New(errSlashInHostName, nil)
+ }
+
// Create the TXT contents with addresses to announce. Also pick up a port number.
var txt []string
var port uint16
@@ -105,7 +115,10 @@
}
vlog.VI(2).Infof("listening for service vanadium on port %d", port)
mdns.SubscribeToService("vanadium")
- mdns.AddService("vanadium", "", port, txt...)
+ if host != AnonymousNeighbor {
+ mdns.AddService("vanadium", "", port, txt...)
+ }
+ time.Sleep(50 * time.Millisecond)
nh := &neighborhood{
mdns: mdns,
@@ -199,6 +212,12 @@
// neighbors returns all neighbors and their MountedServer structs.
func (nh *neighborhood) neighbors() map[string][]naming.MountedServer {
+ // If we haven't refreshed in a while, do it now.
+ if time.Now().Sub(nh.lastSubscription) > time.Duration(30)*time.Second {
+ nh.mdns.SubscribeToService("vanadium")
+ time.Sleep(50 * time.Millisecond)
+ nh.lastSubscription = time.Now()
+ }
neighbors := make(map[string][]naming.MountedServer, 0)
members := nh.mdns.ServiceDiscovery("vanadium")
for _, m := range members {
diff --git a/services/mounttable/mounttablelib/neighborhood_test.go b/services/mounttable/mounttablelib/neighborhood_test.go
index a8d67d8..4225985 100644
--- a/services/mounttable/mounttablelib/neighborhood_test.go
+++ b/services/mounttable/mounttablelib/neighborhood_test.go
@@ -31,7 +31,7 @@
}
func TestNeighborhood(t *testing.T) {
- rootCtx, shutdown := test.InitForTest()
+ rootCtx, shutdown := test.V23Init()
defer shutdown()
vlog.Infof("TestNeighborhood")
diff --git a/services/mounttable/mounttablelib/v23_internal_test.go b/services/mounttable/mounttablelib/v23_internal_test.go
index 1d210b4..82b7beb 100644
--- a/services/mounttable/mounttablelib/v23_internal_test.go
+++ b/services/mounttable/mounttablelib/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package mounttablelib
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/services/profile/profile/impl_test.go b/services/profile/profile/impl_test.go
index cf2b402..7ac0fcb 100644
--- a/services/profile/profile/impl_test.go
+++ b/services/profile/profile/impl_test.go
@@ -117,7 +117,7 @@
}
func TestProfileClient(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
server, endpoint, err := startServer(t, ctx)
diff --git a/services/profile/profile/v23_internal_test.go b/services/profile/profile/v23_internal_test.go
index dcd0029..ae59080 100644
--- a/services/profile/profile/v23_internal_test.go
+++ b/services/profile/profile/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package main
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/services/profile/profiled/impl_test.go b/services/profile/profiled/impl_test.go
index a981873..133c88a 100644
--- a/services/profile/profiled/impl_test.go
+++ b/services/profile/profiled/impl_test.go
@@ -36,7 +36,7 @@
// TestInterface tests that the implementation correctly implements
// the Profile interface.
func TestInterface(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
// Setup and start the profile repository server.
@@ -114,7 +114,7 @@
}
func TestPreserveAcrossRestarts(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
// Setup and start the profile repository server.
diff --git a/services/profile/profiled/v23_test.go b/services/profile/profiled/v23_test.go
index cb53f83..9df2772 100644
--- a/services/profile/profiled/v23_test.go
+++ b/services/profile/profiled/v23_test.go
@@ -4,16 +4,21 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package main_test
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/v23tests"
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+ "v.io/x/ref/test/v23tests"
+)
func TestMain(m *testing.M) {
test.Init()
+ modules.DispatchAndExitIfChild()
cleanup := v23tests.UseSharedBinDir()
r := m.Run()
cleanup()
diff --git a/services/proxy/proxyd/proxyd_v23_test.go b/services/proxy/proxyd/proxyd_v23_test.go
index e58c90d..167ea42 100644
--- a/services/proxy/proxyd/proxyd_v23_test.go
+++ b/services/proxy/proxyd/proxyd_v23_test.go
@@ -6,13 +6,11 @@
import (
"fmt"
- "io"
"v.io/v23"
"v.io/v23/context"
"v.io/v23/rpc"
"v.io/v23/security"
-
"v.io/x/ref/test/modules"
"v.io/x/ref/test/v23tests"
)
@@ -20,18 +18,11 @@
//go:generate v23 test generate
const (
- serverCmd = "server"
- clientCmd = "client"
proxyName = "proxy" // Name which the proxy mounts itself at
serverName = "server" // Name which the server mounts itself at
responseVar = "RESPONSE" // Name of the variable used by client program to output the response
)
-func init() {
- modules.RegisterChild(serverCmd, "server", runServer)
- modules.RegisterChild(clientCmd, "client", runClient)
-}
-
func V23TestProxyd(t *v23tests.T) {
v23tests.RunRootMT(t, "--v23.tcp.address=127.0.0.1:0")
var (
@@ -47,14 +38,14 @@
if _, err := t.Shell().StartWithOpts(
t.Shell().DefaultStartOpts().WithCustomCredentials(serverCreds),
nil,
- serverCmd); err != nil {
+ runServer); err != nil {
t.Fatal(err)
}
// Run the client.
client, err := t.Shell().StartWithOpts(
t.Shell().DefaultStartOpts().WithCustomCredentials(clientCreds),
nil,
- clientCmd)
+ runClient)
if err != nil {
t.Fatal(err)
}
@@ -63,7 +54,7 @@
}
}
-func runServer(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var runServer = modules.Register(func(env *modules.Env, args ...string) error {
ctx, shutdown := v23.Init()
defer shutdown()
@@ -79,11 +70,11 @@
return err
}
- modules.WaitForEOF(stdin)
+ modules.WaitForEOF(env.Stdin)
return nil
-}
+}, "runServer")
-func runClient(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var runClient = modules.Register(func(env *modules.Env, args ...string) error {
ctx, shutdown := v23.Init()
defer shutdown()
@@ -95,9 +86,9 @@
if err := call.Finish(&response); err != nil {
return err
}
- fmt.Fprintf(stdout, "%v=%v\n", responseVar, response)
+ fmt.Fprintf(env.Stdout, "%v=%v\n", responseVar, response)
return nil
-}
+}, "runClient")
type service struct{}
diff --git a/services/proxy/proxyd/v23_test.go b/services/proxy/proxyd/v23_test.go
index 436b072..98cd476 100644
--- a/services/proxy/proxyd/v23_test.go
+++ b/services/proxy/proxyd/v23_test.go
@@ -4,30 +4,21 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package main_test
-import "fmt"
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/modules"
-import "v.io/x/ref/test/v23tests"
-
-func init() {
- modules.RegisterChild("runServer", ``, runServer)
- modules.RegisterChild("runClient", ``, runClient)
-}
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+ "v.io/x/ref/test/v23tests"
+)
func TestMain(m *testing.M) {
test.Init()
- if modules.IsModulesChildProcess() {
- if err := modules.Dispatch(); err != nil {
- fmt.Fprintf(os.Stderr, "modules.Dispatch failed: %v\n", err)
- os.Exit(1)
- }
- return
- }
+ modules.DispatchAndExitIfChild()
cleanup := v23tests.UseSharedBinDir()
r := m.Run()
cleanup()
diff --git a/services/wspr/internal/app/app.go b/services/wspr/internal/app/app.go
index 5eb77d1..140203f 100644
--- a/services/wspr/internal/app/app.go
+++ b/services/wspr/internal/app/app.go
@@ -92,8 +92,11 @@
// the default implementation.
writerCreator func(id int32) lib.ClientWriter
- // Cache for all the Blessings that javascript has a handle to.
- blessingsCache *principal.JSBlessingsHandles
+ // Handles for all the Blessings that javascript has a handle to.
+ blessingsHandles *principal.JSBlessingsHandles
+
+ // Cache of Blessings that were sent to Javascript.
+ blessingsCache *principal.BlessingsCache
// reservedServices contains a map of reserved service names. These
// are objects that serve requests in wspr without actually making
@@ -106,6 +109,8 @@
typeReader *lib.TypeReader
}
+var _ ControllerServerMethods = (*Controller)(nil)
+
// NewController creates a new Controller. writerCreator will be used to create a new flow for rpcs to
// javascript server.
func NewController(ctx *context.T, writerCreator func(id int32) lib.ClientWriter, listenSpec *rpc.ListenSpec, namespaceRoots []string, p security.Principal) (*Controller, error) {
@@ -127,13 +132,15 @@
}
controller := &Controller{
- ctx: ctx,
- cancel: cancel,
- writerCreator: writerCreator,
- listenSpec: listenSpec,
- blessingsCache: principal.NewJSBlessingsHandles(),
+ ctx: ctx,
+ cancel: cancel,
+ writerCreator: writerCreator,
+ listenSpec: listenSpec,
+ blessingsHandles: principal.NewJSBlessingsHandles(),
}
+ controller.blessingsCache = principal.NewBlessingsCache(controller.SendBlessingsCacheMessages, principal.PeriodicGcPolicy(1*time.Minute))
+
controllerInvoker, err := rpc.ReflectInvoker(ControllerServer(controller))
if err != nil {
return nil, err
@@ -164,7 +171,7 @@
return
}
if blessings, ok := item.(security.Blessings); ok {
- item = principal.ConvertBlessingsToHandle(blessings, c.blessingsCache.GetOrAddHandle(blessings))
+ item = principal.ConvertBlessingsToHandle(blessings, c.blessingsHandles.GetOrAddHandle(blessings))
}
vomItem, err := lib.HexVomEncode(item, c.typeEncoder)
if err != nil {
@@ -198,7 +205,8 @@
w.Error(err)
return
}
- results[i] = vdl.ValueOf(principal.ConvertBlessingsToHandle(blessings, c.blessingsCache.GetOrAddHandle(blessings)))
+ jsBless := principal.ConvertBlessingsToHandle(blessings, c.blessingsHandles.GetOrAddHandle(blessings))
+ results[i] = vdl.ValueOf(c.blessingsCache.Put(jsBless))
}
}
c.sendRPCResponse(ctx, w, span, results)
@@ -284,7 +292,7 @@
id := c.lastGeneratedId
c.lastGeneratedId += 2
c.flowMap[id] = s
- os := newStream(c.blessingsCache, c.typeDecoder)
+ os := newStream(c.blessingsHandles, c.typeDecoder)
os.init(stream)
c.outstandingRequests[id] = &outstandingRequest{
stream: os,
@@ -305,6 +313,11 @@
}
}
+// BlessingsCache gets the blessings cache used by the controller.
+func (c *Controller) BlessingsCache() *principal.BlessingsCache {
+ return c.blessingsCache
+}
+
// RT returns the runtime of the app.
func (c *Controller) Context() *context.T {
return c.ctx
@@ -315,12 +328,12 @@
// because JS only has a handle to the blessings to avoid shipping the
// certificate forest to JS and back.
func (c *Controller) GetOrAddBlessingsHandle(blessings security.Blessings) principal.BlessingsHandle {
- return c.blessingsCache.GetOrAddHandle(blessings)
+ return c.blessingsHandles.GetOrAddHandle(blessings)
}
// GetBlessings gets blessings for a given blessings handle.
func (c *Controller) GetBlessings(handle principal.BlessingsHandle) security.Blessings {
- return c.blessingsCache.GetBlessings(handle)
+ return c.blessingsHandles.GetBlessings(handle)
}
// Cleanup cleans up any outstanding rpcs.
@@ -400,7 +413,7 @@
for i, arg := range inArgs {
if jsBlessings, ok := arg.(principal.JsBlessings); ok {
- inArgs[i] = c.blessingsCache.GetBlessings(jsBlessings.Handle)
+ inArgs[i] = c.blessingsHandles.GetBlessings(jsBlessings.Handle)
}
}
// We have to make the start call synchronous so we can make sure that we populate
@@ -580,7 +593,7 @@
// to put the outstanding stream in the map before we make the async call so that
// the future send know which queue to write to, even if the client call isn't
// actually ready yet.
- request.stream = newStream(c.blessingsCache, c.typeDecoder)
+ request.stream = newStream(c.blessingsHandles, c.typeDecoder)
}
c.Lock()
c.outstandingRequests[id] = request
@@ -743,20 +756,20 @@
// UnlinkBlessings removes the given blessings from the blessings store.
func (c *Controller) UnlinkBlessings(_ *context.T, _ rpc.ServerCall, handle principal.BlessingsHandle) error {
- return c.blessingsCache.RemoveReference(handle)
+ return c.blessingsHandles.RemoveReference(handle)
}
// Bless binds extensions of blessings held by this principal to
// another principal (represented by its public key).
-func (c *Controller) Bless(_ *context.T, _ rpc.ServerCall, publicKey string, blessingHandle principal.BlessingsHandle, extension string, caveats []security.Caveat) (string, principal.BlessingsHandle, error) {
+func (c *Controller) Bless(_ *context.T, _ rpc.ServerCall, publicKey string, blessingHandle principal.BlessingsHandle, extension string, caveats []security.Caveat) (principal.BlessingsId, error) {
var inputBlessing security.Blessings
if inputBlessing = c.GetBlessings(blessingHandle); inputBlessing.IsZero() {
- return "", principal.ZeroHandle, verror.New(invalidBlessingsHandle, nil, blessingHandle)
+ return 0, verror.New(invalidBlessingsHandle, nil, blessingHandle)
}
key, err := principal.DecodePublicKey(publicKey)
if err != nil {
- return "", principal.ZeroHandle, err
+ return 0, err
}
if len(caveats) == 0 {
@@ -766,60 +779,58 @@
p := v23.GetPrincipal(c.ctx)
blessings, err := p.Bless(key, inputBlessing, extension, caveats[0], caveats[1:]...)
if err != nil {
- return "", principal.ZeroHandle, err
+ return 0, err
}
- handle := c.blessingsCache.GetOrAddHandle(blessings)
- return publicKey, handle, nil
+ jsBlessings := principal.ConvertBlessingsToHandle(blessings, c.blessingsHandles.GetOrAddHandle(blessings))
+ return c.blessingsCache.Put(jsBlessings), nil
}
// BlessSelf creates a blessing with the provided name for this principal.
-func (c *Controller) BlessSelf(_ *context.T, _ rpc.ServerCall, extension string, caveats []security.Caveat) (string, principal.BlessingsHandle, error) {
+func (c *Controller) BlessSelf(_ *context.T, _ rpc.ServerCall, extension string, caveats []security.Caveat) (principal.BlessingsId, error) {
p := v23.GetPrincipal(c.ctx)
blessings, err := p.BlessSelf(extension)
if err != nil {
- return "", principal.ZeroHandle, verror.Convert(verror.ErrInternal, nil, err)
+ return 0, verror.Convert(verror.ErrInternal, nil, err)
}
- handle := c.blessingsCache.GetOrAddHandle(blessings)
-
- encKey, err := principal.EncodePublicKey(p.PublicKey())
- return encKey, handle, err
+ jsBlessings := principal.ConvertBlessingsToHandle(blessings, c.blessingsHandles.GetOrAddHandle(blessings))
+ return c.blessingsCache.Put(jsBlessings), err
}
// BlessingStoreSet puts the specified blessing in the blessing store under the
// provided pattern.
-func (c *Controller) BlessingStoreSet(_ *context.T, _ rpc.ServerCall, handle principal.BlessingsHandle, pattern security.BlessingPattern) (*principal.JsBlessings, error) {
+func (c *Controller) BlessingStoreSet(_ *context.T, _ rpc.ServerCall, handle principal.BlessingsHandle, pattern security.BlessingPattern) (principal.BlessingsId, error) {
var inputBlessings security.Blessings
if inputBlessings = c.GetBlessings(handle); inputBlessings.IsZero() {
- return nil, verror.New(invalidBlessingsHandle, nil, handle)
+ return 0, verror.New(invalidBlessingsHandle, nil, handle)
}
p := v23.GetPrincipal(c.ctx)
outBlessings, err := p.BlessingStore().Set(inputBlessings, security.BlessingPattern(pattern))
if err != nil {
- return nil, err
+ return 0, err
}
if outBlessings.IsZero() {
- return nil, nil
+ return 0, nil
}
- jsBlessings := principal.ConvertBlessingsToHandle(outBlessings, c.blessingsCache.GetOrAddHandle(outBlessings))
- return jsBlessings, nil
+ jsBlessings := principal.ConvertBlessingsToHandle(outBlessings, c.blessingsHandles.GetOrAddHandle(outBlessings))
+ return c.blessingsCache.Put(jsBlessings), nil
}
// BlessingStoreForPeer puts the specified blessing in the blessing store under the
// provided pattern.
-func (c *Controller) BlessingStoreForPeer(_ *context.T, _ rpc.ServerCall, peerBlessings []string) (*principal.JsBlessings, error) {
+func (c *Controller) BlessingStoreForPeer(_ *context.T, _ rpc.ServerCall, peerBlessings []string) (principal.BlessingsId, error) {
p := v23.GetPrincipal(c.ctx)
outBlessings := p.BlessingStore().ForPeer(peerBlessings...)
if outBlessings.IsZero() {
- return nil, nil
+ return 0, nil
}
- jsBlessings := principal.ConvertBlessingsToHandle(outBlessings, c.blessingsCache.GetOrAddHandle(outBlessings))
- return jsBlessings, nil
+ jsBlessings := principal.ConvertBlessingsToHandle(outBlessings, c.blessingsHandles.GetOrAddHandle(outBlessings))
+ return c.blessingsCache.Put(jsBlessings), nil
}
// BlessingStoreSetDefault sets the default blessings in the blessing store.
@@ -834,16 +845,16 @@
}
// BlessingStoreDefault fetches the default blessings for the principal of the controller.
-func (c *Controller) BlessingStoreDefault(*context.T, rpc.ServerCall) (*principal.JsBlessings, error) {
+func (c *Controller) BlessingStoreDefault(*context.T, rpc.ServerCall) (principal.BlessingsId, error) {
p := v23.GetPrincipal(c.ctx)
outBlessings := p.BlessingStore().Default()
if outBlessings.IsZero() {
- return nil, nil
+ return 0, nil
}
- jsBlessing := principal.ConvertBlessingsToHandle(outBlessings, c.blessingsCache.GetOrAddHandle(outBlessings))
- return jsBlessing, nil
+ jsBlessing := principal.ConvertBlessingsToHandle(outBlessings, c.blessingsHandles.GetOrAddHandle(outBlessings))
+ return c.blessingsCache.Put(jsBlessing), nil
}
// BlessingStorePublicKey fetches the public key used by the principal associated with the blessing store.
@@ -854,11 +865,12 @@
}
// BlessingStorePeerBlessings returns all the blessings that the BlessingStore holds.
-func (c *Controller) BlessingStorePeerBlessings(*context.T, rpc.ServerCall) (map[security.BlessingPattern]*principal.JsBlessings, error) {
+func (c *Controller) BlessingStorePeerBlessings(*context.T, rpc.ServerCall) (map[security.BlessingPattern]principal.BlessingsId, error) {
p := v23.GetPrincipal(c.ctx)
- outBlessingsMap := map[security.BlessingPattern]*principal.JsBlessings{}
+ outBlessingsMap := map[security.BlessingPattern]principal.BlessingsId{}
for pattern, blessings := range p.BlessingStore().PeerBlessings() {
- outBlessingsMap[pattern] = principal.ConvertBlessingsToHandle(blessings, c.blessingsCache.GetOrAddHandle(blessings))
+ jsBless := principal.ConvertBlessingsToHandle(blessings, c.blessingsHandles.GetOrAddHandle(blessings))
+ outBlessingsMap[pattern] = c.blessingsCache.Put(jsBless)
}
return outBlessingsMap, nil
}
@@ -882,23 +894,23 @@
}
// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
-func (c *Controller) UnionOfBlessings(_ *context.T, _ rpc.ServerCall, handles []principal.BlessingsHandle) (*principal.JsBlessings, error) {
+func (c *Controller) UnionOfBlessings(_ *context.T, _ rpc.ServerCall, handles []principal.BlessingsHandle) (principal.BlessingsId, error) {
inputBlessings := make([]security.Blessings, len(handles))
for i, handle := range handles {
bless := c.GetBlessings(handle)
if bless.IsZero() {
- return nil, verror.New(invalidBlessingsHandle, nil, handle)
+ return 0, verror.New(invalidBlessingsHandle, nil, handle)
}
inputBlessings[i] = bless
}
outBlessings, err := security.UnionOfBlessings(inputBlessings...)
if err != nil {
- return nil, err
+ return 0, err
}
- jsBlessings := principal.ConvertBlessingsToHandle(outBlessings, c.blessingsCache.GetOrAddHandle(outBlessings))
- return jsBlessings, nil
+ jsBlessings := principal.ConvertBlessingsToHandle(outBlessings, c.blessingsHandles.GetOrAddHandle(outBlessings))
+ return c.blessingsCache.Put(jsBlessings), nil
}
// HandleGranterResponse handles the result of a Granter request.
@@ -953,3 +965,17 @@
Message: msg,
})
}
+
+func (c *Controller) SendBlessingsCacheMessages(messages []principal.BlessingsCacheMessage) {
+ c.Lock()
+ defer c.Unlock()
+ id := c.lastGeneratedId
+ c.lastGeneratedId += 2
+ if err := c.writerCreator(id).Send(lib.ResponseBlessingsCacheMessage, messages); err != nil {
+ vlog.Errorf("unexpected error sending blessings cache message: %v", err)
+ }
+}
+
+func (c *Controller) TypeEncoder() *vom.TypeEncoder {
+ return c.typeEncoder
+}
diff --git a/services/wspr/internal/app/app.go.orig b/services/wspr/internal/app/app.go.orig
deleted file mode 100644
index 7243674..0000000
--- a/services/wspr/internal/app/app.go.orig
+++ /dev/null
@@ -1,947 +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.
-
-// The app package contains the struct that keeps per javascript app state and handles translating
-// javascript requests to vanadium requests and vice versa.
-package app
-
-import (
- "bytes"
- "encoding/hex"
- "fmt"
- "io"
- "reflect"
- "sync"
- "time"
-
- "v.io/v23"
- "v.io/v23/context"
- "v.io/v23/i18n"
- "v.io/v23/naming"
- "v.io/v23/options"
- "v.io/v23/rpc"
- "v.io/v23/security"
- "v.io/v23/vdl"
- "v.io/v23/vdlroot/signature"
- "v.io/v23/verror"
- "v.io/v23/vom"
- "v.io/v23/vtrace"
- "v.io/x/lib/vlog"
- "v.io/x/ref/services/wspr/internal/lib"
- "v.io/x/ref/services/wspr/internal/namespace"
- "v.io/x/ref/services/wspr/internal/principal"
- "v.io/x/ref/services/wspr/internal/rpc/server"
-)
-
-const (
- // pkgPath is the prefix os errors in this package.
- pkgPath = "v.io/x/ref/services/wspr/internal/app"
-)
-
-// Errors
-var (
- marshallingError = verror.Register(pkgPath+".marshallingError", verror.NoRetry, "{1} {2} marshalling error {_}")
- noResults = verror.Register(pkgPath+".noResults", verror.NoRetry, "{1} {2} no results from call {_}")
- badCaveatType = verror.Register(pkgPath+".badCaveatType", verror.NoRetry, "{1} {2} bad caveat type {_}")
- unknownBlessings = verror.Register(pkgPath+".unknownBlessings", verror.NoRetry, "{1} {2} unknown public id {_}")
- invalidBlessingsHandle = verror.Register(pkgPath+".invalidBlessingsHandle", verror.NoRetry, "{1} {2} invalid blessings handle {3} {_}")
-)
-
-type outstandingRequest struct {
- stream *outstandingStream
- cancel context.CancelFunc
-}
-
-// Controller represents all the state of a Vanadium Web App. This is the struct
-// that is in charge performing all the vanadium options.
-type Controller struct {
- // Protects everything.
- // TODO(bjornick): We need to split this up.
- sync.Mutex
-
- // The context of this controller.
- ctx *context.T
-
- // The cleanup function for this controller.
- cancel context.CancelFunc
-
- // The rpc.ListenSpec to use with server.Listen
- listenSpec *rpc.ListenSpec
-
- // Used to generate unique ids for requests initiated by the proxy.
- // These ids will be even so they don't collide with the ids generated
- // by the client.
- lastGeneratedId int32
-
- // Used to keep track of data (streams and cancellation functions) for
- // outstanding requests.
- outstandingRequests map[int32]*outstandingRequest
-
- // Maps flowids to the server that owns them.
- flowMap map[int32]interface{}
-
- // A manager that Handles fetching and caching signature of remote services
- signatureManager lib.SignatureManager
-
- // We maintain multiple Vanadium server per pipe for serving JavaScript
- // services.
- servers map[uint32]*server.Server
-
- // Creates a client writer for a given flow. This is a member so that tests can override
- // the default implementation.
- writerCreator func(id int32) lib.ClientWriter
-
- // Cache for all the Blessings that javascript has a handle to.
- blessingsCache *principal.JSBlessingsHandles
-
- // reservedServices contains a map of reserved service names. These
- // are objects that serve requests in wspr without actually making
- // an outgoing rpc call.
- reservedServices map[string]rpc.Invoker
-}
-
-// NewController creates a new Controller. writerCreator will be used to create a new flow for rpcs to
-// javascript server.
-func NewController(ctx *context.T, writerCreator func(id int32) lib.ClientWriter, listenSpec *rpc.ListenSpec, namespaceRoots []string, p security.Principal) (*Controller, error) {
- ctx, cancel := context.WithCancel(ctx)
-
- if namespaceRoots != nil {
- var err error
- ctx, _, err = v23.WithNewNamespace(ctx, namespaceRoots...)
- if err != nil {
- return nil, err
- }
- }
-
- ctx, _ = vtrace.WithNewTrace(ctx)
-
- ctx, err := v23.WithPrincipal(ctx, p)
- if err != nil {
- return nil, err
- }
-
- controller := &Controller{
- ctx: ctx,
- cancel: cancel,
- writerCreator: writerCreator,
- listenSpec: listenSpec,
- blessingsCache: principal.NewJSBlessingsHandles(),
- }
-
- controllerInvoker, err := rpc.ReflectInvoker(ControllerServer(controller))
- if err != nil {
- return nil, err
- }
- namespaceInvoker, err := rpc.ReflectInvoker(namespace.New(ctx))
- if err != nil {
- return nil, err
- }
- controller.reservedServices = map[string]rpc.Invoker{
- "__controller": controllerInvoker,
- "__namespace": namespaceInvoker,
- }
-
- controller.setup()
- return controller, nil
-}
-
-// finishCall waits for the call to finish and write out the response to w.
-func (c *Controller) finishCall(ctx *context.T, w lib.ClientWriter, clientCall rpc.ClientCall, msg *RpcRequest, span vtrace.Span) {
- if msg.IsStreaming {
- for {
- var item interface{}
- if err := clientCall.Recv(&item); err != nil {
- if err == io.EOF {
- break
- }
- w.Error(err) // Send streaming error as is
- return
- }
- if blessings, ok := item.(security.Blessings); ok {
- item = principal.ConvertBlessingsToHandle(blessings, c.blessingsCache.GetOrAddHandle(blessings))
- }
- vomItem, err := lib.HexVomEncode(item)
- if err != nil {
- w.Error(verror.New(marshallingError, ctx, item, err))
- continue
- }
- if err := w.Send(lib.ResponseStream, vomItem); err != nil {
- w.Error(verror.New(marshallingError, ctx, item))
- }
- }
- if err := w.Send(lib.ResponseStreamClose, nil); err != nil {
- w.Error(verror.New(marshallingError, ctx, "ResponseStreamClose"))
- }
- }
- results := make([]*vdl.Value, msg.NumOutArgs)
- wireBlessingsType := vdl.TypeOf(security.WireBlessings{})
- // This array will have pointers to the values in results.
- resultptrs := make([]interface{}, msg.NumOutArgs)
- for i := range results {
- resultptrs[i] = &results[i]
- }
- if err := clientCall.Finish(resultptrs...); err != nil {
- // return the call system error as is
- w.Error(err)
- return
- }
- for i, val := range results {
- if val.Type() == wireBlessingsType {
- var blessings security.Blessings
- if err := vdl.Convert(&blessings, val); err != nil {
- w.Error(err)
- return
- }
- results[i] = vdl.ValueOf(principal.ConvertBlessingsToHandle(blessings, c.blessingsCache.GetOrAddHandle(blessings)))
- }
- }
- c.sendRPCResponse(ctx, w, span, results)
-}
-
-func (c *Controller) sendRPCResponse(ctx *context.T, w lib.ClientWriter, span vtrace.Span, results []*vdl.Value) {
- span.Finish()
- response := RpcResponse{
- OutArgs: results,
- TraceResponse: vtrace.GetResponse(ctx),
- }
- encoded, err := lib.HexVomEncode(response)
- if err != nil {
- w.Error(err)
- return
- }
- if err := w.Send(lib.ResponseFinal, encoded); err != nil {
- w.Error(verror.Convert(marshallingError, ctx, err))
- }
-}
-
-// callOpts turns a slice of type []RpcCallOption object into an array of rpc.CallOpt.
-func (c *Controller) callOpts(opts []RpcCallOption) ([]rpc.CallOpt, error) {
- var callOpts []rpc.CallOpt
-
- for _, opt := range opts {
- switch v := opt.(type) {
- case RpcCallOptionAllowedServersPolicy:
- callOpts = append(callOpts, options.AllowedServersPolicy(v.Value))
- case RpcCallOptionRetryTimeout:
- callOpts = append(callOpts, options.RetryTimeout(v.Value))
- case RpcCallOptionGranter:
- callOpts = append(callOpts, &jsGranter{c, v.Value})
- default:
- return nil, fmt.Errorf("Unknown RpcCallOption type %T", v)
- }
- }
-
- return callOpts, nil
-}
-
-// serverOpts turns a slice of type []RpcServerOptions object into an array of rpc.ServerOpt.
-func (c *Controller) serverOpts(opts []RpcServerOption) ([]rpc.ServerOpt, error) {
- var serverOpts []rpc.ServerOpt
-
- for _, opt := range opts {
- switch v := opt.(type) {
- case RpcServerOptionIsLeaf:
- serverOpts = append(serverOpts, options.IsLeaf(v.Value))
- case RpcServerOptionServesMountTable:
- serverOpts = append(serverOpts, options.ServesMountTable(v.Value))
- default:
- return nil, fmt.Errorf("Unknown RpcServerOption type %T", v)
- }
- }
-
- return serverOpts, nil
-}
-
-func (c *Controller) startCall(ctx *context.T, w lib.ClientWriter, msg *RpcRequest, inArgs []interface{}) (rpc.ClientCall, error) {
- methodName := lib.UppercaseFirstCharacter(msg.Method)
- callOpts, err := c.callOpts(msg.CallOptions)
- if err != nil {
- return nil, err
- }
- clientCall, err := v23.GetClient(ctx).StartCall(ctx, msg.Name, methodName, inArgs, callOpts...)
- if err != nil {
- return nil, fmt.Errorf("error starting call (name: %v, method: %v, args: %v): %v", msg.Name, methodName, inArgs, err)
- }
-
- return clientCall, nil
-}
-
-// Implements the serverHelper interface
-
-// CreateNewFlow creats a new server flow that will be used to write out
-// streaming messages to Javascript.
-func (c *Controller) CreateNewFlow(s interface{}, stream rpc.Stream) *server.Flow {
- c.Lock()
- defer c.Unlock()
- id := c.lastGeneratedId
- c.lastGeneratedId += 2
- c.flowMap[id] = s
- os := newStream(c.blessingsCache)
- os.init(stream)
- c.outstandingRequests[id] = &outstandingRequest{
- stream: os,
- }
- return &server.Flow{ID: id, Writer: c.writerCreator(id)}
-}
-
-// CleanupFlow removes the bookkeeping for a previously created flow.
-func (c *Controller) CleanupFlow(id int32) {
- c.Lock()
- request := c.outstandingRequests[id]
- delete(c.outstandingRequests, id)
- delete(c.flowMap, id)
- c.Unlock()
- if request != nil && request.stream != nil {
- request.stream.end()
- request.stream.waitUntilDone()
- }
-}
-
-// RT returns the runtime of the app.
-func (c *Controller) Context() *context.T {
- return c.ctx
-}
-
-// GetOrAddBlessingsHandle adds the Blessings to the local blessings store if they
-// don't already existand returns the handle to it. This function exists
-// because JS only has a handle to the blessings to avoid shipping the
-// certificate forest to JS and back.
-func (c *Controller) GetOrAddBlessingsHandle(blessings security.Blessings) principal.BlessingsHandle {
- return c.blessingsCache.GetOrAddHandle(blessings)
-}
-
-// GetBlessings gets blessings for a given blessings handle.
-func (c *Controller) GetBlessings(handle principal.BlessingsHandle) security.Blessings {
- return c.blessingsCache.GetBlessings(handle)
-}
-
-// Cleanup cleans up any outstanding rpcs.
-func (c *Controller) Cleanup() {
- vlog.VI(0).Info("Cleaning up controller")
- c.Lock()
-
- for _, request := range c.outstandingRequests {
- if request.cancel != nil {
- request.cancel()
- }
- if request.stream != nil {
- request.stream.end()
- }
- }
-
- servers := []*server.Server{}
- for _, server := range c.servers {
- servers = append(servers, server)
- }
-
- c.Unlock()
-
- // We must unlock before calling server.Stop otherwise it can deadlock.
- for _, server := range servers {
- server.Stop()
- }
-
- c.cancel()
-}
-
-func (c *Controller) setup() {
- c.signatureManager = lib.NewSignatureManager()
- c.outstandingRequests = make(map[int32]*outstandingRequest)
- c.flowMap = make(map[int32]interface{})
- c.servers = make(map[uint32]*server.Server)
-}
-
-// SendOnStream writes data on id's stream. The actual network write will be
-// done asynchronously. If there is an error, it will be sent to w.
-func (c *Controller) SendOnStream(id int32, data string, w lib.ClientWriter) {
- c.Lock()
- request := c.outstandingRequests[id]
- if request == nil || request.stream == nil {
- vlog.Errorf("unknown stream: %d", id)
- c.Unlock()
- return
- }
- stream := request.stream
- c.Unlock()
- stream.send(data, w)
-}
-
-// SendVeyronRequest makes a vanadium request for the given flowId. If signal is non-nil, it will receive
-// the call object after it has been constructed.
-func (c *Controller) sendVeyronRequest(ctx *context.T, id int32, msg *RpcRequest, inArgs []interface{}, w lib.ClientWriter, stream *outstandingStream, span vtrace.Span) {
- sig, err := c.getSignature(ctx, msg.Name)
- if err != nil {
- w.Error(err)
- return
- }
- methName := lib.UppercaseFirstCharacter(msg.Method)
- methSig, ok := signature.FirstMethod(sig, methName)
- if !ok {
- w.Error(fmt.Errorf("method %q not found in signature: %#v", methName, sig))
- return
- }
- if len(methSig.InArgs) != len(inArgs) {
- w.Error(fmt.Errorf("invalid number of arguments, expected: %v, got:%v", methSig, *msg))
- return
- }
-
- for i, arg := range inArgs {
- if jsBlessings, ok := arg.(principal.JsBlessings); ok {
- inArgs[i] = c.blessingsCache.GetBlessings(jsBlessings.Handle)
- }
- }
- // We have to make the start call synchronous so we can make sure that we populate
- // the call map before we can Handle a recieve call.
- call, err := c.startCall(ctx, w, msg, inArgs)
- if err != nil {
- w.Error(verror.Convert(verror.ErrInternal, ctx, err))
- return
- }
-
- if stream != nil {
- stream.init(call)
- }
-
- c.finishCall(ctx, w, call, msg, span)
- c.Lock()
- if request, ok := c.outstandingRequests[id]; ok {
- delete(c.outstandingRequests, id)
- if request.cancel != nil {
- request.cancel()
- }
- }
- c.Unlock()
-}
-
-// TODO(mattr): This is a very limited implementation of ServerCall,
-// but currently none of the methods the controller exports require
-// any of this context information.
-type localCall struct {
- ctx *context.T
- vrpc *RpcRequest
- tags []*vdl.Value
- w lib.ClientWriter
-}
-
-var (
- _ rpc.StreamServerCall = (*localCall)(nil)
- _ security.Call = (*localCall)(nil)
-)
-
-func (l *localCall) Send(item interface{}) error {
- vomItem, err := lib.HexVomEncode(item)
- if err != nil {
- err = verror.New(marshallingError, l.ctx, item, err)
- l.w.Error(err)
- return err
- }
- if err := l.w.Send(lib.ResponseStream, vomItem); err != nil {
- err = verror.New(marshallingError, l.ctx, item)
- l.w.Error(err)
- return err
- }
- return nil
-}
-func (l *localCall) Recv(interface{}) error { return nil }
-func (l *localCall) GrantedBlessings() security.Blessings { return security.Blessings{} }
-func (l *localCall) Server() rpc.Server { return nil }
-func (l *localCall) Timestamp() (t time.Time) { return }
-func (l *localCall) Method() string { return l.vrpc.Method }
-func (l *localCall) MethodTags() []*vdl.Value { return l.tags }
-func (l *localCall) Suffix() string { return l.vrpc.Name }
-func (l *localCall) LocalDischarges() map[string]security.Discharge { return nil }
-func (l *localCall) RemoteDischarges() map[string]security.Discharge { return nil }
-func (l *localCall) LocalPrincipal() security.Principal { return nil }
-func (l *localCall) LocalBlessings() security.Blessings { return security.Blessings{} }
-func (l *localCall) RemoteBlessings() security.Blessings { return security.Blessings{} }
-func (l *localCall) LocalEndpoint() naming.Endpoint { return nil }
-func (l *localCall) RemoteEndpoint() naming.Endpoint { return nil }
-func (l *localCall) Security() security.Call { return l }
-
-func (c *Controller) handleInternalCall(ctx *context.T, invoker rpc.Invoker, msg *RpcRequest, decoder *vom.Decoder, w lib.ClientWriter, span vtrace.Span) {
- argptrs, tags, err := invoker.Prepare(msg.Method, int(msg.NumInArgs))
- if err != nil {
- w.Error(verror.Convert(verror.ErrInternal, ctx, err))
- return
- }
- for _, argptr := range argptrs {
- if err := decoder.Decode(argptr); err != nil {
- w.Error(verror.Convert(verror.ErrInternal, ctx, err))
- return
- }
- }
- results, err := invoker.Invoke(ctx, &localCall{ctx, msg, tags, w}, msg.Method, argptrs)
- if err != nil {
- w.Error(verror.Convert(verror.ErrInternal, ctx, err))
- return
- }
- if msg.IsStreaming {
- if err := w.Send(lib.ResponseStreamClose, nil); err != nil {
- w.Error(verror.New(marshallingError, ctx, "ResponseStreamClose"))
- }
- }
-
- // Convert results from []interface{} to []*vdl.Value.
- vresults := make([]*vdl.Value, len(results))
- for i, res := range results {
- vv, err := vdl.ValueFromReflect(reflect.ValueOf(res))
- if err != nil {
- w.Error(verror.Convert(verror.ErrInternal, ctx, err))
- return
- }
- vresults[i] = vv
- }
- c.sendRPCResponse(ctx, w, span, vresults)
-}
-
-// HandleCaveatValidationResponse handles the response to caveat validation
-// requests.
-func (c *Controller) HandleCaveatValidationResponse(id int32, data string) {
- c.Lock()
- server, ok := c.flowMap[id].(*server.Server)
- c.Unlock()
- if !ok {
- vlog.Errorf("unexpected result from JavaScript. No server found matching id %d.", id)
- return // ignore unknown server
- }
- server.HandleCaveatValidationResponse(id, data)
-}
-
-// HandleVeyronRequest starts a vanadium rpc and returns before the rpc has been completed.
-func (c *Controller) HandleVeyronRequest(ctx *context.T, id int32, data string, w lib.ClientWriter) {
- binbytes, err := hex.DecodeString(data)
- if err != nil {
- w.Error(verror.Convert(verror.ErrInternal, ctx, fmt.Errorf("Error decoding hex string %q: %v", data, err)))
- return
- }
- decoder := vom.NewDecoder(bytes.NewReader(binbytes))
- var msg RpcRequest
- if err := decoder.Decode(&msg); err != nil {
- w.Error(verror.Convert(verror.ErrInternal, ctx, err))
- return
- }
- vlog.VI(2).Infof("Rpc: %s.%s(..., streaming=%v)", msg.Name, msg.Method, msg.IsStreaming)
- spanName := fmt.Sprintf("<wspr>%q.%s", msg.Name, msg.Method)
- ctx, span := vtrace.WithContinuedTrace(ctx, spanName, msg.TraceRequest)
- ctx = i18n.WithLangID(ctx, i18n.LangID(msg.Context.Language))
-
- var cctx *context.T
- var cancel context.CancelFunc
-
- // TODO(mattr): To be consistent with go, we should not ignore 0 timeouts.
- // However as a rollout strategy we must, otherwise there is a circular
- // dependency between the WSPR change and the JS change that will follow.
- if msg.Deadline.IsZero() {
- cctx, cancel = context.WithCancel(ctx)
- } else {
- cctx, cancel = context.WithDeadline(ctx, msg.Deadline.Time)
- }
-
- // If this message is for an internal service, do a short-circuit dispatch here.
- if invoker, ok := c.reservedServices[msg.Name]; ok {
- go c.handleInternalCall(ctx, invoker, &msg, decoder, w, span)
- return
- }
-
- inArgs := make([]interface{}, msg.NumInArgs)
- for i := range inArgs {
- var v *vdl.Value
- if err := decoder.Decode(&v); err != nil {
- w.Error(err)
- return
- }
- inArgs[i] = v
- }
-
- request := &outstandingRequest{
- cancel: cancel,
- }
- if msg.IsStreaming {
- // If this rpc is streaming, we would expect that the client would try to send
- // on this stream. Since the initial handshake is done asynchronously, we have
- // to put the outstanding stream in the map before we make the async call so that
- // the future send know which queue to write to, even if the client call isn't
- // actually ready yet.
- request.stream = newStream(c.blessingsCache)
- }
- c.Lock()
- c.outstandingRequests[id] = request
- go c.sendVeyronRequest(cctx, id, &msg, inArgs, w, request.stream, span)
- c.Unlock()
-}
-
-// HandleVeyronCancellation cancels the request corresponding to the
-// given id if it is still outstanding.
-func (c *Controller) HandleVeyronCancellation(id int32) {
- c.Lock()
- defer c.Unlock()
- if request, ok := c.outstandingRequests[id]; ok && request.cancel != nil {
- request.cancel()
- }
-}
-
-// CloseStream closes the stream for a given id.
-func (c *Controller) CloseStream(id int32) {
- c.Lock()
- defer c.Unlock()
- if request, ok := c.outstandingRequests[id]; ok && request.stream != nil {
- request.stream.end()
- return
- }
- vlog.Errorf("close called on non-existent call: %v", id)
-}
-
-func (c *Controller) maybeCreateServer(serverId uint32, opts ...rpc.ServerOpt) (*server.Server, error) {
- c.Lock()
- defer c.Unlock()
- if server, ok := c.servers[serverId]; ok {
- return server, nil
- }
- server, err := server.NewServer(serverId, c.listenSpec, c, opts...)
- if err != nil {
- return nil, err
- }
- c.servers[serverId] = server
- return server, nil
-}
-
-// HandleLookupResponse handles the result of a Dispatcher.Lookup call that was
-// run by the Javascript server.
-func (c *Controller) HandleLookupResponse(id int32, data string) {
- c.Lock()
- server, ok := c.flowMap[id].(*server.Server)
- c.Unlock()
- if !ok {
- vlog.Errorf("unexpected result from JavaScript. No channel "+
- "for MessageId: %d exists. Ignoring the results.", id)
- //Ignore unknown responses that don't belong to any channel
- return
- }
- server.HandleLookupResponse(id, data)
-}
-
-// HandleAuthResponse handles the result of a Authorizer.Authorize call that was
-// run by the Javascript server.
-func (c *Controller) HandleAuthResponse(id int32, data string) {
- c.Lock()
- server, ok := c.flowMap[id].(*server.Server)
- c.Unlock()
- if !ok {
- vlog.Errorf("unexpected result from JavaScript. No channel "+
- "for MessageId: %d exists. Ignoring the results.", id)
- //Ignore unknown responses that don't belong to any channel
- return
- }
- server.HandleAuthResponse(id, data)
-}
-
-// Serve instructs WSPR to start listening for calls on behalf
-// of a javascript server.
-func (c *Controller) Serve(_ *context.T, _ rpc.ServerCall, name string, serverId uint32, rpcServerOpts []RpcServerOption) error {
-
- opts, err := c.serverOpts(rpcServerOpts)
- if err != nil {
- return verror.Convert(verror.ErrInternal, nil, err)
- }
- server, err := c.maybeCreateServer(serverId, opts...)
- if err != nil {
- return verror.Convert(verror.ErrInternal, nil, err)
- }
- vlog.VI(2).Infof("serving under name: %q", name)
- if err := server.Serve(name); err != nil {
- return verror.Convert(verror.ErrInternal, nil, err)
- }
- return nil
-}
-
-// Stop instructs WSPR to stop listening for calls for the
-// given javascript server.
-func (c *Controller) Stop(_ *context.T, _ rpc.ServerCall, serverId uint32) error {
- c.Lock()
- server, ok := c.servers[serverId]
- if !ok {
- c.Unlock()
- return nil
- }
- delete(c.servers, serverId)
- c.Unlock()
-
- server.Stop()
- return nil
-}
-
-// AddName adds a published name to an existing server.
-func (c *Controller) AddName(_ *context.T, _ rpc.ServerCall, serverId uint32, name string) error {
- // Create a server for the pipe, if it does not exist already
- server, err := c.maybeCreateServer(serverId)
- if err != nil {
- return verror.Convert(verror.ErrInternal, nil, err)
- }
- // Add name
- if err := server.AddName(name); err != nil {
- return verror.Convert(verror.ErrInternal, nil, err)
- }
- return nil
-}
-
-// RemoveName removes a published name from an existing server.
-func (c *Controller) RemoveName(_ *context.T, _ rpc.ServerCall, serverId uint32, name string) error {
- // Create a server for the pipe, if it does not exist already
- server, err := c.maybeCreateServer(serverId)
- if err != nil {
- return verror.Convert(verror.ErrInternal, nil, err)
- }
- // Remove name
- server.RemoveName(name)
- // Remove name from signature cache as well
- c.signatureManager.FlushCacheEntry(name)
- return nil
-}
-
-// HandleServerResponse handles the completion of outstanding calls to JavaScript services
-// by filling the corresponding channel with the result from JavaScript.
-func (c *Controller) HandleServerResponse(id int32, data string) {
- c.Lock()
- server, ok := c.flowMap[id].(*server.Server)
- c.Unlock()
- if !ok {
- vlog.Errorf("unexpected result from JavaScript. No channel "+
- "for MessageId: %d exists. Ignoring the results.", id)
- //Ignore unknown responses that don't belong to any channel
- return
- }
- server.HandleServerResponse(id, data)
-}
-
-// parseVeyronRequest parses a json rpc request into a RpcRequest object.
-func (c *Controller) parseVeyronRequest(data string) (*RpcRequest, error) {
- var msg RpcRequest
- if err := lib.HexVomDecode(data, &msg); err != nil {
- return nil, err
- }
- vlog.VI(2).Infof("RpcRequest: %s.%s(..., streaming=%v)", msg.Name, msg.Method, msg.IsStreaming)
- return &msg, nil
-}
-
-// getSignature uses the signature manager to get and cache the signature of a remote server.
-func (c *Controller) getSignature(ctx *context.T, name string) ([]signature.Interface, error) {
- return c.signatureManager.Signature(ctx, name)
-}
-
-// Signature uses the signature manager to get and cache the signature of a remote server.
-func (c *Controller) Signature(ctx *context.T, _ rpc.ServerCall, name string) ([]signature.Interface, error) {
- return c.getSignature(ctx, name)
-}
-
-// UnlinkBlessings removes the given blessings from the blessings store.
-func (c *Controller) UnlinkBlessings(_ *context.T, _ rpc.ServerCall, handle principal.BlessingsHandle) error {
- return c.blessingsCache.RemoveReference(handle)
-}
-
-// Bless binds extensions of blessings held by this principal to
-// another principal (represented by its public key).
-func (c *Controller) Bless(_ *context.T, _ rpc.ServerCall, publicKey string, blessingHandle principal.BlessingsHandle, extension string, caveats []security.Caveat) (string, principal.BlessingsHandle, error) {
- var inputBlessing security.Blessings
- if inputBlessing = c.GetBlessings(blessingHandle); inputBlessing.IsZero() {
- return "", principal.ZeroHandle, verror.New(invalidBlessingsHandle, nil, blessingHandle)
- }
-
- key, err := principal.DecodePublicKey(publicKey)
- if err != nil {
- return "", principal.ZeroHandle, err
- }
-
- if len(caveats) == 0 {
- caveats = append(caveats, security.UnconstrainedUse())
- }
-
- p := v23.GetPrincipal(c.ctx)
- blessings, err := p.Bless(key, inputBlessing, extension, caveats[0], caveats[1:]...)
- if err != nil {
- return "", principal.ZeroHandle, err
- }
- handle := c.blessingsCache.GetOrAddHandle(blessings)
- return publicKey, handle, nil
-}
-
-// BlessSelf creates a blessing with the provided name for this principal.
-func (c *Controller) BlessSelf(_ *context.T, _ rpc.ServerCall, extension string, caveats []security.Caveat) (string, principal.BlessingsHandle, error) {
- p := v23.GetPrincipal(c.ctx)
- blessings, err := p.BlessSelf(extension)
- if err != nil {
- return "", principal.ZeroHandle, verror.Convert(verror.ErrInternal, nil, err)
- }
-
- handle := c.blessingsCache.GetOrAddHandle(blessings)
-
- encKey, err := principal.EncodePublicKey(p.PublicKey())
- return encKey, handle, err
-}
-
-// BlessingStoreSet puts the specified blessing in the blessing store under the
-// provided pattern.
-func (c *Controller) BlessingStoreSet(_ *context.T, _ rpc.ServerCall, handle principal.BlessingsHandle, pattern security.BlessingPattern) (*principal.JsBlessings, error) {
- var inputBlessings security.Blessings
- if inputBlessings = c.GetBlessings(handle); inputBlessings.IsZero() {
- return nil, verror.New(invalidBlessingsHandle, nil, handle)
- }
-
- p := v23.GetPrincipal(c.ctx)
- outBlessings, err := p.BlessingStore().Set(inputBlessings, security.BlessingPattern(pattern))
- if err != nil {
- return nil, err
- }
-
- if outBlessings.IsZero() {
- return nil, nil
- }
-
- jsBlessings := principal.ConvertBlessingsToHandle(outBlessings, c.blessingsCache.GetOrAddHandle(outBlessings))
- return jsBlessings, nil
-}
-
-// BlessingStoreForPeer puts the specified blessing in the blessing store under the
-// provided pattern.
-func (c *Controller) BlessingStoreForPeer(_ *context.T, _ rpc.ServerCall, peerBlessings []string) (*principal.JsBlessings, error) {
- p := v23.GetPrincipal(c.ctx)
- outBlessings := p.BlessingStore().ForPeer(peerBlessings...)
-
- if outBlessings.IsZero() {
- return nil, nil
- }
-
- jsBlessings := principal.ConvertBlessingsToHandle(outBlessings, c.blessingsCache.GetOrAddHandle(outBlessings))
- return jsBlessings, nil
-}
-
-// BlessingStoreSetDefault sets the default blessings in the blessing store.
-func (c *Controller) BlessingStoreSetDefault(_ *context.T, _ rpc.ServerCall, handle principal.BlessingsHandle) error {
- var inputBlessings security.Blessings
- if inputBlessings = c.GetBlessings(handle); inputBlessings.IsZero() {
- return verror.New(invalidBlessingsHandle, nil, handle)
- }
-
- p := v23.GetPrincipal(c.ctx)
- return p.BlessingStore().SetDefault(inputBlessings)
-}
-
-// BlessingStoreDefault fetches the default blessings for the principal of the controller.
-func (c *Controller) BlessingStoreDefault(*context.T, rpc.ServerCall) (*principal.JsBlessings, error) {
- p := v23.GetPrincipal(c.ctx)
- outBlessings := p.BlessingStore().Default()
-
- if outBlessings.IsZero() {
- return nil, nil
- }
-
- jsBlessing := principal.ConvertBlessingsToHandle(outBlessings, c.blessingsCache.GetOrAddHandle(outBlessings))
- return jsBlessing, nil
-}
-
-<<<<<<< HEAD
-// BlessingStorePublicKey fetches the public key used by the principal associated with the blessing store.
-func (c *Controller) BlessingStorePublicKey(*context.T, rpc.ServerCall) (string, error) {
- p := v23.GetPrincipal(c.ctx)
- pk := p.BlessingStore().PublicKey()
- return principal.EncodePublicKey(pk)
-}
-
-// BlessingStorePeerBlessings returns all the blessings that the BlessingStore holds.
-func (c *Controller) BlessingStorePeerBlessings(*context.T, rpc.ServerCall) (map[security.BlessingPattern]*principal.JsBlessings, error) {
- p := v23.GetPrincipal(c.ctx)
- outBlessingsMap := map[security.BlessingPattern]*principal.JsBlessings{}
- for pattern, blessings := range p.BlessingStore().PeerBlessings() {
- outBlessingsMap[pattern] = principal.ConvertBlessingsToHandle(blessings, c.blessingsCache.GetOrAddHandle(blessings))
- }
- return outBlessingsMap, nil
-}
-
-// BlessingStoreDebugString retrieves a debug string describing the state of the blessing store
-func (c *Controller) BlessingStoreDebugString(*context.T, rpc.ServerCall) (string, error) {
- p := v23.GetPrincipal(c.ctx)
- ds := p.BlessingStore().DebugString()
- return ds, nil
-}
-
-// AddToRoots adds the provided blessing as a root.
-func (c *Controller) AddToRoots(_ *context.T, _ rpc.ServerCall, handle principal.BlessingsHandle) error {
- var inputBlessings security.Blessings
- if inputBlessings = c.GetBlessings(handle); inputBlessings.IsZero() {
- return verror.New(invalidBlessingsHandle, nil, handle)
- }
-
- p := v23.GetPrincipal(c.ctx)
- return p.AddToRoots(inputBlessings)
-}
-
-=======
->>>>>>> master
-// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
-func (c *Controller) UnionOfBlessings(_ *context.T, _ rpc.ServerCall, handles []principal.BlessingsHandle) (*principal.JsBlessings, error) {
- inputBlessings := make([]security.Blessings, len(handles))
- for i, handle := range handles {
- bless := c.GetBlessings(handle)
- if bless.IsZero() {
- return nil, verror.New(invalidBlessingsHandle, nil, handle)
- }
- inputBlessings[i] = bless
- }
-
- outBlessings, err := security.UnionOfBlessings(inputBlessings...)
- if err != nil {
- return nil, err
- }
-
- jsBlessings := principal.ConvertBlessingsToHandle(outBlessings, c.blessingsCache.GetOrAddHandle(outBlessings))
- return jsBlessings, nil
-}
-
-// HandleGranterResponse handles the result of a Granter request.
-func (c *Controller) HandleGranterResponse(id int32, data string) {
- c.Lock()
- granterStr, ok := c.flowMap[id].(*granterStream)
- c.Unlock()
- if !ok {
- vlog.Errorf("unexpected result from JavaScript. Flow was not a granter "+
- "stream for MessageId: %d exists. Ignoring the results.", id)
- //Ignore unknown responses that don't belong to any channel
- return
- }
- granterStr.Send(data)
-}
-
-func (c *Controller) BlessingsDebugString(_ *context.T, _ rpc.ServerCall, handle principal.BlessingsHandle) (string, error) {
- var inputBlessings security.Blessings
- if inputBlessings = c.GetBlessings(handle); inputBlessings.IsZero() {
- return "", verror.New(invalidBlessingsHandle, nil, handle)
- }
-
- return inputBlessings.String(), nil
-}
-
-func (c *Controller) RemoteBlessings(ctx *context.T, _ rpc.ServerCall, name, method string) ([]string, error) {
- vlog.VI(2).Infof("requesting remote blessings for %q", name)
-
- cctx, cancel := context.WithTimeout(ctx, 5*time.Second)
- defer cancel()
-
- clientCall, err := v23.GetClient(cctx).StartCall(cctx, name, method, nil)
- if err != nil {
- return nil, verror.Convert(verror.ErrInternal, cctx, err)
- }
-
- blessings, _ := clientCall.RemoteBlessings()
- return blessings, nil
-}
-
-func (c *Controller) SendLogMessage(level lib.LogLevel, msg string) error {
- c.Lock()
- defer c.Unlock()
- id := c.lastGeneratedId
- c.lastGeneratedId += 2
- return c.writerCreator(id).Send(lib.ResponseLog, lib.LogMessage{
- Level: level,
- Message: msg,
- })
-}
diff --git a/services/wspr/internal/app/app_test.go b/services/wspr/internal/app/app_test.go
index 537b8fc..b71c6ff 100644
--- a/services/wspr/internal/app/app_test.go
+++ b/services/wspr/internal/app/app_test.go
@@ -136,7 +136,7 @@
}
}
func TestGetGoServerSignature(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
s, endpoint, err := startAdderServer(ctx)
@@ -181,7 +181,7 @@
}
func runGoServerTestCase(t *testing.T, testCase goServerTestCase) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
s, endpoint, err := startAdderServer(ctx)
@@ -430,7 +430,7 @@
}
func runJsServerTestCase(t *testing.T, testCase jsServerTestCase) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
vomClientStream := []string{}
diff --git a/services/wspr/internal/app/controller.vdl b/services/wspr/internal/app/controller.vdl
index 8983e4e..cbe271c 100644
--- a/services/wspr/internal/app/controller.vdl
+++ b/services/wspr/internal/app/controller.vdl
@@ -29,24 +29,24 @@
BlessingsDebugString(handle principal.BlessingsHandle) (string | error)
// Bless binds extensions of blessings held by this principal to
// another principal (represented by its public key).
- Bless(publicKey string, handle principal.BlessingsHandle, extension string, caveat []security.Caveat) (publicKeyOut string, handleOut principal.BlessingsHandle | error)
+ Bless(publicKey string, handle principal.BlessingsHandle, extension string, caveat []security.Caveat) (principal.BlessingsId | error)
// BlessSelf creates a blessing with the provided name for this principal.
- BlessSelf(name string, caveats []security.Caveat) (publicKeyOut string, handleOut principal.BlessingsHandle | error)
+ BlessSelf(name string, caveats []security.Caveat) (principal.BlessingsId | error)
// AddToRoots adds the provided blessing as a root.
AddToRoots(handle principal.BlessingsHandle) error
// BlessingStoreSet puts the specified blessing in the blessing store under the provided pattern.
- BlessingStoreSet(blessingsHandle principal.BlessingsHandle, pattern security.BlessingPattern) (?principal.JsBlessings | error)
+ BlessingStoreSet(blessingsHandle principal.BlessingsHandle, pattern security.BlessingPattern) (principal.BlessingsId | error)
// BlessingStoreForPeer retrieves the blessings marked for the given peers.
- BlessingStoreForPeer(peerBlessings []string) (?principal.JsBlessings | error)
+ BlessingStoreForPeer(peerBlessings []string) (principal.BlessingsId | error)
// BlessingStoreSetDefault sets the default blessings.
BlessingStoreSetDefault(blessingsHandle principal.BlessingsHandle) error
// BlessingStoreDefault fetches the default blessings for the principal of the controller.
- BlessingStoreDefault() (?principal.JsBlessings | error)
+ BlessingStoreDefault() (principal.BlessingsId | error)
// BlessingStorePublicKey fetches the public key of the principal for which this store hosts blessings.
BlessingStorePublicKey() (string | error)
// BlessingStorePeerBlessings returns all the blessings that the BlessingStore holds.
- BlessingStorePeerBlessings() (map[security.BlessingPattern]?principal.JsBlessings | error)
+ BlessingStorePeerBlessings() (map[security.BlessingPattern]principal.BlessingsId | error)
// BlessingStoreDebugString retrieves a debug string describing the state of the blessing store
BlessingStoreDebugString() (string | error)
@@ -57,5 +57,5 @@
Signature(name string) ([]signature.Interface | error)
// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
- UnionOfBlessings(toJoin []principal.BlessingsHandle) (?principal.JsBlessings | error)
+ UnionOfBlessings(toJoin []principal.BlessingsHandle) (principal.BlessingsId | error)
}
diff --git a/services/wspr/internal/app/controller.vdl.go b/services/wspr/internal/app/controller.vdl.go
index 2731e36..4b185de 100644
--- a/services/wspr/internal/app/controller.vdl.go
+++ b/services/wspr/internal/app/controller.vdl.go
@@ -38,23 +38,23 @@
BlessingsDebugString(ctx *context.T, handle principal.BlessingsHandle, opts ...rpc.CallOpt) (string, error)
// Bless binds extensions of blessings held by this principal to
// another principal (represented by its public key).
- Bless(ctx *context.T, publicKey string, handle principal.BlessingsHandle, extension string, caveat []security.Caveat, opts ...rpc.CallOpt) (publicKeyOut string, handleOut principal.BlessingsHandle, err error)
+ Bless(ctx *context.T, publicKey string, handle principal.BlessingsHandle, extension string, caveat []security.Caveat, opts ...rpc.CallOpt) (principal.BlessingsId, error)
// BlessSelf creates a blessing with the provided name for this principal.
- BlessSelf(ctx *context.T, name string, caveats []security.Caveat, opts ...rpc.CallOpt) (publicKeyOut string, handleOut principal.BlessingsHandle, err error)
+ BlessSelf(ctx *context.T, name string, caveats []security.Caveat, opts ...rpc.CallOpt) (principal.BlessingsId, error)
// AddToRoots adds the provided blessing as a root.
AddToRoots(ctx *context.T, handle principal.BlessingsHandle, opts ...rpc.CallOpt) error
// BlessingStoreSet puts the specified blessing in the blessing store under the provided pattern.
- BlessingStoreSet(ctx *context.T, blessingsHandle principal.BlessingsHandle, pattern security.BlessingPattern, opts ...rpc.CallOpt) (*principal.JsBlessings, error)
+ BlessingStoreSet(ctx *context.T, blessingsHandle principal.BlessingsHandle, pattern security.BlessingPattern, opts ...rpc.CallOpt) (principal.BlessingsId, error)
// BlessingStoreForPeer retrieves the blessings marked for the given peers.
- BlessingStoreForPeer(ctx *context.T, peerBlessings []string, opts ...rpc.CallOpt) (*principal.JsBlessings, error)
+ BlessingStoreForPeer(ctx *context.T, peerBlessings []string, opts ...rpc.CallOpt) (principal.BlessingsId, error)
// BlessingStoreSetDefault sets the default blessings.
BlessingStoreSetDefault(ctx *context.T, blessingsHandle principal.BlessingsHandle, opts ...rpc.CallOpt) error
// BlessingStoreDefault fetches the default blessings for the principal of the controller.
- BlessingStoreDefault(*context.T, ...rpc.CallOpt) (*principal.JsBlessings, error)
+ BlessingStoreDefault(*context.T, ...rpc.CallOpt) (principal.BlessingsId, error)
// BlessingStorePublicKey fetches the public key of the principal for which this store hosts blessings.
BlessingStorePublicKey(*context.T, ...rpc.CallOpt) (string, error)
// BlessingStorePeerBlessings returns all the blessings that the BlessingStore holds.
- BlessingStorePeerBlessings(*context.T, ...rpc.CallOpt) (map[security.BlessingPattern]*principal.JsBlessings, error)
+ BlessingStorePeerBlessings(*context.T, ...rpc.CallOpt) (map[security.BlessingPattern]principal.BlessingsId, error)
// BlessingStoreDebugString retrieves a debug string describing the state of the blessing store
BlessingStoreDebugString(*context.T, ...rpc.CallOpt) (string, error)
// RemoteBlessings fetches the remote blessings for a given name and method.
@@ -62,7 +62,7 @@
// Signature fetches the signature for a given name.
Signature(ctx *context.T, name string, opts ...rpc.CallOpt) ([]signature.Interface, error)
// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
- UnionOfBlessings(ctx *context.T, toJoin []principal.BlessingsHandle, opts ...rpc.CallOpt) (*principal.JsBlessings, error)
+ UnionOfBlessings(ctx *context.T, toJoin []principal.BlessingsHandle, opts ...rpc.CallOpt) (principal.BlessingsId, error)
}
// ControllerClientStub adds universal methods to ControllerClientMethods.
@@ -110,13 +110,13 @@
return
}
-func (c implControllerClientStub) Bless(ctx *context.T, i0 string, i1 principal.BlessingsHandle, i2 string, i3 []security.Caveat, opts ...rpc.CallOpt) (o0 string, o1 principal.BlessingsHandle, err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "Bless", []interface{}{i0, i1, i2, i3}, []interface{}{&o0, &o1}, opts...)
+func (c implControllerClientStub) Bless(ctx *context.T, i0 string, i1 principal.BlessingsHandle, i2 string, i3 []security.Caveat, opts ...rpc.CallOpt) (o0 principal.BlessingsId, err error) {
+ err = v23.GetClient(ctx).Call(ctx, c.name, "Bless", []interface{}{i0, i1, i2, i3}, []interface{}{&o0}, opts...)
return
}
-func (c implControllerClientStub) BlessSelf(ctx *context.T, i0 string, i1 []security.Caveat, opts ...rpc.CallOpt) (o0 string, o1 principal.BlessingsHandle, err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "BlessSelf", []interface{}{i0, i1}, []interface{}{&o0, &o1}, opts...)
+func (c implControllerClientStub) BlessSelf(ctx *context.T, i0 string, i1 []security.Caveat, opts ...rpc.CallOpt) (o0 principal.BlessingsId, err error) {
+ err = v23.GetClient(ctx).Call(ctx, c.name, "BlessSelf", []interface{}{i0, i1}, []interface{}{&o0}, opts...)
return
}
@@ -125,12 +125,12 @@
return
}
-func (c implControllerClientStub) BlessingStoreSet(ctx *context.T, i0 principal.BlessingsHandle, i1 security.BlessingPattern, opts ...rpc.CallOpt) (o0 *principal.JsBlessings, err error) {
+func (c implControllerClientStub) BlessingStoreSet(ctx *context.T, i0 principal.BlessingsHandle, i1 security.BlessingPattern, opts ...rpc.CallOpt) (o0 principal.BlessingsId, err error) {
err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStoreSet", []interface{}{i0, i1}, []interface{}{&o0}, opts...)
return
}
-func (c implControllerClientStub) BlessingStoreForPeer(ctx *context.T, i0 []string, opts ...rpc.CallOpt) (o0 *principal.JsBlessings, err error) {
+func (c implControllerClientStub) BlessingStoreForPeer(ctx *context.T, i0 []string, opts ...rpc.CallOpt) (o0 principal.BlessingsId, err error) {
err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStoreForPeer", []interface{}{i0}, []interface{}{&o0}, opts...)
return
}
@@ -140,7 +140,7 @@
return
}
-func (c implControllerClientStub) BlessingStoreDefault(ctx *context.T, opts ...rpc.CallOpt) (o0 *principal.JsBlessings, err error) {
+func (c implControllerClientStub) BlessingStoreDefault(ctx *context.T, opts ...rpc.CallOpt) (o0 principal.BlessingsId, err error) {
err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStoreDefault", nil, []interface{}{&o0}, opts...)
return
}
@@ -150,7 +150,7 @@
return
}
-func (c implControllerClientStub) BlessingStorePeerBlessings(ctx *context.T, opts ...rpc.CallOpt) (o0 map[security.BlessingPattern]*principal.JsBlessings, err error) {
+func (c implControllerClientStub) BlessingStorePeerBlessings(ctx *context.T, opts ...rpc.CallOpt) (o0 map[security.BlessingPattern]principal.BlessingsId, err error) {
err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStorePeerBlessings", nil, []interface{}{&o0}, opts...)
return
}
@@ -170,7 +170,7 @@
return
}
-func (c implControllerClientStub) UnionOfBlessings(ctx *context.T, i0 []principal.BlessingsHandle, opts ...rpc.CallOpt) (o0 *principal.JsBlessings, err error) {
+func (c implControllerClientStub) UnionOfBlessings(ctx *context.T, i0 []principal.BlessingsHandle, opts ...rpc.CallOpt) (o0 principal.BlessingsId, err error) {
err = v23.GetClient(ctx).Call(ctx, c.name, "UnionOfBlessings", []interface{}{i0}, []interface{}{&o0}, opts...)
return
}
@@ -194,23 +194,23 @@
BlessingsDebugString(ctx *context.T, call rpc.ServerCall, handle principal.BlessingsHandle) (string, error)
// Bless binds extensions of blessings held by this principal to
// another principal (represented by its public key).
- Bless(ctx *context.T, call rpc.ServerCall, publicKey string, handle principal.BlessingsHandle, extension string, caveat []security.Caveat) (publicKeyOut string, handleOut principal.BlessingsHandle, err error)
+ Bless(ctx *context.T, call rpc.ServerCall, publicKey string, handle principal.BlessingsHandle, extension string, caveat []security.Caveat) (principal.BlessingsId, error)
// BlessSelf creates a blessing with the provided name for this principal.
- BlessSelf(ctx *context.T, call rpc.ServerCall, name string, caveats []security.Caveat) (publicKeyOut string, handleOut principal.BlessingsHandle, err error)
+ BlessSelf(ctx *context.T, call rpc.ServerCall, name string, caveats []security.Caveat) (principal.BlessingsId, error)
// AddToRoots adds the provided blessing as a root.
AddToRoots(ctx *context.T, call rpc.ServerCall, handle principal.BlessingsHandle) error
// BlessingStoreSet puts the specified blessing in the blessing store under the provided pattern.
- BlessingStoreSet(ctx *context.T, call rpc.ServerCall, blessingsHandle principal.BlessingsHandle, pattern security.BlessingPattern) (*principal.JsBlessings, error)
+ BlessingStoreSet(ctx *context.T, call rpc.ServerCall, blessingsHandle principal.BlessingsHandle, pattern security.BlessingPattern) (principal.BlessingsId, error)
// BlessingStoreForPeer retrieves the blessings marked for the given peers.
- BlessingStoreForPeer(ctx *context.T, call rpc.ServerCall, peerBlessings []string) (*principal.JsBlessings, error)
+ BlessingStoreForPeer(ctx *context.T, call rpc.ServerCall, peerBlessings []string) (principal.BlessingsId, error)
// BlessingStoreSetDefault sets the default blessings.
BlessingStoreSetDefault(ctx *context.T, call rpc.ServerCall, blessingsHandle principal.BlessingsHandle) error
// BlessingStoreDefault fetches the default blessings for the principal of the controller.
- BlessingStoreDefault(*context.T, rpc.ServerCall) (*principal.JsBlessings, error)
+ BlessingStoreDefault(*context.T, rpc.ServerCall) (principal.BlessingsId, error)
// BlessingStorePublicKey fetches the public key of the principal for which this store hosts blessings.
BlessingStorePublicKey(*context.T, rpc.ServerCall) (string, error)
// BlessingStorePeerBlessings returns all the blessings that the BlessingStore holds.
- BlessingStorePeerBlessings(*context.T, rpc.ServerCall) (map[security.BlessingPattern]*principal.JsBlessings, error)
+ BlessingStorePeerBlessings(*context.T, rpc.ServerCall) (map[security.BlessingPattern]principal.BlessingsId, error)
// BlessingStoreDebugString retrieves a debug string describing the state of the blessing store
BlessingStoreDebugString(*context.T, rpc.ServerCall) (string, error)
// RemoteBlessings fetches the remote blessings for a given name and method.
@@ -218,7 +218,7 @@
// Signature fetches the signature for a given name.
Signature(ctx *context.T, call rpc.ServerCall, name string) ([]signature.Interface, error)
// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
- UnionOfBlessings(ctx *context.T, call rpc.ServerCall, toJoin []principal.BlessingsHandle) (*principal.JsBlessings, error)
+ UnionOfBlessings(ctx *context.T, call rpc.ServerCall, toJoin []principal.BlessingsHandle) (principal.BlessingsId, error)
}
// ControllerServerStubMethods is the server interface containing
@@ -280,11 +280,11 @@
return s.impl.BlessingsDebugString(ctx, call, i0)
}
-func (s implControllerServerStub) Bless(ctx *context.T, call rpc.ServerCall, i0 string, i1 principal.BlessingsHandle, i2 string, i3 []security.Caveat) (string, principal.BlessingsHandle, error) {
+func (s implControllerServerStub) Bless(ctx *context.T, call rpc.ServerCall, i0 string, i1 principal.BlessingsHandle, i2 string, i3 []security.Caveat) (principal.BlessingsId, error) {
return s.impl.Bless(ctx, call, i0, i1, i2, i3)
}
-func (s implControllerServerStub) BlessSelf(ctx *context.T, call rpc.ServerCall, i0 string, i1 []security.Caveat) (string, principal.BlessingsHandle, error) {
+func (s implControllerServerStub) BlessSelf(ctx *context.T, call rpc.ServerCall, i0 string, i1 []security.Caveat) (principal.BlessingsId, error) {
return s.impl.BlessSelf(ctx, call, i0, i1)
}
@@ -292,11 +292,11 @@
return s.impl.AddToRoots(ctx, call, i0)
}
-func (s implControllerServerStub) BlessingStoreSet(ctx *context.T, call rpc.ServerCall, i0 principal.BlessingsHandle, i1 security.BlessingPattern) (*principal.JsBlessings, error) {
+func (s implControllerServerStub) BlessingStoreSet(ctx *context.T, call rpc.ServerCall, i0 principal.BlessingsHandle, i1 security.BlessingPattern) (principal.BlessingsId, error) {
return s.impl.BlessingStoreSet(ctx, call, i0, i1)
}
-func (s implControllerServerStub) BlessingStoreForPeer(ctx *context.T, call rpc.ServerCall, i0 []string) (*principal.JsBlessings, error) {
+func (s implControllerServerStub) BlessingStoreForPeer(ctx *context.T, call rpc.ServerCall, i0 []string) (principal.BlessingsId, error) {
return s.impl.BlessingStoreForPeer(ctx, call, i0)
}
@@ -304,7 +304,7 @@
return s.impl.BlessingStoreSetDefault(ctx, call, i0)
}
-func (s implControllerServerStub) BlessingStoreDefault(ctx *context.T, call rpc.ServerCall) (*principal.JsBlessings, error) {
+func (s implControllerServerStub) BlessingStoreDefault(ctx *context.T, call rpc.ServerCall) (principal.BlessingsId, error) {
return s.impl.BlessingStoreDefault(ctx, call)
}
@@ -312,7 +312,7 @@
return s.impl.BlessingStorePublicKey(ctx, call)
}
-func (s implControllerServerStub) BlessingStorePeerBlessings(ctx *context.T, call rpc.ServerCall) (map[security.BlessingPattern]*principal.JsBlessings, error) {
+func (s implControllerServerStub) BlessingStorePeerBlessings(ctx *context.T, call rpc.ServerCall) (map[security.BlessingPattern]principal.BlessingsId, error) {
return s.impl.BlessingStorePeerBlessings(ctx, call)
}
@@ -328,7 +328,7 @@
return s.impl.Signature(ctx, call, i0)
}
-func (s implControllerServerStub) UnionOfBlessings(ctx *context.T, call rpc.ServerCall, i0 []principal.BlessingsHandle) (*principal.JsBlessings, error) {
+func (s implControllerServerStub) UnionOfBlessings(ctx *context.T, call rpc.ServerCall, i0 []principal.BlessingsHandle) (principal.BlessingsId, error) {
return s.impl.UnionOfBlessings(ctx, call, i0)
}
@@ -407,8 +407,7 @@
{"caveat", ``}, // []security.Caveat
},
OutArgs: []rpc.ArgDesc{
- {"publicKeyOut", ``}, // string
- {"handleOut", ``}, // principal.BlessingsHandle
+ {"", ``}, // principal.BlessingsId
},
},
{
@@ -419,8 +418,7 @@
{"caveats", ``}, // []security.Caveat
},
OutArgs: []rpc.ArgDesc{
- {"publicKeyOut", ``}, // string
- {"handleOut", ``}, // principal.BlessingsHandle
+ {"", ``}, // principal.BlessingsId
},
},
{
@@ -438,7 +436,7 @@
{"pattern", ``}, // security.BlessingPattern
},
OutArgs: []rpc.ArgDesc{
- {"", ``}, // *principal.JsBlessings
+ {"", ``}, // principal.BlessingsId
},
},
{
@@ -448,7 +446,7 @@
{"peerBlessings", ``}, // []string
},
OutArgs: []rpc.ArgDesc{
- {"", ``}, // *principal.JsBlessings
+ {"", ``}, // principal.BlessingsId
},
},
{
@@ -462,7 +460,7 @@
Name: "BlessingStoreDefault",
Doc: "// BlessingStoreDefault fetches the default blessings for the principal of the controller.",
OutArgs: []rpc.ArgDesc{
- {"", ``}, // *principal.JsBlessings
+ {"", ``}, // principal.BlessingsId
},
},
{
@@ -476,7 +474,7 @@
Name: "BlessingStorePeerBlessings",
Doc: "// BlessingStorePeerBlessings returns all the blessings that the BlessingStore holds.",
OutArgs: []rpc.ArgDesc{
- {"", ``}, // map[security.BlessingPattern]*principal.JsBlessings
+ {"", ``}, // map[security.BlessingPattern]principal.BlessingsId
},
},
{
@@ -514,7 +512,7 @@
{"toJoin", ``}, // []principal.BlessingsHandle
},
OutArgs: []rpc.ArgDesc{
- {"", ``}, // *principal.JsBlessings
+ {"", ``}, // principal.BlessingsId
},
},
},
diff --git a/services/wspr/internal/app/controller.vdl.go.orig b/services/wspr/internal/app/controller.vdl.go.orig
deleted file mode 100644
index b8d730a..0000000
--- a/services/wspr/internal/app/controller.vdl.go.orig
+++ /dev/null
@@ -1,550 +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.
-
-// This file was auto-generated by the vanadium vdl tool.
-// Source: controller.vdl
-
-package app
-
-import (
- // VDL system imports
- "v.io/v23"
- "v.io/v23/context"
- "v.io/v23/rpc"
-
- // VDL user imports
- "v.io/v23/security"
- "v.io/v23/vdlroot/signature"
- "v.io/x/ref/services/wspr/internal/principal"
-)
-
-// ControllerClientMethods is the client interface
-// containing Controller methods.
-type ControllerClientMethods interface {
- // Serve instructs WSPR to start listening for calls on behalf
- // of a javascript server.
- Serve(ctx *context.T, name string, serverId uint32, serverOpts []RpcServerOption, opts ...rpc.CallOpt) error
- // Stop instructs WSPR to stop listening for calls for the
- // given javascript server.
- Stop(ctx *context.T, serverId uint32, opts ...rpc.CallOpt) error
- // AddName adds a published name to an existing server.
- AddName(ctx *context.T, serverId uint32, name string, opts ...rpc.CallOpt) error
- // RemoveName removes a published name from an existing server.
- RemoveName(ctx *context.T, serverId uint32, name string, opts ...rpc.CallOpt) error
- // UnlinkBlessings removes the given blessings from the blessings store.
- UnlinkBlessings(ctx *context.T, handle principal.BlessingsHandle, opts ...rpc.CallOpt) error
- // BlessingsDebugString gets a string useful for debugging blessings.
- BlessingsDebugString(ctx *context.T, handle principal.BlessingsHandle, opts ...rpc.CallOpt) (string, error)
- // Bless binds extensions of blessings held by this principal to
- // another principal (represented by its public key).
- Bless(ctx *context.T, publicKey string, handle principal.BlessingsHandle, extension string, caveat []security.Caveat, opts ...rpc.CallOpt) (publicKeyOut string, handleOut principal.BlessingsHandle, err error)
- // BlessSelf creates a blessing with the provided name for this principal.
- BlessSelf(ctx *context.T, name string, caveats []security.Caveat, opts ...rpc.CallOpt) (publicKeyOut string, handleOut principal.BlessingsHandle, err error)
- // AddToRoots adds the provided blessing as a root.
- AddToRoots(ctx *context.T, handle principal.BlessingsHandle, opts ...rpc.CallOpt) error
- // BlessingStoreSet puts the specified blessing in the blessing store under the provided pattern.
- BlessingStoreSet(ctx *context.T, blessingsHandle principal.BlessingsHandle, pattern security.BlessingPattern, opts ...rpc.CallOpt) (*principal.JsBlessings, error)
- // BlessingStoreForPeer retrieves the blessings marked for the given peers.
- BlessingStoreForPeer(ctx *context.T, peerBlessings []string, opts ...rpc.CallOpt) (*principal.JsBlessings, error)
- // BlessingStoreSetDefault sets the default blessings.
- BlessingStoreSetDefault(ctx *context.T, blessingsHandle principal.BlessingsHandle, opts ...rpc.CallOpt) error
- // BlessingStoreDefault fetches the default blessings for the principal of the controller.
- BlessingStoreDefault(*context.T, ...rpc.CallOpt) (*principal.JsBlessings, error)
- // BlessingStorePublicKey fetches the public key of the principal for which this store hosts blessings.
- BlessingStorePublicKey(*context.T, ...rpc.CallOpt) (string, error)
- // BlessingStorePeerBlessings returns all the blessings that the BlessingStore holds.
- BlessingStorePeerBlessings(*context.T, ...rpc.CallOpt) (map[security.BlessingPattern]*principal.JsBlessings, error)
- // BlessingStoreDebugString retrieves a debug string describing the state of the blessing store
- BlessingStoreDebugString(*context.T, ...rpc.CallOpt) (string, error)
- // RemoteBlessings fetches the remote blessings for a given name and method.
- RemoteBlessings(ctx *context.T, name string, method string, opts ...rpc.CallOpt) ([]string, error)
- // Signature fetches the signature for a given name.
- Signature(ctx *context.T, name string, opts ...rpc.CallOpt) ([]signature.Interface, error)
-<<<<<<< HEAD
-=======
- // GetDefaultBlessings fetches the default blessings for the principal of the controller.
- GetDefaultBlessings(*context.T, ...rpc.CallOpt) (*principal.JsBlessings, error)
->>>>>>> master
- // UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
- UnionOfBlessings(ctx *context.T, toJoin []principal.BlessingsHandle, opts ...rpc.CallOpt) (*principal.JsBlessings, error)
-}
-
-// ControllerClientStub adds universal methods to ControllerClientMethods.
-type ControllerClientStub interface {
- ControllerClientMethods
- rpc.UniversalServiceMethods
-}
-
-// ControllerClient returns a client stub for Controller.
-func ControllerClient(name string) ControllerClientStub {
- return implControllerClientStub{name}
-}
-
-type implControllerClientStub struct {
- name string
-}
-
-func (c implControllerClientStub) Serve(ctx *context.T, i0 string, i1 uint32, i2 []RpcServerOption, opts ...rpc.CallOpt) (err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "Serve", []interface{}{i0, i1, i2}, nil, opts...)
- return
-}
-
-func (c implControllerClientStub) Stop(ctx *context.T, i0 uint32, opts ...rpc.CallOpt) (err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "Stop", []interface{}{i0}, nil, opts...)
- return
-}
-
-func (c implControllerClientStub) AddName(ctx *context.T, i0 uint32, i1 string, opts ...rpc.CallOpt) (err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "AddName", []interface{}{i0, i1}, nil, opts...)
- return
-}
-
-func (c implControllerClientStub) RemoveName(ctx *context.T, i0 uint32, i1 string, opts ...rpc.CallOpt) (err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "RemoveName", []interface{}{i0, i1}, nil, opts...)
- return
-}
-
-func (c implControllerClientStub) UnlinkBlessings(ctx *context.T, i0 principal.BlessingsHandle, opts ...rpc.CallOpt) (err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "UnlinkBlessings", []interface{}{i0}, nil, opts...)
- return
-}
-
-func (c implControllerClientStub) BlessingsDebugString(ctx *context.T, i0 principal.BlessingsHandle, opts ...rpc.CallOpt) (o0 string, err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingsDebugString", []interface{}{i0}, []interface{}{&o0}, opts...)
- return
-}
-
-func (c implControllerClientStub) Bless(ctx *context.T, i0 string, i1 principal.BlessingsHandle, i2 string, i3 []security.Caveat, opts ...rpc.CallOpt) (o0 string, o1 principal.BlessingsHandle, err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "Bless", []interface{}{i0, i1, i2, i3}, []interface{}{&o0, &o1}, opts...)
- return
-}
-
-func (c implControllerClientStub) BlessSelf(ctx *context.T, i0 string, i1 []security.Caveat, opts ...rpc.CallOpt) (o0 string, o1 principal.BlessingsHandle, err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "BlessSelf", []interface{}{i0, i1}, []interface{}{&o0, &o1}, opts...)
- return
-}
-
-func (c implControllerClientStub) AddToRoots(ctx *context.T, i0 principal.BlessingsHandle, opts ...rpc.CallOpt) (err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "AddToRoots", []interface{}{i0}, nil, opts...)
- return
-}
-
-func (c implControllerClientStub) BlessingStoreSet(ctx *context.T, i0 principal.BlessingsHandle, i1 security.BlessingPattern, opts ...rpc.CallOpt) (o0 *principal.JsBlessings, err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStoreSet", []interface{}{i0, i1}, []interface{}{&o0}, opts...)
- return
-}
-
-func (c implControllerClientStub) BlessingStoreForPeer(ctx *context.T, i0 []string, opts ...rpc.CallOpt) (o0 *principal.JsBlessings, err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStoreForPeer", []interface{}{i0}, []interface{}{&o0}, opts...)
- return
-}
-
-func (c implControllerClientStub) BlessingStoreSetDefault(ctx *context.T, i0 principal.BlessingsHandle, opts ...rpc.CallOpt) (err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStoreSetDefault", []interface{}{i0}, nil, opts...)
- return
-}
-
-func (c implControllerClientStub) BlessingStoreDefault(ctx *context.T, opts ...rpc.CallOpt) (o0 *principal.JsBlessings, err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStoreDefault", nil, []interface{}{&o0}, opts...)
- return
-}
-
-func (c implControllerClientStub) BlessingStorePublicKey(ctx *context.T, opts ...rpc.CallOpt) (o0 string, err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStorePublicKey", nil, []interface{}{&o0}, opts...)
- return
-}
-
-func (c implControllerClientStub) BlessingStorePeerBlessings(ctx *context.T, opts ...rpc.CallOpt) (o0 map[security.BlessingPattern]*principal.JsBlessings, err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStorePeerBlessings", nil, []interface{}{&o0}, opts...)
- return
-}
-
-func (c implControllerClientStub) BlessingStoreDebugString(ctx *context.T, opts ...rpc.CallOpt) (o0 string, err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "BlessingStoreDebugString", nil, []interface{}{&o0}, opts...)
- return
-}
-
-func (c implControllerClientStub) RemoteBlessings(ctx *context.T, i0 string, i1 string, opts ...rpc.CallOpt) (o0 []string, err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "RemoteBlessings", []interface{}{i0, i1}, []interface{}{&o0}, opts...)
- return
-}
-
-func (c implControllerClientStub) Signature(ctx *context.T, i0 string, opts ...rpc.CallOpt) (o0 []signature.Interface, err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "Signature", []interface{}{i0}, []interface{}{&o0}, opts...)
- return
-}
-
-func (c implControllerClientStub) UnionOfBlessings(ctx *context.T, i0 []principal.BlessingsHandle, opts ...rpc.CallOpt) (o0 *principal.JsBlessings, err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "UnionOfBlessings", []interface{}{i0}, []interface{}{&o0}, opts...)
- return
-}
-
-func (c implControllerClientStub) UnionOfBlessings(ctx *context.T, i0 []principal.BlessingsHandle, opts ...rpc.CallOpt) (o0 *principal.JsBlessings, err error) {
- err = v23.GetClient(ctx).Call(ctx, c.name, "UnionOfBlessings", []interface{}{i0}, []interface{}{&o0}, opts...)
- return
-}
-
-// ControllerServerMethods is the interface a server writer
-// implements for Controller.
-type ControllerServerMethods interface {
- // Serve instructs WSPR to start listening for calls on behalf
- // of a javascript server.
- Serve(ctx *context.T, call rpc.ServerCall, name string, serverId uint32, serverOpts []RpcServerOption) error
- // Stop instructs WSPR to stop listening for calls for the
- // given javascript server.
- Stop(ctx *context.T, call rpc.ServerCall, serverId uint32) error
- // AddName adds a published name to an existing server.
- AddName(ctx *context.T, call rpc.ServerCall, serverId uint32, name string) error
- // RemoveName removes a published name from an existing server.
- RemoveName(ctx *context.T, call rpc.ServerCall, serverId uint32, name string) error
- // UnlinkBlessings removes the given blessings from the blessings store.
- UnlinkBlessings(ctx *context.T, call rpc.ServerCall, handle principal.BlessingsHandle) error
- // BlessingsDebugString gets a string useful for debugging blessings.
- BlessingsDebugString(ctx *context.T, call rpc.ServerCall, handle principal.BlessingsHandle) (string, error)
- // Bless binds extensions of blessings held by this principal to
- // another principal (represented by its public key).
- Bless(ctx *context.T, call rpc.ServerCall, publicKey string, handle principal.BlessingsHandle, extension string, caveat []security.Caveat) (publicKeyOut string, handleOut principal.BlessingsHandle, err error)
- // BlessSelf creates a blessing with the provided name for this principal.
- BlessSelf(ctx *context.T, call rpc.ServerCall, name string, caveats []security.Caveat) (publicKeyOut string, handleOut principal.BlessingsHandle, err error)
- // AddToRoots adds the provided blessing as a root.
- AddToRoots(ctx *context.T, call rpc.ServerCall, handle principal.BlessingsHandle) error
- // BlessingStoreSet puts the specified blessing in the blessing store under the provided pattern.
- BlessingStoreSet(ctx *context.T, call rpc.ServerCall, blessingsHandle principal.BlessingsHandle, pattern security.BlessingPattern) (*principal.JsBlessings, error)
- // BlessingStoreForPeer retrieves the blessings marked for the given peers.
- BlessingStoreForPeer(ctx *context.T, call rpc.ServerCall, peerBlessings []string) (*principal.JsBlessings, error)
- // BlessingStoreSetDefault sets the default blessings.
- BlessingStoreSetDefault(ctx *context.T, call rpc.ServerCall, blessingsHandle principal.BlessingsHandle) error
- // BlessingStoreDefault fetches the default blessings for the principal of the controller.
- BlessingStoreDefault(*context.T, rpc.ServerCall) (*principal.JsBlessings, error)
- // BlessingStorePublicKey fetches the public key of the principal for which this store hosts blessings.
- BlessingStorePublicKey(*context.T, rpc.ServerCall) (string, error)
- // BlessingStorePeerBlessings returns all the blessings that the BlessingStore holds.
- BlessingStorePeerBlessings(*context.T, rpc.ServerCall) (map[security.BlessingPattern]*principal.JsBlessings, error)
- // BlessingStoreDebugString retrieves a debug string describing the state of the blessing store
- BlessingStoreDebugString(*context.T, rpc.ServerCall) (string, error)
- // RemoteBlessings fetches the remote blessings for a given name and method.
- RemoteBlessings(ctx *context.T, call rpc.ServerCall, name string, method string) ([]string, error)
- // Signature fetches the signature for a given name.
- Signature(ctx *context.T, call rpc.ServerCall, name string) ([]signature.Interface, error)
-<<<<<<< HEAD
-=======
- // GetDefaultBlessings fetches the default blessings for the principal of the controller.
- GetDefaultBlessings(*context.T, rpc.ServerCall) (*principal.JsBlessings, error)
->>>>>>> master
- // UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
- UnionOfBlessings(ctx *context.T, call rpc.ServerCall, toJoin []principal.BlessingsHandle) (*principal.JsBlessings, error)
-}
-
-// ControllerServerStubMethods is the server interface containing
-// Controller methods, as expected by rpc.Server.
-// There is no difference between this interface and ControllerServerMethods
-// since there are no streaming methods.
-type ControllerServerStubMethods ControllerServerMethods
-
-// ControllerServerStub adds universal methods to ControllerServerStubMethods.
-type ControllerServerStub interface {
- ControllerServerStubMethods
- // Describe the Controller interfaces.
- Describe__() []rpc.InterfaceDesc
-}
-
-// ControllerServer returns a server stub for Controller.
-// It converts an implementation of ControllerServerMethods into
-// an object that may be used by rpc.Server.
-func ControllerServer(impl ControllerServerMethods) ControllerServerStub {
- stub := implControllerServerStub{
- impl: impl,
- }
- // Initialize GlobState; always check the stub itself first, to handle the
- // case where the user has the Glob method defined in their VDL source.
- if gs := rpc.NewGlobState(stub); gs != nil {
- stub.gs = gs
- } else if gs := rpc.NewGlobState(impl); gs != nil {
- stub.gs = gs
- }
- return stub
-}
-
-type implControllerServerStub struct {
- impl ControllerServerMethods
- gs *rpc.GlobState
-}
-
-func (s implControllerServerStub) Serve(ctx *context.T, call rpc.ServerCall, i0 string, i1 uint32, i2 []RpcServerOption) error {
- return s.impl.Serve(ctx, call, i0, i1, i2)
-}
-
-func (s implControllerServerStub) Stop(ctx *context.T, call rpc.ServerCall, i0 uint32) error {
- return s.impl.Stop(ctx, call, i0)
-}
-
-func (s implControllerServerStub) AddName(ctx *context.T, call rpc.ServerCall, i0 uint32, i1 string) error {
- return s.impl.AddName(ctx, call, i0, i1)
-}
-
-func (s implControllerServerStub) RemoveName(ctx *context.T, call rpc.ServerCall, i0 uint32, i1 string) error {
- return s.impl.RemoveName(ctx, call, i0, i1)
-}
-
-func (s implControllerServerStub) UnlinkBlessings(ctx *context.T, call rpc.ServerCall, i0 principal.BlessingsHandle) error {
- return s.impl.UnlinkBlessings(ctx, call, i0)
-}
-
-func (s implControllerServerStub) BlessingsDebugString(ctx *context.T, call rpc.ServerCall, i0 principal.BlessingsHandle) (string, error) {
- return s.impl.BlessingsDebugString(ctx, call, i0)
-}
-
-func (s implControllerServerStub) Bless(ctx *context.T, call rpc.ServerCall, i0 string, i1 principal.BlessingsHandle, i2 string, i3 []security.Caveat) (string, principal.BlessingsHandle, error) {
- return s.impl.Bless(ctx, call, i0, i1, i2, i3)
-}
-
-func (s implControllerServerStub) BlessSelf(ctx *context.T, call rpc.ServerCall, i0 string, i1 []security.Caveat) (string, principal.BlessingsHandle, error) {
- return s.impl.BlessSelf(ctx, call, i0, i1)
-}
-
-func (s implControllerServerStub) AddToRoots(ctx *context.T, call rpc.ServerCall, i0 principal.BlessingsHandle) error {
- return s.impl.AddToRoots(ctx, call, i0)
-}
-
-func (s implControllerServerStub) BlessingStoreSet(ctx *context.T, call rpc.ServerCall, i0 principal.BlessingsHandle, i1 security.BlessingPattern) (*principal.JsBlessings, error) {
- return s.impl.BlessingStoreSet(ctx, call, i0, i1)
-}
-
-func (s implControllerServerStub) BlessingStoreForPeer(ctx *context.T, call rpc.ServerCall, i0 []string) (*principal.JsBlessings, error) {
- return s.impl.BlessingStoreForPeer(ctx, call, i0)
-}
-
-func (s implControllerServerStub) BlessingStoreSetDefault(ctx *context.T, call rpc.ServerCall, i0 principal.BlessingsHandle) error {
- return s.impl.BlessingStoreSetDefault(ctx, call, i0)
-}
-
-func (s implControllerServerStub) BlessingStoreDefault(ctx *context.T, call rpc.ServerCall) (*principal.JsBlessings, error) {
- return s.impl.BlessingStoreDefault(ctx, call)
-}
-
-func (s implControllerServerStub) BlessingStorePublicKey(ctx *context.T, call rpc.ServerCall) (string, error) {
- return s.impl.BlessingStorePublicKey(ctx, call)
-}
-
-func (s implControllerServerStub) BlessingStorePeerBlessings(ctx *context.T, call rpc.ServerCall) (map[security.BlessingPattern]*principal.JsBlessings, error) {
- return s.impl.BlessingStorePeerBlessings(ctx, call)
-}
-
-func (s implControllerServerStub) BlessingStoreDebugString(ctx *context.T, call rpc.ServerCall) (string, error) {
- return s.impl.BlessingStoreDebugString(ctx, call)
-}
-
-func (s implControllerServerStub) RemoteBlessings(ctx *context.T, call rpc.ServerCall, i0 string, i1 string) ([]string, error) {
- return s.impl.RemoteBlessings(ctx, call, i0, i1)
-}
-
-func (s implControllerServerStub) Signature(ctx *context.T, call rpc.ServerCall, i0 string) ([]signature.Interface, error) {
- return s.impl.Signature(ctx, call, i0)
-}
-
-func (s implControllerServerStub) UnionOfBlessings(ctx *context.T, call rpc.ServerCall, i0 []principal.BlessingsHandle) (*principal.JsBlessings, error) {
- return s.impl.UnionOfBlessings(ctx, call, i0)
-}
-
-func (s implControllerServerStub) UnionOfBlessings(ctx *context.T, call rpc.ServerCall, i0 []principal.BlessingsHandle) (*principal.JsBlessings, error) {
- return s.impl.UnionOfBlessings(ctx, call, i0)
-}
-
-func (s implControllerServerStub) Globber() *rpc.GlobState {
- return s.gs
-}
-
-func (s implControllerServerStub) Describe__() []rpc.InterfaceDesc {
- return []rpc.InterfaceDesc{ControllerDesc}
-}
-
-// ControllerDesc describes the Controller interface.
-var ControllerDesc rpc.InterfaceDesc = descController
-
-// descController hides the desc to keep godoc clean.
-var descController = rpc.InterfaceDesc{
- Name: "Controller",
- PkgPath: "v.io/x/ref/services/wspr/internal/app",
- Methods: []rpc.MethodDesc{
- {
- Name: "Serve",
- Doc: "// Serve instructs WSPR to start listening for calls on behalf\n// of a javascript server.",
- InArgs: []rpc.ArgDesc{
- {"name", ``}, // string
- {"serverId", ``}, // uint32
- {"serverOpts", ``}, // []RpcServerOption
- },
- },
- {
- Name: "Stop",
- Doc: "// Stop instructs WSPR to stop listening for calls for the\n// given javascript server.",
- InArgs: []rpc.ArgDesc{
- {"serverId", ``}, // uint32
- },
- },
- {
- Name: "AddName",
- Doc: "// AddName adds a published name to an existing server.",
- InArgs: []rpc.ArgDesc{
- {"serverId", ``}, // uint32
- {"name", ``}, // string
- },
- },
- {
- Name: "RemoveName",
- Doc: "// RemoveName removes a published name from an existing server.",
- InArgs: []rpc.ArgDesc{
- {"serverId", ``}, // uint32
- {"name", ``}, // string
- },
- },
- {
- Name: "UnlinkBlessings",
- Doc: "// UnlinkBlessings removes the given blessings from the blessings store.",
- InArgs: []rpc.ArgDesc{
- {"handle", ``}, // principal.BlessingsHandle
- },
- },
- {
- Name: "BlessingsDebugString",
- Doc: "// BlessingsDebugString gets a string useful for debugging blessings.",
- InArgs: []rpc.ArgDesc{
- {"handle", ``}, // principal.BlessingsHandle
- },
- OutArgs: []rpc.ArgDesc{
- {"", ``}, // string
- },
- },
- {
- Name: "Bless",
- Doc: "// Bless binds extensions of blessings held by this principal to\n// another principal (represented by its public key).",
- InArgs: []rpc.ArgDesc{
- {"publicKey", ``}, // string
- {"handle", ``}, // principal.BlessingsHandle
- {"extension", ``}, // string
- {"caveat", ``}, // []security.Caveat
- },
- OutArgs: []rpc.ArgDesc{
- {"publicKeyOut", ``}, // string
- {"handleOut", ``}, // principal.BlessingsHandle
- },
- },
- {
- Name: "BlessSelf",
- Doc: "// BlessSelf creates a blessing with the provided name for this principal.",
- InArgs: []rpc.ArgDesc{
- {"name", ``}, // string
- {"caveats", ``}, // []security.Caveat
- },
- OutArgs: []rpc.ArgDesc{
- {"publicKeyOut", ``}, // string
- {"handleOut", ``}, // principal.BlessingsHandle
- },
- },
- {
- Name: "AddToRoots",
- Doc: "// AddToRoots adds the provided blessing as a root.",
- InArgs: []rpc.ArgDesc{
- {"handle", ``}, // principal.BlessingsHandle
- },
- },
- {
- Name: "BlessingStoreSet",
- Doc: "// BlessingStoreSet puts the specified blessing in the blessing store under the provided pattern.",
- InArgs: []rpc.ArgDesc{
- {"blessingsHandle", ``}, // principal.BlessingsHandle
- {"pattern", ``}, // security.BlessingPattern
- },
- OutArgs: []rpc.ArgDesc{
- {"", ``}, // *principal.JsBlessings
- },
- },
- {
- Name: "BlessingStoreForPeer",
- Doc: "// BlessingStoreForPeer retrieves the blessings marked for the given peers.",
- InArgs: []rpc.ArgDesc{
- {"peerBlessings", ``}, // []string
- },
- OutArgs: []rpc.ArgDesc{
- {"", ``}, // *principal.JsBlessings
- },
- },
- {
- Name: "BlessingStoreSetDefault",
- Doc: "// BlessingStoreSetDefault sets the default blessings.",
- InArgs: []rpc.ArgDesc{
- {"blessingsHandle", ``}, // principal.BlessingsHandle
- },
- },
- {
- Name: "BlessingStoreDefault",
- Doc: "// BlessingStoreDefault fetches the default blessings for the principal of the controller.",
- OutArgs: []rpc.ArgDesc{
- {"", ``}, // *principal.JsBlessings
- },
- },
- {
- Name: "BlessingStorePublicKey",
- Doc: "// BlessingStorePublicKey fetches the public key of the principal for which this store hosts blessings.",
- OutArgs: []rpc.ArgDesc{
- {"", ``}, // string
- },
- },
- {
- Name: "BlessingStorePeerBlessings",
- Doc: "// BlessingStorePeerBlessings returns all the blessings that the BlessingStore holds.",
- OutArgs: []rpc.ArgDesc{
- {"", ``}, // map[security.BlessingPattern]*principal.JsBlessings
- },
- },
- {
- Name: "BlessingStoreDebugString",
- Doc: "// BlessingStoreDebugString retrieves a debug string describing the state of the blessing store",
- OutArgs: []rpc.ArgDesc{
- {"", ``}, // string
- },
- },
- {
- Name: "RemoteBlessings",
- Doc: "// RemoteBlessings fetches the remote blessings for a given name and method.",
- InArgs: []rpc.ArgDesc{
- {"name", ``}, // string
- {"method", ``}, // string
- },
- OutArgs: []rpc.ArgDesc{
- {"", ``}, // []string
- },
- },
- {
- Name: "Signature",
- Doc: "// Signature fetches the signature for a given name.",
- InArgs: []rpc.ArgDesc{
- {"name", ``}, // string
- },
- OutArgs: []rpc.ArgDesc{
- {"", ``}, // []signature.Interface
- },
- },
- {
- Name: "UnionOfBlessings",
- Doc: "// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.",
- InArgs: []rpc.ArgDesc{
- {"toJoin", ``}, // []principal.BlessingsHandle
- },
- OutArgs: []rpc.ArgDesc{
- {"", ``}, // *principal.JsBlessings
- },
- },
- {
- Name: "UnionOfBlessings",
- Doc: "// UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.",
- InArgs: []rpc.ArgDesc{
- {"toJoin", ``}, // []principal.BlessingsHandle
- },
- OutArgs: []rpc.ArgDesc{
- {"", ``}, // *principal.JsBlessings
- },
- },
- },
-}
diff --git a/services/wspr/internal/app/controller.vdl.orig b/services/wspr/internal/app/controller.vdl.orig
deleted file mode 100644
index 87cc159..0000000
--- a/services/wspr/internal/app/controller.vdl.orig
+++ /dev/null
@@ -1,67 +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 app
-
-import (
- "signature"
-
- "v.io/v23/security"
- "v.io/x/ref/services/wspr/internal/principal"
-)
-
-type Controller interface {
- // Serve instructs WSPR to start listening for calls on behalf
- // of a javascript server.
- Serve(name string, serverId uint32, serverOpts []RpcServerOption) error
- // Stop instructs WSPR to stop listening for calls for the
- // given javascript server.
- Stop(serverId uint32) error
- // AddName adds a published name to an existing server.
- AddName(serverId uint32, name string) error
- // RemoveName removes a published name from an existing server.
- RemoveName(serverId uint32, name string) error
-
- // UnlinkBlessings removes the given blessings from the blessings store.
- UnlinkBlessings(handle principal.BlessingsHandle) error
- // BlessingsDebugString gets a string useful for debugging blessings.
- BlessingsDebugString(handle principal.BlessingsHandle) (string | error)
- // Bless binds extensions of blessings held by this principal to
- // another principal (represented by its public key).
- Bless(publicKey string, handle principal.BlessingsHandle, extension string, caveat []security.Caveat) (publicKeyOut string, handleOut principal.BlessingsHandle | error)
- // BlessSelf creates a blessing with the provided name for this principal.
- BlessSelf(name string, caveats []security.Caveat) (publicKeyOut string, handleOut principal.BlessingsHandle | error)
- // AddToRoots adds the provided blessing as a root.
- AddToRoots(handle principal.BlessingsHandle) error
-
- // BlessingStoreSet puts the specified blessing in the blessing store under the provided pattern.
- BlessingStoreSet(blessingsHandle principal.BlessingsHandle, pattern security.BlessingPattern) (?principal.JsBlessings | error)
- // BlessingStoreForPeer retrieves the blessings marked for the given peers.
- BlessingStoreForPeer(peerBlessings []string) (?principal.JsBlessings | error)
- // BlessingStoreSetDefault sets the default blessings.
- BlessingStoreSetDefault(blessingsHandle principal.BlessingsHandle) error
- // BlessingStoreDefault fetches the default blessings for the principal of the controller.
- BlessingStoreDefault() (?principal.JsBlessings | error)
- // BlessingStorePublicKey fetches the public key of the principal for which this store hosts blessings.
- BlessingStorePublicKey() (string | error)
- // BlessingStorePeerBlessings returns all the blessings that the BlessingStore holds.
- BlessingStorePeerBlessings() (map[security.BlessingPattern]?principal.JsBlessings | error)
- // BlessingStoreDebugString retrieves a debug string describing the state of the blessing store
- BlessingStoreDebugString() (string | error)
-
-
- // RemoteBlessings fetches the remote blessings for a given name and method.
- RemoteBlessings(name, method string) ([]string | error)
- // Signature fetches the signature for a given name.
- Signature(name string) ([]signature.Interface | error)
-
-<<<<<<< HEAD
- // UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
-=======
- // GetDefaultBlessings fetches the default blessings for the principal of the controller.
- GetDefaultBlessings() (?principal.JsBlessings | error)
- // UnionOfBlessings returns a Blessings object that carries the union of the provided blessings.
->>>>>>> master
- UnionOfBlessings(toJoin []principal.BlessingsHandle) (?principal.JsBlessings | error)
-}
diff --git a/services/wspr/internal/app/mock_jsServer_test.go b/services/wspr/internal/app/mock_jsServer_test.go
index 663efea..27891d2 100644
--- a/services/wspr/internal/app/mock_jsServer_test.go
+++ b/services/wspr/internal/app/mock_jsServer_test.go
@@ -19,7 +19,6 @@
"v.io/v23/vom"
"v.io/x/ref/internal/reflectutil"
"v.io/x/ref/services/wspr/internal/lib"
- "v.io/x/ref/services/wspr/internal/principal"
"v.io/x/ref/services/wspr/internal/rpc/server"
)
@@ -71,7 +70,7 @@
}
m.receivedResponse = vdl.ValueOf(msg)
return nil
- case lib.ResponseLog:
+ case lib.ResponseLog, lib.ResponseBlessingsCacheMessage:
m.flowCount += 2
return nil
case lib.ResponseTypeMessage:
@@ -142,11 +141,6 @@
return nil
}
-// Returns false if the blessing is malformed
-func validateBlessing(blessings principal.JsBlessings) bool {
- return blessings.Handle != 0 && blessings.PublicKey != ""
-}
-
func validateEndpoint(ep string) bool {
return ep != ""
}
@@ -184,13 +178,13 @@
return nil
}
- // We expect localBlessings and remoteBlessings to be set and the publicKey be a string
- if !validateBlessing(call.LocalBlessings) {
- m.controller.HandleAuthResponse(m.flowCount, internalErr(fmt.Sprintf("bad localblessing:%v", call.LocalBlessings)))
+ // We expect localBlessings and remoteBlessings to be a non-zero id
+ if call.LocalBlessings == 0 {
+ m.controller.HandleAuthResponse(m.flowCount, internalErr(fmt.Sprintf("bad local blessing: %v", call.LocalBlessings)))
return nil
}
- if !validateBlessing(call.RemoteBlessings) {
- m.controller.HandleAuthResponse(m.flowCount, internalErr(fmt.Sprintf("bad remoteblessing:%v", call.RemoteBlessings)))
+ if call.RemoteBlessings == 0 {
+ m.controller.HandleAuthResponse(m.flowCount, internalErr(fmt.Sprintf("bad remote blessing: %v", call.RemoteBlessings)))
return nil
}
@@ -256,8 +250,13 @@
return nil
}
- if !validateBlessing(call.RemoteBlessings) {
- m.controller.HandleServerResponse(m.flowCount, internalErr(fmt.Sprintf("bad Remoteblessing:%v", call.RemoteBlessings)))
+ // We expect localBlessings and remoteBlessings to be a non-zero id
+ if call.LocalBlessings == 0 {
+ m.controller.HandleAuthResponse(m.flowCount, internalErr(fmt.Sprintf("bad local blessing: %v", call.LocalBlessings)))
+ return nil
+ }
+ if call.RemoteBlessings == 0 {
+ m.controller.HandleAuthResponse(m.flowCount, internalErr(fmt.Sprintf("bad remote blessing: %v", call.RemoteBlessings)))
return nil
}
diff --git a/services/wspr/internal/app/v23_internal_test.go b/services/wspr/internal/app/v23_internal_test.go
index 9ae5683..70d6982 100644
--- a/services/wspr/internal/app/v23_internal_test.go
+++ b/services/wspr/internal/app/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package app
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/services/wspr/internal/browspr/browspr_account_test.go b/services/wspr/internal/browspr/browspr_account_test.go
index eccef39..ff35bbf 100644
--- a/services/wspr/internal/browspr/browspr_account_test.go
+++ b/services/wspr/internal/browspr/browspr_account_test.go
@@ -43,7 +43,7 @@
}
func setup(t *testing.T) (*Browspr, func()) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
spec := v23.GetListenSpec(ctx)
spec.Proxy = "/mock/proxy"
diff --git a/services/wspr/internal/browspr/browspr_test.go b/services/wspr/internal/browspr/browspr_test.go
index 7b110f9..956fe54 100644
--- a/services/wspr/internal/browspr/browspr_test.go
+++ b/services/wspr/internal/browspr/browspr_test.go
@@ -99,7 +99,7 @@
}
func TestBrowspr(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
proxySpec := rpc.ListenSpec{
diff --git a/services/wspr/internal/browspr/v23_internal_test.go b/services/wspr/internal/browspr/v23_internal_test.go
index 9b21db0..6c94e49 100644
--- a/services/wspr/internal/browspr/v23_internal_test.go
+++ b/services/wspr/internal/browspr/v23_internal_test.go
@@ -4,12 +4,15 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package browspr
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
+ "v.io/x/ref/test"
+)
func TestMain(m *testing.M) {
test.Init()
diff --git a/services/wspr/internal/lib/signature_manager_test.go b/services/wspr/internal/lib/signature_manager_test.go
index 94a0b43..7e50213 100644
--- a/services/wspr/internal/lib/signature_manager_test.go
+++ b/services/wspr/internal/lib/signature_manager_test.go
@@ -22,7 +22,7 @@
)
func initContext(t *testing.T) (*context.T, clientWithTimesCalled, v23.Shutdown) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
initialSig := []signature.Interface{
{
Methods: []signature.Method{
diff --git a/services/wspr/internal/lib/writer.go b/services/wspr/internal/lib/writer.go
index 2a9316c..1c90372 100644
--- a/services/wspr/internal/lib/writer.go
+++ b/services/wspr/internal/lib/writer.go
@@ -7,18 +7,19 @@
type ResponseType int32
const (
- ResponseFinal ResponseType = 0
- ResponseStream = 1
- ResponseError = 2
- ResponseServerRequest = 3
- ResponseStreamClose = 4
- ResponseDispatcherLookup = 5
- ResponseAuthRequest = 6
- ResponseCancel = 7
- ResponseValidate = 8 // Request to validate caveats.
- ResponseLog = 9 // Sends a message to be logged.
- ResponseGranterRequest = 10
- ResponseTypeMessage = 12
+ ResponseFinal ResponseType = 0
+ ResponseStream = 1
+ ResponseError = 2
+ ResponseServerRequest = 3
+ ResponseStreamClose = 4
+ ResponseDispatcherLookup = 5
+ ResponseAuthRequest = 6
+ ResponseCancel = 7
+ ResponseValidate = 8 // Request to validate caveats.
+ ResponseLog = 9 // Sends a message to be logged.
+ ResponseGranterRequest = 10
+ ResponseBlessingsCacheMessage = 11 // Update the blessings cache
+ ResponseTypeMessage = 12
)
type Response struct {
diff --git a/services/wspr/internal/principal/cache.go b/services/wspr/internal/principal/cache.go
new file mode 100644
index 0000000..f4be4d8
--- /dev/null
+++ b/services/wspr/internal/principal/cache.go
@@ -0,0 +1,144 @@
+// 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 principal
+
+import (
+ "reflect"
+ "sync"
+ "time"
+)
+
+// BlessingsCacheEntry is an entry in the blessing cache.
+type BlessingsCacheEntry struct {
+ refCount uint32 // Keep track of uses so JS knows when to clean up.
+ blessings *JsBlessings // For now. Switch to security.Blessings
+ dirty bool // True iff modified since last GC.
+}
+
+// BlessingsCache is a cache for blessings.
+// This cache is synced with a corresponding cache in Javascript with the goal
+// of reducing the number of times that blessings objects are sent in their
+// entirety.
+// BlessingsCache provides an id for a blessing after a Put() call that is
+// understood by Javascript.
+// After a new blessings cache is created, recently unused blessings will be
+// cleaned up periodically.
+type BlessingsCache struct {
+ lock sync.Mutex
+ nextId BlessingsId
+ entries map[BlessingsId]*BlessingsCacheEntry
+ notifier func([]BlessingsCacheMessage)
+ inactiveGc bool
+}
+
+func NewBlessingsCache(notifier func([]BlessingsCacheMessage), gcPolicy *BlessingsCacheGCPolicy) *BlessingsCache {
+ bc := &BlessingsCache{
+ entries: map[BlessingsId]*BlessingsCacheEntry{},
+ notifier: notifier,
+ }
+ go bc.gcLoop(gcPolicy)
+ return bc
+}
+
+// Put a blessing in the blessing cache and get an id for it that will
+// be understood by the Javascript cache.
+// If the blessings object is already in the cache, a new entry won't be created
+// and the id for the blessings from a previous put will be returned.
+func (bc *BlessingsCache) Put(blessings *JsBlessings) BlessingsId {
+ if blessings == nil {
+ return 0
+ }
+
+ bc.lock.Lock()
+ defer bc.lock.Unlock()
+
+ for id, entry := range bc.entries {
+ if reflect.DeepEqual(blessings, entry.blessings) {
+ entry.refCount++
+ entry.dirty = true
+ return id
+ }
+ }
+
+ bc.nextId++
+ id := bc.nextId
+ bc.entries[id] = &BlessingsCacheEntry{
+ refCount: 1,
+ blessings: blessings,
+ dirty: true,
+ }
+ addMessage := BlessingsCacheAddMessage{
+ CacheId: id,
+ Blessings: *blessings,
+ }
+ bc.notifier([]BlessingsCacheMessage{
+ BlessingsCacheMessageAdd{
+ Value: addMessage,
+ },
+ })
+ return id
+}
+
+// BlessingsCacheGCPolicy specifies when GC will occur and provides a function
+// to pass notifications of deletions (used to notify Javascript to delete
+// the cache items).
+type BlessingsCacheGCPolicy struct {
+ nextTrigger func() <-chan time.Time
+}
+
+// PeriodicGcPolicy periodically performs gc at the specified interval.
+func PeriodicGcPolicy(interval time.Duration) *BlessingsCacheGCPolicy {
+ return &BlessingsCacheGCPolicy{
+ nextTrigger: func() <-chan time.Time { return time.After(interval) },
+ }
+}
+
+// Stop stops the GC loop and frees up resources.
+func (bc *BlessingsCache) Stop() {
+ bc.lock.Lock()
+ bc.inactiveGc = true
+ bc.lock.Unlock()
+}
+
+func (bc *BlessingsCache) gcLoop(policy *BlessingsCacheGCPolicy) {
+ for {
+ bc.lock.Lock()
+ if bc.inactiveGc {
+ return
+ }
+ bc.lock.Unlock()
+ <-policy.nextTrigger()
+ bc.gc(policy)
+ }
+}
+
+// Perform Garbage Collection.
+// All blessings that weren't referenced since the last GC will be removed from
+// the cache.
+func (bc *BlessingsCache) gc(policy *BlessingsCacheGCPolicy) {
+ bc.lock.Lock()
+ defer bc.lock.Unlock()
+
+ var toDelete []BlessingsCacheMessage
+ for id, entry := range bc.entries {
+ if !entry.dirty {
+ deleteEntry := BlessingsCacheDeleteMessage{
+ CacheId: id,
+ DeleteAfter: entry.refCount,
+ }
+ toDelete = append(toDelete, BlessingsCacheMessageDelete{Value: deleteEntry})
+ } else {
+ entry.dirty = false
+ }
+ }
+
+ for _, deleteEntry := range toDelete {
+ delete(bc.entries, deleteEntry.(BlessingsCacheMessageDelete).Value.CacheId)
+ }
+
+ if len(toDelete) > 0 {
+ bc.notifier(toDelete)
+ }
+}
diff --git a/services/wspr/internal/principal/cache.vdl b/services/wspr/internal/principal/cache.vdl
new file mode 100644
index 0000000..ceabd3c
--- /dev/null
+++ b/services/wspr/internal/principal/cache.vdl
@@ -0,0 +1,28 @@
+// 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 principal
+
+// Identifier of a blessings cache entry.
+type BlessingsId uint32
+
+type BlessingsCacheAddMessage struct {
+ CacheId BlessingsId
+ Blessings JsBlessings
+}
+
+// Message from Blessings Cache GC to delete a cache entry in Javascript.
+type BlessingsCacheDeleteMessage struct {
+ CacheId BlessingsId
+
+ // Number of references expected. Javascript should wait until this number
+ // has been received before deleting the entry because up until that point
+ // messages with further references are expected.
+ DeleteAfter uint32
+}
+
+type BlessingsCacheMessage union {
+ Add BlessingsCacheAddMessage
+ Delete BlessingsCacheDeleteMessage
+}
diff --git a/services/wspr/internal/principal/cache.vdl.go b/services/wspr/internal/principal/cache.vdl.go
new file mode 100644
index 0000000..efcd507
--- /dev/null
+++ b/services/wspr/internal/principal/cache.vdl.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.
+
+// This file was auto-generated by the vanadium vdl tool.
+// Source: cache.vdl
+
+package principal
+
+import (
+ // VDL system imports
+ "v.io/v23/vdl"
+)
+
+// Identifier of a blessings cache entry.
+type BlessingsId uint32
+
+func (BlessingsId) __VDLReflect(struct {
+ Name string `vdl:"v.io/x/ref/services/wspr/internal/principal.BlessingsId"`
+}) {
+}
+
+type BlessingsCacheAddMessage struct {
+ CacheId BlessingsId
+ Blessings JsBlessings
+}
+
+func (BlessingsCacheAddMessage) __VDLReflect(struct {
+ Name string `vdl:"v.io/x/ref/services/wspr/internal/principal.BlessingsCacheAddMessage"`
+}) {
+}
+
+// Message from Blessings Cache GC to delete a cache entry in Javascript.
+type BlessingsCacheDeleteMessage struct {
+ CacheId BlessingsId
+ // Number of references expected. Javascript should wait until this number
+ // has been received before deleting the entry because up until that point
+ // messages with further references are expected.
+ DeleteAfter uint32
+}
+
+func (BlessingsCacheDeleteMessage) __VDLReflect(struct {
+ Name string `vdl:"v.io/x/ref/services/wspr/internal/principal.BlessingsCacheDeleteMessage"`
+}) {
+}
+
+type (
+ // BlessingsCacheMessage represents any single field of the BlessingsCacheMessage union type.
+ BlessingsCacheMessage interface {
+ // Index returns the field index.
+ Index() int
+ // Interface returns the field value as an interface.
+ Interface() interface{}
+ // Name returns the field name.
+ Name() string
+ // __VDLReflect describes the BlessingsCacheMessage union type.
+ __VDLReflect(__BlessingsCacheMessageReflect)
+ }
+ // BlessingsCacheMessageAdd represents field Add of the BlessingsCacheMessage union type.
+ BlessingsCacheMessageAdd struct{ Value BlessingsCacheAddMessage }
+ // BlessingsCacheMessageDelete represents field Delete of the BlessingsCacheMessage union type.
+ BlessingsCacheMessageDelete struct{ Value BlessingsCacheDeleteMessage }
+ // __BlessingsCacheMessageReflect describes the BlessingsCacheMessage union type.
+ __BlessingsCacheMessageReflect struct {
+ Name string `vdl:"v.io/x/ref/services/wspr/internal/principal.BlessingsCacheMessage"`
+ Type BlessingsCacheMessage
+ Union struct {
+ Add BlessingsCacheMessageAdd
+ Delete BlessingsCacheMessageDelete
+ }
+ }
+)
+
+func (x BlessingsCacheMessageAdd) Index() int { return 0 }
+func (x BlessingsCacheMessageAdd) Interface() interface{} { return x.Value }
+func (x BlessingsCacheMessageAdd) Name() string { return "Add" }
+func (x BlessingsCacheMessageAdd) __VDLReflect(__BlessingsCacheMessageReflect) {}
+
+func (x BlessingsCacheMessageDelete) Index() int { return 1 }
+func (x BlessingsCacheMessageDelete) Interface() interface{} { return x.Value }
+func (x BlessingsCacheMessageDelete) Name() string { return "Delete" }
+func (x BlessingsCacheMessageDelete) __VDLReflect(__BlessingsCacheMessageReflect) {}
+
+func init() {
+ vdl.Register((*BlessingsId)(nil))
+ vdl.Register((*BlessingsCacheAddMessage)(nil))
+ vdl.Register((*BlessingsCacheDeleteMessage)(nil))
+ vdl.Register((*BlessingsCacheMessage)(nil))
+}
diff --git a/services/wspr/internal/principal/cache_test.go b/services/wspr/internal/principal/cache_test.go
new file mode 100644
index 0000000..6aa222e
--- /dev/null
+++ b/services/wspr/internal/principal/cache_test.go
@@ -0,0 +1,236 @@
+// 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 principal
+
+import (
+ "reflect"
+ "sync"
+ "testing"
+ "time"
+)
+
+// manualTrigger provides a gc trigger that can be signaled manually
+type manualTrigger struct {
+ gcShouldBeNext bool
+ lock sync.Mutex
+ cond *sync.Cond
+ gcHasRun bool
+}
+
+func newManualTrigger() *manualTrigger {
+ mt := &manualTrigger{
+ gcShouldBeNext: true,
+ }
+ mt.cond = sync.NewCond(&mt.lock)
+ return mt
+}
+
+// policyTrigger is the trigger that should be provided in GC policy config.
+// It waits until it receives a signal and then returns a chan time.Time
+// that resolves immediately.
+func (mt *manualTrigger) waitForNextGc() <-chan time.Time {
+ mt.lock.Lock()
+ if !mt.gcHasRun {
+ mt.gcHasRun = true
+ } else {
+ mt.gcShouldBeNext = false // hand off control
+ mt.cond.Broadcast()
+ for !mt.gcShouldBeNext {
+ mt.cond.Wait()
+ }
+ }
+ mt.lock.Unlock()
+
+ trigger := make(chan time.Time, 1)
+ trigger <- time.Time{}
+ return trigger
+}
+
+// next should be called to trigger the next policy trigger event.
+func (mt *manualTrigger) next() {
+ mt.lock.Lock()
+ mt.gcShouldBeNext = true // hand off control
+ mt.cond.Broadcast()
+ for mt.gcShouldBeNext {
+ mt.cond.Wait()
+ }
+ mt.lock.Unlock()
+}
+
+// Test just to confirm it signals in order as expected.
+func TestManualTrigger(t *testing.T) {
+ mt := newManualTrigger()
+
+ countTriggers := 0
+ go func() {
+ for i := 1; i <= 100; i++ {
+ <-mt.waitForNextGc()
+ countTriggers++
+ }
+ }()
+
+ for i := 1; i <= 99; i++ {
+ mt.next()
+ if countTriggers != i {
+ t.Errorf("Expected %d triggers, got %d", i, countTriggers)
+ }
+ }
+}
+
+func TestBlessingsCache(t *testing.T) {
+ notificationCh := make(chan []BlessingsCacheMessage, 1)
+ notifier := func(msg []BlessingsCacheMessage) {
+ notificationCh <- msg
+ }
+
+ mt := newManualTrigger()
+
+ // Create a BlessingsCache with a GC policy that we can trigger on demand.
+ onDemandGCPolicy := &BlessingsCacheGCPolicy{
+ nextTrigger: mt.waitForNextGc,
+ }
+ bc := NewBlessingsCache(notifier, onDemandGCPolicy)
+
+ // Blessings for the tests.
+ jsBlessA := &JsBlessings{
+ Handle: 1,
+ PublicKey: "A",
+ }
+ jsBlessB := &JsBlessings{
+ Handle: 2,
+ PublicKey: "B",
+ }
+ jsBlessC := &JsBlessings{
+ Handle: 4,
+ PublicKey: "C",
+ }
+
+ // First do puts and make sure the ids are reasonable.
+ idA := bc.Put(jsBlessA)
+ expectAddMessage(t, notificationCh, 1, jsBlessA)
+ idB := bc.Put(jsBlessB)
+ expectAddMessage(t, notificationCh, 2, jsBlessB)
+ if idA == idB {
+ t.Errorf("A and B unexpectedly had same id: %v", idA)
+ }
+
+ idA2 := bc.Put(jsBlessA)
+ expectNoMessage(t, notificationCh)
+ if idA2 != idA {
+ t.Errorf("A and A2 expected to have same id, but they were %v and %v",
+ idA, idA2)
+ }
+
+ // Now perform GC. Check that the values are still in the cache.
+ mt.next()
+ expectNoMessage(t, notificationCh)
+
+ idGc1A := bc.Put(jsBlessA)
+ idGc1B := bc.Put(jsBlessB)
+ expectNoMessage(t, notificationCh)
+ if idA != idGc1A {
+ t.Errorf("Expected to get same id after one gc of A, but got %v and %v",
+ idA, idGc1A)
+ }
+ if idB != idGc1B {
+ t.Errorf("Expected to get same id after one gc of B, but got %v and %v",
+ idB, idGc1B)
+ }
+
+ // Now perform GC to clear the dirty bits.
+ mt.next()
+ expectNoMessage(t, notificationCh)
+
+ // Update B and add C.
+ idGc2B := bc.Put(jsBlessB)
+ expectNoMessage(t, notificationCh)
+ if idB != idGc2B {
+ t.Errorf("Expected to get same id after two gcs of B, but got %v and %v",
+ idB, idGc2B)
+ }
+ idC := bc.Put(jsBlessC)
+ expectAddMessage(t, notificationCh, 3, jsBlessC)
+ if idC == idA || idC == idB {
+ t.Error("C was unexpectedly the same as A or B")
+ }
+
+ // Perform GC. A should be removed but B and C should stay.
+ mt.next()
+ expectDeleteMessage(t, notificationCh, BlessingsCacheDeleteMessage{CacheId: 1, DeleteAfter: 3})
+ if idB != bc.Put(jsBlessB) {
+ t.Errorf("B seems to have been cleaned up as it was given a new id")
+ }
+ if idC != bc.Put(jsBlessC) {
+ t.Errorf("C seems to have been cleaned up as it was given a new id")
+ }
+ expectNoMessage(t, notificationCh)
+
+ // Perform GC twice to remove the other items.
+ mt.next()
+ expectNoMessage(t, notificationCh)
+ mt.next()
+ expectDeleteMessage(t, notificationCh,
+ BlessingsCacheDeleteMessage{CacheId: 2, DeleteAfter: 4},
+ BlessingsCacheDeleteMessage{CacheId: 3, DeleteAfter: 2})
+
+ // No notifications should occur on further GCs.
+ mt.next()
+ mt.next()
+ mt.next()
+ // Note that this should only be reached after the second GC is done because
+ // the GC trigger channel has size 1.
+ expectNoMessage(t, notificationCh)
+
+ bc.Stop()
+}
+
+func expectNoMessage(t *testing.T, notificationCh chan []BlessingsCacheMessage) {
+ select {
+ case <-notificationCh:
+ t.Errorf("Got message when none expected")
+ default:
+ }
+}
+
+func expectAddMessage(t *testing.T, notificationCh chan []BlessingsCacheMessage, id BlessingsId, bless *JsBlessings) {
+ select {
+ case notifications := <-notificationCh:
+ if len(notifications) != 1 {
+ t.Fatalf("Got invalid add message with %d messages", len(notifications))
+ }
+ addMsg := notifications[0].(BlessingsCacheMessageAdd).Value
+ if got, want := addMsg.CacheId, id; got != want {
+ t.Errorf("Unexpected id in add message: %v. Wanted: %v", got, want)
+ }
+ if got, want := addMsg.Blessings, *bless; !reflect.DeepEqual(got, want) {
+ t.Errorf("Blessings unexpectedly not equal. Got %v, want %v", got, want)
+ }
+ case <-time.After(10 * time.Second):
+ t.Fatalf("Timed out waiting for notification")
+ }
+}
+
+func expectDeleteMessage(t *testing.T, notificationCh chan []BlessingsCacheMessage, expected ...BlessingsCacheDeleteMessage) {
+ select {
+ case notifications := <-notificationCh:
+ if len(notifications) != len(expected) {
+ t.Fatalf("Got %d notifications but expected %d delete notifications", len(notifications), len(expected))
+ }
+ for _, notification := range notifications {
+ delNotif := notification.(BlessingsCacheMessageDelete).Value
+ var foundMatch bool
+ for _, expectedNotif := range expected {
+ if reflect.DeepEqual(delNotif, expectedNotif) {
+ foundMatch = true
+ }
+ }
+ if !foundMatch {
+ t.Errorf("Unexpected delete notification: %v", delNotif)
+ }
+ }
+ case <-time.After(10 * time.Second):
+ t.Fatalf("Timed out waiting for notification")
+ }
+}
diff --git a/services/wspr/internal/rpc/server/server.go b/services/wspr/internal/rpc/server/server.go
index c709731..e3cd66e 100644
--- a/services/wspr/internal/rpc/server/server.go
+++ b/services/wspr/internal/rpc/server/server.go
@@ -21,6 +21,7 @@
"v.io/v23/vdlroot/signature"
vdltime "v.io/v23/vdlroot/time"
"v.io/v23/verror"
+ "v.io/v23/vom"
"v.io/v23/vtrace"
"v.io/x/lib/vlog"
"v.io/x/ref/services/wspr/internal/lib"
@@ -49,6 +50,9 @@
HandleStore
SendLogMessage(level lib.LogLevel, msg string) error
+ BlessingsCache() *principal.BlessingsCache
+
+ TypeEncoder() *vom.TypeEncoder
Context() *context.T
}
@@ -143,9 +147,10 @@
return replyChan
}
- var grantedBlessings *principal.JsBlessings
+ var grantedBlessings principal.BlessingsId
if !call.GrantedBlessings().IsZero() {
- grantedBlessings = convertBlessingsToHandle(s.helper, call.GrantedBlessings())
+ grantedBlessings = s.helper.BlessingsCache().Put(
+ convertBlessingsToHandle(s.helper, call.GrantedBlessings()))
}
rpcCall := ServerRpcRequestCall{
@@ -161,7 +166,8 @@
var vdlValArgs []*vdl.Value = make([]*vdl.Value, len(args))
for i, arg := range args {
if blessings, ok := arg.(security.Blessings); ok {
- arg = principal.ConvertBlessingsToHandle(blessings, s.helper.GetOrAddBlessingsHandle(blessings))
+ jsBless := principal.ConvertBlessingsToHandle(blessings, s.helper.GetOrAddBlessingsHandle(blessings))
+ arg = s.helper.BlessingsCache().Put(jsBless)
}
vdlValArgs[i] = vdl.ValueOf(arg)
}
@@ -200,7 +206,7 @@
ch <- &lib.ServerRpcReply{nil, &err, vtrace.Response{}}
}()
- go proxyStream(call, flow.Writer, s.helper)
+ go proxyStream(call, flow.Writer, s.helper, s.helper.TypeEncoder())
return replyChan
}
@@ -269,7 +275,7 @@
rpcCall := ServerRpcRequestCall{
SecurityCall: securityCall,
Deadline: timeout,
- GrantedBlessings: grantedBlessings,
+ GrantedBlessings: s.helper.BlessingsCache().Put(grantedBlessings),
Context: Context{
Language: string(i18n.GetLangID(ctx)),
},
@@ -313,14 +319,15 @@
}
}
-func proxyStream(stream rpc.Stream, w lib.ClientWriter, blessingsCache HandleStore) {
+func proxyStream(stream rpc.Stream, w lib.ClientWriter, blessingsCache HandleStore, typeEncoder *vom.TypeEncoder) {
var item interface{}
- for err := stream.Recv(&item); err == nil; err = stream.Recv(&item) {
+ var err error
+ for err = stream.Recv(&item); err == nil; err = stream.Recv(&item) {
if blessings, ok := item.(security.Blessings); ok {
item = principal.ConvertBlessingsToHandle(blessings, blessingsCache.GetOrAddBlessingsHandle(blessings))
}
- vomItem, err := lib.HexVomEncode(item, nil)
+ vomItem, err := lib.HexVomEncode(item, typeEncoder)
if err != nil {
w.Error(verror.Convert(verror.ErrInternal, nil, err))
return
@@ -330,6 +337,8 @@
return
}
}
+ vlog.Log.Errorf("Error reading from stream: %v\n", err)
+
if err := w.Send(lib.ResponseStreamClose, nil); err != nil {
w.Error(verror.Convert(verror.ErrInternal, nil, err))
return
@@ -508,14 +517,15 @@
for i, mtag := range call.MethodTags() {
anymtags[i] = mtag
}
+ remoteBlessings := *convertBlessingsToHandle(helper, call.RemoteBlessings())
secCall := SecurityCall{
Method: lib.LowercaseFirstCharacter(call.Method()),
Suffix: call.Suffix(),
MethodTags: anymtags,
LocalEndpoint: localEndpoint,
RemoteEndpoint: remoteEndpoint,
- LocalBlessings: localBlessings,
- RemoteBlessings: *convertBlessingsToHandle(helper, call.RemoteBlessings()),
+ LocalBlessings: helper.BlessingsCache().Put(&localBlessings),
+ RemoteBlessings: helper.BlessingsCache().Put(&remoteBlessings),
}
if includeBlessingStrings {
secCall.LocalBlessingStrings = security.LocalBlessingNames(ctx, call)
@@ -768,6 +778,7 @@
s.dispatcher.Cleanup()
}
+ s.outstandingRequestLock.Lock()
for _, ch := range s.outstandingAuthRequests {
ch <- fmt.Errorf("Cleaning up server")
}
@@ -778,7 +789,6 @@
default:
}
}
- s.outstandingRequestLock.Lock()
s.outstandingAuthRequests = make(map[int32]chan error)
s.outstandingServerRequests = make(map[int32]chan *lib.ServerRpcReply)
s.outstandingRequestLock.Unlock()
diff --git a/services/wspr/internal/rpc/server/server.vdl b/services/wspr/internal/rpc/server/server.vdl
index 790960c..0ab325e 100644
--- a/services/wspr/internal/rpc/server/server.vdl
+++ b/services/wspr/internal/rpc/server/server.vdl
@@ -21,9 +21,9 @@
Method string
Suffix string
MethodTags []any
- LocalBlessings principal.JsBlessings
+ LocalBlessings principal.BlessingsId
LocalBlessingStrings []string
- RemoteBlessings principal.JsBlessings
+ RemoteBlessings principal.BlessingsId
RemoteBlessingStrings []string
LocalEndpoint string
RemoteEndpoint string
@@ -50,7 +50,7 @@
Deadline time.WireDeadline
Context Context
TraceRequest vtrace.Request
- GrantedBlessings ?principal.JsBlessings
+ GrantedBlessings principal.BlessingsId
}
// A request from the proxy to javascript to handle an RPC
diff --git a/services/wspr/internal/rpc/server/server.vdl.go b/services/wspr/internal/rpc/server/server.vdl.go
index 6a18704..76bbb0f 100644
--- a/services/wspr/internal/rpc/server/server.vdl.go
+++ b/services/wspr/internal/rpc/server/server.vdl.go
@@ -35,9 +35,9 @@
Method string
Suffix string
MethodTags []*vdl.Value
- LocalBlessings principal.JsBlessings
+ LocalBlessings principal.BlessingsId
LocalBlessingStrings []string
- RemoteBlessings principal.JsBlessings
+ RemoteBlessings principal.BlessingsId
RemoteBlessingStrings []string
LocalEndpoint string
RemoteEndpoint string
@@ -73,7 +73,7 @@
Deadline time.Deadline
Context Context
TraceRequest vtrace.Request
- GrantedBlessings *principal.JsBlessings
+ GrantedBlessings principal.BlessingsId
}
func (ServerRpcRequestCall) __VDLReflect(struct {
diff --git a/services/wspr/wsprlib/pipe.go b/services/wspr/wsprlib/pipe.go
index 2fa9aaf..c8fe142 100644
--- a/services/wspr/wsprlib/pipe.go
+++ b/services/wspr/wsprlib/pipe.go
@@ -9,7 +9,6 @@
"fmt"
"io"
"net/http"
- _ "net/http/pprof"
"time"
"v.io/v23"
diff --git a/services/wspr/wsprlib/wspr.go b/services/wspr/wsprlib/wspr.go
index d30e5f4..0544575 100644
--- a/services/wspr/wsprlib/wspr.go
+++ b/services/wspr/wsprlib/wspr.go
@@ -14,7 +14,6 @@
"io"
"net"
"net/http"
- _ "net/http/pprof"
"sync"
"time"
@@ -89,7 +88,6 @@
// Starts serving http requests. This method is blocking.
func (wspr *WSPR) Serve() {
// Configure HTTP routes.
- http.HandleFunc("/debug", wspr.handleDebug)
http.HandleFunc("/ws", wspr.handleWS)
// Everything else is a 404.
// Note: the pattern "/" matches all paths not matched by other registered
@@ -146,24 +144,6 @@
// HTTP Handlers
-func (wspr *WSPR) handleDebug(w http.ResponseWriter, r *http.Request) {
- if r.Method != "GET" {
- w.WriteHeader(http.StatusMethodNotAllowed)
- fmt.Fprintf(w, "")
- return
- }
- w.Header().Set("Content-Type", "text/html")
- w.Write([]byte(`<html>
-<head>
-<title>/debug</title>
-</head>
-<body>
-<ul>
-<li><a href="/debug/pprof">/debug/pprof</a></li>
-</li></ul></body></html>
-`))
-}
-
func (wspr *WSPR) handleWS(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
http.Error(w, "Method not allowed.", http.StatusMethodNotAllowed)
diff --git a/test/doc.go b/test/doc.go
index cb84f2b..206164e 100644
--- a/test/doc.go
+++ b/test/doc.go
@@ -14,11 +14,10 @@
// os.Exit(m.Run())
// }
//
-// InitForTest can be used within test functions as a safe alternative
-// to v23.Init.
+// V23Init can be used within test functions as a safe alternative to v23.Init.
//
// func TestFoo(t *testing.T) {
-// ctx, shutdown := test.InitForTest()
+// ctx, shutdown := test.V23Init()
// defer shutdown()
// ...
// }
diff --git a/test/hello/v23_test.go b/test/hello/v23_test.go
index 515e1cd..6364cfb 100644
--- a/test/hello/v23_test.go
+++ b/test/hello/v23_test.go
@@ -4,16 +4,21 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package hello_test
-import "testing"
-import "os"
+import (
+ "os"
+ "testing"
-import "v.io/x/ref/test"
-import "v.io/x/ref/test/v23tests"
+ "v.io/x/ref/test"
+ "v.io/x/ref/test/modules"
+ "v.io/x/ref/test/v23tests"
+)
func TestMain(m *testing.M) {
test.Init()
+ modules.DispatchAndExitIfChild()
cleanup := v23tests.UseSharedBinDir()
r := m.Run()
cleanup()
diff --git a/test/init.go b/test/init.go
index f01b1df..395cab7 100644
--- a/test/init.go
+++ b/test/init.go
@@ -63,11 +63,11 @@
once.Do(init)
}
-// InitForTest initializes a new context.T and sets a freshly created principal
+// V23Init initializes a new context.T and sets a freshly created principal
// (with a single self-signed blessing) on it. The principal setting step is
// skipped if this function is invoked from a process run using the modules
// package.
-func InitForTest() (*context.T, v23.Shutdown) {
+func V23Init() (*context.T, v23.Shutdown) {
ctx, shutdown := v23.Init()
if len(os.Getenv("V23_SHELL_HELPER_PROCESS_ENTRY_POINT")) != 0 {
return ctx, shutdown
diff --git a/test/modules/examples_test.go b/test/modules/examples_test.go
index 8b3113b..18d05a4 100644
--- a/test/modules/examples_test.go
+++ b/test/modules/examples_test.go
@@ -6,52 +6,48 @@
import (
"fmt"
- "io"
"os"
"v.io/x/ref/test"
"v.io/x/ref/test/modules"
)
-func init() {
- modules.RegisterChild("echo", "<args>...", echo)
-}
-
-func echo(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var Echo = modules.Register(func(env *modules.Env, args ...string) error {
for i, a := range args {
- fmt.Fprintf(stdout, "%d: %s\n", i, a)
+ fmt.Fprintf(env.Stdout, "%d: %s\n", i, a)
}
return nil
-}
+}, "echo")
func ExampleDispatch() {
- ctx, shutdown := test.InitForTest()
- defer shutdown()
- if modules.IsModulesChildProcess() {
- // Child process. Dispatch will invoke the 'echo' command
+ if modules.IsChildProcess() {
+ // Child process dispatches to the echo program.
if err := modules.Dispatch(); err != nil {
- panic(fmt.Sprintf("unexpected error: %s", err))
+ panic(err)
}
return
}
- // Parent process.
+ // Parent process spawns the echo program.
+ ctx, shutdown := test.V23Init()
+ defer shutdown()
sh, _ := modules.NewShell(ctx, nil, false, nil)
defer sh.Cleanup(nil, nil)
- h, _ := sh.Start("echo", nil, "a", "b")
+ h, _ := sh.Start(nil, Echo, "a", "b")
h.Shutdown(os.Stdout, os.Stderr)
// Output:
// 0: a
// 1: b
}
-func ExampleDispatchAndExit() {
- ctx, shutdown := test.InitForTest()
+func ExampleDispatchAndExitIfChild() {
+ // Child process dispatches to the echo program.
+ modules.DispatchAndExitIfChild()
+ // Parent process spawns the echo program.
+ ctx, shutdown := test.V23Init()
defer shutdown()
- // DispatchAndExit will call os.Exit(0) when executed within the child.
- modules.DispatchAndExit()
sh, _ := modules.NewShell(ctx, nil, false, nil)
defer sh.Cleanup(nil, nil)
- h, _ := sh.Start("echo", nil, "c", "d")
+ h, _ := sh.Start(nil, Echo, "c", "d")
h.Shutdown(os.Stdout, os.Stderr)
// Output:
// 0: c
diff --git a/test/modules/exec.go b/test/modules/exec.go
index 63e0b94..c85a2c9 100644
--- a/test/modules/exec.go
+++ b/test/modules/exec.go
@@ -21,20 +21,21 @@
"v.io/x/ref/test/expect"
)
-// execHandle implements both the command and Handle interfaces.
+// execHandle implements both the Handle interface.
type execHandle struct {
*expect.Session
- mu sync.Mutex
- cmd *exec.Cmd
- name string
- handle *vexec.ParentHandle
- sh *Shell
- stderr *os.File
- stdout io.ReadCloser
- stdin io.WriteCloser
- procErrCh chan error
- opts *StartOpts
- external bool
+ mu sync.Mutex
+ cmd *exec.Cmd
+ entryPoint string
+ desc string
+ handle *vexec.ParentHandle
+ sh *Shell
+ stderr *os.File
+ stdout io.ReadCloser
+ stdin io.WriteCloser
+ procErrCh chan error
+ opts *StartOpts
+ external bool
}
func testFlags() []string {
@@ -51,7 +52,7 @@
// must be a go test binary
val := timeout.Value.(flag.Getter).Get().(time.Duration)
if val.String() != timeout.DefValue {
- // use supplied command value for subprocesses
+ // use supplied value for subprocesses
fl = append(fl, "--test.timeout="+timeout.Value.String())
} else {
// translate default value into 3m for subproccesses. The
@@ -62,12 +63,12 @@
return fl
}
-func newExecHandle(name string) *execHandle {
- return &execHandle{name: name, procErrCh: make(chan error, 1)}
+func newExecHandle(entry, desc string) *execHandle {
+ return &execHandle{entryPoint: entry, desc: desc, procErrCh: make(chan error, 1)}
}
-func newExecHandleForExternalCommand(name string) *execHandle {
- return &execHandle{name: name, procErrCh: make(chan error, 1), external: true}
+func newExecHandleExternal(prog string) *execHandle {
+ return &execHandle{entryPoint: prog, desc: prog, procErrCh: make(chan error, 1), external: true}
}
func (eh *execHandle) Stdout() io.Reader {
@@ -96,7 +97,7 @@
func (eh *execHandle) envelope(sh *Shell, env []string, args []string) ([]string, []string) {
if eh.external {
- newargs := append([]string{eh.name}, args...)
+ newargs := append([]string{eh.entryPoint}, args...)
newenv := envvar.SliceToMap(env)
delete(newenv, shellEntryPoint)
return newargs, envvar.MapToSlice(newenv)
@@ -104,7 +105,7 @@
newargs := append([]string{os.Args[0]}, testFlags()...)
newargs = append(newargs, args...)
newenv := envvar.SliceToMap(env)
- newenv[shellEntryPoint] = eh.name
+ newenv[shellEntryPoint] = eh.entryPoint
return newargs, envvar.MapToSlice(newenv)
}
@@ -117,7 +118,7 @@
cmd := exec.Command(args[0], args[1:]...)
cmd.Env = env
- stderr, err := newLogfile("stderr", eh.name)
+ stderr, err := newLogfile("stderr", eh.entryPoint)
if err != nil {
return nil, err
}
@@ -163,7 +164,7 @@
execOpts = append(execOpts, vexec.ConfigOpt{Config: config})
}
- // TODO(cnicolaou): for external commands, vexec should either not be
+ // TODO(cnicolaou): for external programs, vexec should either not be
// used or it should taken an option to not use its protocol, and in
// particular to share secrets with children.
handle := vexec.NewParentHandle(cmd, execOpts...)
@@ -171,9 +172,9 @@
eh.stderr = stderr
eh.handle = handle
eh.cmd = cmd
- vlog.VI(1).Infof("Start: %q stderr: %s", eh.name, stderr.Name())
- vlog.VI(1).Infof("Start: %q args: %v", eh.name, cmd.Args)
- vlog.VI(2).Infof("Start: %q env: %v", eh.name, cmd.Env)
+ vlog.VI(1).Infof("Start: %q stderr: %s", eh.desc, stderr.Name())
+ vlog.VI(1).Infof("Start: %q args: %v", eh.desc, cmd.Args)
+ vlog.VI(2).Infof("Start: %q env: %v", eh.desc, cmd.Env)
if err := handle.Start(); err != nil {
// The child process failed to start, either because of some setup
// error (e.g. creating pipes for it to use), or a bad binary etc.
@@ -194,7 +195,7 @@
return eh, err
}
}
- vlog.VI(1).Infof("Started: %q, pid %d", eh.name, cmd.Process.Pid)
+ vlog.VI(1).Infof("Started: %q, pid %d", eh.desc, cmd.Process.Pid)
go func() {
eh.procErrCh <- eh.handle.Wait(0)
// It's now safe to close eh.stdout, since Wait only returns
@@ -215,8 +216,8 @@
func (eh *execHandle) Shutdown(stdout, stderr io.Writer) error {
eh.mu.Lock()
defer eh.mu.Unlock()
- vlog.VI(1).Infof("Shutdown: %q", eh.name)
- defer vlog.VI(1).Infof("Shutdown: %q [DONE]", eh.name)
+ vlog.VI(1).Infof("Shutdown: %q", eh.desc)
+ defer vlog.VI(1).Infof("Shutdown: %q [DONE]", eh.desc)
if eh.stdin != nil {
eh.stdin.Close()
}
diff --git a/test/modules/modules_test.go b/test/modules/modules_test.go
index b0ce9e4..117b4e4 100644
--- a/test/modules/modules_test.go
+++ b/test/modules/modules_test.go
@@ -32,98 +32,85 @@
_ "v.io/x/ref/runtime/factories/generic"
)
-func init() {
- modules.RegisterChild("envtest", "envtest: <variables to print>...", PrintFromEnv)
- modules.RegisterChild("printenv", "printenv", PrintEnv)
- modules.RegisterChild("printblessing", "printblessing", PrintBlessing)
- modules.RegisterChild("echos", "[args]*", Echo)
- modules.RegisterChild("errortestChild", "", ErrorMain)
- modules.RegisterChild("ignores_stdin", "", ignoresStdin)
- modules.RegisterChild("pipeEcho", "", pipeEcho)
- modules.RegisterChild("lifo", "", lifo)
-}
-
-// We must call Testmain ourselves because using v23 test generate
+// We must call TestMain ourselves because using v23 test generate
// creates an import cycle for this package.
func TestMain(m *testing.M) {
test.Init()
- if modules.IsModulesChildProcess() {
- if err := modules.Dispatch(); err != nil {
- fmt.Fprintf(os.Stderr, "modules.Dispatch failed: %v\n", err)
- os.Exit(1)
- }
- return
- }
+ modules.DispatchAndExitIfChild()
os.Exit(m.Run())
}
-func ignoresStdin(io.Reader, io.Writer, io.Writer, map[string]string, ...string) error {
+var ignoreStdin = modules.Register(func(*modules.Env, ...string) error {
<-time.After(time.Minute)
return nil
-}
+}, "ignoreStdin")
-func Echo(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var echo = modules.Register(func(env *modules.Env, args ...string) error {
for _, a := range args {
- fmt.Fprintf(stdout, "stdout: %s\n", a)
- fmt.Fprintf(stderr, "stderr: %s\n", a)
+ fmt.Fprintf(env.Stdout, "stdout: %s\n", a)
+ fmt.Fprintf(env.Stderr, "stderr: %s\n", a)
}
return nil
-}
+}, "Echo")
-func pipeEcho(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- scanner := bufio.NewScanner(stdin)
+var pipeEcho = modules.Register(pipeEchoFunc, "pipeEcho")
+
+func pipeEchoFunc(env *modules.Env, args ...string) error {
+ scanner := bufio.NewScanner(env.Stdin)
for scanner.Scan() {
- fmt.Fprintf(stdout, "%p: %s\n", pipeEcho, scanner.Text())
+ fmt.Fprintf(env.Stdout, "%p: %s\n", pipeEchoFunc, scanner.Text())
}
return nil
}
-func lifo(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- scanner := bufio.NewScanner(stdin)
+var lifo = modules.Register(lifoFunc, "lifo")
+
+func lifoFunc(env *modules.Env, args ...string) error {
+ scanner := bufio.NewScanner(env.Stdin)
scanner.Scan()
msg := scanner.Text()
- modules.WaitForEOF(stdin)
- fmt.Fprintf(stdout, "%p: %s\n", lifo, msg)
+ modules.WaitForEOF(env.Stdin)
+ fmt.Fprintf(env.Stdout, "%p: %s\n", lifoFunc, msg)
return nil
}
-func PrintBlessing(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
- ctx, shutdown := test.InitForTest()
+var printBlessing = modules.Register(func(env *modules.Env, args ...string) error {
+ ctx, shutdown := test.V23Init()
defer shutdown()
blessing := v23.GetPrincipal(ctx).BlessingStore().Default()
- fmt.Fprintf(stdout, "%s", blessing)
+ fmt.Fprintf(env.Stdout, "%s", blessing)
return nil
-}
+}, "printBlessing")
-func PrintFromEnv(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var envTest = modules.Register(func(env *modules.Env, args ...string) error {
for _, a := range args {
- if v := env[a]; len(v) > 0 {
- fmt.Fprintf(stdout, "%s\n", a+"="+v)
+ if v := env.Vars[a]; len(v) > 0 {
+ fmt.Fprintf(env.Stdout, "%s\n", a+"="+v)
} else {
- fmt.Fprintf(stderr, "missing %s\n", a)
+ fmt.Fprintf(env.Stderr, "missing %s\n", a)
}
}
- modules.WaitForEOF(stdin)
- fmt.Fprintf(stdout, "done\n")
+ modules.WaitForEOF(env.Stdin)
+ fmt.Fprintf(env.Stdout, "done\n")
return nil
-}
+}, "envTest")
const printEnvArgPrefix = "PRINTENV_ARG="
-func PrintEnv(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var printEnv = modules.Register(func(env *modules.Env, args ...string) error {
for _, a := range args {
- fmt.Fprintf(stdout, "%s%s\n", printEnvArgPrefix, a)
+ fmt.Fprintf(env.Stdout, "%s%s\n", printEnvArgPrefix, a)
}
- for k, v := range env {
- fmt.Fprintf(stdout, "%q\n", k+"="+v)
+ for k, v := range env.Vars {
+ fmt.Fprintf(env.Stdout, "%q\n", k+"="+v)
}
return nil
-}
+}, "printEnv")
-func ErrorMain(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var errorMain = modules.Register(func(env *modules.Env, args ...string) error {
return fmt.Errorf("an error")
-}
+}, "errorMain")
func waitForInput(scanner *bufio.Scanner) bool {
ch := make(chan struct{})
@@ -139,8 +126,8 @@
}
}
-func testCommand(t *testing.T, sh *modules.Shell, name, key, val string) {
- h, err := sh.Start(name, nil, key)
+func testProgram(t *testing.T, sh *modules.Shell, prog modules.Program, key, val string) {
+ h, err := sh.Start(nil, prog, key)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -180,7 +167,7 @@
}
func getBlessing(t *testing.T, sh *modules.Shell, env ...string) string {
- h, err := sh.Start("printblessing", env)
+ h, err := sh.Start(env, printBlessing)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -193,7 +180,7 @@
}
func getCustomBlessing(t *testing.T, sh *modules.Shell, creds *modules.CustomCredentials) string {
- h, err := sh.StartWithOpts(sh.DefaultStartOpts().WithCustomCredentials(creds), nil, "printblessing")
+ h, err := sh.StartWithOpts(sh.DefaultStartOpts().WithCustomCredentials(creds), nil, printBlessing)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -206,7 +193,7 @@
}
func TestChild(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
@@ -216,11 +203,11 @@
defer sh.Cleanup(nil, nil)
key, val := "simpleVar", "foo & bar"
sh.SetVar(key, val)
- testCommand(t, sh, "envtest", key, val)
+ testProgram(t, sh, envTest, key, val)
}
func TestAgent(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
@@ -236,7 +223,7 @@
}
func TestCustomPrincipal(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
p, err := vsecurity.NewPrincipal()
@@ -266,7 +253,7 @@
}
func TestCustomCredentials(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
root := testutil.NewIDProvider("myshell")
@@ -357,7 +344,7 @@
}
func TestChildNoRegistration(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
@@ -367,8 +354,8 @@
defer sh.Cleanup(os.Stderr, os.Stderr)
key, val := "simpleVar", "foo & bar"
sh.SetVar(key, val)
- testCommand(t, sh, "envtest", key, val)
- _, err = sh.Start("non-existent-command", nil, "random", "args")
+ testProgram(t, sh, envTest, key, val)
+ _, err = sh.Start(nil, modules.Program("non-existent-program"), "random", "args")
if err == nil {
fmt.Fprintf(os.Stderr, "Failed: %v\n", err)
t.Fatalf("expected error")
@@ -376,7 +363,7 @@
}
func TestErrorChild(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
@@ -384,7 +371,7 @@
t.Fatalf("unexpected error: %s", err)
}
defer sh.Cleanup(nil, nil)
- h, err := sh.Start("errortestChild", nil)
+ h, err := sh.Start(nil, errorMain)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -393,10 +380,10 @@
}
}
-func testShutdown(t *testing.T, sh *modules.Shell, command string, isfunc bool) {
+func testShutdown(t *testing.T, sh *modules.Shell, prog modules.Program) {
result := ""
args := []string{"a", "b c", "ddd"}
- if _, err := sh.Start(command, nil, args...); err != nil {
+ if _, err := sh.Start(nil, prog, args...); err != nil {
t.Fatalf("unexpected error: %s", err)
}
var stdoutBuf bytes.Buffer
@@ -410,16 +397,14 @@
if got, want := stdoutBuf.String(), stdoutOutput+result; got != want {
t.Errorf("got %q want %q", got, want)
}
- if !isfunc {
- stderrBuf.ReadString('\n') // Skip past the random # generator output
- }
+ stderrBuf.ReadString('\n') // Skip past the random # generator output
if got, want := stderrBuf.String(), stderrOutput; got != want {
t.Errorf("got %q want %q", got, want)
}
}
func TestShutdownSubprocess(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
sh, err := modules.NewShell(ctx, nil, false, t)
@@ -427,14 +412,14 @@
t.Fatalf("unexpected error: %s", err)
}
defer sh.Cleanup(nil, nil)
- testShutdown(t, sh, "echos", false)
+ testShutdown(t, sh, echo)
}
-// TestShutdownSubprocessIgnoresStdin verifies that Shutdown doesn't wait
+// TestShutdownSubprocessIgnoreStdin verifies that Shutdown doesn't wait
// forever if a child does not die upon closing stdin; but instead times out and
// returns an appropriate error.
-func TestShutdownSubprocessIgnoresStdin(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+func TestShutdownSubprocessIgnoreStdin(t *testing.T) {
+ ctx, shutdown := test.V23Init()
defer shutdown()
sh, err := modules.NewShell(ctx, nil, false, t)
@@ -443,7 +428,7 @@
}
opts := sh.DefaultStartOpts()
opts.ShutdownTimeout = time.Second
- h, err := sh.StartWithOpts(opts, nil, "ignores_stdin")
+ h, err := sh.StartWithOpts(opts, nil, ignoreStdin)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -463,7 +448,7 @@
// implementation inappropriately sets stdout to the file that is to be closed
// in Wait.
func TestStdoutRace(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
@@ -472,7 +457,7 @@
}
opts := sh.DefaultStartOpts()
opts.ShutdownTimeout = time.Second
- h, err := sh.StartWithOpts(opts, nil, "ignores_stdin")
+ h, err := sh.StartWithOpts(opts, nil, ignoreStdin)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -508,7 +493,7 @@
}
func TestEnvelope(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
@@ -519,7 +504,7 @@
sh.SetVar("a", "1")
sh.SetVar("b", "2")
args := []string{"oh", "ah"}
- h, err := sh.Start("printenv", nil, args...)
+ h, err := sh.Start(nil, printEnv, args...)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -533,7 +518,7 @@
childEnv = append(childEnv, o)
}
}
- shArgs, shEnv := sh.CommandEnvelope("printenv", nil, args...)
+ shArgs, shEnv := sh.ProgramEnvelope(nil, printEnv, args...)
for i, ev := range shEnv {
shEnv[i] = fmt.Sprintf("%q", ev)
}
@@ -563,7 +548,7 @@
}
func TestEnvMerge(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
@@ -575,7 +560,7 @@
os.Setenv("a", "wrong, should be 1")
sh.SetVar("b", "2 also wrong")
os.Setenv("b", "wrong, should be 2")
- h, err := sh.Start("printenv", []string{"b=2"})
+ h, err := sh.Start([]string{"b=2"}, printEnv)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -596,7 +581,7 @@
}
func TestNoExec(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
@@ -604,7 +589,7 @@
t.Fatalf("unexpected error: %s", err)
}
defer sh.Cleanup(nil, nil)
- h, err := sh.StartWithOpts(sh.DefaultStartOpts().NoExecCommand(), nil, "/bin/echo", "hello", "world")
+ h, err := sh.StartWithOpts(sh.DefaultStartOpts().NoExecProgram(), nil, modules.Program("/bin/echo"), "hello", "world")
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -616,7 +601,7 @@
}
func TestExternal(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
@@ -626,7 +611,7 @@
defer sh.Cleanup(nil, nil)
cookie := strconv.Itoa(rand.Int())
sh.SetConfigKey("cookie", cookie)
- h, err := sh.StartWithOpts(sh.DefaultStartOpts().ExternalCommand(), nil, os.Args[0], "--test.run=TestExternalTestHelper")
+ h, err := sh.StartWithOpts(sh.DefaultStartOpts().ExternalProgram(), nil, modules.Program(os.Args[0]), "--test.run=TestExternalTestHelper")
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
@@ -654,7 +639,7 @@
}
func TestPipe(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
@@ -669,7 +654,7 @@
}
opts := sh.DefaultStartOpts()
opts.Stdin = r
- h, err := sh.StartWithOpts(opts, nil, "pipeEcho")
+ h, err := sh.StartWithOpts(opts, nil, pipeEcho)
if err != nil {
t.Fatal(err)
}
@@ -682,8 +667,8 @@
scanner := bufio.NewScanner(h.Stdout())
want := []string{
- fmt.Sprintf("%p: hello world", pipeEcho),
- fmt.Sprintf("%p: %s", pipeEcho, cookie),
+ fmt.Sprintf("%p: hello world", pipeEchoFunc),
+ fmt.Sprintf("%p: %s", pipeEchoFunc, cookie),
}
i := 0
for scanner.Scan() {
@@ -702,7 +687,7 @@
}
func TestLIFO(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
if err != nil {
@@ -712,7 +697,7 @@
cases := []string{"a", "b", "c"}
for _, msg := range cases {
- h, err := sh.Start("lifo", nil)
+ h, err := sh.Start(nil, lifo)
if err != nil {
t.Fatal(err)
}
@@ -728,7 +713,7 @@
}
sort.Sort(sort.Reverse(sort.StringSlice(cases)))
for i, msg := range cases {
- if got, want := lines[i], fmt.Sprintf("%p: %s", lifo, msg); got != want {
+ if got, want := lines[i], fmt.Sprintf("%p: %s", lifoFunc, msg); got != want {
t.Fatalf("got %v, want %v", got, want)
}
}
@@ -782,20 +767,20 @@
}
func TestCredentialsAndNoExec(t *testing.T) {
- ctx, shutdown := test.InitForTest()
+ ctx, shutdown := test.V23Init()
defer shutdown()
sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
opts := sh.DefaultStartOpts()
- opts = opts.NoExecCommand()
+ opts = opts.NoExecProgram()
creds, err := sh.NewCustomCredentials()
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
opts = opts.WithCustomCredentials(creds)
- h, err := sh.StartWithOpts(opts, nil, "echos", "a")
+ h, err := sh.StartWithOpts(opts, nil, echo, "a")
if got, want := err, modules.ErrNoExecAndCustomCreds; got != want {
t.Fatalf("got %v, want %v", got, want)
diff --git a/test/modules/registry.go b/test/modules/registry.go
index 877d1ba..ed4c871 100644
--- a/test/modules/registry.go
+++ b/test/modules/registry.go
@@ -10,125 +10,109 @@
"io"
"io/ioutil"
"os"
- "strings"
- "sync"
+ "path/filepath"
+ "runtime"
+ "strconv"
"time"
- "v.io/x/lib/envvar"
"v.io/x/lib/vlog"
-
vexec "v.io/x/ref/lib/exec"
)
-type commandDesc struct {
- factory func() *execHandle
+// Program is a symbolic representation of a registered Main function.
+type Program string
+
+type programInfo struct {
main Main
- help string
+ factory func() *execHandle
}
-type cmdRegistry struct {
- sync.Mutex
- cmds map[string]*commandDesc
+type programRegistry struct {
+ programs []*programInfo
}
-var registry = &cmdRegistry{cmds: make(map[string]*commandDesc)}
+var registry = new(programRegistry)
-func (r *cmdRegistry) addCommand(name, help string, factory func() *execHandle, main Main) {
- r.Lock()
- defer r.Unlock()
- r.cmds[name] = &commandDesc{factory, main, help}
+func (r *programRegistry) addProgram(main Main, description string) Program {
+ prog := strconv.Itoa(len(r.programs))
+ factory := func() *execHandle { return newExecHandle(prog, description) }
+ r.programs = append(r.programs, &programInfo{main, factory})
+ return Program(prog)
}
-func (r *cmdRegistry) getCommand(name string) *commandDesc {
- r.Lock()
- defer r.Unlock()
- return r.cmds[name]
+func (r *programRegistry) getProgram(prog Program) *programInfo {
+ index, err := strconv.Atoi(string(prog))
+ if err != nil || index < 0 || index >= len(r.programs) {
+ return nil
+ }
+ return r.programs[index]
}
-func (r *cmdRegistry) getExternalCommand(name string) *commandDesc {
- h := newExecHandleForExternalCommand(name)
- return &commandDesc{
+func (r *programRegistry) getExternalProgram(prog Program) *programInfo {
+ h := newExecHandleExternal(string(prog))
+ return &programInfo{
factory: func() *execHandle { return h },
}
}
-// RegisterChild adds a new command to the registry that will be run
-// as a subprocess. It must be called before Dispatch or DispatchInTest is
-// called, typically from an init function.
-func RegisterChild(name, help string, main Main) {
- factory := func() *execHandle { return newExecHandle(name) }
- registry.addCommand(name, help, factory, main)
+func (r *programRegistry) String() string {
+ var s string
+ for _, info := range r.programs {
+ h := info.factory()
+ s += fmt.Sprintf("%s: %s\n", h.entryPoint, h.desc)
+ }
+ return s
}
-// Help returns the help message for the specified command, or a list
-// of all commands if the command parameter is an empty string.
-func Help(command string) string {
- return registry.help(command)
+// Register adds a new program to the registry that will be run as a subprocess.
+// It must be called before Dispatch is called, typically from an init function.
+func Register(main Main, description string) Program {
+ if _, file, line, ok := runtime.Caller(1); ok {
+ description = fmt.Sprintf("%s:%d %s", shortFile(file), line, description)
+ }
+ return registry.addProgram(main, description)
}
-func (r *cmdRegistry) help(command string) string {
- r.Lock()
- defer r.Unlock()
- if len(command) == 0 {
- h := ""
- for c, _ := range r.cmds {
- h += c + ", "
- }
- return strings.TrimRight(h, ", ")
+// shortFile returns the last 3 components of the given file name.
+func shortFile(file string) string {
+ var short string
+ for i := 0; i < 3; i++ {
+ short = filepath.Join(filepath.Base(file), short)
+ file = filepath.Dir(file)
}
- if c := r.cmds[command]; c != nil {
- return command + ": " + c.help
- }
- return ""
+ return short
}
const shellEntryPoint = "V23_SHELL_HELPER_PROCESS_ENTRY_POINT"
-// IsModulesChildProcess returns true if this process was started by
-// the modules package.
-func IsModulesChildProcess() bool {
+// IsChildProcess returns true if this process was started by the modules
+// package.
+func IsChildProcess() bool {
return os.Getenv(shellEntryPoint) != ""
}
-// Dispatch will execute the requested subprocess command from a within a
-// a subprocess. It will return without an error if it is executed by a
-// process that does not specify an entry point in its environment.
-//
-// func main() {
-// if modules.IsModulesChildProcess() {
-// if err := modules.Dispatch(); err != nil {
-// panic("error")
-// }
-// eturn
-// }
-// parent code...
-//
+// Dispatch executes the requested subprocess program from within a subprocess.
+// Returns an error if it is executed by a process that does not specify an
+// entry point in its environment.
func Dispatch() error {
- if !IsModulesChildProcess() {
- return nil
- }
return registry.dispatch()
}
-// DispatchAndExit is like Dispatch except that it will call os.Exit(0)
-// when executed within a child process and the command succeeds, or panic
-// on encountering an error.
-//
-// func main() {
-// modules.DispatchAndExit()
-// parent code...
-//
-func DispatchAndExit() {
- if !IsModulesChildProcess() {
- return
+// DispatchAndExitIfChild is a convenience function with three possible results:
+// * os.Exit(0) if called within a child process, and the dispatch succeeds.
+// * os.Exit(1) if called within a child process, and the dispatch fails.
+// * return with no side-effects, if not called within a child process.
+func DispatchAndExitIfChild() {
+ if IsChildProcess() {
+ if err := Dispatch(); err != nil {
+ fmt.Fprintf(os.Stderr, "modules.Dispatch failed: %v\n", err)
+ os.Exit(1)
+ }
+ os.Exit(0)
}
- if err := registry.dispatch(); err != nil {
- panic(fmt.Sprintf("unexpected error: %s", err))
- }
- os.Exit(0)
}
-func (r *cmdRegistry) dispatch() error {
+func (r *programRegistry) dispatch() error {
ch, err := vexec.GetChildHandle()
if err != nil {
// This is for debugging only. It's perfectly reasonable for this
@@ -140,18 +124,18 @@
// Only signal that the child is ready or failed if we successfully get
// a child handle. We most likely failed to get a child handle
// because the subprocess was run directly from the command line.
- command := os.Getenv(shellEntryPoint)
- if len(command) == 0 {
- err := fmt.Errorf("Failed to find entrypoint %q", command)
+ prog := os.Getenv(shellEntryPoint)
+ if prog == "" {
+ err := fmt.Errorf("Failed to find entrypoint %q", prog)
if ch != nil {
ch.SetFailed(err)
}
return err
}
- m := registry.getCommand(command)
+ m := registry.getProgram(Program(prog))
if m == nil {
- err := fmt.Errorf("%s: not registered", command)
+ err := fmt.Errorf("%s: not registered\n%s", prog, registry.String())
if ch != nil {
ch.SetFailed(err)
}
@@ -173,7 +157,7 @@
}(os.Getppid())
flag.Parse()
- return m.main(os.Stdin, os.Stdout, os.Stderr, envvar.SliceToMap(os.Environ()), flag.Args()...)
+ return m.main(EnvFromOS(), flag.Args()...)
}
// WaitForEOF returns when a read on its io.Reader parameter returns io.EOF
diff --git a/test/modules/shell.go b/test/modules/shell.go
index ca4c53d..34401c8 100644
--- a/test/modules/shell.go
+++ b/test/modules/shell.go
@@ -4,17 +4,17 @@
// Package modules implements a mechanism for running commonly used services as
// subprocesses, and client functionality for accessing those services. Such
-// services and functions are collectively called 'commands' and are managed by
+// services and functions are collectively called 'programs' and are managed by
// a 'Registry'. The Shell is analagous to the UNIX shell and maintains a key,
// value store of environment variables and config settings that are accessible
-// to the commands that it hosts. Simple variable expansion is supported.
+// to the programs that it hosts. Simple variable expansion is supported.
//
-// Three types of 'commands' may be invoked via a Shell:
+// Three types of 'programs' may be invoked via a Shell:
//
-// 1) Functions of type Shell.Main as subprocesses via fork/exec.
-// 2) Arbitrary non-Vanadium commands available on the underlying operating
+// 1) Functions of type Main as subprocesses via fork/exec.
+// 2) Arbitrary non-Vanadium programs available on the underlying operating
// system such as '/bin/cp', 'bash' etc.
-// 3) Arbitrary Vanadium commands available on the underlying operating system
+// 3) Arbitrary Vanadium programs available on the underlying operating system
// such as precompiled Vanadium services.
//
// The first type requires that the function to be executed is compiled into the
@@ -22,8 +22,8 @@
// a single, per-process, registry.
//
// The second two types allow for arbitrary binaries to be executed. The
-// distinction between a Vanadium and non-Vanadium command is that the Vanadium
-// command implements the protocol used by v.io/x/ref/lib/exec package to
+// distinction between a Vanadium and non-Vanadium program is that the Vanadium
+// program implements the protocol used by v.io/x/ref/lib/exec package to
// synchronise between the parent and child processes and to share information
// such as the ConfigKey key,value store supported by the Shell, a shared
// secret, shared file descriptors etc.
@@ -36,23 +36,20 @@
//
// The registry provides the following functions:
//
-// RegisterChild: generally called from an init function to register a
-// shell.Main to be executed in a subprocess by fork/exec'ing the calling
-// process.
-// Dispatch: which must be called in the child process to lookup the requested
-// function in the registry and to invoke it. This will typically be called
-// from a TestMain. modules.IsModulesChildProcess can be used to determine
-// if the calling process is a child started via this package.
+// Register: registers a Main function to be executed in a subprocess,
+// the returned Program is typically assigned to a global variable.
+// Dispatch: must be called in the child process to lookup and invoke the
+// requested function. Typically called from TestMain.
//
-// The v23 tool can automate generation of TestMain and calls to RegisterChild.
-// Adding the comment below to a test file will generate the appropriate code.
+// The v23 tool can automate generation of TestMain. Adding the comment below
+// to a test file will generate the appropriate code.
//
// //go:generate v23 test generate .
//
// Use 'v23 test generate --help' to get a complete explanation.
//
-// In all cases commands are started by invoking the StartWithOpts method on the
-// Shell with the name of the command to run. An instance of the Handle
+// In all cases programs are started by invoking the StartWithOpts method on the
+// Shell with the name of the program to run. An instance of the Handle
// interface is returned which can be used to interact with the function or
// subprocess, and in particular to read/write data from/to it using io channels
// that follow the stdin, stdout, stderr convention. The StartOpts struct is
@@ -61,20 +58,19 @@
// StartOpts and for common uses of StartWithOpts.
//
// Each successful call to StartWithOpts returns a handle representing the
-// running command. This handle can be used to gain access to that command's
+// running program. This handle can be used to gain access to that program's
// stdin, stdout, stderr and to request or synchronize with its termination via
// the Shutdown method. The Shutdown method can optionally be used to read any
-// remaining output from the commands stdout and stderr. The Shell maintains a
+// remaining output from the programs stdout and stderr. The Shell maintains a
// record of all such handles and will call Shutdown on them in LIFO order when
// the Shell's Cleanup method is called.
//
-// A simple protocol must be followed by all modules.Main commands, in
-// particular, they should wait for their stdin stream to be closed before
-// exiting. The caller can then coordinate with any command by writing to that
-// stdin stream and reading responses from the stdout stream, and it can close
-// stdin when it's ready for the command to exit using the CloseStdin method on
-// the command's handle. Any binary or script that follows this protocol can be
-// used as well.
+// A simple protocol must be followed by all programs, in particular, they
+// should wait for their stdin stream to be closed before exiting. The caller
+// can then coordinate with any program by writing to that stdin stream and
+// reading responses from the stdout stream, and it can close stdin when it's
+// ready for the program to exit using the CloseStdin method on the program's
+// handle. Any binary or script that follows this protocol can be used as well.
//
// By default, every Shell created by NewShell starts a security agent to manage
// principals for child processes. These default credentials can be overridden
@@ -82,12 +78,12 @@
// environment provided as a parameter to the StartWithOpts method. It is also
// possible to specify custom credentials via StartOpts.
//
-// Interacting with Commands
+// Interacting with Programs
//
// Handle.Stdout(), Stdin(), Stderr():
//
// StartWithOpts returns a Handle which can be used to interact with the running
-// command. In particular, its Stdin() and Stdout() methods give access to the
+// program. In particular, its Stdin() and Stdout() methods give access to the
// running process' corresponding stdin and stdout and hence can be used to
// communicate with it. Stderr is handled differently and is configured so that
// the child's stderr is written to a log file rather than a pipe. This is in
@@ -96,9 +92,9 @@
//
// Handle.Shutdown(stdout, stderr io.Writer):
//
-// The Shutdown method is used to gracefully shutdown a command and to
+// The Shutdown method is used to gracefully shutdown a program and to
// synchronise with its termination. In particular, Shutdown can be used to read
-// any unread output from the command's stdout and stderr. Note that since
+// any unread output from the program's stdout and stderr. Note that since
// Stderr is buffered to a file, Shutdown is able to return the entire contents
// of that file. This is useful for debugging misbehaving/crashing child
// processes.
@@ -107,32 +103,32 @@
//
// The Shell keeps track of all Handles that it has issued and in particular if
// Shutdown (or Forget) have not been called, it will call Shutdown for each
-// such Handle in LIFO order. This ensures that all commands will be Shutdown
+// such Handle in LIFO order. This ensures that all programs will be Shutdown
// even if the developer does not explicitly take care to do so for every
// invocation.
//
// Pipes:
//
-// StartWithOpts allows the caller to pass an io.Reader to the command
+// StartWithOpts allows the caller to pass an io.Reader to the program
// (StartOpts.Stdin) for it to read from, rather than creating a new pipe
-// internally. This makes it possible to connect the output of one command to
+// internally. This makes it possible to connect the output of one program to
// the input of another directly.
//
// Command Line Arguments:
//
// The arguments passed in calls to Start are appended to any system required
// ones (e.g. for propagating test timeouts, verbosity etc) and the child
-// process will call the command with the result of flag.Args(). In this way the
+// process will call the program with the result of flag.Args(). In this way the
// caller can provide flags used by libraries in the child process as well as
-// those specific to the command and the command will only receive the args
+// those specific to the program and the program will only receive the args
// specific to it. The usual "--" convention can be used to override this
// default behaviour.
//
// Caveats:
//
-// Handle.Shutdown assumes that the child command/process will terminate when
+// Handle.Shutdown assumes that the child program/process will terminate when
// its stdin stream is closed. This assumption is unlikely to be valid for
-// 'external' commands (e.g. /bin/cp) and in these cases Kill or some other
+// 'external' programs (e.g. /bin/cp) and in these cases Kill or some other
// application specific mechanism will need to be used.
package modules
@@ -172,7 +168,7 @@
ExecProtocol: true,
}
-// Shell represents the context within which commands are run.
+// Shell represents the context within which programs are run.
type Shell struct {
mu sync.Mutex
env map[string]string
@@ -350,22 +346,30 @@
return creds, nil
}
-type Main func(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error
-
-// String returns a string representation of the Shell, which is a
-// list of the commands currently available in the shell.
-func (sh *Shell) String() string {
- return registry.help("")
+// Env represents the environment for Main functions.
+type Env struct {
+ Stdin io.Reader
+ Stdout io.Writer
+ Stderr io.Writer
+ Vars map[string]string // Environment variables
}
-// Help returns the help message for the specified command.
-func (sh *Shell) Help(command string) string {
- return registry.help(command)
+// EnvFromOS returns a new Env based on the underlying OS.
+func EnvFromOS() *Env {
+ return &Env{
+ Stdin: os.Stdin,
+ Stdout: os.Stdout,
+ Stderr: os.Stderr,
+ Vars: envvar.SliceToMap(os.Environ()),
+ }
}
+// Main describes the entry-point function type for registered programs.
+type Main func(env *Env, args ...string) error
+
// Start is shorthand for StartWithOpts(sh.DefaultStartOpts(), ...)
-func (sh *Shell) Start(name string, env []string, args ...string) (Handle, error) {
- return sh.StartWithOpts(sh.DefaultStartOpts(), env, name, args...)
+func (sh *Shell) Start(env []string, prog Program, args ...string) (Handle, error) {
+ return sh.StartWithOpts(sh.DefaultStartOpts(), env, prog, args...)
}
// StartOpts represents the options that can be passed to the
@@ -397,11 +401,11 @@
Credentials *CustomCredentials
// ExecProtocol indicates whether the child process is expected to
// implement the v.io/x.ref/lib/exec parent/child protocol.
- // It should be set to false when running non-vanadium commands
+ // It should be set to false when running non-vanadium programs
// (e.g. /bin/cp).
ExecProtocol bool
- // External indicates if the command is an external process rather than
- // a Shell.Main function.
+ // External indicates if the program is an external process rather than
+ // a Main function.
External bool
// StartTimeout specifies the amount of time to wait for the
// child process to signal its correct intialization for Vanadium
@@ -451,37 +455,37 @@
return opts
}
-// NoExecCommand returns a copy of opts with the External option
+// NoExecProgram returns a copy of opts with the External option
// enabled and ExecProtocol disabled.
-func (opts StartOpts) NoExecCommand() StartOpts {
+func (opts StartOpts) NoExecProgram() StartOpts {
opts.External = true
opts.ExecProtocol = false
return opts
}
-// ExternalCommand returns a copy of StartOpts with the
+// ExternalProgram returns a copy of StartOpts with the
// External option enabled.
-func (opts StartOpts) ExternalCommand() StartOpts {
+func (opts StartOpts) ExternalProgram() StartOpts {
opts.External = true
return opts
}
var (
- ErrNotRegistered = errors.New("command not registered")
+ ErrNotRegistered = errors.New("program not registered")
ErrNoExecAndCustomCreds = errors.New("ExecProtocol set to false but this invocation is attempting to use custome credentials")
)
-// StartWithOpts starts the specified command according to the supplied
+// StartWithOpts starts the specified program according to the supplied
// StartOpts and returns a Handle which can be used for interacting with
-// that command.
+// that program.
//
-// The environment variables for the command are set by merging variables
+// The environment variables for the program are set by merging variables
// from the OS environment, those in this Shell and those provided as a
// parameter to it. In general, it prefers values from its parameter over
// those from the Shell, over those from the OS. However, the VeyronCredentials
// and agent FdEnvVar variables will never use the value from the Shell or OS.
//
-// If the shell is managing principals, the command is configured to
+// If the shell is managing principals, the program is configured to
// connect to the shell's agent. Custom credentials may be specified
// via StartOpts. If the shell is not managing principals, set
// the VeyronCredentials environment variable in the 'env' parameter.
@@ -489,7 +493,7 @@
// The Shell tracks all of the Handles that it creates so that it can shut
// them down when asked to. The returned Handle may be non-nil even when an
// error is returned, in which case it may be used to retrieve any output
-// from the failed command.
+// from the failed program.
//
// StartWithOpts will return a valid handle for errors that occur during the
// child processes startup process. It is thus possible to call Shutdown
@@ -504,16 +508,16 @@
// }
// t.Fatal(err)
// }
-func (sh *Shell) StartWithOpts(opts StartOpts, env []string, name string, args ...string) (Handle, error) {
+func (sh *Shell) StartWithOpts(opts StartOpts, env []string, prog Program, args ...string) (Handle, error) {
var err error
if opts.Error != nil {
return nil, opts.Error
}
- var desc *commandDesc
+ var info *programInfo
if opts.External {
- desc = registry.getExternalCommand(name)
- } else if desc = registry.getCommand(name); desc == nil {
+ info = registry.getExternalProgram(prog)
+ } else if info = registry.getProgram(prog); info == nil {
return nil, ErrNotRegistered
}
@@ -536,8 +540,8 @@
}
}
- handle := desc.factory()
- h, err := handle.start(sh, p, &opts, sh.setupCommandEnv(env), sh.expand(args))
+ handle := info.factory()
+ h, err := handle.start(sh, p, &opts, sh.setupProgramEnv(env), sh.expand(args))
if err != nil {
return h, err
}
@@ -548,19 +552,19 @@
return h, nil
}
-// CommandEnvelope returns the command line and environment that would be used
+// ProgramEnvelope returns the command line and environment that would be used
// for running the subprocess if it were started with the specifed arguments.
-func (sh *Shell) CommandEnvelope(name string, env []string, args ...string) ([]string, []string) {
- desc := registry.getCommand(name)
- if desc == nil {
+func (sh *Shell) ProgramEnvelope(env []string, prog Program, args ...string) ([]string, []string) {
+ info := registry.getProgram(prog)
+ if info == nil {
return []string{}, []string{}
}
- return desc.factory().envelope(sh, sh.setupCommandEnv(env), sh.expand(args))
+ return info.factory().envelope(sh, sh.setupProgramEnv(env), sh.expand(args))
}
// Forget tells the Shell to stop tracking the supplied Handle. This is
// generally used when the application wants to control the order that
-// commands are shutdown in.
+// programs are shutdown in.
func (sh *Shell) Forget(h Handle) {
sh.mu.Lock()
if handle, ok := h.(*execHandle); ok {
@@ -670,7 +674,7 @@
var err error
for i := len(handles); i > 0; i-- {
h := handles[i-1]
- writeMsg("---- Cleanup calling Shutdown on command %q\n", h.name)
+ writeMsg("---- Cleanup calling Shutdown on program %q\n", h.desc)
cerr := h.Shutdown(stdout, stderr)
if cerr != nil {
err = cerr
@@ -682,7 +686,7 @@
return ": error: " + err.Error()
}
}
- writeMsg("---- Shutdown on command %q%s\n", h.name, fn())
+ writeMsg("---- Shutdown on program %q%s\n", h.desc, fn())
}
if sh.cancelCtx != nil {
@@ -697,7 +701,7 @@
return err
}
-func (sh *Shell) setupCommandEnv(env []string) []string {
+func (sh *Shell) setupProgramEnv(env []string) []string {
osmap := envvar.SliceToMap(os.Environ())
evmap := envvar.SliceToMap(env)
@@ -731,34 +735,34 @@
Error() error
}
-// Handle represents a running command.
+// Handle represents a running program.
type Handle interface {
ExpectSession
- // Stdout returns a reader to the running command's stdout stream.
+ // Stdout returns a reader to the running program's stdout stream.
Stdout() io.Reader
- // Stderr returns a reader to the running command's stderr
+ // Stderr returns a reader to the running program's stderr
// stream.
Stderr() io.Reader
- // Stdin returns a writer to the running command's stdin. The
- // convention is for commands to wait for stdin to be closed before
+ // Stdin returns a writer to the running program's stdin. The
+ // convention is for programs to wait for stdin to be closed before
// they exit, thus the caller should close stdin when it wants the
- // command to exit cleanly.
+ // program to exit cleanly.
Stdin() io.Writer
// CloseStdin closes stdin in a manner that avoids a data race
// between any current readers on it.
CloseStdin()
- // Shutdown closes the Stdin for the command and then reads output
- // from the command's stdout until it encounters EOF, waits for
- // the command to complete and then reads all of its stderr output.
+ // Shutdown closes the Stdin for the program and then reads output
+ // from the program's stdout until it encounters EOF, waits for
+ // the program to complete and then reads all of its stderr output.
// The stdout and stderr contents are written to the corresponding
// io.Writers if they are non-nil, otherwise the content is discarded.
Shutdown(stdout, stderr io.Writer) error
- // Pid returns the pid of the process running the command
+ // Pid returns the pid of the process running the program
Pid() int
}
diff --git a/test/modules/util.go b/test/modules/util.go
index db463a1..642abfe 100644
--- a/test/modules/util.go
+++ b/test/modules/util.go
@@ -5,13 +5,11 @@
package modules
import (
- "flag"
"fmt"
"hash/adler32"
"io"
"io/ioutil"
"os"
- "strings"
"v.io/v23/security"
"v.io/x/lib/vlog"
@@ -60,19 +58,3 @@
}
return p, nil
}
-
-// Usage generates a usage string based on the flags in a flagset.
-func Usage(fs *flag.FlagSet) string {
- res := []string{}
- fs.VisitAll(func(f *flag.Flag) {
- format := " -%s=%s: %s"
- if getter, ok := f.Value.(flag.Getter); ok {
- if _, ok := getter.Get().(string); ok {
- // put quotes on the value
- format = " -%s=%q: %s"
- }
- }
- res = append(res, fmt.Sprintf(format, f.Name, f.DefValue, f.Usage))
- })
- return strings.Join(res, "\n") + "\n"
-}
diff --git a/test/testutil/util.go b/test/testutil/util.go
index cd80aa6..05492e2 100644
--- a/test/testutil/util.go
+++ b/test/testutil/util.go
@@ -10,24 +10,6 @@
"runtime"
)
-// DepthToExternalCaller determines the number of stack frames to the first
-// enclosing caller that is external to the package that this function is
-// called from. Drectory name is used as a proxy for package name,
-// that is, the directory component of the file return runtime.Caller is
-// compared to that of the lowest level caller until a different one is
-// encountered as the stack is walked upwards.
-func DepthToExternalCaller() int {
- _, file, _, _ := runtime.Caller(1)
- cwd := filepath.Dir(file)
- for d := 2; d < 10; d++ {
- _, file, _, _ := runtime.Caller(d)
- if cwd != filepath.Dir(file) {
- return d
- }
- }
- return 1
-}
-
// FormatLogLine will prepend the file and line number of the caller
// at the specificied depth (as per runtime.Caller) to the supplied
// format and args and return a formatted string. It is useful when
diff --git a/test/testutil/util_test.go b/test/testutil/util_test.go
index 86a8d24..0a44dab 100644
--- a/test/testutil/util_test.go
+++ b/test/testutil/util_test.go
@@ -10,14 +10,8 @@
)
func TestFormatLogline(t *testing.T) {
- depth, want := DepthToExternalCaller(), 2
- if depth != want {
- t.Errorf("got %v, want %v", depth, want)
- }
- {
- line, want := FormatLogLine(depth, "test"), "testing.go:.*"
- if ok, err := regexp.MatchString(want, line); !ok || err != nil {
- t.Errorf("got %v, want %v", line, want)
- }
+ line, want := FormatLogLine(2, "test"), "testing.go:.*"
+ if ok, err := regexp.MatchString(want, line); !ok || err != nil {
+ t.Errorf("got %v, want %v", line, want)
}
}
diff --git a/test/v23tests/binary.go b/test/v23tests/binary.go
index c4dd0cc..ec770e3 100644
--- a/test/v23tests/binary.go
+++ b/test/v23tests/binary.go
@@ -11,7 +11,6 @@
"strings"
"v.io/x/lib/vlog"
-
"v.io/x/ref/test/modules"
)
@@ -65,7 +64,7 @@
opts.Credentials, opts.Error = b.env.shell.NewChildCredentials("child")
}
opts.ExpectTesting = b.env.TB
- handle, err := b.env.shell.StartWithOpts(opts, b.envVars, b.Path(), args...)
+ handle, err := b.env.shell.StartWithOpts(opts, b.envVars, modules.Program(b.Path()), args...)
if err != nil {
if handle != nil {
vlog.Infof("%s: start failed", Caller(skip+1))
diff --git a/test/v23tests/internal/v23_test.go b/test/v23tests/internal/v23_test.go
index 87514d1..aad6a7a 100644
--- a/test/v23tests/internal/v23_test.go
+++ b/test/v23tests/internal/v23_test.go
@@ -4,11 +4,14 @@
// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY
+
package internal_test
-import "testing"
+import (
+ "testing"
-import "v.io/x/ref/test/v23tests"
+ "v.io/x/ref/test/v23tests"
+)
func TestV23One(t *testing.T) {
v23tests.RunTest(t, V23TestOne)
diff --git a/test/v23tests/invocation.go b/test/v23tests/invocation.go
index 8d5f3cf..63ddc75 100644
--- a/test/v23tests/invocation.go
+++ b/test/v23tests/invocation.go
@@ -11,7 +11,6 @@
"syscall"
"v.io/x/lib/vlog"
-
"v.io/x/ref/test/modules"
)
diff --git a/test/v23tests/v23tests.go b/test/v23tests/v23tests.go
index 4976dd1..91e1afa 100644
--- a/test/v23tests/v23tests.go
+++ b/test/v23tests/v23tests.go
@@ -419,7 +419,7 @@
env: t,
envVars: nil,
path: path,
- opts: t.shell.DefaultStartOpts().NoExecCommand(),
+ opts: t.shell.DefaultStartOpts().NoExecProgram(),
}
}
@@ -449,7 +449,7 @@
// be used via BuildV23Pkg.
func (t *T) BuildV23Pkg(pkg string, flags ...string) *Binary {
b := t.buildPkg(pkg, flags...)
- b.opts = t.shell.DefaultStartOpts().ExternalCommand()
+ b.opts = t.shell.DefaultStartOpts().ExternalProgram()
return b
}
@@ -474,7 +474,7 @@
env: t,
envVars: nil,
path: built_path,
- opts: t.shell.DefaultStartOpts().NoExecCommand(),
+ opts: t.shell.DefaultStartOpts().NoExecProgram(),
}
t.builtBinaries[pkg] = binary
return binary
diff --git a/test/v23tests/v23tests_test.go b/test/v23tests/v23tests_test.go
index 76e16be..63efeb9 100644
--- a/test/v23tests/v23tests_test.go
+++ b/test/v23tests/v23tests_test.go
@@ -8,7 +8,6 @@
"bytes"
"crypto/sha1"
"fmt"
- "io"
"os"
"regexp"
"strings"
@@ -101,23 +100,26 @@
var globalT *testing.T
func TestHelperProcess(t *testing.T) {
- globalT = t
- modules.Dispatch()
+ if modules.IsChildProcess() {
+ globalT = t
+ if err := modules.Dispatch(); err != nil {
+ t.Errorf("modules.Dispatch failed: %v", err)
+ }
+ }
}
-func RunIntegrationTestInChild(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+var RunIntegrationTestInChild = modules.Register(func(env *modules.Env, args ...string) error {
v23tests.RunTest(globalT, IntegrationTestInChild)
return nil
-}
+}, "RunIntegrationTestInChild")
func init() {
test.Init()
- modules.RegisterChild("RunIntegrationTestInChild", "", RunIntegrationTestInChild)
}
func TestDeferHandling(t *testing.T) {
sh, _ := modules.NewShell(nil, nil, testing.Verbose(), t)
- child, err := sh.Start("RunIntegrationTestInChild", nil, "--test.run=TestHelperProcess", "--v23.tests")
+ child, err := sh.Start(nil, RunIntegrationTestInChild, "--test.run=TestHelperProcess", "--v23.tests")
if err != nil {
t.Fatal(err)
}
@@ -294,7 +296,7 @@
msg := recover().(string)
// this, and the tests below are intended to ensure that line #s
// are captured and reported correctly.
- if got, want := msg, "v23tests_test.go:304"; !strings.Contains(got, want) {
+ if got, want := msg, "v23tests_test.go:306"; !strings.Contains(got, want) {
t.Fatalf("%q does not contain %q", got, want)
}
if got, want := msg, "fork/exec /bin/echox: no such file or directory"; !strings.Contains(got, want) {
@@ -316,7 +318,7 @@
sh.SetDefaultStartOpts(opts)
defer func() {
msg := recover().(string)
- if got, want := msg, "v23tests_test.go:326"; !strings.Contains(got, want) {
+ if got, want := msg, "v23tests_test.go:328"; !strings.Contains(got, want) {
t.Fatalf("%q does not contain %q", got, want)
}
if got, want := msg, "StartWithOpts"; !strings.Contains(got, want) {
@@ -340,7 +342,7 @@
if iterations == 0 {
t.Fatalf("our sleeper didn't get to run")
}
- if got, want := recover().(string), "v23tests_test.go:347: timed out"; !strings.Contains(got, want) {
+ if got, want := recover().(string), "v23tests_test.go:349: timed out"; !strings.Contains(got, want) {
t.Fatalf("%q does not contain %q", got, want)
}
}()
@@ -362,7 +364,7 @@
if iterations != 0 {
t.Fatalf("our sleeper got to run")
}
- if got, want := recover().(string), "v23tests_test.go:369: timed out"; !strings.Contains(got, want) {
+ if got, want := recover().(string), "v23tests_test.go:371: timed out"; !strings.Contains(got, want) {
t.Fatalf("%q does not contain %q", got, want)
}
}()