blob: 8274aaeb2b1037354d2f159e2bea24bf3923fc19 [file] [log] [blame]
Allen George8b96bfb2016-11-02 08:01:08 -04001// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
Allen George55c3e4c2021-03-01 23:19:52 -050018use clap::{clap_app, value_t};
Allen George7ddbcc02020-11-08 09:51:19 -050019use env_logger;
20use log::*;
Allen Georgebc1344d2017-04-28 10:22:03 -040021
Allen George8b96bfb2016-11-02 08:01:08 -040022use std::collections::{BTreeMap, BTreeSet};
23use std::fmt::Debug;
tokcumf0336412022-03-30 11:39:08 +020024use std::net::{TcpStream, ToSocketAddrs};
25
26#[cfg(unix)]
27use std::os::unix::net::UnixStream;
28#[cfg(unix)]
29use std::path::Path;
Allen George8b96bfb2016-11-02 08:01:08 -040030
Allen George7ddbcc02020-11-08 09:51:19 -050031use thrift;
Allen George55c3e4c2021-03-01 23:19:52 -050032use thrift::protocol::{
33 TBinaryInputProtocol, TBinaryOutputProtocol, TCompactInputProtocol, TCompactOutputProtocol,
34 TInputProtocol, TMultiplexedOutputProtocol, TOutputProtocol,
35};
36use thrift::transport::{
37 TBufferedReadTransport, TBufferedWriteTransport, TFramedReadTransport, TFramedWriteTransport,
38 TIoChannel, TReadTransport, TTcpChannel, TWriteTransport,
39};
Allen George7ddbcc02020-11-08 09:51:19 -050040use thrift::OrderedFloat;
Allen George8b96bfb2016-11-02 08:01:08 -040041use thrift_test::*;
42
tokcumf0336412022-03-30 11:39:08 +020043type ThriftClientPair = (
44 ThriftTestSyncClient<Box<dyn TInputProtocol>, Box<dyn TOutputProtocol>>,
45 Option<SecondServiceSyncClient<Box<dyn TInputProtocol>, Box<dyn TOutputProtocol>>>,
46);
47
Allen George8b96bfb2016-11-02 08:01:08 -040048fn main() {
Allen George7ddbcc02020-11-08 09:51:19 -050049 env_logger::init();
Allen Georgebc1344d2017-04-28 10:22:03 -040050
51 debug!("initialized logger - running cross-test client");
52
Allen George8b96bfb2016-11-02 08:01:08 -040053 match run() {
Allen Georgebc1344d2017-04-28 10:22:03 -040054 Ok(()) => info!("cross-test client succeeded"),
Allen George8b96bfb2016-11-02 08:01:08 -040055 Err(e) => {
Allen Georgebc1344d2017-04-28 10:22:03 -040056 info!("cross-test client failed with error {:?}", e);
Allen George8b96bfb2016-11-02 08:01:08 -040057 std::process::exit(1);
58 }
59 }
60}
61
62fn run() -> thrift::Result<()> {
63 // unsupported options:
Jens Geyer4a33b182020-03-22 13:46:34 +010064 // --pipe
Allen George8b96bfb2016-11-02 08:01:08 -040065 // --anon-pipes
66 // --ssl
67 // --threads
68 let matches = clap_app!(rust_test_client =>
69 (version: "1.0")
70 (author: "Apache Thrift Developers <dev@thrift.apache.org>")
71 (about: "Rust Thrift test client")
72 (@arg host: --host +takes_value "Host on which the Thrift test server is located")
73 (@arg port: --port +takes_value "Port on which the Thrift test server is listening")
tokcumf0336412022-03-30 11:39:08 +020074 (@arg domain_socket: --("domain-socket") +takes_value "Unix Domain Socket on which the Thrift test server is listening")
James E. King III9804ab92019-02-07 16:59:05 -050075 (@arg protocol: --protocol +takes_value "Thrift protocol implementation to use (\"binary\", \"compact\", \"multi\", \"multic\")")
tokcumf0336412022-03-30 11:39:08 +020076 (@arg transport: --transport +takes_value "Thrift transport implementation to use (\"buffered\", \"framed\")")
Allen George8b96bfb2016-11-02 08:01:08 -040077 (@arg testloops: -n --testloops +takes_value "Number of times to run tests")
Allen George0e22c362017-01-30 07:15:00 -050078 )
Allen Georgebc1344d2017-04-28 10:22:03 -040079 .get_matches();
Allen George8b96bfb2016-11-02 08:01:08 -040080
81 let host = matches.value_of("host").unwrap_or("127.0.0.1");
82 let port = value_t!(matches, "port", u16).unwrap_or(9090);
tokcumf0336412022-03-30 11:39:08 +020083 let domain_socket = matches.value_of("domain_socket");
Allen George8b96bfb2016-11-02 08:01:08 -040084 let protocol = matches.value_of("protocol").unwrap_or("binary");
tokcumf0336412022-03-30 11:39:08 +020085 let transport = matches.value_of("transport").unwrap_or("buffered");
86 let testloops = value_t!(matches, "testloops", u8).unwrap_or(1);
Allen George8b96bfb2016-11-02 08:01:08 -040087
tokcumf0336412022-03-30 11:39:08 +020088 let (mut thrift_test_client, mut second_service_client) = match domain_socket {
89 None => {
90 let listen_address = format!("{}:{}", host, port);
91 info!(
92 "Client binds to {} with {}+{} stack",
93 listen_address, protocol, transport
94 );
95 bind(listen_address.as_str(), protocol, transport)?
96 }
97 Some(domain_socket) => {
98 info!(
99 "Client binds to {} (UDS) with {}+{} stack",
100 domain_socket, protocol, transport
101 );
102 bind_uds(domain_socket, protocol, transport)?
103 }
Allen George8b96bfb2016-11-02 08:01:08 -0400104 };
105
Allen George8b96bfb2016-11-02 08:01:08 -0400106 for _ in 0..testloops {
Allen Georgebc1344d2017-04-28 10:22:03 -0400107 make_thrift_calls(&mut thrift_test_client, &mut second_service_client)?
Allen George8b96bfb2016-11-02 08:01:08 -0400108 }
109
110 Ok(())
111}
112
tokcumf0336412022-03-30 11:39:08 +0200113fn bind<A: ToSocketAddrs>(
114 listen_address: A,
115 protocol: &str,
116 transport: &str,
117) -> Result<ThriftClientPair, thrift::Error> {
118 // create a TCPStream that will be shared by all Thrift clients
119 // service calls from multiple Thrift clients will be interleaved over the same connection
120 // this isn't a problem for us because we're single-threaded and all calls block to completion
121 let shared_stream = TcpStream::connect(listen_address)?;
122
123 let second_service_client = if protocol.starts_with("multi") {
124 let shared_stream_clone = shared_stream.try_clone()?;
125 let channel = TTcpChannel::with_stream(shared_stream_clone);
126 let (i_prot, o_prot) = build(channel, transport, protocol, "SecondService")?;
127 Some(SecondServiceSyncClient::new(i_prot, o_prot))
128 } else {
129 None
130 };
131
132 let thrift_test_client = {
133 let channel = TTcpChannel::with_stream(shared_stream);
134 let (i_prot, o_prot) = build(channel, transport, protocol, "ThriftTest")?;
135 ThriftTestSyncClient::new(i_prot, o_prot)
136 };
137
138 Ok((thrift_test_client, second_service_client))
139}
140
141#[cfg(unix)]
142fn bind_uds<P: AsRef<Path>>(
143 domain_socket: P,
144 protocol: &str,
145 transport: &str,
146) -> Result<ThriftClientPair, thrift::Error> {
147 // create a UnixStream that will be shared by all Thrift clients
148 // service calls from multiple Thrift clients will be interleaved over the same connection
149 // this isn't a problem for us because we're single-threaded and all calls block to completion
150 let shared_stream = UnixStream::connect(domain_socket)?;
151
152 let second_service_client = if protocol.starts_with("multi") {
153 let shared_stream_clone = shared_stream.try_clone()?;
154 let (i_prot, o_prot) = build(shared_stream_clone, transport, protocol, "SecondService")?;
155 Some(SecondServiceSyncClient::new(i_prot, o_prot))
156 } else {
157 None
158 };
159
160 let thrift_test_client = {
161 let (i_prot, o_prot) = build(shared_stream, transport, protocol, "ThriftTest")?;
162 ThriftTestSyncClient::new(i_prot, o_prot)
163 };
164
165 Ok((thrift_test_client, second_service_client))
166}
167
168fn build<C: TIoChannel + 'static>(
169 channel: C,
Allen Georgebc1344d2017-04-28 10:22:03 -0400170 transport: &str,
171 protocol: &str,
172 service_name: &str,
Allen Georgeb0d14132020-03-29 11:48:55 -0400173) -> thrift::Result<(Box<dyn TInputProtocol>, Box<dyn TOutputProtocol>)> {
tokcumf0336412022-03-30 11:39:08 +0200174 let (i_chan, o_chan) = channel.split()?;
Allen Georgebc1344d2017-04-28 10:22:03 -0400175
Allen Georgeb0d14132020-03-29 11:48:55 -0400176 let (i_tran, o_tran): (Box<dyn TReadTransport>, Box<dyn TWriteTransport>) = match transport {
Allen George55c3e4c2021-03-01 23:19:52 -0500177 "buffered" => (
178 Box::new(TBufferedReadTransport::new(i_chan)),
179 Box::new(TBufferedWriteTransport::new(o_chan)),
180 ),
181 "framed" => (
182 Box::new(TFramedReadTransport::new(i_chan)),
183 Box::new(TFramedWriteTransport::new(o_chan)),
184 ),
Allen Georgebc1344d2017-04-28 10:22:03 -0400185 unmatched => return Err(format!("unsupported transport {}", unmatched).into()),
186 };
187
Allen Georgeb0d14132020-03-29 11:48:55 -0400188 let (i_prot, o_prot): (Box<dyn TInputProtocol>, Box<dyn TOutputProtocol>) = match protocol {
Allen George55c3e4c2021-03-01 23:19:52 -0500189 "binary" => (
190 Box::new(TBinaryInputProtocol::new(i_tran, true)),
191 Box::new(TBinaryOutputProtocol::new(o_tran, true)),
192 ),
193 "multi" => (
194 Box::new(TBinaryInputProtocol::new(i_tran, true)),
195 Box::new(TMultiplexedOutputProtocol::new(
196 service_name,
197 TBinaryOutputProtocol::new(o_tran, true),
198 )),
199 ),
200 "compact" => (
201 Box::new(TCompactInputProtocol::new(i_tran)),
202 Box::new(TCompactOutputProtocol::new(o_tran)),
203 ),
204 "multic" => (
205 Box::new(TCompactInputProtocol::new(i_tran)),
206 Box::new(TMultiplexedOutputProtocol::new(
207 service_name,
208 TCompactOutputProtocol::new(o_tran),
209 )),
210 ),
Allen Georgebc1344d2017-04-28 10:22:03 -0400211 unmatched => return Err(format!("unsupported protocol {}", unmatched).into()),
212 };
213
214 Ok((i_prot, o_prot))
215}
216
Allen George55c3e4c2021-03-01 23:19:52 -0500217type BuildThriftTestClient =
218 ThriftTestSyncClient<Box<dyn TInputProtocol>, Box<dyn TOutputProtocol>>;
219type BuiltSecondServiceClient =
220 SecondServiceSyncClient<Box<dyn TInputProtocol>, Box<dyn TOutputProtocol>>;
Allen George8b96bfb2016-11-02 08:01:08 -0400221
Allen George7ddbcc02020-11-08 09:51:19 -0500222#[allow(clippy::cognitive_complexity)]
Allen Georgebc1344d2017-04-28 10:22:03 -0400223fn make_thrift_calls(
224 thrift_test_client: &mut BuildThriftTestClient,
225 second_service_client: &mut Option<BuiltSecondServiceClient>,
226) -> Result<(), thrift::Error> {
227 info!("testVoid");
228 thrift_test_client.test_void()?;
Allen George8b96bfb2016-11-02 08:01:08 -0400229
Allen Georgebc1344d2017-04-28 10:22:03 -0400230 info!("testString");
Allen George0e22c362017-01-30 07:15:00 -0500231 verify_expected_result(
Allen Georgebc1344d2017-04-28 10:22:03 -0400232 thrift_test_client.test_string("thing".to_owned()),
233 "thing".to_owned(),
234 )?;
235
236 info!("testBool");
237 verify_expected_result(thrift_test_client.test_bool(true), true)?;
238
239 info!("testBool");
240 verify_expected_result(thrift_test_client.test_bool(false), false)?;
241
242 info!("testByte");
243 verify_expected_result(thrift_test_client.test_byte(42), 42)?;
244
245 info!("testi32");
Allen George7ddbcc02020-11-08 09:51:19 -0500246 verify_expected_result(thrift_test_client.test_i32(1_159_348_374), 1_159_348_374)?;
Allen Georgebc1344d2017-04-28 10:22:03 -0400247
248 info!("testi64");
249 // try!(verify_expected_result(thrift_test_client.test_i64(-8651829879438294565),
250 // -8651829879438294565));
251 verify_expected_result(
252 thrift_test_client.test_i64(i64::min_value()),
253 i64::min_value(),
254 )?;
255
256 info!("testDouble");
257 verify_expected_result(
258 thrift_test_client.test_double(OrderedFloat::from(42.42)),
Allen George0e22c362017-01-30 07:15:00 -0500259 OrderedFloat::from(42.42),
260 )?;
Allen George8b96bfb2016-11-02 08:01:08 -0400261
Allen Georgebc1344d2017-04-28 10:22:03 -0400262 info!("testTypedef");
Allen George8b96bfb2016-11-02 08:01:08 -0400263 {
264 let u_snd: UserId = 2348;
265 let u_cmp: UserId = 2348;
Allen Georgebc1344d2017-04-28 10:22:03 -0400266 verify_expected_result(thrift_test_client.test_typedef(u_snd), u_cmp)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400267 }
268
Allen Georgebc1344d2017-04-28 10:22:03 -0400269 info!("testEnum");
Allen George8b96bfb2016-11-02 08:01:08 -0400270 {
Allen George2e90ef52021-03-01 14:47:04 -0500271 verify_expected_result(thrift_test_client.test_enum(Numberz::TWO), Numberz::TWO)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400272 }
273
Allen Georgebc1344d2017-04-28 10:22:03 -0400274 info!("testBinary");
Allen George8b96bfb2016-11-02 08:01:08 -0400275 {
276 let b_snd = vec![0x77, 0x30, 0x30, 0x74, 0x21, 0x20, 0x52, 0x75, 0x73, 0x74];
277 let b_cmp = vec![0x77, 0x30, 0x30, 0x74, 0x21, 0x20, 0x52, 0x75, 0x73, 0x74];
Allen Georgebc1344d2017-04-28 10:22:03 -0400278 verify_expected_result(thrift_test_client.test_binary(b_snd), b_cmp)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400279 }
280
Allen Georgebc1344d2017-04-28 10:22:03 -0400281 info!("testStruct");
Allen George8b96bfb2016-11-02 08:01:08 -0400282 {
283 let x_snd = Xtruct {
284 string_thing: Some("foo".to_owned()),
285 byte_thing: Some(12),
Allen George7ddbcc02020-11-08 09:51:19 -0500286 i32_thing: Some(219_129),
287 i64_thing: Some(12_938_492_818),
Allen George8b96bfb2016-11-02 08:01:08 -0400288 };
289 let x_cmp = Xtruct {
290 string_thing: Some("foo".to_owned()),
291 byte_thing: Some(12),
Allen George7ddbcc02020-11-08 09:51:19 -0500292 i32_thing: Some(219_129),
293 i64_thing: Some(12_938_492_818),
Allen George8b96bfb2016-11-02 08:01:08 -0400294 };
Allen Georgebc1344d2017-04-28 10:22:03 -0400295 verify_expected_result(thrift_test_client.test_struct(x_snd), x_cmp)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400296 }
297
298 // Xtruct again, with optional values
Allen George0e22c362017-01-30 07:15:00 -0500299 // FIXME: apparently the erlang thrift server does not like opt-in-req-out
300 // parameters that are undefined. Joy.
Allen George8b96bfb2016-11-02 08:01:08 -0400301 // {
Allen George0e22c362017-01-30 07:15:00 -0500302 // let x_snd = Xtruct { string_thing: Some("foo".to_owned()), byte_thing: None,
303 // i32_thing: None, i64_thing: Some(12938492818) };
304 // let x_cmp = Xtruct { string_thing: Some("foo".to_owned()), byte_thing:
305 // Some(0), i32_thing: Some(0), i64_thing: Some(12938492818) }; // the C++
306 // server is responding correctly
Allen Georgebc1344d2017-04-28 10:22:03 -0400307 // try!(verify_expected_result(thrift_test_client.test_struct(x_snd), x_cmp));
Allen George8b96bfb2016-11-02 08:01:08 -0400308 // }
309 //
310
Allen Georgebc1344d2017-04-28 10:22:03 -0400311 info!("testNest"); // (FIXME: try Xtruct2 with optional values)
Allen George8b96bfb2016-11-02 08:01:08 -0400312 {
313 let x_snd = Xtruct2 {
314 byte_thing: Some(32),
Allen George55c3e4c2021-03-01 23:19:52 -0500315 struct_thing: Some(Xtruct {
316 string_thing: Some("foo".to_owned()),
317 byte_thing: Some(1),
318 i32_thing: Some(324_382_098),
319 i64_thing: Some(12_938_492_818),
320 }),
Allen George7ddbcc02020-11-08 09:51:19 -0500321 i32_thing: Some(293_481_098),
Allen George8b96bfb2016-11-02 08:01:08 -0400322 };
323 let x_cmp = Xtruct2 {
324 byte_thing: Some(32),
Allen George55c3e4c2021-03-01 23:19:52 -0500325 struct_thing: Some(Xtruct {
326 string_thing: Some("foo".to_owned()),
327 byte_thing: Some(1),
328 i32_thing: Some(324_382_098),
329 i64_thing: Some(12_938_492_818),
330 }),
Allen George7ddbcc02020-11-08 09:51:19 -0500331 i32_thing: Some(293_481_098),
Allen George8b96bfb2016-11-02 08:01:08 -0400332 };
Allen Georgebc1344d2017-04-28 10:22:03 -0400333 verify_expected_result(thrift_test_client.test_nest(x_snd), x_cmp)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400334 }
335
Allen Georgebc1344d2017-04-28 10:22:03 -0400336 // do the multiplexed calls while making the main ThriftTest calls
337 if let Some(ref mut client) = second_service_client.as_mut() {
Allen Georgebc1344d2017-04-28 10:22:03 -0400338 info!("SecondService secondtestString");
339 {
340 verify_expected_result(
341 client.secondtest_string("test_string".to_owned()),
342 "testString(\"test_string\")".to_owned(),
343 )?;
344 }
345 }
346
347 info!("testList");
Allen George8b96bfb2016-11-02 08:01:08 -0400348 {
349 let mut v_snd: Vec<i32> = Vec::new();
350 v_snd.push(29384);
351 v_snd.push(238);
352 v_snd.push(32498);
353
354 let mut v_cmp: Vec<i32> = Vec::new();
355 v_cmp.push(29384);
356 v_cmp.push(238);
357 v_cmp.push(32498);
358
Allen Georgebc1344d2017-04-28 10:22:03 -0400359 verify_expected_result(thrift_test_client.test_list(v_snd), v_cmp)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400360 }
361
Allen Georgebc1344d2017-04-28 10:22:03 -0400362 info!("testSet");
Allen George8b96bfb2016-11-02 08:01:08 -0400363 {
364 let mut s_snd: BTreeSet<i32> = BTreeSet::new();
Allen George7ddbcc02020-11-08 09:51:19 -0500365 s_snd.insert(293_481);
Allen George8b96bfb2016-11-02 08:01:08 -0400366 s_snd.insert(23);
367 s_snd.insert(3234);
368
369 let mut s_cmp: BTreeSet<i32> = BTreeSet::new();
Allen George7ddbcc02020-11-08 09:51:19 -0500370 s_cmp.insert(293_481);
Allen George8b96bfb2016-11-02 08:01:08 -0400371 s_cmp.insert(23);
372 s_cmp.insert(3234);
373
Allen Georgebc1344d2017-04-28 10:22:03 -0400374 verify_expected_result(thrift_test_client.test_set(s_snd), s_cmp)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400375 }
376
Allen Georgebc1344d2017-04-28 10:22:03 -0400377 info!("testMap");
Allen George8b96bfb2016-11-02 08:01:08 -0400378 {
379 let mut m_snd: BTreeMap<i32, i32> = BTreeMap::new();
380 m_snd.insert(2, 4);
381 m_snd.insert(4, 6);
382 m_snd.insert(8, 7);
383
384 let mut m_cmp: BTreeMap<i32, i32> = BTreeMap::new();
385 m_cmp.insert(2, 4);
386 m_cmp.insert(4, 6);
387 m_cmp.insert(8, 7);
388
Allen Georgebc1344d2017-04-28 10:22:03 -0400389 verify_expected_result(thrift_test_client.test_map(m_snd), m_cmp)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400390 }
391
Allen Georgebc1344d2017-04-28 10:22:03 -0400392 info!("testStringMap");
Allen George8b96bfb2016-11-02 08:01:08 -0400393 {
394 let mut m_snd: BTreeMap<String, String> = BTreeMap::new();
395 m_snd.insert("2".to_owned(), "4_string".to_owned());
396 m_snd.insert("4".to_owned(), "6_string".to_owned());
397 m_snd.insert("8".to_owned(), "7_string".to_owned());
398
399 let mut m_rcv: BTreeMap<String, String> = BTreeMap::new();
400 m_rcv.insert("2".to_owned(), "4_string".to_owned());
401 m_rcv.insert("4".to_owned(), "6_string".to_owned());
402 m_rcv.insert("8".to_owned(), "7_string".to_owned());
403
Allen Georgebc1344d2017-04-28 10:22:03 -0400404 verify_expected_result(thrift_test_client.test_string_map(m_snd), m_rcv)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400405 }
406
407 // nested map
Allen George0e22c362017-01-30 07:15:00 -0500408 // expect : {-4 => {-4 => -4, -3 => -3, -2 => -2, -1 => -1, }, 4 => {1 => 1, 2
409 // => 2, 3 => 3, 4 => 4, }, }
Allen Georgebc1344d2017-04-28 10:22:03 -0400410 info!("testMapMap");
Allen George8b96bfb2016-11-02 08:01:08 -0400411 {
412 let mut m_cmp_nested_0: BTreeMap<i32, i32> = BTreeMap::new();
413 for i in (-4 as i32)..0 {
414 m_cmp_nested_0.insert(i, i);
415 }
416 let mut m_cmp_nested_1: BTreeMap<i32, i32> = BTreeMap::new();
417 for i in 1..5 {
418 m_cmp_nested_1.insert(i, i);
419 }
420
421 let mut m_cmp: BTreeMap<i32, BTreeMap<i32, i32>> = BTreeMap::new();
422 m_cmp.insert(-4, m_cmp_nested_0);
423 m_cmp.insert(4, m_cmp_nested_1);
424
Allen Georgebc1344d2017-04-28 10:22:03 -0400425 verify_expected_result(thrift_test_client.test_map_map(42), m_cmp)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400426 }
427
Allen Georgebc1344d2017-04-28 10:22:03 -0400428 info!("testMulti");
Allen George8b96bfb2016-11-02 08:01:08 -0400429 {
430 let mut m_snd: BTreeMap<i16, String> = BTreeMap::new();
431 m_snd.insert(1298, "fizz".to_owned());
432 m_snd.insert(-148, "buzz".to_owned());
433
434 let s_cmp = Xtruct {
435 string_thing: Some("Hello2".to_owned()),
436 byte_thing: Some(1),
Allen George7ddbcc02020-11-08 09:51:19 -0500437 i32_thing: Some(-123_948),
438 i64_thing: Some(-19_234_123_981),
Allen George8b96bfb2016-11-02 08:01:08 -0400439 };
440
Allen George0e22c362017-01-30 07:15:00 -0500441 verify_expected_result(
Allen George2e90ef52021-03-01 14:47:04 -0500442 thrift_test_client.test_multi(1, -123_948, -19_234_123_981, m_snd, Numberz::EIGHT, 81),
Allen George0e22c362017-01-30 07:15:00 -0500443 s_cmp,
444 )?;
Allen George8b96bfb2016-11-02 08:01:08 -0400445 }
446
447 // Insanity
448 // returns:
449 // { 1 => { 2 => argument,
450 // 3 => argument,
451 // },
452 // 2 => { 6 => <empty Insanity struct>, },
453 // }
454 {
455 let mut arg_map_usermap: BTreeMap<Numberz, i64> = BTreeMap::new();
Allen George2e90ef52021-03-01 14:47:04 -0500456 arg_map_usermap.insert(Numberz::ONE, 4289);
457 arg_map_usermap.insert(Numberz::EIGHT, 19);
Allen George8b96bfb2016-11-02 08:01:08 -0400458
459 let mut arg_vec_xtructs: Vec<Xtruct> = Vec::new();
Allen George55c3e4c2021-03-01 23:19:52 -0500460 arg_vec_xtructs.push(Xtruct {
461 string_thing: Some("foo".to_owned()),
462 byte_thing: Some(8),
463 i32_thing: Some(29),
464 i64_thing: Some(92384),
465 });
466 arg_vec_xtructs.push(Xtruct {
467 string_thing: Some("bar".to_owned()),
468 byte_thing: Some(28),
469 i32_thing: Some(2),
470 i64_thing: Some(-1281),
471 });
472 arg_vec_xtructs.push(Xtruct {
473 string_thing: Some("baz".to_owned()),
474 byte_thing: Some(0),
475 i32_thing: Some(3_948_539),
476 i64_thing: Some(-12_938_492),
477 });
Allen George8b96bfb2016-11-02 08:01:08 -0400478
479 let mut s_cmp_nested_1: BTreeMap<Numberz, Insanity> = BTreeMap::new();
480 let insanity = Insanity {
481 user_map: Some(arg_map_usermap),
482 xtructs: Some(arg_vec_xtructs),
483 };
Allen George2e90ef52021-03-01 14:47:04 -0500484 s_cmp_nested_1.insert(Numberz::TWO, insanity.clone());
485 s_cmp_nested_1.insert(Numberz::THREE, insanity.clone());
Allen George8b96bfb2016-11-02 08:01:08 -0400486
487 let mut s_cmp_nested_2: BTreeMap<Numberz, Insanity> = BTreeMap::new();
488 let empty_insanity = Insanity {
489 user_map: Some(BTreeMap::new()),
490 xtructs: Some(Vec::new()),
491 };
Allen George2e90ef52021-03-01 14:47:04 -0500492 s_cmp_nested_2.insert(Numberz::SIX, empty_insanity);
Allen George8b96bfb2016-11-02 08:01:08 -0400493
494 let mut s_cmp: BTreeMap<UserId, BTreeMap<Numberz, Insanity>> = BTreeMap::new();
495 s_cmp.insert(1 as UserId, s_cmp_nested_1);
496 s_cmp.insert(2 as UserId, s_cmp_nested_2);
497
Allen George7ddbcc02020-11-08 09:51:19 -0500498 verify_expected_result(thrift_test_client.test_insanity(insanity), s_cmp)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400499 }
500
Allen Georgebc1344d2017-04-28 10:22:03 -0400501 info!("testException - remote throws Xception");
Allen George8b96bfb2016-11-02 08:01:08 -0400502 {
Allen Georgebc1344d2017-04-28 10:22:03 -0400503 let r = thrift_test_client.test_exception("Xception".to_owned());
Allen George8b96bfb2016-11-02 08:01:08 -0400504 let x = match r {
Allen George55c3e4c2021-03-01 23:19:52 -0500505 Err(thrift::Error::User(ref e)) => match e.downcast_ref::<Xception>() {
506 Some(x) => Ok(x),
507 None => Err(thrift::Error::User(
508 "did not get expected Xception struct".into(),
509 )),
510 },
Allen George8b96bfb2016-11-02 08:01:08 -0400511 _ => Err(thrift::Error::User("did not get exception".into())),
512 }?;
513
514 let x_cmp = Xception {
515 error_code: Some(1001),
516 message: Some("Xception".to_owned()),
517 };
518
519 verify_expected_result(Ok(x), &x_cmp)?;
520 }
521
Allen Georgebc1344d2017-04-28 10:22:03 -0400522 info!("testException - remote throws TApplicationException");
Allen George8b96bfb2016-11-02 08:01:08 -0400523 {
Allen Georgebc1344d2017-04-28 10:22:03 -0400524 let r = thrift_test_client.test_exception("TException".to_owned());
Allen George8b96bfb2016-11-02 08:01:08 -0400525 match r {
526 Err(thrift::Error::Application(ref e)) => {
Allen Georgebc1344d2017-04-28 10:22:03 -0400527 info!("received an {:?}", e);
Allen George8b96bfb2016-11-02 08:01:08 -0400528 Ok(())
529 }
530 _ => Err(thrift::Error::User("did not get exception".into())),
531 }?;
532 }
533
Allen Georgebc1344d2017-04-28 10:22:03 -0400534 info!("testException - remote succeeds");
Allen George8b96bfb2016-11-02 08:01:08 -0400535 {
Allen Georgebc1344d2017-04-28 10:22:03 -0400536 let r = thrift_test_client.test_exception("foo".to_owned());
Allen George8b96bfb2016-11-02 08:01:08 -0400537 match r {
538 Ok(_) => Ok(()),
539 _ => Err(thrift::Error::User("received an exception".into())),
540 }?;
541 }
542
Allen Georgebc1344d2017-04-28 10:22:03 -0400543 info!("testMultiException - remote throws Xception");
Allen George8b96bfb2016-11-02 08:01:08 -0400544 {
Allen Georgebc1344d2017-04-28 10:22:03 -0400545 let r =
546 thrift_test_client.test_multi_exception("Xception".to_owned(), "ignored".to_owned());
Allen George8b96bfb2016-11-02 08:01:08 -0400547 let x = match r {
Allen George55c3e4c2021-03-01 23:19:52 -0500548 Err(thrift::Error::User(ref e)) => match e.downcast_ref::<Xception>() {
549 Some(x) => Ok(x),
550 None => Err(thrift::Error::User(
551 "did not get expected Xception struct".into(),
552 )),
553 },
Allen George8b96bfb2016-11-02 08:01:08 -0400554 _ => Err(thrift::Error::User("did not get exception".into())),
555 }?;
556
557 let x_cmp = Xception {
558 error_code: Some(1001),
559 message: Some("This is an Xception".to_owned()),
560 };
561
562 verify_expected_result(Ok(x), &x_cmp)?;
563 }
564
Allen Georgebc1344d2017-04-28 10:22:03 -0400565 info!("testMultiException - remote throws Xception2");
Allen George8b96bfb2016-11-02 08:01:08 -0400566 {
Allen Georgebc1344d2017-04-28 10:22:03 -0400567 let r =
568 thrift_test_client.test_multi_exception("Xception2".to_owned(), "ignored".to_owned());
Allen George8b96bfb2016-11-02 08:01:08 -0400569 let x = match r {
Allen George55c3e4c2021-03-01 23:19:52 -0500570 Err(thrift::Error::User(ref e)) => match e.downcast_ref::<Xception2>() {
571 Some(x) => Ok(x),
572 None => Err(thrift::Error::User(
573 "did not get expected Xception struct".into(),
574 )),
575 },
Allen George8b96bfb2016-11-02 08:01:08 -0400576 _ => Err(thrift::Error::User("did not get exception".into())),
577 }?;
578
579 let x_cmp = Xception2 {
580 error_code: Some(2002),
Allen George55c3e4c2021-03-01 23:19:52 -0500581 struct_thing: Some(Xtruct {
582 string_thing: Some("This is an Xception2".to_owned()),
583 // since this is an OPT_IN_REQ_OUT field the sender sets a default
584 byte_thing: Some(0),
585 // since this is an OPT_IN_REQ_OUT field the sender sets a default
586 i32_thing: Some(0),
587 // since this is an OPT_IN_REQ_OUT field the sender sets a default
588 i64_thing: Some(0),
589 }),
Allen George8b96bfb2016-11-02 08:01:08 -0400590 };
591
592 verify_expected_result(Ok(x), &x_cmp)?;
593 }
594
Allen Georgebc1344d2017-04-28 10:22:03 -0400595 info!("testMultiException - remote succeeds");
Allen George8b96bfb2016-11-02 08:01:08 -0400596 {
Allen Georgebc1344d2017-04-28 10:22:03 -0400597 let r = thrift_test_client.test_multi_exception("haha".to_owned(), "RETURNED".to_owned());
Allen George8b96bfb2016-11-02 08:01:08 -0400598 let x = match r {
Allen George55c3e4c2021-03-01 23:19:52 -0500599 Err(e) => Err(thrift::Error::User(
600 format!("received an unexpected exception {:?}", e).into(),
601 )),
Allen George8b96bfb2016-11-02 08:01:08 -0400602 _ => r,
603 }?;
604
605 let x_cmp = Xtruct {
606 string_thing: Some("RETURNED".to_owned()),
Allen George0e22c362017-01-30 07:15:00 -0500607 // since this is an OPT_IN_REQ_OUT field the sender sets a default
608 byte_thing: Some(0),
609 // since this is an OPT_IN_REQ_OUT field the sender sets a default
610 i32_thing: Some(0),
611 // since this is an OPT_IN_REQ_OUT field the sender sets a default
612 i64_thing: Some(0),
Allen George8b96bfb2016-11-02 08:01:08 -0400613 };
614
615 verify_expected_result(Ok(x), x_cmp)?;
616 }
617
Allen Georgebc1344d2017-04-28 10:22:03 -0400618 info!("testOneWay - remote sleeps for 1 second");
Allen George8b96bfb2016-11-02 08:01:08 -0400619 {
Allen Georgebc1344d2017-04-28 10:22:03 -0400620 thrift_test_client.test_oneway(1)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400621 }
622
Allen George0e22c362017-01-30 07:15:00 -0500623 // final test to verify that the connection is still writable after the one-way
624 // call
Allen Georgebc1344d2017-04-28 10:22:03 -0400625 thrift_test_client.test_void()
Allen George8b96bfb2016-11-02 08:01:08 -0400626}
627
Allen George0e22c362017-01-30 07:15:00 -0500628fn verify_expected_result<T: Debug + PartialEq + Sized>(
629 actual: Result<T, thrift::Error>,
630 expected: T,
631) -> Result<(), thrift::Error> {
James E. King, III20e16bc2017-11-18 22:37:54 -0500632 info!("*** EXPECTED: Ok({:?})", expected);
633 info!("*** ACTUAL : {:?}", actual);
Allen George8b96bfb2016-11-02 08:01:08 -0400634 match actual {
635 Ok(v) => {
636 if v == expected {
James E. King, III20e16bc2017-11-18 22:37:54 -0500637 info!("*** OK ***");
Allen George8b96bfb2016-11-02 08:01:08 -0400638 Ok(())
639 } else {
James E. King, III20e16bc2017-11-18 22:37:54 -0500640 info!("*** FAILED ***");
Allen George55c3e4c2021-03-01 23:19:52 -0500641 Err(thrift::Error::User(
642 format!("expected {:?} but got {:?}", &expected, &v).into(),
643 ))
Allen George8b96bfb2016-11-02 08:01:08 -0400644 }
645 }
646 Err(e) => Err(e),
647 }
648}