Skip to content

Commit 5aff63c

Browse files
committed
chore(engine): roxiproxi tests
1 parent 298ede2 commit 5aff63c

11 files changed

Lines changed: 910 additions & 24 deletions

File tree

Cargo.lock

Lines changed: 255 additions & 20 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
@@ -64,6 +64,7 @@ pub struct TestOpts {
6464
pub timeout_secs: u64,
6565
pub pegboard_outbound: bool,
6666
pub auth_admin_token: Option<String>,
67+
pub network_faults: bool,
6768
}
6869

6970
impl TestOpts {
@@ -73,6 +74,7 @@ impl TestOpts {
7374
timeout_secs: 10,
7475
pegboard_outbound: false,
7576
auth_admin_token: None,
77+
network_faults: false,
7678
}
7779
}
7880

@@ -90,6 +92,11 @@ impl TestOpts {
9092
self.auth_admin_token = Some(token.into());
9193
self
9294
}
95+
96+
pub fn with_network_faults(mut self) -> Self {
97+
self.network_faults = true;
98+
self
99+
}
93100
}
94101

95102
impl Default for TestOpts {
@@ -99,13 +106,15 @@ impl Default for TestOpts {
99106
timeout_secs: 10,
100107
pegboard_outbound: false,
101108
auth_admin_token: None,
109+
network_faults: false,
102110
}
103111
}
104112
}
105113

106114
pub struct TestCtx {
107115
dcs: Vec<TestDatacenter>,
108116
pub opts: TestOpts,
117+
network_faults: Option<rivet_test_deps::ToxiproxyTestServer>,
109118
}
110119

111120
pub struct TestDatacenter {
@@ -157,7 +166,17 @@ impl TestCtx {
157166
let mut dcs: Vec<TestDatacenter> = futures_util::future::try_join_all(setup_futures).await?;
158167
dcs.sort_by_key(|dc| dc.config.dc_label());
159168

160-
Ok(Self { dcs, opts })
169+
let network_faults = if opts.network_faults {
170+
Some(rivet_test_deps::ToxiproxyTestServer::start().await?)
171+
} else {
172+
None
173+
};
174+
175+
Ok(Self {
176+
dcs,
177+
opts,
178+
network_faults,
179+
})
161180
}
162181

163182
async fn setup_instance(
@@ -262,6 +281,12 @@ impl TestCtx {
262281
.unwrap_or_else(|| panic!("No datacenter found with label {}", label))
263282
}
264283

284+
pub fn network_faults(&self) -> &rivet_test_deps::ToxiproxyTestServer {
285+
self.network_faults
286+
.as_ref()
287+
.expect("Network faults were not enabled. Use TestOpts::with_network_faults().")
288+
}
289+
265290
pub async fn shutdown(self) {
266291
tracing::info!("shutting down multi-DC test context");
267292
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,
@@ -526,6 +594,7 @@ pub struct TestEnvoyBuilder {
526594
namespace: String,
527595
pool_name: String,
528596
version: u32,
597+
endpoint: Option<String>,
529598
actor_factories: HashMap<String, ActorFactory>,
530599
}
531600

@@ -535,6 +604,7 @@ impl TestEnvoyBuilder {
535604
namespace: namespace.to_string(),
536605
pool_name: "test-envoy".to_string(),
537606
version: 1,
607+
endpoint: None,
538608
actor_factories: HashMap::new(),
539609
}
540610
}
@@ -549,6 +619,11 @@ impl TestEnvoyBuilder {
549619
self
550620
}
551621

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

561636
pub async fn build(self, dc: &super::TestDatacenter) -> Result<Envoy> {
562637
let config = EnvoyConfig::builder()
563-
.endpoint(format!("http://127.0.0.1:{}", dc.guard_port()))
638+
.endpoint(
639+
self.endpoint
640+
.unwrap_or_else(|| format!("http://127.0.0.1:{}", dc.guard_port())),
641+
)
564642
.token("dev")
565643
.namespace(&self.namespace)
566644
.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: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod auth;
2+
pub mod network_faults;
23
pub mod actors_alarm;
34
pub mod actors_kv_crud;
45
pub mod actors_kv_delete_range;

0 commit comments

Comments
 (0)