Update broken references to image assets
[chromium-blink-merge.git] / extensions / browser / mojo / stash_backend_unittest.cc
blobae142085413b71eb9965427f537080a9cde9300f
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.
5 #include "base/bind.h"
6 #include "base/message_loop/message_loop.h"
7 #include "base/run_loop.h"
8 #include "extensions/browser/mojo/stash_backend.h"
9 #include "mojo/application/public/interfaces/service_provider.mojom.h"
10 #include "testing/gtest/include/gtest/gtest.h"
12 namespace extensions {
13 namespace {
15 // Create a data pipe, write some data to the producer handle and return the
16 // consumer handle.
17 mojo::ScopedHandle CreateReadableHandle() {
18 mojo::ScopedDataPipeConsumerHandle consumer_handle;
19 mojo::ScopedDataPipeProducerHandle producer_handle;
20 MojoCreateDataPipeOptions options = {
21 sizeof(options), MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, 1, 1,
23 MojoResult result =
24 mojo::CreateDataPipe(&options, &producer_handle, &consumer_handle);
25 EXPECT_EQ(MOJO_RESULT_OK, result);
26 uint32_t num_bytes = 1;
27 result = mojo::WriteDataRaw(producer_handle.get(), "a", &num_bytes,
28 MOJO_WRITE_DATA_FLAG_NONE);
29 EXPECT_EQ(MOJO_RESULT_OK, result);
30 EXPECT_EQ(1u, num_bytes);
31 return mojo::ScopedHandle::From(consumer_handle.Pass());
34 } // namespace
36 class StashServiceTest : public testing::Test, public mojo::ErrorHandler {
37 public:
38 enum Event {
39 EVENT_NONE,
40 EVENT_STASH_RETRIEVED,
41 EVENT_HANDLE_READY,
44 StashServiceTest() {}
46 void SetUp() override {
47 expecting_error_ = false;
48 expected_event_ = EVENT_NONE;
49 stash_backend_.reset(new StashBackend(base::Bind(
50 &StashServiceTest::OnHandleReadyToRead, base::Unretained(this))));
51 stash_backend_->BindToRequest(mojo::GetProxy(&stash_service_));
52 stash_service_.set_error_handler(this);
53 handles_ready_ = 0;
56 void OnConnectionError() override { FAIL() << "Unexpected connection error"; }
58 mojo::Array<StashedObjectPtr> RetrieveStash() {
59 mojo::Array<StashedObjectPtr> stash;
60 stash_service_->RetrieveStash(base::Bind(
61 &StashServiceTest::StashRetrieved, base::Unretained(this), &stash));
62 WaitForEvent(EVENT_STASH_RETRIEVED);
63 return stash.Pass();
66 void StashRetrieved(mojo::Array<StashedObjectPtr>* output,
67 mojo::Array<StashedObjectPtr> stash) {
68 *output = stash.Pass();
69 EventReceived(EVENT_STASH_RETRIEVED);
72 void WaitForEvent(Event event) {
73 expected_event_ = event;
74 base::RunLoop run_loop;
75 stop_run_loop_ = run_loop.QuitClosure();
76 run_loop.Run();
79 void EventReceived(Event event) {
80 if (event == expected_event_ && !stop_run_loop_.is_null())
81 stop_run_loop_.Run();
84 void OnHandleReadyToRead() {
85 handles_ready_++;
86 EventReceived(EVENT_HANDLE_READY);
89 protected:
90 base::MessageLoop message_loop_;
91 base::Closure stop_run_loop_;
92 scoped_ptr<StashBackend> stash_backend_;
93 Event expected_event_;
94 bool expecting_error_;
95 mojo::InterfacePtr<StashService> stash_service_;
96 int handles_ready_;
98 private:
99 DISALLOW_COPY_AND_ASSIGN(StashServiceTest);
102 // Test that adding stashed objects in multiple calls can all be retrieved by a
103 // Retrieve call.
104 TEST_F(StashServiceTest, AddTwiceAndRetrieve) {
105 mojo::Array<StashedObjectPtr> stashed_objects;
106 StashedObjectPtr stashed_object(StashedObject::New());
107 stashed_object->id = "test type";
108 stashed_object->data.push_back(1);
109 stashed_object->stashed_handles = mojo::Array<mojo::ScopedHandle>(0);
110 stashed_objects.push_back(stashed_object.Pass());
111 stash_service_->AddToStash(stashed_objects.Pass());
112 stashed_object = StashedObject::New();
113 stashed_object->id = "test type2";
114 stashed_object->data.push_back(2);
115 stashed_object->data.push_back(3);
116 stashed_object->stashed_handles = mojo::Array<mojo::ScopedHandle>(0);
117 stashed_objects.push_back(stashed_object.Pass());
118 stash_service_->AddToStash(stashed_objects.Pass());
119 stashed_objects = RetrieveStash();
120 ASSERT_EQ(2u, stashed_objects.size());
121 EXPECT_EQ("test type", stashed_objects[0]->id);
122 EXPECT_EQ(0u, stashed_objects[0]->stashed_handles.size());
123 EXPECT_EQ(1u, stashed_objects[0]->data.size());
124 EXPECT_EQ(1, stashed_objects[0]->data[0]);
125 EXPECT_EQ("test type2", stashed_objects[1]->id);
126 EXPECT_EQ(0u, stashed_objects[1]->stashed_handles.size());
127 EXPECT_EQ(2u, stashed_objects[1]->data.size());
128 EXPECT_EQ(2, stashed_objects[1]->data[0]);
129 EXPECT_EQ(3, stashed_objects[1]->data[1]);
132 // Test that handles survive a round-trip through the stash.
133 TEST_F(StashServiceTest, StashAndRetrieveHandles) {
134 mojo::Array<StashedObjectPtr> stashed_objects;
135 StashedObjectPtr stashed_object(StashedObject::New());
136 stashed_object->id = "test type";
137 stashed_object->data.push_back(1);
139 mojo::ScopedDataPipeConsumerHandle consumer;
140 mojo::ScopedDataPipeProducerHandle producer;
141 MojoCreateDataPipeOptions options = {
142 sizeof(options), MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, 1, 1,
144 mojo::CreateDataPipe(&options, &producer, &consumer);
145 uint32_t num_bytes = 1;
146 MojoResult result = mojo::WriteDataRaw(
147 producer.get(), "1", &num_bytes, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
148 ASSERT_EQ(MOJO_RESULT_OK, result);
149 ASSERT_EQ(1u, num_bytes);
151 stashed_object->stashed_handles.push_back(
152 mojo::ScopedHandle::From(producer.Pass()));
153 stashed_object->stashed_handles.push_back(
154 mojo::ScopedHandle::From(consumer.Pass()));
155 stashed_objects.push_back(stashed_object.Pass());
156 stash_service_->AddToStash(stashed_objects.Pass());
157 stashed_objects = RetrieveStash();
158 ASSERT_EQ(1u, stashed_objects.size());
159 EXPECT_EQ("test type", stashed_objects[0]->id);
160 ASSERT_EQ(2u, stashed_objects[0]->stashed_handles.size());
162 consumer = mojo::ScopedDataPipeConsumerHandle::From(
163 stashed_objects[0]->stashed_handles[1].Pass());
164 result = mojo::Wait(
165 consumer.get(), MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE,
166 nullptr);
167 ASSERT_EQ(MOJO_RESULT_OK, result);
168 char data = '\0';
169 result = mojo::ReadDataRaw(
170 consumer.get(), &data, &num_bytes, MOJO_READ_DATA_FLAG_ALL_OR_NONE);
171 ASSERT_EQ(MOJO_RESULT_OK, result);
172 ASSERT_EQ(1u, num_bytes);
173 EXPECT_EQ('1', data);
176 TEST_F(StashServiceTest, RetrieveWithoutStashing) {
177 mojo::Array<StashedObjectPtr> stashed_objects = RetrieveStash();
178 ASSERT_TRUE(!stashed_objects.is_null());
179 EXPECT_EQ(0u, stashed_objects.size());
182 TEST_F(StashServiceTest, NotifyOnReadableHandle) {
183 mojo::Array<StashedObjectPtr> stash_entries;
184 StashedObjectPtr stashed_object(StashedObject::New());
185 stashed_object->id = "test type";
186 stashed_object->data.push_back(0);
187 stashed_object->monitor_handles = true;
188 mojo::ServiceProviderPtr service_provider;
190 // Stash the ServiceProvider request. When we make a call on
191 // |service_provider|, the stashed handle will become readable.
192 stashed_object->stashed_handles.push_back(mojo::ScopedHandle::From(
193 mojo::GetProxy(&service_provider).PassMessagePipe()));
195 stash_entries.push_back(stashed_object.Pass());
196 stash_service_->AddToStash(stash_entries.Pass());
198 mojo::MessagePipe pipe;
199 service_provider->ConnectToService("", pipe.handle0.Pass());
201 WaitForEvent(EVENT_HANDLE_READY);
202 EXPECT_EQ(1, handles_ready_);
205 TEST_F(StashServiceTest, NotifyOnReadableDataPipeHandle) {
206 mojo::Array<StashedObjectPtr> stash_entries;
207 StashedObjectPtr stashed_object(StashedObject::New());
208 stashed_object->id = "test type";
209 stashed_object->monitor_handles = true;
211 MojoCreateDataPipeOptions options = {
212 sizeof(options), MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, 1, 1,
214 mojo::ScopedDataPipeConsumerHandle consumer_handle;
215 mojo::ScopedDataPipeProducerHandle producer_handle;
216 uint32_t num_bytes = 1;
217 MojoResult result =
218 mojo::CreateDataPipe(&options, &producer_handle, &consumer_handle);
219 ASSERT_EQ(MOJO_RESULT_OK, result);
220 result = mojo::WriteDataRaw(producer_handle.get(), "a", &num_bytes,
221 MOJO_WRITE_DATA_FLAG_NONE);
222 ASSERT_EQ(MOJO_RESULT_OK, result);
223 ASSERT_EQ(1u, num_bytes);
224 stashed_object->stashed_handles.push_back(
225 mojo::ScopedHandle::From(producer_handle.Pass()));
226 stashed_object->stashed_handles.push_back(
227 mojo::ScopedHandle::From(consumer_handle.Pass()));
228 stashed_object->data.push_back(1);
230 stash_entries.push_back(stashed_object.Pass());
231 stash_service_->AddToStash(stash_entries.Pass());
232 WaitForEvent(EVENT_HANDLE_READY);
233 EXPECT_EQ(1, handles_ready_);
236 TEST_F(StashServiceTest, NotifyOncePerStashOnReadableHandles) {
237 mojo::Array<StashedObjectPtr> stash_entries;
238 StashedObjectPtr stashed_object(StashedObject::New());
239 stashed_object->id = "test type";
240 stashed_object->data.push_back(1);
241 stashed_object->monitor_handles = true;
242 stashed_object->stashed_handles.push_back(CreateReadableHandle());
243 stashed_object->stashed_handles.push_back(CreateReadableHandle());
244 stash_entries.push_back(stashed_object.Pass());
245 stashed_object = StashedObject::New();
246 stashed_object->id = "another test type";
247 stashed_object->data.push_back(2);
248 stashed_object->monitor_handles = true;
249 stashed_object->stashed_handles.push_back(CreateReadableHandle());
250 stashed_object->stashed_handles.push_back(CreateReadableHandle());
251 stash_entries.push_back(stashed_object.Pass());
252 stash_service_->AddToStash(stash_entries.Pass());
253 WaitForEvent(EVENT_HANDLE_READY);
254 EXPECT_EQ(1, handles_ready_);
256 stashed_object = StashedObject::New();
257 stashed_object->id = "yet another test type";
258 stashed_object->data.push_back(3);
259 stashed_object->monitor_handles = true;
260 stashed_object->stashed_handles.push_back(CreateReadableHandle());
261 stashed_object->stashed_handles.push_back(CreateReadableHandle());
262 stash_entries.push_back(stashed_object.Pass());
263 stash_service_->AddToStash(stash_entries.Pass());
265 stash_service_->AddToStash(RetrieveStash());
266 WaitForEvent(EVENT_HANDLE_READY);
267 EXPECT_EQ(2, handles_ready_);
270 // Test that a stash service discards stashed objects when the backend no longer
271 // exists.
272 TEST_F(StashServiceTest, ServiceWithDeletedBackend) {
273 stash_backend_.reset();
274 stash_service_.set_error_handler(this);
276 mojo::Array<StashedObjectPtr> stashed_objects;
277 StashedObjectPtr stashed_object(StashedObject::New());
278 stashed_object->id = "test type";
279 stashed_object->data.push_back(1);
280 mojo::MessagePipe message_pipe;
281 stashed_object->stashed_handles.push_back(
282 mojo::ScopedHandle::From(message_pipe.handle0.Pass()));
283 stashed_objects.push_back(stashed_object.Pass());
284 stash_service_->AddToStash(stashed_objects.Pass());
285 stashed_objects = RetrieveStash();
286 ASSERT_EQ(0u, stashed_objects.size());
287 // Check that the stashed handle has been closed.
288 MojoResult result =
289 mojo::Wait(message_pipe.handle1.get(),
290 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_READABLE,
291 MOJO_DEADLINE_INDEFINITE, nullptr);
292 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
295 } // namespace extensions