Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(123)

Side by Side Diff: content/child/web_data_consumer_handle_impl_unittest.cc

Issue 620303002: Implement WebDataConsumerHandle. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "content/child/web_data_consumer_handle_impl.h"
6
7 #include <algorithm>
8 #include <string>
9 #include "base/bind.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/synchronization/waitable_event.h"
12 #include "base/threading/thread.h"
13 #include "mojo/public/cpp/system/data_pipe.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace content {
17
18 namespace {
19
20 using blink::WebDataConsumerHandle;
21
22 class ReadDataOperationBase {
23 public:
24 virtual ~ReadDataOperationBase() {}
25 virtual void ReadMore() = 0;
26
27 static const WebDataConsumerHandle::Flags kNone =
28 WebDataConsumerHandle::FlagNone;
29 static const WebDataConsumerHandle::Result kOk = WebDataConsumerHandle::Ok;
30 static const WebDataConsumerHandle::Result kDone =
31 WebDataConsumerHandle::Done;
32 static const WebDataConsumerHandle::Result kShouldWait =
33 WebDataConsumerHandle::ShouldWait;
34 };
35
36 class ClientImpl final : public WebDataConsumerHandle::Client {
37 public:
38 explicit ClientImpl(ReadDataOperationBase* operation)
39 : operation_(operation) {}
40
41 virtual void didGetReadable() override {
42 base::MessageLoop::current()->PostTask(
43 FROM_HERE,
44 base::Bind(&ReadDataOperationBase::ReadMore,
45 base::Unretained(operation_)));
46 }
47
48 private:
49 ReadDataOperationBase* operation_;
50 };
51
52 class ReadDataOperation : public ReadDataOperationBase {
53 public:
54 typedef WebDataConsumerHandle::Result Result;
55 ReadDataOperation(mojo::ScopedDataPipeConsumerHandle handle,
56 base::MessageLoop* main_message_loop,
57 const base::Closure& stop)
58 : handle_(new WebDataConsumerHandleImpl(handle.Pass())),
59 main_message_loop_(main_message_loop), stop_(stop) {}
60
61 const std::string& result() const { return result_; }
62
63 virtual void ReadMore() override {
64 ReadData();
65 }
66
67 void ReadData() {
68 if (!client_) {
69 client_.reset(new ClientImpl(this));
70 handle_->registerClient(client_.get());
71 }
72
73 Result rv = kOk;
74 size_t readSize = 0;
75
76 while (rv == kOk) {
77 char buffer[16];
78 result_.insert(result_.size(), &buffer[0], readSize);
79 rv = handle_->read(&buffer, sizeof(buffer), kNone, &readSize);
80 }
81
82 if (rv == kShouldWait) {
83 // Wait a while...
84 return;
85 }
86
87 if (rv != kDone) {
88 // Something is wrong.
89 result_ = "error";
90 }
91
92 // The operation is done.
93 main_message_loop_->PostTask(FROM_HERE, stop_);
94 }
95
96 private:
97 scoped_ptr<WebDataConsumerHandle> handle_;
98 scoped_ptr<WebDataConsumerHandle::Client> client_;
99 base::MessageLoop* main_message_loop_;
100 base::Closure stop_;
101 std::string result_;
102 };
103
104
105 class TwoPhaseReadDataOperation : public ReadDataOperationBase {
106 public:
107 typedef WebDataConsumerHandle::Result Result;
108 TwoPhaseReadDataOperation(mojo::ScopedDataPipeConsumerHandle handle,
109 base::MessageLoop* main_message_loop,
110 const base::Closure& stop)
111 : handle_(new WebDataConsumerHandleImpl(handle.Pass())),
112 main_message_loop_(main_message_loop), stop_(stop) {}
113
114 const std::string& result() const { return result_; }
115
116 virtual void ReadMore() override {
117 ReadData();
118 }
119
120 void ReadData() {
121 if (!client_) {
122 client_.reset(new ClientImpl(this));
123 handle_->registerClient(client_.get());
124 }
125
126 Result rv;
127 while (true) {
128 const void* buffer = nullptr;
129 size_t size;
130 rv = handle_->beginRead(&buffer, kNone, &size);
131 if (rv != kOk)
132 break;
133 // In order to verify endRead, we read at most one byte for each time.
134 size_t read_size = std::max(static_cast<size_t>(1), size);
135 result_.insert(result_.size(), static_cast<const char*>(buffer),
136 read_size);
137 rv = handle_->endRead(read_size);
138 }
139
140 if (rv == kShouldWait) {
141 // Wait a while...
142 return;
143 }
144
145 if (rv != kDone) {
146 // Something is wrong.
147 result_ = "error";
148 }
149
150 // The operation is done.
151 main_message_loop_->PostTask(FROM_HERE, stop_);
152 }
153
154 private:
155 scoped_ptr<WebDataConsumerHandle> handle_;
156 scoped_ptr<WebDataConsumerHandle::Client> client_;
157 base::MessageLoop* main_message_loop_;
158 base::Closure stop_;
159 std::string result_;
160 };
161
162 class WebDataConsumerHandleImplTest : public ::testing::Test {
163 public:
164 typedef WebDataConsumerHandle::Result Result;
165
166 WebDataConsumerHandleImplTest(): done_(false) {}
167
168 virtual void SetUp() override {
169 MojoCreateDataPipeOptions options;
170 options.struct_size = sizeof(MojoCreateDataPipeOptions);
171 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
172 options.element_num_bytes = 1;
173 options.capacity_num_bytes = 4;
174
175 MojoResult result = mojo::CreateDataPipe(&options, &producer_, &consumer_);
176 ASSERT_EQ(MOJO_RESULT_OK, result);
177 }
178
179 void Loop() {
180 if (!done_) {
181 message_loop_.PostTask(FROM_HERE,
182 base::Bind(&WebDataConsumerHandleImplTest::Loop,
183 base::Unretained(this)));
184 }
185 }
186
187 void StopLoop() {
188 done_ = true;
189 }
190
191 // This function can be blocked if the associated consumer doesn't consume
192 // the data.
193 std::string ProduceData(size_t total_size) {
194 int index = 0;
195 std::string expected;
196 for (size_t i = 0; i < total_size; ++i) {
197 expected += static_cast<char>(index + 'a');
198 index = (37 * index + 11) % 26;
199 }
200
201 const char* p = expected.data();
202 size_t remaining = total_size;
203 const MojoWriteDataFlags kNone = MOJO_WRITE_DATA_FLAG_NONE;
204 MojoResult rv;
205 while (remaining > 0) {
206 uint32_t size = remaining;
207 rv = mojo::WriteDataRaw(producer_.get(), p, &size, kNone);
208 if (rv == MOJO_RESULT_OK) {
209 remaining -= size;
210 p += size;
211 } else if (rv != MOJO_RESULT_SHOULD_WAIT) {
212 // Something is wrong.
213 EXPECT_TRUE(false) << "mojo::WriteDataRaw returns an invalid value.";
214 return "error on writing";
215 }
216 }
217 return expected;
218 }
219
220 base::MessageLoop message_loop_;
221
222 mojo::ScopedDataPipeProducerHandle producer_;
223 mojo::ScopedDataPipeConsumerHandle consumer_;
224
225 bool done_;
226 };
227
228 TEST_F(WebDataConsumerHandleImplTest, ReadData) {
229 auto operation = make_scoped_ptr(new ReadDataOperation(
230 consumer_.Pass(),
231 &message_loop_,
232 base::Bind(&WebDataConsumerHandleImplTest::StopLoop,
233 base::Unretained(this))));
234
235 base::Thread t("DataConsumerHandle test thread");
236 ASSERT_TRUE(t.Start());
237
238 t.message_loop()->PostTask(
239 FROM_HERE,
240 base::Bind(&ReadDataOperation::ReadData,
241 base::Unretained(operation.get())));
242
243 std::string expected = ProduceData(24 * 1024);
244 producer_.reset();
245
246 Loop();
247 message_loop_.RunUntilIdle();
248 t.Stop();
249
250 EXPECT_EQ(expected, operation->result());
251 }
252
253 TEST_F(WebDataConsumerHandleImplTest, TwoPhaseReadData) {
254 auto operation = make_scoped_ptr(new TwoPhaseReadDataOperation(
255 consumer_.Pass(),
256 &message_loop_,
257 base::Bind(&WebDataConsumerHandleImplTest::StopLoop,
258 base::Unretained(this))));
259
260 base::Thread t("DataConsumerHandle test thread");
261 ASSERT_TRUE(t.Start());
262
263 t.message_loop()->PostTask(
264 FROM_HERE,
265 base::Bind(&TwoPhaseReadDataOperation::ReadData,
266 base::Unretained(operation.get())));
267
268 std::string expected = ProduceData(24 * 1024);
269 producer_.reset();
270
271 Loop();
272 message_loop_.RunUntilIdle();
273 t.Stop();
274
275 EXPECT_EQ(expected, operation->result());
276 }
277
278 } // namespace
279
280 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698