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

Side by Side Diff: extensions/browser/api/socket/tcp_socket_unittest.cc

Issue 494573002: A change for the setPause() api in chrome.sockets.tcp: Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Cosmetics and commentary. Created 5 years 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2015 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 <algorithm>
6 #include <queue>
7 #include <vector>
8
9 #include "base/memory/scoped_ptr.h"
10 #include "extensions/browser/api/socket/tcp_socket.h"
11 #include "extensions/browser/api_unittest.h"
12 #include "net/base/io_buffer.h"
13 #include "net/base/net_errors.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace extensions {
18
19 class UnderlyingSource {
20 public:
21 UnderlyingSource() {}
22
23 int Read(net::IOBuffer* dest, int sz, const net::CompletionCallback& cb) {
24 CHECK(!response_queue_.empty());
25 CHECK(waiting_cb_.is_null());
26 const bool immediate = response_queue_.front().immediate_return;
27 std::string& front_text = response_queue_.front().text;
28 int amount_to_return = std::min<int>(sz, front_text.length());
29 memcpy(dest->data(), front_text.c_str(), amount_to_return);
30 // This may make the string empty. We use that as a consumption
31 // state-var.
32 front_text.erase(0, amount_to_return);
33
34 if (immediate) {
35 if (front_text.empty()) {
36 response_queue_.pop();
37 }
38 return amount_to_return;
39 } else {
40 waiting_cb_ = cb;
41 waiting_cb_arg_ = amount_to_return;
42 return net::ERR_IO_PENDING;
43 }
44 }
45
46 void QueueResponse(const std::string& data, bool immediate) {
47 response_queue_.push(response(data, immediate));
48 }
49
50 void SendResponse() {
51 int arg = waiting_cb_arg_;
52 net::CompletionCallback cb = waiting_cb_;
53 waiting_cb_.Reset();
54 waiting_cb_arg_ = 0;
55 if (response_queue_.front().text.empty()) {
56 response_queue_.pop();
57 }
58 cb.Run(arg);
59 }
60
61 size_t remaining_responses() { return response_queue_.size(); }
62
63 struct response {
64 std::string text;
65 const bool immediate_return;
66 response(const std::string& s, bool ret) : text(s), immediate_return(ret) {}
67 };
68
69 // The top of this queue is either a fresh, ready-to-use response, or it's
70 // mid-response, and waiting_cb_ is non-null.
71 std::queue<response> response_queue_;
72 // If the last caller to Read() had a non-immediate return, then this is
73 // the callback that's called when SendResponse() is invoked.
74 net::CompletionCallback waiting_cb_;
75 int waiting_cb_arg_;
76 };
77
78 class SocketPauseBufferUnitTest : public testing::Test {
79 public:
80 SocketPauseBufferUnitTest()
81 : complete_callback_(base::Bind(&SocketPauseBufferUnitTest::IOComplete,
82 base::Unretained(this))) {}
83 void SetUp() override {
84 testing::Test::SetUp();
85 last_size_ = 0;
86 source_.reset(new UnderlyingSource);
87 pause_buffer_.reset(new SocketPauseBuffer(
88 base::Bind(&UnderlyingSource::Read, base::Unretained(source_.get()))));
89 }
90
91 void IOComplete(int size) { last_size_ = size; }
92
93 protected:
94 SocketPauseBuffer* pause_buffer() { return pause_buffer_.get(); }
95
96 UnderlyingSource* source() { return source_.get(); }
97
98 net::CompletionCallback& complete_callback() { return complete_callback_; }
99
100 int last_size() { return last_size_; }
101 void reset_size() { last_size_ = 0; }
102
103 scoped_ptr<SocketPauseBuffer> pause_buffer_;
104 scoped_ptr<UnderlyingSource> source_;
105 int last_size_;
106 net::CompletionCallback complete_callback_;
107 };
108
109 TEST_F(SocketPauseBufferUnitTest, ReadNormally) {
110 source()->QueueResponse("Foo", true);
111 scoped_refptr<net::IOBuffer> iob(new net::IOBuffer(512));
112 int ret = pause_buffer()->Read(iob.get(), 3, complete_callback());
113
114 CHECK_EQ(ret, 3);
115 CHECK_EQ(last_size_, 0);
116 CHECK_EQ(source()->remaining_responses(), 0);
117 CHECK_EQ(memcmp(iob->data(), "Foo", 3), 0);
118 source()->QueueResponse("BarBaz", false);
119 ret = pause_buffer()->Read(iob.get(), 3, complete_callback());
120 CHECK_LT(ret, 0);
121 source()->SendResponse();
122 CHECK_EQ(source()->remaining_responses(), 1);
123 CHECK_EQ(last_size(), 3);
124 CHECK_EQ(memcmp(iob->data(), "Bar", 3), 0);
125 }
126
127 TEST_F(SocketPauseBufferUnitTest, PauseAndRead) {
128 source()->QueueResponse("FirstSecond", false);
129 scoped_refptr<net::IOBuffer> iob(new net::IOBuffer(512));
130 int read_count = pause_buffer()->Read(iob.get(), 5, complete_callback());
131 CHECK_LT(read_count, 0);
132 bool pause_ret = pause_buffer()->Pause();
133 CHECK_EQ(pause_ret, true);
134 // Verify that we got a ERR_ABORTED from the Read() upon Pause().
135 CHECK_EQ(last_size(), net::ERR_ABORTED);
136 reset_size();
137 source()->SendResponse();
138 // Now the PauseBuffer has data. 5 bytes.
139 read_count = pause_buffer()->Read(iob.get(), 10, complete_callback());
140 CHECK_EQ(read_count, 5); // that's all that was requested originally.
141 read_count = pause_buffer()->Read(iob.get(), 10, complete_callback());
142
143 // This isn't from the buffer, so it'll invoke the callback.
144 CHECK_LT(read_count, 0);
145 CHECK_EQ(last_size(), 0); // no callback invoked yet...
146 source()->SendResponse();
147 CHECK_EQ(last_size(), 6);
148 }
149
150 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698