87 lines
3.0 KiB
Rust
87 lines
3.0 KiB
Rust
// Copyright 2022 The ChromiumOS Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
use fixture::vm::Config;
|
|
use fixture::vm::TestVm;
|
|
use tempfile::tempdir;
|
|
|
|
// Tests for suspend/resume.
|
|
//
|
|
// System-wide suspend/resume, snapshot/restore.
|
|
// Tests below check for snapshot/restore functionality, and suspend/resume.
|
|
|
|
#[ignore]
|
|
#[test]
|
|
fn suspend_snapshot_restore_resume() -> anyhow::Result<()> {
|
|
let mut vm = TestVm::new(Config::new()).unwrap();
|
|
suspend_resume_system(&mut vm)
|
|
}
|
|
|
|
#[ignore]
|
|
#[test]
|
|
fn suspend_snapshot_restore_resume_disable_sandbox() -> anyhow::Result<()> {
|
|
let mut vm = TestVm::new(Config::new().disable_sandbox()).unwrap();
|
|
suspend_resume_system(&mut vm)
|
|
}
|
|
|
|
fn suspend_resume_system(vm: &mut TestVm) -> anyhow::Result<()> {
|
|
// WARNING: Suspend/resume is only partially implemented, some aspects of these tests only work
|
|
// by chance. Still, the tests are useful to avoid backslide. If a seemingly unrelated change
|
|
// breaks this test, it is probably reasonable to disable the test.
|
|
|
|
// Verify RAM is saved and restored by interacting with a filesystem pinned in RAM (i.e. tmpfs
|
|
// with swap disabled).
|
|
vm.exec_in_guest("swapoff -a").unwrap();
|
|
vm.exec_in_guest("mount -t tmpfs none /tmp").unwrap();
|
|
|
|
vm.exec_in_guest("echo foo > /tmp/foo").unwrap();
|
|
assert_eq!("foo", vm.exec_in_guest("cat /tmp/foo").unwrap().trim());
|
|
|
|
// Take snapshot of original VM state
|
|
println!("snapshotting VM - clean state");
|
|
let dir = tempdir().unwrap();
|
|
let snap1_path = dir.path().join("snapshot.bkp");
|
|
vm.snapshot(&snap1_path).unwrap();
|
|
|
|
vm.exec_in_guest("echo bar > /tmp/foo").unwrap();
|
|
assert_eq!("bar", vm.exec_in_guest("cat /tmp/foo").unwrap().trim());
|
|
|
|
// suspend VM
|
|
vm.suspend().unwrap();
|
|
let snap2_path = dir.path().join("snapshot2.bkp");
|
|
|
|
// Write command to VM
|
|
// This command will get queued and not run while the VM is suspended. The command is saved in
|
|
// the serial device. After the snapshot is taken, the VM is resumed. At that point, the
|
|
// command runs and is validated.
|
|
let echo_cmd = vm.exec_in_guest_async("echo 42").unwrap();
|
|
// Take snapshot of modified VM
|
|
println!("snapshotting VM - mod state");
|
|
vm.snapshot(&snap2_path).unwrap();
|
|
|
|
vm.resume().unwrap();
|
|
assert_eq!("42", echo_cmd.wait(vm).unwrap());
|
|
|
|
// suspend VM
|
|
vm.suspend().unwrap();
|
|
// restore VM
|
|
println!("restoring VM - to clean state");
|
|
vm.restore(&snap1_path).unwrap();
|
|
|
|
// snapshot VM after restore
|
|
println!("snapshotting VM - clean state restored");
|
|
let snap3_path = dir.path().join("snapshot3.bkp");
|
|
vm.snapshot(&snap3_path).unwrap();
|
|
vm.resume().unwrap();
|
|
|
|
assert_eq!("foo", vm.exec_in_guest("cat /tmp/foo").unwrap().trim());
|
|
|
|
let snap1 = std::fs::read_to_string(&snap1_path).unwrap();
|
|
let snap2 = std::fs::read_to_string(&snap2_path).unwrap();
|
|
let snap3 = std::fs::read_to_string(&snap3_path).unwrap();
|
|
assert_ne!(snap1, snap2);
|
|
assert_eq!(snap1, snap3);
|
|
Ok(())
|
|
}
|