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.
6 #include "base/files/file_util.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/macros.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/run_loop.h"
11 #include "chrome/browser/media/webrtc_rtp_dump_handler.h"
12 #include "chrome/browser/media/webrtc_rtp_dump_writer.h"
13 #include "content/public/test/test_browser_thread_bundle.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 class FakeDumpWriter
: public WebRtcRtpDumpWriter
{
19 FakeDumpWriter(size_t max_dump_size
,
20 const base::Closure
& max_size_reached_callback
,
21 bool end_dump_success
)
22 : WebRtcRtpDumpWriter(base::FilePath(),
26 max_dump_size_(max_dump_size
),
27 current_dump_size_(0),
28 max_size_reached_callback_(max_size_reached_callback
),
29 end_dump_success_(end_dump_success
) {}
31 void WriteRtpPacket(const uint8
* packet_header
,
34 bool incoming
) override
{
35 current_dump_size_
+= header_length
;
36 if (current_dump_size_
> max_dump_size_
)
37 max_size_reached_callback_
.Run();
40 void EndDump(RtpDumpType type
,
41 const EndDumpCallback
& finished_callback
) override
{
42 bool incoming_sucess
= end_dump_success_
;
43 bool outgoing_success
= end_dump_success_
;
45 if (type
== RTP_DUMP_INCOMING
)
46 outgoing_success
= false;
47 else if (type
== RTP_DUMP_OUTGOING
)
48 incoming_sucess
= false;
50 base::MessageLoop::current()->PostTask(
52 base::Bind(finished_callback
, incoming_sucess
, outgoing_success
));
56 size_t max_dump_size_
;
57 size_t current_dump_size_
;
58 base::Closure max_size_reached_callback_
;
59 bool end_dump_success_
;
62 class WebRtcRtpDumpHandlerTest
: public testing::Test
{
64 WebRtcRtpDumpHandlerTest()
65 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP
) {
66 ResetDumpHandler(base::FilePath(), true);
69 void ResetDumpHandler(const base::FilePath
& dir
, bool end_dump_success
) {
70 handler_
.reset(new WebRtcRtpDumpHandler(
71 dir
.empty() ? base::FilePath(FILE_PATH_LITERAL("dummy")) : dir
));
73 scoped_ptr
<WebRtcRtpDumpWriter
> writer(new FakeDumpWriter(
75 base::Bind(&WebRtcRtpDumpHandler::OnMaxDumpSizeReached
,
76 base::Unretained(handler_
.get())),
79 handler_
->SetDumpWriterForTesting(writer
.Pass());
82 void DeleteDumpHandler() { handler_
.reset(); }
84 void WriteFakeDumpFiles(const base::FilePath
& dir
,
85 base::FilePath
* incoming_dump
,
86 base::FilePath
* outgoing_dump
) {
87 *incoming_dump
= dir
.AppendASCII("recv");
88 *outgoing_dump
= dir
.AppendASCII("send");
89 const char dummy
[] = "dummy";
90 EXPECT_GT(base::WriteFile(*incoming_dump
, dummy
, arraysize(dummy
)), 0);
91 EXPECT_GT(base::WriteFile(*outgoing_dump
, dummy
, arraysize(dummy
)), 0);
94 MOCK_METHOD2(OnStopDumpFinished
,
95 void(bool success
, const std::string
& error
));
97 MOCK_METHOD0(OnStopOngoingDumpsFinished
, void(void));
100 content::TestBrowserThreadBundle thread_bundle_
;
101 scoped_ptr
<WebRtcRtpDumpHandler
> handler_
;
104 TEST_F(WebRtcRtpDumpHandlerTest
, StateTransition
) {
107 RtpDumpType types
[3];
108 types
[0] = RTP_DUMP_INCOMING
;
109 types
[1] = RTP_DUMP_OUTGOING
;
110 types
[2] = RTP_DUMP_BOTH
;
112 for (size_t i
= 0; i
< arraysize(types
); ++i
) {
113 DVLOG(2) << "Verifying state transition: type = " << types
[i
];
115 // Only StartDump is allowed in STATE_NONE.
116 EXPECT_CALL(*this, OnStopDumpFinished(false, testing::_
));
117 handler_
->StopDump(types
[i
],
118 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished
,
119 base::Unretained(this)));
121 WebRtcRtpDumpHandler::ReleasedDumps
empty_dumps(handler_
->ReleaseDumps());
122 EXPECT_TRUE(empty_dumps
.incoming_dump_path
.empty());
123 EXPECT_TRUE(empty_dumps
.outgoing_dump_path
.empty());
124 EXPECT_TRUE(handler_
->StartDump(types
[i
], &error
));
125 base::RunLoop().RunUntilIdle();
127 // Only StopDump is allowed in STATE_STARTED.
128 EXPECT_FALSE(handler_
->StartDump(types
[i
], &error
));
129 EXPECT_FALSE(handler_
->ReadyToRelease());
131 EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_
));
132 handler_
->StopDump(types
[i
],
133 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished
,
134 base::Unretained(this)));
135 base::RunLoop().RunUntilIdle();
137 // Only ReleaseDump is allowed in STATE_STOPPED.
138 EXPECT_FALSE(handler_
->StartDump(types
[i
], &error
));
140 EXPECT_CALL(*this, OnStopDumpFinished(false, testing::_
));
141 handler_
->StopDump(types
[i
],
142 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished
,
143 base::Unretained(this)));
144 EXPECT_TRUE(handler_
->ReadyToRelease());
146 WebRtcRtpDumpHandler::ReleasedDumps
dumps(handler_
->ReleaseDumps());
147 if (types
[i
] == RTP_DUMP_INCOMING
|| types
[i
] == RTP_DUMP_BOTH
)
148 EXPECT_FALSE(dumps
.incoming_dump_path
.empty());
150 if (types
[i
] == RTP_DUMP_OUTGOING
|| types
[i
] == RTP_DUMP_BOTH
)
151 EXPECT_FALSE(dumps
.outgoing_dump_path
.empty());
153 base::RunLoop().RunUntilIdle();
154 ResetDumpHandler(base::FilePath(), true);
158 TEST_F(WebRtcRtpDumpHandlerTest
, StoppedWhenMaxSizeReached
) {
161 EXPECT_TRUE(handler_
->StartDump(RTP_DUMP_INCOMING
, &error
));
163 std::vector
<uint8
> buffer(100, 0);
164 handler_
->OnRtpPacket(&buffer
[0], buffer
.size(), buffer
.size(), true);
165 base::RunLoop().RunUntilIdle();
167 // Dumping should have been stopped, so ready to release.
168 WebRtcRtpDumpHandler::ReleasedDumps dumps
= handler_
->ReleaseDumps();
169 EXPECT_FALSE(dumps
.incoming_dump_path
.empty());
172 TEST_F(WebRtcRtpDumpHandlerTest
, PacketIgnoredIfDumpingNotStarted
) {
173 std::vector
<uint8
> buffer(100, 0);
174 handler_
->OnRtpPacket(&buffer
[0], buffer
.size(), buffer
.size(), true);
175 handler_
->OnRtpPacket(&buffer
[0], buffer
.size(), buffer
.size(), false);
176 base::RunLoop().RunUntilIdle();
179 TEST_F(WebRtcRtpDumpHandlerTest
, PacketIgnoredIfDumpingStopped
) {
182 EXPECT_TRUE(handler_
->StartDump(RTP_DUMP_INCOMING
, &error
));
184 EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_
));
185 handler_
->StopDump(RTP_DUMP_INCOMING
,
186 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished
,
187 base::Unretained(this)));
189 std::vector
<uint8
> buffer(100, 0);
190 handler_
->OnRtpPacket(&buffer
[0], buffer
.size(), buffer
.size(), true);
191 base::RunLoop().RunUntilIdle();
194 TEST_F(WebRtcRtpDumpHandlerTest
, CannotStartMoreThanFiveDumps
) {
199 scoped_ptr
<WebRtcRtpDumpHandler
> handlers
[6];
201 for (size_t i
= 0; i
< arraysize(handlers
); ++i
) {
202 handlers
[i
].reset(new WebRtcRtpDumpHandler(base::FilePath()));
204 if (i
< arraysize(handlers
) - 1) {
205 EXPECT_TRUE(handlers
[i
]->StartDump(RTP_DUMP_INCOMING
, &error
));
207 EXPECT_FALSE(handlers
[i
]->StartDump(RTP_DUMP_INCOMING
, &error
));
212 TEST_F(WebRtcRtpDumpHandlerTest
, StartStopIncomingThenStartStopOutgoing
) {
215 EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_
)).Times(2);
217 EXPECT_TRUE(handler_
->StartDump(RTP_DUMP_INCOMING
, &error
));
218 handler_
->StopDump(RTP_DUMP_INCOMING
,
219 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished
,
220 base::Unretained(this)));
222 EXPECT_TRUE(handler_
->StartDump(RTP_DUMP_OUTGOING
, &error
));
223 handler_
->StopDump(RTP_DUMP_OUTGOING
,
224 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished
,
225 base::Unretained(this)));
227 base::RunLoop().RunUntilIdle();
230 TEST_F(WebRtcRtpDumpHandlerTest
, StartIncomingStartOutgoingThenStopBoth
) {
233 EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_
));
235 EXPECT_TRUE(handler_
->StartDump(RTP_DUMP_INCOMING
, &error
));
236 EXPECT_TRUE(handler_
->StartDump(RTP_DUMP_OUTGOING
, &error
));
238 handler_
->StopDump(RTP_DUMP_INCOMING
,
239 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished
,
240 base::Unretained(this)));
242 base::RunLoop().RunUntilIdle();
245 TEST_F(WebRtcRtpDumpHandlerTest
, StartBothThenStopIncomingStopOutgoing
) {
248 EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_
)).Times(2);
250 EXPECT_TRUE(handler_
->StartDump(RTP_DUMP_BOTH
, &error
));
252 handler_
->StopDump(RTP_DUMP_INCOMING
,
253 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished
,
254 base::Unretained(this)));
255 handler_
->StopDump(RTP_DUMP_OUTGOING
,
256 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished
,
257 base::Unretained(this)));
259 base::RunLoop().RunUntilIdle();
262 TEST_F(WebRtcRtpDumpHandlerTest
, DumpsCleanedUpIfNotReleased
) {
263 base::ScopedTempDir temp_dir
;
264 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
265 ResetDumpHandler(temp_dir
.path(), true);
267 base::FilePath incoming_dump
, outgoing_dump
;
268 WriteFakeDumpFiles(temp_dir
.path(), &incoming_dump
, &outgoing_dump
);
271 EXPECT_TRUE(handler_
->StartDump(RTP_DUMP_BOTH
, &error
));
273 EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_
));
274 handler_
->StopDump(RTP_DUMP_BOTH
,
275 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished
,
276 base::Unretained(this)));
277 base::RunLoop().RunUntilIdle();
280 base::RunLoop().RunUntilIdle();
282 EXPECT_FALSE(base::PathExists(incoming_dump
));
283 EXPECT_FALSE(base::PathExists(outgoing_dump
));
286 TEST_F(WebRtcRtpDumpHandlerTest
, DumpDeletedIfEndDumpFailed
) {
287 base::ScopedTempDir temp_dir
;
288 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
290 // Make the writer return failure on EndStream.
291 ResetDumpHandler(temp_dir
.path(), false);
293 base::FilePath incoming_dump
, outgoing_dump
;
294 WriteFakeDumpFiles(temp_dir
.path(), &incoming_dump
, &outgoing_dump
);
297 EXPECT_TRUE(handler_
->StartDump(RTP_DUMP_BOTH
, &error
));
298 EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_
)).Times(2);
300 handler_
->StopDump(RTP_DUMP_INCOMING
,
301 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished
,
302 base::Unretained(this)));
303 base::RunLoop().RunUntilIdle();
305 EXPECT_FALSE(base::PathExists(incoming_dump
));
306 EXPECT_TRUE(base::PathExists(outgoing_dump
));
308 handler_
->StopDump(RTP_DUMP_OUTGOING
,
309 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished
,
310 base::Unretained(this)));
311 base::RunLoop().RunUntilIdle();
312 EXPECT_FALSE(base::PathExists(outgoing_dump
));
315 TEST_F(WebRtcRtpDumpHandlerTest
, StopOngoingDumpsWhileStoppingDumps
) {
317 EXPECT_TRUE(handler_
->StartDump(RTP_DUMP_BOTH
, &error
));
319 testing::InSequence s
;
320 EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_
));
321 EXPECT_CALL(*this, OnStopOngoingDumpsFinished());
323 handler_
->StopDump(RTP_DUMP_BOTH
,
324 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished
,
325 base::Unretained(this)));
327 handler_
->StopOngoingDumps(
328 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopOngoingDumpsFinished
,
329 base::Unretained(this)));
331 base::RunLoop().RunUntilIdle();
333 WebRtcRtpDumpHandler::ReleasedDumps
dumps(handler_
->ReleaseDumps());
334 EXPECT_FALSE(dumps
.incoming_dump_path
.empty());
335 EXPECT_FALSE(dumps
.outgoing_dump_path
.empty());
338 TEST_F(WebRtcRtpDumpHandlerTest
, StopOngoingDumpsWhileDumping
) {
340 EXPECT_TRUE(handler_
->StartDump(RTP_DUMP_BOTH
, &error
));
342 EXPECT_CALL(*this, OnStopOngoingDumpsFinished());
344 handler_
->StopOngoingDumps(
345 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopOngoingDumpsFinished
,
346 base::Unretained(this)));
348 base::RunLoop().RunUntilIdle();
350 WebRtcRtpDumpHandler::ReleasedDumps
dumps(handler_
->ReleaseDumps());
351 EXPECT_FALSE(dumps
.incoming_dump_path
.empty());
352 EXPECT_FALSE(dumps
.outgoing_dump_path
.empty());
355 TEST_F(WebRtcRtpDumpHandlerTest
, StopOngoingDumpsWhenAlreadyStopped
) {
357 EXPECT_TRUE(handler_
->StartDump(RTP_DUMP_BOTH
, &error
));
360 EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_
));
362 handler_
->StopDump(RTP_DUMP_BOTH
,
363 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished
,
364 base::Unretained(this)));
365 base::RunLoop().RunUntilIdle();
368 EXPECT_CALL(*this, OnStopOngoingDumpsFinished());
369 handler_
->StopOngoingDumps(
370 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopOngoingDumpsFinished
,
371 base::Unretained(this)));
374 TEST_F(WebRtcRtpDumpHandlerTest
, StopOngoingDumpsWhileStoppingOneDump
) {
376 EXPECT_TRUE(handler_
->StartDump(RTP_DUMP_BOTH
, &error
));
378 testing::InSequence s
;
379 EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_
));
380 EXPECT_CALL(*this, OnStopOngoingDumpsFinished());
382 handler_
->StopDump(RTP_DUMP_INCOMING
,
383 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished
,
384 base::Unretained(this)));
386 handler_
->StopOngoingDumps(
387 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopOngoingDumpsFinished
,
388 base::Unretained(this)));
390 base::RunLoop().RunUntilIdle();
392 WebRtcRtpDumpHandler::ReleasedDumps
dumps(handler_
->ReleaseDumps());
393 EXPECT_FALSE(dumps
.incoming_dump_path
.empty());
394 EXPECT_FALSE(dumps
.outgoing_dump_path
.empty());
397 TEST_F(WebRtcRtpDumpHandlerTest
, DeleteHandlerBeforeStopCallback
) {
400 EXPECT_CALL(*this, OnStopOngoingDumpsFinished())
401 .WillOnce(testing::InvokeWithoutArgs(
402 this, &WebRtcRtpDumpHandlerTest::DeleteDumpHandler
));
404 EXPECT_TRUE(handler_
->StartDump(RTP_DUMP_BOTH
, &error
));
406 handler_
->StopOngoingDumps(
407 base::Bind(&WebRtcRtpDumpHandlerTest::OnStopOngoingDumpsFinished
,
408 base::Unretained(this)));
410 base::RunLoop().RunUntilIdle();