a8e_test_support/
session.rs1use std::sync::{Arc, Mutex};
2
3pub const TEST_SESSION_ID: &str = "test-session-id";
4pub const TEST_MODEL: &str = "gpt-5-nano";
5
6const NOT_YET_SET: &str = "session-id-not-yet-set";
7pub(crate) const SESSION_ID_HEADER: &str = "agent-session-id";
8
9#[derive(Clone)]
10pub struct ExpectedSessionId {
11 value: Arc<Mutex<String>>,
12 errors: Arc<Mutex<Vec<String>>>,
13}
14
15impl Default for ExpectedSessionId {
16 fn default() -> Self {
17 Self {
18 value: Arc::new(Mutex::new(NOT_YET_SET.to_string())),
19 errors: Arc::new(Mutex::new(Vec::new())),
20 }
21 }
22}
23
24impl ExpectedSessionId {
25 pub fn set(&self, id: impl Into<String>) {
26 *self.value.lock().unwrap() = id.into();
27 }
28
29 pub fn validate(&self, actual: Option<&str>) -> Result<(), String> {
30 let expected = self.value.lock().unwrap();
31 let err = match actual {
32 Some(act) if act == *expected => None,
33 _ => Some(format!(
34 "{} mismatch: expected '{}', got {:?}",
35 SESSION_ID_HEADER, expected, actual
36 )),
37 };
38 match err {
39 Some(e) => {
40 self.errors.lock().unwrap().push(e.clone());
41 Err(e)
42 }
43 None => Ok(()),
44 }
45 }
46
47 pub fn assert_matches(&self, actual: &str) {
48 let result = self.validate(Some(actual));
49 assert!(result.is_ok(), "{}", result.unwrap_err());
50 let errors = self.errors.lock().unwrap();
51 assert!(
52 errors.is_empty(),
53 "Session ID validation errors: {:?}",
54 *errors
55 );
56 }
57}