blob: 85cd4b8042a34de36ee84bdddcc092262763d5e9 [file] [log] [blame]
// Copyright 2019 The Chromium 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 "base/optional.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "content/public/browser/service_process_host.h"
#include "content/public/test/content_browser_test.h"
#include "services/test/echo/public/mojom/echo.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
using ServiceProcessHostBrowserTest = ContentBrowserTest;
class EchoServiceProcessObserver : public ServiceProcessHost::Observer {
public:
EchoServiceProcessObserver() { ServiceProcessHost::AddObserver(this); }
~EchoServiceProcessObserver() override {
ServiceProcessHost::RemoveObserver(this);
}
void WaitForLaunch() { launch_loop_.Run(); }
void WaitForDeath() { death_loop_.Run(); }
void WaitForCrash() { crash_loop_.Run(); }
private:
// ServiceProcessHost::Observer:
void OnServiceProcessLaunched(const ServiceProcessInfo& info) override {
if (info.IsService<echo::mojom::EchoService>())
launch_loop_.Quit();
}
void OnServiceProcessTerminatedNormally(
const ServiceProcessInfo& info) override {
if (info.IsService<echo::mojom::EchoService>())
death_loop_.Quit();
}
void OnServiceProcessCrashed(const ServiceProcessInfo& info) override {
if (info.IsService<echo::mojom::EchoService>())
crash_loop_.Quit();
}
base::RunLoop launch_loop_;
base::RunLoop death_loop_;
base::RunLoop crash_loop_;
DISALLOW_COPY_AND_ASSIGN(EchoServiceProcessObserver);
};
IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, Launch) {
EchoServiceProcessObserver observer;
auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>();
observer.WaitForLaunch();
const std::string kTestString =
"Aurora borealis! At this time of year? At this time of day? "
"In this part of the country? Localized entirely within your kitchen?";
base::RunLoop loop;
echo_service->EchoString(
kTestString,
base::BindLambdaForTesting([&](const std::string& echoed_input) {
EXPECT_EQ(kTestString, echoed_input);
loop.Quit();
}));
loop.Run();
}
IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, LocalDisconnectQuits) {
EchoServiceProcessObserver observer;
auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>();
observer.WaitForLaunch();
echo_service.reset();
observer.WaitForDeath();
}
IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, RemoteDisconnectQuits) {
EchoServiceProcessObserver observer;
auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>();
observer.WaitForLaunch();
echo_service->Quit();
observer.WaitForDeath();
}
IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, ObserveCrash) {
EchoServiceProcessObserver observer;
auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>();
observer.WaitForLaunch();
echo_service->Crash();
observer.WaitForCrash();
}
IN_PROC_BROWSER_TEST_F(ServiceProcessHostBrowserTest, IdleTimeout) {
EchoServiceProcessObserver observer;
auto echo_service = ServiceProcessHost::Launch<echo::mojom::EchoService>();
base::RunLoop wait_for_idle_loop;
constexpr auto kTimeout = base::TimeDelta::FromSeconds(1);
echo_service.set_idle_handler(kTimeout, base::BindLambdaForTesting([&] {
wait_for_idle_loop.Quit();
echo_service.reset();
}));
// Send a message and wait for the reply. Once the message is sent we should
// observe at least |kTimeout| time elapsing before the RunLoop quits, because
// the service process must wait at least that long to report itself as idle.
base::ElapsedTimer timer;
const std::string kTestString =
"Yes, and you call them steamed hams despite the fact that they are "
"obviously grilled.";
echo_service->EchoString(
kTestString,
base::BindLambdaForTesting([&](const std::string& echoed_input) {
EXPECT_EQ(kTestString, echoed_input);
}));
wait_for_idle_loop.Run();
EXPECT_GE(timer.Elapsed(), kTimeout);
// And since the idle handler resets |echo_service|, we should imminently see
// normal service process termination.
observer.WaitForDeath();
}
} // namespace content