molecule-core/workspace-server/internal/supervised/supervised_test.go
Hongming Wang 479a027e4b chore: open-source restructure — rename dirs, remove internal files, scrub secrets
Renames:
- platform/ → workspace-server/ (Go module path stays as "platform" for
  external dep compat — will update after plugin module republish)
- workspace-template/ → workspace/

Removed (moved to separate repos or deleted):
- PLAN.md — internal roadmap (move to private project board)
- HANDOFF.md, AGENTS.md — one-time internal session docs
- .claude/ — gitignored entirely (local agent config)
- infra/cloudflare-worker/ → Molecule-AI/molecule-tenant-proxy
- org-templates/molecule-dev/ → standalone template repo
- .mcp-eval/ → molecule-mcp-server repo
- test-results/ — ephemeral, gitignored

Security scrubbing:
- Cloudflare account/zone/KV IDs → placeholders
- Real EC2 IPs → <EC2_IP> in all docs
- CF token prefix, Neon project ID, Fly app names → redacted
- Langfuse dev credentials → parameterized
- Personal runner username/machine name → generic

Community files:
- CONTRIBUTING.md — build, test, branch conventions
- CODE_OF_CONDUCT.md — Contributor Covenant 2.1

All Dockerfiles, CI workflows, docker-compose, railway.toml, render.yaml,
README, CLAUDE.md updated for new directory names.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-18 00:24:44 -07:00

121 lines
3.0 KiB
Go

package supervised
import (
"context"
"sync/atomic"
"testing"
"time"
)
func TestRunWithRecover_CleanReturnDoesNotRestart(t *testing.T) {
var calls int32
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
done := make(chan struct{})
go func() {
RunWithRecover(ctx, "clean", func(c context.Context) {
atomic.AddInt32(&calls, 1)
// Return immediately — no panic, not blocked on ctx.
})
close(done)
}()
select {
case <-done:
case <-time.After(2 * time.Second):
t.Fatal("RunWithRecover did not return after clean fn exit")
}
if got := atomic.LoadInt32(&calls); got != 1 {
t.Errorf("fn called %d times on clean return; want 1", got)
}
}
func TestRunWithRecover_PanicRestartsWithBackoff(t *testing.T) {
var calls int32
ctx, cancel := context.WithCancel(context.Background())
go RunWithRecover(ctx, "panic-test", func(c context.Context) {
atomic.AddInt32(&calls, 1)
if atomic.LoadInt32(&calls) < 3 {
panic("deliberate")
}
// On 3rd call, wait for ctx.Done so we can inspect calls cleanly.
<-c.Done()
})
// Give it time to panic + restart at least twice (1s + 2s backoffs).
time.Sleep(4 * time.Second)
cancel()
got := atomic.LoadInt32(&calls)
if got < 3 {
t.Errorf("fn called %d times after 4s of restarts; want >= 3", got)
}
}
func TestRunWithRecover_CtxDoneStopsRestart(t *testing.T) {
var calls int32
ctx, cancel := context.WithCancel(context.Background())
done := make(chan struct{})
go func() {
RunWithRecover(ctx, "ctx-done", func(c context.Context) {
atomic.AddInt32(&calls, 1)
panic("always")
})
close(done)
}()
time.Sleep(100 * time.Millisecond)
cancel()
select {
case <-done:
case <-time.After(35 * time.Second):
t.Fatal("RunWithRecover did not return after ctx cancel")
}
}
func TestLivenessRegistry(t *testing.T) {
// Heartbeat records; LastTick reads back.
before := time.Now()
Heartbeat("testsubsys-A")
after := time.Now()
last := LastTick("testsubsys-A")
if last.Before(before) || last.After(after) {
t.Errorf("LastTick=%v outside [%v, %v]", last, before, after)
}
// Unknown subsystem → zero time.
if !LastTick("nonexistent-subsys").IsZero() {
t.Errorf("LastTick for unknown subsystem should be zero")
}
// IsHealthy: fresh heartbeat → healthy; stale → not healthy.
Heartbeat("testsubsys-B")
healthy, stale := IsHealthy([]string{"testsubsys-A", "testsubsys-B"}, time.Minute)
if !healthy || len(stale) != 0 {
t.Errorf("expected healthy, got healthy=%v stale=%v", healthy, stale)
}
// Force staleness by asking for an impossibly tight threshold.
time.Sleep(10 * time.Millisecond)
healthy, stale = IsHealthy([]string{"testsubsys-A"}, time.Nanosecond)
if healthy || len(stale) != 1 {
t.Errorf("expected stale testsubsys-A, got healthy=%v stale=%v", healthy, stale)
}
}
func TestSnapshotIsCopy(t *testing.T) {
Heartbeat("snap-test")
s1 := Snapshot()
// Mutating the returned map must not affect the registry.
s1["snap-test"] = time.Time{}
if LastTick("snap-test").IsZero() {
t.Errorf("Snapshot returned a live reference; should be a copy")
}
}