1 use interop::client;
2 use std::{str::FromStr, time::Duration};
3 use tonic::transport::Endpoint;
4 use tonic::transport::{Certificate, ClientTlsConfig};
5
6 #[derive(Debug)]
7 struct Opts {
8 use_tls: bool,
9 test_case: Vec<Testcase>,
10 }
11
12 impl Opts {
parse() -> Result<Self, pico_args::Error>13 fn parse() -> Result<Self, pico_args::Error> {
14 let mut pargs = pico_args::Arguments::from_env();
15 Ok(Self {
16 use_tls: pargs.contains("--use_tls"),
17 test_case: pargs.value_from_fn("--test_case", |test_case| {
18 test_case.split(',').map(Testcase::from_str).collect()
19 })?,
20 })
21 }
22 }
23
24 #[tokio::main]
main() -> Result<(), Box<dyn std::error::Error>>25 async fn main() -> Result<(), Box<dyn std::error::Error>> {
26 interop::trace_init();
27
28 let matches = Opts::parse()?;
29
30 let test_cases = matches.test_case;
31
32 let scheme = if matches.use_tls { "https" } else { "http" };
33
34 #[allow(unused_mut)]
35 let mut endpoint = Endpoint::try_from(format!("{}://localhost:10000", scheme))?
36 .timeout(Duration::from_secs(5))
37 .concurrency_limit(30);
38
39 if matches.use_tls {
40 let pem = std::fs::read_to_string("interop/data/ca.pem")?;
41 let ca = Certificate::from_pem(pem);
42 endpoint = endpoint.tls_config(
43 ClientTlsConfig::new()
44 .ca_certificate(ca)
45 .domain_name("foo.test.google.fr"),
46 )?;
47 }
48
49 let channel = endpoint.connect().await?;
50
51 let mut client = client::TestClient::new(channel.clone());
52 let mut unimplemented_client = client::UnimplementedClient::new(channel);
53
54 let mut failures = Vec::new();
55
56 for test_case in test_cases {
57 println!("{:?}:", test_case);
58 let mut test_results = Vec::new();
59
60 match test_case {
61 Testcase::EmptyUnary => client::empty_unary(&mut client, &mut test_results).await,
62 Testcase::LargeUnary => client::large_unary(&mut client, &mut test_results).await,
63 Testcase::ClientStreaming => {
64 client::client_streaming(&mut client, &mut test_results).await
65 }
66 Testcase::ServerStreaming => {
67 client::server_streaming(&mut client, &mut test_results).await
68 }
69 Testcase::PingPong => client::ping_pong(&mut client, &mut test_results).await,
70 Testcase::EmptyStream => client::empty_stream(&mut client, &mut test_results).await,
71 Testcase::StatusCodeAndMessage => {
72 client::status_code_and_message(&mut client, &mut test_results).await
73 }
74 Testcase::SpecialStatusMessage => {
75 client::special_status_message(&mut client, &mut test_results).await
76 }
77 Testcase::UnimplementedMethod => {
78 client::unimplemented_method(&mut client, &mut test_results).await
79 }
80 Testcase::UnimplementedService => {
81 client::unimplemented_service(&mut unimplemented_client, &mut test_results).await
82 }
83 Testcase::CustomMetadata => {
84 client::custom_metadata(&mut client, &mut test_results).await
85 }
86 _ => unimplemented!(),
87 }
88
89 for result in test_results {
90 println!(" {}", result);
91
92 if result.is_failed() {
93 failures.push(result);
94 }
95 }
96 }
97
98 if !failures.is_empty() {
99 println!("{} tests failed", failures.len());
100 std::process::exit(1);
101 }
102
103 Ok(())
104 }
105
106 #[derive(Debug, strum::EnumString)]
107 #[strum(serialize_all = "snake_case")]
108 enum Testcase {
109 EmptyUnary,
110 CacheableUnary,
111 LargeUnary,
112 ClientCompressedUnary,
113 ServerCompressedUnary,
114 ClientStreaming,
115 ClientCompressedStreaming,
116 ServerStreaming,
117 ServerCompressedStreaming,
118 PingPong,
119 EmptyStream,
120 ComputeEngineCreds,
121 JwtTokenCreds,
122 Oauth2AuthToken,
123 PerRpcCreds,
124 CustomMetadata,
125 StatusCodeAndMessage,
126 SpecialStatusMessage,
127 UnimplementedMethod,
128 UnimplementedService,
129 CancelAfterBegin,
130 CancelAfterFirstResponse,
131 TimeoutOnSleepingServer,
132 ConcurrentLargeUnary,
133 }
134