xref: /aosp_15_r20/external/libchrome/ipc/ipc_channel_reader_unittest.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright 2015 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
6*635a8641SAndroid Build Coastguard Worker 
7*635a8641SAndroid Build Coastguard Worker #include <stddef.h>
8*635a8641SAndroid Build Coastguard Worker #include <stdint.h>
9*635a8641SAndroid Build Coastguard Worker 
10*635a8641SAndroid Build Coastguard Worker #include <limits>
11*635a8641SAndroid Build Coastguard Worker #include <memory>
12*635a8641SAndroid Build Coastguard Worker #include <set>
13*635a8641SAndroid Build Coastguard Worker 
14*635a8641SAndroid Build Coastguard Worker #include "base/run_loop.h"
15*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_channel_reader.h"
16*635a8641SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
17*635a8641SAndroid Build Coastguard Worker 
18*635a8641SAndroid Build Coastguard Worker namespace IPC {
19*635a8641SAndroid Build Coastguard Worker namespace internal {
20*635a8641SAndroid Build Coastguard Worker 
21*635a8641SAndroid Build Coastguard Worker namespace {
22*635a8641SAndroid Build Coastguard Worker 
23*635a8641SAndroid Build Coastguard Worker class MockChannelReader : public ChannelReader {
24*635a8641SAndroid Build Coastguard Worker  public:
MockChannelReader()25*635a8641SAndroid Build Coastguard Worker   MockChannelReader()
26*635a8641SAndroid Build Coastguard Worker       : ChannelReader(nullptr), last_dispatched_message_(nullptr) {}
27*635a8641SAndroid Build Coastguard Worker 
ReadData(char * buffer,int buffer_len,int * bytes_read)28*635a8641SAndroid Build Coastguard Worker   ReadState ReadData(char* buffer, int buffer_len, int* bytes_read) override {
29*635a8641SAndroid Build Coastguard Worker     if (data_.empty())
30*635a8641SAndroid Build Coastguard Worker       return READ_PENDING;
31*635a8641SAndroid Build Coastguard Worker 
32*635a8641SAndroid Build Coastguard Worker     size_t read_len = std::min(static_cast<size_t>(buffer_len), data_.size());
33*635a8641SAndroid Build Coastguard Worker     memcpy(buffer, data_.data(), read_len);
34*635a8641SAndroid Build Coastguard Worker     *bytes_read = static_cast<int>(read_len);
35*635a8641SAndroid Build Coastguard Worker     data_.erase(0, read_len);
36*635a8641SAndroid Build Coastguard Worker     return READ_SUCCEEDED;
37*635a8641SAndroid Build Coastguard Worker   }
38*635a8641SAndroid Build Coastguard Worker 
ShouldDispatchInputMessage(Message * msg)39*635a8641SAndroid Build Coastguard Worker   bool ShouldDispatchInputMessage(Message* msg) override { return true; }
40*635a8641SAndroid Build Coastguard Worker 
GetAttachments(Message * msg)41*635a8641SAndroid Build Coastguard Worker   bool GetAttachments(Message* msg) override { return true; }
42*635a8641SAndroid Build Coastguard Worker 
DidEmptyInputBuffers()43*635a8641SAndroid Build Coastguard Worker   bool DidEmptyInputBuffers() override { return true; }
44*635a8641SAndroid Build Coastguard Worker 
HandleInternalMessage(const Message & msg)45*635a8641SAndroid Build Coastguard Worker   void HandleInternalMessage(const Message& msg) override {}
46*635a8641SAndroid Build Coastguard Worker 
DispatchMessage(Message * m)47*635a8641SAndroid Build Coastguard Worker   void DispatchMessage(Message* m) override { last_dispatched_message_ = m; }
48*635a8641SAndroid Build Coastguard Worker 
get_last_dispatched_message()49*635a8641SAndroid Build Coastguard Worker   Message* get_last_dispatched_message() { return last_dispatched_message_; }
50*635a8641SAndroid Build Coastguard Worker 
AppendData(const void * data,size_t size)51*635a8641SAndroid Build Coastguard Worker   void AppendData(const void* data, size_t size) {
52*635a8641SAndroid Build Coastguard Worker     data_.append(static_cast<const char*>(data), size);
53*635a8641SAndroid Build Coastguard Worker   }
54*635a8641SAndroid Build Coastguard Worker 
AppendMessageData(const Message & message)55*635a8641SAndroid Build Coastguard Worker   void AppendMessageData(const Message& message) {
56*635a8641SAndroid Build Coastguard Worker     AppendData(message.data(), message.size());
57*635a8641SAndroid Build Coastguard Worker   }
58*635a8641SAndroid Build Coastguard Worker 
59*635a8641SAndroid Build Coastguard Worker  private:
60*635a8641SAndroid Build Coastguard Worker   Message* last_dispatched_message_;
61*635a8641SAndroid Build Coastguard Worker   std::string data_;
62*635a8641SAndroid Build Coastguard Worker };
63*635a8641SAndroid Build Coastguard Worker 
64*635a8641SAndroid Build Coastguard Worker class ExposedMessage: public Message {
65*635a8641SAndroid Build Coastguard Worker  public:
66*635a8641SAndroid Build Coastguard Worker   using Message::Header;
67*635a8641SAndroid Build Coastguard Worker   using Message::header;
68*635a8641SAndroid Build Coastguard Worker };
69*635a8641SAndroid Build Coastguard Worker 
70*635a8641SAndroid Build Coastguard Worker // Payload that makes messages large
71*635a8641SAndroid Build Coastguard Worker const size_t LargePayloadSize = Channel::kMaximumReadBufferSize * 3 / 2;
72*635a8641SAndroid Build Coastguard Worker 
73*635a8641SAndroid Build Coastguard Worker }  // namespace
74*635a8641SAndroid Build Coastguard Worker 
75*635a8641SAndroid Build Coastguard Worker // We can determine message size from its header (and hence resize the buffer)
76*635a8641SAndroid Build Coastguard Worker // only when attachment broker is not used, see IPC::Message::FindNext().
77*635a8641SAndroid Build Coastguard Worker 
TEST(ChannelReaderTest,ResizeOverflowBuffer)78*635a8641SAndroid Build Coastguard Worker TEST(ChannelReaderTest, ResizeOverflowBuffer) {
79*635a8641SAndroid Build Coastguard Worker   MockChannelReader reader;
80*635a8641SAndroid Build Coastguard Worker 
81*635a8641SAndroid Build Coastguard Worker   ExposedMessage::Header header = {};
82*635a8641SAndroid Build Coastguard Worker 
83*635a8641SAndroid Build Coastguard Worker   header.payload_size = 128 * 1024;
84*635a8641SAndroid Build Coastguard Worker   EXPECT_LT(reader.input_overflow_buf_.capacity(), header.payload_size);
85*635a8641SAndroid Build Coastguard Worker   EXPECT_TRUE(reader.TranslateInputData(
86*635a8641SAndroid Build Coastguard Worker       reinterpret_cast<const char*>(&header), sizeof(header)));
87*635a8641SAndroid Build Coastguard Worker 
88*635a8641SAndroid Build Coastguard Worker   // Once message header is available we resize overflow buffer to
89*635a8641SAndroid Build Coastguard Worker   // fit the entire message.
90*635a8641SAndroid Build Coastguard Worker   EXPECT_GE(reader.input_overflow_buf_.capacity(), header.payload_size);
91*635a8641SAndroid Build Coastguard Worker }
92*635a8641SAndroid Build Coastguard Worker 
TEST(ChannelReaderTest,InvalidMessageSize)93*635a8641SAndroid Build Coastguard Worker TEST(ChannelReaderTest, InvalidMessageSize) {
94*635a8641SAndroid Build Coastguard Worker   MockChannelReader reader;
95*635a8641SAndroid Build Coastguard Worker 
96*635a8641SAndroid Build Coastguard Worker   ExposedMessage::Header header = {};
97*635a8641SAndroid Build Coastguard Worker 
98*635a8641SAndroid Build Coastguard Worker   size_t capacity_before = reader.input_overflow_buf_.capacity();
99*635a8641SAndroid Build Coastguard Worker 
100*635a8641SAndroid Build Coastguard Worker   // Message is slightly larger than maximum allowed size
101*635a8641SAndroid Build Coastguard Worker   header.payload_size = Channel::kMaximumMessageSize + 1;
102*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(reader.TranslateInputData(
103*635a8641SAndroid Build Coastguard Worker       reinterpret_cast<const char*>(&header), sizeof(header)));
104*635a8641SAndroid Build Coastguard Worker   EXPECT_LE(reader.input_overflow_buf_.capacity(), capacity_before);
105*635a8641SAndroid Build Coastguard Worker 
106*635a8641SAndroid Build Coastguard Worker   // Payload size is negative, overflow is detected by Pickle::PeekNext()
107*635a8641SAndroid Build Coastguard Worker   header.payload_size = static_cast<uint32_t>(-1);
108*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(reader.TranslateInputData(
109*635a8641SAndroid Build Coastguard Worker       reinterpret_cast<const char*>(&header), sizeof(header)));
110*635a8641SAndroid Build Coastguard Worker   EXPECT_LE(reader.input_overflow_buf_.capacity(), capacity_before);
111*635a8641SAndroid Build Coastguard Worker 
112*635a8641SAndroid Build Coastguard Worker   // Payload size is maximum int32_t value
113*635a8641SAndroid Build Coastguard Worker   header.payload_size = std::numeric_limits<int32_t>::max();
114*635a8641SAndroid Build Coastguard Worker   EXPECT_FALSE(reader.TranslateInputData(
115*635a8641SAndroid Build Coastguard Worker       reinterpret_cast<const char*>(&header), sizeof(header)));
116*635a8641SAndroid Build Coastguard Worker   EXPECT_LE(reader.input_overflow_buf_.capacity(), capacity_before);
117*635a8641SAndroid Build Coastguard Worker }
118*635a8641SAndroid Build Coastguard Worker 
TEST(ChannelReaderTest,TrimBuffer)119*635a8641SAndroid Build Coastguard Worker TEST(ChannelReaderTest, TrimBuffer) {
120*635a8641SAndroid Build Coastguard Worker   // ChannelReader uses std::string as a buffer, and calls reserve()
121*635a8641SAndroid Build Coastguard Worker   // to trim it to kMaximumReadBufferSize. However, an implementation
122*635a8641SAndroid Build Coastguard Worker   // is free to actually reserve a larger amount.
123*635a8641SAndroid Build Coastguard Worker   size_t trimmed_buffer_size;
124*635a8641SAndroid Build Coastguard Worker   {
125*635a8641SAndroid Build Coastguard Worker     std::string buf;
126*635a8641SAndroid Build Coastguard Worker     buf.reserve(Channel::kMaximumReadBufferSize);
127*635a8641SAndroid Build Coastguard Worker     trimmed_buffer_size = buf.capacity();
128*635a8641SAndroid Build Coastguard Worker   }
129*635a8641SAndroid Build Coastguard Worker 
130*635a8641SAndroid Build Coastguard Worker   // Buffer is trimmed after message is processed.
131*635a8641SAndroid Build Coastguard Worker   {
132*635a8641SAndroid Build Coastguard Worker     MockChannelReader reader;
133*635a8641SAndroid Build Coastguard Worker 
134*635a8641SAndroid Build Coastguard Worker     Message message;
135*635a8641SAndroid Build Coastguard Worker     message.WriteString(std::string(LargePayloadSize, 'X'));
136*635a8641SAndroid Build Coastguard Worker 
137*635a8641SAndroid Build Coastguard Worker     // Sanity check
138*635a8641SAndroid Build Coastguard Worker     EXPECT_TRUE(message.size() > trimmed_buffer_size);
139*635a8641SAndroid Build Coastguard Worker 
140*635a8641SAndroid Build Coastguard Worker     // Initially buffer is small
141*635a8641SAndroid Build Coastguard Worker     EXPECT_LE(reader.input_overflow_buf_.capacity(), trimmed_buffer_size);
142*635a8641SAndroid Build Coastguard Worker 
143*635a8641SAndroid Build Coastguard Worker     // Write and process large message
144*635a8641SAndroid Build Coastguard Worker     reader.AppendMessageData(message);
145*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
146*635a8641SAndroid Build Coastguard Worker               reader.ProcessIncomingMessages());
147*635a8641SAndroid Build Coastguard Worker 
148*635a8641SAndroid Build Coastguard Worker     // After processing large message buffer is trimmed
149*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(reader.input_overflow_buf_.capacity(), trimmed_buffer_size);
150*635a8641SAndroid Build Coastguard Worker   }
151*635a8641SAndroid Build Coastguard Worker 
152*635a8641SAndroid Build Coastguard Worker   // Buffer is trimmed only after entire message is processed.
153*635a8641SAndroid Build Coastguard Worker   {
154*635a8641SAndroid Build Coastguard Worker     MockChannelReader reader;
155*635a8641SAndroid Build Coastguard Worker 
156*635a8641SAndroid Build Coastguard Worker     ExposedMessage message;
157*635a8641SAndroid Build Coastguard Worker     message.WriteString(std::string(LargePayloadSize, 'X'));
158*635a8641SAndroid Build Coastguard Worker 
159*635a8641SAndroid Build Coastguard Worker     // Write and process message header
160*635a8641SAndroid Build Coastguard Worker     reader.AppendData(message.header(), sizeof(ExposedMessage::Header));
161*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
162*635a8641SAndroid Build Coastguard Worker               reader.ProcessIncomingMessages());
163*635a8641SAndroid Build Coastguard Worker 
164*635a8641SAndroid Build Coastguard Worker     // We determined message size for the message from its header, so
165*635a8641SAndroid Build Coastguard Worker     // we resized the buffer to fit.
166*635a8641SAndroid Build Coastguard Worker     EXPECT_GE(reader.input_overflow_buf_.capacity(), message.size());
167*635a8641SAndroid Build Coastguard Worker 
168*635a8641SAndroid Build Coastguard Worker     // Write and process payload
169*635a8641SAndroid Build Coastguard Worker     reader.AppendData(message.payload(), message.payload_size());
170*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
171*635a8641SAndroid Build Coastguard Worker               reader.ProcessIncomingMessages());
172*635a8641SAndroid Build Coastguard Worker 
173*635a8641SAndroid Build Coastguard Worker     // But once we process the message, we trim the buffer
174*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(reader.input_overflow_buf_.capacity(), trimmed_buffer_size);
175*635a8641SAndroid Build Coastguard Worker   }
176*635a8641SAndroid Build Coastguard Worker 
177*635a8641SAndroid Build Coastguard Worker   // Buffer is not trimmed if the next message is also large.
178*635a8641SAndroid Build Coastguard Worker   {
179*635a8641SAndroid Build Coastguard Worker     MockChannelReader reader;
180*635a8641SAndroid Build Coastguard Worker 
181*635a8641SAndroid Build Coastguard Worker     // Write large message
182*635a8641SAndroid Build Coastguard Worker     Message message1;
183*635a8641SAndroid Build Coastguard Worker     message1.WriteString(std::string(LargePayloadSize * 2, 'X'));
184*635a8641SAndroid Build Coastguard Worker     reader.AppendMessageData(message1);
185*635a8641SAndroid Build Coastguard Worker 
186*635a8641SAndroid Build Coastguard Worker     // Write header for the next large message
187*635a8641SAndroid Build Coastguard Worker     ExposedMessage message2;
188*635a8641SAndroid Build Coastguard Worker     message2.WriteString(std::string(LargePayloadSize, 'Y'));
189*635a8641SAndroid Build Coastguard Worker     reader.AppendData(message2.header(), sizeof(ExposedMessage::Header));
190*635a8641SAndroid Build Coastguard Worker 
191*635a8641SAndroid Build Coastguard Worker     // Process messages
192*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
193*635a8641SAndroid Build Coastguard Worker               reader.ProcessIncomingMessages());
194*635a8641SAndroid Build Coastguard Worker 
195*635a8641SAndroid Build Coastguard Worker     // We determined message size for the second (partial) message, so
196*635a8641SAndroid Build Coastguard Worker     // we resized the buffer to fit.
197*635a8641SAndroid Build Coastguard Worker     EXPECT_GE(reader.input_overflow_buf_.capacity(), message1.size());
198*635a8641SAndroid Build Coastguard Worker   }
199*635a8641SAndroid Build Coastguard Worker 
200*635a8641SAndroid Build Coastguard Worker   // Buffer resized appropriately if next message is larger than the first.
201*635a8641SAndroid Build Coastguard Worker   // (Similar to the test above except for the order of messages.)
202*635a8641SAndroid Build Coastguard Worker   {
203*635a8641SAndroid Build Coastguard Worker     MockChannelReader reader;
204*635a8641SAndroid Build Coastguard Worker 
205*635a8641SAndroid Build Coastguard Worker     // Write large message
206*635a8641SAndroid Build Coastguard Worker     Message message1;
207*635a8641SAndroid Build Coastguard Worker     message1.WriteString(std::string(LargePayloadSize, 'Y'));
208*635a8641SAndroid Build Coastguard Worker     reader.AppendMessageData(message1);
209*635a8641SAndroid Build Coastguard Worker 
210*635a8641SAndroid Build Coastguard Worker     // Write header for the next even larger message
211*635a8641SAndroid Build Coastguard Worker     ExposedMessage message2;
212*635a8641SAndroid Build Coastguard Worker     message2.WriteString(std::string(LargePayloadSize * 2, 'X'));
213*635a8641SAndroid Build Coastguard Worker     reader.AppendData(message2.header(), sizeof(ExposedMessage::Header));
214*635a8641SAndroid Build Coastguard Worker 
215*635a8641SAndroid Build Coastguard Worker     // Process messages
216*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
217*635a8641SAndroid Build Coastguard Worker               reader.ProcessIncomingMessages());
218*635a8641SAndroid Build Coastguard Worker 
219*635a8641SAndroid Build Coastguard Worker     // We determined message size for the second (partial) message, and
220*635a8641SAndroid Build Coastguard Worker     // resized the buffer to fit it.
221*635a8641SAndroid Build Coastguard Worker     EXPECT_GE(reader.input_overflow_buf_.capacity(), message2.size());
222*635a8641SAndroid Build Coastguard Worker   }
223*635a8641SAndroid Build Coastguard Worker 
224*635a8641SAndroid Build Coastguard Worker   // Buffer is not trimmed if we've just resized it to accommodate large
225*635a8641SAndroid Build Coastguard Worker   // incoming message.
226*635a8641SAndroid Build Coastguard Worker   {
227*635a8641SAndroid Build Coastguard Worker     MockChannelReader reader;
228*635a8641SAndroid Build Coastguard Worker 
229*635a8641SAndroid Build Coastguard Worker     // Write small message
230*635a8641SAndroid Build Coastguard Worker     Message message1;
231*635a8641SAndroid Build Coastguard Worker     message1.WriteString(std::string(11, 'X'));
232*635a8641SAndroid Build Coastguard Worker     reader.AppendMessageData(message1);
233*635a8641SAndroid Build Coastguard Worker 
234*635a8641SAndroid Build Coastguard Worker     // Write header for the next large message
235*635a8641SAndroid Build Coastguard Worker     ExposedMessage message2;
236*635a8641SAndroid Build Coastguard Worker     message2.WriteString(std::string(LargePayloadSize, 'Y'));
237*635a8641SAndroid Build Coastguard Worker     reader.AppendData(message2.header(), sizeof(ExposedMessage::Header));
238*635a8641SAndroid Build Coastguard Worker 
239*635a8641SAndroid Build Coastguard Worker     EXPECT_EQ(ChannelReader::DISPATCH_FINISHED,
240*635a8641SAndroid Build Coastguard Worker               reader.ProcessIncomingMessages());
241*635a8641SAndroid Build Coastguard Worker 
242*635a8641SAndroid Build Coastguard Worker     // We determined message size for the second (partial) message, so
243*635a8641SAndroid Build Coastguard Worker     // we resized the buffer to fit.
244*635a8641SAndroid Build Coastguard Worker     EXPECT_GE(reader.input_overflow_buf_.capacity(), message2.size());
245*635a8641SAndroid Build Coastguard Worker   }
246*635a8641SAndroid Build Coastguard Worker }
247*635a8641SAndroid Build Coastguard Worker 
248*635a8641SAndroid Build Coastguard Worker }  // namespace internal
249*635a8641SAndroid Build Coastguard Worker }  // namespace IPC
250