blob: c087f9b5846834af926bb2b3d0cba55c24bdbe10 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_VIRTUALIZATION_LIB_GUEST_INTERACTION_TEST_INTEGRATION_TEST_LIB_H_
#define SRC_VIRTUALIZATION_LIB_GUEST_INTERACTION_TEST_INTEGRATION_TEST_LIB_H_
#include <fuchsia/net/stack/cpp/fidl.h>
#include <fuchsia/netstack/cpp/fidl.h>
#include <fuchsia/sysinfo/cpp/fidl.h>
#include <fuchsia/virtualization/cpp/fidl.h>
#include <lib/sys/cpp/testing/enclosing_environment.h>
#include <lib/sys/cpp/testing/test_with_environment.h>
#include <src/virtualization/bin/vmm/guest_config.h>
#include <src/virtualization/tests/fake_netstack.h>
#include <src/virtualization/tests/guest_console.h>
static constexpr char kGuestLabel[] = "debian_guest";
static constexpr char kGuestManagerUrl[] =
"fuchsia-pkg://fuchsia.com/guest_manager#meta/guest_manager.cmx";
static constexpr char kDebianGuestUrl[] =
"fuchsia-pkg://fuchsia.com/debian_guest#meta/debian_guest.cmx";
static constexpr char kGuestDiscoveryUrl[] =
"fuchsia-pkg://fuchsia.com/guest_discovery_service#meta/guest_discovery_service.cmx";
// The host will copy kTestScriptSource to kGuestScriptDestination on the
// guest. The host will then ask the guest to exec kGuestScriptDestination
// and feed kTestScriptInput to the guest process's stdin. The script will
// will echo kTestStdout to stdout, kTestStderr to stderr, and kTestScriptInput
// to kGuestFileOutputLocation. The host will
// download the file to kHostOuputCopyLocation.
static constexpr char kTestScriptSource[] = "/pkg/data/test_script.sh";
static constexpr char kGuestScriptDestination[] = "/root/input/test_script.sh";
static constexpr char kTestStdout[] = "stdout";
static constexpr char kTestStderr[] = "stderr";
static constexpr char kTestScriptInput[] = "hello world\n";
static constexpr char kGuestFileOutputLocation[] = "/root/output/script_output.txt";
static constexpr char kHostOuputCopyLocation[] = "/data/copy";
class GuestInteractionTest : public sys::testing::TestWithEnvironment {
public:
void CreateEnvironment() {
ASSERT_TRUE(services_ && !env_);
env_ = CreateNewEnclosingEnvironment("GuestInteractionEnvironment", std::move(services_));
}
void LaunchDebianGuest() {
// Launch the Debian guest
fuchsia::virtualization::LaunchInfo guest_launch_info;
guest_launch_info.url = kDebianGuestUrl;
guest_launch_info.label = kGuestLabel;
guest_launch_info.guest_config.set_virtio_gpu(false);
fuchsia::virtualization::ManagerPtr guest_environment_manager;
fuchsia::virtualization::GuestPtr guest_instance_controller;
cid_ = -1;
env_->ConnectToService(guest_environment_manager.NewRequest());
guest_environment_manager->Create(fuchsia::netemul::guest::DEFAULT_REALM, realm_.NewRequest());
realm_->LaunchInstance(std::move(guest_launch_info), guest_instance_controller.NewRequest(),
[&](uint32_t callback_cid) { cid_ = callback_cid; });
ASSERT_TRUE(RunLoopWithTimeoutOrUntil([this]() { return cid_ >= 0; }, zx::sec(5)));
// Start a GuestConsole. When the console starts, it waits until it
// receives some sensible output from the guest to ensure that the guest is
// usable.
zx::socket socket;
guest_instance_controller->GetSerial([&socket](zx::socket s) { socket = std::move(s); });
ASSERT_TRUE(RunLoopWithTimeoutOrUntil([&socket] { return socket.is_valid(); }, zx::sec(30)));
GuestConsole serial(std::make_unique<ZxSocket>(std::move(socket)));
zx_status_t status = serial.Start();
ASSERT_EQ(status, ZX_OK);
// Wait until sysctl shows that the guest_interaction_daemon is running.
RunLoopUntil([&status, &serial]() -> bool {
std::string output;
status = serial.ExecuteBlocking("journalctl -u guest_interaction_daemon | grep Listening",
"$", &output);
// If the command cannot be executed, break out of the loop so the test can fail.
if (status != ZX_OK) {
return true;
}
// Ensure that the output from the command indicates that guest_interaction_daemon is
// active.
if (output.find("Listening") != std::string::npos) {
return true;
}
return false;
});
ASSERT_EQ(status, ZX_OK);
}
uint32_t cid_;
fuchsia::virtualization::RealmPtr realm_;
std::unique_ptr<sys::testing::EnvironmentServices> services_;
std::unique_ptr<sys::testing::EnclosingEnvironment> env_;
FakeNetstack fake_netstack_;
protected:
void SetUp() {
services_ = CreateServices();
// Add Netstack services
services_->AddService(fake_netstack_.GetHandler(), fuchsia::netstack::Netstack::Name_);
services_->AddService(fake_netstack_.GetHandler(), fuchsia::net::stack::Stack::Name_);
// Add guest service
fuchsia::sys::LaunchInfo guest_manager_launch_info;
guest_manager_launch_info.url = kGuestManagerUrl;
guest_manager_launch_info.out = sys::CloneFileDescriptor(1);
guest_manager_launch_info.err = sys::CloneFileDescriptor(2);
services_->AddServiceWithLaunchInfo(std::move(guest_manager_launch_info),
fuchsia::virtualization::Manager::Name_);
// Allow sysinfo service
services_->AllowParentService(fuchsia::sysinfo::SysInfo::Name_);
}
};
#endif // SRC_VIRTUALIZATION_LIB_GUEST_INTERACTION_TEST_INTEGRATION_TEST_LIB_H_