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