blob: 8a3007c51226a01ddc7c78649f46accdfe1cd6ba [file] [log] [blame]
// Copyright 2018 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/sys/cpp/fidl.h>
#include <gtest/gtest.h>
#include <lib/component/cpp/environment_services_helper.h>
#include <lib/fit/function.h>
#include <src/lib/fxl/logging.h>
#include <src/lib/fxl/strings/string_printf.h>
#include <lib/gtest/real_loop_fixture.h>
#include <zircon/status.h>
#include "topaz/tests/web_runner_tests/chromium_context.h"
#include "topaz/tests/web_runner_tests/test_server.h"
// This file contains a subset of adapted Chromium Fuchsia tests to make sure
// nothing broke on the import boundary.
//
// See also: https://chromium.googlesource.com/chromium/src/+/master/fuchsia
namespace {
// This is a black box smoke test for whether the web runner in a given system
// is capable of performing basic operations.
//
// This tests if launching a component with an HTTP URL triggers an HTTP GET for
// the main resource, and if an HTML response with an <img> tag triggers a
// subresource load for the image.
//
// See also:
// https://chromium.googlesource.com/chromium/src/+/master/fuchsia/runners/web/web_runner_smoke_test.cc
TEST(WebRunnerIntegrationTest, Smoke) {
web_runner_tests::TestServer server;
FXL_CHECK(server.FindAndBindPort());
fuchsia::sys::LaunchInfo launch_info;
launch_info.url =
fxl::StringPrintf("http://localhost:%d/foo.html", server.port());
fuchsia::sys::LauncherSyncPtr launcher;
component::GetEnvironmentServices()->ConnectToService(launcher.NewRequest());
fuchsia::sys::ComponentControllerSyncPtr controller;
launcher->CreateComponent(std::move(launch_info), controller.NewRequest());
ASSERT_TRUE(server.Accept());
std::string expected_prefix = "GET /foo.html HTTP";
// We need to overallocate the first time to drain the read since we expect
// the subsresource load on the same connection.
std::string buf(4096, 0);
ASSERT_TRUE(server.Read(&buf));
EXPECT_EQ(expected_prefix, buf.substr(0, expected_prefix.size()));
FXL_CHECK(server.WriteContent("<!doctype html><img src=\"/img.png\">"));
expected_prefix = "GET /img.png HTTP";
buf.resize(expected_prefix.size());
ASSERT_TRUE(server.Read(&buf));
ASSERT_GE(buf.size(), expected_prefix.size());
EXPECT_EQ(expected_prefix, std::string(buf.data(), expected_prefix.size()));
}
class MockNavigationEventObserver
: public chromium::web::NavigationEventObserver {
public:
// |chromium::web::NavigationEventObserver|
void OnNavigationStateChanged(
chromium::web::NavigationEvent change,
OnNavigationStateChangedCallback callback) override {
if (on_navigation_state_changed_) {
on_navigation_state_changed_(std::move(change));
}
callback();
}
void set_on_navigation_state_changed(
fit::function<void(chromium::web::NavigationEvent)> fn) {
on_navigation_state_changed_ = std::move(fn);
}
private:
fit::function<void(chromium::web::NavigationEvent)>
on_navigation_state_changed_;
};
class ChromiumAppTest : public gtest::RealLoopFixture {
protected:
ChromiumAppTest()
: chromium_(component::StartupContext::CreateFromStartupInfo().get()) {}
ChromiumContext* chromium() { return &chromium_; }
private:
ChromiumContext chromium_;
};
// This test ensures that we can interact with the chromium.web FIDL.
//
// See also
// https://chromium.googlesource.com/chromium/src/+/master/fuchsia/engine/browser/context_impl_browsertest.cc
TEST_F(ChromiumAppTest, CreateAndNavigate) {
MockNavigationEventObserver navigation_event_observer;
fidl::Binding<chromium::web::NavigationEventObserver>
navigation_event_observer_binding(&navigation_event_observer);
chromium()->frame()->SetNavigationEventObserver(
navigation_event_observer_binding.NewBinding());
navigation_event_observer_binding.set_error_handler([](zx_status_t status) {
FAIL() << "navigation_event_observer_binding: "
<< zx_status_get_string(status);
});
std::string observed_url;
std::string observed_title;
navigation_event_observer.set_on_navigation_state_changed(
[this, &navigation_event_observer, &observed_url,
&observed_title](chromium::web::NavigationEvent change) {
if (change.url) {
observed_url = *change.url;
}
if (change.title) {
observed_title = *change.title;
}
EXPECT_FALSE(change.is_error);
if (!(observed_url.empty() || observed_title.empty())) {
navigation_event_observer.set_on_navigation_state_changed(nullptr);
QuitLoop();
}
});
// TODO(NET-2089): Without this (or even if this is moved down below
// |FindAndBindPort|), this test flakes about 10% of the time. Reordering the
// tests such that this test executes first also deflakes it.
sleep(1);
web_runner_tests::TestServer server;
FXL_CHECK(server.FindAndBindPort());
const std::string url =
fxl::StringPrintf("http://localhost:%d/foo.html", server.port());
chromium()->Navigate(url);
ASSERT_TRUE(server.Accept());
const std::string expected_prefix = "GET /foo.html HTTP";
std::string buf(expected_prefix.size(), 0);
ASSERT_TRUE(server.Read(&buf));
EXPECT_EQ(expected_prefix, buf.substr(0, expected_prefix.size()));
FXL_CHECK(server.WriteContent(R"(<!doctype html>
<html>
<head>
<title>Test title!</title>
</head>
</html>)"));
EXPECT_FALSE(RunLoopWithTimeout(zx::sec(5)))
<< "Timed out waiting for navigation events";
EXPECT_EQ(url, observed_url);
EXPECT_EQ("Test title!", observed_title);
}
} // namespace