Home | History | Annotate | Download | only in service_worker
      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.
      4 
      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"
     17 
     18 namespace content {
     19 
     20 static const int kRenderProcessId = 11;
     21 
     22 class EmbeddedWorkerInstanceTest : public testing::Test {
     23  protected:
     24   EmbeddedWorkerInstanceTest()
     25       : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
     26 
     27   virtual void SetUp() OVERRIDE {
     28     helper_.reset(new EmbeddedWorkerTestHelper(kRenderProcessId));
     29   }
     30 
     31   virtual void TearDown() OVERRIDE {
     32     helper_.reset();
     33   }
     34 
     35   ServiceWorkerContextCore* context() { return helper_->context(); }
     36 
     37   EmbeddedWorkerRegistry* embedded_worker_registry() {
     38     DCHECK(context());
     39     return context()->embedded_worker_registry();
     40   }
     41 
     42   IPC::TestSink* ipc_sink() { return helper_->ipc_sink(); }
     43 
     44   TestBrowserThreadBundle thread_bundle_;
     45   scoped_ptr<EmbeddedWorkerTestHelper> helper_;
     46 
     47  private:
     48   DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstanceTest);
     49 };
     50 
     51 static void SaveStatusAndCall(ServiceWorkerStatusCode* out,
     52                               const base::Closure& callback,
     53                               ServiceWorkerStatusCode status) {
     54   *out = status;
     55   callback.Run();
     56 }
     57 
     58 TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) {
     59   scoped_ptr<EmbeddedWorkerInstance> worker =
     60       embedded_worker_registry()->CreateWorker();
     61   EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
     62 
     63   const int64 service_worker_version_id = 55L;
     64   const GURL pattern("http://example.com/");
     65   const GURL url("http://example.com/worker.js");
     66 
     67   // Simulate adding one process to the pattern.
     68   helper_->SimulateAddProcessToPattern(pattern, kRenderProcessId);
     69 
     70   // Start should succeed.
     71   ServiceWorkerStatusCode status;
     72   base::RunLoop run_loop;
     73   worker->Start(
     74       service_worker_version_id,
     75       pattern,
     76       url,
     77       false,
     78       base::Bind(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
     79   run_loop.Run();
     80   EXPECT_EQ(SERVICE_WORKER_OK, status);
     81   EXPECT_EQ(EmbeddedWorkerInstance::STARTING, worker->status());
     82   base::RunLoop().RunUntilIdle();
     83 
     84   // Worker started message should be notified (by EmbeddedWorkerTestHelper).
     85   EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker->status());
     86   EXPECT_EQ(kRenderProcessId, worker->process_id());
     87 
     88   // Stop the worker.
     89   EXPECT_EQ(SERVICE_WORKER_OK, worker->Stop());
     90   EXPECT_EQ(EmbeddedWorkerInstance::STOPPING, worker->status());
     91   base::RunLoop().RunUntilIdle();
     92 
     93   // Worker stopped message should be notified (by EmbeddedWorkerTestHelper).
     94   EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
     95 
     96   // Verify that we've sent two messages to start and terminate the worker.
     97   ASSERT_TRUE(ipc_sink()->GetUniqueMessageMatching(
     98       EmbeddedWorkerMsg_StartWorker::ID));
     99   ASSERT_TRUE(ipc_sink()->GetUniqueMessageMatching(
    100       EmbeddedWorkerMsg_StopWorker::ID));
    101 }
    102 
    103 TEST_F(EmbeddedWorkerInstanceTest, InstanceDestroyedBeforeStartFinishes) {
    104   scoped_ptr<EmbeddedWorkerInstance> worker =
    105       embedded_worker_registry()->CreateWorker();
    106   EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
    107 
    108   const int64 service_worker_version_id = 55L;
    109   const GURL pattern("http://example.com/");
    110   const GURL url("http://example.com/worker.js");
    111 
    112   ServiceWorkerStatusCode status;
    113   base::RunLoop run_loop;
    114   // Begin starting the worker.
    115   context()->process_manager()->AddProcessReferenceToPattern(
    116       pattern, kRenderProcessId);
    117   worker->Start(
    118       service_worker_version_id,
    119       pattern,
    120       url,
    121       false,
    122       base::Bind(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
    123   // But destroy it before it gets a chance to complete.
    124   worker.reset();
    125   run_loop.Run();
    126   EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT, status);
    127 
    128   // Verify that we didn't send the message to start the worker.
    129   ASSERT_FALSE(
    130       ipc_sink()->GetUniqueMessageMatching(EmbeddedWorkerMsg_StartWorker::ID));
    131 }
    132 
    133 }  // namespace content
    134