From 4e7aab07d5b175345fdf3ea08868dab1e6d90126 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Thu, 13 Nov 2025 01:15:19 +0900 Subject: internal/system: relocate from system These packages are highly specific to hakurei and are difficult to use safely from other pieces of code. Their exported symbols are made available until v0.4.0 where they will be removed for #24. Signed-off-by: Ophestra --- system/dispatcher_test.go | 379 ---------------------------------------------- 1 file changed, 379 deletions(-) delete mode 100644 system/dispatcher_test.go (limited to 'system/dispatcher_test.go') diff --git a/system/dispatcher_test.go b/system/dispatcher_test.go deleted file mode 100644 index fd6e5d09..00000000 --- a/system/dispatcher_test.go +++ /dev/null @@ -1,379 +0,0 @@ -package system - -import ( - "log" - "os" - "reflect" - "slices" - "testing" - "unsafe" - - "hakurei.app/container/stub" - "hakurei.app/hst" - "hakurei.app/system/acl" - "hakurei.app/system/dbus" - "hakurei.app/system/internal/xcb" -) - -// call initialises a [stub.Call]. -// This keeps composites analysis happy without making the test cases too bloated. -func call(name string, args stub.ExpectArgs, ret any, err error) stub.Call { - return stub.Call{Name: name, Args: args, Ret: ret, Err: err} -} - -type opBehaviourTestCase struct { - name string - uid int - ec hst.Enablement - op Op - - apply []stub.Call - wantErrApply error - - revert []stub.Call - wantErrRevert error -} - -func checkOpBehaviour(t *testing.T, testCases []opBehaviourTestCase) { - t.Helper() - - t.Run("behaviour", func(t *testing.T) { - t.Helper() - t.Parallel() - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - t.Helper() - t.Parallel() - - var ec *Criteria - if tc.ec != 0xff { - ec = (*Criteria)(&tc.ec) - } - - sys, s := InternalNew(t, stub.Expect{Calls: slices.Concat(tc.apply, []stub.Call{{Name: stub.CallSeparator}}, tc.revert)}, tc.uid) - defer stub.HandleExit(t) - errApply := tc.op.apply(sys) - s.Expects(stub.CallSeparator) - if !reflect.DeepEqual(errApply, tc.wantErrApply) { - t.Errorf("apply: error = %v, want %v", errApply, tc.wantErrApply) - } - if errApply != nil { - goto out - } - - if err := tc.op.revert(sys, ec); !reflect.DeepEqual(err, tc.wantErrRevert) { - t.Errorf("revert: error = %v, want %v", err, tc.wantErrRevert) - } - - out: - s.VisitIncomplete(func(s *stub.Stub[syscallDispatcher]) { - count := s.Pos() - 1 // separator - if count < len(tc.apply) { - t.Errorf("apply: %d calls, want %d", count, len(tc.apply)) - } else { - t.Errorf("revert: %d calls, want %d", count-len(tc.apply), len(tc.revert)) - } - }) - }) - } - }) -} - -type opsBuilderTestCase struct { - name string - uid int - f func(t *testing.T, sys *I) - want []Op - exp stub.Expect -} - -func checkOpsBuilder(t *testing.T, fname string, testCases []opsBuilderTestCase) { - t.Helper() - - t.Run("build", func(t *testing.T) { - t.Helper() - t.Parallel() - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - t.Helper() - t.Parallel() - - sys, s := InternalNew(t, tc.exp, tc.uid) - defer stub.HandleExit(t) - tc.f(t, sys) - s.VisitIncomplete(func(s *stub.Stub[syscallDispatcher]) { - t.Helper() - - t.Errorf("%s: %d calls, want %d", fname, s.Pos(), s.Len()) - }) - if !slices.EqualFunc(sys.ops, tc.want, func(op Op, v Op) bool { return op.Is(v) }) { - t.Errorf("ops: %#v, want %#v", sys.ops, tc.want) - } - }) - } - }) -} - -type opIsTestCase struct { - name string - op, v Op - want bool -} - -func checkOpIs(t *testing.T, testCases []opIsTestCase) { - t.Helper() - - t.Run("is", func(t *testing.T) { - t.Helper() - t.Parallel() - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - t.Helper() - t.Parallel() - - if got := tc.op.Is(tc.v); got != tc.want { - t.Errorf("Is: %v, want %v", got, tc.want) - } - }) - } - }) -} - -type opMetaTestCase struct { - name string - op Op - - wantType hst.Enablement - wantPath string - wantString string -} - -func checkOpMeta(t *testing.T, testCases []opMetaTestCase) { - t.Helper() - - t.Run("meta", func(t *testing.T) { - t.Helper() - t.Parallel() - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - t.Helper() - t.Parallel() - - t.Run("type", func(t *testing.T) { - t.Helper() - - if got := tc.op.Type(); got != tc.wantType { - t.Errorf("Type: %q, want %q", got, tc.wantType) - } - }) - - t.Run("path", func(t *testing.T) { - t.Helper() - - if got := tc.op.Path(); got != tc.wantPath { - t.Errorf("Path: %q, want %q", got, tc.wantPath) - } - }) - - t.Run("string", func(t *testing.T) { - t.Helper() - - if got := tc.op.String(); got != tc.wantString { - t.Errorf("String: %s, want %s", got, tc.wantString) - } - }) - }) - } - }) -} - -// InternalNew initialises [I] with a stub syscallDispatcher. -func InternalNew(t *testing.T, want stub.Expect, uid int) (*I, *stub.Stub[syscallDispatcher]) { - k := &kstub{stub.New(t, func(s *stub.Stub[syscallDispatcher]) syscallDispatcher { return &kstub{s} }, want)} - sys := New(t.Context(), k, uid) - sys.syscallDispatcher = k - return sys, k.Stub -} - -type kstub struct{ *stub.Stub[syscallDispatcher] } - -func (k *kstub) new(f func(k syscallDispatcher)) { k.Helper(); k.New(f) } - -func (k *kstub) stat(name string) (fi os.FileInfo, err error) { - k.Helper() - expect := k.Expects("stat") - err = expect.Error( - stub.CheckArg(k.Stub, "name", name, 0)) - if err == nil { - fi = expect.Ret.(os.FileInfo) - } - return -} - -func (k *kstub) open(name string) (f osFile, err error) { - k.Helper() - expect := k.Expects("open") - err = expect.Error( - stub.CheckArg(k.Stub, "name", name, 0)) - if err == nil { - f = expect.Ret.(osFile) - } - return -} - -func (k *kstub) mkdir(name string, perm os.FileMode) error { - k.Helper() - return k.Expects("mkdir").Error( - stub.CheckArg(k.Stub, "name", name, 0), - stub.CheckArg(k.Stub, "perm", perm, 1)) -} - -func (k *kstub) chmod(name string, mode os.FileMode) error { - k.Helper() - return k.Expects("chmod").Error( - stub.CheckArg(k.Stub, "name", name, 0), - stub.CheckArg(k.Stub, "mode", mode, 1)) -} - -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) println(v ...any) { - k.Helper() - k.Expects("println") - if !stub.CheckArgReflect(k.Stub, "v", v, 0) { - k.FailNow() - } -} - -func (k *kstub) aclUpdate(name string, uid int, perms ...acl.Perm) error { - k.Helper() - return k.Expects("aclUpdate").Error( - stub.CheckArg(k.Stub, "name", name, 0), - stub.CheckArg(k.Stub, "uid", uid, 1), - 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) dbusFinalise(sessionBus, systemBus dbus.ProxyPair, session, system *hst.BusConfig) (final *dbus.Final, err error) { - k.Helper() - expect := k.Expects("dbusFinalise") - - final = expect.Ret.(*dbus.Final) - err = expect.Error( - stub.CheckArg(k.Stub, "sessionBus", sessionBus, 0), - stub.CheckArg(k.Stub, "systemBus", systemBus, 1), - stub.CheckArgReflect(k.Stub, "session", session, 2), - stub.CheckArgReflect(k.Stub, "system", system, 3)) - if err != nil { - final = nil - } - return -} - -func (k *kstub) dbusProxyStart(proxy *dbus.Proxy) error { - k.Helper() - return k.dbusProxySCW(k.Expects("dbusProxyStart"), proxy) -} -func (k *kstub) dbusProxyClose(proxy *dbus.Proxy) { - k.Helper() - if k.dbusProxySCW(k.Expects("dbusProxyClose"), proxy) != nil { - k.Fail() - } -} -func (k *kstub) dbusProxyWait(proxy *dbus.Proxy) error { - k.Helper() - return k.dbusProxySCW(k.Expects("dbusProxyWait"), proxy) -} -func (k *kstub) dbusProxySCW(expect *stub.Call, proxy *dbus.Proxy) error { - k.Helper() - v := reflect.ValueOf(proxy).Elem() - - if ctxV := v.FieldByName("ctx"); ctxV.IsNil() { - k.Errorf("proxy: ctx = %s", ctxV.String()) - return os.ErrInvalid - } - - finalV := v.FieldByName("final") - if gotFinal := reflect.NewAt(finalV.Type(), unsafe.Pointer(finalV.UnsafeAddr())).Elem().Interface().(*dbus.Final); !reflect.DeepEqual(gotFinal, expect.Args[0]) { - k.Errorf("proxy: final = %#v, want %#v", gotFinal, expect.Args[0]) - return os.ErrInvalid - } - - outputV := v.FieldByName("output") - if _, ok := reflect.NewAt(outputV.Type(), unsafe.Pointer(outputV.UnsafeAddr())).Elem().Interface().(*linePrefixWriter); !ok { - k.Errorf("proxy: output = %s", outputV.String()) - return os.ErrInvalid - } - - return expect.Err -} - -func (k *kstub) GetLogger() *log.Logger { panic("unreachable") } - -func (k *kstub) IsVerbose() bool { k.Helper(); return k.Expects("isVerbose").Ret.(bool) } -func (k *kstub) SwapVerbose(verbose bool) bool { - k.Helper() - expect := k.Expects("swapVerbose") - if expect.Error( - stub.CheckArg(k.Stub, "verbose", verbose, 0)) != nil { - k.FailNow() - } - return expect.Ret.(bool) -} - -// ignoreValue marks a value to be ignored by the test suite. -type ignoreValue struct{} - -func (k *kstub) Verbose(v ...any) { - k.Helper() - expect := k.Expects("verbose") - - // translate ignores in v - if want, ok := expect.Args[0].([]any); ok && len(v) == len(want) { - for i, a := range want { - if _, ok = a.(ignoreValue); ok { - v[i] = ignoreValue{} - } - } - } - - if expect.Error( - stub.CheckArgReflect(k.Stub, "v", v, 0)) != nil { - k.FailNow() - } -} - -func (k *kstub) Verbosef(format string, v ...any) { - k.Helper() - if k.Expects("verbosef").Error( - stub.CheckArg(k.Stub, "format", format, 0), - stub.CheckArgReflect(k.Stub, "v", v, 1)) != nil { - k.FailNow() - } -} - -func (k *kstub) Suspend() bool { k.Helper(); return k.Expects("suspend").Ret.(bool) } -func (k *kstub) Resume() bool { k.Helper(); return k.Expects("resume").Ret.(bool) } -func (k *kstub) BeforeExit() { k.Helper(); k.Expects("beforeExit") } -- cgit v1.3.1