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