111 lines
4.5 KiB
Go
111 lines
4.5 KiB
Go
package runtime
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"browser.local/run/config"
|
|
)
|
|
|
|
func TestManagedProcessStateRootIsolatedPerRunService(t *testing.T) {
|
|
workspace := t.TempDir()
|
|
base := config.Config{WorkspaceRoot: workspace, ServerInstanceID: "server-1", PluginID: "game.scum", ComponentKind: "run", ComponentKey: "run-local"}
|
|
first := base
|
|
first.RunEndpointID = "run-a"
|
|
second := base
|
|
second.RunEndpointID = "run-b"
|
|
third := base
|
|
third.RunEndpointID = "run-a"
|
|
third.ComponentKey = "run-secondary"
|
|
|
|
firstRoot := managedProcessStateRoot(first)
|
|
secondRoot := managedProcessStateRoot(second)
|
|
thirdRoot := managedProcessStateRoot(third)
|
|
if firstRoot == secondRoot || firstRoot == thirdRoot || secondRoot == thirdRoot {
|
|
t.Fatalf("run services must not share managed process state: %q %q %q", firstRoot, secondRoot, thirdRoot)
|
|
}
|
|
wantPrefix := filepath.Join(workspace, "run-services") + string(filepath.Separator)
|
|
for _, root := range []string{firstRoot, secondRoot, thirdRoot} {
|
|
if !strings.HasPrefix(root, wantPrefix) {
|
|
t.Fatalf("managed process state escaped the isolated root: %q", root)
|
|
}
|
|
if len(filepath.Base(root)) != 64 {
|
|
t.Fatalf("managed process state namespace is not a sha256 directory: %q", root)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMigrateLegacyManagedProcessStateKeepsOnlyThisRunService(t *testing.T) {
|
|
workspace := t.TempDir()
|
|
cfg := config.Config{WorkspaceRoot: workspace, RunEndpointID: "run-a", ServerInstanceID: "server-1", PluginID: "game.scum", ComponentKind: "run", ComponentKey: "run-local"}
|
|
legacy := processJournal{Version: 1, Items: map[string]ProcessIdentity{
|
|
"owned": {RunEndpointID: "run-a", ServerInstanceID: "server-1", ProfileKey: "run-local", PID: 101, State: "running"},
|
|
"other-endpoint": {RunEndpointID: "run-b", ServerInstanceID: "server-1", ProfileKey: "run-local", PID: 102, State: "running"},
|
|
"other-profile": {RunEndpointID: "run-a", ServerInstanceID: "server-1", ProfileKey: "run-other", PID: 103, State: "running"},
|
|
}}
|
|
body, err := json.Marshal(legacy)
|
|
if err != nil {
|
|
t.Fatalf("marshal legacy journal: %v", err)
|
|
}
|
|
legacyPath := filepath.Join(workspace, "state", "processes.json")
|
|
if err := os.MkdirAll(filepath.Dir(legacyPath), 0o700); err != nil {
|
|
t.Fatalf("create legacy state directory: %v", err)
|
|
}
|
|
if err := os.WriteFile(legacyPath, body, 0o600); err != nil {
|
|
t.Fatalf("write legacy journal: %v", err)
|
|
}
|
|
|
|
stateRoot := managedProcessStateRoot(cfg)
|
|
if err := migrateLegacyManagedProcessState(cfg, stateRoot); err != nil {
|
|
t.Fatalf("migrate legacy journal: %v", err)
|
|
}
|
|
migratedBody, err := os.ReadFile(filepath.Join(stateRoot, "state", "processes.json"))
|
|
if err != nil {
|
|
t.Fatalf("read isolated journal: %v", err)
|
|
}
|
|
var migrated processJournal
|
|
if err := json.Unmarshal(migratedBody, &migrated); err != nil {
|
|
t.Fatalf("decode isolated journal: %v", err)
|
|
}
|
|
if len(migrated.Items) != 1 || migrated.Items["owned"].PID != 101 {
|
|
t.Fatalf("isolated journal imported another Run service: %+v", migrated.Items)
|
|
}
|
|
}
|
|
|
|
func TestMigrateManagedProcessStateImportsMatchingPriorNamespace(t *testing.T) {
|
|
workspace := t.TempDir()
|
|
cfg := config.Config{WorkspaceRoot: workspace, RunEndpointID: "run-a", ServerInstanceID: "server-1", PluginID: "game.scum", ComponentKind: "run", ComponentKey: "run-local"}
|
|
priorRoot := filepath.Join(workspace, "run-services", "prior", "state")
|
|
if err := os.MkdirAll(priorRoot, 0o700); err != nil {
|
|
t.Fatalf("create prior state directory: %v", err)
|
|
}
|
|
body, err := json.Marshal(processJournal{Version: 2, Items: map[string]ProcessIdentity{
|
|
"owned": {RunEndpointID: "run-a", ServerInstanceID: "server-1", ProfileKey: "run-local", PID: 101, State: "exited"},
|
|
"other": {RunEndpointID: "run-b", ServerInstanceID: "server-1", ProfileKey: "run-local", PID: 102, State: "running"},
|
|
}})
|
|
if err != nil {
|
|
t.Fatalf("marshal prior journal: %v", err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(priorRoot, "processes.json"), body, 0o600); err != nil {
|
|
t.Fatalf("write prior journal: %v", err)
|
|
}
|
|
stateRoot := managedProcessStateRoot(cfg)
|
|
if err := migrateManagedProcessState(cfg, stateRoot); err != nil {
|
|
t.Fatalf("migrate managed state: %v", err)
|
|
}
|
|
migratedBody, err := os.ReadFile(filepath.Join(stateRoot, "state", "processes.json"))
|
|
if err != nil {
|
|
t.Fatalf("read migrated journal: %v", err)
|
|
}
|
|
var migrated processJournal
|
|
if err := json.Unmarshal(migratedBody, &migrated); err != nil {
|
|
t.Fatalf("decode migrated journal: %v", err)
|
|
}
|
|
if len(migrated.Items) != 1 || migrated.Items["owned"].PID != 101 {
|
|
t.Fatalf("unexpected migrated matching state: %+v", migrated.Items)
|
|
}
|
|
}
|