postjevsql.git / tests / gate_layout_parity.rs

Release gate "layout parity", replayed (tests/fixtures/layout_parity.json, from tools/record-gates --send). The row-as-state requests are sent by the extension and must match the recording byte for byte. Row in instructions is unreachable from the extension until this gate passes (LayoutParity has no values), so its recorded exchange is checked for an answer per row rather than replayed.

8use support::gates::{QUESTION, ROWS, fixture, setup_people};
9use support::mock_jev::MockJev;
10use support::mock_jev::replay::Replay;
12#[tokio::test(flavor = "multi_thread")]
13async fn row_as_state_replays_and_row_in_instructions_answers_every_row() {
14    let fixture = fixture("layout_parity");
15    let replay = Replay::new(&fixture);
16    let mock = MockJev::start(replay.responder()).await;
17    let (_pg, client) = support::jev_instance(&mock).await;
18    setup_people(&client).await.expect("setup");
19
20    let rows = client
21        .query("SELECT name, jev_prob(p, $1) FROM people p", &[&QUESTION])
22        .await
23        .expect("replayed");
24    assert_eq!(rows.len(), ROWS.len());
25    assert_eq!(mock.requests().len(), ROWS.len(), "one request per row, as state");
26    replay.assert_complete();
27
28    // The one exchange the extension did not send: every row a question.
29    let sent: Vec<String> = mock.requests().iter().map(|r| String::from_utf8(r.body.to_vec()).unwrap()).collect();
30    let unsent: Vec<_> = fixture.exchanges.iter().filter(|(request, _)| !sent.contains(request)).collect();
31    assert_eq!(unsent.len(), 1, "row in instructions is one request");
32    let (request, responses) = unsent[0];
33    let request: serde_json::Value = serde_json::from_str(request).unwrap();
34    assert_eq!(request["state"], serde_json::json!({}));
35    let body: serde_json::Value = serde_json::from_str(&responses[0].body).unwrap();
36    for (i, row) in ROWS.iter().enumerate() {
37        let row: serde_json::Value = serde_json::from_str(row).unwrap();
38        assert_eq!(request["questions"][format!("r{i}")]["instructions"]["row"], row);
39        let p = body["answers"][format!("r{i}")]["noul"].as_f64();
40        assert!(p.is_some_and(|p| (0.0..=1.0).contains(&p)), "r{i} answered: {body}");
41    }
42}