OLD | NEW |
| (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_handler.h" | |
6 | |
7 #include <stddef.h> | |
8 #include <stdint.h> | |
9 | |
10 #include <memory> | |
11 #include <utility> | |
12 | |
13 #include "base/bind.h" | |
14 #include "base/files/file_util.h" | |
15 #include "base/files/scoped_temp_dir.h" | |
16 #include "base/location.h" | |
17 #include "base/macros.h" | |
18 #include "base/run_loop.h" | |
19 #include "base/single_thread_task_runner.h" | |
20 #include "base/threading/thread_task_runner_handle.h" | |
21 #include "chrome/browser/media/webrtc_rtp_dump_writer.h" | |
22 #include "content/public/test/test_browser_thread_bundle.h" | |
23 #include "testing/gmock/include/gmock/gmock.h" | |
24 #include "testing/gtest/include/gtest/gtest.h" | |
25 | |
26 class FakeDumpWriter : public WebRtcRtpDumpWriter { | |
27 public: | |
28 FakeDumpWriter(size_t max_dump_size, | |
29 const base::Closure& max_size_reached_callback, | |
30 bool end_dump_success) | |
31 : WebRtcRtpDumpWriter(base::FilePath(), | |
32 base::FilePath(), | |
33 max_dump_size, | |
34 base::Closure()), | |
35 max_dump_size_(max_dump_size), | |
36 current_dump_size_(0), | |
37 max_size_reached_callback_(max_size_reached_callback), | |
38 end_dump_success_(end_dump_success) {} | |
39 | |
40 void WriteRtpPacket(const uint8_t* packet_header, | |
41 size_t header_length, | |
42 size_t packet_length, | |
43 bool incoming) override { | |
44 current_dump_size_ += header_length; | |
45 if (current_dump_size_ > max_dump_size_) | |
46 max_size_reached_callback_.Run(); | |
47 } | |
48 | |
49 void EndDump(RtpDumpType type, | |
50 const EndDumpCallback& finished_callback) override { | |
51 bool incoming_success = end_dump_success_; | |
52 bool outgoing_success = end_dump_success_; | |
53 | |
54 if (type == RTP_DUMP_INCOMING) | |
55 outgoing_success = false; | |
56 else if (type == RTP_DUMP_OUTGOING) | |
57 incoming_success = false; | |
58 | |
59 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
60 FROM_HERE, | |
61 base::Bind(finished_callback, incoming_success, outgoing_success)); | |
62 } | |
63 | |
64 private: | |
65 size_t max_dump_size_; | |
66 size_t current_dump_size_; | |
67 base::Closure max_size_reached_callback_; | |
68 bool end_dump_success_; | |
69 }; | |
70 | |
71 class WebRtcRtpDumpHandlerTest : public testing::Test { | |
72 public: | |
73 WebRtcRtpDumpHandlerTest() | |
74 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) { | |
75 ResetDumpHandler(base::FilePath(), true); | |
76 } | |
77 | |
78 void ResetDumpHandler(const base::FilePath& dir, bool end_dump_success) { | |
79 handler_.reset(new WebRtcRtpDumpHandler( | |
80 dir.empty() ? base::FilePath(FILE_PATH_LITERAL("dummy")) : dir)); | |
81 | |
82 std::unique_ptr<WebRtcRtpDumpWriter> writer(new FakeDumpWriter( | |
83 10, base::Bind(&WebRtcRtpDumpHandler::OnMaxDumpSizeReached, | |
84 base::Unretained(handler_.get())), | |
85 end_dump_success)); | |
86 | |
87 handler_->SetDumpWriterForTesting(std::move(writer)); | |
88 } | |
89 | |
90 void DeleteDumpHandler() { handler_.reset(); } | |
91 | |
92 void WriteFakeDumpFiles(const base::FilePath& dir, | |
93 base::FilePath* incoming_dump, | |
94 base::FilePath* outgoing_dump) { | |
95 *incoming_dump = dir.AppendASCII("recv"); | |
96 *outgoing_dump = dir.AppendASCII("send"); | |
97 const char dummy[] = "dummy"; | |
98 EXPECT_GT(base::WriteFile(*incoming_dump, dummy, arraysize(dummy)), 0); | |
99 EXPECT_GT(base::WriteFile(*outgoing_dump, dummy, arraysize(dummy)), 0); | |
100 } | |
101 | |
102 MOCK_METHOD2(OnStopDumpFinished, | |
103 void(bool success, const std::string& error)); | |
104 | |
105 MOCK_METHOD0(OnStopOngoingDumpsFinished, void(void)); | |
106 | |
107 protected: | |
108 content::TestBrowserThreadBundle thread_bundle_; | |
109 std::unique_ptr<WebRtcRtpDumpHandler> handler_; | |
110 }; | |
111 | |
112 TEST_F(WebRtcRtpDumpHandlerTest, StateTransition) { | |
113 std::string error; | |
114 | |
115 RtpDumpType types[3]; | |
116 types[0] = RTP_DUMP_INCOMING; | |
117 types[1] = RTP_DUMP_OUTGOING; | |
118 types[2] = RTP_DUMP_BOTH; | |
119 | |
120 for (size_t i = 0; i < arraysize(types); ++i) { | |
121 DVLOG(2) << "Verifying state transition: type = " << types[i]; | |
122 | |
123 // Only StartDump is allowed in STATE_NONE. | |
124 EXPECT_CALL(*this, OnStopDumpFinished(false, testing::_)); | |
125 handler_->StopDump(types[i], | |
126 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | |
127 base::Unretained(this))); | |
128 | |
129 WebRtcRtpDumpHandler::ReleasedDumps empty_dumps(handler_->ReleaseDumps()); | |
130 EXPECT_TRUE(empty_dumps.incoming_dump_path.empty()); | |
131 EXPECT_TRUE(empty_dumps.outgoing_dump_path.empty()); | |
132 EXPECT_TRUE(handler_->StartDump(types[i], &error)); | |
133 base::RunLoop().RunUntilIdle(); | |
134 | |
135 // Only StopDump is allowed in STATE_STARTED. | |
136 EXPECT_FALSE(handler_->StartDump(types[i], &error)); | |
137 EXPECT_FALSE(handler_->ReadyToRelease()); | |
138 | |
139 EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)); | |
140 handler_->StopDump(types[i], | |
141 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | |
142 base::Unretained(this))); | |
143 base::RunLoop().RunUntilIdle(); | |
144 | |
145 // Only ReleaseDump is allowed in STATE_STOPPED. | |
146 EXPECT_FALSE(handler_->StartDump(types[i], &error)); | |
147 | |
148 EXPECT_CALL(*this, OnStopDumpFinished(false, testing::_)); | |
149 handler_->StopDump(types[i], | |
150 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | |
151 base::Unretained(this))); | |
152 EXPECT_TRUE(handler_->ReadyToRelease()); | |
153 | |
154 WebRtcRtpDumpHandler::ReleasedDumps dumps(handler_->ReleaseDumps()); | |
155 if (types[i] == RTP_DUMP_INCOMING || types[i] == RTP_DUMP_BOTH) | |
156 EXPECT_FALSE(dumps.incoming_dump_path.empty()); | |
157 | |
158 if (types[i] == RTP_DUMP_OUTGOING || types[i] == RTP_DUMP_BOTH) | |
159 EXPECT_FALSE(dumps.outgoing_dump_path.empty()); | |
160 | |
161 base::RunLoop().RunUntilIdle(); | |
162 ResetDumpHandler(base::FilePath(), true); | |
163 } | |
164 } | |
165 | |
166 TEST_F(WebRtcRtpDumpHandlerTest, StoppedWhenMaxSizeReached) { | |
167 std::string error; | |
168 | |
169 EXPECT_TRUE(handler_->StartDump(RTP_DUMP_INCOMING, &error)); | |
170 | |
171 std::vector<uint8_t> buffer(100, 0); | |
172 handler_->OnRtpPacket(&buffer[0], buffer.size(), buffer.size(), true); | |
173 base::RunLoop().RunUntilIdle(); | |
174 | |
175 // Dumping should have been stopped, so ready to release. | |
176 WebRtcRtpDumpHandler::ReleasedDumps dumps = handler_->ReleaseDumps(); | |
177 EXPECT_FALSE(dumps.incoming_dump_path.empty()); | |
178 } | |
179 | |
180 TEST_F(WebRtcRtpDumpHandlerTest, PacketIgnoredIfDumpingNotStarted) { | |
181 std::vector<uint8_t> buffer(100, 0); | |
182 handler_->OnRtpPacket(&buffer[0], buffer.size(), buffer.size(), true); | |
183 handler_->OnRtpPacket(&buffer[0], buffer.size(), buffer.size(), false); | |
184 base::RunLoop().RunUntilIdle(); | |
185 } | |
186 | |
187 TEST_F(WebRtcRtpDumpHandlerTest, PacketIgnoredIfDumpingStopped) { | |
188 std::string error; | |
189 | |
190 EXPECT_TRUE(handler_->StartDump(RTP_DUMP_INCOMING, &error)); | |
191 | |
192 EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)); | |
193 handler_->StopDump(RTP_DUMP_INCOMING, | |
194 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | |
195 base::Unretained(this))); | |
196 | |
197 std::vector<uint8_t> buffer(100, 0); | |
198 handler_->OnRtpPacket(&buffer[0], buffer.size(), buffer.size(), true); | |
199 base::RunLoop().RunUntilIdle(); | |
200 } | |
201 | |
202 TEST_F(WebRtcRtpDumpHandlerTest, CannotStartMoreThanFiveDumps) { | |
203 std::string error; | |
204 | |
205 handler_.reset(); | |
206 | |
207 std::unique_ptr<WebRtcRtpDumpHandler> handlers[6]; | |
208 | |
209 for (size_t i = 0; i < arraysize(handlers); ++i) { | |
210 handlers[i].reset(new WebRtcRtpDumpHandler(base::FilePath())); | |
211 | |
212 if (i < arraysize(handlers) - 1) { | |
213 EXPECT_TRUE(handlers[i]->StartDump(RTP_DUMP_INCOMING, &error)); | |
214 } else { | |
215 EXPECT_FALSE(handlers[i]->StartDump(RTP_DUMP_INCOMING, &error)); | |
216 } | |
217 } | |
218 } | |
219 | |
220 TEST_F(WebRtcRtpDumpHandlerTest, StartStopIncomingThenStartStopOutgoing) { | |
221 std::string error; | |
222 | |
223 EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)).Times(2); | |
224 | |
225 EXPECT_TRUE(handler_->StartDump(RTP_DUMP_INCOMING, &error)); | |
226 handler_->StopDump(RTP_DUMP_INCOMING, | |
227 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | |
228 base::Unretained(this))); | |
229 | |
230 EXPECT_TRUE(handler_->StartDump(RTP_DUMP_OUTGOING, &error)); | |
231 handler_->StopDump(RTP_DUMP_OUTGOING, | |
232 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | |
233 base::Unretained(this))); | |
234 | |
235 base::RunLoop().RunUntilIdle(); | |
236 } | |
237 | |
238 TEST_F(WebRtcRtpDumpHandlerTest, StartIncomingStartOutgoingThenStopBoth) { | |
239 std::string error; | |
240 | |
241 EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)); | |
242 | |
243 EXPECT_TRUE(handler_->StartDump(RTP_DUMP_INCOMING, &error)); | |
244 EXPECT_TRUE(handler_->StartDump(RTP_DUMP_OUTGOING, &error)); | |
245 | |
246 handler_->StopDump(RTP_DUMP_INCOMING, | |
247 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | |
248 base::Unretained(this))); | |
249 | |
250 base::RunLoop().RunUntilIdle(); | |
251 } | |
252 | |
253 TEST_F(WebRtcRtpDumpHandlerTest, StartBothThenStopIncomingStopOutgoing) { | |
254 std::string error; | |
255 | |
256 EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)).Times(2); | |
257 | |
258 EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error)); | |
259 | |
260 handler_->StopDump(RTP_DUMP_INCOMING, | |
261 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | |
262 base::Unretained(this))); | |
263 handler_->StopDump(RTP_DUMP_OUTGOING, | |
264 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | |
265 base::Unretained(this))); | |
266 | |
267 base::RunLoop().RunUntilIdle(); | |
268 } | |
269 | |
270 TEST_F(WebRtcRtpDumpHandlerTest, DumpsCleanedUpIfNotReleased) { | |
271 base::ScopedTempDir temp_dir; | |
272 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | |
273 ResetDumpHandler(temp_dir.path(), true); | |
274 | |
275 base::FilePath incoming_dump, outgoing_dump; | |
276 WriteFakeDumpFiles(temp_dir.path(), &incoming_dump, &outgoing_dump); | |
277 | |
278 std::string error; | |
279 EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error)); | |
280 | |
281 EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)); | |
282 handler_->StopDump(RTP_DUMP_BOTH, | |
283 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | |
284 base::Unretained(this))); | |
285 base::RunLoop().RunUntilIdle(); | |
286 | |
287 handler_.reset(); | |
288 base::RunLoop().RunUntilIdle(); | |
289 | |
290 EXPECT_FALSE(base::PathExists(incoming_dump)); | |
291 EXPECT_FALSE(base::PathExists(outgoing_dump)); | |
292 } | |
293 | |
294 TEST_F(WebRtcRtpDumpHandlerTest, DumpDeletedIfEndDumpFailed) { | |
295 base::ScopedTempDir temp_dir; | |
296 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | |
297 | |
298 // Make the writer return failure on EndStream. | |
299 ResetDumpHandler(temp_dir.path(), false); | |
300 | |
301 base::FilePath incoming_dump, outgoing_dump; | |
302 WriteFakeDumpFiles(temp_dir.path(), &incoming_dump, &outgoing_dump); | |
303 | |
304 std::string error; | |
305 EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error)); | |
306 EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)).Times(2); | |
307 | |
308 handler_->StopDump(RTP_DUMP_INCOMING, | |
309 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | |
310 base::Unretained(this))); | |
311 base::RunLoop().RunUntilIdle(); | |
312 | |
313 EXPECT_FALSE(base::PathExists(incoming_dump)); | |
314 EXPECT_TRUE(base::PathExists(outgoing_dump)); | |
315 | |
316 handler_->StopDump(RTP_DUMP_OUTGOING, | |
317 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | |
318 base::Unretained(this))); | |
319 base::RunLoop().RunUntilIdle(); | |
320 EXPECT_FALSE(base::PathExists(outgoing_dump)); | |
321 } | |
322 | |
323 TEST_F(WebRtcRtpDumpHandlerTest, StopOngoingDumpsWhileStoppingDumps) { | |
324 std::string error; | |
325 EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error)); | |
326 | |
327 testing::InSequence s; | |
328 EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)); | |
329 EXPECT_CALL(*this, OnStopOngoingDumpsFinished()); | |
330 | |
331 handler_->StopDump(RTP_DUMP_BOTH, | |
332 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | |
333 base::Unretained(this))); | |
334 | |
335 handler_->StopOngoingDumps( | |
336 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopOngoingDumpsFinished, | |
337 base::Unretained(this))); | |
338 | |
339 base::RunLoop().RunUntilIdle(); | |
340 | |
341 WebRtcRtpDumpHandler::ReleasedDumps dumps(handler_->ReleaseDumps()); | |
342 EXPECT_FALSE(dumps.incoming_dump_path.empty()); | |
343 EXPECT_FALSE(dumps.outgoing_dump_path.empty()); | |
344 } | |
345 | |
346 TEST_F(WebRtcRtpDumpHandlerTest, StopOngoingDumpsWhileDumping) { | |
347 std::string error; | |
348 EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error)); | |
349 | |
350 EXPECT_CALL(*this, OnStopOngoingDumpsFinished()); | |
351 | |
352 handler_->StopOngoingDumps( | |
353 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopOngoingDumpsFinished, | |
354 base::Unretained(this))); | |
355 | |
356 base::RunLoop().RunUntilIdle(); | |
357 | |
358 WebRtcRtpDumpHandler::ReleasedDumps dumps(handler_->ReleaseDumps()); | |
359 EXPECT_FALSE(dumps.incoming_dump_path.empty()); | |
360 EXPECT_FALSE(dumps.outgoing_dump_path.empty()); | |
361 } | |
362 | |
363 TEST_F(WebRtcRtpDumpHandlerTest, StopOngoingDumpsWhenAlreadyStopped) { | |
364 std::string error; | |
365 EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error)); | |
366 | |
367 { | |
368 EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)); | |
369 | |
370 handler_->StopDump(RTP_DUMP_BOTH, | |
371 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | |
372 base::Unretained(this))); | |
373 base::RunLoop().RunUntilIdle(); | |
374 } | |
375 | |
376 EXPECT_CALL(*this, OnStopOngoingDumpsFinished()); | |
377 handler_->StopOngoingDumps( | |
378 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopOngoingDumpsFinished, | |
379 base::Unretained(this))); | |
380 } | |
381 | |
382 TEST_F(WebRtcRtpDumpHandlerTest, StopOngoingDumpsWhileStoppingOneDump) { | |
383 std::string error; | |
384 EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error)); | |
385 | |
386 testing::InSequence s; | |
387 EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)); | |
388 EXPECT_CALL(*this, OnStopOngoingDumpsFinished()); | |
389 | |
390 handler_->StopDump(RTP_DUMP_INCOMING, | |
391 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | |
392 base::Unretained(this))); | |
393 | |
394 handler_->StopOngoingDumps( | |
395 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopOngoingDumpsFinished, | |
396 base::Unretained(this))); | |
397 | |
398 base::RunLoop().RunUntilIdle(); | |
399 | |
400 WebRtcRtpDumpHandler::ReleasedDumps dumps(handler_->ReleaseDumps()); | |
401 EXPECT_FALSE(dumps.incoming_dump_path.empty()); | |
402 EXPECT_FALSE(dumps.outgoing_dump_path.empty()); | |
403 } | |
404 | |
405 TEST_F(WebRtcRtpDumpHandlerTest, DeleteHandlerBeforeStopCallback) { | |
406 std::string error; | |
407 | |
408 EXPECT_CALL(*this, OnStopOngoingDumpsFinished()) | |
409 .WillOnce(testing::InvokeWithoutArgs( | |
410 this, &WebRtcRtpDumpHandlerTest::DeleteDumpHandler)); | |
411 | |
412 EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error)); | |
413 | |
414 handler_->StopOngoingDumps( | |
415 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopOngoingDumpsFinished, | |
416 base::Unretained(this))); | |
417 | |
418 base::RunLoop().RunUntilIdle(); | |
419 } | |
OLD | NEW |