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