@@ -85,9 +85,12 @@ 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_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