internal/outcome/shim: check full behaviour
All checks were successful
Test / Create distribution (push) Successful in 24s
Test / Hakurei (push) Successful in 42s
Test / Sandbox (push) Successful in 38s
Test / Hakurei (race detector) (push) Successful in 42s
Test / Sandbox (race detector) (push) Successful in 38s
Test / Hpkg (push) Successful in 39s
Test / Flake checks (push) Successful in 1m21s
All checks were successful
Test / Create distribution (push) Successful in 24s
Test / Hakurei (push) Successful in 42s
Test / Sandbox (push) Successful in 38s
Test / Hakurei (race detector) (push) Successful in 42s
Test / Sandbox (race detector) (push) Successful in 38s
Test / Hpkg (push) Successful in 39s
Test / Flake checks (push) Successful in 1m21s
This took significant effort to stub out, and achieves full coverage after c5aefe5e9d. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
36f8064905
commit
46c5ce4936
@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
@ -193,8 +194,8 @@ func checkOpBehaviour(t *testing.T, testCases []opBehaviourTestCase) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wantConfig := tc.newConfig()
|
wantConfig := tc.newConfig()
|
||||||
k := &kstub{panicDispatcher{}, stub.New(t,
|
k := &kstub{nil, nil, panicDispatcher{}, stub.New(t,
|
||||||
func(s *stub.Stub[syscallDispatcher]) syscallDispatcher { return &kstub{panicDispatcher{}, s} },
|
func(s *stub.Stub[syscallDispatcher]) syscallDispatcher { return &kstub{nil, nil, panicDispatcher{}, s} },
|
||||||
stub.Expect{Calls: wantCallsFull},
|
stub.Expect{Calls: wantCallsFull},
|
||||||
)}
|
)}
|
||||||
defer stub.HandleExit(t)
|
defer stub.HandleExit(t)
|
||||||
@ -297,7 +298,12 @@ func checkSimple(t *testing.T, fname string, testCases []simpleTestCase) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
defer stub.HandleExit(t)
|
defer stub.HandleExit(t)
|
||||||
k := &kstub{panicDispatcher{}, stub.New(t, func(s *stub.Stub[syscallDispatcher]) syscallDispatcher { return &kstub{panicDispatcher{}, s} }, tc.want)}
|
|
||||||
|
uNotifyContext, uShimReader := make(chan struct{}), make(chan struct{})
|
||||||
|
k := &kstub{uNotifyContext, uShimReader, panicDispatcher{},
|
||||||
|
stub.New(t, func(s *stub.Stub[syscallDispatcher]) syscallDispatcher {
|
||||||
|
return &kstub{uNotifyContext, uShimReader, panicDispatcher{}, s}
|
||||||
|
}, tc.want)}
|
||||||
if err := tc.f(k); !reflect.DeepEqual(err, tc.wantErr) {
|
if err := tc.f(k); !reflect.DeepEqual(err, tc.wantErr) {
|
||||||
t.Errorf("%s: error = %#v, want %#v", fname, err, tc.wantErr)
|
t.Errorf("%s: error = %#v, want %#v", fname, err, tc.wantErr)
|
||||||
}
|
}
|
||||||
@ -312,6 +318,11 @@ func checkSimple(t *testing.T, fname string, testCases []simpleTestCase) {
|
|||||||
|
|
||||||
// kstub partially implements syscallDispatcher via [stub.Stub].
|
// kstub partially implements syscallDispatcher via [stub.Stub].
|
||||||
type kstub struct {
|
type kstub struct {
|
||||||
|
// notifyContext blocks on unblockNotifyContext if provided with a kstub.Stub track.
|
||||||
|
unblockNotifyContext chan struct{}
|
||||||
|
// stubTrackReader blocks on unblockShimReader if unblocking notifyContext.
|
||||||
|
unblockShimReader chan struct{}
|
||||||
|
|
||||||
panicDispatcher
|
panicDispatcher
|
||||||
*stub.Stub[syscallDispatcher]
|
*stub.Stub[syscallDispatcher]
|
||||||
}
|
}
|
||||||
@ -354,6 +365,19 @@ func (k *kstub) readdir(name string) ([]os.DirEntry, error) {
|
|||||||
stub.CheckArg(k.Stub, "name", name, 0))
|
stub.CheckArg(k.Stub, "name", name, 0))
|
||||||
}
|
}
|
||||||
func (k *kstub) tempdir() string { k.Helper(); return k.Expects("tempdir").Ret.(string) }
|
func (k *kstub) tempdir() string { k.Helper(); return k.Expects("tempdir").Ret.(string) }
|
||||||
|
func (k *kstub) exit(code int) {
|
||||||
|
k.Helper()
|
||||||
|
expect := k.Expects("exit")
|
||||||
|
|
||||||
|
if errors.Is(expect.Err, unblockNotifyContext) {
|
||||||
|
close(k.unblockNotifyContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !stub.CheckArg(k.Stub, "code", code, 0) {
|
||||||
|
k.FailNow()
|
||||||
|
}
|
||||||
|
panic(expect.Ret.(int))
|
||||||
|
}
|
||||||
func (k *kstub) evalSymlinks(path string) (string, error) {
|
func (k *kstub) evalSymlinks(path string) (string, error) {
|
||||||
k.Helper()
|
k.Helper()
|
||||||
expect := k.Expects("evalSymlinks")
|
expect := k.Expects("evalSymlinks")
|
||||||
@ -388,16 +412,17 @@ func (k *kstub) receive(key string, e any, fdp *uintptr) (closeFunc func() error
|
|||||||
|
|
||||||
func (k *kstub) expectCheckContainer(expect *stub.Call, z *container.Container) error {
|
func (k *kstub) expectCheckContainer(expect *stub.Call, z *container.Container) error {
|
||||||
k.Helper()
|
k.Helper()
|
||||||
err := expect.Error(
|
if !stub.CheckArgReflect(k.Stub, "params", &z.Params, 0) {
|
||||||
stub.CheckArgReflect(k.Stub, "params", &z.Params, 0))
|
|
||||||
if err != nil {
|
|
||||||
k.Errorf("params:\n%s\n%s", mustMarshal(&z.Params), mustMarshal(expect.Args[0]))
|
k.Errorf("params:\n%s\n%s", mustMarshal(&z.Params), mustMarshal(expect.Args[0]))
|
||||||
}
|
}
|
||||||
return err
|
return expect.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *kstub) containerStart(z *container.Container) error {
|
func (k *kstub) containerStart(z *container.Container) error {
|
||||||
k.Helper()
|
k.Helper()
|
||||||
|
if k.unblockShimReader != nil {
|
||||||
|
close(k.unblockShimReader)
|
||||||
|
}
|
||||||
return k.expectCheckContainer(k.Expects("containerStart"), z)
|
return k.expectCheckContainer(k.Expects("containerStart"), z)
|
||||||
}
|
}
|
||||||
func (k *kstub) containerServe(z *container.Container) error {
|
func (k *kstub) containerServe(z *container.Container) error {
|
||||||
@ -428,12 +453,25 @@ func (k *kstub) cmdOutput(cmd *exec.Cmd) ([]byte, error) {
|
|||||||
|
|
||||||
func (k *kstub) notifyContext(parent context.Context, signals ...os.Signal) (ctx context.Context, stop context.CancelFunc) {
|
func (k *kstub) notifyContext(parent context.Context, signals ...os.Signal) (ctx context.Context, stop context.CancelFunc) {
|
||||||
k.Helper()
|
k.Helper()
|
||||||
if k.Expects("notifyContext").Error(
|
expect := k.Expects("notifyContext")
|
||||||
|
|
||||||
|
if expect.Error(
|
||||||
stub.CheckArgReflect(k.Stub, "parent", parent, 0),
|
stub.CheckArgReflect(k.Stub, "parent", parent, 0),
|
||||||
stub.CheckArgReflect(k.Stub, "signals", signals, 1)) != nil {
|
stub.CheckArgReflect(k.Stub, "signals", signals, 1)) != nil {
|
||||||
k.FailNow()
|
k.FailNow()
|
||||||
}
|
}
|
||||||
return k.Context(), func() { k.Helper(); k.Expects("notifyContextStop") }
|
|
||||||
|
if sub, ok := expect.Ret.(int); ok && sub >= 0 {
|
||||||
|
subVal := reflect.ValueOf(k.Stub).Elem().FieldByName("sub")
|
||||||
|
ks := &kstub{nil, nil, panicDispatcher{}, reflect.
|
||||||
|
NewAt(subVal.Type(), unsafe.Pointer(subVal.UnsafeAddr())).Elem().
|
||||||
|
Interface().([]*stub.Stub[syscallDispatcher])[sub]}
|
||||||
|
|
||||||
|
<-k.unblockNotifyContext
|
||||||
|
return k.Context(), func() { k.Helper(); ks.Expects("notifyContextStop") }
|
||||||
|
}
|
||||||
|
|
||||||
|
return k.Context(), func() { panic("unexpected call to stop") }
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *kstub) mustHsuPath() *check.Absolute {
|
func (k *kstub) mustHsuPath() *check.Absolute {
|
||||||
@ -457,26 +495,51 @@ type stubTrackReader struct {
|
|||||||
*kstub
|
*kstub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unblockNotifyContext is passed via call and must be handled by stubTrackReader.Read
|
||||||
|
var unblockNotifyContext = errors.New("this error unblocks notifyContext and must not be returned")
|
||||||
|
|
||||||
func (r *stubTrackReader) Read(p []byte) (n int, err error) {
|
func (r *stubTrackReader) Read(p []byte) (n int, err error) {
|
||||||
r.subOnce.Do(func() {
|
r.subOnce.Do(func() {
|
||||||
subVal := reflect.ValueOf(r.kstub.Stub).Elem().FieldByName("sub")
|
subVal := reflect.ValueOf(r.kstub.Stub).Elem().FieldByName("sub")
|
||||||
r.kstub = &kstub{panicDispatcher{}, reflect.
|
r.kstub = &kstub{r.kstub.unblockNotifyContext, r.kstub.unblockShimReader, panicDispatcher{}, reflect.
|
||||||
NewAt(subVal.Type(), unsafe.Pointer(subVal.UnsafeAddr())).Elem().
|
NewAt(subVal.Type(), unsafe.Pointer(subVal.UnsafeAddr())).Elem().
|
||||||
Interface().([]*stub.Stub[syscallDispatcher])[r.sub]}
|
Interface().([]*stub.Stub[syscallDispatcher])[r.sub]}
|
||||||
})
|
})
|
||||||
|
|
||||||
return r.kstub.Read(p)
|
n, err = r.kstub.Read(p)
|
||||||
|
if errors.Is(err, unblockNotifyContext) {
|
||||||
|
err = nil
|
||||||
|
close(r.unblockNotifyContext)
|
||||||
|
<-r.unblockShimReader
|
||||||
|
}
|
||||||
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *kstub) setupContSignal(pid int) (io.ReadCloser, func(), error) {
|
func (k *kstub) setupContSignal(pid int) (io.ReadCloser, func(), error) {
|
||||||
k.Helper()
|
k.Helper()
|
||||||
expect := k.Expects("setupContSignal")
|
expect := k.Expects("setupContSignal")
|
||||||
return &stubTrackReader{sub: expect.Ret.(int), kstub: k}, func() { k.Expects("wKeepAlive") }, expect.Error(
|
return &stubTrackReader{sub: expect.Ret.(int), kstub: k}, func() { k.Helper(); k.Expects("wKeepAlive") }, expect.Error(
|
||||||
stub.CheckArg(k.Stub, "pid", pid, 0))
|
stub.CheckArg(k.Stub, "pid", pid, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *kstub) getMsg() message.Msg { k.Helper(); k.Expects("getMsg"); return k }
|
func (k *kstub) getMsg() message.Msg { k.Helper(); k.Expects("getMsg"); return k }
|
||||||
|
|
||||||
|
func (k *kstub) fatal(v ...any) {
|
||||||
|
if k.Expects("fatal").Error(
|
||||||
|
stub.CheckArgReflect(k.Stub, "v", v, 0)) != nil {
|
||||||
|
k.FailNow()
|
||||||
|
}
|
||||||
|
panic(stub.PanicExit)
|
||||||
|
}
|
||||||
|
func (k *kstub) fatalf(format string, v ...any) {
|
||||||
|
if k.Expects("fatalf").Error(
|
||||||
|
stub.CheckArg(k.Stub, "format", format, 0),
|
||||||
|
stub.CheckArgReflect(k.Stub, "v", v, 1)) != nil {
|
||||||
|
k.FailNow()
|
||||||
|
}
|
||||||
|
panic(stub.PanicExit)
|
||||||
|
}
|
||||||
|
|
||||||
func (k *kstub) Close() error { k.Helper(); return k.Expects("rcClose").Err }
|
func (k *kstub) Close() error { k.Helper(); return k.Expects("rcClose").Err }
|
||||||
func (k *kstub) Read(p []byte) (n int, err error) {
|
func (k *kstub) Read(p []byte) (n int, err error) {
|
||||||
k.Helper()
|
k.Helper()
|
||||||
|
|||||||
@ -93,7 +93,7 @@ func shimEntrypoint(k syscallDispatcher) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := k.setDumpable(container.SUID_DUMP_DISABLE); err != nil {
|
if err := k.setDumpable(container.SUID_DUMP_DISABLE); err != nil {
|
||||||
k.fatalf("cannot set SUID_DUMP_DISABLE: %s", err)
|
k.fatalf("cannot set SUID_DUMP_DISABLE: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -114,11 +114,8 @@ func shimEntrypoint(k syscallDispatcher) {
|
|||||||
closeSetup = f
|
closeSetup = f
|
||||||
|
|
||||||
if err = state.populateLocal(k, msg); err != nil {
|
if err = state.populateLocal(k, msg); err != nil {
|
||||||
if m, ok := message.GetMessage(err); ok {
|
printMessageError(func(v ...any) { k.fatal(fmt.Sprintln(v...)) },
|
||||||
k.fatal(m)
|
"cannot populate local state:", err)
|
||||||
} else {
|
|
||||||
k.fatalf("cannot populate local state: %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +135,6 @@ func shimEntrypoint(k syscallDispatcher) {
|
|||||||
k.fatalf("cannot set up exit request: %v", err)
|
k.fatalf("cannot set up exit request: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
defer wKeepAlive()
|
defer wKeepAlive()
|
||||||
signalPipe = r
|
signalPipe = r
|
||||||
@ -152,15 +148,12 @@ func shimEntrypoint(k syscallDispatcher) {
|
|||||||
stateParams := state.newParams()
|
stateParams := state.newParams()
|
||||||
for _, op := range state.Shim.Ops {
|
for _, op := range state.Shim.Ops {
|
||||||
if err := op.toContainer(stateParams); err != nil {
|
if err := op.toContainer(stateParams); err != nil {
|
||||||
if m, ok := message.GetMessage(err); ok {
|
printMessageError(func(v ...any) { k.fatal(fmt.Sprintln(v...)) },
|
||||||
k.fatal(m)
|
"cannot create container state:", err)
|
||||||
} else {
|
|
||||||
k.fatalf("cannot create container state: %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if stateParams.params.Ops == nil { // unreachable
|
if stateParams.params.Ops == nil { // only reachable with corrupted outcomeState
|
||||||
k.fatal("invalid container params")
|
k.fatal("invalid container state")
|
||||||
}
|
}
|
||||||
|
|
||||||
// shim exit outcomes
|
// shim exit outcomes
|
||||||
@ -226,7 +219,8 @@ func shimEntrypoint(k syscallDispatcher) {
|
|||||||
k.exit(hst.ExitFailure)
|
k.exit(hst.ExitFailure)
|
||||||
}
|
}
|
||||||
if err := k.containerServe(z); err != nil {
|
if err := k.containerServe(z); err != nil {
|
||||||
printMessageError(func(v ...any) { k.fatal(fmt.Sprintln(v...)) }, "cannot configure container:", err)
|
printMessageError(func(v ...any) { k.fatal(fmt.Sprintln(v...)) },
|
||||||
|
"cannot configure container:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := k.seccompLoad(
|
if err := k.seccompLoad(
|
||||||
|
|||||||
@ -106,8 +106,8 @@ func TestShimEntrypoint(t *testing.T) {
|
|||||||
Remount(fhs.AbsRoot, syscall.MS_RDONLY),
|
Remount(fhs.AbsRoot, syscall.MS_RDONLY),
|
||||||
}
|
}
|
||||||
|
|
||||||
templateState := outcomeState{
|
newShimParams := func() *shimParams {
|
||||||
Shim: &shimParams{PrivPID: 0xbad, WaitDelay: 0xf, Verbose: true, Ops: []outcomeOp{
|
return &shimParams{PrivPID: 0xbad, WaitDelay: 0xf, Verbose: true, Ops: []outcomeOp{
|
||||||
&spParamsOp{"xterm-256color", true},
|
&spParamsOp{"xterm-256color", true},
|
||||||
&spRuntimeOp{sessionTypeWayland},
|
&spRuntimeOp{sessionTypeWayland},
|
||||||
spTmpdirOp{},
|
spTmpdirOp{},
|
||||||
@ -116,8 +116,11 @@ func TestShimEntrypoint(t *testing.T) {
|
|||||||
&spPulseOp{(*[pulseCookieSizeMax]byte)(bytes.Repeat([]byte{0}, pulseCookieSizeMax)), pulseCookieSizeMax},
|
&spPulseOp{(*[pulseCookieSizeMax]byte)(bytes.Repeat([]byte{0}, pulseCookieSizeMax)), pulseCookieSizeMax},
|
||||||
&spDBusOp{true},
|
&spDBusOp{true},
|
||||||
&spFilesystemOp{},
|
&spFilesystemOp{},
|
||||||
}},
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
templateState := outcomeState{
|
||||||
|
Shim: newShimParams(),
|
||||||
ID: &checkExpectInstanceId,
|
ID: &checkExpectInstanceId,
|
||||||
Identity: hst.IdentityMax,
|
Identity: hst.IdentityMax,
|
||||||
UserID: 10,
|
UserID: 10,
|
||||||
@ -128,6 +131,333 @@ func TestShimEntrypoint(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkSimple(t, "shimEntrypoint", []simpleTestCase{
|
checkSimple(t, "shimEntrypoint", []simpleTestCase{
|
||||||
|
{"dumpable", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
||||||
|
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, new(log.Logger), nil),
|
||||||
|
call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, stub.UniqueError(11)),
|
||||||
|
call("fatalf", stub.ExpectArgs{"cannot set SUID_DUMP_DISABLE: %v", []any{stub.UniqueError(11)}}, nil, nil),
|
||||||
|
}}, nil},
|
||||||
|
|
||||||
|
{"receive fd", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
||||||
|
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
||||||
|
call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil),
|
||||||
|
call("receive", stub.ExpectArgs{"HAKUREI_SHIM", outcomeState{}, nil}, nil, syscall.EBADF),
|
||||||
|
call("fatal", stub.ExpectArgs{[]any{"invalid config descriptor"}}, nil, nil),
|
||||||
|
}}, nil},
|
||||||
|
|
||||||
|
{"receive env", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
||||||
|
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
||||||
|
call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil),
|
||||||
|
call("receive", stub.ExpectArgs{"HAKUREI_SHIM", outcomeState{}, nil}, nil, container.ErrReceiveEnv),
|
||||||
|
call("fatal", stub.ExpectArgs{[]any{"HAKUREI_SHIM not set"}}, nil, nil),
|
||||||
|
}}, nil},
|
||||||
|
|
||||||
|
{"receive strange", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
||||||
|
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
||||||
|
call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil),
|
||||||
|
call("receive", stub.ExpectArgs{"HAKUREI_SHIM", outcomeState{}, nil}, nil, stub.UniqueError(10)),
|
||||||
|
call("fatalf", stub.ExpectArgs{"cannot receive shim setup params: %v", []any{stub.UniqueError(10)}}, nil, nil),
|
||||||
|
}}, nil},
|
||||||
|
|
||||||
|
{"invalid state", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
||||||
|
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
||||||
|
call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil),
|
||||||
|
call("receive", stub.ExpectArgs{"HAKUREI_SHIM", func() outcomeState {
|
||||||
|
state := templateState
|
||||||
|
state.Shim = newShimParams()
|
||||||
|
state.Shim.PrivPID = 0
|
||||||
|
return state
|
||||||
|
}(), nil}, nil, nil),
|
||||||
|
call("swapVerbose", stub.ExpectArgs{true}, false, nil),
|
||||||
|
call("fatal", stub.ExpectArgs{[]any{"impossible outcome state reached\n"}}, nil, nil),
|
||||||
|
}}, nil},
|
||||||
|
|
||||||
|
{"sigaction pipe", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
||||||
|
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
||||||
|
call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil),
|
||||||
|
call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil),
|
||||||
|
call("swapVerbose", stub.ExpectArgs{true}, false, nil),
|
||||||
|
call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil),
|
||||||
|
call("setupContSignal", stub.ExpectArgs{0xbad}, 0, &os.SyscallError{Syscall: "pipe2", Err: stub.UniqueError(9)}),
|
||||||
|
call("fatal", stub.ExpectArgs{[]any{"pipe2: unique error 9 injected by the test suite"}}, nil, nil),
|
||||||
|
}}, nil},
|
||||||
|
|
||||||
|
{"sigaction cgo", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
||||||
|
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
||||||
|
call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil),
|
||||||
|
call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil),
|
||||||
|
call("swapVerbose", stub.ExpectArgs{true}, false, nil),
|
||||||
|
call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil),
|
||||||
|
call("setupContSignal", stub.ExpectArgs{0xbad}, 0, syscall.ENOTRECOVERABLE),
|
||||||
|
call("fatalf", stub.ExpectArgs{"cannot install SIGCONT handler: %v", []any{syscall.ENOTRECOVERABLE}}, nil, nil),
|
||||||
|
}}, nil},
|
||||||
|
|
||||||
|
{"sigaction strange", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
||||||
|
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
||||||
|
call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil),
|
||||||
|
call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil),
|
||||||
|
call("swapVerbose", stub.ExpectArgs{true}, false, nil),
|
||||||
|
call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil),
|
||||||
|
call("setupContSignal", stub.ExpectArgs{0xbad}, 0, stub.UniqueError(8)),
|
||||||
|
call("fatalf", stub.ExpectArgs{"cannot set up exit request: %v", []any{stub.UniqueError(8)}}, nil, nil),
|
||||||
|
}}, nil},
|
||||||
|
|
||||||
|
{"prctl", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
||||||
|
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
||||||
|
call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil),
|
||||||
|
call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil),
|
||||||
|
call("swapVerbose", stub.ExpectArgs{true}, false, nil),
|
||||||
|
call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil),
|
||||||
|
call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil),
|
||||||
|
call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, stub.UniqueError(7)),
|
||||||
|
call("fatalf", stub.ExpectArgs{"cannot set parent-death signal: %v", []any{stub.UniqueError(7)}}, nil, nil),
|
||||||
|
|
||||||
|
// deferred
|
||||||
|
call("wKeepAlive", stub.ExpectArgs{}, nil, nil),
|
||||||
|
}}, nil},
|
||||||
|
|
||||||
|
{"toContainer", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
||||||
|
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
||||||
|
call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil),
|
||||||
|
call("receive", stub.ExpectArgs{"HAKUREI_SHIM", func() outcomeState {
|
||||||
|
state := templateState
|
||||||
|
state.Shim = newShimParams()
|
||||||
|
state.Shim.Ops = []outcomeOp{errorOp(6)}
|
||||||
|
return state
|
||||||
|
}(), nil}, nil, nil),
|
||||||
|
call("swapVerbose", stub.ExpectArgs{true}, false, nil),
|
||||||
|
call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil),
|
||||||
|
call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil),
|
||||||
|
call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil),
|
||||||
|
call("fatal", stub.ExpectArgs{[]any{"cannot create container state: unique error 6 injected by the test suite\n"}}, nil, nil),
|
||||||
|
|
||||||
|
// deferred
|
||||||
|
call("wKeepAlive", stub.ExpectArgs{}, nil, nil),
|
||||||
|
}}, nil},
|
||||||
|
|
||||||
|
{"bad ops", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
||||||
|
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
||||||
|
call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil),
|
||||||
|
call("receive", stub.ExpectArgs{"HAKUREI_SHIM", func() outcomeState {
|
||||||
|
state := templateState
|
||||||
|
state.Shim = newShimParams()
|
||||||
|
state.Shim.Ops = nil
|
||||||
|
return state
|
||||||
|
}(), nil}, nil, nil),
|
||||||
|
call("swapVerbose", stub.ExpectArgs{true}, false, nil),
|
||||||
|
call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil),
|
||||||
|
call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil),
|
||||||
|
call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil),
|
||||||
|
call("fatal", stub.ExpectArgs{[]any{"invalid container state"}}, nil, nil),
|
||||||
|
|
||||||
|
// deferred
|
||||||
|
call("wKeepAlive", stub.ExpectArgs{}, nil, nil),
|
||||||
|
}}, nil},
|
||||||
|
|
||||||
|
{"start", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
||||||
|
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
||||||
|
call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil),
|
||||||
|
call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil),
|
||||||
|
call("swapVerbose", stub.ExpectArgs{true}, false, nil),
|
||||||
|
call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil),
|
||||||
|
call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil),
|
||||||
|
call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil),
|
||||||
|
call("New", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("closeReceive", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("notifyContext", stub.ExpectArgs{context.Background(), []os.Signal{os.Interrupt, syscall.SIGTERM}}, -1, nil),
|
||||||
|
call("containerStart", stub.ExpectArgs{templateParams}, nil, stub.UniqueError(5)),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
||||||
|
call("verbose", stub.ExpectArgs{[]any{"cannot start container: unique error 5 injected by the test suite\n"}}, nil, nil),
|
||||||
|
call("exit", stub.ExpectArgs{hst.ExitFailure}, stub.PanicExit, nil),
|
||||||
|
|
||||||
|
// deferred
|
||||||
|
call("wKeepAlive", stub.ExpectArgs{}, nil, nil),
|
||||||
|
}, Tracks: []stub.Expect{{Calls: []stub.Call{
|
||||||
|
call("rcRead", stub.ExpectArgs{}, nil, nil), // stub terminates this goroutine
|
||||||
|
}}}}, nil},
|
||||||
|
|
||||||
|
{"start logger signalread", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
||||||
|
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
||||||
|
call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil),
|
||||||
|
call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil),
|
||||||
|
call("swapVerbose", stub.ExpectArgs{true}, false, nil),
|
||||||
|
call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil),
|
||||||
|
call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil),
|
||||||
|
call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil),
|
||||||
|
call("New", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("closeReceive", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("notifyContext", stub.ExpectArgs{context.Background(), []os.Signal{os.Interrupt, syscall.SIGTERM}}, -1, nil),
|
||||||
|
call("containerStart", stub.ExpectArgs{templateParams}, nil, stub.UniqueError(5)),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, log.Default(), nil),
|
||||||
|
call("exit", stub.ExpectArgs{hst.ExitFailure}, stub.PanicExit, nil),
|
||||||
|
|
||||||
|
// deferred
|
||||||
|
call("wKeepAlive", stub.ExpectArgs{}, nil, nil),
|
||||||
|
}, Tracks: []stub.Expect{{Calls: []stub.Call{
|
||||||
|
call("rcRead", stub.ExpectArgs{}, []byte{}, stub.UniqueError(4)),
|
||||||
|
call("fatalf", stub.ExpectArgs{"cannot read from signal pipe: %v", []any{stub.UniqueError(4)}}, nil, nil),
|
||||||
|
}}}}, nil},
|
||||||
|
|
||||||
|
{"serve", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
||||||
|
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
||||||
|
call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil),
|
||||||
|
call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil),
|
||||||
|
call("swapVerbose", stub.ExpectArgs{true}, false, nil),
|
||||||
|
call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil),
|
||||||
|
call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil),
|
||||||
|
call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil),
|
||||||
|
call("New", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("closeReceive", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("notifyContext", stub.ExpectArgs{context.Background(), []os.Signal{os.Interrupt, syscall.SIGTERM}}, -1, nil),
|
||||||
|
call("containerStart", stub.ExpectArgs{templateParams}, nil, nil),
|
||||||
|
call("containerServe", stub.ExpectArgs{templateParams}, nil, stub.UniqueError(3)),
|
||||||
|
call("fatal", stub.ExpectArgs{[]any{"cannot configure container: unique error 3 injected by the test suite\n"}}, nil, nil),
|
||||||
|
|
||||||
|
// deferred
|
||||||
|
call("wKeepAlive", stub.ExpectArgs{}, nil, nil),
|
||||||
|
}, Tracks: []stub.Expect{{Calls: []stub.Call{
|
||||||
|
call("rcRead", stub.ExpectArgs{}, nil, nil), // stub terminates this goroutine
|
||||||
|
}}}}, nil},
|
||||||
|
|
||||||
|
{"seccomp", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
||||||
|
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
||||||
|
call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil),
|
||||||
|
call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil),
|
||||||
|
call("swapVerbose", stub.ExpectArgs{true}, false, nil),
|
||||||
|
call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil),
|
||||||
|
call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil),
|
||||||
|
call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil),
|
||||||
|
call("New", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("closeReceive", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("notifyContext", stub.ExpectArgs{context.Background(), []os.Signal{os.Interrupt, syscall.SIGTERM}}, -1, nil),
|
||||||
|
call("containerStart", stub.ExpectArgs{templateParams}, nil, nil),
|
||||||
|
call("containerServe", stub.ExpectArgs{templateParams}, nil, nil),
|
||||||
|
call("seccompLoad", stub.ExpectArgs{shimPreset, seccomp.AllowMultiarch}, nil, stub.UniqueError(2)),
|
||||||
|
call("fatalf", stub.ExpectArgs{"cannot load syscall filter: %v", []any{stub.UniqueError(2)}}, nil, nil),
|
||||||
|
|
||||||
|
// deferred
|
||||||
|
call("wKeepAlive", stub.ExpectArgs{}, nil, nil),
|
||||||
|
}, Tracks: []stub.Expect{{Calls: []stub.Call{
|
||||||
|
call("rcRead", stub.ExpectArgs{}, nil, nil), // stub terminates this goroutine
|
||||||
|
}}}}, nil},
|
||||||
|
|
||||||
|
{"exited closesetup earlyrequested", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
||||||
|
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
||||||
|
call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil),
|
||||||
|
call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil),
|
||||||
|
call("swapVerbose", stub.ExpectArgs{true}, false, nil),
|
||||||
|
call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil),
|
||||||
|
call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil),
|
||||||
|
call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil),
|
||||||
|
call("New", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("closeReceive", stub.ExpectArgs{}, nil, stub.UniqueError(1)),
|
||||||
|
call("verbosef", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(1)}}, nil, nil),
|
||||||
|
call("notifyContext", stub.ExpectArgs{context.Background(), []os.Signal{os.Interrupt, syscall.SIGTERM}}, 0, nil),
|
||||||
|
call("containerStart", stub.ExpectArgs{templateParams}, nil, nil),
|
||||||
|
call("containerServe", stub.ExpectArgs{templateParams}, nil, nil),
|
||||||
|
call("seccompLoad", stub.ExpectArgs{shimPreset, seccomp.AllowMultiarch}, nil, nil),
|
||||||
|
call("containerWait", stub.ExpectArgs{templateParams}, nil, makeExitError(1<<8)),
|
||||||
|
call("exit", stub.ExpectArgs{1}, stub.PanicExit, nil),
|
||||||
|
|
||||||
|
// deferred
|
||||||
|
call("wKeepAlive", stub.ExpectArgs{}, nil, nil),
|
||||||
|
}, Tracks: []stub.Expect{{Calls: []stub.Call{
|
||||||
|
call("rcRead", stub.ExpectArgs{}, []byte{shimMsgExitRequested}, nil),
|
||||||
|
call("exit", stub.ExpectArgs{hst.ExitRequest}, stub.PanicExit, unblockNotifyContext),
|
||||||
|
}}}}, nil},
|
||||||
|
|
||||||
|
{"exited requested", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
||||||
|
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
||||||
|
call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil),
|
||||||
|
call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil),
|
||||||
|
call("swapVerbose", stub.ExpectArgs{true}, false, nil),
|
||||||
|
call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil),
|
||||||
|
call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil),
|
||||||
|
call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil),
|
||||||
|
call("New", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("closeReceive", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("notifyContext", stub.ExpectArgs{context.Background(), []os.Signal{os.Interrupt, syscall.SIGTERM}}, 0, nil),
|
||||||
|
call("containerStart", stub.ExpectArgs{templateParams}, nil, nil),
|
||||||
|
call("containerServe", stub.ExpectArgs{templateParams}, nil, nil),
|
||||||
|
call("seccompLoad", stub.ExpectArgs{shimPreset, seccomp.AllowMultiarch}, nil, nil),
|
||||||
|
call("containerWait", stub.ExpectArgs{templateParams}, nil, makeExitError(1<<8)),
|
||||||
|
call("exit", stub.ExpectArgs{1}, stub.PanicExit, nil),
|
||||||
|
|
||||||
|
// deferred
|
||||||
|
call("wKeepAlive", stub.ExpectArgs{}, nil, nil),
|
||||||
|
}, Tracks: []stub.Expect{{Calls: []stub.Call{
|
||||||
|
call("rcRead", stub.ExpectArgs{}, []byte{shimMsgExitRequested}, unblockNotifyContext),
|
||||||
|
call("notifyContextStop", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("rcRead", stub.ExpectArgs{}, nil, nil), // stub terminates this goroutine
|
||||||
|
}}}}, nil},
|
||||||
|
|
||||||
|
{"canceled orphaned", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
||||||
|
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
||||||
|
call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil),
|
||||||
|
call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil),
|
||||||
|
call("swapVerbose", stub.ExpectArgs{true}, false, nil),
|
||||||
|
call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil),
|
||||||
|
call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil),
|
||||||
|
call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil),
|
||||||
|
call("New", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("closeReceive", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("notifyContext", stub.ExpectArgs{context.Background(), []os.Signal{os.Interrupt, syscall.SIGTERM}}, -1, nil),
|
||||||
|
call("containerStart", stub.ExpectArgs{templateParams}, nil, nil),
|
||||||
|
call("containerServe", stub.ExpectArgs{templateParams}, nil, nil),
|
||||||
|
call("seccompLoad", stub.ExpectArgs{shimPreset, seccomp.AllowMultiarch}, nil, nil),
|
||||||
|
call("containerWait", stub.ExpectArgs{templateParams}, nil, context.Canceled),
|
||||||
|
call("exit", stub.ExpectArgs{hst.ExitCancel}, stub.PanicExit, nil),
|
||||||
|
|
||||||
|
// deferred
|
||||||
|
call("wKeepAlive", stub.ExpectArgs{}, nil, nil),
|
||||||
|
}, Tracks: []stub.Expect{{Calls: []stub.Call{
|
||||||
|
call("rcRead", stub.ExpectArgs{}, []byte{shimMsgOrphaned}, nil),
|
||||||
|
call("exit", stub.ExpectArgs{hst.ExitOrphan}, stub.PanicExit, nil),
|
||||||
|
}}}}, nil},
|
||||||
|
|
||||||
|
{"strangewait invalidmsg", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
||||||
|
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
||||||
|
call("setDumpable", stub.ExpectArgs{uintptr(container.SUID_DUMP_DISABLE)}, nil, nil),
|
||||||
|
call("receive", stub.ExpectArgs{"HAKUREI_SHIM", templateState, nil}, nil, nil),
|
||||||
|
call("swapVerbose", stub.ExpectArgs{true}, false, nil),
|
||||||
|
call("verbosef", stub.ExpectArgs{"process share directory at %q, runtime directory at %q", []any{m("/tmp/hakurei.10"), m("/run/user/1000/hakurei")}}, nil, nil),
|
||||||
|
call("setupContSignal", stub.ExpectArgs{0xbad}, 0, nil),
|
||||||
|
call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil),
|
||||||
|
call("New", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("closeReceive", stub.ExpectArgs{}, nil, nil),
|
||||||
|
call("notifyContext", stub.ExpectArgs{context.Background(), []os.Signal{os.Interrupt, syscall.SIGTERM}}, -1, nil),
|
||||||
|
call("containerStart", stub.ExpectArgs{templateParams}, nil, nil),
|
||||||
|
call("containerServe", stub.ExpectArgs{templateParams}, nil, nil),
|
||||||
|
call("seccompLoad", stub.ExpectArgs{shimPreset, seccomp.AllowMultiarch}, nil, nil),
|
||||||
|
call("containerWait", stub.ExpectArgs{templateParams}, nil, stub.UniqueError(0)),
|
||||||
|
call("verbosef", stub.ExpectArgs{"cannot wait: %v", []any{stub.UniqueError(0)}}, nil, nil),
|
||||||
|
call("exit", stub.ExpectArgs{127}, stub.PanicExit, nil),
|
||||||
|
|
||||||
|
// deferred
|
||||||
|
call("wKeepAlive", stub.ExpectArgs{}, nil, nil),
|
||||||
|
}, Tracks: []stub.Expect{{Calls: []stub.Call{
|
||||||
|
call("rcRead", stub.ExpectArgs{}, []byte{0xff}, nil),
|
||||||
|
call("fatalf", stub.ExpectArgs{"got invalid message %d from signal handler", []any{byte(0xff)}}, nil, nil),
|
||||||
|
}}}}, nil},
|
||||||
|
|
||||||
{"success", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
{"success", func(k *kstub) error { shimEntrypoint(k); return nil }, stub.Expect{Calls: []stub.Call{
|
||||||
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
call("getMsg", stub.ExpectArgs{}, nil, nil),
|
||||||
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
call("getLogger", stub.ExpectArgs{}, (*log.Logger)(nil), nil),
|
||||||
@ -139,7 +469,7 @@ func TestShimEntrypoint(t *testing.T) {
|
|||||||
call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil),
|
call("prctl", stub.ExpectArgs{uintptr(syscall.PR_SET_PDEATHSIG), uintptr(syscall.SIGCONT), uintptr(0)}, nil, nil),
|
||||||
call("New", stub.ExpectArgs{}, nil, nil),
|
call("New", stub.ExpectArgs{}, nil, nil),
|
||||||
call("closeReceive", stub.ExpectArgs{}, nil, nil),
|
call("closeReceive", stub.ExpectArgs{}, nil, nil),
|
||||||
call("notifyContext", stub.ExpectArgs{context.Background(), []os.Signal{os.Interrupt, syscall.SIGTERM}}, nil, nil),
|
call("notifyContext", stub.ExpectArgs{context.Background(), []os.Signal{os.Interrupt, syscall.SIGTERM}}, -1, nil),
|
||||||
call("containerStart", stub.ExpectArgs{templateParams}, nil, nil),
|
call("containerStart", stub.ExpectArgs{templateParams}, nil, nil),
|
||||||
call("containerServe", stub.ExpectArgs{templateParams}, nil, nil),
|
call("containerServe", stub.ExpectArgs{templateParams}, nil, nil),
|
||||||
call("seccompLoad", stub.ExpectArgs{shimPreset, seccomp.AllowMultiarch}, nil, nil),
|
call("seccompLoad", stub.ExpectArgs{shimPreset, seccomp.AllowMultiarch}, nil, nil),
|
||||||
@ -156,3 +486,9 @@ func TestShimEntrypoint(t *testing.T) {
|
|||||||
}}}}, nil},
|
}}}}, nil},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// errorOp implements a noop outcomeOp that unconditionally returns [stub.UniqueError].
|
||||||
|
type errorOp stub.UniqueError
|
||||||
|
|
||||||
|
func (e errorOp) toSystem(*outcomeStateSys) error { return stub.UniqueError(e) }
|
||||||
|
func (e errorOp) toContainer(*outcomeStateParams) error { return stub.UniqueError(e) }
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user