All checks were successful
Test / Create distribution (push) Successful in 43s
Test / Hpkg (push) Successful in 4m3s
Test / Sandbox (race detector) (push) Successful in 4m36s
Test / Hakurei (race detector) (push) Successful in 5m17s
Test / Sandbox (push) Successful in 1m27s
Test / Hakurei (push) Successful in 2m15s
Test / Flake checks (push) Successful in 1m28s
This turns out to still be quite useful across internal/app and its relatives. Perhaps a cleaner replacement for baseError. Signed-off-by: Ophestra <cat@gensokyo.uk>
254 lines
6.1 KiB
Go
254 lines
6.1 KiB
Go
package hst_test
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"net"
|
|
"os"
|
|
"syscall"
|
|
"testing"
|
|
|
|
"hakurei.app/container"
|
|
"hakurei.app/container/stub"
|
|
"hakurei.app/hst"
|
|
)
|
|
|
|
func TestAppError(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
err error
|
|
s string
|
|
message string
|
|
is, isF error
|
|
}{
|
|
{"message", &hst.AppError{Step: "obtain uid from hsu", Err: stub.UniqueError(0),
|
|
Msg: "the setuid helper is missing: /run/wrappers/bin/hsu"},
|
|
"unique error 0 injected by the test suite",
|
|
"the setuid helper is missing: /run/wrappers/bin/hsu",
|
|
stub.UniqueError(0), os.ErrNotExist},
|
|
|
|
{"os.PathError", &hst.AppError{Step: "passthrough os.PathError",
|
|
Err: &os.PathError{Op: "stat", Path: "/proc/nonexistent", Err: os.ErrNotExist}},
|
|
"stat /proc/nonexistent: file does not exist",
|
|
"cannot stat /proc/nonexistent: file does not exist",
|
|
os.ErrNotExist, stub.UniqueError(0xdeadbeef)},
|
|
|
|
{"os.LinkError", &hst.AppError{Step: "passthrough os.LinkError",
|
|
Err: &os.LinkError{Op: "link", Old: "/proc/self", New: "/proc/nonexistent", Err: os.ErrNotExist}},
|
|
"link /proc/self /proc/nonexistent: file does not exist",
|
|
"cannot link /proc/self /proc/nonexistent: file does not exist",
|
|
os.ErrNotExist, stub.UniqueError(0xdeadbeef)},
|
|
|
|
{"os.SyscallError", &hst.AppError{Step: "passthrough os.SyscallError",
|
|
Err: &os.SyscallError{Syscall: "meow", Err: syscall.ENOSYS}},
|
|
"meow: function not implemented",
|
|
"cannot meow: function not implemented",
|
|
syscall.ENOSYS, syscall.ENOTRECOVERABLE},
|
|
|
|
{"net.OpError", &hst.AppError{Step: "passthrough net.OpError",
|
|
Err: &net.OpError{Op: "dial", Net: "cat", Err: net.UnknownNetworkError("cat")}},
|
|
"dial cat: unknown network cat",
|
|
"cannot dial cat: unknown network cat",
|
|
net.UnknownNetworkError("cat"), syscall.ENOTRECOVERABLE},
|
|
|
|
{"default", &hst.AppError{Step: "initialise container configuration", Err: stub.UniqueError(1)},
|
|
"unique error 1 injected by the test suite",
|
|
"cannot initialise container configuration: unique error 1 injected by the test suite",
|
|
stub.UniqueError(1), os.ErrInvalid},
|
|
}
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Run("error", func(t *testing.T) {
|
|
if got := tc.err.Error(); got != tc.s {
|
|
t.Errorf("Error: %s, want %s", got, tc.s)
|
|
}
|
|
})
|
|
|
|
t.Run("message", func(t *testing.T) {
|
|
gotMessage, gotMessageOk := container.GetErrorMessage(tc.err)
|
|
if want := tc.message != "\x00"; gotMessageOk != want {
|
|
t.Errorf("GetErrorMessage: ok = %v, want %v", gotMessage, want)
|
|
}
|
|
|
|
if gotMessageOk {
|
|
if gotMessage != tc.message {
|
|
t.Errorf("GetErrorMessage: %s, want %s", gotMessage, tc.message)
|
|
}
|
|
}
|
|
})
|
|
|
|
t.Run("is", func(t *testing.T) {
|
|
if !errors.Is(tc.err, tc.is) {
|
|
t.Errorf("Is: unexpected false for %v", tc.is)
|
|
}
|
|
if errors.Is(tc.err, tc.isF) {
|
|
t.Errorf("Is: unexpected true for %v", tc.isF)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestTemplate(t *testing.T) {
|
|
const want = `{
|
|
"id": "org.chromium.Chromium",
|
|
"path": "/run/current-system/sw/bin/chromium",
|
|
"args": [
|
|
"chromium",
|
|
"--ignore-gpu-blocklist",
|
|
"--disable-smooth-scrolling",
|
|
"--enable-features=UseOzonePlatform",
|
|
"--ozone-platform=wayland"
|
|
],
|
|
"enablements": {
|
|
"wayland": true,
|
|
"dbus": true,
|
|
"pulse": true
|
|
},
|
|
"session_bus": {
|
|
"see": null,
|
|
"talk": [
|
|
"org.freedesktop.Notifications",
|
|
"org.freedesktop.FileManager1",
|
|
"org.freedesktop.ScreenSaver",
|
|
"org.freedesktop.secrets",
|
|
"org.kde.kwalletd5",
|
|
"org.kde.kwalletd6",
|
|
"org.gnome.SessionManager"
|
|
],
|
|
"own": [
|
|
"org.chromium.Chromium.*",
|
|
"org.mpris.MediaPlayer2.org.chromium.Chromium.*",
|
|
"org.mpris.MediaPlayer2.chromium.*"
|
|
],
|
|
"call": {
|
|
"org.freedesktop.portal.*": "*"
|
|
},
|
|
"broadcast": {
|
|
"org.freedesktop.portal.*": "@/org/freedesktop/portal/*"
|
|
},
|
|
"filter": true
|
|
},
|
|
"system_bus": {
|
|
"see": null,
|
|
"talk": [
|
|
"org.bluez",
|
|
"org.freedesktop.Avahi",
|
|
"org.freedesktop.UPower"
|
|
],
|
|
"own": null,
|
|
"call": null,
|
|
"broadcast": null,
|
|
"filter": true
|
|
},
|
|
"username": "chronos",
|
|
"shell": "/run/current-system/sw/bin/zsh",
|
|
"home": "/data/data/org.chromium.Chromium",
|
|
"extra_perms": [
|
|
{
|
|
"ensure": true,
|
|
"path": "/var/lib/hakurei/u0",
|
|
"x": true
|
|
},
|
|
{
|
|
"path": "/var/lib/hakurei/u0/org.chromium.Chromium",
|
|
"r": true,
|
|
"w": true,
|
|
"x": true
|
|
}
|
|
],
|
|
"identity": 9,
|
|
"groups": [
|
|
"video",
|
|
"dialout",
|
|
"plugdev"
|
|
],
|
|
"container": {
|
|
"hostname": "localhost",
|
|
"wait_delay": -1,
|
|
"seccomp_flags": 1,
|
|
"seccomp_presets": 1,
|
|
"seccomp_compat": true,
|
|
"devel": true,
|
|
"userns": true,
|
|
"host_net": true,
|
|
"host_abstract": true,
|
|
"tty": true,
|
|
"multiarch": true,
|
|
"env": {
|
|
"GOOGLE_API_KEY": "AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY",
|
|
"GOOGLE_DEFAULT_CLIENT_ID": "77185425430.apps.googleusercontent.com",
|
|
"GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT"
|
|
},
|
|
"map_real_uid": true,
|
|
"device": true,
|
|
"filesystem": [
|
|
{
|
|
"type": "bind",
|
|
"dst": "/",
|
|
"src": "/var/lib/hakurei/base/org.debian",
|
|
"write": true,
|
|
"special": true
|
|
},
|
|
{
|
|
"type": "bind",
|
|
"dst": "/etc/",
|
|
"src": "/etc/",
|
|
"special": true
|
|
},
|
|
{
|
|
"type": "ephemeral",
|
|
"dst": "/tmp/",
|
|
"write": true,
|
|
"perm": 493
|
|
},
|
|
{
|
|
"type": "overlay",
|
|
"dst": "/nix/store",
|
|
"lower": [
|
|
"/mnt-root/nix/.ro-store"
|
|
],
|
|
"upper": "/mnt-root/nix/.rw-store/upper",
|
|
"work": "/mnt-root/nix/.rw-store/work"
|
|
},
|
|
{
|
|
"type": "bind",
|
|
"src": "/nix/store"
|
|
},
|
|
{
|
|
"type": "link",
|
|
"dst": "/run/current-system",
|
|
"linkname": "/run/current-system",
|
|
"dereference": true
|
|
},
|
|
{
|
|
"type": "link",
|
|
"dst": "/run/opengl-driver",
|
|
"linkname": "/run/opengl-driver",
|
|
"dereference": true
|
|
},
|
|
{
|
|
"type": "bind",
|
|
"dst": "/data/data/org.chromium.Chromium",
|
|
"src": "/var/lib/hakurei/u0/org.chromium.Chromium",
|
|
"write": true,
|
|
"ensure": true
|
|
},
|
|
{
|
|
"type": "bind",
|
|
"src": "/dev/dri",
|
|
"dev": true,
|
|
"optional": true
|
|
}
|
|
]
|
|
}
|
|
}`
|
|
|
|
if p, err := json.MarshalIndent(hst.Template(), "", "\t"); err != nil {
|
|
t.Fatalf("cannot marshal: %v", err)
|
|
} else if s := string(p); s != want {
|
|
t.Fatalf("Template:\n%s\nwant:\n%s",
|
|
s, want)
|
|
}
|
|
}
|