OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "google_apis/gcm/base/socket_stream.h" | 5 #include "google_apis/gcm/base/socket_stream.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
10 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
12 #include "base/strings/string_piece.h" | 12 #include "base/strings/string_piece.h" |
13 #include "net/socket/socket_test_util.h" | 13 #include "net/socket/socket_test_util.h" |
14 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
15 | 15 |
16 namespace gcm { | 16 namespace gcm { |
17 namespace { | 17 namespace { |
18 | 18 |
19 typedef std::vector<net::MockRead> ReadList; | 19 typedef std::vector<net::MockRead> ReadList; |
20 typedef std::vector<net::MockWrite> WriteList; | 20 typedef std::vector<net::MockWrite> WriteList; |
21 | 21 |
22 const char kReadData[] = "read_data"; | 22 const char kReadData[] = "read_data"; |
23 const uint64 kReadDataSize = arraysize(kReadData) - 1; | 23 const int kReadDataSize = arraysize(kReadData) - 1; |
24 const char kReadData2[] = "read_alternate_data"; | 24 const char kReadData2[] = "read_alternate_data"; |
25 const uint64 kReadData2Size = arraysize(kReadData2) - 1; | 25 const int kReadData2Size = arraysize(kReadData2) - 1; |
26 const char kWriteData[] = "write_data"; | 26 const char kWriteData[] = "write_data"; |
27 const uint64 kWriteDataSize = arraysize(kWriteData) - 1; | 27 const int kWriteDataSize = arraysize(kWriteData) - 1; |
28 | 28 |
29 class GCMSocketStreamTest : public testing::Test { | 29 class GCMSocketStreamTest : public testing::Test { |
30 public: | 30 public: |
31 GCMSocketStreamTest(); | 31 GCMSocketStreamTest(); |
32 virtual ~GCMSocketStreamTest(); | 32 virtual ~GCMSocketStreamTest(); |
33 | 33 |
34 // Build a socket with the expected reads and writes. | 34 // Build a socket with the expected reads and writes. |
35 void BuildSocket(const ReadList& read_list, const WriteList& write_list); | 35 void BuildSocket(const ReadList& read_list, const WriteList& write_list); |
36 | 36 |
37 // Pump the message loop until idle. | 37 // Pump the message loop until idle. |
38 void PumpLoop(); | 38 void PumpLoop(); |
39 | 39 |
40 // Simulates a google::protobuf::io::CodedInputStream read. | 40 // Simulates a google::protobuf::io::CodedInputStream read. |
41 base::StringPiece DoInputStreamRead(uint64 bytes); | 41 base::StringPiece DoInputStreamRead(int bytes); |
42 // Simulates a google::protobuf::io::CodedOutputStream write. | 42 // Simulates a google::protobuf::io::CodedOutputStream write. |
43 uint64 DoOutputStreamWrite(const base::StringPiece& write_src); | 43 int DoOutputStreamWrite(const base::StringPiece& write_src); |
44 | 44 |
45 // Synchronous Refresh wrapper. | 45 // Synchronous Refresh wrapper. |
46 void WaitForData(size_t msg_size); | 46 void WaitForData(int msg_size); |
47 | 47 |
48 base::MessageLoop* message_loop() { return &message_loop_; }; | 48 base::MessageLoop* message_loop() { return &message_loop_; }; |
49 net::DelayedSocketData* data_provider() { return data_provider_.get(); } | 49 net::DelayedSocketData* data_provider() { return data_provider_.get(); } |
50 SocketInputStream* input_stream() { return socket_input_stream_.get(); } | 50 SocketInputStream* input_stream() { return socket_input_stream_.get(); } |
51 SocketOutputStream* output_stream() { return socket_output_stream_.get(); } | 51 SocketOutputStream* output_stream() { return socket_output_stream_.get(); } |
52 net::StreamSocket* socket() { return socket_.get(); } | 52 net::StreamSocket* socket() { return socket_.get(); } |
53 | 53 |
54 private: | 54 private: |
55 void OpenConnection(); | 55 void OpenConnection(); |
56 void ResetInputStream(); | 56 void ResetInputStream(); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 OpenConnection(); | 94 OpenConnection(); |
95 ResetInputStream(); | 95 ResetInputStream(); |
96 ResetOutputStream(); | 96 ResetOutputStream(); |
97 } | 97 } |
98 | 98 |
99 void GCMSocketStreamTest::PumpLoop() { | 99 void GCMSocketStreamTest::PumpLoop() { |
100 base::RunLoop run_loop; | 100 base::RunLoop run_loop; |
101 run_loop.RunUntilIdle(); | 101 run_loop.RunUntilIdle(); |
102 } | 102 } |
103 | 103 |
104 base::StringPiece GCMSocketStreamTest::DoInputStreamRead(uint64 bytes) { | 104 base::StringPiece GCMSocketStreamTest::DoInputStreamRead(int bytes) { |
105 uint64 total_bytes_read = 0; | 105 int total_bytes_read = 0; |
106 const void* initial_buffer = NULL; | 106 const void* initial_buffer = NULL; |
107 const void* buffer = NULL; | 107 const void* buffer = NULL; |
108 int size = 0; | 108 int size = 0; |
109 | 109 |
110 do { | 110 do { |
111 DCHECK(socket_input_stream_->GetState() == SocketInputStream::EMPTY || | 111 DCHECK(socket_input_stream_->GetState() == SocketInputStream::EMPTY || |
112 socket_input_stream_->GetState() == SocketInputStream::READY); | 112 socket_input_stream_->GetState() == SocketInputStream::READY); |
113 if (!socket_input_stream_->Next(&buffer, &size)) | 113 if (!socket_input_stream_->Next(&buffer, &size)) |
114 break; | 114 break; |
115 total_bytes_read += size; | 115 total_bytes_read += size; |
116 if (initial_buffer) { // Verify the buffer doesn't skip data. | 116 if (initial_buffer) { // Verify the buffer doesn't skip data. |
117 EXPECT_EQ(static_cast<const uint8*>(initial_buffer) + total_bytes_read, | 117 EXPECT_EQ(static_cast<const uint8*>(initial_buffer) + total_bytes_read, |
118 static_cast<const uint8*>(buffer) + size); | 118 static_cast<const uint8*>(buffer) + size); |
119 } else { | 119 } else { |
120 initial_buffer = buffer; | 120 initial_buffer = buffer; |
121 } | 121 } |
122 } while (total_bytes_read < bytes); | 122 } while (total_bytes_read < bytes); |
123 | 123 |
124 if (total_bytes_read > bytes) { | 124 if (total_bytes_read > bytes) { |
125 socket_input_stream_->BackUp(total_bytes_read - bytes); | 125 socket_input_stream_->BackUp(total_bytes_read - bytes); |
126 total_bytes_read = bytes; | 126 total_bytes_read = bytes; |
127 } | 127 } |
128 | 128 |
129 return base::StringPiece(static_cast<const char*>(initial_buffer), | 129 return base::StringPiece(static_cast<const char*>(initial_buffer), |
130 total_bytes_read); | 130 total_bytes_read); |
131 } | 131 } |
132 | 132 |
133 uint64 GCMSocketStreamTest::DoOutputStreamWrite( | 133 int GCMSocketStreamTest::DoOutputStreamWrite( |
134 const base::StringPiece& write_src) { | 134 const base::StringPiece& write_src) { |
135 DCHECK_EQ(socket_output_stream_->GetState(), SocketOutputStream::EMPTY); | 135 DCHECK_EQ(socket_output_stream_->GetState(), SocketOutputStream::EMPTY); |
136 uint64 total_bytes_written = 0; | 136 int total_bytes_written = 0; |
137 void* buffer = NULL; | 137 void* buffer = NULL; |
138 int size = 0; | 138 int size = 0; |
139 size_t bytes = write_src.size(); | 139 int bytes = write_src.size(); |
140 | 140 |
141 do { | 141 do { |
142 if (!socket_output_stream_->Next(&buffer, &size)) | 142 if (!socket_output_stream_->Next(&buffer, &size)) |
143 break; | 143 break; |
144 uint64 bytes_to_write = (static_cast<uint64>(size) < bytes ? size : bytes); | 144 int bytes_to_write = (size < bytes ? size : bytes); |
145 memcpy(buffer, | 145 memcpy(buffer, |
146 write_src.data() + total_bytes_written, | 146 write_src.data() + total_bytes_written, |
147 bytes_to_write); | 147 bytes_to_write); |
148 if (bytes_to_write < static_cast<uint64>(size)) | 148 if (bytes_to_write < size) |
149 socket_output_stream_->BackUp(size - bytes_to_write); | 149 socket_output_stream_->BackUp(size - bytes_to_write); |
150 total_bytes_written += bytes_to_write; | 150 total_bytes_written += bytes_to_write; |
151 } while (total_bytes_written < bytes); | 151 } while (total_bytes_written < bytes); |
152 | 152 |
153 base::RunLoop run_loop; | 153 base::RunLoop run_loop; |
154 if (socket_output_stream_->Flush(run_loop.QuitClosure()) == | 154 if (socket_output_stream_->Flush(run_loop.QuitClosure()) == |
155 net::ERR_IO_PENDING) { | 155 net::ERR_IO_PENDING) { |
156 run_loop.Run(); | 156 run_loop.Run(); |
157 } | 157 } |
158 | 158 |
159 return total_bytes_written; | 159 return total_bytes_written; |
160 } | 160 } |
161 | 161 |
162 void GCMSocketStreamTest::WaitForData(size_t msg_size) { | 162 void GCMSocketStreamTest::WaitForData(int msg_size) { |
163 while (input_stream()->UnreadByteCount() < msg_size) { | 163 while (input_stream()->UnreadByteCount() < msg_size) { |
164 base::RunLoop run_loop; | 164 base::RunLoop run_loop; |
165 if (input_stream()->Refresh(run_loop.QuitClosure(), | 165 if (input_stream()->Refresh(run_loop.QuitClosure(), |
166 msg_size - input_stream()->UnreadByteCount()) == | 166 msg_size - input_stream()->UnreadByteCount()) == |
167 net::ERR_IO_PENDING) { | 167 net::ERR_IO_PENDING) { |
168 run_loop.Run(); | 168 run_loop.Run(); |
169 } | 169 } |
170 if (input_stream()->GetState() == SocketInputStream::CLOSED) | 170 if (input_stream()->GetState() == SocketInputStream::CLOSED) |
171 return; | 171 return; |
172 } | 172 } |
(...skipping 27 matching lines...) Expand all Loading... |
200 kReadDataSize)), | 200 kReadDataSize)), |
201 WriteList()); | 201 WriteList()); |
202 | 202 |
203 WaitForData(kReadDataSize); | 203 WaitForData(kReadDataSize); |
204 ASSERT_EQ(std::string(kReadData, kReadDataSize), | 204 ASSERT_EQ(std::string(kReadData, kReadDataSize), |
205 DoInputStreamRead(kReadDataSize)); | 205 DoInputStreamRead(kReadDataSize)); |
206 } | 206 } |
207 | 207 |
208 // A read that comes in two parts. | 208 // A read that comes in two parts. |
209 TEST_F(GCMSocketStreamTest, ReadPartialDataSync) { | 209 TEST_F(GCMSocketStreamTest, ReadPartialDataSync) { |
210 size_t first_read_len = kReadDataSize / 2; | 210 int first_read_len = kReadDataSize / 2; |
211 size_t second_read_len = kReadDataSize - first_read_len; | 211 int second_read_len = kReadDataSize - first_read_len; |
212 ReadList read_list; | 212 ReadList read_list; |
213 read_list.push_back( | 213 read_list.push_back( |
214 net::MockRead(net::SYNCHRONOUS, | 214 net::MockRead(net::SYNCHRONOUS, |
215 kReadData, | 215 kReadData, |
216 first_read_len)); | 216 first_read_len)); |
217 read_list.push_back( | 217 read_list.push_back( |
218 net::MockRead(net::SYNCHRONOUS, | 218 net::MockRead(net::SYNCHRONOUS, |
219 &kReadData[first_read_len], | 219 &kReadData[first_read_len], |
220 second_read_len)); | 220 second_read_len)); |
221 BuildSocket(read_list, WriteList()); | 221 BuildSocket(read_list, WriteList()); |
222 | 222 |
223 WaitForData(kReadDataSize); | 223 WaitForData(kReadDataSize); |
224 ASSERT_EQ(std::string(kReadData, kReadDataSize), | 224 ASSERT_EQ(std::string(kReadData, kReadDataSize), |
225 DoInputStreamRead(kReadDataSize)); | 225 DoInputStreamRead(kReadDataSize)); |
226 } | 226 } |
227 | 227 |
228 // A read where no data is available at first (IO_PENDING will be returned). | 228 // A read where no data is available at first (IO_PENDING will be returned). |
229 TEST_F(GCMSocketStreamTest, ReadAsync) { | 229 TEST_F(GCMSocketStreamTest, ReadAsync) { |
230 size_t first_read_len = kReadDataSize / 2; | 230 int first_read_len = kReadDataSize / 2; |
231 size_t second_read_len = kReadDataSize - first_read_len; | 231 int second_read_len = kReadDataSize - first_read_len; |
232 ReadList read_list; | 232 ReadList read_list; |
233 read_list.push_back( | 233 read_list.push_back( |
234 net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)); | 234 net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)); |
235 read_list.push_back( | 235 read_list.push_back( |
236 net::MockRead(net::ASYNC, kReadData, first_read_len)); | 236 net::MockRead(net::ASYNC, kReadData, first_read_len)); |
237 read_list.push_back( | 237 read_list.push_back( |
238 net::MockRead(net::ASYNC, &kReadData[first_read_len], second_read_len)); | 238 net::MockRead(net::ASYNC, &kReadData[first_read_len], second_read_len)); |
239 BuildSocket(read_list, WriteList()); | 239 BuildSocket(read_list, WriteList()); |
240 | 240 |
241 base::MessageLoop::current()->PostTask( | 241 base::MessageLoop::current()->PostTask( |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 TEST_F(GCMSocketStreamTest, WriteDisconnected) { | 397 TEST_F(GCMSocketStreamTest, WriteDisconnected) { |
398 BuildSocket(ReadList(), WriteList()); | 398 BuildSocket(ReadList(), WriteList()); |
399 socket()->Disconnect(); | 399 socket()->Disconnect(); |
400 DoOutputStreamWrite(base::StringPiece(kWriteData, kWriteDataSize)); | 400 DoOutputStreamWrite(base::StringPiece(kWriteData, kWriteDataSize)); |
401 ASSERT_EQ(SocketOutputStream::CLOSED, output_stream()->GetState()); | 401 ASSERT_EQ(SocketOutputStream::CLOSED, output_stream()->GetState()); |
402 ASSERT_EQ(net::ERR_CONNECTION_CLOSED, output_stream()->last_error()); | 402 ASSERT_EQ(net::ERR_CONNECTION_CLOSED, output_stream()->last_error()); |
403 } | 403 } |
404 | 404 |
405 } // namespace | 405 } // namespace |
406 } // namespace gcm | 406 } // namespace gcm |
OLD | NEW |