blob: be5f1180160d657ebb77594e390aeb178527326d [file] [log] [blame]
David Brazdil66fc1202022-07-04 21:48:45 +01001// Copyright 2022, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Integration test for Rialto.
16
17use android_system_virtualizationservice::{
18 aidl::android::system::virtualizationservice::{
David Brazdil7d1e5ec2023-02-06 17:56:29 +000019 CpuTopology::CpuTopology, VirtualMachineConfig::VirtualMachineConfig,
David Brazdil66fc1202022-07-04 21:48:45 +010020 VirtualMachineRawConfig::VirtualMachineRawConfig,
21 },
22 binder::{ParcelFileDescriptor, ProcessState},
23};
Alan Stokesdfca76c2022-08-03 13:31:47 +010024use anyhow::{anyhow, Context, Error};
David Brazdil66fc1202022-07-04 21:48:45 +010025use log::info;
26use std::fs::File;
27use std::io::{self, BufRead, BufReader};
28use std::os::unix::io::FromRawFd;
29use std::panic;
30use std::thread;
Alan Stokesdfca76c2022-08-03 13:31:47 +010031use std::time::Duration;
David Brazdil66fc1202022-07-04 21:48:45 +010032use vmclient::{DeathReason, VmInstance};
33
34const RIALTO_PATH: &str = "/data/local/tmp/rialto_test/arm64/rialto.bin";
35
Alan Stokes8d39a9b2023-01-10 15:01:00 +000036/// Runs the Rialto VM as a non-protected VM via VirtualizationService.
David Brazdil66fc1202022-07-04 21:48:45 +010037#[test]
38fn test_boots() -> Result<(), Error> {
39 android_logger::init_once(
40 android_logger::Config::default().with_tag("rialto").with_min_level(log::Level::Debug),
41 );
42
43 // Redirect panic messages to logcat.
44 panic::set_hook(Box::new(|panic_info| {
45 log::error!("{}", panic_info);
46 }));
47
48 // We need to start the thread pool for Binder to work properly, especially link_to_death.
49 ProcessState::start_thread_pool();
50
David Brazdil4b4c5102022-12-19 22:56:20 +000051 let virtmgr =
52 vmclient::VirtualizationService::new().context("Failed to spawn VirtualizationService")?;
53 let service = virtmgr.connect().context("Failed to connect to VirtualizationService")?;
54
David Brazdil66fc1202022-07-04 21:48:45 +010055 let rialto = File::open(RIALTO_PATH).context("Failed to open Rialto kernel binary")?;
56 let console = android_log_fd()?;
57 let log = android_log_fd()?;
58
59 let config = VirtualMachineConfig::RawConfig(VirtualMachineRawConfig {
Seungjae Yoo62085c02022-08-12 04:44:52 +000060 name: String::from("RialtoTest"),
David Brazdil66fc1202022-07-04 21:48:45 +010061 kernel: None,
62 initrd: None,
63 params: None,
64 bootloader: Some(ParcelFileDescriptor::new(rialto)),
65 disks: vec![],
66 protectedVm: false,
67 memoryMib: 300,
David Brazdil7d1e5ec2023-02-06 17:56:29 +000068 cpuTopology: CpuTopology::ONE_CPU,
David Brazdil66fc1202022-07-04 21:48:45 +010069 platformVersion: "~1.0".to_string(),
70 taskProfiles: vec![],
Nikita Ioffe5776f082023-02-10 21:38:26 +000071 gdbPort: 0, // No gdb
David Brazdil66fc1202022-07-04 21:48:45 +010072 });
Alan Stokes0e82b502022-08-08 14:44:48 +010073 let vm = VmInstance::create(service.as_ref(), &config, Some(console), Some(log), None)
David Brazdil66fc1202022-07-04 21:48:45 +010074 .context("Failed to create VM")?;
75
76 vm.start().context("Failed to start VM")?;
77
78 // Wait for VM to finish, and check that it shut down cleanly.
Alan Stokesdfca76c2022-08-03 13:31:47 +010079 let death_reason = vm
80 .wait_for_death_with_timeout(Duration::from_secs(10))
81 .ok_or_else(|| anyhow!("Timed out waiting for VM exit"))?;
David Brazdil66fc1202022-07-04 21:48:45 +010082 assert_eq!(death_reason, DeathReason::Shutdown);
83
84 Ok(())
85}
86
87fn android_log_fd() -> io::Result<File> {
88 let (reader_fd, writer_fd) = nix::unistd::pipe()?;
89
90 // SAFETY: These are new FDs with no previous owner.
91 let reader = unsafe { File::from_raw_fd(reader_fd) };
92 let writer = unsafe { File::from_raw_fd(writer_fd) };
93
94 thread::spawn(|| {
95 for line in BufReader::new(reader).lines() {
96 info!("{}", line.unwrap());
97 }
98 });
99 Ok(writer)
100}