Home | History | Annotate | Download | only in protocol
      1 // Copyright (c) 2012 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 "remoting/protocol/buffered_socket_writer.h"
      6 
      7 #include <stdlib.h>
      8 
      9 #include "base/bind.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "net/base/io_buffer.h"
     12 #include "net/base/net_errors.h"
     13 #include "remoting/protocol/fake_session.h"
     14 #include "testing/gmock/include/gmock/gmock.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 
     17 namespace remoting {
     18 namespace protocol {
     19 
     20 namespace {
     21 const int kTestBufferSize = 10 * 1024; // 10k;
     22 const size_t kWriteChunkSize = 1024U;
     23 }  // namespace
     24 
     25 class BufferedSocketWriterTest : public testing::Test {
     26  public:
     27   BufferedSocketWriterTest()
     28       : write_error_(0) {
     29   }
     30 
     31   void OnDone() {
     32     base::MessageLoop::current()->PostTask(FROM_HERE,
     33                                            base::MessageLoop::QuitClosure());
     34   }
     35 
     36   void DestroyWriterAndQuit() {
     37     written_data_ = socket_->written_data();
     38     writer_.reset();
     39     socket_.reset();
     40     base::MessageLoop::current()->PostTask(FROM_HERE,
     41                                            base::MessageLoop::QuitClosure());
     42   }
     43 
     44   void Unexpected() {
     45     EXPECT_TRUE(false);
     46   }
     47 
     48  protected:
     49   virtual void SetUp() OVERRIDE {
     50     socket_.reset(new FakeSocket());
     51     writer_.reset(new BufferedSocketWriter());
     52     writer_->Init(socket_.get(), base::Bind(
     53         &BufferedSocketWriterTest::OnWriteFailed, base::Unretained(this)));
     54     test_buffer_ = new net::IOBufferWithSize(kTestBufferSize);
     55     test_buffer_2_ = new net::IOBufferWithSize(kTestBufferSize);
     56     for (int i = 0; i< kTestBufferSize; ++i) {
     57       test_buffer_->data()[i] = rand() % 256;
     58       test_buffer_2_->data()[i] = rand() % 256;
     59     }
     60   }
     61 
     62   void OnWriteFailed(int error) {
     63     write_error_ = error;
     64   }
     65 
     66   void TestWrite() {
     67     writer_->Write(test_buffer_, base::Bind(&BufferedSocketWriterTest::OnDone,
     68                                             base::Unretained(this)));
     69     writer_->Write(test_buffer_2_, base::Bind(&BufferedSocketWriterTest::OnDone,
     70                                               base::Unretained(this)));
     71     message_loop_.Run();
     72     ASSERT_EQ(static_cast<size_t>(test_buffer_->size() +
     73                                   test_buffer_2_->size()),
     74               socket_->written_data().size());
     75     EXPECT_EQ(0, memcmp(test_buffer_->data(), socket_->written_data().data(),
     76                         test_buffer_->size()));
     77     EXPECT_EQ(0, memcmp(test_buffer_2_->data(),
     78                         socket_->written_data().data() + test_buffer_->size(),
     79                         test_buffer_2_->size()));
     80   }
     81 
     82   void TestAppendInCallback() {
     83     writer_->Write(test_buffer_, base::Bind(
     84         base::IgnoreResult(&BufferedSocketWriterBase::Write),
     85         base::Unretained(writer_.get()), test_buffer_2_,
     86         base::Bind(&BufferedSocketWriterTest::OnDone,
     87                   base::Unretained(this))));
     88     message_loop_.Run();
     89     ASSERT_EQ(static_cast<size_t>(test_buffer_->size() +
     90                                   test_buffer_2_->size()),
     91               socket_->written_data().size());
     92     EXPECT_EQ(0, memcmp(test_buffer_->data(), socket_->written_data().data(),
     93                         test_buffer_->size()));
     94     EXPECT_EQ(0, memcmp(test_buffer_2_->data(),
     95                         socket_->written_data().data() + test_buffer_->size(),
     96                         test_buffer_2_->size()));
     97   }
     98 
     99   base::MessageLoop message_loop_;
    100   scoped_ptr<FakeSocket> socket_;
    101   scoped_ptr<BufferedSocketWriter> writer_;
    102   scoped_refptr<net::IOBufferWithSize> test_buffer_;
    103   scoped_refptr<net::IOBufferWithSize> test_buffer_2_;
    104   std::string written_data_;
    105   int write_error_;
    106 };
    107 
    108 // Test synchronous write.
    109 TEST_F(BufferedSocketWriterTest, WriteFull) {
    110   TestWrite();
    111 }
    112 
    113 // Test synchronous write in 1k chunks.
    114 TEST_F(BufferedSocketWriterTest, WriteChunks) {
    115   socket_->set_write_limit(kWriteChunkSize);
    116   TestWrite();
    117 }
    118 
    119 // Test asynchronous write.
    120 TEST_F(BufferedSocketWriterTest, WriteAsync) {
    121   socket_->set_async_write(true);
    122   socket_->set_write_limit(kWriteChunkSize);
    123   TestWrite();
    124 }
    125 
    126 // Make sure we can call Write() from the done callback.
    127 TEST_F(BufferedSocketWriterTest, AppendInCallbackSync) {
    128   TestAppendInCallback();
    129 }
    130 
    131 // Make sure we can call Write() from the done callback.
    132 TEST_F(BufferedSocketWriterTest, AppendInCallbackAsync) {
    133   socket_->set_async_write(true);
    134   socket_->set_write_limit(kWriteChunkSize);
    135   TestAppendInCallback();
    136 }
    137 
    138 // Test that the writer can be destroyed from callback.
    139 TEST_F(BufferedSocketWriterTest, DestroyFromCallback) {
    140   socket_->set_async_write(true);
    141   writer_->Write(test_buffer_, base::Bind(
    142       &BufferedSocketWriterTest::DestroyWriterAndQuit,
    143       base::Unretained(this)));
    144   writer_->Write(test_buffer_2_, base::Bind(
    145       &BufferedSocketWriterTest::Unexpected,
    146       base::Unretained(this)));
    147   socket_->set_async_write(false);
    148   message_loop_.Run();
    149   ASSERT_GE(written_data_.size(),
    150             static_cast<size_t>(test_buffer_->size()));
    151   EXPECT_EQ(0, memcmp(test_buffer_->data(), written_data_.data(),
    152                       test_buffer_->size()));
    153 }
    154 
    155 // Verify that it stops writing after the first error.
    156 TEST_F(BufferedSocketWriterTest, TestWriteErrorSync) {
    157   socket_->set_write_limit(kWriteChunkSize);
    158   writer_->Write(test_buffer_, base::Closure());
    159   socket_->set_async_write(true);
    160   writer_->Write(test_buffer_2_,
    161                  base::Bind(&BufferedSocketWriterTest::Unexpected,
    162                             base::Unretained(this)));
    163   socket_->set_next_write_error(net::ERR_FAILED);
    164   socket_->set_async_write(false);
    165   message_loop_.RunUntilIdle();
    166   EXPECT_EQ(net::ERR_FAILED, write_error_);
    167   EXPECT_EQ(static_cast<size_t>(test_buffer_->size()),
    168             socket_->written_data().size());
    169 }
    170 
    171 // Verify that it stops writing after the first error.
    172 TEST_F(BufferedSocketWriterTest, TestWriteErrorAsync) {
    173   socket_->set_write_limit(kWriteChunkSize);
    174   writer_->Write(test_buffer_, base::Closure());
    175   socket_->set_async_write(true);
    176   writer_->Write(test_buffer_2_,
    177                  base::Bind(&BufferedSocketWriterTest::Unexpected,
    178                             base::Unretained(this)));
    179   socket_->set_next_write_error(net::ERR_FAILED);
    180   message_loop_.RunUntilIdle();
    181   EXPECT_EQ(net::ERR_FAILED, write_error_);
    182   EXPECT_EQ(static_cast<size_t>(test_buffer_->size()),
    183             socket_->written_data().size());
    184 }
    185 
    186 }  // namespace protocol
    187 }  // namespace remoting
    188 
    189