Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Side by Side Diff: mojo/shell/shell_test_base_unittest.cc

Issue 349303006: mojo: add some end-to-end shell tests and a new test sample app (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: ServiceProvider rebase Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "mojo/shell/shell_test_base.h" 5 #include "mojo/shell/shell_test_base.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/i18n/time_formatting.h"
8 #include "base/macros.h" 9 #include "base/macros.h"
9 #include "base/message_loop/message_loop.h" 10 #include "base/message_loop/message_loop.h"
11 #include "base/strings/utf_string_conversions.h"
10 #include "mojo/public/cpp/bindings/error_handler.h" 12 #include "mojo/public/cpp/bindings/error_handler.h"
11 #include "mojo/public/cpp/bindings/interface_ptr.h" 13 #include "mojo/public/cpp/bindings/interface_ptr.h"
12 #include "mojo/public/cpp/system/core.h" 14 #include "mojo/public/cpp/system/core.h"
13 #include "mojo/services/test_service/test_service.mojom.h" 15 #include "mojo/services/test_service/test_service.mojom.h"
16 #include "mojo/services/test_service/toy_monitoring_service.mojom.h"
14 #include "testing/gtest/include/gtest/gtest.h" 17 #include "testing/gtest/include/gtest/gtest.h"
15 #include "url/gurl.h" 18 #include "url/gurl.h"
16 19
20 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
21 using mojo::test::ServiceReportPtr;
22 using mojo::test::TestService;
23 using mojo::test::TestTimeService;
24 using mojo::test::TestServicePtr;
25 using mojo::test::TestTimeServicePtr;
26 using mojo::test::ToyMonitoringService;
27 using mojo::test::ToyMonitoringServicePtr;
28
17 namespace mojo { 29 namespace mojo {
18 namespace shell { 30 namespace shell {
19 namespace test { 31 namespace test {
20 namespace { 32 namespace {
21 33
22 typedef ShellTestBase ShellTestBaseTest; 34 void GetReportCallback(base::MessageLoop* loop,
35 std::vector<ServiceReport>* reports_out,
36 mojo::Array<ServiceReportPtr> report) {
37 for (size_t i = 0; i < report.size(); i++)
38 reports_out->push_back(*report[i]);
39 loop->QuitWhenIdle();
40 }
41
42 class ShellTestBaseTest : public ShellTestBase {
43 public:
44 // Convenience helpers for use as callbacks in tests.
45 template <typename T>
46 base::Callback<void()> SetAndQuit(T* val, T result) {
47 return base::Bind(&ShellTestBaseTest::SetAndQuitImpl<T>,
48 base::Unretained(this), val, result);
49 }
50 template <typename T>
51 base::Callback<void(T result)> SetAndQuit(T* val) {
52 return base::Bind(&ShellTestBaseTest::SetAndQuitImpl<T>,
53 base::Unretained(this), val);
54 }
55
56 static GURL test_app_url() {
57 return GURL("mojo:mojo_test_app");
58 }
59
60 void GetReport(std::vector<ServiceReport>* report) {
61 monitoring_.Bind(ConnectToService(GURL("mojo:mojo_test_monitoring_app"),
62 ToyMonitoringService::Name_).Pass());
63 monitoring_->GetReport(base::Bind(&GetReportCallback,
64 base::Unretained(message_loop()),
65 base::Unretained(report)));
66 message_loop()->Run();
67 }
68
69 private:
70 template<typename T>
71 void SetAndQuitImpl(T* val, T result) {
72 *val = result;
73 message_loop()->QuitWhenIdle();
74 }
75 ToyMonitoringServicePtr monitoring_;
76 };
23 77
24 class QuitMessageLoopErrorHandler : public ErrorHandler { 78 class QuitMessageLoopErrorHandler : public ErrorHandler {
25 public: 79 public:
26 QuitMessageLoopErrorHandler() {} 80 QuitMessageLoopErrorHandler() {}
27 virtual ~QuitMessageLoopErrorHandler() {} 81 virtual ~QuitMessageLoopErrorHandler() {}
28 82
29 // |ErrorHandler| implementation: 83 // |ErrorHandler| implementation:
30 virtual void OnConnectionError() OVERRIDE { 84 virtual void OnConnectionError() OVERRIDE {
31 base::MessageLoop::current()->QuitWhenIdle(); 85 base::MessageLoop::current()->QuitWhenIdle();
32 } 86 }
33 87
34 private: 88 private:
35 DISALLOW_COPY_AND_ASSIGN(QuitMessageLoopErrorHandler); 89 DISALLOW_COPY_AND_ASSIGN(QuitMessageLoopErrorHandler);
36 }; 90 };
37 91
38 void PingCallback(base::MessageLoop* message_loop, bool* was_run) { 92 // Tests that we can connect to a single service within a single app.
39 *was_run = true; 93 TEST_F(ShellTestBaseTest, ConnectBasic) {
40 VLOG(2) << "Ping callback"; 94 InterfacePtr<TestService> service;
41 message_loop->QuitWhenIdle(); 95 service.Bind(ConnectToService(test_app_url(), TestService::Name_).Pass());
42 }
43
44 TEST_F(ShellTestBaseTest, LaunchServiceInProcess) {
45 InterfacePtr<mojo::test::ITestService> test_service;
46
47 {
48 ScopedMessagePipeHandle service_handle =
49 LaunchServiceInProcess(GURL("mojo:mojo_test_service"),
50 mojo::test::ITestService::Name_);
51 test_service.Bind(service_handle.Pass());
52 }
53 96
54 bool was_run = false; 97 bool was_run = false;
55 test_service->Ping(base::Bind(&PingCallback, 98 service->Ping(SetAndQuit<bool>(&was_run, true));
56 base::Unretained(message_loop()),
57 base::Unretained(&was_run)));
58 message_loop()->Run(); 99 message_loop()->Run();
59 EXPECT_TRUE(was_run); 100 EXPECT_TRUE(was_run);
60 EXPECT_FALSE(test_service.encountered_error()); 101 EXPECT_FALSE(service.encountered_error());
61 102
62 test_service.reset(); 103 service.reset();
63 104
64 // This will run until the test service has actually quit (which it will, 105 // This will run until the test app has actually quit (which it will,
65 // since we killed the only connection to it). 106 // since we killed the only connection to it).
66 message_loop()->Run(); 107 message_loop()->Run();
67 } 108 }
68 109
69 // Tests that launching a service in process fails properly if the service 110 // Tests that trying to connect to a service fails properly if the service
70 // doesn't exist. 111 // doesn't exist.
71 TEST_F(ShellTestBaseTest, LaunchServiceInProcessInvalidService) { 112 TEST_F(ShellTestBaseTest, ConnectInvalidService) {
72 InterfacePtr<mojo::test::ITestService> test_service; 113 InterfacePtr<TestService> test_service;
73 114 test_service.Bind(ConnectToService(GURL("mojo:non_existent_service"),
74 { 115 TestService::Name_).Pass());
75 ScopedMessagePipeHandle service_handle =
76 LaunchServiceInProcess(GURL("mojo:non_existent_service"),
77 mojo::test::ITestService::Name_);
78 test_service.Bind(service_handle.Pass());
79 }
80 116
81 bool was_run = false; 117 bool was_run = false;
82 test_service->Ping(base::Bind(&PingCallback, 118 test_service->Ping(SetAndQuit<bool>(&was_run, true));
83 base::Unretained(message_loop()),
84 base::Unretained(&was_run)));
85 119
86 // This will quit because there's nothing running. 120 // This will quit because there's nothing running.
87 message_loop()->Run(); 121 message_loop()->Run();
88 EXPECT_FALSE(was_run); 122 EXPECT_FALSE(was_run);
89 123
90 // It may have quit before an error was processed. 124 // It may have quit before an error was processed.
91 if (!test_service.encountered_error()) { 125 if (!test_service.encountered_error()) {
92 QuitMessageLoopErrorHandler quitter; 126 QuitMessageLoopErrorHandler quitter;
93 test_service.set_error_handler(&quitter); 127 test_service.set_error_handler(&quitter);
94 message_loop()->Run(); 128 message_loop()->Run();
95 EXPECT_TRUE(test_service.encountered_error()); 129 EXPECT_TRUE(test_service.encountered_error());
96 } 130 }
97 131
98 test_service.reset(); 132 test_service.reset();
99 } 133 }
100 134
135 // Similar to ConnectBasic, but causes the app to instantiate multiple
136 // service implementation objects and verifies the shell can reach both.
137 TEST_F(ShellTestBaseTest, ConnectMultipleInstancesPerApp) {
138 {
139 TestServicePtr service1, service2;
140 service1.Bind(ConnectToService(test_app_url(), TestService::Name_).Pass());
141 service2.Bind(ConnectToService(test_app_url(), TestService::Name_).Pass());
142
143 bool was_run1 = false;
144 bool was_run2 = false;
145 service1->Ping(SetAndQuit<bool>(&was_run1, true));
146 service2->Ping(SetAndQuit<bool>(&was_run2, true));
147 message_loop()->Run();
148 EXPECT_TRUE(was_run1);
149 EXPECT_TRUE(was_run2);
150 EXPECT_FALSE(service1.encountered_error());
151 EXPECT_FALSE(service2.encountered_error());
152 }
153 message_loop()->Run();
154 }
155
156 // Tests that service A and service B, both in App 1, can talk to each other
157 // and parameters are passed around properly.
158 TEST_F(ShellTestBaseTest, ConnectDifferentServicesInSingleApp) {
159 // Have a TestService GetPartyTime on a TestTimeService in the same app.
160 std::string welcome;
161 TestServicePtr service;
162 service.Bind(ConnectToService(test_app_url(), TestService::Name_).Pass());
163 service->GetFriendlyWelcomeMessage(test_app_url().spec(),
164 SetAndQuit<std::string>(&welcome));
165 message_loop()->Run();
166
167 // Verify by hitting the TimeService directly.
168 TestTimeServicePtr time_service;
169 time_service.Bind(
170 ConnectToService(test_app_url(), TestTimeService::Name_).Pass());
171 int64 party_time;
172 time_service->GetPartyTime(SetAndQuit<int64>(&party_time));
173 message_loop()->Run();
174
175 std::string expected_welcome(
176 TestService::kWelcomeMessagePrefix +
177 UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
178 base::Time::FromInternalValue(party_time))));
179 EXPECT_EQ(welcome, expected_welcome);
180 }
181
182 // Tests that a service A in App 1 can talk to service B in App 2 and
183 // parameters are passed around properly.
184 TEST_F(ShellTestBaseTest, ConnectDifferentServicesInDifferentApps) {
185 std::string welcome;
186 TestServicePtr service;
187 service.Bind(ConnectToService(test_app_url(), TestService::Name_).Pass());
188 service->GetFriendlyWelcomeMessage("mojo:mojo_test_monitoring_app",
189 SetAndQuit<std::string>(&welcome));
190 message_loop()->Run();
191
192 // Verify by hitting the TimeService in the monitoring app directly.
193 TestTimeServicePtr time_service;
194 time_service.Bind(ConnectToService(GURL("mojo:mojo_test_monitoring_app"),
195 TestTimeService::Name_).Pass());
196 int64 party_time;
197 time_service->GetPartyTime(SetAndQuit<int64>(&party_time));
198 message_loop()->Run();
199
200 std::string expected_welcome(
201 TestService::kWelcomeMessagePrefix +
202 UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(
203 base::Time::FromInternalValue(party_time))));
204 EXPECT_EQ(welcome, expected_welcome);
205 }
206
207 // Tests that service A in App 1 can be a client of service B in App 2.
208 TEST_F(ShellTestBaseTest, ConnectServiceAsClientOfSeparateApp) {
209 TestServicePtr service;
210 service.Bind(ConnectToService(test_app_url(), TestService::Name_).Pass());
211 service->StartMonitoring(message_loop()->QuitWhenIdleClosure());
212 service->Ping(mojo::Callback<void()>());
213 message_loop()->Run();
214
215 for (int i = 0; i < 9; i++)
216 service->Ping(mojo::Callback<void()>());
217
218 // If everything worked properly, the monitoring service should report
219 // 10 pings to TestService.
220 std::vector<ServiceReport> reports;
221 GetReport(&reports);
222 ASSERT_EQ(1U, reports.size());
223 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.
224 EXPECT_EQ(10U, reports[0].total_requests);
225 }
226
227 // Connect several services together and use the monitoring service to verify
228 // communication.
229 TEST_F(ShellTestBaseTest, ConnectManyClientsAndServices) {
230 TestServicePtr service;
231 TestTimeServicePtr time_service;
232
233 // Make a request to the TestService and have it contact TimeService in the
234 // monitoring app. Do all this with monitoring enabled, meaning both services
235 // are connected as clients of the MonitoringService.
236 service.Bind(ConnectToService(test_app_url(), TestService::Name_).Pass());
237 service->StartMonitoring(message_loop()->QuitWhenIdleClosure());
238 message_loop()->Run();
239 for (int i = 0; i < 5; i++)
240 service->Ping(mojo::Callback<void()>());
241 std::string welcome;
242 service->GetFriendlyWelcomeMessage("mojo:mojo_test_monitoring_app",
243 SetAndQuit<std::string>(&welcome));
244 message_loop()->Run();
245
246 // Also make a few requests to the TimeService in the test_app.
247 time_service.Bind(
248 ConnectToService(test_app_url(), TestTimeService::Name_).Pass());
249 time_service->StartMonitoring(message_loop()->QuitWhenIdleClosure());
250 time_service->GetPartyTime(mojo::Callback<void(uint64_t)>());
251 message_loop()->Run();
252 for (int i = 0; i < 19; i++)
253 time_service->GetPartyTime(mojo::Callback<void(uint64_t)>());
254
255 std::vector<ServiceReport> reports;
256 GetReport(&reports);
257 ASSERT_EQ(3U, reports.size());
258 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.
259 EXPECT_EQ(6U, reports[0].total_requests);
260 EXPECT_EQ("mojo::test::TestTimeService", reports[1].service_name);
261 EXPECT_EQ(1U, reports[1].total_requests);
262 EXPECT_EQ("mojo::test::TestTimeService", reports[2].service_name);
263 EXPECT_EQ(20U, reports[2].total_requests);
264 }
265
101 } // namespace 266 } // namespace
102 } // namespace test 267 } // namespace test
103 } // namespace shell 268 } // namespace shell
104 } // namespace mojo 269 } // namespace mojo
OLDNEW
« mojo/services/test_service/toy_monitoring_service_impl.cc ('K') | « mojo/shell/shell_test_base.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698