stemedb/sdk/go/adk/adk_test.go
jordan b3e8a9a058 feat: Multi-application expansion with chaos testing and community UI
Major additions:
- Community Next.js app (port 18187) for browsing claims with API docs
- stemedb-chaos crate: Fault injection, chaos testing, CRDT properties
- Latent ingestion system: Reddit/FDA ingesters with ADK-Go agents
- Disputed claims handling: Manual review workflows and validation
- Aphoria security scanner: New extractors (SQL injection, command
  injection, weak crypto, TLS version), policy-based ignores, UAT reports
- Docker infrastructure: Dockerfile, docker-compose.yml for full stack
- VulnBank demo: Intentionally vulnerable multi-language test corpus

SDK & API enhancements:
- Source registry handlers for tracking data provenance
- Metrics endpoint
- Skeptic filtering improvements

Code quality:
- Split 14 large files (>500 lines) into focused modules
- All files now under 500-line limit per project guidelines

Documentation:
- Chaos testing guide, circuit breakers, observability docs
- Phase 7 UAT documentation updates
- Martin Kleppmann technical writer agent

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 01:24:14 -07:00

216 lines
5.6 KiB
Go

package adk
import (
"context"
"encoding/json"
"testing"
"github.com/orchard9/stemedb-go/steme"
)
// mockClient implements EpistemeClient for testing
type mockClient struct {
queryFunc func(ctx context.Context, params steme.QueryParams) (*steme.QueryResult, error)
assertFunc func(ctx context.Context, assertion steme.Assertion) (string, error)
traceFunc func(ctx context.Context, params steme.TraceParams) (*steme.TraceResult, error)
supersedeFunc func(ctx context.Context, params steme.SupersedeParams) (*steme.SupersedeResult, error)
}
func (m *mockClient) Query(ctx context.Context, params steme.QueryParams) (*steme.QueryResult, error) {
if m.queryFunc != nil {
return m.queryFunc(ctx, params)
}
return &steme.QueryResult{}, nil
}
func (m *mockClient) Assert(ctx context.Context, assertion steme.Assertion) (string, error) {
if m.assertFunc != nil {
return m.assertFunc(ctx, assertion)
}
return "mock_hash", nil
}
func (m *mockClient) Trace(ctx context.Context, params steme.TraceParams) (*steme.TraceResult, error) {
if m.traceFunc != nil {
return m.traceFunc(ctx, params)
}
return &steme.TraceResult{}, nil
}
func (m *mockClient) Supersede(ctx context.Context, params steme.SupersedeParams) (*steme.SupersedeResult, error) {
if m.supersedeFunc != nil {
return m.supersedeFunc(ctx, params)
}
return &steme.SupersedeResult{
Status: "superseded",
TargetHash: params.TargetHash,
SupersessionType: params.SupersessionType,
Timestamp: 1704067200,
}, nil
}
func TestQueryTool(t *testing.T) {
// Mock client that returns a test assertion
client := &mockClient{
queryFunc: func(ctx context.Context, params steme.QueryParams) (*steme.QueryResult, error) {
lifecycle := steme.LifecycleApproved
return &steme.QueryResult{
Assertions: []steme.AssertionResponse{
{
Hash: "test_hash",
Subject: "Tesla_Inc",
Predicate: "has_revenue",
Object: steme.NewNumberValue(96.7),
Confidence: 0.95,
SourceHash: "source_hash",
Lifecycle: lifecycle,
},
},
TotalCount: 1,
HasMore: false,
}, nil
},
}
tool := NewQueryTool(client)
// Test basic query
input := QueryInput{
Subject: "Tesla_Inc",
Predicate: "has_revenue",
Lens: "consensus",
}
inputBytes, err := json.Marshal(input)
if err != nil {
t.Fatalf("failed to marshal input: %v", err)
}
outputBytes, err := tool.Execute(context.Background(), inputBytes)
if err != nil {
t.Fatalf("query failed: %v", err)
}
var output QueryOutput
if err := json.Unmarshal(outputBytes, &output); err != nil {
t.Fatalf("failed to unmarshal output: %v", err)
}
// Verify output
if output.Confidence != 0.95 {
t.Errorf("expected confidence 0.95, got %f", output.Confidence)
}
if output.Lifecycle != "Approved" {
t.Errorf("expected lifecycle Approved, got %s", output.Lifecycle)
}
if output.QueryID == "" {
t.Error("expected non-empty query ID")
}
if len(output.Sources) == 0 {
t.Error("expected at least one source")
}
}
func TestQueryToolConfidenceThreshold(t *testing.T) {
// Mock client that returns low confidence
client := &mockClient{
queryFunc: func(ctx context.Context, params steme.QueryParams) (*steme.QueryResult, error) {
lifecycle := steme.LifecycleApproved
return &steme.QueryResult{
Assertions: []steme.AssertionResponse{
{
Hash: "test_hash",
Subject: "test",
Predicate: "test",
Object: steme.NewTextValue("test"),
Confidence: 0.6, // Low confidence
SourceHash: "source_hash",
Lifecycle: lifecycle,
},
},
TotalCount: 1,
}, nil
},
}
tool := NewQueryTool(client)
input := QueryInput{
Subject: "test",
Predicate: "test",
MinConfidence: 0.8, // Require high confidence
}
inputBytes, _ := json.Marshal(input)
outputBytes, err := tool.Execute(context.Background(), inputBytes)
if err != nil {
t.Fatalf("query failed: %v", err)
}
var output QueryOutput
if err := json.Unmarshal(outputBytes, &output); err != nil {
t.Fatalf("failed to unmarshal output: %v", err)
}
// Should have error about low confidence
if output.Error == "" {
t.Error("expected error for low confidence")
}
}
func TestAssertTool(t *testing.T) {
// Track what assertion was created
var capturedAssertion steme.Assertion
client := &mockClient{
assertFunc: func(ctx context.Context, assertion steme.Assertion) (string, error) {
capturedAssertion = assertion
return "created_hash", nil
},
}
tool := NewAssertTool(client)
input := AssertInput{
Subject: "Tesla_Inc",
Predicate: "has_revenue",
Object: 96.7,
SourceHash: "0000000000000000000000000000000000000000000000000000000000000000",
Confidence: 0.95,
Lifecycle: "approved",
}
inputBytes, _ := json.Marshal(input)
outputBytes, err := tool.Execute(context.Background(), inputBytes)
if err != nil {
t.Fatalf("assert failed: %v", err)
}
var output AssertOutput
if err := json.Unmarshal(outputBytes, &output); err != nil {
t.Fatalf("failed to unmarshal output: %v", err)
}
// Verify output
if !output.Success {
t.Errorf("expected success, got error: %s", output.Error)
}
if output.Hash != "created_hash" {
t.Errorf("expected hash created_hash, got %s", output.Hash)
}
// Verify captured assertion
if capturedAssertion.Subject != "Tesla_Inc" {
t.Errorf("expected subject Tesla_Inc, got %s", capturedAssertion.Subject)
}
// Use approximate comparison for floating point
if capturedAssertion.Confidence < 0.94 || capturedAssertion.Confidence > 0.96 {
t.Errorf("expected confidence ~0.95, got %f", capturedAssertion.Confidence)
}
}