1 use std::time::Duration; 2 use structopt::{clap::arg_enum, StructOpt}; 3 use tonic::transport::Endpoint; 4 use tonic::transport::{Certificate, ClientTlsConfig}; 5 use tonic_interop::client; 6 7 #[derive(StructOpt)] 8 struct Opts { 9 #[structopt(name = "use_tls", long)] 10 use_tls: bool, 11 12 #[structopt( 13 long = "test_case", 14 use_delimiter = true, 15 min_values = 1, 16 possible_values = &Testcase::variants() 17 )] 18 test_case: Vec<Testcase>, 19 } 20 21 #[tokio::main] 22 async fn main() -> Result<(), Box<dyn std::error::Error>> { 23 tonic_interop::trace_init(); 24 25 let matches = Opts::from_args(); 26 27 let test_cases = matches.test_case; 28 29 #[allow(unused_mut)] 30 let mut endpoint = Endpoint::from_static("http://localhost:10000") 31 .timeout(Duration::from_secs(5)) 32 .concurrency_limit(30); 33 34 if matches.use_tls { 35 let pem = tokio::fs::read("interop/data/ca.pem").await?; 36 let ca = Certificate::from_pem(pem); 37 endpoint = endpoint.tls_config( 38 ClientTlsConfig::new() 39 .ca_certificate(ca) 40 .domain_name("foo.test.google.fr"), 41 ); 42 } 43 44 let channel = endpoint.connect().await?; 45 46 let mut client = client::TestClient::new(channel.clone()); 47 let mut unimplemented_client = client::UnimplementedClient::new(channel); 48 49 let mut failures = Vec::new(); 50 51 for test_case in test_cases { 52 println!("{:?}:", test_case); 53 let mut test_results = Vec::new(); 54 55 match test_case { 56 Testcase::empty_unary => client::empty_unary(&mut client, &mut test_results).await, 57 Testcase::large_unary => client::large_unary(&mut client, &mut test_results).await, 58 Testcase::client_streaming => { 59 client::client_streaming(&mut client, &mut test_results).await 60 } 61 Testcase::server_streaming => { 62 client::server_streaming(&mut client, &mut test_results).await 63 } 64 Testcase::ping_pong => client::ping_pong(&mut client, &mut test_results).await, 65 Testcase::empty_stream => client::empty_stream(&mut client, &mut test_results).await, 66 Testcase::status_code_and_message => { 67 client::status_code_and_message(&mut client, &mut test_results).await 68 } 69 Testcase::special_status_message => { 70 client::special_status_message(&mut client, &mut test_results).await 71 } 72 Testcase::unimplemented_method => { 73 client::unimplemented_method(&mut client, &mut test_results).await 74 } 75 Testcase::unimplemented_service => { 76 client::unimplemented_service(&mut unimplemented_client, &mut test_results).await 77 } 78 Testcase::custom_metadata => { 79 client::custom_metadata(&mut client, &mut test_results).await 80 } 81 _ => unimplemented!(), 82 } 83 84 for result in test_results { 85 println!(" {}", result); 86 87 if result.is_failed() { 88 failures.push(result); 89 } 90 } 91 } 92 93 if !failures.is_empty() { 94 println!("{} tests failed", failures.len()); 95 std::process::exit(1); 96 } 97 98 Ok(()) 99 } 100 101 arg_enum! { 102 #[derive(Debug, Copy, Clone)] 103 #[allow(non_camel_case_types)] 104 enum Testcase { 105 empty_unary, 106 cacheable_unary, 107 large_unary, 108 client_compressed_unary, 109 server_compressed_unary, 110 client_streaming, 111 client_compressed_streaming, 112 server_streaming, 113 server_compressed_streaming, 114 ping_pong, 115 empty_stream, 116 compute_engine_creds, 117 jwt_token_creds, 118 oauth2_auth_token, 119 per_rpc_creds, 120 custom_metadata, 121 status_code_and_message, 122 special_status_message, 123 unimplemented_method, 124 unimplemented_service, 125 cancel_after_begin, 126 cancel_after_first_response, 127 timeout_on_sleeping_server, 128 concurrent_large_unary 129 } 130 } 131