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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: extensions/browser/api/socket/tcp_socket_unittest.cc
diff --git a/extensions/browser/api/socket/tcp_socket_unittest.cc b/extensions/browser/api/socket/tcp_socket_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..31a6c1fe3fea3a53a5ec18f1b7c79bc1cb6adf1a
--- /dev/null
+++ b/extensions/browser/api/socket/tcp_socket_unittest.cc
@@ -0,0 +1,150 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <algorithm>
+#include <queue>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "extensions/browser/api/socket/tcp_socket.h"
+#include "extensions/browser/api_unittest.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+
+class UnderlyingSource {
+ public:
+ UnderlyingSource() {}
+
+ int Read(net::IOBuffer* dest, int sz, const net::CompletionCallback& cb) {
+ CHECK(!response_queue_.empty());
+ CHECK(waiting_cb_.is_null());
+ const bool immediate = response_queue_.front().immediate_return;
+ std::string& front_text = response_queue_.front().text;
+ int amount_to_return = std::min<int>(sz, front_text.length());
+ memcpy(dest->data(), front_text.c_str(), amount_to_return);
+ // This may make the string empty. We use that as a consumption
+ // state-var.
+ front_text.erase(0, amount_to_return);
+
+ if (immediate) {
+ if (front_text.empty()) {
+ response_queue_.pop();
+ }
+ return amount_to_return;
+ } else {
+ waiting_cb_ = cb;
+ waiting_cb_arg_ = amount_to_return;
+ return net::ERR_IO_PENDING;
+ }
+ }
+
+ void QueueResponse(const std::string& data, bool immediate) {
+ response_queue_.push(response(data, immediate));
+ }
+
+ void SendResponse() {
+ int arg = waiting_cb_arg_;
+ net::CompletionCallback cb = waiting_cb_;
+ waiting_cb_.Reset();
+ waiting_cb_arg_ = 0;
+ if (response_queue_.front().text.empty()) {
+ response_queue_.pop();
+ }
+ cb.Run(arg);
+ }
+
+ size_t remaining_responses() { return response_queue_.size(); }
+
+ struct response {
+ std::string text;
+ const bool immediate_return;
+ response(const std::string& s, bool ret) : text(s), immediate_return(ret) {}
+ };
+
+ // The top of this queue is either a fresh, ready-to-use response, or it's
+ // mid-response, and waiting_cb_ is non-null.
+ std::queue<response> response_queue_;
+ // If the last caller to Read() had a non-immediate return, then this is
+ // the callback that's called when SendResponse() is invoked.
+ net::CompletionCallback waiting_cb_;
+ int waiting_cb_arg_;
+};
+
+class SocketPauseBufferUnitTest : public testing::Test {
+ public:
+ SocketPauseBufferUnitTest()
+ : complete_callback_(base::Bind(&SocketPauseBufferUnitTest::IOComplete,
+ base::Unretained(this))) {}
+ void SetUp() override {
+ testing::Test::SetUp();
+ last_size_ = 0;
+ source_.reset(new UnderlyingSource);
+ pause_buffer_.reset(new SocketPauseBuffer(
+ base::Bind(&UnderlyingSource::Read, base::Unretained(source_.get()))));
+ }
+
+ void IOComplete(int size) { last_size_ = size; }
+
+ protected:
+ SocketPauseBuffer* pause_buffer() { return pause_buffer_.get(); }
+
+ UnderlyingSource* source() { return source_.get(); }
+
+ net::CompletionCallback& complete_callback() { return complete_callback_; }
+
+ int last_size() { return last_size_; }
+ void reset_size() { last_size_ = 0; }
+
+ scoped_ptr<SocketPauseBuffer> pause_buffer_;
+ scoped_ptr<UnderlyingSource> source_;
+ int last_size_;
+ net::CompletionCallback complete_callback_;
+};
+
+TEST_F(SocketPauseBufferUnitTest, ReadNormally) {
+ source()->QueueResponse("Foo", true);
+ scoped_refptr<net::IOBuffer> iob(new net::IOBuffer(512));
+ int ret = pause_buffer()->Read(iob.get(), 3, complete_callback());
+
+ CHECK_EQ(ret, 3);
+ CHECK_EQ(last_size_, 0);
+ CHECK_EQ(source()->remaining_responses(), 0);
+ CHECK_EQ(memcmp(iob->data(), "Foo", 3), 0);
+ source()->QueueResponse("BarBaz", false);
+ ret = pause_buffer()->Read(iob.get(), 3, complete_callback());
+ CHECK_LT(ret, 0);
+ source()->SendResponse();
+ CHECK_EQ(source()->remaining_responses(), 1);
+ CHECK_EQ(last_size(), 3);
+ CHECK_EQ(memcmp(iob->data(), "Bar", 3), 0);
+}
+
+TEST_F(SocketPauseBufferUnitTest, PauseAndRead) {
+ source()->QueueResponse("FirstSecond", false);
+ scoped_refptr<net::IOBuffer> iob(new net::IOBuffer(512));
+ int read_count = pause_buffer()->Read(iob.get(), 5, complete_callback());
+ CHECK_LT(read_count, 0);
+ bool pause_ret = pause_buffer()->Pause();
+ CHECK_EQ(pause_ret, true);
+ // Verify that we got a ERR_ABORTED from the Read() upon Pause().
+ CHECK_EQ(last_size(), net::ERR_ABORTED);
+ reset_size();
+ source()->SendResponse();
+ // Now the PauseBuffer has data. 5 bytes.
+ read_count = pause_buffer()->Read(iob.get(), 10, complete_callback());
+ CHECK_EQ(read_count, 5); // that's all that was requested originally.
+ read_count = pause_buffer()->Read(iob.get(), 10, complete_callback());
+
+ // This isn't from the buffer, so it'll invoke the callback.
+ CHECK_LT(read_count, 0);
+ CHECK_EQ(last_size(), 0); // no callback invoked yet...
+ source()->SendResponse();
+ CHECK_EQ(last_size(), 6);
+}
+
+} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698