Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / service_worker / service_worker_version_unittest.cc
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.
4
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"
15
16 // IPC messages for testing ---------------------------------------------------
17
18 #define IPC_MESSAGE_IMPL
19 #include "ipc/ipc_message_macros.h"
20
21 #define IPC_MESSAGE_START TestMsgStart
22
23 IPC_MESSAGE_CONTROL0(TestMsg_Message);
24 IPC_MESSAGE_ROUTED1(TestMsg_MessageFromWorker, int);
25
26 // ---------------------------------------------------------------------------
27
28 namespace content {
29
30 namespace {
31
32 static const int kRenderProcessId = 1;
33
34 class MessageReceiver : public EmbeddedWorkerTestHelper {
35  public:
36   MessageReceiver()
37       : EmbeddedWorkerTestHelper(kRenderProcessId),
38         current_embedded_worker_id_(0) {}
39   ~MessageReceiver() override {}
40
41   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;
47     }
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;
55   }
56
57   void SimulateSendValueToBrowser(int embedded_worker_id, int value) {
58     SimulateSend(new TestMsg_MessageFromWorker(embedded_worker_id, value));
59   }
60
61  private:
62   void OnMessage() {
63     // Do nothing.
64   }
65
66   int current_embedded_worker_id_;
67   DISALLOW_COPY_AND_ASSIGN(MessageReceiver);
68 };
69
70 void VerifyCalled(bool* called) {
71   *called = true;
72 }
73
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));
79 }
80
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);
87   }
88   ~MessageReceiverFromWorker() override { instance_->RemoveListener(this); }
89
90   void OnStarted() override { NOTREACHED(); }
91   void OnStopped() override { NOTREACHED(); }
92   bool OnMessageReceived(const IPC::Message& message) override {
93     bool handled = true;
94     IPC_BEGIN_MESSAGE_MAP(MessageReceiverFromWorker, message)
95       IPC_MESSAGE_HANDLER(TestMsg_MessageFromWorker, OnMessageFromWorker)
96       IPC_MESSAGE_UNHANDLED(handled = false)
97     IPC_END_MESSAGE_MAP()
98     return handled;
99   }
100
101   void OnMessageFromWorker(int value) { received_values_.push_back(value); }
102   const std::vector<int>& received_values() const { return received_values_; }
103
104  private:
105   EmbeddedWorkerInstance* instance_;
106   std::vector<int> received_values_;
107   DISALLOW_COPY_AND_ASSIGN(MessageReceiverFromWorker);
108 };
109
110 }  // namespace
111
112 class ServiceWorkerVersionTest : public testing::Test {
113  protected:
114   ServiceWorkerVersionTest()
115       : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
116
117   void SetUp() override {
118     helper_ = GetMessageReceiver();
119
120     pattern_ = GURL("http://www.example.com/");
121     registration_ = new ServiceWorkerRegistration(
122         pattern_,
123         1L,
124         helper_->context()->AsWeakPtr());
125     version_ = new ServiceWorkerVersion(
126         registration_.get(),
127         GURL("http://www.example.com/service_worker.js"),
128         1L,
129         helper_->context()->AsWeakPtr());
130
131     // Simulate adding one process to the pattern.
132     helper_->SimulateAddProcessToPattern(pattern_, kRenderProcessId);
133     ASSERT_TRUE(helper_->context()->process_manager()
134         ->PatternHasProcessToRun(pattern_));
135   }
136
137   virtual scoped_ptr<MessageReceiver> GetMessageReceiver() {
138     return make_scoped_ptr(new MessageReceiver());
139   }
140
141   void TearDown() override {
142     version_ = 0;
143     registration_ = 0;
144     helper_.reset();
145   }
146
147   TestBrowserThreadBundle thread_bundle_;
148   scoped_ptr<MessageReceiver> helper_;
149   scoped_refptr<ServiceWorkerRegistration> registration_;
150   scoped_refptr<ServiceWorkerVersion> version_;
151   GURL pattern_;
152
153  private:
154   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersionTest);
155 };
156
157 class MessageReceiverDisallowStart : public MessageReceiver {
158  public:
159   MessageReceiverDisallowStart()
160       : MessageReceiver() {}
161   ~MessageReceiverDisallowStart() override {}
162
163   void OnStartWorker(int embedded_worker_id,
164                      int64 service_worker_version_id,
165                      const GURL& scope,
166                      const GURL& script_url,
167                      bool pause_after_download) override {
168     // Do nothing.
169   }
170
171  private:
172   DISALLOW_COPY_AND_ASSIGN(MessageReceiverDisallowStart);
173 };
174
175 class ServiceWorkerFailToStartTest : public ServiceWorkerVersionTest {
176  protected:
177   ServiceWorkerFailToStartTest()
178       : ServiceWorkerVersionTest() {}
179
180   virtual scoped_ptr<MessageReceiver> GetMessageReceiver() override {
181     return make_scoped_ptr(new MessageReceiverDisallowStart());
182   }
183
184  private:
185   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerFailToStartTest);
186 };
187
188 TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
189   // Call StartWorker() multiple times.
190   ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_FAILED;
191   ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_FAILED;
192   ServiceWorkerStatusCode status3 = SERVICE_WORKER_ERROR_FAILED;
193   version_->StartWorker(CreateReceiverOnCurrentThread(&status1));
194   version_->StartWorker(CreateReceiverOnCurrentThread(&status2));
195
196   EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
197   base::RunLoop().RunUntilIdle();
198   EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
199
200   // Call StartWorker() after it's started.
201   version_->StartWorker(CreateReceiverOnCurrentThread(&status3));
202   base::RunLoop().RunUntilIdle();
203
204   // All should just succeed.
205   EXPECT_EQ(SERVICE_WORKER_OK, status1);
206   EXPECT_EQ(SERVICE_WORKER_OK, status2);
207   EXPECT_EQ(SERVICE_WORKER_OK, status3);
208
209   // Call StopWorker() multiple times.
210   status1 = SERVICE_WORKER_ERROR_FAILED;
211   status2 = SERVICE_WORKER_ERROR_FAILED;
212   status3 = SERVICE_WORKER_ERROR_FAILED;
213   version_->StopWorker(CreateReceiverOnCurrentThread(&status1));
214   version_->StopWorker(CreateReceiverOnCurrentThread(&status2));
215
216   // Also try calling StartWorker while StopWorker is in queue.
217   version_->StartWorker(CreateReceiverOnCurrentThread(&status3));
218
219   EXPECT_EQ(ServiceWorkerVersion::STOPPING, version_->running_status());
220   base::RunLoop().RunUntilIdle();
221   EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
222
223   // All StopWorker should just succeed, while StartWorker fails.
224   EXPECT_EQ(SERVICE_WORKER_OK, status1);
225   EXPECT_EQ(SERVICE_WORKER_OK, status2);
226   EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status3);
227 }
228
229 TEST_F(ServiceWorkerVersionTest, SendMessage) {
230   EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
231
232   // Send a message without starting the worker.
233   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
234   version_->SendMessage(TestMsg_Message(),
235                         CreateReceiverOnCurrentThread(&status));
236   base::RunLoop().RunUntilIdle();
237   EXPECT_EQ(SERVICE_WORKER_OK, status);
238
239   // The worker should be now started.
240   EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
241
242   // Stop the worker, and then send the message immediately.
243   ServiceWorkerStatusCode msg_status = SERVICE_WORKER_ERROR_FAILED;
244   ServiceWorkerStatusCode stop_status = SERVICE_WORKER_ERROR_FAILED;
245   version_->StopWorker(CreateReceiverOnCurrentThread(&stop_status));
246   version_->SendMessage(TestMsg_Message(),
247                        CreateReceiverOnCurrentThread(&msg_status));
248   base::RunLoop().RunUntilIdle();
249   EXPECT_EQ(SERVICE_WORKER_OK, stop_status);
250
251   // SendMessage should return START_WORKER_FAILED error since it tried to
252   // start a worker while it was stopping.
253   EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, msg_status);
254 }
255
256 TEST_F(ServiceWorkerVersionTest, ReSendMessageAfterStop) {
257   EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
258
259   // Start the worker.
260   ServiceWorkerStatusCode start_status = SERVICE_WORKER_ERROR_FAILED;
261   version_->StartWorker(CreateReceiverOnCurrentThread(&start_status));
262   base::RunLoop().RunUntilIdle();
263   EXPECT_EQ(SERVICE_WORKER_OK, start_status);
264   EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
265
266   // Stop the worker, and then send the message immediately.
267   ServiceWorkerStatusCode msg_status = SERVICE_WORKER_ERROR_FAILED;
268   ServiceWorkerStatusCode stop_status = SERVICE_WORKER_ERROR_FAILED;
269   version_->StopWorker(CreateReceiverOnCurrentThread(&stop_status));
270   version_->SendMessage(TestMsg_Message(),
271                        CreateReceiverOnCurrentThread(&msg_status));
272   base::RunLoop().RunUntilIdle();
273   EXPECT_EQ(SERVICE_WORKER_OK, stop_status);
274
275   // SendMessage should return START_WORKER_FAILED error since it tried to
276   // start a worker while it was stopping.
277   EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, msg_status);
278
279   // Resend the message, which should succeed and restart the worker.
280   version_->SendMessage(TestMsg_Message(),
281                        CreateReceiverOnCurrentThread(&msg_status));
282   base::RunLoop().RunUntilIdle();
283   EXPECT_EQ(SERVICE_WORKER_OK, msg_status);
284   EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
285 }
286
287 TEST_F(ServiceWorkerVersionTest, ReceiveMessageFromWorker) {
288   MessageReceiverFromWorker receiver(version_->embedded_worker());
289
290   // Simulate sending some dummy values from the worker.
291   helper_->SimulateSendValueToBrowser(
292       version_->embedded_worker()->embedded_worker_id(), 555);
293   helper_->SimulateSendValueToBrowser(
294       version_->embedded_worker()->embedded_worker_id(), 777);
295
296   // Verify the receiver received the values.
297   ASSERT_EQ(2U, receiver.received_values().size());
298   EXPECT_EQ(555, receiver.received_values()[0]);
299   EXPECT_EQ(777, receiver.received_values()[1]);
300 }
301
302 TEST_F(ServiceWorkerVersionTest, InstallAndWaitCompletion) {
303   version_->SetStatus(ServiceWorkerVersion::INSTALLING);
304
305   // Dispatch an install event.
306   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
307   version_->DispatchInstallEvent(-1, CreateReceiverOnCurrentThread(&status));
308
309   // Wait for the completion.
310   bool status_change_called = false;
311   version_->RegisterStatusChangeCallback(
312       base::Bind(&VerifyCalled, &status_change_called));
313
314   base::RunLoop().RunUntilIdle();
315
316   // Version's status must not have changed during installation.
317   EXPECT_EQ(SERVICE_WORKER_OK, status);
318   EXPECT_FALSE(status_change_called);
319   EXPECT_EQ(ServiceWorkerVersion::INSTALLING, version_->status());
320 }
321
322 TEST_F(ServiceWorkerVersionTest, ActivateAndWaitCompletion) {
323   version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
324
325   // Dispatch an activate event.
326   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
327   version_->DispatchActivateEvent(CreateReceiverOnCurrentThread(&status));
328
329   // Wait for the completion.
330   bool status_change_called = false;
331   version_->RegisterStatusChangeCallback(
332       base::Bind(&VerifyCalled, &status_change_called));
333
334   base::RunLoop().RunUntilIdle();
335
336   // Version's status must not have changed during activation.
337   EXPECT_EQ(SERVICE_WORKER_OK, status);
338   EXPECT_FALSE(status_change_called);
339   EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, version_->status());
340 }
341
342 TEST_F(ServiceWorkerVersionTest, RepeatedlyObserveStatusChanges) {
343   EXPECT_EQ(ServiceWorkerVersion::NEW, version_->status());
344
345   // Repeatedly observe status changes (the callback re-registers itself).
346   std::vector<ServiceWorkerVersion::Status> statuses;
347   version_->RegisterStatusChangeCallback(
348       base::Bind(&ObserveStatusChanges, version_, &statuses));
349
350   version_->SetStatus(ServiceWorkerVersion::INSTALLING);
351   version_->SetStatus(ServiceWorkerVersion::INSTALLED);
352   version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
353   version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
354   version_->SetStatus(ServiceWorkerVersion::REDUNDANT);
355
356   // Verify that we could successfully observe repeated status changes.
357   ASSERT_EQ(5U, statuses.size());
358   ASSERT_EQ(ServiceWorkerVersion::INSTALLING, statuses[0]);
359   ASSERT_EQ(ServiceWorkerVersion::INSTALLED, statuses[1]);
360   ASSERT_EQ(ServiceWorkerVersion::ACTIVATING, statuses[2]);
361   ASSERT_EQ(ServiceWorkerVersion::ACTIVATED, statuses[3]);
362   ASSERT_EQ(ServiceWorkerVersion::REDUNDANT, statuses[4]);
363 }
364
365 TEST_F(ServiceWorkerVersionTest, ScheduleStopWorker) {
366   // Verify the timer is not running when version initializes its status.
367   version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
368   EXPECT_FALSE(version_->stop_worker_timer_.IsRunning());
369
370   // Verify the timer is running when version status changes frome ACTIVATING
371   // to ACTIVATED.
372   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
373   version_->StartWorker(CreateReceiverOnCurrentThread(&status));
374   base::RunLoop().RunUntilIdle();
375   EXPECT_EQ(SERVICE_WORKER_OK, status);
376   version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
377   version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
378   EXPECT_TRUE(version_->stop_worker_timer_.IsRunning());
379
380   // The timer should be running if the worker is restarted without controllee.
381   status = SERVICE_WORKER_ERROR_FAILED;
382   version_->StopWorker(CreateReceiverOnCurrentThread(&status));
383   base::RunLoop().RunUntilIdle();
384   EXPECT_EQ(SERVICE_WORKER_OK, status);
385   status = SERVICE_WORKER_ERROR_FAILED;
386   version_->StartWorker(CreateReceiverOnCurrentThread(&status));
387   base::RunLoop().RunUntilIdle();
388   EXPECT_EQ(SERVICE_WORKER_OK, status);
389   EXPECT_TRUE(version_->stop_worker_timer_.IsRunning());
390
391   // The timer should not be running if a controllee is added.
392   scoped_ptr<ServiceWorkerProviderHost> host(
393       new ServiceWorkerProviderHost(33 /* dummy render process id */,
394                                     1 /* dummy provider_id */,
395                                     helper_->context()->AsWeakPtr(),
396                                     NULL));
397   version_->AddControllee(host.get());
398   EXPECT_FALSE(version_->stop_worker_timer_.IsRunning());
399
400   // The timer should be running if the controllee is removed.
401   version_->RemoveControllee(host.get());
402   EXPECT_TRUE(version_->stop_worker_timer_.IsRunning());
403 }
404
405 TEST_F(ServiceWorkerVersionTest, ListenerAvailability) {
406   // Initially the worker is not running. There should be no cache_listener_.
407   EXPECT_FALSE(version_->cache_listener_.get());
408
409   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
410   version_->StartWorker(
411       CreateReceiverOnCurrentThread(&status));
412   base::RunLoop().RunUntilIdle();
413
414   // A new cache listener should be available once the worker starts.
415   EXPECT_TRUE(version_->cache_listener_.get());
416
417   version_->StopWorker(
418       CreateReceiverOnCurrentThread(&status));
419   base::RunLoop().RunUntilIdle();
420
421   // Should be destroyed when the worker stops.
422   EXPECT_FALSE(version_->cache_listener_.get());
423
424   version_->StartWorker(
425       CreateReceiverOnCurrentThread(&status));
426   base::RunLoop().RunUntilIdle();
427
428   // Recreated when the worker starts again.
429   EXPECT_TRUE(version_->cache_listener_.get());
430 }
431
432 TEST_F(ServiceWorkerFailToStartTest, RendererCrash) {
433   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK;  // dummy value
434   version_->StartWorker(
435       CreateReceiverOnCurrentThread(&status));
436   base::RunLoop().RunUntilIdle();
437
438   // Callback has not completed yet.
439   EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, status);
440   EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
441
442   // Simulate renderer crash: do what
443   // ServiceWorkerDispatcherHost::OnFilterRemoved does.
444   int process_id = helper_->mock_render_process_id();
445   helper_->context()->RemoveAllProviderHostsForProcess(process_id);
446   helper_->context()->embedded_worker_registry()->RemoveChildProcessSender(
447       process_id);
448   base::RunLoop().RunUntilIdle();
449
450   // Callback completed.
451   EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status);
452   EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
453 }
454
455 }  // namespace content