From a8cef2e903258adf6a34175a01a62a781f98a58f Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 2 May 2017 19:45:47 +0300 Subject: [PATCH 1/3] failing test for response > 8kb --- ipc/src/server.rs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/ipc/src/server.rs b/ipc/src/server.rs index ae10f7f84..93c766ff7 100644 --- a/ipc/src/server.rs +++ b/ipc/src/server.rs @@ -323,4 +323,36 @@ mod tests { let core = Core::new().expect("Tokio Core should be created with no errors"); assert!(UnixStream::connect(path, &core.handle()).is_err(), "Connection to the closed socket should fail"); } + + #[test] + fn test_huge_response() { + let path = "/tmp/test-ipc-60000"; + + let mut io = MetaIoHandler::<()>::default(); + io.add_method("say_huge_hello", |_params| { + let mut str_response = String::from("begin_hello"); + str_response.push_str("begin_hello"); + for _ in 0..8192 { str_response.push(' '); } + str_response.push_str("end_hello"); + Ok(Value::String(str_response)) + }); + let builder = ServerBuilder::new(io); + + let _server = builder.start(path).expect("Server must run with no issues"); + thread::sleep(::std::time::Duration::from_millis(50)); + + let result = dummy_request_str(&path, + b"{\"jsonrpc\": \"2.0\", \"method\": \"say_huge_hello\", \"params\": [], \"id\": 1}\n", + ); + + assert_eq!( + result, + "{\"jsonrpc\":\"2.0\",\"result\":\"hello\",\"id\":1}\n", + "Response does not exactly much the expected response", + ); + + } + + + } From ba4c6f74f15a81d4a22030f308ad7744ab65cc2d Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 2 May 2017 21:08:43 +0300 Subject: [PATCH 2/3] test little refactoring, fix huge test --- ipc/src/server.rs | 63 +++++++++++++++++++++++------------------ ipc/src/stream_codec.rs | 6 +++- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/ipc/src/server.rs b/ipc/src/server.rs index 93c766ff7..2507b0967 100644 --- a/ipc/src/server.rs +++ b/ipc/src/server.rs @@ -193,10 +193,11 @@ mod tests { use std::thread; use super::{ServerBuilder, Server}; use jsonrpc::{MetaIoHandler, Value}; - use jsonrpc::futures::{Future, future}; + use jsonrpc::futures::{Future, future, Stream, Sink}; use self::tokio_uds::UnixStream; use server_utils::tokio_core::reactor::Core; - use server_utils::tokio_io::io; + use server_utils::tokio_io::AsyncRead; + use stream_codec::StreamCodec; fn server_builder() -> ServerBuilder { let mut io = MetaIoHandler::<()>::default(); @@ -213,25 +214,21 @@ mod tests { server } - fn dummy_request(path: &str, data: &[u8]) -> Vec { + fn dummy_request_str(path: &str, data: &str) -> String { let mut core = Core::new().expect("Tokio Core should be created with no errors"); - let mut buffer = vec![0u8; 1024]; let stream = UnixStream::connect(path, &core.handle()).expect("Should have been connected to the server"); - let reqrep = io::write_all(stream, data) - .and_then(|(stream, _)| { - io::read(stream, &mut buffer) + let (writer, reader) = stream.framed(StreamCodec).split(); + let reply = writer + .send(data.to_owned()) + .and_then(move |_| { + reader.into_future().map_err(|(err, _)| err) }) - .and_then(|(_, read_buf, len)| { - future::ok(read_buf[0..len].to_vec()) + .and_then(|(reply, _)| { + future::ok(reply.expect("there should be one reply")) }); - let result = core.run(reqrep).expect("Core should run with no errors"); - result - } - - fn dummy_request_str(path: &str, data: &[u8]) -> String { - String::from_utf8(dummy_request(path, data)).expect("String should be utf-8") + core.run(reply).unwrap() } #[test] @@ -266,12 +263,12 @@ mod tests { let result = dummy_request_str( path, - b"{\"jsonrpc\": \"2.0\", \"method\": \"say_hello\", \"params\": [42, 23], \"id\": 1}\n", + "{\"jsonrpc\": \"2.0\", \"method\": \"say_hello\", \"params\": [42, 23], \"id\": 1}", ); assert_eq!( result, - "{\"jsonrpc\":\"2.0\",\"result\":\"hello\",\"id\":1}\n", + "{\"jsonrpc\":\"2.0\",\"result\":\"hello\",\"id\":1}", "Response does not exactly much the expected response", ); } @@ -292,12 +289,12 @@ mod tests { for _ in 0..100 { let result = dummy_request_str( &path, - b"{\"jsonrpc\": \"2.0\", \"method\": \"say_hello\", \"params\": [42, 23], \"id\": 1}\n", + "{\"jsonrpc\": \"2.0\", \"method\": \"say_hello\", \"params\": [42, 23], \"id\": 1}", ); assert_eq!( result, - "{\"jsonrpc\":\"2.0\",\"result\":\"hello\",\"id\":1}\n", + "{\"jsonrpc\":\"2.0\",\"result\":\"hello\",\"id\":1}", "Response does not exactly much the expected response", ); @@ -324,17 +321,29 @@ mod tests { assert!(UnixStream::connect(path, &core.handle()).is_err(), "Connection to the closed socket should fail"); } + fn huge_response_test_str() -> String { + let mut result = String::from("begin_hello"); + result.push_str("begin_hello"); + for _ in 0..16384 { result.push(' '); } + result.push_str("end_hello"); + result + } + + fn huge_response_test_json() -> String { + let mut result = String::from("{\"jsonrpc\":\"2.0\",\"result\":\""); + result.push_str(&huge_response_test_str()); + result.push_str("\",\"id\":1}"); + + result + } + #[test] fn test_huge_response() { let path = "/tmp/test-ipc-60000"; let mut io = MetaIoHandler::<()>::default(); io.add_method("say_huge_hello", |_params| { - let mut str_response = String::from("begin_hello"); - str_response.push_str("begin_hello"); - for _ in 0..8192 { str_response.push(' '); } - str_response.push_str("end_hello"); - Ok(Value::String(str_response)) + Ok(Value::String(huge_response_test_str())) }); let builder = ServerBuilder::new(io); @@ -342,14 +351,14 @@ mod tests { thread::sleep(::std::time::Duration::from_millis(50)); let result = dummy_request_str(&path, - b"{\"jsonrpc\": \"2.0\", \"method\": \"say_huge_hello\", \"params\": [], \"id\": 1}\n", + "{\"jsonrpc\": \"2.0\", \"method\": \"say_huge_hello\", \"params\": [], \"id\": 1}", ); assert_eq!( result, - "{\"jsonrpc\":\"2.0\",\"result\":\"hello\",\"id\":1}\n", + huge_response_test_json(), "Response does not exactly much the expected response", - ); + ); } diff --git a/ipc/src/stream_codec.rs b/ipc/src/stream_codec.rs index c42f19c24..54c6c4d97 100644 --- a/ipc/src/stream_codec.rs +++ b/ipc/src/stream_codec.rs @@ -62,8 +62,12 @@ impl Encoder for StreamCodec { type Error = io::Error; fn encode(&mut self, msg: String, buf: &mut BytesMut) -> io::Result<()> { + let total_length = msg.as_bytes().len() + 1; + if buf.remaining_mut() < total_length { + buf.reserve(total_length); + } buf.put_slice(msg.as_bytes()); - buf.put(b'\n'); // for #4750 + buf.put(b'\n'); Ok(()) } } From 46f2c290fd7de32e94d419876f4eed4f2c02b78f Mon Sep 17 00:00:00 2001 From: NikVolf Date: Thu, 4 May 2017 09:12:02 +0300 Subject: [PATCH 3/3] fix typo --- ipc/src/server.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ipc/src/server.rs b/ipc/src/server.rs index 2507b0967..24005bac2 100644 --- a/ipc/src/server.rs +++ b/ipc/src/server.rs @@ -269,7 +269,7 @@ mod tests { assert_eq!( result, "{\"jsonrpc\":\"2.0\",\"result\":\"hello\",\"id\":1}", - "Response does not exactly much the expected response", + "Response does not exactly match the expected response", ); } @@ -295,7 +295,7 @@ mod tests { assert_eq!( result, "{\"jsonrpc\":\"2.0\",\"result\":\"hello\",\"id\":1}", - "Response does not exactly much the expected response", + "Response does not exactly match the expected response", ); ::std::thread::sleep(::std::time::Duration::from_millis(10)); @@ -357,7 +357,7 @@ mod tests { assert_eq!( result, huge_response_test_json(), - "Response does not exactly much the expected response", + "Response does not exactly match the expected response", ); }