Chromium Code Reviews| Index: services/python/mojo_url_redirector/mojo_url_redirector_apptest.cc |
| diff --git a/services/python/mojo_url_redirector/mojo_url_redirector_apptest.cc b/services/python/mojo_url_redirector/mojo_url_redirector_apptest.cc |
| index 394a891277ab34ca6e9d02ad685fcd56cad5df69..7c0dc061c0c756104be7eb8a31f2da147f2dd7ae 100644 |
| --- a/services/python/mojo_url_redirector/mojo_url_redirector_apptest.cc |
| +++ b/services/python/mojo_url_redirector/mojo_url_redirector_apptest.cc |
| @@ -2,26 +2,75 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| -#include <iostream> |
| - |
| #include "base/bind.h" |
| #include "base/logging.h" |
| #include "base/run_loop.h" |
| +#include "base/strings/string_split.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/services/http_server/public/cpp/http_server_util.h" |
| +#include "mojo/services/http_server/public/interfaces/http_server.mojom.h" |
| +#include "mojo/services/http_server/public/interfaces/http_server_factory.mojom.h" |
| #include "mojo/services/network/public/interfaces/net_address.mojom.h" |
| #include "mojo/services/network/public/interfaces/network_service.mojom.h" |
| #include "mojo/services/network/public/interfaces/url_loader.mojom.h" |
| namespace mojo_url_redirector { |
| +namespace { |
| +const std::string kPlatform1 = "platform1"; |
| +const std::string kPlatform2 = "platform2"; |
| +const std::string kKnownAppName = "spinning_cube"; |
| +const std::string kMissingAppName = "missing_app"; |
| + |
| +std::string LocationOfAppOnPlatform(const std::string& platform, |
| + const std::string& app) { |
| + return platform + "-" + app; |
| +} |
| + |
| +void CheckRedirectorResponse(uint32 expected_http_status, |
| + std::string expected_redirect, |
| + mojo::URLResponsePtr response) { |
| + // Break out of the nested runloop that the test started running after |
| + // starting the request that is now complete. |
| + base::MessageLoop::current()->Quit(); |
| + |
| + EXPECT_EQ(nullptr, response->error); |
| + EXPECT_EQ(expected_http_status, response->status_code); |
| + std::string response_body; |
| + mojo::common::BlockingCopyToString(response->body.Pass(), &response_body); |
| + EXPECT_EQ("", response_body); |
| + |
| + if (expected_http_status != 302) |
| + return; |
| + |
| + // Check that the response contains a header redirecting to the expected |
| + // location. |
| + std::string expected_redirect_header = "location: " + expected_redirect; |
| + bool found_redirect_header = false; |
| + EXPECT_FALSE(response->headers.is_null()); |
| + for (size_t i = 0; i < response->headers.size(); i++) { |
| + mojo::String header = response->headers[i]; |
| + if (header == expected_redirect_header) { |
| + found_redirect_header = true; |
| + break; |
| + } |
| + } |
| + EXPECT_TRUE(found_redirect_header); |
| +} |
| + |
| +} // namespace |
| + |
| class MojoUrlRedirectorApplicationTest : |
| - public mojo::test::ApplicationTestBase { |
| + public mojo::test::ApplicationTestBase, |
| + public http_server::HttpHandler { |
| public: |
| MojoUrlRedirectorApplicationTest() : ApplicationTestBase(), |
| - assigned_port_(0), handler_registered_(false) {} |
| + binding_(this), |
| + redirector_port_(0), |
| + redirector_registered_(false) {} |
| ~MojoUrlRedirectorApplicationTest() override {} |
| protected: |
| @@ -29,81 +78,159 @@ class MojoUrlRedirectorApplicationTest : |
| void SetUp() override { |
| ApplicationTestBase::SetUp(); |
| - // Construct the server's address. |
| - mojo::NetAddressPtr server_address(mojo::NetAddress::New()); |
| - server_address->family = mojo::NET_ADDRESS_FAMILY_IPV4; |
| - server_address->ipv4 = mojo::NetAddressIPv4::New(); |
| - server_address->ipv4->addr.resize(4); |
| + // Obtain the port that the redirector is at and the port that we should |
| + // spin up the app location files server at. |
| + uint16_t app_location_files_port = 0; |
| for (const std::string& arg : application_impl()->args()) { |
|
qsr
2015/04/01 13:49:03
Given that you are using base, you can probably se
|
| - if (arg.find("--address") != std::string::npos) { |
| - sscanf(arg.c_str(), "--address=%hhu.%hhu.%hhu.%hhu:%hu", |
| - &server_address->ipv4->addr[0], |
| - &server_address->ipv4->addr[1], |
| - &server_address->ipv4->addr[2], |
| - &server_address->ipv4->addr[3], |
| - &assigned_port_); |
| - server_address->ipv4->port = assigned_port_; |
| - break; |
| + if (arg.find("--redirector_port") != std::string::npos) { |
| + sscanf(arg.c_str(), "--redirector_port=%hu", &redirector_port_); |
| + } else if (arg.find("--app_location_files_port") != std::string::npos) { |
| + sscanf(arg.c_str(), "--app_location_files_port=%hu", |
| + &app_location_files_port); |
| } |
| } |
| - DCHECK(assigned_port_); |
| + DCHECK(redirector_port_); |
| + DCHECK(app_location_files_port); |
| + |
| + // Spin up the app location files server. |
| + http_server::HttpHandlerPtr location_files_handler; |
| + binding_.Bind(GetProxy(&location_files_handler)); |
| + |
| + http_server::HttpServerFactoryPtr http_server_factory; |
| + application_impl()->ConnectToService("mojo:http_server", |
| + &http_server_factory); |
| + |
| + mojo::NetAddressPtr location_files_server_addr(mojo::NetAddress::New()); |
| + location_files_server_addr->family = mojo::NET_ADDRESS_FAMILY_IPV4; |
| + location_files_server_addr->ipv4 = mojo::NetAddressIPv4::New(); |
| + location_files_server_addr->ipv4->addr.resize(4); |
| + location_files_server_addr->ipv4->addr[0] = 0; |
| + location_files_server_addr->ipv4->addr[1] = 0; |
| + location_files_server_addr->ipv4->addr[2] = 0; |
| + location_files_server_addr->ipv4->addr[3] = 0; |
| + location_files_server_addr->ipv4->port = app_location_files_port; |
| + http_server_factory->CreateHttpServer( |
| + GetProxy(&location_files_server_).Pass(), |
| + location_files_server_addr.Pass()); |
| + |
| + location_files_server_->SetHandler( |
| + "/.*", |
| + location_files_handler.Pass(), |
| + base::Bind(&MojoUrlRedirectorApplicationTest::OnAddedHandler, |
| + base::Unretained(this))); |
| + location_files_server_.WaitForIncomingMethodCall(); |
| + // Connect to the redirector and wait until it registers itself as a |
| + // handler with the server on |redirector_port_|. |
| application_impl()->ConnectToApplication("mojo:mojo_url_redirector"); |
| application_impl()->ConnectToService("mojo:network_service", |
| &network_service_); |
| - |
| - // Wait until the MojoUrlRedirector is registered as a handler with the |
| - // server. |
| - WaitForHandlerRegistration(); |
| + WaitForRedirectorRegistration(); |
| } |
| + void TestRedirectForKnownApp(const std::string& platform, |
| + const std::string& app); |
| + |
| + mojo::Binding<http_server::HttpHandler> binding_; |
| mojo::NetworkServicePtr network_service_; |
| - uint16_t assigned_port_; |
| - bool handler_registered_; |
| + uint16_t redirector_port_; |
| + bool redirector_registered_; |
| private: |
| - void WaitForHandlerRegistration(); |
| - void CheckHandlerRegistered(mojo::URLResponsePtr response); |
| + // HttpHandler: |
| + void HandleRequest( |
| + http_server::HttpRequestPtr request, |
| + const mojo::Callback<void(http_server::HttpResponsePtr)>& callback) |
| + override; |
| + |
| + void WaitForRedirectorRegistration(); |
| + void CheckRedirectorRegistered(mojo::URLResponsePtr response); |
| + void OnAddedHandler(bool result); |
| + |
| + http_server::HttpServerPtr location_files_server_; |
| MOJO_DISALLOW_COPY_AND_ASSIGN(MojoUrlRedirectorApplicationTest); |
| }; |
| -void MojoUrlRedirectorApplicationTest::WaitForHandlerRegistration() { |
| - while (!handler_registered_) { |
| +void MojoUrlRedirectorApplicationTest::OnAddedHandler(bool result) { |
| + CHECK(result); |
| +} |
| + |
| + // Handles requests for app location files. |
| +void MojoUrlRedirectorApplicationTest::HandleRequest( |
| + http_server::HttpRequestPtr request, |
| + const mojo::Callback<void(http_server::HttpResponsePtr)>& callback) { |
| + // The relative url should be of the form "/<platform>/<app>_location". |
| + std::vector<std::string> url_components; |
| + base::SplitString(request->relative_url, '/', &url_components); |
| + ASSERT_EQ(3u, url_components.size()); |
| + std::string requested_platform = url_components[1]; |
| + EXPECT_TRUE(requested_platform == kPlatform1 || |
| + requested_platform == kPlatform2); |
| + |
| + std::string location_file_basename = url_components[2]; |
| + std::string known_app_location_file = kKnownAppName + "_location"; |
| + std::string missing_app_location_file = kMissingAppName + "_location"; |
| + EXPECT_TRUE(location_file_basename == known_app_location_file || |
| + location_file_basename == missing_app_location_file); |
| + |
| + if (location_file_basename == missing_app_location_file) { |
| + callback.Run(http_server::CreateHttpResponse(404, "")); |
| + return; |
| + } |
| + |
| + std::string app_location = LocationOfAppOnPlatform(requested_platform, |
| + kKnownAppName); |
| + callback.Run(http_server::CreateHttpResponse(200, app_location)); |
| +} |
| + |
| +void MojoUrlRedirectorApplicationTest::WaitForRedirectorRegistration() { |
| + while (!redirector_registered_) { |
| mojo::URLLoaderPtr url_loader; |
| network_service_->CreateURLLoader(GetProxy(&url_loader)); |
| mojo::URLRequestPtr url_request = mojo::URLRequest::New(); |
| url_request->url = |
| - base::StringPrintf("http://localhost:%u/test", assigned_port_); |
| + base::StringPrintf("http://localhost:%u/test", redirector_port_); |
| url_loader->Start(url_request.Pass(), |
| - base::Bind(&MojoUrlRedirectorApplicationTest::CheckHandlerRegistered, |
| - base::Unretained(this))); |
| + base::Bind( |
| + &MojoUrlRedirectorApplicationTest::CheckRedirectorRegistered, |
| + base::Unretained(this))); |
| ASSERT_TRUE(url_loader.WaitForIncomingMethodCall()); |
| } |
| } |
| -void MojoUrlRedirectorApplicationTest::CheckHandlerRegistered( |
| +void MojoUrlRedirectorApplicationTest::CheckRedirectorRegistered( |
| mojo::URLResponsePtr response) { |
| if (response->error) { |
| - // The server has not yet been spun up. |
| + // The server at |redirector_port_| has not yet been spun up. |
| return; |
| } |
| if (response->status_code == 404) { |
| - // The handler has not yet been registered. |
| + // The redirector has not yet been registered as a handler. |
| return; |
| } |
| - handler_registered_ = true; |
| + redirector_registered_ = true; |
| } |
| -void CheckHandlerResponse(uint32 expected_http_status, |
| - mojo::URLResponsePtr response) { |
| - EXPECT_EQ(nullptr, response->error); |
| - EXPECT_EQ(expected_http_status, response->status_code); |
| - std::string response_body; |
| - mojo::common::BlockingCopyToString(response->body.Pass(), &response_body); |
| - EXPECT_EQ("", response_body); |
| +void MojoUrlRedirectorApplicationTest::TestRedirectForKnownApp( |
| + const std::string& platform, const std::string& app) { |
| + mojo::URLLoaderPtr url_loader; |
| + network_service_->CreateURLLoader(GetProxy(&url_loader)); |
| + |
| + mojo::URLRequestPtr url_request = mojo::URLRequest::New(); |
| + url_request->url = |
| + base::StringPrintf("http://localhost:%u/%s/%s.mojo", |
| + redirector_port_, |
| + platform.c_str(), |
| + app.c_str()); |
| + |
| + std::string app_location = LocationOfAppOnPlatform(platform, app); |
| + url_loader->Start(url_request.Pass(), base::Bind(&CheckRedirectorResponse, |
| + 302, app_location)); |
| + base::RunLoop run_loop; |
| + run_loop.Run(); |
| } |
| TEST_F(MojoUrlRedirectorApplicationTest, MalformedRequest) { |
| @@ -112,10 +239,32 @@ TEST_F(MojoUrlRedirectorApplicationTest, MalformedRequest) { |
| mojo::URLRequestPtr url_request = mojo::URLRequest::New(); |
| url_request->url = |
| - base::StringPrintf("http://localhost:%u/test", assigned_port_); |
| - url_loader->Start(url_request.Pass(), base::Bind(&CheckHandlerResponse, |
| - 400)); |
| - url_loader.WaitForIncomingMethodCall(); |
| + base::StringPrintf("http://localhost:%u/test", redirector_port_); |
| + url_loader->Start(url_request.Pass(), base::Bind(&CheckRedirectorResponse, |
| + 400, "")); |
| + base::RunLoop run_loop; |
| + run_loop.Run(); |
| +} |
| + |
| +TEST_F(MojoUrlRedirectorApplicationTest, RequestForMissingApp) { |
| + mojo::URLLoaderPtr url_loader; |
| + network_service_->CreateURLLoader(GetProxy(&url_loader)); |
| + |
| + mojo::URLRequestPtr url_request = mojo::URLRequest::New(); |
| + url_request->url = |
| + base::StringPrintf("http://localhost:%u/%s/%s.mojo", |
| + redirector_port_, |
| + kPlatform1.c_str(), |
| + kMissingAppName.c_str()); |
| + url_loader->Start(url_request.Pass(), base::Bind(&CheckRedirectorResponse, |
| + 404, "")); |
| + base::RunLoop run_loop; |
| + run_loop.Run(); |
| +} |
| + |
| +TEST_F(MojoUrlRedirectorApplicationTest, RequestForKnownApp) { |
| + TestRedirectForKnownApp(kPlatform1, kKnownAppName); |
| + TestRedirectForKnownApp(kPlatform2, kKnownAppName); |
| } |
| } // namespace mojo_url_redirector |