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