Skip to content

Commit 0604b95

Browse files
committed
Fix up tests that rely on timeout-based cancellation
Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
1 parent da99173 commit 0604b95

File tree

5 files changed

+84
-37
lines changed

5 files changed

+84
-37
lines changed

Justfile

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,7 @@ test-isolated target=default-target features="":
8888
cargo test {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--no-default-features -F " + features } }} --profile={{ if target == "debug" { "dev" } else { target } }} -p hyperlight-host --lib -- mem::shared_mem::tests::test_drop --exact --ignored
8989
cargo test {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--no-default-features -F " + features } }} --profile={{ if target == "debug" { "dev" } else { target } }} -p hyperlight-host --test integration_test -- log_message --exact --ignored
9090
@# metrics tests
91-
cargo test {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--no-default-features -F " + features } }} --profile={{ if target == "debug" { "dev" } else { target } }} -p hyperlight-host --lib -- metrics::tests::test_metrics_are_emitted --exact --ignored
92-
cargo test {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--no-default-features -F function_call_metrics," + features } }} --profile={{ if target == "debug" { "dev" } else { target } }} -p hyperlight-host --lib -- metrics::tests::test_metrics_are_emitted --exact --ignored
93-
91+
cargo test {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--no-default-features -F function_call_metrics," + features } }} --profile={{ if target == "debug" { "dev" } else { target } }} -p hyperlight-host --lib -- metrics::tests::test_metrics_are_emitted --exact
9492
# runs integration tests. Guest can either be "rust" or "c"
9593
test-integration guest target=default-target features="":
9694
@# run execute_on_heap test with feature "executable_heap" on and off

src/hyperlight_host/examples/logging/main.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,17 +89,29 @@ fn main() -> Result<()> {
8989
let no_op = Noop::<UninitializedSandbox, MultiUseSandbox>::default();
9090

9191
let mut multiuse_sandbox = usandbox.evolve(no_op)?;
92+
let interrupt_handle = multiuse_sandbox.interrupt_handle();
93+
94+
const NUM_CALLS: i32 = 5;
95+
let thread = std::thread::spawn(move || {
96+
for _ in 0..NUM_CALLS {
97+
// Sleep for a short time to allow the guest function to run.
98+
std::thread::sleep(std::time::Duration::from_millis(500));
99+
// Cancel the host function call.
100+
interrupt_handle.kill();
101+
}
102+
});
92103

93104
// Call a function that gets cancelled by the host function 5 times to generate some log entries.
94105

95-
for _ in 0..5 {
106+
for _ in 0..NUM_CALLS {
96107
let mut ctx = multiuse_sandbox.new_call_context();
97108

98109
let result = ctx.call("Spin", ReturnType::Void, None);
99110
assert!(result.is_err());
100111
let result = ctx.finish();
101112
multiuse_sandbox = result.unwrap();
102113
}
114+
thread.join().unwrap();
103115

104116
Ok(())
105117
}

src/hyperlight_host/examples/metrics/main.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,22 @@ fn do_hyperlight_stuff() {
102102
let no_op = Noop::<UninitializedSandbox, MultiUseSandbox>::default();
103103

104104
let mut multiuse_sandbox = usandbox.evolve(no_op).expect("Failed to evolve sandbox");
105+
let interrupt_handle = multiuse_sandbox.interrupt_handle();
106+
107+
const NUM_CALLS: i32 = 5;
108+
109+
let thread = std::thread::spawn(move || {
110+
for _ in 0..NUM_CALLS {
111+
// Sleep for a short time to allow the guest function to run.
112+
std::thread::sleep(std::time::Duration::from_millis(500));
113+
// Cancel the host function call.
114+
interrupt_handle.kill();
115+
}
116+
});
105117

106118
// Call a function that gets cancelled by the host function 5 times to generate some metrics.
107119

108-
for _ in 0..5 {
120+
for _ in 0..NUM_CALLS {
109121
let mut ctx = multiuse_sandbox.new_call_context();
110122

111123
let result = ctx.call("Spin", ReturnType::Void, None);
@@ -119,6 +131,7 @@ fn do_hyperlight_stuff() {
119131
let result = join_handle.join();
120132
assert!(result.is_ok());
121133
}
134+
thread.join().unwrap();
122135
}
123136

124137
fn fn_writer(_msg: String) -> Result<i32> {

src/hyperlight_host/examples/tracing/main.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,18 @@ fn run_example() -> Result<()> {
117117
let no_op = Noop::<UninitializedSandbox, MultiUseSandbox>::default();
118118

119119
let mut multiuse_sandbox = usandbox.evolve(no_op)?;
120+
let interrupt_handle = multiuse_sandbox.interrupt_handle();
120121

121122
// Call a function that gets cancelled by the host function 5 times to generate some log entries.
123+
const NUM_CALLS: i32 = 5;
124+
let thread = std::thread::spawn(move || {
125+
for _ in 0..NUM_CALLS {
126+
// Sleep for a short time to allow the guest function to run.
127+
std::thread::sleep(std::time::Duration::from_millis(500));
128+
// Cancel the host function call.
129+
interrupt_handle.kill();
130+
}
131+
});
122132

123133
for i in 0..5 {
124134
let id = Uuid::new_v4();
@@ -143,6 +153,7 @@ fn run_example() -> Result<()> {
143153
let result = join_handle.join();
144154
assert!(result.is_ok());
145155
}
156+
thread.join().unwrap();
146157

147158
Ok(())
148159
}

src/hyperlight_host/src/metrics/mod.rs

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,12 @@ pub(crate) fn maybe_time_and_emit_host_call<T, F: FnOnce() -> T>(
8585

8686
#[cfg(test)]
8787
mod tests {
88+
use std::thread;
89+
use std::time::Duration;
90+
8891
use hyperlight_common::flatbuffer_wrappers::function_types::{ParameterValue, ReturnType};
8992
use hyperlight_testing::simple_guest_as_string;
90-
use metrics::Key;
93+
use metrics::{with_local_recorder, Key};
9194
use metrics_util::CompositeKey;
9295

9396
use super::*;
@@ -96,24 +99,24 @@ mod tests {
9699
use crate::{GuestBinary, UninitializedSandbox};
97100

98101
#[test]
99-
#[ignore = "This test needs to be run separately to avoid having other tests interfere with it"]
100102
fn test_metrics_are_emitted() {
101-
// Set up the recorder and snapshotter
102103
let recorder = metrics_util::debugging::DebuggingRecorder::new();
103104
let snapshotter = recorder.snapshotter();
104-
105-
// we cannot use with_local_recorder, since that won't capture the metrics
106-
// emitted by the hypervisor-thread (which is all of them)
107-
recorder.install().unwrap();
108-
109-
let snapshot = {
105+
let snapshot = with_local_recorder(&recorder, || {
110106
let uninit = UninitializedSandbox::new(
111107
GuestBinary::FilePath(simple_guest_as_string().unwrap()),
112108
None,
113109
)
114110
.unwrap();
115111

116112
let mut multi = uninit.evolve(Noop::default()).unwrap();
113+
let interrupt_handle = multi.interrupt_handle();
114+
115+
// interrupt the guest function call to "Spin" after 1 second
116+
let thread = thread::spawn(move || {
117+
thread::sleep(Duration::from_secs(1));
118+
assert!(interrupt_handle.kill());
119+
});
117120

118121
multi
119122
.call_guest_function_by_name(
@@ -126,9 +129,10 @@ mod tests {
126129
multi
127130
.call_guest_function_by_name("Spin", ReturnType::Int, None)
128131
.unwrap_err();
132+
thread.join().unwrap();
129133

130134
snapshotter.snapshot()
131-
};
135+
});
132136

133137
// Convert snapshot into a hashmap for easier lookup
134138
#[expect(clippy::mutable_key_type)]
@@ -137,27 +141,17 @@ mod tests {
137141
cfg_if::cfg_if! {
138142
if #[cfg(feature = "function_call_metrics")] {
139143
use metrics::Label;
140-
// Verify that the histogram metrics are recorded correctly
141-
assert_eq!(snapshot.len(), 4, "Expected two metrics in the snapshot");
142144

143-
// 1. Host print duration
144-
let histogram_key = CompositeKey::new(
145-
metrics_util::MetricKind::Histogram,
146-
Key::from_parts(
147-
METRIC_HOST_FUNC_DURATION,
148-
vec![Label::new("function_name", "HostPrint")],
149-
),
150-
);
151-
let histogram_value = &snapshot.get(&histogram_key).unwrap().2;
152-
assert!(
153-
matches!(
154-
histogram_value,
155-
metrics_util::debugging::DebugValue::Histogram(ref histogram) if histogram.len() == 1
156-
),
157-
"Histogram metric does not match expected value"
158-
);
145+
let expected_num_metrics = if cfg!(all(feature = "seccomp", target_os = "linux")) {
146+
3 // if seccomp enabled, the host call duration metric is emitted on a separate thread which this local recorder doesn't capture
147+
} else {
148+
4
149+
};
159150

160-
// 2. Guest call duration
151+
// Verify that the histogram metrics are recorded correctly
152+
assert_eq!(snapshot.len(), expected_num_metrics);
153+
154+
// 1. Guest call duration
161155
let histogram_key = CompositeKey::new(
162156
metrics_util::MetricKind::Histogram,
163157
Key::from_parts(
@@ -174,7 +168,7 @@ mod tests {
174168
"Histogram metric does not match expected value"
175169
);
176170

177-
// 3. Guest cancellation
171+
// 2. Guest cancellation
178172
let counter_key = CompositeKey::new(
179173
metrics_util::MetricKind::Counter,
180174
Key::from_name(METRIC_GUEST_CANCELLATION),
@@ -184,7 +178,7 @@ mod tests {
184178
metrics_util::debugging::DebugValue::Counter(1)
185179
);
186180

187-
// 4. Guest call duration
181+
// 3. Guest call duration
188182
let histogram_key = CompositeKey::new(
189183
metrics_util::MetricKind::Histogram,
190184
Key::from_parts(
@@ -200,9 +194,28 @@ mod tests {
200194
),
201195
"Histogram metric does not match expected value"
202196
);
197+
198+
if !cfg!(all(feature = "seccomp", target_os = "linux")) {
199+
// 4. Host call duration
200+
let histogram_key = CompositeKey::new(
201+
metrics_util::MetricKind::Histogram,
202+
Key::from_parts(
203+
METRIC_HOST_FUNC_DURATION,
204+
vec![Label::new("function_name", "HostPrint")],
205+
),
206+
);
207+
let histogram_value = &snapshot.get(&histogram_key).unwrap().2;
208+
assert!(
209+
matches!(
210+
histogram_value,
211+
metrics_util::debugging::DebugValue::Histogram(ref histogram) if histogram.len() == 1
212+
),
213+
"Histogram metric does not match expected value"
214+
);
215+
}
203216
} else {
204217
// Verify that the counter metrics are recorded correctly
205-
assert_eq!(snapshot.len(), 1, "Expected two metrics in the snapshot");
218+
assert_eq!(snapshot.len(), 1);
206219

207220
let counter_key = CompositeKey::new(
208221
metrics_util::MetricKind::Counter,

0 commit comments

Comments
 (0)