xref: /tonic/interop/src/lib.rs (revision 3a5c66d5)
1 #![recursion_limit = "256"]
2 
3 pub mod client;
4 pub mod server;
5 
6 pub mod pb {
7     #![allow(dead_code)]
8     #![allow(unused_imports)]
9     include!(concat!(env!("OUT_DIR"), "/grpc.testing.rs"));
10 }
11 
12 use http::header::{HeaderMap, HeaderName, HeaderValue};
13 use http_body::Body;
14 use std::{
15     default, fmt, iter,
16     pin::Pin,
17     task::{Context, Poll},
18 };
19 
20 pub fn trace_init() {
21     let sub = tracing_subscriber::FmtSubscriber::builder()
22         .with_env_filter(tracing_subscriber::filter::EnvFilter::from_default_env())
23         .finish();
24 
25     let _ = tracing::subscriber::set_global_default(sub);
26     let _ = tracing_log::LogTracer::init();
27 }
28 
29 pub fn client_payload(size: usize) -> pb::Payload {
30     pb::Payload {
31         r#type: default::Default::default(),
32         body: iter::repeat(0u8).take(size).collect(),
33     }
34 }
35 
36 pub fn server_payload(size: usize) -> pb::Payload {
37     pb::Payload {
38         r#type: default::Default::default(),
39         body: iter::repeat(0u8).take(size).collect(),
40     }
41 }
42 
43 impl pb::ResponseParameters {
44     fn with_size(size: i32) -> Self {
45         pb::ResponseParameters {
46             size,
47             ..Default::default()
48         }
49     }
50 }
51 
52 fn response_length(response: &pb::StreamingOutputCallResponse) -> i32 {
53     match &response.payload {
54         Some(ref payload) => payload.body.len() as i32,
55         None => 0,
56     }
57 }
58 
59 fn response_lengths(responses: &Vec<pb::StreamingOutputCallResponse>) -> Vec<i32> {
60     responses.iter().map(&response_length).collect()
61 }
62 
63 #[derive(Debug)]
64 pub enum TestAssertion {
65     Passed {
66         description: &'static str,
67     },
68     Failed {
69         description: &'static str,
70         expression: &'static str,
71         why: Option<String>,
72     },
73 }
74 
75 impl TestAssertion {
76     pub fn is_failed(&self) -> bool {
77         match self {
78             TestAssertion::Failed { .. } => true,
79             _ => false,
80         }
81     }
82 }
83 
84 impl fmt::Display for TestAssertion {
85     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86         use console::{style, Emoji};
87         match *self {
88             TestAssertion::Passed { ref description } => write!(
89                 f,
90                 "{check} {desc}",
91                 check = style(Emoji("✔", "+")).green(),
92                 desc = style(description).green(),
93             ),
94             TestAssertion::Failed {
95                 ref description,
96                 ref expression,
97                 why: Some(ref why),
98             } => write!(
99                 f,
100                 "{check} {desc}\n  in `{exp}`: {why}",
101                 check = style(Emoji("✖", "x")).red(),
102                 desc = style(description).red(),
103                 exp = style(expression).red(),
104                 why = style(why).red(),
105             ),
106             TestAssertion::Failed {
107                 ref description,
108                 ref expression,
109                 why: None,
110             } => write!(
111                 f,
112                 "{check} {desc}\n  in `{exp}`",
113                 check = style(Emoji("✖", "x")).red(),
114                 desc = style(description).red(),
115                 exp = style(expression).red(),
116             ),
117         }
118     }
119 }
120 
121 #[macro_export]
122 macro_rules! test_assert {
123     ($description:expr, $assertion:expr) => {
124         if $assertion {
125             crate::TestAssertion::Passed {
126                 description: $description,
127             }
128         } else {
129             TestAssertion::Failed {
130                 description: $description,
131                 expression: stringify!($assertion),
132                 why: None,
133             }
134         }
135     };
136     ($description:expr, $assertion:expr, $why:expr) => {
137         if $assertion {
138             crate::TestAssertion::Passed {
139                 description: $description,
140             }
141         } else {
142             crate::TestAssertion::Failed {
143                 description: $description,
144                 expression: stringify!($assertion),
145                 why: Some($why),
146             }
147         }
148     };
149 }
150 
151 pub struct MergeTrailers<B> {
152     inner: B,
153     trailer: Option<(HeaderName, HeaderValue)>,
154 }
155 
156 impl<B> MergeTrailers<B> {
157     pub fn new(inner: B, trailer: Option<(HeaderName, HeaderValue)>) -> Self {
158         Self { inner, trailer }
159     }
160 }
161 
162 impl<B: Body + Unpin> Body for MergeTrailers<B> {
163     type Data = B::Data;
164     type Error = B::Error;
165 
166     fn poll_data(
167         mut self: Pin<&mut Self>,
168         cx: &mut Context<'_>,
169     ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
170         Pin::new(&mut self.inner).poll_data(cx)
171     }
172 
173     fn poll_trailers(
174         mut self: Pin<&mut Self>,
175         cx: &mut Context<'_>,
176     ) -> Poll<Result<Option<HeaderMap>, Self::Error>> {
177         Pin::new(&mut self.inner).poll_trailers(cx).map_ok(|h| {
178             h.map(|mut headers| {
179                 if let Some((key, value)) = &self.trailer {
180                     headers.insert(key.clone(), value.clone());
181                 }
182 
183                 headers
184             })
185         })
186     }
187 }
188