cmd/hakurei/print: serialise array for ps
All checks were successful
Test / Create distribution (push) Successful in 35s
Test / Sandbox (push) Successful in 40s
Test / Sandbox (race detector) (push) Successful in 42s
Test / Hakurei (push) Successful in 2m25s
Test / Hakurei (race detector) (push) Successful in 3m7s
Test / Hpkg (push) Successful in 3m13s
Test / Flake checks (push) Successful in 1m27s

Wanted to do this for a long time, since the key is redundant. This also makes it easier to migrate to the new store interface.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
Ophestra 2025-11-02 16:15:09 +09:00
parent 23ae7822bf
commit 0e5ca74b98
Signed by: cat
SSH Key Fingerprint: SHA256:gQ67O0enBZ7UdZypgtspB2FDM1g3GVw8nX0XSdcFw8Q
5 changed files with 55 additions and 11 deletions

View File

@ -1,9 +1,11 @@
package main package main
import ( import (
"bytes"
"fmt" "fmt"
"io" "io"
"log" "log"
"maps"
"slices" "slices"
"strconv" "strconv"
"strings" "strings"
@ -177,10 +179,8 @@ func printPs(output io.Writer, now time.Time, s store.Compat, short, flagJSON bo
} }
if !short && flagJSON { if !short && flagJSON {
es := make(map[string]*hst.State, len(entries)) es := slices.Collect(maps.Values(entries))
for id, instance := range entries { slices.SortFunc(es, func(a, b *hst.State) int { return bytes.Compare(a.ID[:], b.ID[:]) })
es[id.String()] = instance
}
encodeJSON(log.Fatal, output, short, es) encodeJSON(log.Fatal, output, short, es)
return return
} }

View File

@ -1,10 +1,12 @@
package main package main
import ( import (
"bytes"
"strings" "strings"
"testing" "testing"
"time" "time"
"hakurei.app/container/check"
"hakurei.app/hst" "hakurei.app/hst"
"hakurei.app/internal/store" "hakurei.app/internal/store"
) )
@ -530,8 +532,25 @@ func TestPrintPs(t *testing.T) {
4cf073bd 3405691582 9 (org.chromium.Chromium) 1h2m32s 4cf073bd 3405691582 9 (org.chromium.Chromium) 1h2m32s
`}, `},
{"valid short", map[hst.ID]*hst.State{testID: testState}, true, false, "4cf073bd\n"}, {"valid short", map[hst.ID]*hst.State{testID: testState}, true, false, "4cf073bd\n"},
{"valid json", map[hst.ID]*hst.State{testID: testState}, false, true, `{ {"valid json", map[hst.ID]*hst.State{testID: testState, (hst.ID)(bytes.Repeat([]byte{0xaa}, len(hst.ID{}))): {
"8e2c76b066dabe574cf073bdb46eb5c1": { ID: (hst.ID)(bytes.Repeat([]byte{0xaa}, len(hst.ID{}))),
PID: 0xbeef,
ShimPID: 0xcafe,
Config: &hst.Config{
ID: "uk.gensokyo.cat",
Enablements: hst.NewEnablements(hst.EWayland | hst.EPulse),
Identity: 1,
Container: &hst.ContainerConfig{
Shell: check.MustAbs("/bin/sh"),
Home: check.MustAbs("/data/data/uk.gensokyo.cat"),
Path: check.MustAbs("/usr/bin/cat"),
Args: []string{"cat"},
Flags: hst.FUserns,
},
},
Time: time.Unix(0, 0xdeadbeef).UTC(),
}}, false, true, `[
{
"instance": "8e2c76b066dabe574cf073bdb46eb5c1", "instance": "8e2c76b066dabe574cf073bdb46eb5c1",
"pid": 3405691582, "pid": 3405691582,
"shim_pid": 3735928559, "shim_pid": 3735928559,
@ -683,8 +702,33 @@ func TestPrintPs(t *testing.T) {
"share_tmpdir": true "share_tmpdir": true
}, },
"time": "1970-01-01T00:00:00.000000009Z" "time": "1970-01-01T00:00:00.000000009Z"
},
{
"instance": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"pid": 48879,
"shim_pid": 51966,
"id": "uk.gensokyo.cat",
"enablements": {
"wayland": true,
"pulse": true
},
"identity": 1,
"groups": null,
"container": {
"env": null,
"filesystem": null,
"shell": "/bin/sh",
"home": "/data/data/uk.gensokyo.cat",
"path": "/usr/bin/cat",
"args": [
"cat"
],
"userns": true,
"map_real_uid": false
},
"time": "1970-01-01T00:00:03.735928559Z"
} }
} ]
`}, `},
{"valid short json", map[hst.ID]*hst.State{testID: testState}, true, true, `["8e2c76b066dabe574cf073bdb46eb5c1"] {"valid short json", map[hst.ID]*hst.State{testID: testState}, true, true, `["8e2c76b066dabe574cf073bdb46eb5c1"]
`}, `},

View File

@ -58,7 +58,7 @@ def check_state(name, enablements):
instances = json.loads(machine.succeed("sudo -u alice -i XDG_RUNTIME_DIR=/run/user/1000 hakurei --json ps")) instances = json.loads(machine.succeed("sudo -u alice -i XDG_RUNTIME_DIR=/run/user/1000 hakurei --json ps"))
if len(instances) != 1: if len(instances) != 1:
raise Exception(f"unexpected state length {len(instances)}") raise Exception(f"unexpected state length {len(instances)}")
instance = next(iter(instances.values())) instance = instances[0]
if len(instance['container']['args']) != 1 or not (instance['container']['args'][0].startswith("/nix/store/")) or f"hakurei-{name}-" not in (instance['container']['args'][0]): if len(instance['container']['args']) != 1 or not (instance['container']['args'][0].startswith("/nix/store/")) or f"hakurei-{name}-" not in (instance['container']['args'][0]):
raise Exception(f"unexpected args {instance['container']['args']}") raise Exception(f"unexpected args {instance['container']['args']}")

View File

@ -84,14 +84,14 @@
virtualisation = { virtualisation = {
# Hopefully reduces spurious test failures: # Hopefully reduces spurious test failures:
memorySize = 4096; memorySize = 8192;
qemu.options = [ qemu.options = [
# Need to switch to a different GPU driver than the default one (-vga std) so that Sway can launch: # Need to switch to a different GPU driver than the default one (-vga std) so that Sway can launch:
"-vga none -device virtio-gpu-pci" "-vga none -device virtio-gpu-pci"
# Increase Go test compiler performance: # Increase Go test compiler performance:
"-smp 8" "-smp 16"
]; ];
}; };

View File

@ -56,7 +56,7 @@ def check_state(name, enablements):
instances = json.loads(machine.succeed("sudo -u alice -i XDG_RUNTIME_DIR=/run/user/1000 hakurei --json ps")) instances = json.loads(machine.succeed("sudo -u alice -i XDG_RUNTIME_DIR=/run/user/1000 hakurei --json ps"))
if len(instances) != 1: if len(instances) != 1:
raise Exception(f"unexpected state length {len(instances)}") raise Exception(f"unexpected state length {len(instances)}")
instance = next(iter(instances.values())) instance = instances[0]
command = f"{name}-start" command = f"{name}-start"
if not (instance['container']['path'].startswith("/nix/store/")) or not (instance['container']['path'].endswith(command)): if not (instance['container']['path'].startswith("/nix/store/")) or not (instance['container']['path'].endswith(command)):