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

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

Powered by Google App Engine
This is Rietveld 408576698