service_worker_version_unittest.cc revision 116680a4aac90f2aa7413d9095a592090648e557
15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/basictypes.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/run_loop.h"
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/service_worker/embedded_worker_registry.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/service_worker/embedded_worker_test_helper.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/service_worker/service_worker_context_core.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/service_worker/service_worker_registration.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/service_worker/service_worker_test_utils.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/service_worker/service_worker_version.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/test/test_browser_thread_bundle.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// IPC messages for testing ---------------------------------------------------
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define IPC_MESSAGE_IMPL
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ipc/ipc_message_macros.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define IPC_MESSAGE_START TestMsgStart
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)IPC_MESSAGE_CONTROL0(TestMsg_Message);
240529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochIPC_MESSAGE_ROUTED1(TestMsg_MessageFromWorker, int);
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// ---------------------------------------------------------------------------
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace content {
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static const int kRenderProcessId = 1;
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class MessageReceiver : public EmbeddedWorkerTestHelper {
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  MessageReceiver()
375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      : EmbeddedWorkerTestHelper(kRenderProcessId),
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        current_embedded_worker_id_(0) {}
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~MessageReceiver() {}
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  virtual bool OnMessageToWorker(int thread_id,
420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                 int embedded_worker_id,
430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                 const IPC::Message& message) OVERRIDE {
440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (EmbeddedWorkerTestHelper::OnMessageToWorker(
455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            thread_id, embedded_worker_id, message)) {
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return true;
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    current_embedded_worker_id_ = embedded_worker_id;
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool handled = true;
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IPC_BEGIN_MESSAGE_MAP(MessageReceiver, message)
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      IPC_MESSAGE_HANDLER(TestMsg_Message, OnMessage)
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      IPC_MESSAGE_UNHANDLED(handled = false)
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IPC_END_MESSAGE_MAP()
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return handled;
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  void SimulateSendValueToBrowser(int embedded_worker_id, int value) {
580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    SimulateSend(new TestMsg_MessageFromWorker(embedded_worker_id, value));
590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void OnMessage() {
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Do nothing.
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int current_embedded_worker_id_;
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MessageReceiver);
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void VerifyCalled(bool* called) {
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  *called = true;
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ObserveStatusChanges(ServiceWorkerVersion* version,
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                          std::vector<ServiceWorkerVersion::Status>* statuses) {
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  statuses->push_back(version->status());
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  version->RegisterStatusChangeCallback(
78c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      base::Bind(&ObserveStatusChanges, base::Unretained(version), statuses));
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// A specialized listener class to receive test messages from a worker.
820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochclass MessageReceiverFromWorker : public EmbeddedWorkerInstance::Listener {
830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch public:
840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  explicit MessageReceiverFromWorker(EmbeddedWorkerInstance* instance)
850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      : instance_(instance) {
860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    instance_->AddListener(this);
870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  virtual ~MessageReceiverFromWorker() {
890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    instance_->RemoveListener(this);
900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  virtual void OnStarted() OVERRIDE { NOTREACHED(); }
930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  virtual void OnStopped() OVERRIDE { NOTREACHED(); }
940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    bool handled = true;
960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    IPC_BEGIN_MESSAGE_MAP(MessageReceiverFromWorker, message)
970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      IPC_MESSAGE_HANDLER(TestMsg_MessageFromWorker, OnMessageFromWorker)
980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      IPC_MESSAGE_UNHANDLED(handled = false)
990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    IPC_END_MESSAGE_MAP()
1000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return handled;
1010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
1020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  void OnMessageFromWorker(int value) { received_values_.push_back(value); }
1040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const std::vector<int>& received_values() const { return received_values_; }
1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch private:
1070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EmbeddedWorkerInstance* instance_;
1080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  std::vector<int> received_values_;
1090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DISALLOW_COPY_AND_ASSIGN(MessageReceiverFromWorker);
1100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch};
1110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class ServiceWorkerVersionTest : public testing::Test {
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) protected:
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ServiceWorkerVersionTest()
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    helper_.reset(new MessageReceiver());
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    registration_ = new ServiceWorkerRegistration(
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        GURL("http://www.example.com/*"),
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        GURL("http://www.example.com/service_worker.js"),
1255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        1L,
1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        helper_->context()->AsWeakPtr());
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    version_ = new ServiceWorkerVersion(
1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        registration_, 1L, helper_->context()->AsWeakPtr());
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Simulate adding one process to the worker.
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int embedded_worker_id = version_->embedded_worker()->embedded_worker_id();
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    helper_->SimulateAddProcessToWorker(embedded_worker_id, kRenderProcessId);
133a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    ASSERT_TRUE(version_->HasProcessToRun());
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void TearDown() OVERRIDE {
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    version_ = 0;
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    registration_ = 0;
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    helper_.reset();
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestBrowserThreadBundle thread_bundle_;
1430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_ptr<MessageReceiver> helper_;
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<ServiceWorkerRegistration> registration_;
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_refptr<ServiceWorkerVersion> version_;
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersionTest);
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Call StartWorker() multiple times.
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_FAILED;
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_FAILED;
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ServiceWorkerStatusCode status3 = SERVICE_WORKER_ERROR_FAILED;
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  version_->StartWorker(CreateReceiverOnCurrentThread(&status1));
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  version_->StartWorker(CreateReceiverOnCurrentThread(&status2));
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Call StartWorker() after it's started.
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  version_->StartWorker(CreateReceiverOnCurrentThread(&status3));
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // All should just succeed.
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(SERVICE_WORKER_OK, status1);
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(SERVICE_WORKER_OK, status2);
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(SERVICE_WORKER_OK, status3);
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Call StopWorker() multiple times.
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  status1 = SERVICE_WORKER_ERROR_FAILED;
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  status2 = SERVICE_WORKER_ERROR_FAILED;
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  status3 = SERVICE_WORKER_ERROR_FAILED;
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  version_->StopWorker(CreateReceiverOnCurrentThread(&status1));
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  version_->StopWorker(CreateReceiverOnCurrentThread(&status2));
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Also try calling StartWorker while StopWorker is in queue.
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  version_->StartWorker(CreateReceiverOnCurrentThread(&status3));
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(ServiceWorkerVersion::STOPPING, version_->running_status());
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // All StopWorker should just succeed, while StartWorker fails.
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(SERVICE_WORKER_OK, status1);
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(SERVICE_WORKER_OK, status2);
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status3);
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(ServiceWorkerVersionTest, SendMessage) {
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Send a message without starting the worker.
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  version_->SendMessage(TestMsg_Message(),
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        CreateReceiverOnCurrentThread(&status));
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(SERVICE_WORKER_OK, status);
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The worker should be now started.
201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Stop the worker, and then send the message immediately.
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ServiceWorkerStatusCode msg_status = SERVICE_WORKER_ERROR_FAILED;
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ServiceWorkerStatusCode stop_status = SERVICE_WORKER_ERROR_FAILED;
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  version_->StopWorker(CreateReceiverOnCurrentThread(&stop_status));
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  version_->SendMessage(TestMsg_Message(),
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       CreateReceiverOnCurrentThread(&msg_status));
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(SERVICE_WORKER_OK, stop_status);
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // SendMessage should return START_WORKER_FAILED error since it tried to
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // start a worker while it was stopping.
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, msg_status);
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(ServiceWorkerVersionTest, ReSendMessageAfterStop) {
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Start the worker.
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ServiceWorkerStatusCode start_status = SERVICE_WORKER_ERROR_FAILED;
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  version_->StartWorker(CreateReceiverOnCurrentThread(&start_status));
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(SERVICE_WORKER_OK, start_status);
225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Stop the worker, and then send the message immediately.
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ServiceWorkerStatusCode msg_status = SERVICE_WORKER_ERROR_FAILED;
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ServiceWorkerStatusCode stop_status = SERVICE_WORKER_ERROR_FAILED;
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  version_->StopWorker(CreateReceiverOnCurrentThread(&stop_status));
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  version_->SendMessage(TestMsg_Message(),
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       CreateReceiverOnCurrentThread(&msg_status));
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(SERVICE_WORKER_OK, stop_status);
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // SendMessage should return START_WORKER_FAILED error since it tried to
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // start a worker while it was stopping.
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, msg_status);
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Resend the message, which should succeed and restart the worker.
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  version_->SendMessage(TestMsg_Message(),
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       CreateReceiverOnCurrentThread(&msg_status));
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(SERVICE_WORKER_OK, msg_status);
245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2480529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(ServiceWorkerVersionTest, ReceiveMessageFromWorker) {
2490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  MessageReceiverFromWorker receiver(version_->embedded_worker());
2500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Simulate sending some dummy values from the worker.
2520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  helper_->SimulateSendValueToBrowser(
2530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      version_->embedded_worker()->embedded_worker_id(), 555);
2540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  helper_->SimulateSendValueToBrowser(
2550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      version_->embedded_worker()->embedded_worker_id(), 777);
2560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Verify the receiver received the values.
2580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  ASSERT_EQ(2U, receiver.received_values().size());
2590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_EQ(555, receiver.received_values()[0]);
2600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_EQ(777, receiver.received_values()[1]);
2610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(ServiceWorkerVersionTest, InstallAndWaitCompletion) {
264116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  version_->SetStatus(ServiceWorkerVersion::INSTALLING);
265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Dispatch an install event.
267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  version_->DispatchInstallEvent(-1, CreateReceiverOnCurrentThread(&status));
269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Wait for the completion.
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool status_change_called = false;
272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  version_->RegisterStatusChangeCallback(
273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(&VerifyCalled, &status_change_called));
274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
277116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Version's status must not have changed during installation.
278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(SERVICE_WORKER_OK, status);
279116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_FALSE(status_change_called);
280116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(ServiceWorkerVersion::INSTALLING, version_->status());
281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(ServiceWorkerVersionTest, ActivateAndWaitCompletion) {
284116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Dispatch an activate event.
287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  version_->DispatchActivateEvent(CreateReceiverOnCurrentThread(&status));
289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Wait for the completion.
291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool status_change_called = false;
292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  version_->RegisterStatusChangeCallback(
293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(&VerifyCalled, &status_change_called));
294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
297116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Version's status must not have changed during activation.
298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(SERVICE_WORKER_OK, status);
299116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_FALSE(status_change_called);
300116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, version_->status());
301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(ServiceWorkerVersionTest, RepeatedlyObserveStatusChanges) {
304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(ServiceWorkerVersion::NEW, version_->status());
305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Repeatedly observe status changes (the callback re-registers itself).
307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::vector<ServiceWorkerVersion::Status> statuses;
308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  version_->RegisterStatusChangeCallback(
309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(&ObserveStatusChanges, version_, &statuses));
310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
311116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  version_->SetStatus(ServiceWorkerVersion::INSTALLING);
312116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  version_->SetStatus(ServiceWorkerVersion::INSTALLED);
313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
315116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  version_->SetStatus(ServiceWorkerVersion::REDUNDANT);
316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Verify that we could successfully observe repeated status changes.
318116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ASSERT_EQ(5U, statuses.size());
319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_EQ(ServiceWorkerVersion::INSTALLING, statuses[0]);
320a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_EQ(ServiceWorkerVersion::INSTALLED, statuses[1]);
321a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_EQ(ServiceWorkerVersion::ACTIVATING, statuses[2]);
322116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ASSERT_EQ(ServiceWorkerVersion::ACTIVATED, statuses[3]);
323116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ASSERT_EQ(ServiceWorkerVersion::REDUNDANT, statuses[4]);
324a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
325a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
326a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochTEST_F(ServiceWorkerVersionTest, AddAndRemoveProcesses) {
327a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Preparation (to reset the process count to 0).
328a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  ASSERT_TRUE(version_->HasProcessToRun());
329a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  version_->RemoveProcessFromWorker(kRenderProcessId);
330a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  ASSERT_FALSE(version_->HasProcessToRun());
331a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
332a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Add another process to the worker twice, and then remove process once.
333a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  const int another_process_id = kRenderProcessId + 1;
334a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  version_->AddProcessToWorker(another_process_id);
335a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  version_->AddProcessToWorker(another_process_id);
336a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  version_->RemoveProcessFromWorker(another_process_id);
337a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
338a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // We're ref-counting the process internally, so adding the same process
339a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // multiple times should be handled correctly.
340a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  ASSERT_TRUE(version_->HasProcessToRun());
341a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
342a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Removing the process again (so that # of AddProcess == # of RemoveProcess
343a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // for the process) should remove all process references.
344a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  version_->RemoveProcessFromWorker(another_process_id);
345a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  ASSERT_FALSE(version_->HasProcessToRun());
346a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
347a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace content
349