aboutsummaryrefslogtreecommitdiffhomepage
path: root/system
diff options
context:
space:
mode:
Diffstat (limited to 'system')
-rw-r--r--system/acl_test.go5
-rw-r--r--system/dispatcher.go10
-rw-r--r--system/dispatcher_test.go13
-rw-r--r--system/link.go15
-rw-r--r--system/link_test.go84
-rw-r--r--system/tmpfiles_test.go37
6 files changed, 116 insertions, 48 deletions
diff --git a/system/acl_test.go b/system/acl_test.go
index 910e5a13..5228b902 100644
--- a/system/acl_test.go
+++ b/system/acl_test.go
@@ -54,7 +54,7 @@ func TestACLUpdateOp(t *testing.T) {
}, nil},
})
- checkOpsBuilder(t, "UpdatePerm", []opsBuilderTestCase{
+ checkOpsBuilder(t, "UpdatePermType", []opsBuilderTestCase{
{"simple",
0xdeadbeef,
func(_ *testing.T, sys *I) {
@@ -65,8 +65,7 @@ func TestACLUpdateOp(t *testing.T) {
&aclUpdateOp{Process, "/run/user/1971/hakurei", []acl.Perm{acl.Execute}},
&aclUpdateOp{Process, "/tmp/hakurei.0/tmpdir/150", []acl.Perm{acl.Read, acl.Write, acl.Execute}},
}, stub.Expect{}},
- })
- checkOpsBuilder(t, "UpdatePermType", []opsBuilderTestCase{
+
{"tmpdirp", 0xdeadbeef, func(_ *testing.T, sys *I) {
sys.UpdatePermType(User, "/tmp/hakurei.0/tmpdir", acl.Execute)
}, []Op{
diff --git a/system/dispatcher.go b/system/dispatcher.go
index c896de57..5d5c82bf 100644
--- a/system/dispatcher.go
+++ b/system/dispatcher.go
@@ -1,6 +1,8 @@
package system
import (
+ "os"
+
"hakurei.app/system/acl"
"hakurei.app/system/dbus"
)
@@ -13,6 +15,11 @@ type syscallDispatcher interface {
// just synchronising access is not enough, as this is for test instrumentation.
new(f func(k syscallDispatcher))
+ // link provides os.Link.
+ link(oldname, newname string) error
+ // remove provides os.Remove.
+ remove(name string) error
+
// aclUpdate provides [acl.Update].
aclUpdate(name string, uid int, perms ...acl.Perm) error
@@ -37,6 +44,9 @@ type direct struct{}
func (k direct) new(f func(k syscallDispatcher)) { go f(k) }
+func (k direct) link(oldname, newname string) error { return os.Link(oldname, newname) }
+func (k direct) remove(name string) error { return os.Remove(name) }
+
func (k direct) aclUpdate(name string, uid int, perms ...acl.Perm) error {
return acl.Update(name, uid, perms...)
}
diff --git a/system/dispatcher_test.go b/system/dispatcher_test.go
index c23c6c58..c459de4b 100644
--- a/system/dispatcher_test.go
+++ b/system/dispatcher_test.go
@@ -192,6 +192,19 @@ type kstub struct{ *stub.Stub[syscallDispatcher] }
func (k *kstub) new(f func(k syscallDispatcher)) { k.Helper(); k.New(f) }
+func (k *kstub) link(oldname, newname string) error {
+ k.Helper()
+ return k.Expects("link").Error(
+ stub.CheckArg(k.Stub, "oldname", oldname, 0),
+ stub.CheckArg(k.Stub, "newname", newname, 1))
+}
+
+func (k *kstub) remove(name string) error {
+ k.Helper()
+ return k.Expects("remove").Error(
+ stub.CheckArg(k.Stub, "name", name, 0))
+}
+
func (k *kstub) aclUpdate(name string, uid int, perms ...acl.Perm) error {
k.Helper()
return k.Expects("aclUpdate").Error(
diff --git a/system/link.go b/system/link.go
index 8df85fc1..2eb658af 100644
--- a/system/link.go
+++ b/system/link.go
@@ -2,7 +2,6 @@ package system
import (
"fmt"
- "os"
)
// Link calls LinkFileType with the [Process] criteria.
@@ -22,17 +21,17 @@ type hardlinkOp struct {
func (l *hardlinkOp) Type() Enablement { return l.et }
-func (l *hardlinkOp) apply(*I) error {
- msg.Verbose("linking", l)
- return newOpError("hardlink", os.Link(l.src, l.dst), false)
+func (l *hardlinkOp) apply(sys *I) error {
+ sys.verbose("linking", l)
+ return newOpError("hardlink", sys.link(l.src, l.dst), false)
}
-func (l *hardlinkOp) revert(_ *I, ec *Criteria) error {
+func (l *hardlinkOp) revert(sys *I, ec *Criteria) error {
if ec.hasType(l.Type()) {
- msg.Verbosef("removing hard link %q", l.dst)
- return newOpError("hardlink", os.Remove(l.dst), true)
+ sys.verbosef("removing hard link %q", l.dst)
+ return newOpError("hardlink", sys.remove(l.dst), true)
} else {
- msg.Verbosef("skipping hard link %q", l.dst)
+ sys.verbosef("skipping hard link %q", l.dst)
return nil
}
}
diff --git a/system/link_test.go b/system/link_test.go
new file mode 100644
index 00000000..b962db1a
--- /dev/null
+++ b/system/link_test.go
@@ -0,0 +1,84 @@
+package system
+
+import (
+ "testing"
+
+ "hakurei.app/container/stub"
+)
+
+func TestHardlinkOp(t *testing.T) {
+ checkOpBehaviour(t, []opBehaviourTestCase{
+ {"link", 0xdeadbeef, 0xff, &hardlinkOp{EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}, []stub.Call{
+ call("verbose", stub.ExpectArgs{[]any{"linking", &hardlinkOp{EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}}}, nil, nil),
+ call("link", stub.ExpectArgs{"/run/user/1000/pulse/native", "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"}, nil, stub.UniqueError(1)),
+ }, &OpError{Op: "hardlink", Err: stub.UniqueError(1)}, nil, nil},
+
+ {"remove", 0xdeadbeef, 0xff, &hardlinkOp{EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}, []stub.Call{
+ call("verbose", stub.ExpectArgs{[]any{"linking", &hardlinkOp{EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}}}, nil, nil),
+ call("link", stub.ExpectArgs{"/run/user/1000/pulse/native", "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"}, nil, nil),
+ }, nil, []stub.Call{
+ call("verbosef", stub.ExpectArgs{"removing hard link %q", []any{"/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"}}, nil, nil),
+ call("remove", stub.ExpectArgs{"/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"}, nil, stub.UniqueError(0)),
+ }, &OpError{Op: "hardlink", Err: stub.UniqueError(0), Revert: true}},
+
+ {"success skip", 0xdeadbeef, EWayland | EX11, &hardlinkOp{EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}, []stub.Call{
+ call("verbose", stub.ExpectArgs{[]any{"linking", &hardlinkOp{EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}}}, nil, nil),
+ call("link", stub.ExpectArgs{"/run/user/1000/pulse/native", "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"}, nil, nil),
+ }, nil, []stub.Call{
+ call("verbosef", stub.ExpectArgs{"skipping hard link %q", []any{"/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"}}, nil, nil),
+ }, nil},
+
+ {"success", 0xdeadbeef, 0xff, &hardlinkOp{EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}, []stub.Call{
+ call("verbose", stub.ExpectArgs{[]any{"linking", &hardlinkOp{EPulse, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"}}}, nil, nil),
+ call("link", stub.ExpectArgs{"/run/user/1000/pulse/native", "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"}, nil, nil),
+ }, nil, []stub.Call{
+ call("verbosef", stub.ExpectArgs{"removing hard link %q", []any{"/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"}}, nil, nil),
+ call("remove", stub.ExpectArgs{"/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse"}, nil, nil),
+ }, nil},
+ })
+
+ checkOpsBuilder(t, "LinkFileType", []opsBuilderTestCase{
+ {"type", 0xcafebabe, func(_ *testing.T, sys *I) {
+ sys.LinkFileType(User, "/run/user/1000/pulse/native", "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse")
+ }, []Op{
+ &hardlinkOp{User, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"},
+ }, stub.Expect{}},
+
+ {"link", 0xcafebabe, func(_ *testing.T, sys *I) {
+ sys.Link("/run/user/1000/pulse/native", "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse")
+ }, []Op{
+ &hardlinkOp{Process, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"},
+ }, stub.Expect{}},
+ })
+
+ checkOpIs(t, []opIsTestCase{
+ {"nil", (*hardlinkOp)(nil), (*hardlinkOp)(nil), false},
+ {"zero", new(hardlinkOp), new(hardlinkOp), true},
+
+ {"src differs",
+ &hardlinkOp{Process, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse"},
+ &hardlinkOp{Process, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"},
+ false},
+
+ {"dst differs",
+ &hardlinkOp{Process, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6", "/run/user/1000/pulse/native"},
+ &hardlinkOp{Process, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"},
+ false},
+
+ {"et differs",
+ &hardlinkOp{User, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"},
+ &hardlinkOp{Process, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"},
+ false},
+
+ {"equals",
+ &hardlinkOp{Process, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"},
+ &hardlinkOp{Process, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"},
+ true},
+ })
+
+ checkOpMeta(t, []opMetaTestCase{
+ {"link", &hardlinkOp{Process, "/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse", "/run/user/1000/pulse/native"},
+ Process, "/run/user/1000/pulse/native",
+ `"/run/user/1000/hakurei/9663730666a44cfc2a81610379e02ed6/pulse" from "/run/user/1000/pulse/native"`},
+ })
+}
diff --git a/system/tmpfiles_test.go b/system/tmpfiles_test.go
index 6410a9a5..a06242ee 100644
--- a/system/tmpfiles_test.go
+++ b/system/tmpfiles_test.go
@@ -24,43 +24,6 @@ func TestCopyFile(t *testing.T) {
}
}
-func TestLink(t *testing.T) {
- testCases := []struct {
- dst, src string
- }{
- {"/tmp/hakurei.1971/f587afe9fce3c8e1ad5b64deb6c41ad5/pulse-cookie", "/home/ophestra/xdg/config/pulse/cookie"},
- {"/tmp/hakurei.1971/62154f708b5184ab01f9dcc2bbe7a33b/pulse-cookie", "/home/ophestra/xdg/config/pulse/cookie"},
- }
- for _, tc := range testCases {
- t.Run("link file "+tc.dst+" from "+tc.src, func(t *testing.T) {
- sys := New(t.Context(), 150)
- sys.Link(tc.src, tc.dst)
- (&tcOp{Process, tc.src}).test(t, sys.ops, []Op{
- &hardlinkOp{Process, tc.dst, tc.src},
- }, "Link")
- })
- }
-}
-
-func TestLinkFileType(t *testing.T) {
- testCases := []struct {
- tcOp
- dst string
- }{
- {tcOp{User, "/tmp/hakurei.1971/f587afe9fce3c8e1ad5b64deb6c41ad5/pulse-cookie"}, "/home/ophestra/xdg/config/pulse/cookie"},
- {tcOp{Process, "/tmp/hakurei.1971/62154f708b5184ab01f9dcc2bbe7a33b/pulse-cookie"}, "/home/ophestra/xdg/config/pulse/cookie"},
- }
- for _, tc := range testCases {
- t.Run("link file "+tc.dst+" from "+tc.path+" with type "+TypeString(tc.et), func(t *testing.T) {
- sys := New(t.Context(), 150)
- sys.LinkFileType(tc.et, tc.path, tc.dst)
- tc.test(t, sys.ops, []Op{
- &hardlinkOp{tc.et, tc.dst, tc.path},
- }, "LinkFileType")
- })
- }
-}
-
func TestTmpfile_String(t *testing.T) {
testCases := []struct {
src string