Skip to content

Commit 661de86

Browse files
committed
Fix tests and examples that relied on timing out
Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
1 parent a45c35b commit 661de86

File tree

4 files changed

+88
-35
lines changed

4 files changed

+88
-35
lines changed

src/hyperlight_host/examples/logging/main.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,15 +82,27 @@ fn main() -> Result<()> {
8282
let no_op = Noop::<UninitializedSandbox, MultiUseSandbox>::default();
8383

8484
let mut multiuse_sandbox = usandbox.evolve(no_op)?;
85+
let interrupt_handle = multiuse_sandbox.interrupt_handle();
86+
87+
const NUM_CALLS: i32 = 5;
88+
let thread = std::thread::spawn(move || {
89+
for _ in 0..NUM_CALLS {
90+
// Sleep for a short time to allow the guest function to run.
91+
std::thread::sleep(std::time::Duration::from_millis(500));
92+
// Cancel the host function call.
93+
interrupt_handle.kill();
94+
}
95+
});
8596

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

88-
for _ in 0..5 {
99+
for _ in 0..NUM_CALLS {
89100
let mut ctx = multiuse_sandbox.new_call_context();
90101

91102
ctx.call::<()>("Spin", ()).unwrap_err();
92103
multiuse_sandbox = ctx.finish().unwrap();
93104
}
105+
thread.join().unwrap();
94106

95107
Ok(())
96108
}

src/hyperlight_host/examples/metrics/main.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ limitations under the License.
1515
*/
1616
#![allow(clippy::disallowed_macros)]
1717
extern crate hyperlight_host;
18+
use std::sync::{Arc, Barrier};
1819
use std::thread::{spawn, JoinHandle};
1920

2021
use hyperlight_host::sandbox::uninitialized::UninitializedSandbox;
@@ -95,12 +96,27 @@ fn do_hyperlight_stuff() {
9596
let no_op = Noop::<UninitializedSandbox, MultiUseSandbox>::default();
9697

9798
let mut multiuse_sandbox = usandbox.evolve(no_op).expect("Failed to evolve sandbox");
99+
let interrupt_handle = multiuse_sandbox.interrupt_handle();
100+
101+
const NUM_CALLS: i32 = 5;
102+
let barrier = Arc::new(Barrier::new(2));
103+
let barrier2 = barrier.clone();
104+
105+
let thread = std::thread::spawn(move || {
106+
for _ in 0..NUM_CALLS {
107+
barrier2.wait();
108+
// Sleep for a short time to allow the guest function to run after the `wait`.
109+
std::thread::sleep(std::time::Duration::from_millis(500));
110+
// Cancel the host function call.
111+
interrupt_handle.kill();
112+
}
113+
});
98114

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

101-
for _ in 0..5 {
117+
for _ in 0..NUM_CALLS {
102118
let mut ctx = multiuse_sandbox.new_call_context();
103-
119+
barrier.wait();
104120
ctx.call::<()>("Spin", ()).unwrap_err();
105121
multiuse_sandbox = ctx.finish().unwrap();
106122
}
@@ -109,6 +125,7 @@ fn do_hyperlight_stuff() {
109125
let result = join_handle.join();
110126
assert!(result.is_ok());
111127
}
128+
thread.join().unwrap();
112129
}
113130

114131
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
@@ -110,8 +110,18 @@ fn run_example() -> Result<()> {
110110
let no_op = Noop::<UninitializedSandbox, MultiUseSandbox>::default();
111111

112112
let mut multiuse_sandbox = usandbox.evolve(no_op)?;
113+
let interrupt_handle = multiuse_sandbox.interrupt_handle();
113114

114115
// Call a function that gets cancelled by the host function 5 times to generate some log entries.
116+
const NUM_CALLS: i32 = 5;
117+
let thread = std::thread::spawn(move || {
118+
for _ in 0..NUM_CALLS {
119+
// Sleep for a short time to allow the guest function to run.
120+
std::thread::sleep(std::time::Duration::from_millis(500));
121+
// Cancel the host function call.
122+
interrupt_handle.kill();
123+
}
124+
});
115125

116126
for i in 0..5 {
117127
let id = Uuid::new_v4();
@@ -133,6 +143,7 @@ fn run_example() -> Result<()> {
133143
let result = join_handle.join();
134144
assert!(result.is_ok());
135145
}
146+
thread.join().unwrap();
136147

137148
Ok(())
138149
}

src/hyperlight_host/src/metrics/mod.rs

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,11 @@ 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_testing::simple_guest_as_string;
89-
use metrics::Key;
92+
use metrics::{with_local_recorder, Key};
9093
use metrics_util::CompositeKey;
9194

9295
use super::*;
@@ -95,24 +98,24 @@ mod tests {
9598
use crate::{GuestBinary, UninitializedSandbox};
9699

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

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

117120
multi
118121
.call_guest_function_by_name::<i32>("PrintOutput", "Hello".to_string())
@@ -121,9 +124,10 @@ mod tests {
121124
multi
122125
.call_guest_function_by_name::<i32>("Spin", ())
123126
.unwrap_err();
127+
thread.join().unwrap();
124128

125129
snapshotter.snapshot()
126-
};
130+
});
127131

128132
// Convert snapshot into a hashmap for easier lookup
129133
#[expect(clippy::mutable_key_type)]
@@ -132,27 +136,17 @@ mod tests {
132136
cfg_if::cfg_if! {
133137
if #[cfg(feature = "function_call_metrics")] {
134138
use metrics::Label;
135-
// Verify that the histogram metrics are recorded correctly
136-
assert_eq!(snapshot.len(), 4, "Expected two metrics in the snapshot");
137139

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

155-
// 2. Guest call duration
146+
// Verify that the histogram metrics are recorded correctly
147+
assert_eq!(snapshot.len(), expected_num_metrics);
148+
149+
// 1. Guest call duration
156150
let histogram_key = CompositeKey::new(
157151
metrics_util::MetricKind::Histogram,
158152
Key::from_parts(
@@ -169,7 +163,7 @@ mod tests {
169163
"Histogram metric does not match expected value"
170164
);
171165

172-
// 3. Guest cancellation
166+
// 2. Guest cancellation
173167
let counter_key = CompositeKey::new(
174168
metrics_util::MetricKind::Counter,
175169
Key::from_name(METRIC_GUEST_CANCELLATION),
@@ -179,7 +173,7 @@ mod tests {
179173
metrics_util::debugging::DebugValue::Counter(1)
180174
);
181175

182-
// 4. Guest call duration
176+
// 3. Guest call duration
183177
let histogram_key = CompositeKey::new(
184178
metrics_util::MetricKind::Histogram,
185179
Key::from_parts(
@@ -195,9 +189,28 @@ mod tests {
195189
),
196190
"Histogram metric does not match expected value"
197191
);
192+
193+
if !cfg!(all(feature = "seccomp", target_os = "linux")) {
194+
// 4. Host call duration
195+
let histogram_key = CompositeKey::new(
196+
metrics_util::MetricKind::Histogram,
197+
Key::from_parts(
198+
METRIC_HOST_FUNC_DURATION,
199+
vec![Label::new("function_name", "HostPrint")],
200+
),
201+
);
202+
let histogram_value = &snapshot.get(&histogram_key).unwrap().2;
203+
assert!(
204+
matches!(
205+
histogram_value,
206+
metrics_util::debugging::DebugValue::Histogram(histogram) if histogram.len() == 1
207+
),
208+
"Histogram metric does not match expected value"
209+
);
210+
}
198211
} else {
199212
// Verify that the counter metrics are recorded correctly
200-
assert_eq!(snapshot.len(), 1, "Expected two metrics in the snapshot");
213+
assert_eq!(snapshot.len(), 1);
201214

202215
let counter_key = CompositeKey::new(
203216
metrics_util::MetricKind::Counter,

0 commit comments

Comments
 (0)