Skip to content

Commit bff3355

Browse files
committed
qos_core: add enclave timout test
also fix small nits
1 parent ff0dd77 commit bff3355

File tree

6 files changed

+106
-19
lines changed

6 files changed

+106
-19
lines changed

src/init/init.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ async fn main() {
7070
);
7171

7272
const START_PORT: u32 = 3;
73-
const INITIAL_POOL_SIZE: u32 = 1; // start at pool size 1, grow based on manifest/args as necessary (see Reaper)
73+
const INITIAL_POOL_SIZE: u8 = 1; // start at pool size 1, grow based on manifest/args as necessary (see Reaper)
7474
let core_pool = StreamPool::new(
7575
SocketAddress::new_vsock(cid, START_PORT, VMADDR_NO_FLAGS),
7676
INITIAL_POOL_SIZE,

src/integration/tests/enclave_app_client_socket_stress.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ async fn enclave_app_client_socket_stress() {
103103
StreamPool::single(SocketAddress::new_unix(ENCLAVE_SOCK)).unwrap();
104104
let enclave_client = SocketClient::new(
105105
enclave_client_pool.shared(),
106-
INITIAL_CLIENT_TIMEOUT + Duration::from_secs(3), // needs to be bigger than the sdlow request below + some time for recovery
106+
INITIAL_CLIENT_TIMEOUT + Duration::from_secs(3), // needs to be bigger than the slow request below + some time for recovery
107107
);
108108

109109
let app_request =

src/integration/tests/reaper.rs

Lines changed: 102 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1-
use std::fs;
1+
use std::{fs, time::Duration};
22

33
use integration::{
4-
wait_for_usock, PIVOT_ABORT_PATH, PIVOT_OK_PATH, PIVOT_PANIC_PATH,
5-
PIVOT_POOL_SIZE_PATH,
4+
wait_for_usock, PivotSocketStressMsg, PIVOT_ABORT_PATH, PIVOT_OK_PATH,
5+
PIVOT_PANIC_PATH, PIVOT_POOL_SIZE_PATH, PIVOT_SOCKET_STRESS_PATH,
66
};
77
use qos_core::{
8+
client::SocketClient,
89
handles::Handles,
910
io::{SocketAddress, StreamPool},
10-
protocol::services::boot::ManifestEnvelope,
11+
protocol::{
12+
msg::ProtocolMsg, services::boot::ManifestEnvelope, ProtocolError,
13+
ProtocolPhase,
14+
},
1115
reaper::{Reaper, REAPER_EXIT_DELAY},
1216
};
1317
use qos_nsm::mock::MockNsm;
@@ -16,7 +20,6 @@ use qos_test_primitives::PathWrapper;
1620
#[tokio::test]
1721
async fn reaper_works() {
1822
let secret_path: PathWrapper = "/tmp/reaper_works.secret".into();
19-
// let eph_path = "reaper_works.eph.key";
2023
let usock: PathWrapper = "/tmp/reaper_works.sock".into();
2124
let manifest_path: PathWrapper = "/tmp/reaper_works.manifest".into();
2225
let msg = "durp-a-durp";
@@ -36,16 +39,15 @@ async fn reaper_works() {
3639
let mut manifest_envelope = ManifestEnvelope::default();
3740
manifest_envelope.manifest.pivot.args =
3841
vec!["--msg".to_string(), msg.to_string()];
39-
manifest_envelope.manifest.client_timeout_ms = Some(2000); // check if this gets applied
4042

4143
handles.put_manifest_envelope(&manifest_envelope).unwrap();
4244
assert!(handles.pivot_exists());
4345

4446
let enclave_pool =
45-
StreamPool::new(SocketAddress::new_unix(&usock), 1).unwrap();
47+
StreamPool::single(SocketAddress::new_unix(&usock)).unwrap();
4648

4749
let app_pool =
48-
StreamPool::new(SocketAddress::new_unix("./never.sock"), 1).unwrap();
50+
StreamPool::single(SocketAddress::new_unix("./never.sock")).unwrap();
4951

5052
let reaper_handle = tokio::spawn(async move {
5153
Reaper::execute(
@@ -59,7 +61,7 @@ async fn reaper_works() {
5961
});
6062

6163
// Give the enclave server time to bind to the socket
62-
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
64+
wait_for_usock(&usock).await;
6365

6466
// Check that the reaper is still running, presumably waiting for
6567
// the secret.
@@ -76,6 +78,94 @@ async fn reaper_works() {
7678
assert!(fs::remove_file(integration::PIVOT_OK_SUCCESS_FILE).is_ok());
7779
}
7880

81+
#[tokio::test]
82+
async fn reaper_timeout_works() {
83+
let secret_path: PathWrapper = "/tmp/reaper_timeout_works.secret".into();
84+
let enclave_sock: PathWrapper = "/tmp/reaper_timeout_works.sock".into();
85+
let app_sock: PathWrapper = "/tmp/reaper_timeout_works_app.sock".into();
86+
let manifest_path: PathWrapper =
87+
"/tmp/reaper_timeout_works.manifest".into();
88+
89+
// clean up old manifest if it's left from a panic
90+
drop(std::fs::remove_file(&*manifest_path));
91+
92+
// For our sanity, ensure the secret does not yet exist
93+
drop(fs::remove_file(&*secret_path));
94+
95+
let handles = Handles::new(
96+
"eph_path".to_string(),
97+
(*secret_path).to_string(),
98+
(*manifest_path).to_string(),
99+
PIVOT_SOCKET_STRESS_PATH.to_string(),
100+
);
101+
102+
// Make sure we have written everything necessary to pivot, except the
103+
// quorum key
104+
let mut manifest_envelope = ManifestEnvelope::default();
105+
// Tell pivot where to open up the server app socket
106+
manifest_envelope.manifest.pivot.args = vec![app_sock.to_string()];
107+
108+
// we'll be checking if this is set by passing slow and fast requests
109+
manifest_envelope.manifest.client_timeout_ms = Some(2000);
110+
111+
handles.put_manifest_envelope(&manifest_envelope).unwrap();
112+
assert!(handles.pivot_exists());
113+
114+
let enclave_pool =
115+
StreamPool::single(SocketAddress::new_unix(&enclave_sock)).unwrap();
116+
117+
let app_pool =
118+
StreamPool::single(SocketAddress::new_unix(&app_sock)).unwrap();
119+
120+
let reaper_handle = tokio::spawn(async move {
121+
Reaper::execute(
122+
&handles,
123+
Box::new(MockNsm),
124+
enclave_pool,
125+
app_pool,
126+
Some(ProtocolPhase::QuorumKeyProvisioned),
127+
)
128+
.await;
129+
});
130+
131+
// Give the enclave server time to bind to the socket
132+
wait_for_usock(&enclave_sock).await;
133+
134+
// Check that the reaper is still running, presumably waiting for
135+
// the secret.
136+
assert!(!reaper_handle.is_finished());
137+
138+
// Create the file with the secret, which should cause the reaper
139+
// to start executable.
140+
fs::write(&*secret_path, b"super dank tank secret tech").unwrap();
141+
142+
// Give the app server time to bind to the socket
143+
wait_for_usock(&app_sock).await;
144+
145+
// create a "slow" app request longer than client timeout from `Manifest`, but longer than 5s timeout on our local client.
146+
let app_request =
147+
borsh::to_vec(&PivotSocketStressMsg::SlowRequest(3000)).unwrap();
148+
let request =
149+
borsh::to_vec(&ProtocolMsg::ProxyRequest { data: app_request })
150+
.unwrap();
151+
152+
// ensure our client to the enclave has longer timeout than the configured 2s and the slow request 3s
153+
let client = SocketClient::single(
154+
SocketAddress::new_unix(&enclave_sock),
155+
Duration::from_millis(5000),
156+
)
157+
.unwrap();
158+
159+
let response: ProtocolMsg =
160+
borsh::from_slice(&client.call(&request).await.unwrap()).unwrap();
161+
162+
// The response should be AppClientRecvTimeout which indicates the enclave short-circuited the timeout
163+
assert_eq!(
164+
response,
165+
ProtocolMsg::ProtocolErrorResponse(ProtocolError::AppClientRecvTimeout)
166+
);
167+
}
168+
79169
#[tokio::test]
80170
async fn reaper_handles_non_zero_exits() {
81171
let secret_path: PathWrapper =
@@ -117,7 +207,7 @@ async fn reaper_handles_non_zero_exits() {
117207
});
118208

119209
// Give the enclave server time to bind to the socket
120-
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
210+
wait_for_usock(&usock).await;
121211

122212
// Check that the reaper is still running, presumably waiting for
123213
// the secret.
@@ -174,7 +264,7 @@ async fn reaper_handles_panic() {
174264
});
175265

176266
// Give the enclave server time to bind to the socket
177-
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
267+
wait_for_usock(&usock).await;
178268

179269
// Check that the reaper is still running, presumably waiting for
180270
// the secret.
@@ -195,11 +285,10 @@ async fn reaper_handles_panic() {
195285
async fn reaper_handles_pool_size() {
196286
let secret_path: PathWrapper =
197287
"/tmp/reaper_handles_pool_size.secret".into();
198-
// let eph_path = "reaper_works.eph.key";
199288
let usock: PathWrapper = "/tmp/reaper_handles_pool_size.sock".into();
200289
let manifest_path: PathWrapper =
201290
"/tmp/reaper_handles_pool_size.manifest".into();
202-
let msg = "5"; // must match pool-size in manifest bellow (test thing)
291+
let msg = "5"; // must match pool-size in manifest below (test thing)
203292

204293
// For our sanity, ensure the secret does not yet exist
205294
drop(fs::remove_file(&*secret_path));

src/integration/tests/simple_socket_stress.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ async fn simple_socket_stress() {
2222

2323
wait_for_usock(SOCKET_STRESS_SOCK).await;
2424

25-
// needs to be long enough for process exit to register and not cause a timeout
26-
2725
let app_pool =
2826
StreamPool::new(SocketAddress::new_unix(SOCKET_STRESS_SOCK), 1)
2927
.unwrap();

src/qos_core/src/io/pool.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ impl StreamPool {
6565
/// Create a new `StreamPool` with given starting `SocketAddress`, timeout and number of addresses to populate.
6666
pub fn new(
6767
start_address: SocketAddress,
68-
mut count: u32,
68+
mut count: u8,
6969
) -> Result<Self, IOError> {
7070
eprintln!("StreamPool start address: {start_address}");
7171

src/qos_net/src/cli.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ impl ProxyOpts {
3737
pub(crate) fn async_pool(
3838
&self,
3939
) -> Result<StreamPool, qos_core::io::IOError> {
40-
let pool_size: u32 = self
40+
let pool_size: u8 = self
4141
.parsed
4242
.single(POOL_SIZE)
4343
.expect("invalid pool options")

0 commit comments

Comments
 (0)