system/xhost: wrap revert error correctly
All checks were successful
Test / Create distribution (push) Successful in 32s
Test / Sandbox (push) Successful in 2m7s
Test / Hakurei (push) Successful in 3m5s
Test / Hpkg (push) Successful in 3m55s
Test / Sandbox (race detector) (push) Successful in 4m25s
Test / Hakurei (race detector) (push) Successful in 5m8s
Test / Flake checks (push) Successful in 1m26s
All checks were successful
Test / Create distribution (push) Successful in 32s
Test / Sandbox (push) Successful in 2m7s
Test / Hakurei (push) Successful in 3m5s
Test / Hpkg (push) Successful in 3m55s
Test / Sandbox (race detector) (push) Successful in 4m25s
Test / Hakurei (race detector) (push) Successful in 5m8s
Test / Flake checks (push) Successful in 1m26s
This otherwise creates a confusing error message on a revert failure. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
da2b9c01ce
commit
985c4dd2fc
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"hakurei.app/system/acl"
|
"hakurei.app/system/acl"
|
||||||
"hakurei.app/system/dbus"
|
"hakurei.app/system/dbus"
|
||||||
|
"hakurei.app/system/internal/xcb"
|
||||||
)
|
)
|
||||||
|
|
||||||
type osFile interface {
|
type osFile interface {
|
||||||
@ -39,6 +40,9 @@ type syscallDispatcher interface {
|
|||||||
// aclUpdate provides [acl.Update].
|
// aclUpdate provides [acl.Update].
|
||||||
aclUpdate(name string, uid int, perms ...acl.Perm) error
|
aclUpdate(name string, uid int, perms ...acl.Perm) error
|
||||||
|
|
||||||
|
// xcbChangeHosts provides [xcb.ChangeHosts].
|
||||||
|
xcbChangeHosts(mode xcb.HostMode, family xcb.Family, address string) error
|
||||||
|
|
||||||
// dbusAddress provides [dbus.Address].
|
// dbusAddress provides [dbus.Address].
|
||||||
dbusAddress() (session, system string)
|
dbusAddress() (session, system string)
|
||||||
// dbusFinalise provides [dbus.Finalise].
|
// dbusFinalise provides [dbus.Finalise].
|
||||||
@ -71,6 +75,10 @@ func (k direct) aclUpdate(name string, uid int, perms ...acl.Perm) error {
|
|||||||
return acl.Update(name, uid, perms...)
|
return acl.Update(name, uid, perms...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k direct) xcbChangeHosts(mode xcb.HostMode, family xcb.Family, address string) error {
|
||||||
|
return xcb.ChangeHosts(mode, family, address)
|
||||||
|
}
|
||||||
|
|
||||||
func (k direct) dbusAddress() (session, system string) {
|
func (k direct) dbusAddress() (session, system string) {
|
||||||
return dbus.Address()
|
return dbus.Address()
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"hakurei.app/container/stub"
|
"hakurei.app/container/stub"
|
||||||
"hakurei.app/system/acl"
|
"hakurei.app/system/acl"
|
||||||
"hakurei.app/system/dbus"
|
"hakurei.app/system/dbus"
|
||||||
|
"hakurei.app/system/internal/xcb"
|
||||||
)
|
)
|
||||||
|
|
||||||
// call initialises a [stub.Call].
|
// call initialises a [stub.Call].
|
||||||
@ -280,6 +281,14 @@ func (k *kstub) aclUpdate(name string, uid int, perms ...acl.Perm) error {
|
|||||||
stub.CheckArgReflect(k.Stub, "perms", perms, 2))
|
stub.CheckArgReflect(k.Stub, "perms", perms, 2))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k *kstub) xcbChangeHosts(mode xcb.HostMode, family xcb.Family, address string) error {
|
||||||
|
k.Helper()
|
||||||
|
return k.Expects("xcbChangeHosts").Error(
|
||||||
|
stub.CheckArg(k.Stub, "mode", mode, 0),
|
||||||
|
stub.CheckArg(k.Stub, "family", family, 1),
|
||||||
|
stub.CheckArg(k.Stub, "address", address, 2))
|
||||||
|
}
|
||||||
|
|
||||||
func (k *kstub) dbusAddress() (session, system string) {
|
func (k *kstub) dbusAddress() (session, system string) {
|
||||||
k.Helper()
|
k.Helper()
|
||||||
ret := k.Expects("dbusAddress").Ret.([2]string)
|
ret := k.Expects("dbusAddress").Ret.([2]string)
|
||||||
|
@ -158,70 +158,3 @@ func TestPrintJoinedError(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type tcOp struct {
|
|
||||||
et Enablement
|
|
||||||
path string
|
|
||||||
}
|
|
||||||
|
|
||||||
// test an instance of the Op interface
|
|
||||||
func (ptc tcOp) test(t *testing.T, gotOps []Op, wantOps []Op, fn string) {
|
|
||||||
if len(gotOps) != len(wantOps) {
|
|
||||||
t.Errorf("%s: inserted %v Ops, want %v", fn,
|
|
||||||
len(gotOps), len(wantOps))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Run("path", func(t *testing.T) {
|
|
||||||
if len(gotOps) > 0 {
|
|
||||||
if got := gotOps[0].Path(); got != ptc.path {
|
|
||||||
t.Errorf("Path() = %q, want %q",
|
|
||||||
got, ptc.path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
for i := range gotOps {
|
|
||||||
o := gotOps[i]
|
|
||||||
|
|
||||||
t.Run("is", func(t *testing.T) {
|
|
||||||
if !o.Is(o) {
|
|
||||||
t.Errorf("Is returned false on self")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !o.Is(wantOps[i]) {
|
|
||||||
t.Errorf("%s: inserted %#v, want %#v",
|
|
||||||
fn,
|
|
||||||
o, wantOps[i])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("criteria", func(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
ec Enablement
|
|
||||||
want bool
|
|
||||||
}{
|
|
||||||
{"nil", 0xff, ptc.et != User},
|
|
||||||
{"self", ptc.et, true},
|
|
||||||
{"all", EWayland | EX11 | EDBus | EPulse | User | Process, true},
|
|
||||||
{"enablements", EWayland | EX11 | EDBus | EPulse, ptc.et != User && ptc.et != Process},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
var criteria *Criteria
|
|
||||||
if tc.ec != 0xff {
|
|
||||||
criteria = (*Criteria)(&tc.ec)
|
|
||||||
}
|
|
||||||
if got := criteria.hasType(o.Type()); got != tc.want {
|
|
||||||
t.Errorf("hasType: got %v, want %v",
|
|
||||||
got, tc.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -15,23 +15,23 @@ type xhostOp string
|
|||||||
|
|
||||||
func (x xhostOp) Type() Enablement { return EX11 }
|
func (x xhostOp) Type() Enablement { return EX11 }
|
||||||
|
|
||||||
func (x xhostOp) apply(*I) error {
|
func (x xhostOp) apply(sys *I) error {
|
||||||
msg.Verbosef("inserting entry %s to X11", x)
|
sys.verbosef("inserting entry %s to X11", x)
|
||||||
return newOpError("xhost",
|
return newOpError("xhost",
|
||||||
xcb.ChangeHosts(xcb.HostModeInsert, xcb.FamilyServerInterpreted, "localuser\x00"+string(x)), false)
|
sys.xcbChangeHosts(xcb.HostModeInsert, xcb.FamilyServerInterpreted, "localuser\x00"+string(x)), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x xhostOp) revert(_ *I, ec *Criteria) error {
|
func (x xhostOp) revert(sys *I, ec *Criteria) error {
|
||||||
if ec.hasType(x.Type()) {
|
if ec.hasType(x.Type()) {
|
||||||
msg.Verbosef("deleting entry %s from X11", x)
|
sys.verbosef("deleting entry %s from X11", x)
|
||||||
return newOpError("xhost",
|
return newOpError("xhost",
|
||||||
xcb.ChangeHosts(xcb.HostModeDelete, xcb.FamilyServerInterpreted, "localuser\x00"+string(x)), false)
|
sys.xcbChangeHosts(xcb.HostModeDelete, xcb.FamilyServerInterpreted, "localuser\x00"+string(x)), true)
|
||||||
} else {
|
} else {
|
||||||
msg.Verbosef("skipping entry %s in X11", x)
|
sys.verbosef("skipping entry %s in X11", x)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x xhostOp) Is(o Op) bool { target, ok := o.(xhostOp); return ok && x == target }
|
func (x xhostOp) Is(o Op) bool { target, ok := o.(xhostOp); return ok && x == target }
|
||||||
func (x xhostOp) Path() string { return string(x) }
|
func (x xhostOp) Path() string { return "/tmp/.X11-unix" }
|
||||||
func (x xhostOp) String() string { return string("SI:localuser:" + x) }
|
func (x xhostOp) String() string { return string("SI:localuser:" + x) }
|
||||||
|
@ -2,33 +2,56 @@ package system
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"hakurei.app/container/stub"
|
||||||
|
"hakurei.app/system/internal/xcb"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestChangeHosts(t *testing.T) {
|
func TestXHostOp(t *testing.T) {
|
||||||
testCases := []string{"chronos", "keyring", "cat", "kbd", "yonah"}
|
checkOpBehaviour(t, []opBehaviourTestCase{
|
||||||
for _, tc := range testCases {
|
{"xcbChangeHosts revert", 0xbeef, EX11, xhostOp("chronos"), []stub.Call{
|
||||||
t.Run("append ChangeHosts operation for "+tc, func(t *testing.T) {
|
call("verbosef", stub.ExpectArgs{"inserting entry %s to X11", []any{xhostOp("chronos")}}, nil, nil),
|
||||||
sys := New(t.Context(), 150)
|
call("xcbChangeHosts", stub.ExpectArgs{xcb.HostMode(xcb.HostModeInsert), xcb.Family(xcb.FamilyServerInterpreted), "localuser\x00chronos"}, nil, stub.UniqueError(1)),
|
||||||
sys.ChangeHosts(tc)
|
}, &OpError{Op: "xhost", Err: stub.UniqueError(1)}, nil, nil},
|
||||||
(&tcOp{EX11, tc}).test(t, sys.ops, []Op{
|
|
||||||
xhostOp(tc),
|
|
||||||
}, "ChangeHosts")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestXHost_String(t *testing.T) {
|
{"xcbChangeHosts revert", 0xbeef, EX11, xhostOp("chronos"), []stub.Call{
|
||||||
testCases := []struct {
|
call("verbosef", stub.ExpectArgs{"inserting entry %s to X11", []any{xhostOp("chronos")}}, nil, nil),
|
||||||
username string
|
call("xcbChangeHosts", stub.ExpectArgs{xcb.HostMode(xcb.HostModeInsert), xcb.Family(xcb.FamilyServerInterpreted), "localuser\x00chronos"}, nil, nil),
|
||||||
want string
|
}, nil, []stub.Call{
|
||||||
}{
|
call("verbosef", stub.ExpectArgs{"deleting entry %s from X11", []any{xhostOp("chronos")}}, nil, nil),
|
||||||
{"chronos", "SI:localuser:chronos"},
|
call("xcbChangeHosts", stub.ExpectArgs{xcb.HostMode(xcb.HostModeDelete), xcb.Family(xcb.FamilyServerInterpreted), "localuser\x00chronos"}, nil, stub.UniqueError(0)),
|
||||||
}
|
}, &OpError{Op: "xhost", Err: stub.UniqueError(0), Revert: true}},
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.want, func(t *testing.T) {
|
{"success skip", 0xbeef, 0, xhostOp("chronos"), []stub.Call{
|
||||||
if got := xhostOp(tc.username).String(); got != tc.want {
|
call("verbosef", stub.ExpectArgs{"inserting entry %s to X11", []any{xhostOp("chronos")}}, nil, nil),
|
||||||
t.Errorf("String() = %v, want %v", got, tc.want)
|
call("xcbChangeHosts", stub.ExpectArgs{xcb.HostMode(xcb.HostModeInsert), xcb.Family(xcb.FamilyServerInterpreted), "localuser\x00chronos"}, nil, nil),
|
||||||
}
|
}, nil, []stub.Call{
|
||||||
|
call("verbosef", stub.ExpectArgs{"skipping entry %s in X11", []any{xhostOp("chronos")}}, nil, nil),
|
||||||
|
}, nil},
|
||||||
|
|
||||||
|
{"success", 0xbeef, EX11, xhostOp("chronos"), []stub.Call{
|
||||||
|
call("verbosef", stub.ExpectArgs{"inserting entry %s to X11", []any{xhostOp("chronos")}}, nil, nil),
|
||||||
|
call("xcbChangeHosts", stub.ExpectArgs{xcb.HostMode(xcb.HostModeInsert), xcb.Family(xcb.FamilyServerInterpreted), "localuser\x00chronos"}, nil, nil),
|
||||||
|
}, nil, []stub.Call{
|
||||||
|
call("verbosef", stub.ExpectArgs{"deleting entry %s from X11", []any{xhostOp("chronos")}}, nil, nil),
|
||||||
|
call("xcbChangeHosts", stub.ExpectArgs{xcb.HostMode(xcb.HostModeDelete), xcb.Family(xcb.FamilyServerInterpreted), "localuser\x00chronos"}, nil, nil),
|
||||||
|
}, nil},
|
||||||
|
})
|
||||||
|
|
||||||
|
checkOpsBuilder(t, "ChangeHosts", []opsBuilderTestCase{
|
||||||
|
{"xhost", 0xcafebabe, func(_ *testing.T, sys *I) {
|
||||||
|
sys.ChangeHosts("chronos")
|
||||||
|
}, []Op{
|
||||||
|
xhostOp("chronos"),
|
||||||
|
}, stub.Expect{}},
|
||||||
|
})
|
||||||
|
|
||||||
|
checkOpIs(t, []opIsTestCase{
|
||||||
|
{"differs", xhostOp("kbd"), xhostOp("chronos"), false},
|
||||||
|
{"equals", xhostOp("chronos"), xhostOp("chronos"), true},
|
||||||
|
})
|
||||||
|
|
||||||
|
checkOpMeta(t, []opMetaTestCase{
|
||||||
|
{"xhost", xhostOp("chronos"), EX11, "/tmp/.X11-unix", "SI:localuser:chronos"},
|
||||||
})
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user