From ad9ba4c2a439c8ef464e34c19696300519e134b6 Mon Sep 17 00:00:00 2001
From: cai <cai@nbcai.cc>
Date: Sat, 08 Aug 2026 18:53:33 +0800
Subject: [PATCH] test: assert per-session ASR NDJSON metadata

---
 src/asr_realtime.rs |  107 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 106 insertions(+), 1 deletions(-)

diff --git a/src/asr_realtime.rs b/src/asr_realtime.rs
index 16d2fd3..69c2843 100644
--- a/src/asr_realtime.rs
+++ b/src/asr_realtime.rs
@@ -93,6 +93,33 @@
 }
 
 impl RealtimeAsrUpload {
+    pub(crate) fn start_with_participant_attributes<F>(
+        http: Client,
+        config: RealtimeAsrConfig,
+        call_id: &str,
+        trace_id: &str,
+        turn_id: &str,
+        initial_samples_48k: &[i16],
+        read_attributes: F,
+    ) -> Result<Self>
+    where
+        F: FnOnce() -> HashMap<String, String>,
+    {
+        let metadata = AudioIngressMetadata::from_participant(&read_attributes())
+            .map_err(|reason| anyhow!(reason))
+            .ok()
+            .flatten();
+        Self::start(
+            http,
+            config,
+            call_id,
+            trace_id,
+            turn_id,
+            initial_samples_48k,
+            metadata.as_ref(),
+        )
+    }
+
     pub(crate) fn start(
         http: Client,
         config: RealtimeAsrConfig,
@@ -325,7 +352,7 @@
     samples: Vec<i16>,
 }
 
-fn session_start_line(
+pub(crate) fn session_start_line(
     call_id: &str,
     trace_id: &str,
     turn_id: &str,
@@ -520,6 +547,84 @@
         .expect("bound json");
         assert_eq!("controlled_fixture", with_metadata["inputSourceCategory"]);
         assert_eq!("fixture-01", with_metadata["clientFixtureSequence"]);
+        let next = AudioIngressMetadata {
+            input_source_category: "controlled_fixture".to_string(),
+            client_fixture_sequence: "fixture-02".to_string(),
+        };
+        let next_line = session_start_line(
+            "call-001",
+            "trace-001",
+            "turn-0002",
+            "nonce-001",
+            Some(&next),
+        )
+        .expect("next bound session line");
+        let next_value: serde_json::Value = serde_json::from_slice(&next_line).expect("next json");
+        assert_eq!("fixture-02", next_value["clientFixtureSequence"]);
+        assert_ne!(
+            with_metadata["clientFixtureSequence"],
+            next_value["clientFixtureSequence"]
+        );
+    }
+
+    #[tokio::test]
+    async fn production_session_boundary_reads_updated_attributes_per_session() {
+        let mut attributes = HashMap::new();
+        attributes.insert(
+            "inputSourceCategory".to_string(),
+            "controlled_fixture".to_string(),
+        );
+        attributes.insert(
+            "clientFixtureSequence".to_string(),
+            "fixture-01".to_string(),
+        );
+        let (url1, captured1, server1) =
+            spawn_http_fixture(json!({"code": 0, "data": {"status": "cancelled"}}).to_string());
+        let upload1 = RealtimeAsrUpload::start_with_participant_attributes(
+            Client::new(),
+            fixture_config(url1),
+            "call-001",
+            "trace-001",
+            "turn-0001",
+            &vec![1; 9_600],
+            || attributes.clone(),
+        )
+        .expect("session one");
+        upload1.cancel("test").await;
+        let request1 = captured1.recv().expect("session one request");
+        server1.join().expect("session one server");
+        assert!(
+            request1
+                .body
+                .contains("\"clientFixtureSequence\":\"fixture-01\"")
+        );
+        assert!(!request1.body.contains("fixture-02"));
+
+        attributes.insert(
+            "clientFixtureSequence".to_string(),
+            "fixture-02".to_string(),
+        );
+        let (url2, captured2, server2) =
+            spawn_http_fixture(json!({"code": 0, "data": {"status": "cancelled"}}).to_string());
+        let upload2 = RealtimeAsrUpload::start_with_participant_attributes(
+            Client::new(),
+            fixture_config(url2),
+            "call-001",
+            "trace-001",
+            "turn-0002",
+            &vec![1; 9_600],
+            || attributes.clone(),
+        )
+        .expect("session two");
+        upload2.cancel("test").await;
+        let request2 = captured2.recv().expect("session two request");
+        server2.join().expect("session two server");
+        assert!(
+            request2
+                .body
+                .contains("\"clientFixtureSequence\":\"fixture-02\"")
+        );
+        assert!(!request2.body.contains("fixture-01"));
     }
 
     #[test]

--
Gitblit v1.9.3