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

Side by Side Diff: chrome/browser/media/webrtc_rtp_dump_writer_unittest.cc

Issue 2307083002: Cleanup: move WebRTC related files from chrome/browser/media to chrome/browser/media/webrtc/ (Closed)
Patch Set: Removed file wrongly resuscitated during rebase Created 4 years, 3 months 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
OLDNEW
(Empty)
1 // Copyright 2014 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 "chrome/browser/media/webrtc_rtp_dump_writer.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9 #include <string.h>
10
11 #include <memory>
12
13 #include "base/big_endian.h"
14 #include "base/bind.h"
15 #include "base/files/file_util.h"
16 #include "base/files/scoped_temp_dir.h"
17 #include "base/macros.h"
18 #include "base/run_loop.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/test/test_browser_thread_bundle.h"
21 #include "content/public/test/test_utils.h"
22 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "third_party/zlib/zlib.h"
25
26 static const size_t kMinimumRtpHeaderLength = 12;
27
28 static void CreateFakeRtpPacketHeader(size_t csrc_count,
29 size_t extension_header_count,
30 std::vector<uint8_t>* packet_header) {
31 packet_header->resize(kMinimumRtpHeaderLength +
32 csrc_count * sizeof(uint32_t) +
33 (extension_header_count + 1) * sizeof(uint32_t));
34
35 memset(&(*packet_header)[0], 0, packet_header->size());
36
37 // First byte format: vvpxcccc, where 'vv' is the version, 'p' is padding, 'x'
38 // is the extension bit, 'cccc' is the CSRC count.
39 (*packet_header)[0] = 0;
40 (*packet_header)[0] |= (0x2 << 6); // version.
41 // The extension bit.
42 (*packet_header)[0] |= (extension_header_count > 0 ? (0x1 << 4) : 0);
43 (*packet_header)[0] |= (csrc_count & 0xf);
44
45 // Set extension length.
46 size_t offset = kMinimumRtpHeaderLength +
47 (csrc_count & 0xf) * sizeof(uint32_t) + sizeof(uint16_t);
48 base::WriteBigEndian(reinterpret_cast<char*>(&(*packet_header)[offset]),
49 static_cast<uint16_t>(extension_header_count));
50 }
51
52 class WebRtcRtpDumpWriterTest : public testing::Test {
53 public:
54 WebRtcRtpDumpWriterTest()
55 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP |
56 content::TestBrowserThreadBundle::REAL_FILE_THREAD),
57 temp_dir_(new base::ScopedTempDir()) {}
58
59 virtual void SetUp() {
60 ASSERT_TRUE(temp_dir_->CreateUniqueTempDir());
61
62 incoming_dump_path_ = temp_dir_->path().AppendASCII("rtpdump_recv");
63 outgoing_dump_path_ = temp_dir_->path().AppendASCII("rtpdump_send");
64 writer_.reset(new WebRtcRtpDumpWriter(
65 incoming_dump_path_,
66 outgoing_dump_path_,
67 4 * 1024 * 1024,
68 base::Bind(&WebRtcRtpDumpWriterTest::OnMaxSizeReached,
69 base::Unretained(this))));
70 }
71
72 // Verifies that the dump contains records of |rtp_packet| repeated
73 // |packet_count| times.
74 void VerifyDumps(size_t incoming_packet_count, size_t outgoing_packet_count) {
75 std::string incoming_dump;
76 std::string outgoing_dump;
77
78 if (incoming_packet_count) {
79 EXPECT_TRUE(base::ReadFileToString(incoming_dump_path_, &incoming_dump));
80 EXPECT_TRUE(VerifyCompressedDump(&incoming_dump, incoming_packet_count));
81 } else {
82 EXPECT_FALSE(base::PathExists(incoming_dump_path_));
83 }
84
85 if (outgoing_packet_count) {
86 EXPECT_TRUE(base::ReadFileToString(outgoing_dump_path_, &outgoing_dump));
87 EXPECT_TRUE(VerifyCompressedDump(&outgoing_dump, outgoing_packet_count));
88 } else {
89 EXPECT_FALSE(base::PathExists(outgoing_dump_path_));
90 }
91 }
92
93 MOCK_METHOD2(OnEndDumpDone, void(bool, bool));
94 MOCK_METHOD0(OnMaxSizeReached, void(void));
95
96 protected:
97 // Verifies the compressed dump file contains the expected number of packets.
98 bool VerifyCompressedDump(std::string* dump, size_t expected_packet_count) {
99 EXPECT_GT(dump->size(), 0U);
100
101 std::vector<uint8_t> decompressed_dump;
102 EXPECT_TRUE(Decompress(dump, &decompressed_dump));
103
104 size_t actual_packet_count = 0;
105 EXPECT_TRUE(ReadDecompressedDump(decompressed_dump, &actual_packet_count));
106 EXPECT_EQ(expected_packet_count, actual_packet_count);
107
108 return true;
109 }
110
111 // Decompresses the |input| into |output|.
112 bool Decompress(std::string* input, std::vector<uint8_t>* output) {
113 z_stream stream = {0};
114
115 int result = inflateInit2(&stream, 15 + 16);
116 EXPECT_EQ(Z_OK, result);
117
118 output->resize(input->size() * 100);
119
120 stream.next_in =
121 reinterpret_cast<unsigned char*>(const_cast<char*>(&(*input)[0]));
122 stream.avail_in = input->size();
123 stream.next_out = &(*output)[0];
124 stream.avail_out = output->size();
125
126 result = inflate(&stream, Z_FINISH);
127 DCHECK_EQ(Z_STREAM_END, result);
128 result = inflateEnd(&stream);
129 DCHECK_EQ(Z_OK, result);
130
131 output->resize(output->size() - stream.avail_out);
132 return true;
133 }
134
135 // Tries to read |dump| as a rtpplay dump file and returns the number of
136 // packets found in the dump.
137 bool ReadDecompressedDump(const std::vector<uint8_t>& dump,
138 size_t* packet_count) {
139 static const char kFirstLine[] = "#!rtpplay1.0 0.0.0.0/0\n";
140 static const size_t kDumpFileHeaderSize = 4 * sizeof(uint32_t);
141
142 *packet_count = 0;
143 size_t dump_pos = 0;
144
145 // Verifies the first line.
146 EXPECT_EQ(memcmp(&dump[0], kFirstLine, arraysize(kFirstLine) - 1), 0);
147
148 dump_pos += arraysize(kFirstLine) - 1;
149 EXPECT_GT(dump.size(), dump_pos);
150
151 // Skips the file header.
152 dump_pos += kDumpFileHeaderSize;
153 EXPECT_GT(dump.size(), dump_pos);
154
155 // Reads each packet dump.
156 while (dump_pos < dump.size()) {
157 size_t packet_dump_length = 0;
158 if (!VerifyPacketDump(&dump[dump_pos],
159 dump.size() - dump_pos,
160 &packet_dump_length)) {
161 DVLOG(0) << "Failed to read the packet dump for packet "
162 << *packet_count << ", dump_pos = " << dump_pos
163 << ", dump_length = " << dump.size();
164 return false;
165 }
166
167 EXPECT_GE(dump.size(), dump_pos + packet_dump_length);
168 dump_pos += packet_dump_length;
169
170 (*packet_count)++;
171 }
172 return true;
173 }
174
175 // Tries to read one packet dump starting at |dump| and returns the size of
176 // the packet dump.
177 bool VerifyPacketDump(const uint8_t* dump,
178 size_t dump_length,
179 size_t* packet_dump_length) {
180 static const size_t kDumpHeaderLength = 8;
181
182 size_t dump_pos = 0;
183 base::ReadBigEndian(reinterpret_cast<const char*>(dump + dump_pos),
184 reinterpret_cast<uint16_t*>(packet_dump_length));
185 if (*packet_dump_length < kDumpHeaderLength + kMinimumRtpHeaderLength)
186 return false;
187
188 EXPECT_GE(dump_length, *packet_dump_length);
189 dump_pos += sizeof(uint16_t);
190
191 uint16_t rtp_packet_length = 0;
192 base::ReadBigEndian(reinterpret_cast<const char*>(dump + dump_pos),
193 &rtp_packet_length);
194 if (rtp_packet_length < kMinimumRtpHeaderLength)
195 return false;
196
197 dump_pos += sizeof(uint16_t);
198
199 // Skips the elapsed time field.
200 dump_pos += sizeof(uint32_t);
201
202 return IsValidRtpHeader(dump + dump_pos,
203 *packet_dump_length - kDumpHeaderLength);
204 }
205
206 // Returns true if |header| is a valid RTP header.
207 bool IsValidRtpHeader(const uint8_t* header, size_t length) {
208 if ((header[0] & 0xC0) != 0x80)
209 return false;
210
211 size_t cc_count = header[0] & 0x0F;
212 size_t header_length_without_extn = kMinimumRtpHeaderLength + 4 * cc_count;
213
214 if (length < header_length_without_extn)
215 return false;
216
217 uint16_t extension_count = 0;
218 base::ReadBigEndian(
219 reinterpret_cast<const char*>(header + header_length_without_extn + 2),
220 &extension_count);
221
222 if (length < (extension_count + 1) * 4 + header_length_without_extn)
223 return false;
224
225 return true;
226 }
227
228 content::TestBrowserThreadBundle thread_bundle_;
229 std::unique_ptr<base::ScopedTempDir> temp_dir_;
230 base::FilePath incoming_dump_path_;
231 base::FilePath outgoing_dump_path_;
232 std::unique_ptr<WebRtcRtpDumpWriter> writer_;
233 };
234
235 TEST_F(WebRtcRtpDumpWriterTest, NoDumpFileIfNoPacketDumped) {
236 // The scope is used to make sure the EXPECT_CALL is checked before exiting
237 // the scope.
238 {
239 EXPECT_CALL(*this, OnEndDumpDone(false, false));
240
241 writer_->EndDump(RTP_DUMP_BOTH,
242 base::Bind(&WebRtcRtpDumpWriterTest::OnEndDumpDone,
243 base::Unretained(this)));
244
245 content::RunAllPendingInMessageLoop(content::BrowserThread::FILE);
246 base::RunLoop().RunUntilIdle();
247 content::RunAllPendingInMessageLoop(content::BrowserThread::FILE);
248 base::RunLoop().RunUntilIdle();
249 }
250 EXPECT_FALSE(base::PathExists(incoming_dump_path_));
251 EXPECT_FALSE(base::PathExists(outgoing_dump_path_));
252 }
253
254 TEST_F(WebRtcRtpDumpWriterTest, WriteAndFlushSmallSizeDump) {
255 std::vector<uint8_t> packet_header;
256 CreateFakeRtpPacketHeader(1, 2, &packet_header);
257
258 writer_->WriteRtpPacket(
259 &packet_header[0], packet_header.size(), 100, true);
260 writer_->WriteRtpPacket(
261 &packet_header[0], packet_header.size(), 100, false);
262
263 // The scope is used to make sure the EXPECT_CALL is checked before exiting
264 // the scope.
265 {
266 EXPECT_CALL(*this, OnEndDumpDone(true, true));
267
268 writer_->EndDump(RTP_DUMP_BOTH,
269 base::Bind(&WebRtcRtpDumpWriterTest::OnEndDumpDone,
270 base::Unretained(this)));
271
272 content::RunAllPendingInMessageLoop(content::BrowserThread::FILE);
273 base::RunLoop().RunUntilIdle();
274 content::RunAllPendingInMessageLoop(content::BrowserThread::FILE);
275 base::RunLoop().RunUntilIdle();
276 }
277
278 VerifyDumps(1, 1);
279 }
280
281 TEST_F(WebRtcRtpDumpWriterTest, WriteOverMaxLimit) {
282 // Reset the writer with a small max size limit.
283 writer_.reset(new WebRtcRtpDumpWriter(
284 incoming_dump_path_,
285 outgoing_dump_path_,
286 100,
287 base::Bind(&WebRtcRtpDumpWriterTest::OnMaxSizeReached,
288 base::Unretained(this))));
289
290 std::vector<uint8_t> packet_header;
291 CreateFakeRtpPacketHeader(3, 4, &packet_header);
292
293 const size_t kPacketCount = 200;
294 // The scope is used to make sure the EXPECT_CALL is checked before exiting
295 // the scope.
296 {
297 EXPECT_CALL(*this, OnMaxSizeReached()).Times(testing::AtLeast(1));
298
299 // Write enough packets to overflow the in-memory buffer and max limit.
300 for (size_t i = 0; i < kPacketCount; ++i) {
301 writer_->WriteRtpPacket(
302 &packet_header[0], packet_header.size(), 100, true);
303
304 writer_->WriteRtpPacket(
305 &packet_header[0], packet_header.size(), 100, false);
306 }
307
308 EXPECT_CALL(*this, OnEndDumpDone(true, true));
309
310 writer_->EndDump(RTP_DUMP_BOTH,
311 base::Bind(&WebRtcRtpDumpWriterTest::OnEndDumpDone,
312 base::Unretained(this)));
313
314 content::RunAllPendingInMessageLoop(content::BrowserThread::FILE);
315 base::RunLoop().RunUntilIdle();
316 content::RunAllPendingInMessageLoop(content::BrowserThread::FILE);
317 base::RunLoop().RunUntilIdle();
318 }
319 VerifyDumps(kPacketCount, kPacketCount);
320 }
321
322 TEST_F(WebRtcRtpDumpWriterTest, DestroyWriterBeforeEndDumpCallback) {
323 EXPECT_CALL(*this, OnEndDumpDone(testing::_, testing::_)).Times(0);
324
325 writer_->EndDump(RTP_DUMP_BOTH,
326 base::Bind(&WebRtcRtpDumpWriterTest::OnEndDumpDone,
327 base::Unretained(this)));
328
329 writer_.reset();
330
331 content::RunAllPendingInMessageLoop(content::BrowserThread::FILE);
332 base::RunLoop().RunUntilIdle();
333 content::RunAllPendingInMessageLoop(content::BrowserThread::FILE);
334 base::RunLoop().RunUntilIdle();
335 }
336
337 TEST_F(WebRtcRtpDumpWriterTest, EndDumpsSeparately) {
338 std::vector<uint8_t> packet_header;
339 CreateFakeRtpPacketHeader(1, 2, &packet_header);
340
341 writer_->WriteRtpPacket(
342 &packet_header[0], packet_header.size(), 100, true);
343 writer_->WriteRtpPacket(
344 &packet_header[0], packet_header.size(), 100, true);
345 writer_->WriteRtpPacket(
346 &packet_header[0], packet_header.size(), 100, false);
347
348 // The scope is used to make sure the EXPECT_CALL is checked before exiting
349 // the scope.
350 {
351 EXPECT_CALL(*this, OnEndDumpDone(true, false));
352 EXPECT_CALL(*this, OnEndDumpDone(false, true));
353
354 writer_->EndDump(RTP_DUMP_INCOMING,
355 base::Bind(&WebRtcRtpDumpWriterTest::OnEndDumpDone,
356 base::Unretained(this)));
357
358 writer_->EndDump(RTP_DUMP_OUTGOING,
359 base::Bind(&WebRtcRtpDumpWriterTest::OnEndDumpDone,
360 base::Unretained(this)));
361
362 content::RunAllPendingInMessageLoop(content::BrowserThread::FILE);
363 base::RunLoop().RunUntilIdle();
364 content::RunAllPendingInMessageLoop(content::BrowserThread::FILE);
365 base::RunLoop().RunUntilIdle();
366 }
367
368 VerifyDumps(2, 1);
369 }
OLDNEW
« no previous file with comments | « chrome/browser/media/webrtc_rtp_dump_writer.cc ('k') | chrome/browser/media/webrtc_simulcast_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698