- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / service / service_process_control_browsertest.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/service/service_process_control.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "base/path_service.h"
11 #include "base/process/kill.h"
12 #include "base/process/process_handle.h"
13 #include "base/process/process_iterator.h"
14 #include "base/test/test_timeouts.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/common/chrome_constants.h"
17 #include "chrome/common/chrome_version_info.h"
18 #include "chrome/common/service_process_util.h"
19 #include "chrome/test/base/in_process_browser_test.h"
20 #include "chrome/test/base/ui_test_utils.h"
21 #include "content/public/common/content_paths.h"
22 #include "content/public/common/content_switches.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24
25 class ServiceProcessControlBrowserTest
26     : public InProcessBrowserTest {
27  public:
28   ServiceProcessControlBrowserTest()
29       : service_process_handle_(base::kNullProcessHandle) {
30   }
31   virtual ~ServiceProcessControlBrowserTest() {
32     base::CloseProcessHandle(service_process_handle_);
33     service_process_handle_ = base::kNullProcessHandle;
34   }
35
36   void HistogramsCallback() {
37     MockHistogramsCallback();
38     QuitMessageLoop();
39   }
40
41   MOCK_METHOD0(MockHistogramsCallback, void());
42
43  protected:
44   void LaunchServiceProcessControl() {
45     // Launch the process asynchronously.
46     ServiceProcessControl::GetInstance()->Launch(
47         base::Bind(&ServiceProcessControlBrowserTest::ProcessControlLaunched,
48                    this),
49         base::Bind(
50             &ServiceProcessControlBrowserTest::ProcessControlLaunchFailed,
51             this));
52
53     // Then run the message loop to keep things running.
54     content::RunMessageLoop();
55   }
56
57   static void QuitMessageLoop() {
58     base::MessageLoop::current()->Quit();
59   }
60
61   static void CloudPrintInfoCallback(
62       const cloud_print::CloudPrintProxyInfo& proxy_info) {
63     QuitMessageLoop();
64   }
65
66   void Disconnect() {
67     // This will close the IPC connection.
68     ServiceProcessControl::GetInstance()->Disconnect();
69   }
70
71   virtual void SetUp() OVERRIDE {
72     service_process_handle_ = base::kNullProcessHandle;
73   }
74
75   virtual void TearDown() OVERRIDE {
76     if (ServiceProcessControl::GetInstance()->IsConnected())
77       EXPECT_TRUE(ServiceProcessControl::GetInstance()->Shutdown());
78 #if defined(OS_MACOSX)
79     // ForceServiceProcessShutdown removes the process from launched on Mac.
80     ForceServiceProcessShutdown("", 0);
81 #endif  // OS_MACOSX
82     if (service_process_handle_ != base::kNullProcessHandle) {
83       EXPECT_TRUE(base::WaitForSingleProcess(
84           service_process_handle_,
85           TestTimeouts::action_max_timeout()));
86       service_process_handle_ = base::kNullProcessHandle;
87     }
88   }
89
90   void ProcessControlLaunched() {
91     base::ProcessId service_pid;
92     EXPECT_TRUE(GetServiceProcessData(NULL, &service_pid));
93     EXPECT_NE(static_cast<base::ProcessId>(0), service_pid);
94     EXPECT_TRUE(base::OpenProcessHandleWithAccess(
95         service_pid,
96         base::kProcessAccessWaitForTermination |
97         // we need query permission to get exit code
98         base::kProcessAccessQueryInformation,
99         &service_process_handle_));
100     // Quit the current message. Post a QuitTask instead of just calling Quit()
101     // because this can get invoked in the context of a Launch() call and we
102     // may not be in Run() yet.
103     base::MessageLoop::current()->PostTask(FROM_HERE,
104                                            base::MessageLoop::QuitClosure());
105   }
106
107   void ProcessControlLaunchFailed() {
108     ADD_FAILURE();
109     // Quit the current message.
110     base::MessageLoop::current()->PostTask(FROM_HERE,
111                                            base::MessageLoop::QuitClosure());
112   }
113
114  private:
115   base::ProcessHandle service_process_handle_;
116 };
117
118 class RealServiceProcessControlBrowserTest
119       : public ServiceProcessControlBrowserTest {
120  public:
121   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
122     ServiceProcessControlBrowserTest::SetUpCommandLine(command_line);
123     base::FilePath exe;
124     PathService::Get(base::DIR_EXE, &exe);
125 #if defined(OS_MACOSX)
126     exe = exe.DirName().DirName().DirName();
127 #endif
128     exe = exe.Append(chrome::kHelperProcessExecutablePath);
129     // Run chrome instead of browser_tests.exe.
130     EXPECT_TRUE(base::PathExists(exe));
131     command_line->AppendSwitchPath(switches::kBrowserSubprocessPath, exe);
132   }
133 };
134
135 #if defined(OS_MACOSX)
136 // Does not work on MACOSX.
137 #define MAYBE_LaunchAndIPC DISABLED_LaunchAndIPC
138 #else
139 #define MAYBE_LaunchAndIPC LaunchAndIPC
140 #endif
141
142 IN_PROC_BROWSER_TEST_F(RealServiceProcessControlBrowserTest,
143                        MAYBE_LaunchAndIPC) {
144   LaunchServiceProcessControl();
145
146   // Make sure we are connected to the service process.
147   ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
148   ServiceProcessControl::GetInstance()->GetCloudPrintProxyInfo(
149         base::Bind(&ServiceProcessControlBrowserTest::CloudPrintInfoCallback));
150   content::RunMessageLoop();
151
152   // And then shutdown the service process.
153   EXPECT_TRUE(ServiceProcessControl::GetInstance()->Shutdown());
154 }
155
156 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, LaunchAndIPC) {
157   LaunchServiceProcessControl();
158
159   // Make sure we are connected to the service process.
160   ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
161   ServiceProcessControl::GetInstance()->GetCloudPrintProxyInfo(
162         base::Bind(&ServiceProcessControlBrowserTest::CloudPrintInfoCallback));
163   content::RunMessageLoop();
164
165   // And then shutdown the service process.
166   EXPECT_TRUE(ServiceProcessControl::GetInstance()->Shutdown());
167 }
168
169 // This tests the case when a service process is launched when the browser
170 // starts but we try to launch it again while setting up Cloud Print.
171 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, LaunchTwice) {
172   // Launch the service process the first time.
173   LaunchServiceProcessControl();
174
175   // Make sure we are connected to the service process.
176   ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
177   EXPECT_TRUE(ServiceProcessControl::GetInstance()->GetCloudPrintProxyInfo(
178         base::Bind(&ServiceProcessControlBrowserTest::CloudPrintInfoCallback)));
179   content::RunMessageLoop();
180
181   // Launch the service process again.
182   LaunchServiceProcessControl();
183   ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
184   EXPECT_TRUE(ServiceProcessControl::GetInstance()->GetCloudPrintProxyInfo(
185         base::Bind(&ServiceProcessControlBrowserTest::CloudPrintInfoCallback)));
186   content::RunMessageLoop();
187 }
188
189 static void DecrementUntilZero(int* count) {
190   (*count)--;
191   if (!(*count))
192     base::MessageLoop::current()->PostTask(FROM_HERE,
193                                            base::MessageLoop::QuitClosure());
194 }
195
196 // Invoke multiple Launch calls in succession and ensure that all the tasks
197 // get invoked.
198 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest,
199                        MultipleLaunchTasks) {
200   ServiceProcessControl* process = ServiceProcessControl::GetInstance();
201   int launch_count = 5;
202   for (int i = 0; i < launch_count; i++) {
203     // Launch the process asynchronously.
204     process->Launch(base::Bind(&DecrementUntilZero, &launch_count),
205                     base::MessageLoop::QuitClosure());
206   }
207   // Then run the message loop to keep things running.
208   content::RunMessageLoop();
209   EXPECT_EQ(0, launch_count);
210 }
211
212 // Make sure using the same task for success and failure tasks works.
213 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, SameLaunchTask) {
214   ServiceProcessControl* process = ServiceProcessControl::GetInstance();
215   int launch_count = 5;
216   for (int i = 0; i < launch_count; i++) {
217     // Launch the process asynchronously.
218     base::Closure task = base::Bind(&DecrementUntilZero, &launch_count);
219     process->Launch(task, task);
220   }
221   // Then run the message loop to keep things running.
222   content::RunMessageLoop();
223   EXPECT_EQ(0, launch_count);
224 }
225
226 // Tests whether disconnecting from the service IPC causes the service process
227 // to die.
228 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, DieOnDisconnect) {
229   // Launch the service process.
230   LaunchServiceProcessControl();
231   // Make sure we are connected to the service process.
232   ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
233   Disconnect();
234 }
235
236 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, ForceShutdown) {
237   // Launch the service process.
238   LaunchServiceProcessControl();
239   // Make sure we are connected to the service process.
240   ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
241   base::ProcessId service_pid;
242   EXPECT_TRUE(GetServiceProcessData(NULL, &service_pid));
243   EXPECT_NE(static_cast<base::ProcessId>(0), service_pid);
244   chrome::VersionInfo version_info;
245   ForceServiceProcessShutdown(version_info.Version(), service_pid);
246 }
247
248 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, CheckPid) {
249   base::ProcessId service_pid;
250   EXPECT_FALSE(GetServiceProcessData(NULL, &service_pid));
251   // Launch the service process.
252   LaunchServiceProcessControl();
253   EXPECT_TRUE(GetServiceProcessData(NULL, &service_pid));
254   EXPECT_NE(static_cast<base::ProcessId>(0), service_pid);
255   // Disconnect from service process.
256   Disconnect();
257 }
258
259 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, HistogramsNoService) {
260   ASSERT_FALSE(ServiceProcessControl::GetInstance()->IsConnected());
261   EXPECT_CALL(*this, MockHistogramsCallback()).Times(0);
262   EXPECT_FALSE(ServiceProcessControl::GetInstance()->GetHistograms(
263       base::Bind(&ServiceProcessControlBrowserTest::HistogramsCallback,
264                  base::Unretained(this)),
265       base::TimeDelta()));
266 }
267
268 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, HistogramsTimeout) {
269   LaunchServiceProcessControl();
270   ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
271   // Callback should not be called during GetHistograms call.
272   EXPECT_CALL(*this, MockHistogramsCallback()).Times(0);
273   EXPECT_TRUE(ServiceProcessControl::GetInstance()->GetHistograms(
274       base::Bind(&ServiceProcessControlBrowserTest::HistogramsCallback,
275                  base::Unretained(this)),
276       base::TimeDelta::FromMilliseconds(100)));
277   EXPECT_CALL(*this, MockHistogramsCallback()).Times(1);
278   EXPECT_TRUE(ServiceProcessControl::GetInstance()->Shutdown());
279   content::RunMessageLoop();
280 }
281
282 IN_PROC_BROWSER_TEST_F(ServiceProcessControlBrowserTest, Histograms) {
283   LaunchServiceProcessControl();
284   ASSERT_TRUE(ServiceProcessControl::GetInstance()->IsConnected());
285   // Callback should not be called during GetHistograms call.
286   EXPECT_CALL(*this, MockHistogramsCallback()).Times(0);
287   // Wait for real callback by providing large timeout value.
288   EXPECT_TRUE(ServiceProcessControl::GetInstance()->GetHistograms(
289       base::Bind(&ServiceProcessControlBrowserTest::HistogramsCallback,
290                 base::Unretained(this)),
291       base::TimeDelta::FromHours(1)));
292   EXPECT_CALL(*this, MockHistogramsCallback()).Times(1);
293   content::RunMessageLoop();
294 }