Index: shell/shell_apptest.cc |
diff --git a/shell/shell_apptest.cc b/shell/shell_apptest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..02e505dec3f0a1a25d64b4b4774fbae4d9d45ba7 |
--- /dev/null |
+++ b/shell/shell_apptest.cc |
@@ -0,0 +1,171 @@ |
+// Copyright 2015 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/base_paths.h" |
+#include "base/bind.h" |
+#include "base/files/file_path.h" |
+#include "base/files/file_util.h" |
+#include "base/path_service.h" |
+#include "base/run_loop.h" |
+#include "base/strings/string_util.h" |
+#include "base/strings/stringprintf.h" |
+#include "mojo/common/data_pipe_utils.h" |
+#include "mojo/public/cpp/application/application_impl.h" |
+#include "mojo/public/cpp/application/application_test_base.h" |
+#include "mojo/public/cpp/system/macros.h" |
+#include "mojo/services/network/public/interfaces/net_address.mojom.h" |
+#include "services/http_server/public/http_server.mojom.h" |
+#include "services/http_server/public/http_server_factory.mojom.h" |
+#include "services/http_server/public/http_server_util.h" |
+#include "shell/test/pingable.mojom.h" |
+ |
+namespace mojo { |
+ |
+namespace { |
+ |
+std::string GetURL(uint16_t port, const std::string& path) { |
+ return base::StringPrintf("http://127.0.0.1:%u/%s", port, path.c_str()); |
+} |
+} |
+ |
+class GetHandler : public http_server::HttpHandler { |
+ public: |
+ GetHandler(InterfaceRequest<http_server::HttpHandler> request, uint16_t port) |
+ : binding_(this, request.Pass()), port_(port) { |
+ CHECK(PathService::Get(base::FILE_MODULE, &app_path_)); |
+ app_path_ = app_path_.DirName().Append("pingable_app.mojo"); |
+ CHECK(base::PathExists(app_path_)); |
+ } |
+ ~GetHandler() override {} |
+ |
+ bool WaitForIncomingMethodCall() { |
+ return binding_.WaitForIncomingMethodCall(); |
+ } |
+ |
+ private: |
+ // http_server::HttpHandler: |
+ void HandleRequest( |
+ http_server::HttpRequestPtr request, |
+ const Callback<void(http_server::HttpResponsePtr)>& callback) override { |
+ http_server::HttpResponsePtr response; |
+ if (StartsWithASCII(request->relative_url, "/app", true)) { |
+ // Super inefficient, but meh. |
+ std::string data; |
+ base::ReadFileToString(app_path_, &data); |
+ response = http_server::CreateHttpResponse(200, data); |
+ response->content_type = "application/octet-stream"; |
+ } else if (request->relative_url == "/redirect") { |
+ response = http_server::HttpResponse::New(); |
+ response->status_code = 302; |
+ response->custom_headers.insert("Location", GetURL(port_, "app")); |
+ } else { |
+ NOTREACHED(); |
+ } |
+ |
+ callback.Run(response.Pass()); |
+ } |
+ |
+ Binding<http_server::HttpHandler> binding_; |
+ base::FilePath app_path_; |
+ uint16_t port_; |
+ |
+ MOJO_DISALLOW_COPY_AND_ASSIGN(GetHandler); |
+}; |
+ |
+class ShellAppTest : public test::ApplicationTestBase { |
+ public: |
+ ShellAppTest() : ApplicationTestBase() {} |
+ ~ShellAppTest() override {} |
+ |
+ protected: |
+ // ApplicationTestBase: |
+ void SetUp() override { |
+ ApplicationTestBase::SetUp(); |
+ |
+ application_impl()->ConnectToService("mojo:http_server", |
+ &http_server_factory_); |
+ |
+ mojo::NetAddressPtr local_address(mojo::NetAddress::New()); |
+ local_address->family = mojo::NET_ADDRESS_FAMILY_IPV4; |
+ local_address->ipv4 = mojo::NetAddressIPv4::New(); |
+ local_address->ipv4->addr.resize(4); |
+ local_address->ipv4->addr[0] = 127; |
+ local_address->ipv4->addr[1] = 0; |
+ local_address->ipv4->addr[2] = 0; |
+ local_address->ipv4->addr[3] = 1; |
+ local_address->ipv4->port = 0; |
+ http_server_factory_->CreateHttpServer(GetProxy(&http_server_), |
+ local_address.Pass()); |
+ |
+ http_server_->GetPort([this](uint16_t p) { port_ = p; }); |
+ EXPECT_TRUE(http_server_.WaitForIncomingMethodCall()); |
+ |
+ InterfacePtr<http_server::HttpHandler> http_handler; |
+ handler_.reset(new GetHandler(GetProxy(&http_handler).Pass(), port_)); |
+ http_server_->SetHandler(".*", http_handler.Pass(), |
+ [](bool result) { EXPECT_TRUE(result); }); |
+ EXPECT_TRUE(http_server_.WaitForIncomingMethodCall()); |
+ } |
+ |
+ std::string GetURL(const std::string& path) { |
+ return ::mojo::GetURL(port_, path); |
+ } |
+ |
+ http_server::HttpServerFactoryPtr http_server_factory_; |
+ http_server::HttpServerPtr http_server_; |
+ scoped_ptr<GetHandler> handler_; |
+ uint16_t port_; |
+ |
+ private: |
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ShellAppTest); |
+}; |
+ |
+// Test that we can load apps over http. |
+TEST_F(ShellAppTest, Http) { |
+ InterfacePtr<Pingable> pingable; |
+ application_impl()->ConnectToService(GetURL("app"), &pingable); |
+ pingable->Ping("hello", [](const String& app_url, const String& message) { |
+ EXPECT_EQ("hello", message); |
+ base::MessageLoop::current()->Quit(); |
+ }); |
+ base::RunLoop().Run(); |
+} |
+ |
+// Test that redirects work. |
+// TODO(aa): Test that apps receive the correct URL parameters. |
+// TODO(aa): This test runs and passes, except it crashes with a scary-looking |
+// segfault+smashed stack. I suspect something in HttpServer having to do with |
qsr
2015/02/27 15:01:41
Collin is using the http server with headers and d
|
+// using headers. |
+TEST_F(ShellAppTest, DISABLED_Redirect) { |
+ InterfacePtr<Pingable> pingable; |
+ application_impl()->ConnectToService(GetURL("redirect"), &pingable); |
+ pingable->Ping("hello", [](const String& app_url, const String& message) { |
+ EXPECT_EQ("hello", message); |
+ base::MessageLoop::current()->Quit(); |
+ }); |
+ base::RunLoop().Run(); |
+} |
+ |
+// Test that querystring is not considered when resolving http applications. |
+TEST_F(ShellAppTest, QueryHandling) { |
+ InterfacePtr<Pingable> pingable1; |
+ InterfacePtr<Pingable> pingable2; |
+ application_impl()->ConnectToService(GetURL("app?foo"), &pingable1); |
+ application_impl()->ConnectToService(GetURL("app?bar"), &pingable2); |
+ |
+ int num_responses = 0; |
+ auto callback = |
+ [this, &num_responses](const String& app_url, const String& message) { |
+ EXPECT_EQ(GetURL("app"), app_url); |
+ EXPECT_EQ("hello", message); |
+ if (++num_responses == 2) { |
+ base::MessageLoop::current()->Quit(); |
+ } |
+ }; |
+ pingable1->Ping("hello", callback); |
+ pingable2->Ping("hello", callback); |
+ base::RunLoop().Run(); |
+} |
+ |
+} // namespace mojo |