system/link: use syscall dispatcher
All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Successful in 2m5s
Test / Hakurei (push) Successful in 3m4s
Test / Hpkg (push) Successful in 3m45s
Test / Sandbox (race detector) (push) Successful in 4m26s
Test / Hakurei (race detector) (push) Successful in 5m6s
Test / Flake checks (push) Successful in 1m49s
All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Successful in 2m5s
Test / Hakurei (push) Successful in 3m4s
Test / Hpkg (push) Successful in 3m45s
Test / Sandbox (race detector) (push) Successful in 4m26s
Test / Hakurei (race detector) (push) Successful in 5m6s
Test / Flake checks (push) Successful in 1m49s
This enables hardlink op methods to be instrumented. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
fcd0f2ede7
commit
6cc2b406a4
@ -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{
|
||||
|
@ -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...)
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
84
system/link_test.go
Normal file
84
system/link_test.go
Normal file
@ -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"`},
|
||||
})
|
||||
}
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user