Fix link in German terms of service.
[chromium-blink-merge.git] / content / child / web_data_consumer_handle_impl_unittest.cc
blobfd250ec2fe7a38e49ce30427832b69fd81a83f7f
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 "content/child/web_data_consumer_handle_impl.h"
7 #include <algorithm>
8 #include <string>
9 #include "base/bind.h"
10 #include "base/location.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/run_loop.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/synchronization/waitable_event.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "base/threading/thread.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h"
20 namespace content {
22 namespace {
24 using blink::WebDataConsumerHandle;
26 class ReadDataOperationBase {
27 public:
28 virtual ~ReadDataOperationBase() {}
29 virtual void ReadMore() = 0;
31 static const WebDataConsumerHandle::Flags kNone =
32 WebDataConsumerHandle::FlagNone;
33 static const WebDataConsumerHandle::Result kOk = WebDataConsumerHandle::Ok;
34 static const WebDataConsumerHandle::Result kDone =
35 WebDataConsumerHandle::Done;
36 static const WebDataConsumerHandle::Result kShouldWait =
37 WebDataConsumerHandle::ShouldWait;
40 class ClientImpl final : public WebDataConsumerHandle::Client {
41 public:
42 explicit ClientImpl(ReadDataOperationBase* operation)
43 : operation_(operation) {}
45 void didGetReadable() override {
46 base::ThreadTaskRunnerHandle::Get()->PostTask(
47 FROM_HERE, base::Bind(&ReadDataOperationBase::ReadMore,
48 base::Unretained(operation_)));
51 private:
52 ReadDataOperationBase* operation_;
55 class ReadDataOperation : public ReadDataOperationBase {
56 public:
57 typedef WebDataConsumerHandle::Result Result;
58 ReadDataOperation(mojo::ScopedDataPipeConsumerHandle handle,
59 base::MessageLoop* main_message_loop,
60 const base::Closure& on_done)
61 : handle_(new WebDataConsumerHandleImpl(handle.Pass())),
62 main_message_loop_(main_message_loop),
63 on_done_(on_done) {}
65 const std::string& result() const { return result_; }
67 void ReadMore() override { ReadData(); }
69 void ReadData() {
70 if (!client_) {
71 client_.reset(new ClientImpl(this));
72 handle_->registerClient(client_.get());
75 Result rv = kOk;
76 size_t readSize = 0;
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);
86 if (rv == kShouldWait) {
87 // Wait a while...
88 return;
91 if (rv != kDone) {
92 // Something is wrong.
93 result_ = "error";
96 // The operation is done.
97 main_message_loop_->task_runner()->PostTask(FROM_HERE, on_done_);
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_;
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) {}
117 const std::string& result() const { return result_; }
119 void ReadMore() override {
120 ReadData();
123 void ReadData() {
124 if (!client_) {
125 client_.reset(new ClientImpl(this));
126 handle_->registerClient(client_.get());
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_->task_runner()->PostTask(FROM_HERE, on_done_);
145 return;
149 if (rv == kShouldWait) {
150 // Wait a while...
151 return;
154 if (rv != kDone) {
155 // Something is wrong.
156 result_ = "error";
159 // The operation is done.
160 main_message_loop_->task_runner()->PostTask(FROM_HERE, on_done_);
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_;
171 class WebDataConsumerHandleImplTest : public ::testing::Test {
172 public:
173 typedef WebDataConsumerHandle::Result Result;
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;
182 MojoResult result = mojo::CreateDataPipe(&options, &producer_, &consumer_);
183 ASSERT_EQ(MOJO_RESULT_OK, result);
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;
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";
212 return expected;
215 base::MessageLoop message_loop_;
217 mojo::ScopedDataPipeProducerHandle producer_;
218 mojo::ScopedDataPipeConsumerHandle consumer_;
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()));
228 base::Thread t("DataConsumerHandle test thread");
229 ASSERT_TRUE(t.Start());
231 t.task_runner()->PostTask(FROM_HERE,
232 base::Bind(&ReadDataOperation::ReadData,
233 base::Unretained(operation.get())));
235 std::string expected = ProduceData(24 * 1024);
236 producer_.reset();
238 run_loop.Run();
239 t.Stop();
241 EXPECT_EQ(expected, operation->result());
244 TEST_F(WebDataConsumerHandleImplTest, TwoPhaseReadData) {
245 base::RunLoop run_loop;
246 auto operation = make_scoped_ptr(new TwoPhaseReadDataOperation(
247 consumer_.Pass(),
248 &message_loop_,
249 run_loop.QuitClosure()));
251 base::Thread t("DataConsumerHandle test thread");
252 ASSERT_TRUE(t.Start());
254 t.task_runner()->PostTask(FROM_HERE,
255 base::Bind(&TwoPhaseReadDataOperation::ReadData,
256 base::Unretained(operation.get())));
258 std::string expected = ProduceData(24 * 1024);
259 producer_.reset();
261 run_loop.Run();
262 t.Stop();
264 EXPECT_EQ(expected, operation->result());
267 } // namespace
269 } // namespace content