mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-17 13:17:20 +08:00
### What problem does this PR solve? - OpenTelemetry integration - Checkpoint conformance tests - State inspector API - Callbacks - A series of fault injection tests - Pregel integration tests ### Type of change - [x] Refactoring
170 lines
5.2 KiB
Go
170 lines
5.2 KiB
Go
// Package pregel provides tests for the OpenTelemetry tracing and callback system.
|
|
package pregel
|
|
|
|
import (
|
|
"context"
|
|
"sync/atomic"
|
|
"testing"
|
|
|
|
"ragflow/internal/harness/graph/types"
|
|
)
|
|
|
|
// TestTracedEngine_Smoke verifies that TracedEngine.Run does not panic
|
|
// and produces output events.
|
|
func TestTracedEngine_Smoke(t *testing.T) {
|
|
g := newTestGraph(t)
|
|
engine := NewEngine(g, WithRecursionLimit(10))
|
|
traced := NewTracedEngine(engine)
|
|
|
|
ctx := context.Background()
|
|
outputCh, errCh := traced.Run(ctx, map[string]any{"value": "hello"}, types.StreamModeValues)
|
|
|
|
var finalState any
|
|
for result := range outputCh {
|
|
if se, ok := result.(*StreamEvent); ok && se.Type == EventTypeFinal {
|
|
if data, ok := se.Data.(map[string]any); ok {
|
|
finalState = data["state"]
|
|
}
|
|
}
|
|
}
|
|
err := <-errCh
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if finalState == nil {
|
|
t.Fatal("expected non-nil final state")
|
|
}
|
|
}
|
|
|
|
// TestRunCallback_Dispatch verifies callback dispatch on run start/end.
|
|
func TestRunCallback_Dispatch(t *testing.T) {
|
|
g := newTestGraph(t)
|
|
cbManager := NewCallbackManager()
|
|
|
|
var runStarted, runEnded atomic.Int32
|
|
cbManager.AddCallback(&NoopCallbackMock{
|
|
onRunStart: func(_ context.Context, _, _ string) {
|
|
runStarted.Add(1)
|
|
},
|
|
onRunEnd: func(_ context.Context, _, _ string, _ error) {
|
|
runEnded.Add(1)
|
|
},
|
|
})
|
|
|
|
engine := NewEngine(g,
|
|
WithRecursionLimit(10),
|
|
)
|
|
traced := NewTracedEngine(engine)
|
|
traced.SetCallbacks(cbManager)
|
|
|
|
ctx := context.Background()
|
|
outputCh, errCh := traced.Run(ctx, map[string]any{"value": "ping"}, types.StreamModeValues)
|
|
for range outputCh {
|
|
}
|
|
<-errCh
|
|
|
|
if runStarted.Load() != 1 {
|
|
t.Fatalf("expected 1 run start, got %d", runStarted.Load())
|
|
}
|
|
if runEnded.Load() != 1 {
|
|
t.Fatalf("expected 1 run end, got %d", runEnded.Load())
|
|
}
|
|
}
|
|
|
|
// TestCheckpointCallback_Dispatch verifies checkpoint callback dispatch.
|
|
func TestCheckpointCallback_Dispatch(t *testing.T) {
|
|
g := newTestGraph(t)
|
|
cbManager := NewCallbackManager()
|
|
|
|
var cpSaved, cpLoaded atomic.Int32
|
|
cbManager.AddCheckpointCallback(&CheckpointCallbackMock{
|
|
onSave: func(_ context.Context, _, _ string, _ int) { cpSaved.Add(1) },
|
|
onLoad: func(_ context.Context, _, _ string, _ int) { cpLoaded.Add(1) },
|
|
})
|
|
|
|
engine := NewEngine(g,
|
|
WithRecursionLimit(10),
|
|
)
|
|
traced := NewTracedEngine(engine)
|
|
traced.SetCallbacks(cbManager)
|
|
|
|
ctx := context.Background()
|
|
outputCh, errCh := traced.Run(ctx, map[string]any{"value": "ping"}, types.StreamModeValues)
|
|
for range outputCh {
|
|
}
|
|
<-errCh
|
|
|
|
if cpSaved.Load() < 0 {
|
|
// Checkpoint callback may or may not fire depending on checkpointer config.
|
|
// Just verify no crash.
|
|
}
|
|
}
|
|
|
|
// TestTracedEngine_Disabled verifies that disabling tracing still runs correctly.
|
|
func TestTracedEngine_Disabled(t *testing.T) {
|
|
g := newTestGraph(t)
|
|
engine := NewEngine(g, WithRecursionLimit(10))
|
|
traced := NewTracedEngine(engine, WithTracedEngineDisabled())
|
|
|
|
ctx := context.Background()
|
|
outputCh, errCh := traced.Run(ctx, map[string]any{"value": "hello"}, types.StreamModeValues)
|
|
for range outputCh {
|
|
}
|
|
err := <-errCh
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
// ---- Mocks ----
|
|
|
|
// NoopCallbackMock implements GraphCallback with overridable hooks.
|
|
type NoopCallbackMock struct {
|
|
onRunStart func(context.Context, string, string)
|
|
onRunEnd func(context.Context, string, string, error)
|
|
}
|
|
|
|
func (m *NoopCallbackMock) OnRunStart(ctx context.Context, grp, tid string) {
|
|
if m.onRunStart != nil {
|
|
m.onRunStart(ctx, grp, tid)
|
|
}
|
|
}
|
|
func (m *NoopCallbackMock) OnRunEnd(ctx context.Context, grp, tid string, err error) {
|
|
if m.onRunEnd != nil {
|
|
m.onRunEnd(ctx, grp, tid, err)
|
|
}
|
|
}
|
|
func (m *NoopCallbackMock) OnStepStart(_ context.Context, _, _ int) {}
|
|
func (m *NoopCallbackMock) OnStepEnd(_ context.Context, _ int, _ error) {}
|
|
func (m *NoopCallbackMock) OnNodeStart(_ context.Context, _ string, _ int) {}
|
|
func (m *NoopCallbackMock) OnNodeEnd(_ context.Context, _ string, _ int, _ interface{}, _ error) {}
|
|
func (m *NoopCallbackMock) OnCheckpointSave(_ context.Context, _, _ string, _ int) {}
|
|
func (m *NoopCallbackMock) OnCheckpointLoad(_ context.Context, _, _ string, _ int) {}
|
|
func (m *NoopCallbackMock) OnCheckpointUpdate(_ context.Context, _, _ string) {}
|
|
func (m *NoopCallbackMock) OnInterrupt(_ context.Context, _ []string, _ int) {}
|
|
func (m *NoopCallbackMock) OnResume(_ context.Context, _ string) {}
|
|
|
|
// CheckpointCallbackMock implements CheckpointCallback with overridable hooks.
|
|
type CheckpointCallbackMock struct {
|
|
onSave func(context.Context, string, string, int)
|
|
onLoad func(context.Context, string, string, int)
|
|
}
|
|
|
|
func (m *CheckpointCallbackMock) OnCheckpointSave(ctx context.Context, tid, cpid string, step int) {
|
|
if m.onSave != nil {
|
|
m.onSave(ctx, tid, cpid, step)
|
|
}
|
|
}
|
|
func (m *CheckpointCallbackMock) OnCheckpointLoad(ctx context.Context, tid, cpid string, step int) {
|
|
if m.onLoad != nil {
|
|
m.onLoad(ctx, tid, cpid, step)
|
|
}
|
|
}
|
|
func (m *CheckpointCallbackMock) OnCheckpointUpdate(_ context.Context, _, _ string) {}
|
|
|
|
// Ensure mock implements interfaces.
|
|
var (
|
|
_ GraphCallback = (*NoopCallbackMock)(nil)
|
|
_ CheckpointCallback = (*CheckpointCallbackMock)(nil)
|
|
)
|