OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/basictypes.h" | 5 #include "base/basictypes.h" |
6 #include "base/run_loop.h" | 6 #include "base/run_loop.h" |
7 #include "content/browser/service_worker/embedded_worker_registry.h" | 7 #include "content/browser/service_worker/embedded_worker_registry.h" |
8 #include "content/browser/service_worker/embedded_worker_test_helper.h" | 8 #include "content/browser/service_worker/embedded_worker_test_helper.h" |
9 #include "content/browser/service_worker/service_worker_context_core.h" | 9 #include "content/browser/service_worker/service_worker_context_core.h" |
10 #include "content/browser/service_worker/service_worker_registration.h" | 10 #include "content/browser/service_worker/service_worker_registration.h" |
11 #include "content/browser/service_worker/service_worker_test_utils.h" | 11 #include "content/browser/service_worker/service_worker_test_utils.h" |
12 #include "content/browser/service_worker/service_worker_version.h" | 12 #include "content/browser/service_worker/service_worker_version.h" |
13 #include "content/public/test/test_browser_thread_bundle.h" | 13 #include "content/public/test/test_browser_thread_bundle.h" |
14 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
15 | 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_CONTROL1(TestMsg_Request, int); |
| 25 IPC_MESSAGE_CONTROL1(TestMsg_Response, int); |
| 26 |
| 27 // --------------------------------------------------------------------------- |
| 28 |
16 namespace content { | 29 namespace content { |
17 | 30 |
| 31 namespace { |
| 32 |
| 33 class MessageReceiver : public EmbeddedWorkerTestHelper { |
| 34 public: |
| 35 MessageReceiver(ServiceWorkerContextCore* context) |
| 36 : EmbeddedWorkerTestHelper(context), |
| 37 current_embedded_worker_id_(0), |
| 38 current_request_id_(0) {} |
| 39 virtual ~MessageReceiver() {} |
| 40 |
| 41 virtual void OnSendMessageToWorker(int thread_id, |
| 42 int embedded_worker_id, |
| 43 int request_id, |
| 44 const IPC::Message& message) OVERRIDE { |
| 45 current_embedded_worker_id_ = embedded_worker_id; |
| 46 current_request_id_ = request_id; |
| 47 bool handled = true; |
| 48 IPC_BEGIN_MESSAGE_MAP(MessageReceiver, message) |
| 49 IPC_MESSAGE_HANDLER(TestMsg_Message, OnMessage) |
| 50 IPC_MESSAGE_HANDLER(TestMsg_Request, OnRequest) |
| 51 IPC_MESSAGE_UNHANDLED(handled = false) |
| 52 IPC_END_MESSAGE_MAP() |
| 53 ASSERT_TRUE(handled); |
| 54 } |
| 55 |
| 56 private: |
| 57 void OnMessage() { |
| 58 // Do nothing. |
| 59 } |
| 60 |
| 61 void OnRequest(int value) { |
| 62 // Double the given value and send back the response. |
| 63 SimulateSendMessageToBrowser(current_embedded_worker_id_, |
| 64 current_request_id_, |
| 65 TestMsg_Response(value * 2)); |
| 66 } |
| 67 |
| 68 int current_embedded_worker_id_; |
| 69 int current_request_id_; |
| 70 DISALLOW_COPY_AND_ASSIGN(MessageReceiver); |
| 71 }; |
| 72 |
| 73 void ReceiveResponse(ServiceWorkerStatusCode* status_out, |
| 74 int* value_out, |
| 75 ServiceWorkerStatusCode status, |
| 76 const IPC::Message& message) { |
| 77 Tuple1<int> param; |
| 78 ASSERT_TRUE(TestMsg_Response::Read(&message, ¶m)); |
| 79 *status_out = status; |
| 80 *value_out = param.a; |
| 81 } |
| 82 |
| 83 } // namespace |
| 84 |
18 class ServiceWorkerVersionTest : public testing::Test { | 85 class ServiceWorkerVersionTest : public testing::Test { |
19 protected: | 86 protected: |
20 ServiceWorkerVersionTest() | 87 ServiceWorkerVersionTest() |
21 : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {} | 88 : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {} |
22 | 89 |
23 virtual void SetUp() OVERRIDE { | 90 virtual void SetUp() OVERRIDE { |
24 context_.reset(new ServiceWorkerContextCore(base::FilePath(), NULL)); | 91 context_.reset(new ServiceWorkerContextCore(base::FilePath(), NULL)); |
25 helper_.reset(new EmbeddedWorkerTestHelper(context_.get())); | 92 helper_.reset(new MessageReceiver(context_.get())); |
26 | 93 |
27 registration_ = new ServiceWorkerRegistration( | 94 registration_ = new ServiceWorkerRegistration( |
28 GURL("http://www.example.com/*"), | 95 GURL("http://www.example.com/*"), |
29 GURL("http://www.example.com/service_worker.js"), | 96 GURL("http://www.example.com/service_worker.js"), |
30 1L); | 97 1L); |
| 98 version_ = new ServiceWorkerVersion( |
| 99 registration_, |
| 100 embedded_worker_registry(), |
| 101 1L); |
| 102 |
| 103 // Simulate adding one process to the worker. |
| 104 int embedded_worker_id = version_->embedded_worker()->embedded_worker_id(); |
| 105 helper_->SimulateAddProcess(embedded_worker_id, 1); |
31 } | 106 } |
32 | 107 |
33 virtual void TearDown() OVERRIDE { | 108 virtual void TearDown() OVERRIDE { |
| 109 version_->Shutdown(); |
| 110 version_ = 0; |
34 registration_->Shutdown(); | 111 registration_->Shutdown(); |
| 112 registration_ = 0; |
35 helper_.reset(); | 113 helper_.reset(); |
36 context_.reset(); | 114 context_.reset(); |
37 } | 115 } |
38 | 116 |
39 EmbeddedWorkerRegistry* embedded_worker_registry() { | 117 EmbeddedWorkerRegistry* embedded_worker_registry() { |
40 return context_->embedded_worker_registry(); | 118 return context_->embedded_worker_registry(); |
41 } | 119 } |
42 | 120 |
43 TestBrowserThreadBundle thread_bundle_; | 121 TestBrowserThreadBundle thread_bundle_; |
44 scoped_ptr<ServiceWorkerContextCore> context_; | 122 scoped_ptr<ServiceWorkerContextCore> context_; |
45 scoped_ptr<EmbeddedWorkerTestHelper> helper_; | 123 scoped_ptr<EmbeddedWorkerTestHelper> helper_; |
46 scoped_refptr<ServiceWorkerRegistration> registration_; | 124 scoped_refptr<ServiceWorkerRegistration> registration_; |
| 125 scoped_refptr<ServiceWorkerVersion> version_; |
47 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersionTest); | 126 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersionTest); |
48 }; | 127 }; |
49 | 128 |
50 TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) { | 129 TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) { |
51 const int64 version_id = 1L; | |
52 | |
53 scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion( | |
54 registration_, | |
55 embedded_worker_registry(), | |
56 version_id); | |
57 int embedded_worker_id = version->embedded_worker()->embedded_worker_id(); | |
58 | |
59 // Simulate adding one process to the worker. | |
60 helper_->SimulateAddProcess(embedded_worker_id, 1); | |
61 | |
62 BrowserThread::ID current = BrowserThread::IO; | |
63 | |
64 // Call StartWorker() multiple times. | 130 // Call StartWorker() multiple times. |
65 ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_FAILED; | 131 ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_FAILED; |
66 ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_FAILED; | 132 ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_FAILED; |
67 ServiceWorkerStatusCode status3 = SERVICE_WORKER_ERROR_FAILED; | 133 ServiceWorkerStatusCode status3 = SERVICE_WORKER_ERROR_FAILED; |
68 version->StartWorker(CreateReceiver(current, base::Closure(), &status1)); | 134 version_->StartWorker(CreateReceiverOnCurrentThread(&status1)); |
69 version->StartWorker(CreateReceiver(current, base::Closure(), &status2)); | 135 version_->StartWorker(CreateReceiverOnCurrentThread(&status2)); |
70 | 136 |
71 EXPECT_EQ(ServiceWorkerVersion::STARTING, version->status()); | 137 EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->status()); |
72 base::RunLoop().RunUntilIdle(); | 138 base::RunLoop().RunUntilIdle(); |
73 EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->status()); | 139 EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->status()); |
74 | 140 |
75 // Call StartWorker() after it's started. | 141 // Call StartWorker() after it's started. |
76 version->StartWorker(CreateReceiver(current, base::Closure(), &status3)); | 142 version_->StartWorker(CreateReceiverOnCurrentThread(&status3)); |
77 base::RunLoop().RunUntilIdle(); | 143 base::RunLoop().RunUntilIdle(); |
78 | 144 |
79 // All should just succeed. | 145 // All should just succeed. |
80 EXPECT_EQ(SERVICE_WORKER_OK, status1); | 146 EXPECT_EQ(SERVICE_WORKER_OK, status1); |
81 EXPECT_EQ(SERVICE_WORKER_OK, status2); | 147 EXPECT_EQ(SERVICE_WORKER_OK, status2); |
82 EXPECT_EQ(SERVICE_WORKER_OK, status3); | 148 EXPECT_EQ(SERVICE_WORKER_OK, status3); |
83 | 149 |
84 // Call StopWorker() multiple times. | 150 // Call StopWorker() multiple times. |
85 status1 = SERVICE_WORKER_ERROR_FAILED; | 151 status1 = SERVICE_WORKER_ERROR_FAILED; |
86 status2 = SERVICE_WORKER_ERROR_FAILED; | 152 status2 = SERVICE_WORKER_ERROR_FAILED; |
87 status3 = SERVICE_WORKER_ERROR_FAILED; | 153 status3 = SERVICE_WORKER_ERROR_FAILED; |
88 version->StopWorker(CreateReceiver(current, base::Closure(), &status1)); | 154 version_->StopWorker(CreateReceiverOnCurrentThread(&status1)); |
89 version->StopWorker(CreateReceiver(current, base::Closure(), &status2)); | 155 version_->StopWorker(CreateReceiverOnCurrentThread(&status2)); |
90 | 156 |
91 // Also try calling StartWorker while StopWorker is in queue. | 157 // Also try calling StartWorker while StopWorker is in queue. |
92 version->StartWorker(CreateReceiver(current, base::Closure(), &status3)); | 158 version_->StartWorker(CreateReceiverOnCurrentThread(&status3)); |
93 | 159 |
94 EXPECT_EQ(ServiceWorkerVersion::STOPPING, version->status()); | 160 EXPECT_EQ(ServiceWorkerVersion::STOPPING, version_->status()); |
95 base::RunLoop().RunUntilIdle(); | 161 base::RunLoop().RunUntilIdle(); |
96 EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->status()); | 162 EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->status()); |
97 | 163 |
98 // All StopWorker should just succeed, while StartWorker fails. | 164 // All StopWorker should just succeed, while StartWorker fails. |
99 EXPECT_EQ(SERVICE_WORKER_OK, status1); | 165 EXPECT_EQ(SERVICE_WORKER_OK, status1); |
100 EXPECT_EQ(SERVICE_WORKER_OK, status2); | 166 EXPECT_EQ(SERVICE_WORKER_OK, status2); |
101 EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status3); | 167 EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status3); |
| 168 } |
102 | 169 |
103 version->Shutdown(); | 170 TEST_F(ServiceWorkerVersionTest, SendMessage) { |
| 171 EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->status()); |
| 172 |
| 173 // Send a message without starting the worker. |
| 174 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED; |
| 175 version_->SendMessage(TestMsg_Message(), |
| 176 CreateReceiverOnCurrentThread(&status)); |
| 177 base::RunLoop().RunUntilIdle(); |
| 178 EXPECT_EQ(SERVICE_WORKER_OK, status); |
| 179 |
| 180 // The worker should be now started. |
| 181 EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->status()); |
| 182 |
| 183 // Stop the worker, and then send the message immediately. |
| 184 ServiceWorkerStatusCode msg_status = SERVICE_WORKER_ERROR_FAILED; |
| 185 ServiceWorkerStatusCode stop_status = SERVICE_WORKER_ERROR_FAILED; |
| 186 version_->StopWorker(CreateReceiverOnCurrentThread(&stop_status)); |
| 187 version_->SendMessage(TestMsg_Message(), |
| 188 CreateReceiverOnCurrentThread(&msg_status)); |
| 189 base::RunLoop().RunUntilIdle(); |
| 190 EXPECT_EQ(SERVICE_WORKER_OK, stop_status); |
| 191 |
| 192 // SendMessage should return START_WORKER_FAILED error since it tried to |
| 193 // start a worker while it was stopping. |
| 194 EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, msg_status); |
| 195 } |
| 196 |
| 197 TEST_F(ServiceWorkerVersionTest, ReSendMessageAfterStop) { |
| 198 EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->status()); |
| 199 |
| 200 // Start the worker. |
| 201 ServiceWorkerStatusCode start_status = SERVICE_WORKER_ERROR_FAILED; |
| 202 version_->StartWorker(CreateReceiverOnCurrentThread(&start_status)); |
| 203 base::RunLoop().RunUntilIdle(); |
| 204 EXPECT_EQ(SERVICE_WORKER_OK, start_status); |
| 205 EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->status()); |
| 206 |
| 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); |
| 215 |
| 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); |
| 219 |
| 220 // Resend the message, which should succeed and restart the worker. |
| 221 version_->SendMessage(TestMsg_Message(), |
| 222 CreateReceiverOnCurrentThread(&msg_status)); |
| 223 base::RunLoop().RunUntilIdle(); |
| 224 EXPECT_EQ(SERVICE_WORKER_OK, msg_status); |
| 225 EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->status()); |
| 226 } |
| 227 |
| 228 TEST_F(ServiceWorkerVersionTest, SendMessageAndRegisterCallback) { |
| 229 // Send multiple messages and verify responses. |
| 230 ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_FAILED; |
| 231 ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_FAILED; |
| 232 int value1 = -1, value2 = -1; |
| 233 |
| 234 version_->SendMessageAndRegisterCallback( |
| 235 TestMsg_Request(111), |
| 236 base::Bind(&ReceiveResponse, &status1, &value1)); |
| 237 version_->SendMessageAndRegisterCallback( |
| 238 TestMsg_Request(333), |
| 239 base::Bind(&ReceiveResponse, &status2, &value2)); |
| 240 base::RunLoop().RunUntilIdle(); |
| 241 |
| 242 EXPECT_EQ(SERVICE_WORKER_OK, status1); |
| 243 EXPECT_EQ(SERVICE_WORKER_OK, status2); |
| 244 EXPECT_EQ(111 * 2, value1); |
| 245 EXPECT_EQ(333 * 2, value2); |
104 } | 246 } |
105 | 247 |
106 } // namespace content | 248 } // namespace content |
OLD | NEW |