mirror of
https://github.com/ultraworkers/claw-code-parity.git
synced 2026-04-29 00:05:59 +02:00
eea7651dab
Add focused integration coverage for real git branch freshness checks, degraded MCP startup reporting, policy routing, prompt misdelivery recovery, and telemetry JSONL roundtrips. Constraint: Keep coverage isolated to new integration test files so existing in-progress workspace edits stay untouched Rejected: Expand existing unit tests instead | user requested integration coverage across runtime and telemetry boundaries Confidence: high Scope-risk: narrow Reversibility: clean Directive: Keep these scenarios in integration tests because they depend on cross-module behavior and serialized output contracts Tested: cargo test --workspace Not-tested: Remote push hooks or CI-only environment differences
98 lines
3.0 KiB
Rust
98 lines
3.0 KiB
Rust
use std::fs;
|
|
use std::sync::Arc;
|
|
use std::time::{SystemTime, UNIX_EPOCH};
|
|
|
|
use serde_json::{Map, Value};
|
|
use telemetry::{
|
|
AnalyticsEvent, JsonlTelemetrySink, SessionTraceRecord, SessionTracer, TelemetryEvent,
|
|
};
|
|
|
|
fn temp_log_path() -> std::path::PathBuf {
|
|
let nanos = SystemTime::now()
|
|
.duration_since(UNIX_EPOCH)
|
|
.expect("time should be after epoch")
|
|
.as_nanos();
|
|
std::env::temp_dir().join(format!("telemetry-roundtrip-{nanos}.jsonl"))
|
|
}
|
|
|
|
#[test]
|
|
fn telemetry_roundtrip_preserves_structured_jsonl_events() {
|
|
let path = temp_log_path();
|
|
let sink = Arc::new(JsonlTelemetrySink::new(&path).expect("sink should create file"));
|
|
let tracer = SessionTracer::new("session-integration", sink);
|
|
|
|
let mut request_attributes = Map::new();
|
|
request_attributes.insert(
|
|
"model".to_string(),
|
|
Value::String("claude-sonnet".to_string()),
|
|
);
|
|
|
|
tracer.record_http_request_started(1, "POST", "/v1/messages", request_attributes.clone());
|
|
tracer.record_http_request_succeeded(
|
|
1,
|
|
"POST",
|
|
"/v1/messages",
|
|
200,
|
|
Some("req_123".to_string()),
|
|
request_attributes,
|
|
);
|
|
tracer.record_analytics(
|
|
AnalyticsEvent::new("cli", "prompt_sent").with_property("turn", Value::from(1)),
|
|
);
|
|
|
|
let events = fs::read_to_string(&path)
|
|
.expect("telemetry log should be readable")
|
|
.lines()
|
|
.map(|line| serde_json::from_str::<TelemetryEvent>(line).expect("line should deserialize"))
|
|
.collect::<Vec<_>>();
|
|
|
|
assert_eq!(events.len(), 6);
|
|
assert!(matches!(
|
|
&events[0],
|
|
TelemetryEvent::HttpRequestStarted {
|
|
session_id,
|
|
attempt: 1,
|
|
method,
|
|
path,
|
|
..
|
|
} if session_id == "session-integration" && method == "POST" && path == "/v1/messages"
|
|
));
|
|
assert!(matches!(
|
|
&events[1],
|
|
TelemetryEvent::SessionTrace(SessionTraceRecord { sequence: 0, name, .. })
|
|
if name == "http_request_started"
|
|
));
|
|
assert!(matches!(
|
|
&events[2],
|
|
TelemetryEvent::HttpRequestSucceeded {
|
|
session_id,
|
|
attempt: 1,
|
|
method,
|
|
path,
|
|
status: 200,
|
|
request_id,
|
|
..
|
|
} if session_id == "session-integration"
|
|
&& method == "POST"
|
|
&& path == "/v1/messages"
|
|
&& request_id.as_deref() == Some("req_123")
|
|
));
|
|
assert!(matches!(
|
|
&events[3],
|
|
TelemetryEvent::SessionTrace(SessionTraceRecord { sequence: 1, name, .. })
|
|
if name == "http_request_succeeded"
|
|
));
|
|
assert!(matches!(
|
|
&events[4],
|
|
TelemetryEvent::Analytics(analytics)
|
|
if analytics.namespace == "cli" && analytics.action == "prompt_sent"
|
|
));
|
|
assert!(matches!(
|
|
&events[5],
|
|
TelemetryEvent::SessionTrace(SessionTraceRecord { sequence: 2, name, .. })
|
|
if name == "analytics"
|
|
));
|
|
|
|
let _ = fs::remove_file(path);
|
|
}
|