Skip to content

Commit 0460eb7

Browse files
NathanFlurryMasterPtato
authored andcommitted
chore(engine): roxiproxi tests
1 parent 395aa83 commit 0460eb7

11 files changed

Lines changed: 916 additions & 30 deletions

File tree

Cargo.lock

Lines changed: 260 additions & 26 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

engine/packages/engine/tests/common/ctx.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub struct TestOpts {
88
pub timeout_secs: u64,
99
pub pegboard_outbound: bool,
1010
pub auth_admin_token: Option<String>,
11+
pub network_faults: bool,
1112
}
1213

1314
impl TestOpts {
@@ -17,6 +18,7 @@ impl TestOpts {
1718
timeout_secs: 10,
1819
pegboard_outbound: false,
1920
auth_admin_token: None,
21+
network_faults: false,
2022
}
2123
}
2224

@@ -34,6 +36,11 @@ impl TestOpts {
3436
self.auth_admin_token = Some(token.into());
3537
self
3638
}
39+
40+
pub fn with_network_faults(mut self) -> Self {
41+
self.network_faults = true;
42+
self
43+
}
3744
}
3845

3946
impl Default for TestOpts {
@@ -43,13 +50,15 @@ impl Default for TestOpts {
4350
timeout_secs: 10,
4451
pegboard_outbound: false,
4552
auth_admin_token: None,
53+
network_faults: false,
4654
}
4755
}
4856
}
4957

5058
pub struct TestCtx {
5159
dcs: Vec<TestDatacenter>,
5260
pub opts: TestOpts,
61+
network_faults: Option<rivet_test_deps::ToxiproxyTestServer>,
5362
}
5463

5564
pub struct TestDatacenter {
@@ -99,7 +108,17 @@ impl TestCtx {
99108
futures_util::future::try_join_all(setup_futures).await?;
100109
dcs.sort_by_key(|dc| dc.config.dc_label());
101110

102-
Ok(Self { dcs, opts })
111+
let network_faults = if opts.network_faults {
112+
Some(rivet_test_deps::ToxiproxyTestServer::start().await?)
113+
} else {
114+
None
115+
};
116+
117+
Ok(Self {
118+
dcs,
119+
opts,
120+
network_faults,
121+
})
103122
}
104123

105124
async fn setup_instance(
@@ -204,6 +223,12 @@ impl TestCtx {
204223
.unwrap_or_else(|| panic!("No datacenter found with label {}", label))
205224
}
206225

226+
pub fn network_faults(&self) -> &rivet_test_deps::ToxiproxyTestServer {
227+
self.network_faults
228+
.as_ref()
229+
.expect("Network faults were not enabled. Use TestOpts::with_network_faults().")
230+
}
231+
207232
pub async fn shutdown(self) {
208233
tracing::info!("shutting down multi-DC test context");
209234
for dc in self.dcs {

engine/packages/engine/tests/common/test_envoy.rs

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,46 @@ type ActorFactory = Arc<dyn Fn(ActorConfig) -> Box<dyn TestActor> + Send + Sync>
2020

2121
pub type TestEnvoy = Envoy;
2222

23+
#[derive(Clone, Debug, PartialEq, Eq)]
24+
pub enum EnvoyConnectionEvent {
25+
Connected,
26+
Disconnected,
27+
}
28+
29+
pub struct EnvoyConnectionEventWaiter {
30+
rx: broadcast::Receiver<EnvoyConnectionEvent>,
31+
expected: EnvoyConnectionEvent,
32+
timeout: std::time::Duration,
33+
}
34+
35+
impl EnvoyConnectionEventWaiter {
36+
pub fn assert_no_event(&mut self) {
37+
match self.rx.try_recv() {
38+
Err(tokio::sync::broadcast::error::TryRecvError::Empty) => {}
39+
Ok(event) => panic!("unexpected Envoy connection event before fault: {event:?}"),
40+
Err(tokio::sync::broadcast::error::TryRecvError::Lagged(count)) => {
41+
panic!("missed {count} Envoy connection events before fault")
42+
}
43+
Err(err) => panic!("Envoy connection event channel closed: {err}"),
44+
}
45+
}
46+
47+
pub async fn wait(mut self) {
48+
tokio::time::timeout(self.timeout, async {
49+
loop {
50+
match self.rx.recv().await {
51+
Ok(event) if event == self.expected => break,
52+
Ok(_) => {}
53+
Err(tokio::sync::broadcast::error::RecvError::Lagged(_)) => {}
54+
Err(err) => panic!("Envoy connection event channel closed: {err}"),
55+
}
56+
}
57+
})
58+
.await
59+
.expect("timed out waiting for Envoy connection event");
60+
}
61+
}
62+
2363
#[derive(Clone)]
2464
pub struct EnvoyConfig {
2565
endpoint: String,
@@ -119,6 +159,7 @@ impl EnvoyBuilder {
119159
actor_factories: self.actor_factories,
120160
actors: tokio::sync::Mutex::new(HashMap::new()),
121161
lifecycle_tx,
162+
connection_tx: broadcast::channel(100).0,
122163
}),
123164
handle: tokio::sync::Mutex::new(None),
124165
envoy_key: uuid::Uuid::new_v4().to_string(),
@@ -130,6 +171,7 @@ struct EnvoyInner {
130171
actor_factories: HashMap<String, ActorFactory>,
131172
actors: tokio::sync::Mutex<HashMap<String, Box<dyn TestActor>>>,
132173
lifecycle_tx: broadcast::Sender<ActorLifecycleEvent>,
174+
connection_tx: broadcast::Sender<EnvoyConnectionEvent>,
133175
}
134176

135177
pub struct Envoy {
@@ -197,6 +239,21 @@ impl Envoy {
197239
self.inner.lifecycle_tx.subscribe()
198240
}
199241

242+
pub fn subscribe_connection_events(&self) -> broadcast::Receiver<EnvoyConnectionEvent> {
243+
self.inner.connection_tx.subscribe()
244+
}
245+
246+
pub fn wait_for_next_connection_event(
247+
&self,
248+
expected: EnvoyConnectionEvent,
249+
) -> EnvoyConnectionEventWaiter {
250+
EnvoyConnectionEventWaiter {
251+
rx: self.subscribe_connection_events(),
252+
expected,
253+
timeout: std::time::Duration::from_secs(20),
254+
}
255+
}
256+
200257
pub async fn shutdown(&self) {
201258
if let Some(handle) = self.handle.lock().await.take() {
202259
handle.shutdown_and_wait(false).await;
@@ -241,6 +298,17 @@ impl TestEnvoyCallbacks {
241298
}
242299

243300
impl rivet_test_envoy::EnvoyCallbacks for TestEnvoyCallbacks {
301+
fn on_connect(&self, _handle: EnvoyHandle) {
302+
let _ = self.inner.connection_tx.send(EnvoyConnectionEvent::Connected);
303+
}
304+
305+
fn on_disconnect(&self, _handle: EnvoyHandle) {
306+
let _ = self
307+
.inner
308+
.connection_tx
309+
.send(EnvoyConnectionEvent::Disconnected);
310+
}
311+
244312
fn on_actor_start(
245313
&self,
246314
handle: EnvoyHandle,
@@ -527,6 +595,7 @@ pub struct TestEnvoyBuilder {
527595
namespace: String,
528596
pool_name: String,
529597
version: u32,
598+
endpoint: Option<String>,
530599
actor_factories: HashMap<String, ActorFactory>,
531600
}
532601

@@ -536,6 +605,7 @@ impl TestEnvoyBuilder {
536605
namespace: namespace.to_string(),
537606
pool_name: "test-envoy".to_string(),
538607
version: 1,
608+
endpoint: None,
539609
actor_factories: HashMap::new(),
540610
}
541611
}
@@ -550,6 +620,11 @@ impl TestEnvoyBuilder {
550620
self
551621
}
552622

623+
pub fn with_endpoint(mut self, endpoint: impl Into<String>) -> Self {
624+
self.endpoint = Some(endpoint.into());
625+
self
626+
}
627+
553628
pub fn with_actor_behavior<F>(mut self, actor_name: &str, factory: F) -> Self
554629
where
555630
F: Fn(ActorConfig) -> Box<dyn TestActor> + Send + Sync + 'static,
@@ -561,7 +636,10 @@ impl TestEnvoyBuilder {
561636

562637
pub async fn build(self, dc: &super::TestDatacenter) -> Result<Envoy> {
563638
let config = EnvoyConfig::builder()
564-
.endpoint(format!("http://127.0.0.1:{}", dc.guard_port()))
639+
.endpoint(
640+
self.endpoint
641+
.unwrap_or_else(|| format!("http://127.0.0.1:{}", dc.guard_port())),
642+
)
565643
.token("dev")
566644
.namespace(&self.namespace)
567645
.pool_name(&self.pool_name)

engine/packages/engine/tests/common/test_helpers.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,31 @@
1-
use std::{collections::HashMap, str::FromStr};
1+
use std::{collections::HashMap, future::Future, str::FromStr};
22

33
use serde_json::json;
44

55
use super::TestDatacenter;
66

7+
pub async fn wait_with_poll<T, F, Fut>(
8+
timeout: std::time::Duration,
9+
poll_interval: std::time::Duration,
10+
mut check: F,
11+
) -> Option<T>
12+
where
13+
F: FnMut() -> Fut,
14+
Fut: Future<Output = Option<T>>,
15+
{
16+
tokio::time::timeout(timeout, async {
17+
loop {
18+
if let Some(value) = check().await {
19+
break value;
20+
}
21+
22+
tokio::time::sleep(poll_interval).await;
23+
}
24+
})
25+
.await
26+
.ok()
27+
}
28+
729
// Namespace helpers
830
pub async fn setup_test_namespace(leader_dc: &TestDatacenter) -> (String, rivet_util::Id) {
931
let random_suffix = rand::random::<u16>();

engine/packages/engine/tests/envoy/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ pub mod api_actors_get_or_create;
1111
pub mod api_actors_list;
1212
pub mod api_actors_list_names;
1313
pub mod auth;
14+
pub mod auth;
15+
pub mod network_faults;

0 commit comments

Comments
 (0)