vmbase: integration_test: Use Android logger
Use the Android logger instead of env_logger in order for the logs of
vmbase_example to be part of the tests's capture logs (logcat_test*.txt)
as they were previously discarded.
Test: atest vmbase_example.integration_test
Change-Id: I9844c515e5ee54070bcead8670526f01fb8679ff
diff --git a/vmbase/example/Android.bp b/vmbase/example/Android.bp
index e9a3f98..0f1e66a 100644
--- a/vmbase/example/Android.bp
+++ b/vmbase/example/Android.bp
@@ -54,10 +54,11 @@
edition: "2021",
rustlibs: [
"android.system.virtualizationservice-rust",
+ "libandroid_logger",
"libanyhow",
- "libenv_logger",
"liblibc",
"liblog_rust",
+ "libnix",
"libvmclient",
],
data: [
diff --git a/vmbase/example/tests/test.rs b/vmbase/example/tests/test.rs
index 85e0213..57b68ed 100644
--- a/vmbase/example/tests/test.rs
+++ b/vmbase/example/tests/test.rs
@@ -25,8 +25,9 @@
use log::info;
use std::{
fs::File,
- io,
- os::unix::io::{AsRawFd, FromRawFd},
+ io::{self, BufRead, BufReader},
+ os::unix::io::FromRawFd,
+ panic, thread,
};
use vmclient::{DeathReason, VmInstance};
@@ -36,7 +37,14 @@
/// Runs the vmbase_example VM as an unprotected VM via VirtualizationService.
#[test]
fn test_run_example_vm() -> Result<(), Error> {
- env_logger::init();
+ android_logger::init_once(
+ android_logger::Config::default().with_tag("vmbase").with_min_level(log::Level::Debug),
+ );
+
+ // Redirect panic messages to logcat.
+ panic::set_hook(Box::new(|panic_info| {
+ log::error!("{}", panic_info);
+ }));
// We need to start the thread pool for Binder to work properly, especially link_to_death.
ProcessState::start_thread_pool();
@@ -62,8 +70,8 @@
platformVersion: "~1.0".to_string(),
taskProfiles: vec![],
});
- let console = duplicate_stdout()?;
- let log = duplicate_stdout()?;
+ let console = android_log_fd()?;
+ let log = android_log_fd()?;
let vm = VmInstance::create(service.as_ref(), &config, Some(console), Some(log), None)
.context("Failed to create VM")?;
vm.start().context("Failed to start VM")?;
@@ -76,17 +84,17 @@
Ok(())
}
-/// Safely duplicate the standard output file descriptor.
-fn duplicate_stdout() -> io::Result<File> {
- let stdout_fd = io::stdout().as_raw_fd();
- // Safe because this just duplicates a file descriptor which we know to be valid, and we check
- // for an error.
- let dup_fd = unsafe { libc::dup(stdout_fd) };
- if dup_fd < 0 {
- Err(io::Error::last_os_error())
- } else {
- // Safe because we have just duplicated the file descriptor so we own it, and `from_raw_fd`
- // takes ownership of it.
- Ok(unsafe { File::from_raw_fd(dup_fd) })
- }
+fn android_log_fd() -> io::Result<File> {
+ let (reader_fd, writer_fd) = nix::unistd::pipe()?;
+
+ // SAFETY: These are new FDs with no previous owner.
+ let reader = unsafe { File::from_raw_fd(reader_fd) };
+ let writer = unsafe { File::from_raw_fd(writer_fd) };
+
+ thread::spawn(|| {
+ for line in BufReader::new(reader).lines() {
+ info!("{}", line.unwrap());
+ }
+ });
+ Ok(writer)
}