Battery Status API: add UMA logging for Linux.
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_version_unittest.cc
blob11e54404646b9f19e867a4dbabf8365e602e047a
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
3 // found in the LICENSE file.
5 #include "base/basictypes.h"
6 #include "base/run_loop.h"
7 #include "content/browser/service_worker/embedded_worker_registry.h"
8 #include "content/browser/service_worker/embedded_worker_test_helper.h"
9 #include "content/browser/service_worker/service_worker_context_core.h"
10 #include "content/browser/service_worker/service_worker_registration.h"
11 #include "content/browser/service_worker/service_worker_test_utils.h"
12 #include "content/browser/service_worker/service_worker_version.h"
13 #include "content/public/test/test_browser_thread_bundle.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 // IPC messages for testing ---------------------------------------------------
18 #define IPC_MESSAGE_IMPL
19 #include "ipc/ipc_message_macros.h"
21 #define IPC_MESSAGE_START TestMsgStart
23 IPC_MESSAGE_CONTROL0(TestMsg_Message);
24 IPC_MESSAGE_ROUTED1(TestMsg_MessageFromWorker, int);
26 // ---------------------------------------------------------------------------
28 namespace content {
30 namespace {
32 static const int kRenderProcessId = 1;
34 class MessageReceiver : public EmbeddedWorkerTestHelper {
35 public:
36 MessageReceiver()
37 : EmbeddedWorkerTestHelper(kRenderProcessId),
38 current_embedded_worker_id_(0) {}
39 virtual ~MessageReceiver() {}
41 virtual bool OnMessageToWorker(int thread_id,
42 int embedded_worker_id,
43 const IPC::Message& message) OVERRIDE {
44 if (EmbeddedWorkerTestHelper::OnMessageToWorker(
45 thread_id, embedded_worker_id, message)) {
46 return true;
48 current_embedded_worker_id_ = embedded_worker_id;
49 bool handled = true;
50 IPC_BEGIN_MESSAGE_MAP(MessageReceiver, message)
51 IPC_MESSAGE_HANDLER(TestMsg_Message, OnMessage)
52 IPC_MESSAGE_UNHANDLED(handled = false)
53 IPC_END_MESSAGE_MAP()
54 return handled;
57 void SimulateSendValueToBrowser(int embedded_worker_id, int value) {
58 SimulateSend(new TestMsg_MessageFromWorker(embedded_worker_id, value));
61 private:
62 void OnMessage() {
63 // Do nothing.
66 int current_embedded_worker_id_;
67 DISALLOW_COPY_AND_ASSIGN(MessageReceiver);
70 void VerifyCalled(bool* called) {
71 *called = true;
74 void ObserveStatusChanges(ServiceWorkerVersion* version,
75 std::vector<ServiceWorkerVersion::Status>* statuses) {
76 statuses->push_back(version->status());
77 version->RegisterStatusChangeCallback(
78 base::Bind(&ObserveStatusChanges, base::Unretained(version), statuses));
81 // A specialized listener class to receive test messages from a worker.
82 class MessageReceiverFromWorker : public EmbeddedWorkerInstance::Listener {
83 public:
84 explicit MessageReceiverFromWorker(EmbeddedWorkerInstance* instance)
85 : instance_(instance) {
86 instance_->AddListener(this);
88 virtual ~MessageReceiverFromWorker() {
89 instance_->RemoveListener(this);
92 virtual void OnStarted() OVERRIDE { NOTREACHED(); }
93 virtual void OnStopped() OVERRIDE { NOTREACHED(); }
94 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
95 bool handled = true;
96 IPC_BEGIN_MESSAGE_MAP(MessageReceiverFromWorker, message)
97 IPC_MESSAGE_HANDLER(TestMsg_MessageFromWorker, OnMessageFromWorker)
98 IPC_MESSAGE_UNHANDLED(handled = false)
99 IPC_END_MESSAGE_MAP()
100 return handled;
103 void OnMessageFromWorker(int value) { received_values_.push_back(value); }
104 const std::vector<int>& received_values() const { return received_values_; }
106 private:
107 EmbeddedWorkerInstance* instance_;
108 std::vector<int> received_values_;
109 DISALLOW_COPY_AND_ASSIGN(MessageReceiverFromWorker);
112 } // namespace
114 class ServiceWorkerVersionTest : public testing::Test {
115 protected:
116 ServiceWorkerVersionTest()
117 : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
119 virtual void SetUp() OVERRIDE {
120 helper_.reset(new MessageReceiver());
122 registration_ = new ServiceWorkerRegistration(
123 GURL("http://www.example.com/"),
125 helper_->context()->AsWeakPtr());
126 version_ = new ServiceWorkerVersion(
127 registration_.get(),
128 GURL("http://www.example.com/service_worker.js"),
130 helper_->context()->AsWeakPtr());
132 // Simulate adding one process to the worker.
133 int embedded_worker_id = version_->embedded_worker()->embedded_worker_id();
134 helper_->SimulateAddProcessToWorker(embedded_worker_id, kRenderProcessId);
135 ASSERT_TRUE(version_->HasProcessToRun());
138 virtual void TearDown() OVERRIDE {
139 version_ = 0;
140 registration_ = 0;
141 helper_.reset();
144 TestBrowserThreadBundle thread_bundle_;
145 scoped_ptr<MessageReceiver> helper_;
146 scoped_refptr<ServiceWorkerRegistration> registration_;
147 scoped_refptr<ServiceWorkerVersion> version_;
149 private:
150 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersionTest);
153 TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
154 // Call StartWorker() multiple times.
155 ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_FAILED;
156 ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_FAILED;
157 ServiceWorkerStatusCode status3 = SERVICE_WORKER_ERROR_FAILED;
158 version_->StartWorker(CreateReceiverOnCurrentThread(&status1));
159 version_->StartWorker(CreateReceiverOnCurrentThread(&status2));
161 EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
162 base::RunLoop().RunUntilIdle();
163 EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
165 // Call StartWorker() after it's started.
166 version_->StartWorker(CreateReceiverOnCurrentThread(&status3));
167 base::RunLoop().RunUntilIdle();
169 // All should just succeed.
170 EXPECT_EQ(SERVICE_WORKER_OK, status1);
171 EXPECT_EQ(SERVICE_WORKER_OK, status2);
172 EXPECT_EQ(SERVICE_WORKER_OK, status3);
174 // Call StopWorker() multiple times.
175 status1 = SERVICE_WORKER_ERROR_FAILED;
176 status2 = SERVICE_WORKER_ERROR_FAILED;
177 status3 = SERVICE_WORKER_ERROR_FAILED;
178 version_->StopWorker(CreateReceiverOnCurrentThread(&status1));
179 version_->StopWorker(CreateReceiverOnCurrentThread(&status2));
181 // Also try calling StartWorker while StopWorker is in queue.
182 version_->StartWorker(CreateReceiverOnCurrentThread(&status3));
184 EXPECT_EQ(ServiceWorkerVersion::STOPPING, version_->running_status());
185 base::RunLoop().RunUntilIdle();
186 EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
188 // All StopWorker should just succeed, while StartWorker fails.
189 EXPECT_EQ(SERVICE_WORKER_OK, status1);
190 EXPECT_EQ(SERVICE_WORKER_OK, status2);
191 EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status3);
194 TEST_F(ServiceWorkerVersionTest, SendMessage) {
195 EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
197 // Send a message without starting the worker.
198 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
199 version_->SendMessage(TestMsg_Message(),
200 CreateReceiverOnCurrentThread(&status));
201 base::RunLoop().RunUntilIdle();
202 EXPECT_EQ(SERVICE_WORKER_OK, status);
204 // The worker should be now started.
205 EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
207 // Stop the worker, and then send the message immediately.
208 ServiceWorkerStatusCode msg_status = SERVICE_WORKER_ERROR_FAILED;
209 ServiceWorkerStatusCode stop_status = SERVICE_WORKER_ERROR_FAILED;
210 version_->StopWorker(CreateReceiverOnCurrentThread(&stop_status));
211 version_->SendMessage(TestMsg_Message(),
212 CreateReceiverOnCurrentThread(&msg_status));
213 base::RunLoop().RunUntilIdle();
214 EXPECT_EQ(SERVICE_WORKER_OK, stop_status);
216 // SendMessage should return START_WORKER_FAILED error since it tried to
217 // start a worker while it was stopping.
218 EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, msg_status);
221 TEST_F(ServiceWorkerVersionTest, ReSendMessageAfterStop) {
222 EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
224 // Start the worker.
225 ServiceWorkerStatusCode start_status = SERVICE_WORKER_ERROR_FAILED;
226 version_->StartWorker(CreateReceiverOnCurrentThread(&start_status));
227 base::RunLoop().RunUntilIdle();
228 EXPECT_EQ(SERVICE_WORKER_OK, start_status);
229 EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
231 // Stop the worker, and then send the message immediately.
232 ServiceWorkerStatusCode msg_status = SERVICE_WORKER_ERROR_FAILED;
233 ServiceWorkerStatusCode stop_status = SERVICE_WORKER_ERROR_FAILED;
234 version_->StopWorker(CreateReceiverOnCurrentThread(&stop_status));
235 version_->SendMessage(TestMsg_Message(),
236 CreateReceiverOnCurrentThread(&msg_status));
237 base::RunLoop().RunUntilIdle();
238 EXPECT_EQ(SERVICE_WORKER_OK, stop_status);
240 // SendMessage should return START_WORKER_FAILED error since it tried to
241 // start a worker while it was stopping.
242 EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, msg_status);
244 // Resend the message, which should succeed and restart the worker.
245 version_->SendMessage(TestMsg_Message(),
246 CreateReceiverOnCurrentThread(&msg_status));
247 base::RunLoop().RunUntilIdle();
248 EXPECT_EQ(SERVICE_WORKER_OK, msg_status);
249 EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
252 TEST_F(ServiceWorkerVersionTest, ReceiveMessageFromWorker) {
253 MessageReceiverFromWorker receiver(version_->embedded_worker());
255 // Simulate sending some dummy values from the worker.
256 helper_->SimulateSendValueToBrowser(
257 version_->embedded_worker()->embedded_worker_id(), 555);
258 helper_->SimulateSendValueToBrowser(
259 version_->embedded_worker()->embedded_worker_id(), 777);
261 // Verify the receiver received the values.
262 ASSERT_EQ(2U, receiver.received_values().size());
263 EXPECT_EQ(555, receiver.received_values()[0]);
264 EXPECT_EQ(777, receiver.received_values()[1]);
267 TEST_F(ServiceWorkerVersionTest, InstallAndWaitCompletion) {
268 version_->SetStatus(ServiceWorkerVersion::INSTALLING);
270 // Dispatch an install event.
271 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
272 version_->DispatchInstallEvent(-1, CreateReceiverOnCurrentThread(&status));
274 // Wait for the completion.
275 bool status_change_called = false;
276 version_->RegisterStatusChangeCallback(
277 base::Bind(&VerifyCalled, &status_change_called));
279 base::RunLoop().RunUntilIdle();
281 // Version's status must not have changed during installation.
282 EXPECT_EQ(SERVICE_WORKER_OK, status);
283 EXPECT_FALSE(status_change_called);
284 EXPECT_EQ(ServiceWorkerVersion::INSTALLING, version_->status());
287 TEST_F(ServiceWorkerVersionTest, ActivateAndWaitCompletion) {
288 version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
290 // Dispatch an activate event.
291 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
292 version_->DispatchActivateEvent(CreateReceiverOnCurrentThread(&status));
294 // Wait for the completion.
295 bool status_change_called = false;
296 version_->RegisterStatusChangeCallback(
297 base::Bind(&VerifyCalled, &status_change_called));
299 base::RunLoop().RunUntilIdle();
301 // Version's status must not have changed during activation.
302 EXPECT_EQ(SERVICE_WORKER_OK, status);
303 EXPECT_FALSE(status_change_called);
304 EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, version_->status());
307 TEST_F(ServiceWorkerVersionTest, RepeatedlyObserveStatusChanges) {
308 EXPECT_EQ(ServiceWorkerVersion::NEW, version_->status());
310 // Repeatedly observe status changes (the callback re-registers itself).
311 std::vector<ServiceWorkerVersion::Status> statuses;
312 version_->RegisterStatusChangeCallback(
313 base::Bind(&ObserveStatusChanges, version_, &statuses));
315 version_->SetStatus(ServiceWorkerVersion::INSTALLING);
316 version_->SetStatus(ServiceWorkerVersion::INSTALLED);
317 version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
318 version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
319 version_->SetStatus(ServiceWorkerVersion::REDUNDANT);
321 // Verify that we could successfully observe repeated status changes.
322 ASSERT_EQ(5U, statuses.size());
323 ASSERT_EQ(ServiceWorkerVersion::INSTALLING, statuses[0]);
324 ASSERT_EQ(ServiceWorkerVersion::INSTALLED, statuses[1]);
325 ASSERT_EQ(ServiceWorkerVersion::ACTIVATING, statuses[2]);
326 ASSERT_EQ(ServiceWorkerVersion::ACTIVATED, statuses[3]);
327 ASSERT_EQ(ServiceWorkerVersion::REDUNDANT, statuses[4]);
330 TEST_F(ServiceWorkerVersionTest, AddAndRemoveProcesses) {
331 // Preparation (to reset the process count to 0).
332 ASSERT_TRUE(version_->HasProcessToRun());
333 version_->RemoveProcessFromWorker(kRenderProcessId);
334 ASSERT_FALSE(version_->HasProcessToRun());
336 // Add another process to the worker twice, and then remove process once.
337 const int another_process_id = kRenderProcessId + 1;
338 version_->AddProcessToWorker(another_process_id);
339 version_->AddProcessToWorker(another_process_id);
340 version_->RemoveProcessFromWorker(another_process_id);
342 // We're ref-counting the process internally, so adding the same process
343 // multiple times should be handled correctly.
344 ASSERT_TRUE(version_->HasProcessToRun());
346 // Removing the process again (so that # of AddProcess == # of RemoveProcess
347 // for the process) should remove all process references.
348 version_->RemoveProcessFromWorker(another_process_id);
349 ASSERT_FALSE(version_->HasProcessToRun());
352 TEST_F(ServiceWorkerVersionTest, ScheduleStopWorker) {
353 // Verify the timer is not running when version initializes its status.
354 version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
355 EXPECT_FALSE(version_->stop_worker_timer_.IsRunning());
357 // Verify the timer is running when version status changes frome ACTIVATING
358 // to ACTIVATED.
359 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
360 version_->StartWorker(CreateReceiverOnCurrentThread(&status));
361 base::RunLoop().RunUntilIdle();
362 EXPECT_EQ(SERVICE_WORKER_OK, status);
363 version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
364 version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
365 EXPECT_TRUE(version_->stop_worker_timer_.IsRunning());
367 // The timer should be running if the worker is restarted without controllee.
368 status = SERVICE_WORKER_ERROR_FAILED;
369 version_->StopWorker(CreateReceiverOnCurrentThread(&status));
370 base::RunLoop().RunUntilIdle();
371 EXPECT_EQ(SERVICE_WORKER_OK, status);
372 status = SERVICE_WORKER_ERROR_FAILED;
373 version_->StartWorker(CreateReceiverOnCurrentThread(&status));
374 base::RunLoop().RunUntilIdle();
375 EXPECT_EQ(SERVICE_WORKER_OK, status);
376 EXPECT_TRUE(version_->stop_worker_timer_.IsRunning());
378 // The timer should not be running if a controllee is added.
379 scoped_ptr<ServiceWorkerProviderHost> host(
380 new ServiceWorkerProviderHost(33 /* dummy render process id */,
381 1 /* dummy provider_id */,
382 helper_->context()->AsWeakPtr(),
383 NULL));
384 version_->AddControllee(host.get());
385 EXPECT_FALSE(version_->stop_worker_timer_.IsRunning());
387 // The timer should be running if the controllee is removed.
388 version_->RemoveControllee(host.get());
389 EXPECT_TRUE(version_->stop_worker_timer_.IsRunning());
392 } // namespace content