Add mocking check support
This commit is contained in:
parent
6dc58f998c
commit
b2ecb115c0
|
@ -2,6 +2,15 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.70"
|
version = "1.0.70"
|
||||||
|
@ -122,6 +131,18 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "difflib"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "downcast"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.8.1"
|
version = "1.8.1"
|
||||||
|
@ -164,12 +185,27 @@ version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "float-cmp"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fragile"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.3.28"
|
version = "0.3.28"
|
||||||
|
@ -276,6 +312,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-stream",
|
"async-stream",
|
||||||
"futures",
|
"futures",
|
||||||
|
"mockall",
|
||||||
"prost",
|
"prost",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
|
@ -492,12 +529,54 @@ dependencies = [
|
||||||
"windows-sys 0.45.0",
|
"windows-sys 0.45.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mockall"
|
||||||
|
version = "0.11.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c84490118f2ee2d74570d114f3d0493cbf02790df303d2707606c3e14e07c96"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"downcast",
|
||||||
|
"fragile",
|
||||||
|
"lazy_static",
|
||||||
|
"mockall_derive",
|
||||||
|
"predicates",
|
||||||
|
"predicates-tree",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mockall_derive"
|
||||||
|
version = "0.11.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "22ce75669015c4f47b289fd4d4f56e894e4c96003ffdf3ac51313126f94c6cbb"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "multimap"
|
name = "multimap"
|
||||||
version = "0.8.3"
|
version = "0.8.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
|
checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "normalize-line-endings"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.17.1"
|
version = "1.17.1"
|
||||||
|
@ -558,6 +637,36 @@ version = "0.2.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "predicates"
|
||||||
|
version = "2.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd"
|
||||||
|
dependencies = [
|
||||||
|
"difflib",
|
||||||
|
"float-cmp",
|
||||||
|
"itertools",
|
||||||
|
"normalize-line-endings",
|
||||||
|
"predicates-core",
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "predicates-core"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "predicates-tree"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf"
|
||||||
|
dependencies = [
|
||||||
|
"predicates-core",
|
||||||
|
"termtree",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prettyplease"
|
name = "prettyplease"
|
||||||
version = "0.1.25"
|
version = "0.1.25"
|
||||||
|
@ -685,6 +794,8 @@ version = "1.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370"
|
checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
"regex-syntax",
|
"regex-syntax",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -780,6 +891,12 @@ dependencies = [
|
||||||
"windows-sys 0.45.0",
|
"windows-sys 0.45.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termtree"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.28.0"
|
version = "1.28.0"
|
||||||
|
|
|
@ -17,5 +17,8 @@ tokio-stream = { version = "0.1", features = ["sync"] }
|
||||||
tonic = { version = "0.9" }
|
tonic = { version = "0.9" }
|
||||||
prost = { version = "0.11" }
|
prost = { version = "0.11" }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
mockall = "0.11"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
tonic-build = { version = "0.9" }
|
tonic-build = { version = "0.9" }
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// SPDX-FileCopyrightText: 2023 Matteo Settenvini <matteo.settenvini@montecristosoftware.eu>
|
// SPDX-FileCopyrightText: 2023 Matteo Settenvini <matteo.settenvini@montecristosoftware.eu>
|
||||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
use tonic::transport::server::TcpIncoming;
|
||||||
|
|
||||||
mod pb {
|
mod pb {
|
||||||
tonic::include_proto!("package");
|
tonic::include_proto!("package");
|
||||||
}
|
}
|
||||||
|
@ -14,7 +16,6 @@ use {
|
||||||
std::pin::Pin,
|
std::pin::Pin,
|
||||||
std::sync::{Arc, Mutex, Weak},
|
std::sync::{Arc, Mutex, Weak},
|
||||||
tokio::sync::broadcast,
|
tokio::sync::broadcast,
|
||||||
tokio::task::JoinHandle,
|
|
||||||
tokio_stream::wrappers::BroadcastStream,
|
tokio_stream::wrappers::BroadcastStream,
|
||||||
tonic::{Request, Response, Status, Streaming},
|
tonic::{Request, Response, Status, Streaming},
|
||||||
};
|
};
|
||||||
|
@ -24,18 +25,22 @@ const RENDEZVOUS: &'static str = "[::1]:10000";
|
||||||
|
|
||||||
#[tokio::main(flavor = "current_thread")]
|
#[tokio::main(flavor = "current_thread")]
|
||||||
async fn main() -> Result<(), Box<dyn Error>> {
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let server_handle = run_server().await;
|
let url = RENDEZVOUS.parse()?;
|
||||||
Ok(server_handle.await.unwrap()?)
|
let incoming = tonic::transport::server::TcpIncoming::new(url, true, None)
|
||||||
|
.expect("Cannot bind server socket");
|
||||||
|
run_server(incoming).await?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run_server() -> JoinHandle<Result<(), tonic::transport::Error>> {
|
fn run_server(
|
||||||
|
incoming: TcpIncoming,
|
||||||
|
) -> impl std::future::Future<Output = Result<(), tonic::transport::Error>> {
|
||||||
use tonic::transport::Server;
|
use tonic::transport::Server;
|
||||||
|
|
||||||
let addr = RENDEZVOUS.parse().unwrap();
|
|
||||||
let service = MessageService::default();
|
let service = MessageService::default();
|
||||||
let svc_adapter = ServiceServer::new(service);
|
let svc_adapter = ServiceServer::new(service);
|
||||||
let builder = Server::builder().add_service(svc_adapter);
|
let builder = Server::builder().add_service(svc_adapter);
|
||||||
tokio::spawn(builder.serve(addr))
|
builder.serve_with_incoming(incoming)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
|
@ -94,24 +99,32 @@ mod test {
|
||||||
super::pb::service_client::ServiceClient,
|
super::pb::service_client::ServiceClient,
|
||||||
super::run_server,
|
super::run_server,
|
||||||
super::{Message, RENDEZVOUS},
|
super::{Message, RENDEZVOUS},
|
||||||
|
mockall::automock,
|
||||||
tonic::Request,
|
tonic::Request,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[automock]
|
||||||
|
trait MessageChecker {
|
||||||
|
fn check_contents(&self, msg: &Message);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn bidi_streaming() -> Result<(), Box<dyn std::error::Error>> {
|
async fn bidi_streaming() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let _server_handle = run_server().await;
|
let url = RENDEZVOUS.parse()?;
|
||||||
|
let incoming = tonic::transport::server::TcpIncoming::new(url, true, None)
|
||||||
|
.expect("Cannot bind server socket");
|
||||||
|
tokio::spawn(run_server(incoming));
|
||||||
|
|
||||||
// FIXME: avoid sleep waiting for server to start
|
const N_MESSAGES: usize = 20;
|
||||||
tokio::time::sleep(std::time::Duration::from_millis(200)).await;
|
const CLIENT_IDS: &[&str] = &["client AAA", "client BBB", "client CCC"];
|
||||||
|
|
||||||
async fn client(id: &str) {
|
async fn client(id: &str, mock: &MockMessageChecker) {
|
||||||
let mut client = ServiceClient::connect(format!("http://{}", RENDEZVOUS))
|
let addr = format!("http://{}", RENDEZVOUS);
|
||||||
.await
|
let mut client = ServiceClient::connect(addr).await.unwrap();
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let client_id = String::from(id);
|
let client_id = String::from(id);
|
||||||
let outbound = async_stream::stream! {
|
let outbound = async_stream::stream! {
|
||||||
for i in 1..21 {
|
for i in 1..(N_MESSAGES+1) {
|
||||||
tokio::task::yield_now().await;
|
tokio::task::yield_now().await;
|
||||||
let message = Message {
|
let message = Message {
|
||||||
contents: format!("{}: {}", client_id, i),
|
contents: format!("{}: {}", client_id, i),
|
||||||
|
@ -123,16 +136,31 @@ mod test {
|
||||||
|
|
||||||
let response = client.broadcaster(Request::new(outbound)).await.unwrap();
|
let response = client.broadcaster(Request::new(outbound)).await.unwrap();
|
||||||
let mut inbound = response.into_inner();
|
let mut inbound = response.into_inner();
|
||||||
|
|
||||||
while let Some(msg) = inbound.message().await.unwrap() {
|
while let Some(msg) = inbound.message().await.unwrap() {
|
||||||
println!("{} received {:?}", id, msg);
|
println!("{} received {:?}", id, msg);
|
||||||
|
mock.check_contents(&msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let c1 = client("client AAA");
|
let mut mock = MockMessageChecker::new();
|
||||||
let c2 = client("client BBB");
|
|
||||||
let c3 = client("client CCC");
|
let mut clients = vec![];
|
||||||
let _ = tokio::join!(c1, c2, c3);
|
for client_id in CLIENT_IDS.iter() {
|
||||||
|
for i in 1..(N_MESSAGES + 1) {
|
||||||
|
let expected = format!("{}: {}", client_id, i);
|
||||||
|
mock.expect_check_contents()
|
||||||
|
.times(CLIENT_IDS.len())
|
||||||
|
.withf(move |msg| msg.contents == expected)
|
||||||
|
.return_const(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for client_id in CLIENT_IDS {
|
||||||
|
let c = client(client_id, &mock);
|
||||||
|
clients.push(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = futures::future::join_all(clients).await;
|
||||||
println!("Exiting.");
|
println!("Exiting.");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue