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"
20 static const int kRenderProcessId
= 11;
22 class EmbeddedWorkerInstanceTest
: public testing::Test
{
24 EmbeddedWorkerInstanceTest()
25 : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP
) {}
27 virtual void SetUp() OVERRIDE
{
28 helper_
.reset(new EmbeddedWorkerTestHelper(kRenderProcessId
));
31 virtual void TearDown() OVERRIDE
{
35 ServiceWorkerContextCore
* context() { return helper_
->context(); }
37 EmbeddedWorkerRegistry
* embedded_worker_registry() {
39 return context()->embedded_worker_registry();
42 IPC::TestSink
* ipc_sink() { return helper_
->ipc_sink(); }
44 TestBrowserThreadBundle thread_bundle_
;
45 scoped_ptr
<EmbeddedWorkerTestHelper
> helper_
;
48 DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstanceTest
);
51 static void SaveStatusAndCall(ServiceWorkerStatusCode
* out
,
52 const base::Closure
& callback
,
53 ServiceWorkerStatusCode status
) {
58 TEST_F(EmbeddedWorkerInstanceTest
, StartAndStop
) {
59 scoped_ptr
<EmbeddedWorkerInstance
> worker
=
60 embedded_worker_registry()->CreateWorker();
61 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED
, worker
->status());
63 const int embedded_worker_id
= worker
->embedded_worker_id();
64 const int64 service_worker_version_id
= 55L;
65 const GURL
scope("http://example.com/");
66 const GURL
url("http://example.com/worker.js");
68 // Simulate adding one process to the worker.
69 helper_
->SimulateAddProcessToWorker(embedded_worker_id
, kRenderProcessId
);
71 // Start should succeed.
72 ServiceWorkerStatusCode status
;
73 base::RunLoop run_loop
;
75 service_worker_version_id
,
80 base::Bind(&SaveStatusAndCall
, &status
, run_loop
.QuitClosure()));
82 EXPECT_EQ(SERVICE_WORKER_OK
, status
);
83 EXPECT_EQ(EmbeddedWorkerInstance::STARTING
, worker
->status());
84 base::RunLoop().RunUntilIdle();
86 // Worker started message should be notified (by EmbeddedWorkerTestHelper).
87 EXPECT_EQ(EmbeddedWorkerInstance::RUNNING
, worker
->status());
88 EXPECT_EQ(kRenderProcessId
, worker
->process_id());
91 EXPECT_EQ(SERVICE_WORKER_OK
, worker
->Stop());
92 EXPECT_EQ(EmbeddedWorkerInstance::STOPPING
, worker
->status());
93 base::RunLoop().RunUntilIdle();
95 // Worker stopped message should be notified (by EmbeddedWorkerTestHelper).
96 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED
, worker
->status());
98 // Verify that we've sent two messages to start and terminate the worker.
99 ASSERT_TRUE(ipc_sink()->GetUniqueMessageMatching(
100 EmbeddedWorkerMsg_StartWorker::ID
));
101 ASSERT_TRUE(ipc_sink()->GetUniqueMessageMatching(
102 EmbeddedWorkerMsg_StopWorker::ID
));
105 TEST_F(EmbeddedWorkerInstanceTest
, InstanceDestroyedBeforeStartFinishes
) {
106 scoped_ptr
<EmbeddedWorkerInstance
> worker
=
107 embedded_worker_registry()->CreateWorker();
108 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED
, worker
->status());
110 const int64 service_worker_version_id
= 55L;
111 const GURL
scope("http://example.com/");
112 const GURL
url("http://example.com/worker.js");
114 ServiceWorkerStatusCode status
;
115 base::RunLoop run_loop
;
116 // Begin starting the worker.
117 std::vector
<int> available_process
;
118 available_process
.push_back(kRenderProcessId
);
120 service_worker_version_id
,
125 base::Bind(&SaveStatusAndCall
, &status
, run_loop
.QuitClosure()));
126 // But destroy it before it gets a chance to complete.
129 EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT
, status
);
131 // Verify that we didn't send the message to start the worker.
133 ipc_sink()->GetUniqueMessageMatching(EmbeddedWorkerMsg_StartWorker::ID
));
136 TEST_F(EmbeddedWorkerInstanceTest
, SortProcesses
) {
137 scoped_ptr
<EmbeddedWorkerInstance
> worker
=
138 embedded_worker_registry()->CreateWorker();
139 EXPECT_EQ(EmbeddedWorkerInstance::STOPPED
, worker
->status());
141 // Simulate adding processes to the worker.
142 // Process 1 has 1 ref, 2 has 2 refs and 3 has 3 refs.
143 const int embedded_worker_id
= worker
->embedded_worker_id();
144 helper_
->SimulateAddProcessToWorker(embedded_worker_id
, 1);
145 helper_
->SimulateAddProcessToWorker(embedded_worker_id
, 2);
146 helper_
->SimulateAddProcessToWorker(embedded_worker_id
, 2);
147 helper_
->SimulateAddProcessToWorker(embedded_worker_id
, 3);
148 helper_
->SimulateAddProcessToWorker(embedded_worker_id
, 3);
149 helper_
->SimulateAddProcessToWorker(embedded_worker_id
, 3);
151 // Process 3 has the biggest # of references and it should be chosen.
152 EXPECT_THAT(worker
->SortProcesses(std::vector
<int>()),
153 testing::ElementsAre(3, 2, 1));
154 EXPECT_EQ(-1, worker
->process_id());
156 // Argument processes are added to the existing set, but only for a single
158 std::vector
<int> registering_processes
;
159 registering_processes
.push_back(1);
160 registering_processes
.push_back(1);
161 registering_processes
.push_back(1);
162 registering_processes
.push_back(4);
163 EXPECT_THAT(worker
->SortProcesses(registering_processes
),
164 testing::ElementsAre(1, 3, 2, 4));
166 EXPECT_THAT(worker
->SortProcesses(std::vector
<int>()),
167 testing::ElementsAre(3, 2, 1));
170 } // namespace content