Skip to content

Commit 7fd9aa9

Browse files
committed
fix(virtq): move log tests to integration tests
1 parent 1f9ed50 commit 7fd9aa9

File tree

6 files changed

+174
-178
lines changed

6 files changed

+174
-178
lines changed

Justfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ test-unit target=default-target features="":
225225
test-isolated target=default-target features="" :
226226
{{ cargo-cmd }} 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 } }} {{ target-triple-flag }} -p hyperlight-host --lib -- sandbox::uninitialized::tests::test_log_trace --exact --ignored
227227
{{ cargo-cmd }} 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 } }} {{ target-triple-flag }} -p hyperlight-host --lib -- sandbox::outb::tests::test_log_outb_log --exact --ignored
228-
{{ cargo-cmd }} 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 } }} {{ target-triple-flag }} -p hyperlight-host --test integration_test -- log_message --exact --ignored
228+
{{ cargo-cmd }} 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 } }} {{ target-triple-flag }} -p hyperlight-host --test integration_test -- --test-threads=1 --ignored
229229
@# metrics tests
230230
{{ cargo-cmd }} 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 } }} {{ target-triple-flag }} -p hyperlight-host --lib -- metrics::tests::test_metrics_are_emitted --exact
231231

src/hyperlight_guest/src/virtq/context.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ use hyperlight_common::virtq::msg::{MsgKind, VirtqMsgHeader};
3333
use hyperlight_common::virtq::{
3434
self, BufferPool, Layout, Notifier, QueueStats, RecyclePool, Token, VirtqProducer,
3535
};
36-
use tracing::instrument;
37-
3836
use super::GuestMemOps;
3937
use crate::bail;
4038
use crate::error::Result;
@@ -121,7 +119,6 @@ impl GuestContext {
121119
///
122120
/// The reply guard is checked before submitting the readwrite chain
123121
/// to ensure G2H capacity is reserved for pending responses.
124-
#[instrument(skip_all, level = "Info")]
125122
pub fn call_host_function<T: TryFrom<ReturnValue>>(
126123
&mut self,
127124
function_name: &str,

src/hyperlight_guest/src/virtq/mod.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ limitations under the License.
2222
pub mod context;
2323
pub mod mem;
2424

25-
use core::cell::UnsafeCell;
25+
use core::cell::RefCell;
2626
use core::sync::atomic::{AtomicU8, Ordering};
2727

2828
use context::GuestContext;
@@ -31,14 +31,15 @@ pub use mem::GuestMemOps;
3131
// Init state machine
3232
const UNINITIALIZED: u8 = 0;
3333
const INITIALIZED: u8 = 1;
34+
3435
static INIT_STATE: AtomicU8 = AtomicU8::new(UNINITIALIZED);
36+
static GLOBAL_CONTEXT: SyncWrap<RefCell<Option<GuestContext>>> = SyncWrap(RefCell::new(None));
3537

36-
// Storage: UnsafeCell guarded by atomic init state.
38+
// Sync wrapper for the global context.
3739
struct SyncWrap<T>(T);
40+
/// SAFETY: The guest is single-threaded.
3841
unsafe impl<T> Sync for SyncWrap<T> {}
3942

40-
static GLOBAL_CONTEXT: SyncWrap<UnsafeCell<Option<GuestContext>>> = SyncWrap(UnsafeCell::new(None));
41-
4243
/// Check if the global context has been initialized.
4344
pub fn is_initialized() -> bool {
4445
INIT_STATE.load(Ordering::Acquire) == INITIALIZED
@@ -48,14 +49,14 @@ pub fn is_initialized() -> bool {
4849
///
4950
/// # Panics
5051
///
51-
/// Panics if the context has not been initialized.
52+
/// Panics if the context has not been initialized or re-entranted.
5253
pub fn with_context<R>(f: impl FnOnce(&mut GuestContext) -> R) -> R {
5354
assert!(
5455
INIT_STATE.load(Ordering::Acquire) == INITIALIZED,
5556
"guest context not initialized"
5657
);
57-
let ctx = unsafe { &mut *GLOBAL_CONTEXT.0.get() };
58-
f(ctx.as_mut().unwrap())
58+
let mut borrow = GLOBAL_CONTEXT.0.borrow_mut();
59+
f(borrow.as_mut().unwrap())
5960
}
6061

6162
/// Install the global guest context. Called once during guest init.
@@ -75,5 +76,5 @@ pub fn set_global_context(ctx: GuestContext) {
7576
{
7677
panic!("guest context already initialized");
7778
}
78-
unsafe { *GLOBAL_CONTEXT.0.get() = Some(ctx) };
79+
unsafe { *GLOBAL_CONTEXT.0.as_ptr() = Some(ctx) };
7980
}

src/hyperlight_guest_bin/src/host_comm.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,14 @@ use hyperlight_common::flatbuffer_wrappers::util::get_flatbuffer_result;
2828
use hyperlight_common::func::{ParameterTuple, SupportedReturnType};
2929
use hyperlight_guest::error::{HyperlightGuestError, Result};
3030
use hyperlight_guest::virtq;
31+
use tracing::instrument;
3132

3233
const BUFFER_SIZE: usize = 1000;
3334
static mut MESSAGE_BUFFER: Vec<u8> = Vec::new();
3435

3536
use crate::GUEST_HANDLE;
3637

38+
#[instrument(skip_all, level = "Info")]
3739
pub fn call_host_function<T>(
3840
function_name: &str,
3941
parameters: Option<Vec<ParameterValue>>,

src/hyperlight_host/tests/integration_test.rs

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub mod common; // pub to disable dead_code warning
3131
use crate::common::{
3232
new_rust_sandbox, new_rust_uninit_sandbox, with_all_sandboxes, with_c_sandbox,
3333
with_c_uninit_sandbox, with_rust_sandbox, with_rust_sandbox_cfg, with_rust_uninit_sandbox,
34+
with_rust_uninit_sandbox_cfg,
3435
};
3536

3637
// A host function cannot be interrupted, but we can at least make sure after requesting to interrupt a host call,
@@ -801,6 +802,167 @@ fn log_test_messages(levelfilter: Option<tracing_core::LevelFilter>) {
801802
}
802803
}
803804

805+
// The following tests depend on a global SimpleLogger or TracingSubscriber and
806+
// cannot run in parallel with other tests. They are marked #[ignore] and run
807+
// sequentially via `just test-isolated`.
808+
809+
#[test]
810+
#[ignore]
811+
fn virtq_log_delivery() {
812+
use hyperlight_testing::simplelogger::{LOGGER, SimpleLogger};
813+
814+
SimpleLogger::initialize_test_logger();
815+
LOGGER.clear_log_calls();
816+
817+
with_rust_uninit_sandbox(|mut sbox| {
818+
sbox.set_max_guest_log_level(tracing_core::LevelFilter::TRACE);
819+
let mut sandbox = sbox.evolve().unwrap();
820+
821+
sandbox
822+
.call::<()>("LogMessage", ("virtq log test message".to_string(), 3_i32))
823+
.unwrap();
824+
825+
let count = LOGGER.num_log_calls();
826+
let mut found = false;
827+
for i in 0..count {
828+
if let Some(call) = LOGGER.get_log_call(i)
829+
&& call.target == "hyperlight_guest"
830+
&& call.args.contains("virtq log test")
831+
{
832+
found = true;
833+
break;
834+
}
835+
}
836+
assert!(found, "expected 'virtq log test' message from guest");
837+
LOGGER.clear_log_calls();
838+
});
839+
}
840+
841+
#[test]
842+
#[ignore]
843+
fn virtq_log_backpressure() {
844+
use hyperlight_testing::simplelogger::{LOGGER, SimpleLogger};
845+
846+
SimpleLogger::initialize_test_logger();
847+
LOGGER.clear_log_calls();
848+
849+
let mut cfg = SandboxConfiguration::default();
850+
cfg.set_g2h_pool_pages(2);
851+
852+
with_rust_uninit_sandbox_cfg(cfg, |mut sbox| {
853+
sbox.set_max_guest_log_level(tracing_core::LevelFilter::INFO);
854+
let mut sandbox = sbox.evolve().unwrap();
855+
856+
sandbox.call::<()>("LogMessageN", 50_i32).unwrap();
857+
858+
let res: i32 = sandbox
859+
.call("ThisIsNotARealFunctionButTheNameIsImportant", ())
860+
.unwrap();
861+
assert_eq!(res, 99);
862+
863+
let guest_count = (0..LOGGER.num_log_calls())
864+
.filter_map(|i| LOGGER.get_log_call(i))
865+
.filter(|c| c.target == "hyperlight_guest" && c.args.contains("log entry"))
866+
.count();
867+
assert_eq!(guest_count, 50, "expected 50 guest logs, got {guest_count}");
868+
LOGGER.clear_log_calls();
869+
});
870+
}
871+
872+
#[test]
873+
#[ignore]
874+
fn virtq_log_backpressure_repeated() {
875+
let mut cfg = SandboxConfiguration::default();
876+
cfg.set_g2h_pool_pages(2);
877+
878+
with_rust_sandbox_cfg(cfg, |mut sandbox| {
879+
for _ in 0..5 {
880+
sandbox.call::<()>("LogMessageN", 30_i32).unwrap();
881+
}
882+
});
883+
}
884+
885+
#[test]
886+
#[ignore]
887+
fn virtq_backpressure_small_ring() {
888+
use hyperlight_testing::simplelogger::{LOGGER, SimpleLogger};
889+
890+
SimpleLogger::initialize_test_logger();
891+
LOGGER.clear_log_calls();
892+
893+
let mut cfg = SandboxConfiguration::default();
894+
cfg.set_g2h_queue_depth(4);
895+
896+
with_rust_uninit_sandbox_cfg(cfg, |mut sbox| {
897+
sbox.set_max_guest_log_level(tracing_core::LevelFilter::INFO);
898+
let mut sandbox = sbox.evolve().unwrap();
899+
900+
sandbox.call::<()>("LogMessageN", 20_i32).unwrap();
901+
902+
let guest_count = (0..LOGGER.num_log_calls())
903+
.filter_map(|i| LOGGER.get_log_call(i))
904+
.filter(|c| c.target == "hyperlight_guest" && c.args.contains("log entry"))
905+
.count();
906+
assert_eq!(guest_count, 20, "expected 20 guest logs, got {guest_count}");
907+
LOGGER.clear_log_calls();
908+
});
909+
}
910+
911+
#[test]
912+
#[ignore]
913+
fn virtq_log_tracing_delivery() {
914+
use hyperlight_testing::tracing_subscriber::TracingSubscriber;
915+
916+
let subscriber = TracingSubscriber::new(tracing::Level::TRACE);
917+
918+
tracing::subscriber::with_default(subscriber.clone(), || {
919+
with_rust_uninit_sandbox(|mut sbox| {
920+
sbox.set_max_guest_log_level(tracing_core::LevelFilter::INFO);
921+
let mut sandbox = sbox.evolve().unwrap();
922+
923+
subscriber.clear();
924+
925+
sandbox
926+
.call::<()>("LogMessage", ("tracing delivery test".to_string(), 3_i32))
927+
.unwrap();
928+
929+
let events = subscriber.get_events();
930+
assert!(
931+
!events.is_empty(),
932+
"expected tracing events after guest log call, got none"
933+
);
934+
});
935+
});
936+
}
937+
938+
#[test]
939+
#[ignore]
940+
fn virtq_log_tracing_levels() {
941+
use hyperlight_testing::tracing_subscriber::TracingSubscriber;
942+
943+
let subscriber = TracingSubscriber::new(tracing::Level::TRACE);
944+
945+
tracing::subscriber::with_default(subscriber.clone(), || {
946+
with_rust_uninit_sandbox(|mut sbox| {
947+
sbox.set_max_guest_log_level(tracing_core::LevelFilter::TRACE);
948+
let mut sandbox = sbox.evolve().unwrap();
949+
950+
for level in [1_i32, 2, 3, 4, 5] {
951+
subscriber.clear();
952+
let msg = format!("level-test-{}", level);
953+
sandbox.call::<()>("LogMessage", (msg, level)).unwrap();
954+
955+
let events = subscriber.get_events();
956+
assert!(
957+
!events.is_empty(),
958+
"expected tracing events for guest log level {}",
959+
level
960+
);
961+
}
962+
});
963+
});
964+
}
965+
804966
/// Tests whether host is able to return Bool as return type
805967
/// or not
806968
#[test]

0 commit comments

Comments
 (0)