blob: 5be8dbc997e422a6ddcf6a647326efbcdc7f815e [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.
#include <fuchsia/modular/testing/cpp/fidl.h>
#include <lib/fsl/vmo/strings.h>
#include <lib/modular_test_harness/cpp/fake_component.h>
#include <lib/modular_test_harness/cpp/fake_module.h>
#include <lib/modular_test_harness/cpp/test_harness_fixture.h>
#include <lib/sys/cpp/service_directory.h>
#include <lib/sys/cpp/testing/test_with_environment.h>
#include <src/lib/files/glob.h>
#include "gmock/gmock.h"
class TestHarnessFixtureTest : public modular::testing::TestHarnessFixture {};
// Test that the TestHarnessFixture is able to launch the modular runtime by
// asserting that we can intercept a base shell.
TEST_F(TestHarnessFixtureTest, CanLaunchModular) {
constexpr char kFakeBaseShellUrl[] =
"fuchsia-pkg://example.com/FAKE_BASE_SHELL_PKG/fake_base_shell.cmx";
// Setup base shell interception.
modular_testing::TestHarnessBuilder builder;
bool intercepted = false;
builder.InterceptBaseShell(
[&](fuchsia::sys::StartupInfo startup_info,
fidl::InterfaceHandle<fuchsia::modular::testing::InterceptedComponent> component) {
ASSERT_EQ(kFakeBaseShellUrl, startup_info.launch_info.url);
intercepted = true;
},
{.url = kFakeBaseShellUrl});
builder.BuildAndRun(test_harness());
RunLoopUntil([&] { return intercepted; });
}
class TestComponent : public modular::testing::FakeComponent {
public:
TestComponent(fit::function<void()> on_created, fit::function<void()> on_destroyed)
: on_created_(std::move(on_created)), on_destroyed_(std::move(on_destroyed)) {}
protected:
void OnCreate(fuchsia::sys::StartupInfo startup_info) override { on_created_(); }
void OnDestroy() override { on_destroyed_(); }
fit::function<void()> on_created_;
fit::function<void()> on_destroyed_;
};
// Tests that FakeComponent receives lifecycle events when it is killed
// by its parent.
TEST_F(TestHarnessFixtureTest, FakeComponentLifecycle_KilledByParent) {
modular_testing::TestHarnessBuilder builder;
bool running = false;
TestComponent session_shell([&] { running = true; }, [&] { running = false; });
builder.InterceptSessionShell(session_shell.GetOnCreateHandler(),
{.url = modular_testing::TestHarnessBuilder::GenerateFakeUrl(),
.sandbox_services = {"fuchsia.modular.SessionShellContext"}});
builder.BuildAndRun(test_harness());
RunLoopUntil([&] { return session_shell.is_running(); });
EXPECT_TRUE(running);
fuchsia::modular::SessionShellContextPtr session_shell_context;
session_shell.component_context()->svc()->Connect(session_shell_context.NewRequest());
session_shell_context->Logout();
RunLoopUntil([&] { return !session_shell.is_running(); });
EXPECT_FALSE(running);
}
// Tests that FakeComponent receives lifecycle events when it kills
// itself.
TEST_F(TestHarnessFixtureTest, FakeComponentLifecycle_KilledBySelf) {
modular_testing::TestHarnessBuilder builder;
bool running = false;
TestComponent base_shell([&] { running = true; }, [&] { running = false; });
builder.InterceptBaseShell(base_shell.GetOnCreateHandler(),
{.url = modular_testing::TestHarnessBuilder::GenerateFakeUrl()});
builder.BuildAndRun(test_harness());
RunLoopUntil([&] { return base_shell.is_running(); });
EXPECT_TRUE(running);
base_shell.Exit(0);
RunLoopUntil([&] { return !base_shell.is_running(); });
EXPECT_FALSE(running);
}
// Tests that FakeComponent receives lifecycle events when it is killed
// using fuchsia.modular.Lifecycle that is published in its outgoing directory.
TEST_F(TestHarnessFixtureTest, FakeComponentLifecycle_KilledByLifecycleService) {
modular_testing::TestHarnessBuilder builder;
bool running = false;
TestComponent base_shell([&] { running = true; }, [&] { running = false; });
builder.InterceptBaseShell(base_shell.GetOnCreateHandler(),
{.url = modular_testing::TestHarnessBuilder::GenerateFakeUrl()});
builder.BuildAndRun(test_harness());
RunLoopUntil([&] { return base_shell.is_running(); });
EXPECT_TRUE(running);
// Serve the outgoing() directory from FakeComponent.
zx::channel svc_request, svc_dir;
ASSERT_EQ(ZX_OK, zx::channel::create(0, &svc_request, &svc_dir));
base_shell.component_context()->outgoing()->Serve(std::move(svc_request));
sys::ServiceDirectory svc(std::move(svc_dir));
fuchsia::modular::LifecyclePtr lifecycle;
ASSERT_EQ(ZX_OK, svc.Connect(lifecycle.NewRequest(), "svc/fuchsia.modular.Lifecycle"));
lifecycle->Terminate();
RunLoopUntil([&] { return !base_shell.is_running(); });
EXPECT_FALSE(running);
}
TEST_F(TestHarnessFixtureTest, AddModToStory) {
modular_testing::TestHarnessBuilder builder;
modular::testing::FakeModule mod;
auto mod_url = modular_testing::TestHarnessBuilder::GenerateFakeUrl();
builder.InterceptComponent(
mod.GetOnCreateHandler(),
modular_testing::TestHarnessBuilder::InterceptOptions{.url = mod_url});
builder.BuildAndRun(test_harness());
modular::testing::AddModToStory(test_harness(), "mystory", "mymod",
fuchsia::modular::Intent{.handler = mod_url});
RunLoopUntil([&] { return mod.is_running(); });
}
class TestFixtureForTestingCleanup : public modular::testing::TestHarnessFixture {
public:
// Runs the test harness and calls |on_running| once the base shell starts
// running.
void RunUntilBaseShell(fit::function<void()> on_running) {
modular_testing::TestHarnessBuilder builder;
bool running = false;
TestComponent base_shell([&] { running = true; }, [&] { running = false; });
builder.InterceptBaseShell(base_shell.GetOnCreateHandler(),
{.url = modular_testing::TestHarnessBuilder::GenerateFakeUrl()});
builder.BuildAndRun(test_harness());
RunLoopUntil([&] { return running; });
on_running();
};
virtual ~TestFixtureForTestingCleanup() = default;
private:
// |TestBody()| is usually implemented by gtest's test fixture runner, but
// since this test is exercising TestHarnessFixture directly, this method is
// has a dummy implementation here.
void TestBody() override {}
};
// Test that TestHarnessFixture will destroy the modular_test_harness.cmx
// component in its destructor.
TEST(TestHarnessFixtureCleanupTest, CleanupInDestructor) {
// Test that modular_test_harness.cmx is not running.
constexpr char kTestHarnessHubGlob[] = "/hub/c/modular_test_harness.cmx";
bool exists = files::Glob(kTestHarnessHubGlob).size() == 1;
EXPECT_FALSE(exists);
// Test that TestHarnessFixture will run modular_test_harness.cmx
{
TestFixtureForTestingCleanup t;
t.RunUntilBaseShell([&] {
// check that modular_test_harness.cmx is running.
bool exists = files::Glob(kTestHarnessHubGlob).size() == 1;
EXPECT_TRUE(exists);
});
}
// Test that the modular_test_harness.cmx is no longer running after
// TestHarnessFixture is destroyed.
exists = files::Glob(kTestHarnessHubGlob).size() == 1;
EXPECT_FALSE(exists);
}