go/tests/ipc_test.go
Snider 8199727537 feat: restructure Core as unified struct with DTO pattern
Complete architectural overhaul of pkg/core:
- All subsystem types renamed to idiomatic Go (no stutter)
- Core struct: App, Embed, Fs, Config, ErrPan, ErrLog, Cli, Service, Lock, Ipc, I18n
- Exports consolidated in core.go, contracts/options in contract.go
- Service() unified get/register: c.Service(), c.Service("name"), c.Service("name", svc)
- Lock() named mutex map: c.Lock("srv"), c.Lock("ipc")
- Error system: Err/ErrLog/ErrPan + Log/LogErr/LogPan (shared ErrSink interface)
- CoreCommand with optional description (i18n resolves from command path)
- Tests moved to tests/ directory (black-box package core_test)
- Removed: ServiceFor/MustServiceFor, global instance, Display/Workspace/Crypt interfaces
- New files: app.go, fs.go, ipc.go, lock.go, i18n.go, task.go, runtime.go, contract.go

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-18 09:12:29 +00:00

121 lines
2.5 KiB
Go

package core_test
import (
. "forge.lthn.ai/core/go/pkg/core"
"errors"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
type IPCTestQuery struct{ Value string }
type IPCTestTask struct{ Value string }
func TestIPC_Query(t *testing.T) {
c, _ := New()
// No handler
res, handled, err := c.QUERY(IPCTestQuery{})
assert.False(t, handled)
assert.Nil(t, res)
assert.Nil(t, err)
// With handler
c.RegisterQuery(func(c *Core, q Query) (any, bool, error) {
if tq, ok := q.(IPCTestQuery); ok {
return tq.Value + "-response", true, nil
}
return nil, false, nil
})
res, handled, err = c.QUERY(IPCTestQuery{Value: "test"})
assert.True(t, handled)
assert.Nil(t, err)
assert.Equal(t, "test-response", res)
}
func TestIPC_QueryAll(t *testing.T) {
c, _ := New()
c.RegisterQuery(func(c *Core, q Query) (any, bool, error) {
return "h1", true, nil
})
c.RegisterQuery(func(c *Core, q Query) (any, bool, error) {
return "h2", true, nil
})
results, err := c.QUERYALL(IPCTestQuery{})
assert.Nil(t, err)
assert.Len(t, results, 2)
assert.Contains(t, results, "h1")
assert.Contains(t, results, "h2")
}
func TestIPC_Perform(t *testing.T) {
c, _ := New()
c.RegisterTask(func(c *Core, task Task) (any, bool, error) {
if tt, ok := task.(IPCTestTask); ok {
if tt.Value == "error" {
return nil, true, errors.New("task error")
}
return "done", true, nil
}
return nil, false, nil
})
// Success
res, handled, err := c.PERFORM(IPCTestTask{Value: "run"})
assert.True(t, handled)
assert.Nil(t, err)
assert.Equal(t, "done", res)
// Error
res, handled, err = c.PERFORM(IPCTestTask{Value: "error"})
assert.True(t, handled)
assert.Error(t, err)
assert.Nil(t, res)
}
func TestIPC_PerformAsync(t *testing.T) {
c, _ := New()
type AsyncResult struct {
TaskID string
Result any
Error error
}
done := make(chan AsyncResult, 1)
c.RegisterTask(func(c *Core, task Task) (any, bool, error) {
if tt, ok := task.(IPCTestTask); ok {
return tt.Value + "-done", true, nil
}
return nil, false, nil
})
c.RegisterAction(func(c *Core, msg Message) error {
if m, ok := msg.(ActionTaskCompleted); ok {
done <- AsyncResult{
TaskID: m.TaskID,
Result: m.Result,
Error: m.Error,
}
}
return nil
})
taskID := c.PerformAsync(IPCTestTask{Value: "async"})
assert.NotEmpty(t, taskID)
select {
case res := <-done:
assert.Equal(t, taskID, res.TaskID)
assert.Equal(t, "async-done", res.Result)
assert.Nil(t, res.Error)
case <-time.After(time.Second):
t.Fatal("timed out waiting for task completion")
}
}