iop/apps/node/internal/node/provider_tunnel_liveness_test.go
toki fef1f7a9dc feat(liveness): provider 실행 stall 관측을 구현한다
Node의 provider progress 기반 stall timeout, watchdog fencing과 bounded health probe evidence를 실행 경로에 반영한다. Edge-Node 계약과 구현 스펙, 테스트 및 Milestone 완료 evidence를 현재 상태와 맞춘다.
2026-08-05 09:45:14 +09:00

54 lines
1.9 KiB
Go

package node_test
import (
"context"
"testing"
"time"
toki "git.toki-labs.com/toki/proto-socket/go"
"google.golang.org/protobuf/proto"
runtime "iop/packages/go/execution"
iop "iop/proto/gen/iop"
)
// TestNodeSuccessfulTunnelFramesCarryNoHealthEvidence proves health evidence and
// the connection-scoped observation sequence are confined to the stall terminal:
// a successful tunnel over a bound session emits no frame carrying stall/health
// metadata.
func TestNodeSuccessfulTunnelFramesCarryNoHealthEvidence(t *testing.T) {
mta := &mockTunnelAdapter{t: t, expectedReq: runtime.ProviderTunnelRequest{RunID: "run-health-scope", TunnelID: "tunnel-health-scope"}}
router := &fixedRouter{adapterName: "openai_compat", adapters: map[string]runtime.Provider{"openai_compat": mta}}
n, _ := makeNode(t, router)
edgeSide, sess := buildSessionTestPipeForNode(t)
frames := make(chan *iop.ProviderTunnelFrame, 8)
toki.AddListenerTyped[*iop.ProviderTunnelFrame](&edgeSide.Communicator, func(tf *iop.ProviderTunnelFrame) {
frames <- proto.Clone(tf).(*iop.ProviderTunnelFrame)
})
if err := n.OnProviderTunnelRequest(context.Background(), sess, &iop.ProviderTunnelRequest{
RunId: "run-health-scope", TunnelId: "tunnel-health-scope", Adapter: "openai_compat", Target: "qwen", Method: "POST", Path: "/v1/chat/completions",
}); err != nil {
t.Fatalf("tunnel: %v", err)
}
stallKeys := []string{"provider_health", "liveness_classification", "health_observation_seq", "attempt_fence", "failure_code"}
deadline := time.After(2 * time.Second)
for {
select {
case tf := <-frames:
meta := tf.GetMetadata()
for _, key := range stallKeys {
if _, present := meta[key]; present {
t.Fatalf("successful tunnel frame leaked stall/health key %q: %#v", key, meta)
}
}
if tf.GetKind() == iop.ProviderTunnelFrameKind_PROVIDER_TUNNEL_FRAME_KIND_END {
return
}
case <-deadline:
t.Fatal("terminal END frame was not observed")
}
}
}