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

Side by Side Diff: ipc/ipc_channel_reader_unittest.cc

Issue 1377483003: Trim IPC ChannelReader's buffer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@reserve-buffer
Patch Set: Fix USE_ATTACHMENT_BROKER && defined(OS_MACOSX) && !defined(OS_IOS) case Created 5 years, 1 month 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
« no previous file with comments | « ipc/ipc_channel_reader.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 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 "build/build_config.h" 5 #include "build/build_config.h"
6 6
7 #include <limits> 7 #include <limits>
8 #include <set> 8 #include <set>
9 9
10 #include "ipc/attachment_broker.h" 10 #include "ipc/attachment_broker.h"
11 #include "ipc/brokerable_attachment.h" 11 #include "ipc/brokerable_attachment.h"
12 #include "ipc/ipc_channel_reader.h" 12 #include "ipc/ipc_channel_reader.h"
13 #include "ipc/placeholder_brokerable_attachment.h" 13 #include "ipc/placeholder_brokerable_attachment.h"
14 #include "testing/gtest/include/gtest/gtest.h" 14 #include "testing/gtest/include/gtest/gtest.h"
15 15
16 // Whether IPC::Message::FindNext() can determine message size for
17 // partial messages. The condition is from FindNext() implementation.
18 #if USE_ATTACHMENT_BROKER && defined(OS_MACOSX) && !defined(OS_IOS)
19 #define MESSAGE_FINDNEXT_PARTIAL 0
20 #else
21 #define MESSAGE_FINDNEXT_PARTIAL 1
22 #endif
23
16 namespace IPC { 24 namespace IPC {
17 namespace internal { 25 namespace internal {
18 26
19 namespace { 27 namespace {
20 28
21 #if USE_ATTACHMENT_BROKER 29 #if USE_ATTACHMENT_BROKER
22 30
23 class MockAttachment : public BrokerableAttachment { 31 class MockAttachment : public BrokerableAttachment {
24 public: 32 public:
25 MockAttachment() {} 33 MockAttachment() {}
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 }; 65 };
58 66
59 #endif // USE_ATTACHMENT_BROKER 67 #endif // USE_ATTACHMENT_BROKER
60 68
61 class MockChannelReader : public ChannelReader { 69 class MockChannelReader : public ChannelReader {
62 public: 70 public:
63 MockChannelReader() 71 MockChannelReader()
64 : ChannelReader(nullptr), last_dispatched_message_(nullptr) {} 72 : ChannelReader(nullptr), last_dispatched_message_(nullptr) {}
65 73
66 ReadState ReadData(char* buffer, int buffer_len, int* bytes_read) override { 74 ReadState ReadData(char* buffer, int buffer_len, int* bytes_read) override {
67 return READ_FAILED; 75 if (data_.empty())
76 return READ_PENDING;
77
78 size_t read_len = std::min(static_cast<size_t>(buffer_len), data_.size());
79 memcpy(buffer, data_.data(), read_len);
80 *bytes_read = static_cast<int>(read_len);
81 data_.erase(0, read_len);
82 return READ_SUCCEEDED;
68 } 83 }
69 84
70 bool ShouldDispatchInputMessage(Message* msg) override { return true; } 85 bool ShouldDispatchInputMessage(Message* msg) override { return true; }
71 86
72 bool GetNonBrokeredAttachments(Message* msg) override { return true; } 87 bool GetNonBrokeredAttachments(Message* msg) override { return true; }
73 88
74 bool DidEmptyInputBuffers() override { return true; } 89 bool DidEmptyInputBuffers() override { return true; }
75 90
76 void HandleInternalMessage(const Message& msg) override {} 91 void HandleInternalMessage(const Message& msg) override {}
77 92
78 void DispatchMessage(Message* m) override { last_dispatched_message_ = m; } 93 void DispatchMessage(Message* m) override { last_dispatched_message_ = m; }
79 94
80 base::ProcessId GetSenderPID() override { return base::kNullProcessId; } 95 base::ProcessId GetSenderPID() override { return base::kNullProcessId; }
81 96
82 bool IsAttachmentBrokerEndpoint() override { return false; } 97 bool IsAttachmentBrokerEndpoint() override { return false; }
83 98
84 AttachmentBroker* GetAttachmentBroker() override { return broker_; } 99 AttachmentBroker* GetAttachmentBroker() override { return broker_; }
85 100
86 // This instance takes ownership of |m|. 101 // This instance takes ownership of |m|.
87 void AddMessageForDispatch(Message* m) { 102 void AddMessageForDispatch(Message* m) {
88 get_queued_messages()->push_back(m); 103 get_queued_messages()->push_back(m);
89 } 104 }
90 105
91 Message* get_last_dispatched_message() { return last_dispatched_message_; } 106 Message* get_last_dispatched_message() { return last_dispatched_message_; }
92 107
93 void set_broker(AttachmentBroker* broker) { broker_ = broker; } 108 void set_broker(AttachmentBroker* broker) { broker_ = broker; }
94 109
110 void AppendData(const void* data, size_t size) {
111 data_.append(static_cast<const char*>(data), size);
112 }
113
114 void AppendMessageData(const Message& message) {
115 AppendData(message.data(), message.size());
116 }
117
95 private: 118 private:
96 Message* last_dispatched_message_; 119 Message* last_dispatched_message_;
97 AttachmentBroker* broker_; 120 AttachmentBroker* broker_;
121 std::string data_;
98 }; 122 };
99 123
100 class ExposedMessage: public Message { 124 class ExposedMessage: public Message {
101 public: 125 public:
102 using Message::Header; 126 using Message::Header;
103 using Message::header; 127 using Message::header;
104 }; 128 };
105 129
130 // Payload that makes messages large
131 const size_t LargePayloadSize = Channel::kMaximumReadBufferSize * 3 / 2;
132
106 } // namespace 133 } // namespace
107 134
108 #if USE_ATTACHMENT_BROKER 135 #if USE_ATTACHMENT_BROKER
109 136
110 TEST(ChannelReaderTest, AttachmentAlreadyBrokered) { 137 TEST(ChannelReaderTest, AttachmentAlreadyBrokered) {
111 MockAttachmentBroker broker; 138 MockAttachmentBroker broker;
112 MockChannelReader reader; 139 MockChannelReader reader;
113 reader.set_broker(&broker); 140 reader.set_broker(&broker);
114 scoped_refptr<MockAttachment> attachment(new MockAttachment); 141 scoped_refptr<MockAttachment> attachment(new MockAttachment);
115 broker.AddAttachment(attachment); 142 broker.AddAttachment(attachment);
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 212
186 // Payload size is maximum int32 value 213 // Payload size is maximum int32 value
187 header.payload_size = std::numeric_limits<int32_t>::max(); 214 header.payload_size = std::numeric_limits<int32_t>::max();
188 EXPECT_FALSE(reader.TranslateInputData( 215 EXPECT_FALSE(reader.TranslateInputData(
189 reinterpret_cast<const char*>(&header), sizeof(header))); 216 reinterpret_cast<const char*>(&header), sizeof(header)));
190 EXPECT_LE(reader.input_overflow_buf_.capacity(), capacity_before); 217 EXPECT_LE(reader.input_overflow_buf_.capacity(), capacity_before);
191 } 218 }
192 219
193 #endif // !USE_ATTACHMENT_BROKER 220 #endif // !USE_ATTACHMENT_BROKER
194 221
222 TEST(ChannelReaderTest, TrimBuffer) {
223 // ChannelReader uses std::string as a buffer, and calls reserve()
224 // to trim it to kMaximumReadBufferSize. However, an implementation
225 // is free to actually reserve a larger amount.
226 size_t trimmed_buffer_size;
227 {
228 std::string buf;
229 buf.reserve(Channel::kMaximumReadBufferSize);
230 trimmed_buffer_size = buf.capacity();
231 }
232
233 // Buffer is trimmed after message is processed.
234 {
235 MockChannelReader reader;
236
237 Message message;
238 message.WriteString(std::string(LargePayloadSize, 'X'));
239
240 // Sanity check
241 EXPECT_TRUE(message.size() > trimmed_buffer_size);
242
243 // Initially buffer is small
244 EXPECT_LE(reader.input_overflow_buf_.capacity(), trimmed_buffer_size);
245
246 // Write and process large message
247 reader.AppendMessageData(message);
248 EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
249 reader.ProcessIncomingMessages());
250
251 // After processing large message buffer is trimmed
252 EXPECT_EQ(reader.input_overflow_buf_.capacity(), trimmed_buffer_size);
253 }
254
255 // Buffer is trimmed only after entire message is processed.
256 {
257 MockChannelReader reader;
258
259 ExposedMessage message;
260 message.WriteString(std::string(LargePayloadSize, 'X'));
261
262 // Write and process message header
263 reader.AppendData(message.header(), sizeof(ExposedMessage::Header));
264 EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
265 reader.ProcessIncomingMessages());
266
267 #if MESSAGE_FINDNEXT_PARTIAL
268 // We determined message size for the message from its header, so
269 // we resized the buffer to fit.
270 EXPECT_GE(reader.input_overflow_buf_.capacity(), message.size());
271 #else
272 // We couldn't determine message size, so we didn't resize the buffer.
273 #endif
274
275 // Write and process payload
276 reader.AppendData(message.payload(), message.payload_size());
277 EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
278 reader.ProcessIncomingMessages());
279
280 // But once we process the message, we trim the buffer
281 EXPECT_EQ(reader.input_overflow_buf_.capacity(), trimmed_buffer_size);
282 }
283
284 // Buffer is not trimmed if the next message is also large.
285 {
286 MockChannelReader reader;
287
288 // Write large message
289 Message message1;
290 message1.WriteString(std::string(LargePayloadSize * 2, 'X'));
291 reader.AppendMessageData(message1);
292
293 // Write header for the next large message
294 ExposedMessage message2;
295 message2.WriteString(std::string(LargePayloadSize, 'Y'));
296 reader.AppendData(message2.header(), sizeof(ExposedMessage::Header));
297
298 // Process messages
299 EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
300 reader.ProcessIncomingMessages());
301
302 #if MESSAGE_FINDNEXT_PARTIAL
303 // We determined message size for the second (partial) message, so
304 // we resized the buffer to fit.
305 EXPECT_GE(reader.input_overflow_buf_.capacity(), message1.size());
306 #else
307 // We couldn't determine message size for the second (partial) message,
308 // so we trimmed the buffer.
309 EXPECT_EQ(reader.input_overflow_buf_.capacity(), trimmed_buffer_size);
310 #endif
311 }
312
313 // Buffer resized appropriately if next message is larger than the first.
314 // (Similar to the test above except for the order of messages.)
315 {
316 MockChannelReader reader;
317
318 // Write large message
319 Message message1;
320 message1.WriteString(std::string(LargePayloadSize, 'Y'));
321 reader.AppendMessageData(message1);
322
323 // Write header for the next even larger message
324 ExposedMessage message2;
325 message2.WriteString(std::string(LargePayloadSize * 2, 'X'));
326 reader.AppendData(message2.header(), sizeof(ExposedMessage::Header));
327
328 // Process messages
329 EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
330 reader.ProcessIncomingMessages());
331
332 #if MESSAGE_FINDNEXT_PARTIAL
333 // We determined message size for the second (partial) message, and
334 // resized the buffer to fit it.
335 EXPECT_GE(reader.input_overflow_buf_.capacity(), message2.size());
336 #else
337 // We couldn't determine message size for the second (partial) message,
338 // so we trimmed the buffer.
339 EXPECT_EQ(reader.input_overflow_buf_.capacity(), trimmed_buffer_size);
340 #endif
341 }
342
343 // Buffer is not trimmed if we've just resized it to accommodate large
344 // incoming message.
345 {
346 MockChannelReader reader;
347
348 // Write small message
349 Message message1;
350 message1.WriteString(std::string(11, 'X'));
351 reader.AppendMessageData(message1);
352
353 // Write header for the next large message
354 ExposedMessage message2;
355 message2.WriteString(std::string(LargePayloadSize, 'Y'));
356 reader.AppendData(message2.header(), sizeof(ExposedMessage::Header));
357
358 EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
359 reader.ProcessIncomingMessages());
360
361 #if MESSAGE_FINDNEXT_PARTIAL
362 // We determined message size for the second (partial) message, so
363 // we resized the buffer to fit.
364 EXPECT_GE(reader.input_overflow_buf_.capacity(), message2.size());
365 #else
366 // We couldn't determine size for the second (partial) message, and
367 // first message was small, so we did nothing.
368 #endif
369 }
370 }
371
195 } // namespace internal 372 } // namespace internal
196 } // namespace IPC 373 } // namespace IPC
OLDNEW
« no previous file with comments | « ipc/ipc_channel_reader.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698