@@ -85,8 +85,11 @@ pub(crate) fn maybe_time_and_emit_host_call<T, F: FnOnce() -> T>(
8585
8686#[ cfg( test) ]
8787mod 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