services/device/interna/impl: simple test for deamon mode
This CL adds a starting point test for daemon mode sufficient to show
that basic daemon mode is functioning, shifts some test code to
improve the sharding of device manager tests and updates envelope
utilities for the new daemon member variables.
MultiPart: 2/2
Change-Id: I097ab624770d9b990d3c37bc49b6dc97d6eb0078
diff --git a/services/application/application/impl_test.go b/services/application/application/impl_test.go
index 4227acd..8f7a084 100644
--- a/services/application/application/impl_test.go
+++ b/services/application/application/impl_test.go
@@ -37,6 +37,8 @@
File: "/path/to/package1",
},
},
+ Restarts: 0,
+ RestartTimeWindow: 0,
}
jsonEnv = `{
"Title": "fifa world cup",
@@ -70,7 +72,9 @@
"S": null
}
}
- }
+ },
+ "Restarts": 0,
+ "RestartTimeWindow": 0
}`
)
diff --git a/services/device/internal/impl/applife/app_life_test.go b/services/device/internal/impl/applife/app_life_test.go
index f336bb2..8484495 100644
--- a/services/device/internal/impl/applife/app_life_test.go
+++ b/services/device/internal/impl/applife/app_life_test.go
@@ -89,7 +89,7 @@
utiltest.Resolve(t, ctx, "pingserver", 1)
// Create an envelope for a first version of the app.
- *envelope = utiltest.EnvelopeFromShell(sh, []string{utiltest.TestEnvVarName + "=env-val-envelope"}, utiltest.AppCmd, "google naps", fmt.Sprintf("--%s=flag-val-envelope", utiltest.TestFlagName), "appV1")
+ *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")
// Install the app. The config-specified flag value for testFlagName
// should override the value specified in the envelope above, and the
@@ -185,12 +185,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")
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "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", "appV2")
+ *envelope = utiltest.EnvelopeFromShell(sh, []string{utiltest.TestEnvVarName + "=env-val-envelope"}, utiltest.AppCmd, "google naps", 0, 0, "appV2")
utiltest.UpdateApp(t, ctx, appID)
@@ -303,7 +303,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", "hAppV1")
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.HangingAppCmd, "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 ef023ca..dfe3592 100644
--- a/services/device/internal/impl/applife/instance_reaping_test.go
+++ b/services/device/internal/impl/applife/instance_reaping_test.go
@@ -34,7 +34,7 @@
utiltest.Resolve(t, ctx, "pingserver", 1)
// Create an envelope for a first version of the app.
- *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps", "appV1")
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "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
new file mode 100644
index 0000000..84d0602
--- /dev/null
+++ b/services/device/internal/impl/daemonreap/daemon_reaping_test.go
@@ -0,0 +1,87 @@
+// 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 daemonreap_test
+
+import (
+ "syscall"
+ "testing"
+ "time"
+
+ "v.io/v23/naming"
+ "v.io/v23/services/device"
+ "v.io/v23/services/stats"
+ "v.io/v23/vdl"
+
+ "v.io/x/ref/services/device/internal/impl/utiltest"
+ "v.io/x/ref/services/internal/servicetest"
+)
+
+func TestDaemonRestart(t *testing.T) {
+ cleanup, ctx, sh, envelope, root, helperPath, _ := utiltest.StartupHelper(t)
+ defer cleanup()
+
+ // 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")
+ 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)
+
+ // 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")
+ appID := utiltest.InstallApp(t, ctx)
+
+ // Start an instance of the app.
+ instance1ID := utiltest.LaunchApp(t, ctx, appID)
+
+ // Wait until the app pings us that it's ready.
+ pingCh.VerifyPingArgs(t, utiltest.UserName(t), "default", "")
+
+ // Get application pid.
+ name := naming.Join("dm", "apps/"+appID+"/"+instance1ID+"/stats/system/pid")
+ c := stats.StatsClient(name)
+ v, err := c.Value(ctx)
+ if err != nil {
+ t.Fatalf("Value() failed: %v\n", err)
+ }
+ var pid int
+ if err := vdl.Convert(&pid, v); err != nil {
+ t.Fatalf("pid returned from stats interface is not an int: %v", err)
+ }
+
+ utiltest.VerifyState(t, ctx, device.InstanceStateRunning, appID, instance1ID)
+ syscall.Kill(int(pid), 9)
+
+ // Start a second instance of the app which will force polling to happen.
+ instance2ID := utiltest.LaunchApp(t, ctx, appID)
+ pingCh.VerifyPingArgs(t, utiltest.UserName(t), "default", "")
+
+ // TODO(rjkroege): Because there is no daemon mode, instance1ID is not running even
+ // though it should be.
+ utiltest.VerifyState(t, ctx, device.InstanceStateNotRunning, appID, instance1ID)
+
+ // TODO(rjkroege): Demonstrate that the device manager will only restart the app the
+ // configured number of times (1)
+
+ // instance2ID is still running though.
+ utiltest.VerifyState(t, ctx, device.InstanceStateRunning, appID, instance2ID)
+
+ // Cleanup.
+ utiltest.TerminateApp(t, ctx, appID, instance2ID)
+
+ // TODO(rjkroege): instance1ID isn't running but should be.
+ // utiltest.TerminateApp(t, ctx, appID, instance1ID)
+
+ // Cleanly shut down the device manager.
+ utiltest.VerifyNoRunningProcesses(t)
+ syscall.Kill(dmh.Pid(), syscall.SIGINT)
+ dmh.Expect("dm terminated")
+ dmh.ExpectEOF()
+}
diff --git a/services/device/internal/impl/daemonreap/doc.go b/services/device/internal/impl/daemonreap/doc.go
new file mode 100644
index 0000000..c0def53
--- /dev/null
+++ b/services/device/internal/impl/daemonreap/doc.go
@@ -0,0 +1,8 @@
+// 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 daemonreap
+
+// Test code for the device manager's facility to run daemon
+// processes and reconcile processes via kill.
diff --git a/services/device/internal/impl/daemonreap/impl_test.go b/services/device/internal/impl/daemonreap/impl_test.go
new file mode 100644
index 0000000..dd72081
--- /dev/null
+++ b/services/device/internal/impl/daemonreap/impl_test.go
@@ -0,0 +1,19 @@
+// 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 daemonreap_test
+
+import (
+ "testing"
+
+ "v.io/x/ref/services/device/internal/impl/utiltest"
+)
+
+func TestMain(m *testing.M) {
+ utiltest.TestMainImpl(m)
+}
+
+func TestSuidHelper(t *testing.T) {
+ utiltest.TestSuidHelperImpl(t)
+}
diff --git a/services/device/internal/impl/instance_reaping_kill_test.go b/services/device/internal/impl/daemonreap/instance_reaping_kill_test.go
similarity index 98%
rename from services/device/internal/impl/instance_reaping_kill_test.go
rename to services/device/internal/impl/daemonreap/instance_reaping_kill_test.go
index 8e6c68b..c04f8b0 100644
--- a/services/device/internal/impl/instance_reaping_kill_test.go
+++ b/services/device/internal/impl/daemonreap/instance_reaping_kill_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-package impl_test
+package daemonreap_test
import (
"fmt"
@@ -42,7 +42,7 @@
utiltest.Resolve(t, ctx, "pingserver", 1)
// Create an envelope for the app.
- *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps", "appV1")
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps", 0, 0, "appV1")
// Install the app.
appID := utiltest.InstallApp(t, ctx)
diff --git a/services/device/internal/impl/globsuid/glob_test.go b/services/device/internal/impl/globsuid/glob_test.go
index f9becde..30fdc23 100644
--- a/services/device/internal/impl/globsuid/glob_test.go
+++ b/services/device/internal/impl/globsuid/glob_test.go
@@ -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", "appV1")
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "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/suid_test.go b/services/device/internal/impl/globsuid/suid_test.go
index 83ae185..12afe73 100644
--- a/services/device/internal/impl/globsuid/suid_test.go
+++ b/services/device/internal/impl/globsuid/suid_test.go
@@ -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", fmt.Sprintf("--%s=flag-val-envelope", utiltest.TestFlagName), "appV1")
+ *envelope = utiltest.EnvelopeFromShell(sh, []string{utiltest.TestEnvVarName + "=env-var"}, utiltest.AppCmd, "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 14425d8..4a7743d 100644
--- a/services/device/internal/impl/impl_test.go
+++ b/services/device/internal/impl/impl_test.go
@@ -137,7 +137,7 @@
// Brand new device manager must be claimed first.
utiltest.ClaimDevice(t, ctx, "claimable", "factoryDM", "mydevice", utiltest.NoPairingToken)
// Simulate an invalid envelope in the application repository.
- *envelope = utiltest.EnvelopeFromShell(sh, dmPauseBeforeStopEnv, utiltest.DeviceManagerCmd, "bogus", dmArgs...)
+ *envelope = utiltest.EnvelopeFromShell(sh, dmPauseBeforeStopEnv, utiltest.DeviceManagerCmd, "bogus", 0, 0, dmArgs...)
utiltest.UpdateDeviceExpectError(t, ctx, "factoryDM", impl.ErrAppTitleMismatch.ID)
utiltest.RevertDeviceExpectError(t, ctx, "factoryDM", impl.ErrUpdateNoOp.ID)
@@ -145,7 +145,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, "v2DM")
+ *envelope = utiltest.EnvelopeFromShell(sh, dmEnv, utiltest.DeviceManagerCmd, application.DeviceManagerTitle, 0, 0, "v2DM")
utiltest.UpdateDevice(t, ctx, "factoryDM")
// Current link should have been updated to point to v2.
@@ -189,7 +189,7 @@
// 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, "v2.5DM")
+ *envelope = utiltest.EnvelopeFromShell(sh, dmEnv, utiltest.DeviceManagerV10Cmd, application.DeviceManagerTitle, 0, 0, "v2.5DM")
utiltest.UpdateDeviceExpectError(t, ctx, "v2DM", impl.ErrOperationFailed.ID)
if evalLink() != scriptPathV2 {
@@ -197,7 +197,7 @@
}
// Create a third version of the device manager and issue an update.
- *envelope = utiltest.EnvelopeFromShell(sh, dmEnv, utiltest.DeviceManagerCmd, application.DeviceManagerTitle, "v3DM")
+ *envelope = utiltest.EnvelopeFromShell(sh, dmEnv, utiltest.DeviceManagerCmd, application.DeviceManagerTitle, 0, 0, "v3DM")
utiltest.UpdateDevice(t, ctx, "v2DM")
scriptPathV3 := evalLink()
@@ -404,7 +404,7 @@
defer cleanup()
// Create the envelope for the first version of the app.
- *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps", "appV1")
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps", 0, 0, "appV1")
envelope.Packages = map[string]application.SignedFile{
"test": application.SignedFile{
File: "realbin/testpkg",
diff --git a/services/device/internal/impl/perms/debug_perms_test.go b/services/device/internal/impl/perms/debug_perms_test.go
index 9c6e757..296c3b8 100644
--- a/services/device/internal/impl/perms/debug_perms_test.go
+++ b/services/device/internal/impl/perms/debug_perms_test.go
@@ -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", "appV1")
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps", 0, 0, "appV1")
// Install the app.
appID := utiltest.InstallApp(t, ctx)
diff --git a/services/device/internal/impl/perms/perms_test.go b/services/device/internal/impl/perms/perms_test.go
index 83bd086..69fe3c1 100644
--- a/services/device/internal/impl/perms/perms_test.go
+++ b/services/device/internal/impl/perms/perms_test.go
@@ -59,7 +59,7 @@
pid := servicetest.ReadPID(t, dmh)
defer syscall.Kill(pid, syscall.SIGINT)
- *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps", "trapp")
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps", 0, 0, "trapp")
claimantCtx := utiltest.CtxWithNewPrincipal(t, ctx, idp, "claimant")
octx, err := v23.WithPrincipal(ctx, testutil.NewPrincipal("other"))
@@ -142,7 +142,7 @@
defer utiltest.VerifyNoRunningProcesses(t)
// Create an envelope for an app.
- *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps")
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "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/reaping/instance_reaping_test.go b/services/device/internal/impl/reaping/instance_reaping_test.go
index 7dd0c55..d4c1aeb 100644
--- a/services/device/internal/impl/reaping/instance_reaping_test.go
+++ b/services/device/internal/impl/reaping/instance_reaping_test.go
@@ -43,7 +43,7 @@
utiltest.Resolve(t, ctx, "pingserver", 1)
// Create an envelope for the app.
- *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps", "appV1")
+ *envelope = utiltest.EnvelopeFromShell(sh, nil, utiltest.AppCmd, "google naps", 0, 0, "appV1")
// Install the app.
appID := utiltest.InstallApp(t, ctx)
diff --git a/services/device/internal/impl/utiltest/helpers.go b/services/device/internal/impl/utiltest/helpers.go
index 0f2305a..b92adf6 100644
--- a/services/device/internal/impl/utiltest/helpers.go
+++ b/services/device/internal/impl/utiltest/helpers.go
@@ -69,15 +69,17 @@
}
}
-func EnvelopeFromShell(sh *modules.Shell, env []string, cmd, title string, args ...string) application.Envelope {
+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...)
return application.Envelope{
Title: title,
Args: args[1:],
// TODO(caprita): revisit how the environment is sanitized for arbirary
// apps.
- Env: impl.VanadiumEnvironment(nenv),
- Binary: application.SignedFile{File: MockBinaryRepoName},
+ Env: impl.VanadiumEnvironment(nenv),
+ Binary: application.SignedFile{File: MockBinaryRepoName},
+ Restarts: int32(retries),
+ RestartTimeWindow: window,
}
}
diff --git a/services/internal/fs/simplestore.go b/services/internal/fs/simplestore.go
index 8ae5457..2211ecd 100644
--- a/services/internal/fs/simplestore.go
+++ b/services/internal/fs/simplestore.go
@@ -15,6 +15,7 @@
"sort"
"strings"
"sync"
+ "time"
"v.io/x/ref/services/profile"
@@ -86,12 +87,14 @@
// implementation by removing support for loading files in the
// now legacy GOB format.
type applicationEnvelope struct {
- Title string
- Args []string
- Binary application.SignedFile
- Publisher security.WireBlessings
- Env []string
- Packages application.Packages
+ Title string
+ Args []string
+ Binary application.SignedFile
+ Publisher security.WireBlessings
+ Env []string
+ Packages application.Packages
+ Restarts int32
+ RestartTimeWindow time.Duration
}
// This function is needed only to support existing serialized data and
@@ -114,12 +117,14 @@
return nil, err
}
return application.Envelope{
- Title: env.Title,
- Args: env.Args,
- Binary: env.Binary,
- Publisher: publisher,
- Env: env.Env,
- Packages: env.Packages,
+ Title: env.Title,
+ Args: env.Args,
+ Binary: env.Binary,
+ Publisher: publisher,
+ Env: env.Env,
+ Packages: env.Packages,
+ Restarts: env.Restarts,
+ RestartTimeWindow: env.RestartTimeWindow,
}, nil
}
@@ -131,7 +136,7 @@
// Ensure that no fields have been added to application.Envelope,
// because if so, then applicationEnvelope defined in this package
// needs to change
- if n := reflect.TypeOf(application.Envelope{}).NumField(); n != 6 {
+ if n := reflect.TypeOf(application.Envelope{}).NumField(); n != 8 {
panic(fmt.Sprintf("It appears that fields have been added to or removed from application.Envelope before the hack in this file around gob-encodeability was removed. Please also update applicationEnvelope, translateToGobEncodeable and translateToGobDecodeable in this file"))
}
}