Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / content / child / web_data_consumer_handle_impl_unittest.cc
blob53a0bc5cd1dde01351aee7f03e7ce4b1ff80d1d2
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 reader_ = handle_->ObtainReader(client_.get());
75 Result rv = kOk;
76 size_t readSize = 0;
78 while (true) {
79 char buffer[16];
80 rv = reader_->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 reader_.reset();
98 main_message_loop_->task_runner()->PostTask(FROM_HERE, on_done_);
101 private:
102 scoped_ptr<WebDataConsumerHandleImpl> handle_;
103 scoped_ptr<WebDataConsumerHandle::Reader> reader_;
104 scoped_ptr<WebDataConsumerHandle::Client> client_;
105 base::MessageLoop* main_message_loop_;
106 base::Closure on_done_;
107 std::string result_;
110 class TwoPhaseReadDataOperation : public ReadDataOperationBase {
111 public:
112 typedef WebDataConsumerHandle::Result Result;
113 TwoPhaseReadDataOperation(mojo::ScopedDataPipeConsumerHandle handle,
114 base::MessageLoop* main_message_loop,
115 const base::Closure& on_done)
116 : handle_(new WebDataConsumerHandleImpl(handle.Pass())),
117 main_message_loop_(main_message_loop), on_done_(on_done) {}
119 const std::string& result() const { return result_; }
121 void ReadMore() override {
122 ReadData();
125 void ReadData() {
126 if (!client_) {
127 client_.reset(new ClientImpl(this));
128 reader_ = handle_->ObtainReader(client_.get());
131 Result rv;
132 while (true) {
133 const void* buffer = nullptr;
134 size_t size;
135 rv = reader_->beginRead(&buffer, kNone, &size);
136 if (rv != kOk)
137 break;
138 // In order to verify endRead, we read at most one byte for each time.
139 size_t read_size = std::max(static_cast<size_t>(1), size);
140 result_.insert(result_.size(), static_cast<const char*>(buffer),
141 read_size);
142 rv = reader_->endRead(read_size);
143 if (rv != kOk) {
144 // Something is wrong.
145 result_ = "error";
146 main_message_loop_->task_runner()->PostTask(FROM_HERE, on_done_);
147 return;
151 if (rv == kShouldWait) {
152 // Wait a while...
153 return;
156 if (rv != kDone) {
157 // Something is wrong.
158 result_ = "error";
161 // The operation is done.
162 reader_.reset();
163 main_message_loop_->task_runner()->PostTask(FROM_HERE, on_done_);
166 private:
167 scoped_ptr<WebDataConsumerHandleImpl> handle_;
168 scoped_ptr<WebDataConsumerHandle::Reader> reader_;
169 scoped_ptr<WebDataConsumerHandle::Client> client_;
170 base::MessageLoop* main_message_loop_;
171 base::Closure on_done_;
172 std::string result_;
175 class WebDataConsumerHandleImplTest : public ::testing::Test {
176 public:
177 typedef WebDataConsumerHandle::Result Result;
179 void SetUp() override {
180 MojoCreateDataPipeOptions options;
181 options.struct_size = sizeof(MojoCreateDataPipeOptions);
182 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
183 options.element_num_bytes = 1;
184 options.capacity_num_bytes = 4;
186 MojoResult result = mojo::CreateDataPipe(&options, &producer_, &consumer_);
187 ASSERT_EQ(MOJO_RESULT_OK, result);
190 // This function can be blocked if the associated consumer doesn't consume
191 // the data.
192 std::string ProduceData(size_t total_size) {
193 int index = 0;
194 std::string expected;
195 for (size_t i = 0; i < total_size; ++i) {
196 expected += static_cast<char>(index + 'a');
197 index = (37 * index + 11) % 26;
200 const char* p = expected.data();
201 size_t remaining = total_size;
202 const MojoWriteDataFlags kNone = MOJO_WRITE_DATA_FLAG_NONE;
203 MojoResult rv;
204 while (remaining > 0) {
205 uint32_t size = remaining;
206 rv = mojo::WriteDataRaw(producer_.get(), p, &size, kNone);
207 if (rv == MOJO_RESULT_OK) {
208 remaining -= size;
209 p += size;
210 } else if (rv != MOJO_RESULT_SHOULD_WAIT) {
211 // Something is wrong.
212 EXPECT_TRUE(false) << "mojo::WriteDataRaw returns an invalid value.";
213 return "error on writing";
216 return expected;
219 base::MessageLoop message_loop_;
221 mojo::ScopedDataPipeProducerHandle producer_;
222 mojo::ScopedDataPipeConsumerHandle consumer_;
225 TEST_F(WebDataConsumerHandleImplTest, ReadData) {
226 base::RunLoop run_loop;
227 auto operation = make_scoped_ptr(new ReadDataOperation(
228 consumer_.Pass(),
229 &message_loop_,
230 run_loop.QuitClosure()));
232 base::Thread t("DataConsumerHandle test thread");
233 ASSERT_TRUE(t.Start());
235 t.task_runner()->PostTask(FROM_HERE,
236 base::Bind(&ReadDataOperation::ReadData,
237 base::Unretained(operation.get())));
239 std::string expected = ProduceData(24 * 1024);
240 producer_.reset();
242 run_loop.Run();
243 t.Stop();
245 EXPECT_EQ(expected, operation->result());
248 TEST_F(WebDataConsumerHandleImplTest, TwoPhaseReadData) {
249 base::RunLoop run_loop;
250 auto operation = make_scoped_ptr(new TwoPhaseReadDataOperation(
251 consumer_.Pass(),
252 &message_loop_,
253 run_loop.QuitClosure()));
255 base::Thread t("DataConsumerHandle test thread");
256 ASSERT_TRUE(t.Start());
258 t.task_runner()->PostTask(FROM_HERE,
259 base::Bind(&TwoPhaseReadDataOperation::ReadData,
260 base::Unretained(operation.get())));
262 std::string expected = ProduceData(24 * 1024);
263 producer_.reset();
265 run_loop.Run();
266 t.Stop();
268 EXPECT_EQ(expected, operation->result());
271 } // namespace
273 } // namespace content