go/task_test.go
Snider 028ec84c5e fix: remove type Task any — untyped IPC replaced by named Actions
The old IPC Task system passed `any` through TaskHandler and
PerformAsync. Now that named Actions exist with typed signatures
(ActionHandler func(context.Context, Options) Result), the untyped
layer is dead weight.

Changes:
- type Task any removed (was in contract.go)
- type Task struct is now the composed sequence (action.go)
- PerformAsync takes (action string, opts Options) not (t Task)
- TaskHandler type removed — use c.Action("name", handler)
- RegisterTask removed — use c.Action("name", handler)
- PERFORM sugar removed — use c.Action("name").Run()
- ActionTaskStarted/Progress/Completed carry typed fields
  (Action string, Options, Result) not any

ActionDef → Action rename also in this commit (same principle:
DTOs don't have Run() methods).

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-25 15:57:36 +00:00

127 lines
2.8 KiB
Go

package core_test
import (
"context"
"sync"
"testing"
"time"
. "dappco.re/go/core"
"github.com/stretchr/testify/assert"
)
// --- PerformAsync ---
func TestTask_PerformAsync_Good(t *testing.T) {
c := New()
var mu sync.Mutex
var result string
c.Action("work", func(_ context.Context, _ Options) Result {
mu.Lock()
result = "done"
mu.Unlock()
return Result{Value: "done", OK: true}
})
r := c.PerformAsync("work", NewOptions())
assert.True(t, r.OK)
assert.True(t, HasPrefix(r.Value.(string), "id-"), "should return task ID")
time.Sleep(100 * time.Millisecond)
mu.Lock()
assert.Equal(t, "done", result)
mu.Unlock()
}
func TestTask_PerformAsync_Good_Progress(t *testing.T) {
c := New()
c.Action("tracked", func(_ context.Context, _ Options) Result {
return Result{OK: true}
})
r := c.PerformAsync("tracked", NewOptions())
taskID := r.Value.(string)
c.Progress(taskID, 0.5, "halfway", "tracked")
}
func TestTask_PerformAsync_Good_Completion(t *testing.T) {
c := New()
completed := make(chan ActionTaskCompleted, 1)
c.Action("completable", func(_ context.Context, _ Options) Result {
return Result{Value: "output", OK: true}
})
c.RegisterAction(func(_ *Core, msg Message) Result {
if evt, ok := msg.(ActionTaskCompleted); ok {
completed <- evt
}
return Result{OK: true}
})
c.PerformAsync("completable", NewOptions())
select {
case evt := <-completed:
assert.True(t, evt.Result.OK)
assert.Equal(t, "output", evt.Result.Value)
case <-time.After(2 * time.Second):
t.Fatal("timed out waiting for completion")
}
}
func TestTask_PerformAsync_Bad_ActionNotRegistered(t *testing.T) {
c := New()
completed := make(chan ActionTaskCompleted, 1)
c.RegisterAction(func(_ *Core, msg Message) Result {
if evt, ok := msg.(ActionTaskCompleted); ok {
completed <- evt
}
return Result{OK: true}
})
c.PerformAsync("nonexistent", NewOptions())
select {
case evt := <-completed:
assert.False(t, evt.Result.OK, "unregistered action should fail")
case <-time.After(2 * time.Second):
t.Fatal("timed out")
}
}
func TestTask_PerformAsync_Bad_AfterShutdown(t *testing.T) {
c := New()
c.Action("work", func(_ context.Context, _ Options) Result { return Result{OK: true} })
c.ServiceStartup(context.Background(), nil)
c.ServiceShutdown(context.Background())
r := c.PerformAsync("work", NewOptions())
assert.False(t, r.OK)
}
// --- RegisterAction + RegisterActions (broadcast handlers) ---
func TestTask_RegisterAction_Good(t *testing.T) {
c := New()
called := false
c.RegisterAction(func(_ *Core, _ Message) Result {
called = true
return Result{OK: true}
})
c.ACTION(nil)
assert.True(t, called)
}
func TestTask_RegisterActions_Good(t *testing.T) {
c := New()
count := 0
h := func(_ *Core, _ Message) Result { count++; return Result{OK: true} }
c.RegisterActions(h, h)
c.ACTION(nil)
assert.Equal(t, 2, count)
}