1 // Copyright 2013 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.
5 #include "base/basictypes.h"
6 #include "base/run_loop.h"
7 #include "base/stl_util.h"
8 #include "content/browser/service_worker/embedded_worker_instance.h"
9 #include "content/browser/service_worker/embedded_worker_registry.h"
10 #include "content/browser/service_worker/embedded_worker_test_helper.h"
11 #include "content/browser/service_worker/service_worker_context_core.h"
12 #include "content/browser/service_worker/service_worker_context_wrapper.h"
13 #include "content/common/service_worker/embedded_worker_messages.h"
14 #include "content/public/test/test_browser_thread_bundle.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
22 const int kRenderProcessId
= 11;
24 void SaveStatusAndCall(ServiceWorkerStatusCode
* out
,
25 const base::Closure
& callback
,
26 ServiceWorkerStatusCode status
) {
33 class EmbeddedWorkerInstanceTest
: public testing::Test
{
35 EmbeddedWorkerInstanceTest()
36 : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP
) {}
38 void SetUp() override
{
40 new EmbeddedWorkerTestHelper(base::FilePath(), kRenderProcessId
));
43 void TearDown() override
{ helper_
.reset(); }
45 ServiceWorkerStatusCode
StartWorker(EmbeddedWorkerInstance
* worker
,
46 int id
, const GURL
& pattern
,
48 ServiceWorkerStatusCode status
;
49 base::RunLoop run_loop
;
50 worker
->Start(id
, pattern
, url
, base::Bind(&SaveStatusAndCall
, &status
,
51 run_loop
.QuitClosure()));
56 ServiceWorkerContextCore
* context() { return helper_
->context(); }
58 EmbeddedWorkerRegistry
* embedded_worker_registry() {
60 return context()->embedded_worker_registry();
63 IPC::TestSink
* ipc_sink() { return helper_
->ipc_sink(); }
65 TestBrowserThreadBundle thread_bundle_
;
66 scoped_ptr
<EmbeddedWorkerTestHelper
> helper_
;
69 DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstanceTest
);
72 TEST_F(EmbeddedWorkerInstanceTest
, StartAndStop
) {
73 scoped_ptr
<EmbeddedWorkerInstance
> worker
=
74 embedded_worker_registry()->CreateWorker();
75 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED
, worker
->status());
77 const int64 service_worker_version_id
= 55L;
78 const GURL
pattern("http://example.com/");
79 const GURL
url("http://example.com/worker.js");
81 // Simulate adding one process to the pattern.
82 helper_
->SimulateAddProcessToPattern(pattern
, kRenderProcessId
);
84 // Start should succeed.
85 ServiceWorkerStatusCode status
;
86 base::RunLoop run_loop
;
88 service_worker_version_id
,
91 base::Bind(&SaveStatusAndCall
, &status
, run_loop
.QuitClosure()));
92 EXPECT_EQ(EmbeddedWorkerInstance::STARTING
, worker
->status());
94 EXPECT_EQ(SERVICE_WORKER_OK
, status
);
96 // The 'WorkerStarted' message should have been sent by
97 // EmbeddedWorkerTestHelper.
98 EXPECT_EQ(EmbeddedWorkerInstance::RUNNING
, worker
->status());
99 EXPECT_EQ(kRenderProcessId
, worker
->process_id());
102 EXPECT_EQ(SERVICE_WORKER_OK
, worker
->Stop());
103 EXPECT_EQ(EmbeddedWorkerInstance::STOPPING
, worker
->status());
104 base::RunLoop().RunUntilIdle();
106 // The 'WorkerStopped' message should have been sent by
107 // EmbeddedWorkerTestHelper.
108 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED
, worker
->status());
110 // Verify that we've sent two messages to start and terminate the worker.
112 ipc_sink()->GetUniqueMessageMatching(EmbeddedWorkerMsg_StartWorker::ID
));
113 ASSERT_TRUE(ipc_sink()->GetUniqueMessageMatching(
114 EmbeddedWorkerMsg_StopWorker::ID
));
117 TEST_F(EmbeddedWorkerInstanceTest
, StopWhenDevToolsAttached
) {
118 scoped_ptr
<EmbeddedWorkerInstance
> worker
=
119 embedded_worker_registry()->CreateWorker();
120 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED
, worker
->status());
122 const int64 service_worker_version_id
= 55L;
123 const GURL
pattern("http://example.com/");
124 const GURL
url("http://example.com/worker.js");
126 // Simulate adding one process to the pattern.
127 helper_
->SimulateAddProcessToPattern(pattern
, kRenderProcessId
);
129 // Start the worker and then call StopIfIdle().
130 EXPECT_EQ(SERVICE_WORKER_OK
,
131 StartWorker(worker
.get(), service_worker_version_id
, pattern
, url
));
132 EXPECT_EQ(EmbeddedWorkerInstance::RUNNING
, worker
->status());
133 EXPECT_EQ(kRenderProcessId
, worker
->process_id());
134 worker
->StopIfIdle();
135 EXPECT_EQ(EmbeddedWorkerInstance::STOPPING
, worker
->status());
136 base::RunLoop().RunUntilIdle();
138 // The worker must be stopped now.
139 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED
, worker
->status());
141 // Set devtools_attached to true, and do the same.
142 worker
->set_devtools_attached(true);
144 EXPECT_EQ(SERVICE_WORKER_OK
,
145 StartWorker(worker
.get(), service_worker_version_id
, pattern
, url
));
146 EXPECT_EQ(EmbeddedWorkerInstance::RUNNING
, worker
->status());
147 EXPECT_EQ(kRenderProcessId
, worker
->process_id());
148 worker
->StopIfIdle();
149 base::RunLoop().RunUntilIdle();
151 // The worker must not be stopped this time.
152 EXPECT_EQ(EmbeddedWorkerInstance::RUNNING
, worker
->status());
154 // Calling Stop() actually stops the worker regardless of whether devtools
155 // is attached or not.
156 EXPECT_EQ(SERVICE_WORKER_OK
, worker
->Stop());
157 base::RunLoop().RunUntilIdle();
158 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED
, worker
->status());
161 // Test that the removal of a worker from the registry doesn't remove
162 // other workers in the same process.
163 TEST_F(EmbeddedWorkerInstanceTest
, RemoveWorkerInSharedProcess
) {
164 scoped_ptr
<EmbeddedWorkerInstance
> worker1
=
165 embedded_worker_registry()->CreateWorker();
166 scoped_ptr
<EmbeddedWorkerInstance
> worker2
=
167 embedded_worker_registry()->CreateWorker();
169 const int64 version_id1
= 55L;
170 const int64 version_id2
= 56L;
171 const GURL
pattern("http://example.com/");
172 const GURL
url("http://example.com/worker.js");
174 helper_
->SimulateAddProcessToPattern(pattern
, kRenderProcessId
);
177 ServiceWorkerStatusCode status
;
178 base::RunLoop run_loop
;
180 version_id1
, pattern
, url
,
181 base::Bind(&SaveStatusAndCall
, &status
, run_loop
.QuitClosure()));
183 EXPECT_EQ(SERVICE_WORKER_OK
, status
);
188 ServiceWorkerStatusCode status
;
189 base::RunLoop run_loop
;
191 version_id2
, pattern
, url
,
192 base::Bind(&SaveStatusAndCall
, &status
, run_loop
.QuitClosure()));
194 EXPECT_EQ(SERVICE_WORKER_OK
, status
);
197 // The two workers share the same process.
198 EXPECT_EQ(worker1
->process_id(), worker2
->process_id());
200 // Destroy worker1. It removes itself from the registry.
201 int worker1_id
= worker1
->embedded_worker_id();
205 // Only worker1 should be removed from the registry's process_map.
206 EmbeddedWorkerRegistry
* registry
=
207 helper_
->context()->embedded_worker_registry();
209 registry
->worker_process_map_
[kRenderProcessId
].count(worker1_id
));
210 EXPECT_EQ(1UL, registry
->worker_process_map_
[kRenderProcessId
].count(
211 worker2
->embedded_worker_id()));
216 } // namespace content