api_testing_core/grpc/
expect.rs1use anyhow::Context;
2
3use crate::Result;
4use crate::grpc::runner::GrpcExecutedRequest;
5use crate::grpc::schema::GrpcRequest;
6
7pub fn evaluate_main_response(request: &GrpcRequest, executed: &GrpcExecutedRequest) -> Result<()> {
8 let Some(expect) = request.expect.as_ref() else {
9 return Ok(());
10 };
11
12 if let Some(status) = expect.status
13 && executed.grpc_status != status
14 {
15 anyhow::bail!(
16 "gRPC expect.status failed: expected {}, got {}",
17 status,
18 executed.grpc_status
19 );
20 }
21
22 if let Some(expr) = expect.jq.as_deref() {
23 let json: serde_json::Value = serde_json::from_slice(&executed.response_body)
24 .context("gRPC expect.jq requires a JSON response body")?;
25 if !crate::jq::eval_exit_status(&json, expr).unwrap_or(false) {
26 anyhow::bail!("gRPC expect.jq failed: {expr}");
27 }
28 }
29
30 Ok(())
31}
32
33#[cfg(test)]
34mod tests {
35 use super::*;
36 use crate::grpc::schema::{GrpcExpect, GrpcRequest};
37
38 fn base_request(expect: Option<GrpcExpect>) -> GrpcRequest {
39 GrpcRequest {
40 method: "health.HealthService/Check".to_string(),
41 body: serde_json::json!({}),
42 metadata: Vec::new(),
43 proto: None,
44 import_paths: Vec::new(),
45 plaintext: true,
46 authority: None,
47 timeout_seconds: None,
48 expect,
49 raw: serde_json::json!({}),
50 }
51 }
52
53 fn base_executed(body: serde_json::Value) -> GrpcExecutedRequest {
54 GrpcExecutedRequest {
55 target: "127.0.0.1:50051".to_string(),
56 method: "health.HealthService/Check".to_string(),
57 grpc_status: 0,
58 response_body: serde_json::to_vec(&body).unwrap(),
59 stderr: String::new(),
60 }
61 }
62
63 #[test]
64 fn grpc_expect_accepts_matching_status_and_jq() {
65 let request = base_request(Some(GrpcExpect {
66 status: Some(0),
67 jq: Some(".ok == true".to_string()),
68 }));
69 let executed = base_executed(serde_json::json!({"ok": true}));
70 evaluate_main_response(&request, &executed).unwrap();
71 }
72
73 #[test]
74 fn grpc_expect_rejects_mismatched_status() {
75 let request = base_request(Some(GrpcExpect {
76 status: Some(2),
77 jq: None,
78 }));
79 let executed = base_executed(serde_json::json!({"ok": true}));
80 let err = evaluate_main_response(&request, &executed).unwrap_err();
81 assert!(format!("{err:#}").contains("expect.status failed"));
82 }
83
84 #[test]
85 fn grpc_expect_rejects_failed_jq() {
86 let request = base_request(Some(GrpcExpect {
87 status: Some(0),
88 jq: Some(".ok == false".to_string()),
89 }));
90 let executed = base_executed(serde_json::json!({"ok": true}));
91 let err = evaluate_main_response(&request, &executed).unwrap_err();
92 assert!(format!("{err:#}").contains("expect.jq failed"));
93 }
94}