blob: c60769bfdde306272e65605e774924901da839f2 [file]
// Copyright 2020 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.
#include <dirent.h>
#include <fcntl.h>
#include <fidl/fuchsia.hardware.btitest/cpp/wire.h>
#include <fuchsia/driver/test/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/ddk/platform-defs.h>
#include <lib/driver_test_realm/realm_builder/cpp/lib.h>
#include <lib/fdio/cpp/caller.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/watcher.h>
#include <lib/sys/component/cpp/testing/realm_builder.h>
#include <lib/sys/component/cpp/testing/realm_builder_types.h>
#include <lib/zx/time.h>
#include <zircon/boot/image.h>
#include <zircon/status.h>
#include <sdk/lib/device-watcher/cpp/device-watcher.h>
#include <zxtest/zxtest.h>
namespace {
using device_watcher::RecursiveWaitForFile;
using namespace component_testing;
constexpr char kParentPath[] = "sys/platform/11:01:1a";
constexpr char kDevicePath[] = "sys/platform/11:01:1a/test-bti";
TEST(PbusBtiTest, BtiIsSameAfterCrash) {
auto realm_builder = component_testing::RealmBuilder::Create();
driver_test_realm::Setup(realm_builder);
realm_builder.AddRoute(Route{.capabilities = {Protocol{"fuchsia.boot.RootResource"}},
.source = {ParentRef()},
.targets = {ChildRef{"driver_test_realm"}}});
async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
auto realm = realm_builder.Build(loop.dispatcher());
// Start DriverTestRealm.
fidl::SynchronousInterfacePtr<fuchsia::driver::test::Realm> driver_test_realm;
ASSERT_EQ(ZX_OK, realm.Connect(driver_test_realm.NewRequest()));
fuchsia::driver::test::Realm_Start_Result realm_result;
auto args = fuchsia::driver::test::RealmArgs();
args.set_root_driver("fuchsia-boot:///#driver/platform-bus.so");
ASSERT_EQ(ZX_OK, driver_test_realm->Start(std::move(args), &realm_result));
ASSERT_FALSE(realm_result.is_err());
// Connect to dev.
fidl::InterfaceHandle<fuchsia::io::Directory> dev;
zx_status_t status = realm.Connect("dev", dev.NewRequest().TakeChannel());
ASSERT_EQ(status, ZX_OK);
fbl::unique_fd dev_fd;
status = fdio_fd_create(dev.TakeChannel().release(), dev_fd.reset_and_get_address());
ASSERT_EQ(status, ZX_OK);
fbl::unique_fd fd;
EXPECT_OK(RecursiveWaitForFile(dev_fd, kDevicePath, &fd));
zx::status bti_client_end =
fdio_cpp::FdioCaller(std::move(fd)).take_as<fuchsia_hardware_btitest::BtiDevice>();
ASSERT_OK(bti_client_end.status_value());
fidl::WireSyncClient client(std::move(*bti_client_end));
uint64_t koid1;
{
auto result = client->GetKoid();
ASSERT_OK(result.status());
koid1 = result.value().koid;
}
fd.reset(openat(dev_fd.get(), kParentPath, O_DIRECTORY | O_RDONLY));
std::unique_ptr<device_watcher::DirWatcher> watcher;
ASSERT_OK(device_watcher::DirWatcher::Create(std::move(fd), &watcher));
{
auto result = client->Crash();
ASSERT_OK(result.status());
}
// We implicitly rely on driver host being rebound in the event of a crash.
ASSERT_OK(watcher->WaitForRemoval("test-bti", zx::duration::infinite()));
EXPECT_OK(RecursiveWaitForFile(dev_fd, kDevicePath, &fd));
bti_client_end =
fdio_cpp::FdioCaller(std::move(fd)).take_as<fuchsia_hardware_btitest::BtiDevice>();
ASSERT_OK(bti_client_end.status_value());
client = fidl::BindSyncClient(std::move(*bti_client_end));
uint64_t koid2;
{
auto result = client->GetKoid();
ASSERT_OK(result.status());
koid2 = result.value().koid;
}
ASSERT_EQ(koid1, koid2);
}
} // namespace