Index: mojo/shell/shell_test_base_unittest.cc |
diff --git a/mojo/shell/shell_test_base_unittest.cc b/mojo/shell/shell_test_base_unittest.cc |
index 4b861f90ff97bde7c699c56312ab51f178ddd968..8c84ed40fad92652083ca834bec60952e6428eba 100644 |
--- a/mojo/shell/shell_test_base_unittest.cc |
+++ b/mojo/shell/shell_test_base_unittest.cc |
@@ -5,21 +5,75 @@ |
#include "mojo/shell/shell_test_base.h" |
#include "base/bind.h" |
+#include "base/i18n/time_formatting.h" |
#include "base/macros.h" |
#include "base/message_loop/message_loop.h" |
+#include "base/strings/utf_string_conversions.h" |
#include "mojo/public/cpp/bindings/error_handler.h" |
#include "mojo/public/cpp/bindings/interface_ptr.h" |
#include "mojo/public/cpp/system/core.h" |
#include "mojo/services/test_service/test_service.mojom.h" |
+#include "mojo/services/test_service/toy_monitoring_service.mojom.h" |
#include "testing/gtest/include/gtest/gtest.h" |
#include "url/gurl.h" |
+using mojo::test::ServiceReport; |
viettrungluu
2014/06/30 17:08:25
I wonder how specific to shell_tests we should mak
tim (not reviewing)
2014/06/30 22:20:54
Good question. I set out wanting to keep things re
|
+using mojo::test::ServiceReportPtr; |
+using mojo::test::TestService; |
+using mojo::test::TestTimeService; |
+using mojo::test::TestServicePtr; |
+using mojo::test::TestTimeServicePtr; |
+using mojo::test::ToyMonitoringService; |
+using mojo::test::ToyMonitoringServicePtr; |
+ |
namespace mojo { |
namespace shell { |
namespace test { |
namespace { |
-typedef ShellTestBase ShellTestBaseTest; |
+void GetReportCallback(base::MessageLoop* loop, |
+ std::vector<ServiceReport>* reports_out, |
+ mojo::Array<ServiceReportPtr> report) { |
+ for (size_t i = 0; i < report.size(); i++) |
+ reports_out->push_back(*report[i]); |
+ loop->QuitWhenIdle(); |
+} |
+ |
+class ShellTestBaseTest : public ShellTestBase { |
+ public: |
+ // Convenience helpers for use as callbacks in tests. |
+ template <typename T> |
+ base::Callback<void()> SetAndQuit(T* val, T result) { |
+ return base::Bind(&ShellTestBaseTest::SetAndQuitImpl<T>, |
+ base::Unretained(this), val, result); |
+ } |
+ template <typename T> |
+ base::Callback<void(T result)> SetAndQuit(T* val) { |
+ return base::Bind(&ShellTestBaseTest::SetAndQuitImpl<T>, |
+ base::Unretained(this), val); |
+ } |
+ |
+ static GURL test_app_url() { |
+ return GURL("mojo:mojo_test_app"); |
+ } |
+ |
+ void GetReport(std::vector<ServiceReport>* report) { |
+ monitoring_.Bind(ConnectToService(GURL("mojo:mojo_test_monitoring_app"), |
+ ToyMonitoringService::Name_).Pass()); |
+ monitoring_->GetReport(base::Bind(&GetReportCallback, |
+ base::Unretained(message_loop()), |
+ base::Unretained(report))); |
+ message_loop()->Run(); |
+ } |
+ |
+ private: |
+ template<typename T> |
+ void SetAndQuitImpl(T* val, T result) { |
+ *val = result; |
+ message_loop()->QuitWhenIdle(); |
+ } |
+ ToyMonitoringServicePtr monitoring_; |
+}; |
class QuitMessageLoopErrorHandler : public ErrorHandler { |
public: |
@@ -35,53 +89,33 @@ class QuitMessageLoopErrorHandler : public ErrorHandler { |
DISALLOW_COPY_AND_ASSIGN(QuitMessageLoopErrorHandler); |
}; |
-void PingCallback(base::MessageLoop* message_loop, bool* was_run) { |
- *was_run = true; |
- VLOG(2) << "Ping callback"; |
- message_loop->QuitWhenIdle(); |
-} |
- |
-TEST_F(ShellTestBaseTest, LaunchServiceInProcess) { |
- InterfacePtr<mojo::test::ITestService> test_service; |
- |
- { |
- ScopedMessagePipeHandle service_handle = |
- LaunchServiceInProcess(GURL("mojo:mojo_test_service"), |
- mojo::test::ITestService::Name_); |
- test_service.Bind(service_handle.Pass()); |
- } |
+// Tests that we can connect to a single service within a single app. |
+TEST_F(ShellTestBaseTest, ConnectBasic) { |
+ InterfacePtr<TestService> service; |
+ service.Bind(ConnectToService(test_app_url(), TestService::Name_).Pass()); |
bool was_run = false; |
- test_service->Ping(base::Bind(&PingCallback, |
- base::Unretained(message_loop()), |
- base::Unretained(&was_run))); |
+ service->Ping(SetAndQuit<bool>(&was_run, true)); |
message_loop()->Run(); |
EXPECT_TRUE(was_run); |
- EXPECT_FALSE(test_service.encountered_error()); |
+ EXPECT_FALSE(service.encountered_error()); |
- test_service.reset(); |
+ service.reset(); |
- // This will run until the test service has actually quit (which it will, |
+ // This will run until the test app has actually quit (which it will, |
// since we killed the only connection to it). |
message_loop()->Run(); |
} |
-// Tests that launching a service in process fails properly if the service |
+// Tests that trying to connect to a service fails properly if the service |
// doesn't exist. |
-TEST_F(ShellTestBaseTest, LaunchServiceInProcessInvalidService) { |
- InterfacePtr<mojo::test::ITestService> test_service; |
- |
- { |
- ScopedMessagePipeHandle service_handle = |
- LaunchServiceInProcess(GURL("mojo:non_existent_service"), |
- mojo::test::ITestService::Name_); |
- test_service.Bind(service_handle.Pass()); |
- } |
+TEST_F(ShellTestBaseTest, ConnectInvalidService) { |
+ InterfacePtr<TestService> test_service; |
+ test_service.Bind(ConnectToService(GURL("mojo:non_existent_service"), |
+ TestService::Name_).Pass()); |
bool was_run = false; |
- test_service->Ping(base::Bind(&PingCallback, |
- base::Unretained(message_loop()), |
- base::Unretained(&was_run))); |
+ test_service->Ping(SetAndQuit<bool>(&was_run, true)); |
// This will quit because there's nothing running. |
message_loop()->Run(); |
@@ -98,6 +132,137 @@ TEST_F(ShellTestBaseTest, LaunchServiceInProcessInvalidService) { |
test_service.reset(); |
} |
+// Similar to ConnectBasic, but causes the app to instantiate multiple |
+// service implementation objects and verifies the shell can reach both. |
+TEST_F(ShellTestBaseTest, ConnectMultipleInstancesPerApp) { |
+ { |
+ TestServicePtr service1, service2; |
+ service1.Bind(ConnectToService(test_app_url(), TestService::Name_).Pass()); |
+ service2.Bind(ConnectToService(test_app_url(), TestService::Name_).Pass()); |
+ |
+ bool was_run1 = false; |
+ bool was_run2 = false; |
+ service1->Ping(SetAndQuit<bool>(&was_run1, true)); |
+ service2->Ping(SetAndQuit<bool>(&was_run2, true)); |
+ message_loop()->Run(); |
+ EXPECT_TRUE(was_run1); |
+ EXPECT_TRUE(was_run2); |
+ EXPECT_FALSE(service1.encountered_error()); |
+ EXPECT_FALSE(service2.encountered_error()); |
+ } |
+ message_loop()->Run(); |
+} |
+ |
+// Tests that service A and service B, both in App 1, can talk to each other |
+// and parameters are passed around properly. |
+TEST_F(ShellTestBaseTest, ConnectDifferentServicesInSingleApp) { |
+ // Have a TestService GetPartyTime on a TestTimeService in the same app. |
+ std::string welcome; |
+ TestServicePtr service; |
+ service.Bind(ConnectToService(test_app_url(), TestService::Name_).Pass()); |
+ service->GetFriendlyWelcomeMessage(test_app_url().spec(), |
+ SetAndQuit<std::string>(&welcome)); |
+ message_loop()->Run(); |
+ |
+ // Verify by hitting the TimeService directly. |
+ TestTimeServicePtr time_service; |
+ time_service.Bind( |
+ ConnectToService(test_app_url(), TestTimeService::Name_).Pass()); |
+ int64 party_time; |
+ time_service->GetPartyTime(SetAndQuit<int64>(&party_time)); |
+ message_loop()->Run(); |
+ |
+ std::string expected_welcome( |
+ TestService::kWelcomeMessagePrefix + |
+ UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime( |
+ base::Time::FromInternalValue(party_time)))); |
+ EXPECT_EQ(welcome, expected_welcome); |
+} |
+ |
+// Tests that a service A in App 1 can talk to service B in App 2 and |
+// parameters are passed around properly. |
+TEST_F(ShellTestBaseTest, ConnectDifferentServicesInDifferentApps) { |
+ std::string welcome; |
+ TestServicePtr service; |
+ service.Bind(ConnectToService(test_app_url(), TestService::Name_).Pass()); |
+ service->GetFriendlyWelcomeMessage("mojo:mojo_test_monitoring_app", |
+ SetAndQuit<std::string>(&welcome)); |
+ message_loop()->Run(); |
+ |
+ // Verify by hitting the TimeService in the monitoring app directly. |
+ TestTimeServicePtr time_service; |
+ time_service.Bind(ConnectToService(GURL("mojo:mojo_test_monitoring_app"), |
+ TestTimeService::Name_).Pass()); |
+ int64 party_time; |
+ time_service->GetPartyTime(SetAndQuit<int64>(&party_time)); |
+ message_loop()->Run(); |
+ |
+ std::string expected_welcome( |
+ TestService::kWelcomeMessagePrefix + |
+ UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime( |
+ base::Time::FromInternalValue(party_time)))); |
+ EXPECT_EQ(welcome, expected_welcome); |
+} |
+ |
+// Tests that service A in App 1 can be a client of service B in App 2. |
+TEST_F(ShellTestBaseTest, ConnectServiceAsClientOfSeparateApp) { |
+ TestServicePtr service; |
+ service.Bind(ConnectToService(test_app_url(), TestService::Name_).Pass()); |
+ service->StartMonitoring(message_loop()->QuitWhenIdleClosure()); |
+ service->Ping(mojo::Callback<void()>()); |
+ message_loop()->Run(); |
+ |
+ for (int i = 0; i < 9; i++) |
+ service->Ping(mojo::Callback<void()>()); |
+ |
+ // If everything worked properly, the monitoring service should report |
+ // 10 pings to TestService. |
+ std::vector<ServiceReport> reports; |
+ GetReport(&reports); |
+ ASSERT_EQ(1U, reports.size()); |
+ EXPECT_EQ("mojo::test::TestService", reports[0].service_name); |
viettrungluu
2014/06/30 17:08:25
Probably you should use the "Name_" member, rather
tim (not reviewing)
2014/06/30 22:20:54
Done.
|
+ EXPECT_EQ(10U, reports[0].total_requests); |
+} |
+ |
+// Connect several services together and use the monitoring service to verify |
+// communication. |
+TEST_F(ShellTestBaseTest, ConnectManyClientsAndServices) { |
+ TestServicePtr service; |
+ TestTimeServicePtr time_service; |
+ |
+ // Make a request to the TestService and have it contact TimeService in the |
+ // monitoring app. Do all this with monitoring enabled, meaning both services |
+ // are connected as clients of the MonitoringService. |
+ service.Bind(ConnectToService(test_app_url(), TestService::Name_).Pass()); |
+ service->StartMonitoring(message_loop()->QuitWhenIdleClosure()); |
+ message_loop()->Run(); |
+ for (int i = 0; i < 5; i++) |
+ service->Ping(mojo::Callback<void()>()); |
+ std::string welcome; |
+ service->GetFriendlyWelcomeMessage("mojo:mojo_test_monitoring_app", |
+ SetAndQuit<std::string>(&welcome)); |
+ message_loop()->Run(); |
+ |
+ // Also make a few requests to the TimeService in the test_app. |
+ time_service.Bind( |
+ ConnectToService(test_app_url(), TestTimeService::Name_).Pass()); |
+ time_service->StartMonitoring(message_loop()->QuitWhenIdleClosure()); |
+ time_service->GetPartyTime(mojo::Callback<void(uint64_t)>()); |
+ message_loop()->Run(); |
+ for (int i = 0; i < 19; i++) |
+ time_service->GetPartyTime(mojo::Callback<void(uint64_t)>()); |
+ |
+ std::vector<ServiceReport> reports; |
+ GetReport(&reports); |
+ ASSERT_EQ(3U, reports.size()); |
+ EXPECT_EQ("mojo::test::TestService", reports[0].service_name); |
viettrungluu
2014/06/30 17:08:24
"
tim (not reviewing)
2014/06/30 22:20:54
Done.
|
+ EXPECT_EQ(6U, reports[0].total_requests); |
+ EXPECT_EQ("mojo::test::TestTimeService", reports[1].service_name); |
+ EXPECT_EQ(1U, reports[1].total_requests); |
+ EXPECT_EQ("mojo::test::TestTimeService", reports[2].service_name); |
+ EXPECT_EQ(20U, reports[2].total_requests); |
+} |
+ |
} // namespace |
} // namespace test |
} // namespace shell |