Home | History | Annotate | Download | only in media
      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/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"
     16 
     17 class 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 
     62 class 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 DeleteDumpHandler() { handler_.reset(); }
     83 
     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);
     92   }
     93 
     94   MOCK_METHOD2(OnStopDumpFinished,
     95                void(bool success, const std::string& error));
     96 
     97   MOCK_METHOD0(OnStopOngoingDumpsFinished, void(void));
     98 
     99  protected:
    100   content::TestBrowserThreadBundle thread_bundle_;
    101   scoped_ptr<WebRtcRtpDumpHandler> handler_;
    102 };
    103 
    104 TEST_F(WebRtcRtpDumpHandlerTest, StateTransition) {
    105   std::string error;
    106 
    107   RtpDumpType types[3];
    108   types[0] = RTP_DUMP_INCOMING;
    109   types[1] = RTP_DUMP_OUTGOING;
    110   types[2] = RTP_DUMP_BOTH;
    111 
    112   for (size_t i = 0; i < arraysize(types); ++i) {
    113     DVLOG(2) << "Verifying state transition: type = " << types[i];
    114 
    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)));
    120 
    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();
    126 
    127     // Only StopDump is allowed in STATE_STARTED.
    128     EXPECT_FALSE(handler_->StartDump(types[i], &error));
    129     EXPECT_FALSE(handler_->ReadyToRelease());
    130 
    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();
    136 
    137     // Only ReleaseDump is allowed in STATE_STOPPED.
    138     EXPECT_FALSE(handler_->StartDump(types[i], &error));
    139 
    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());
    145 
    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());
    149 
    150     if (types[i] == RTP_DUMP_OUTGOING || types[i] == RTP_DUMP_BOTH)
    151       EXPECT_FALSE(dumps.outgoing_dump_path.empty());
    152 
    153     base::RunLoop().RunUntilIdle();
    154     ResetDumpHandler(base::FilePath(), true);
    155   }
    156 }
    157 
    158 TEST_F(WebRtcRtpDumpHandlerTest, StoppedWhenMaxSizeReached) {
    159   std::string error;
    160 
    161   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_INCOMING, &error));
    162 
    163   std::vector<uint8> buffer(100, 0);
    164   handler_->OnRtpPacket(&buffer[0], buffer.size(), buffer.size(), true);
    165   base::RunLoop().RunUntilIdle();
    166 
    167   // Dumping should have been stopped, so ready to release.
    168   WebRtcRtpDumpHandler::ReleasedDumps dumps = handler_->ReleaseDumps();
    169   EXPECT_FALSE(dumps.incoming_dump_path.empty());
    170 }
    171 
    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();
    177 }
    178 
    179 TEST_F(WebRtcRtpDumpHandlerTest, PacketIgnoredIfDumpingStopped) {
    180   std::string error;
    181 
    182   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_INCOMING, &error));
    183 
    184   EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_));
    185   handler_->StopDump(RTP_DUMP_INCOMING,
    186                      base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished,
    187                                 base::Unretained(this)));
    188 
    189   std::vector<uint8> buffer(100, 0);
    190   handler_->OnRtpPacket(&buffer[0], buffer.size(), buffer.size(), true);
    191   base::RunLoop().RunUntilIdle();
    192 }
    193 
    194 TEST_F(WebRtcRtpDumpHandlerTest, CannotStartMoreThanFiveDumps) {
    195   std::string error;
    196 
    197   handler_.reset();
    198 
    199   scoped_ptr<WebRtcRtpDumpHandler> handlers[6];
    200 
    201   for (size_t i = 0; i < arraysize(handlers); ++i) {
    202     handlers[i].reset(new WebRtcRtpDumpHandler(base::FilePath()));
    203 
    204     if (i < arraysize(handlers) - 1) {
    205       EXPECT_TRUE(handlers[i]->StartDump(RTP_DUMP_INCOMING, &error));
    206     } else {
    207       EXPECT_FALSE(handlers[i]->StartDump(RTP_DUMP_INCOMING, &error));
    208     }
    209   }
    210 }
    211 
    212 TEST_F(WebRtcRtpDumpHandlerTest, StartStopIncomingThenStartStopOutgoing) {
    213   std::string error;
    214 
    215   EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)).Times(2);
    216 
    217   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_INCOMING, &error));
    218   handler_->StopDump(RTP_DUMP_INCOMING,
    219                      base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished,
    220                                 base::Unretained(this)));
    221 
    222   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_OUTGOING, &error));
    223   handler_->StopDump(RTP_DUMP_OUTGOING,
    224                      base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished,
    225                                 base::Unretained(this)));
    226 
    227   base::RunLoop().RunUntilIdle();
    228 }
    229 
    230 TEST_F(WebRtcRtpDumpHandlerTest, StartIncomingStartOutgoingThenStopBoth) {
    231   std::string error;
    232 
    233   EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_));
    234 
    235   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_INCOMING, &error));
    236   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_OUTGOING, &error));
    237 
    238   handler_->StopDump(RTP_DUMP_INCOMING,
    239                      base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished,
    240                                 base::Unretained(this)));
    241 
    242   base::RunLoop().RunUntilIdle();
    243 }
    244 
    245 TEST_F(WebRtcRtpDumpHandlerTest, StartBothThenStopIncomingStopOutgoing) {
    246   std::string error;
    247 
    248   EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)).Times(2);
    249 
    250   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error));
    251 
    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)));
    258 
    259   base::RunLoop().RunUntilIdle();
    260 }
    261 
    262 TEST_F(WebRtcRtpDumpHandlerTest, DumpsCleanedUpIfNotReleased) {
    263   base::ScopedTempDir temp_dir;
    264   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    265   ResetDumpHandler(temp_dir.path(), true);
    266 
    267   base::FilePath incoming_dump, outgoing_dump;
    268   WriteFakeDumpFiles(temp_dir.path(), &incoming_dump, &outgoing_dump);
    269 
    270   std::string error;
    271   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error));
    272 
    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();
    278 
    279   handler_.reset();
    280   base::RunLoop().RunUntilIdle();
    281 
    282   EXPECT_FALSE(base::PathExists(incoming_dump));
    283   EXPECT_FALSE(base::PathExists(outgoing_dump));
    284 }
    285 
    286 TEST_F(WebRtcRtpDumpHandlerTest, DumpDeletedIfEndDumpFailed) {
    287   base::ScopedTempDir temp_dir;
    288   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    289 
    290   // Make the writer return failure on EndStream.
    291   ResetDumpHandler(temp_dir.path(), false);
    292 
    293   base::FilePath incoming_dump, outgoing_dump;
    294   WriteFakeDumpFiles(temp_dir.path(), &incoming_dump, &outgoing_dump);
    295 
    296   std::string error;
    297   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error));
    298   EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)).Times(2);
    299 
    300   handler_->StopDump(RTP_DUMP_INCOMING,
    301                      base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished,
    302                                 base::Unretained(this)));
    303   base::RunLoop().RunUntilIdle();
    304 
    305   EXPECT_FALSE(base::PathExists(incoming_dump));
    306   EXPECT_TRUE(base::PathExists(outgoing_dump));
    307 
    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));
    313 }
    314 
    315 TEST_F(WebRtcRtpDumpHandlerTest, StopOngoingDumpsWhileStoppingDumps) {
    316   std::string error;
    317   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error));
    318 
    319   testing::InSequence s;
    320   EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_));
    321   EXPECT_CALL(*this, OnStopOngoingDumpsFinished());
    322 
    323   handler_->StopDump(RTP_DUMP_BOTH,
    324                      base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished,
    325                                 base::Unretained(this)));
    326 
    327   handler_->StopOngoingDumps(
    328       base::Bind(&WebRtcRtpDumpHandlerTest::OnStopOngoingDumpsFinished,
    329                  base::Unretained(this)));
    330 
    331   base::RunLoop().RunUntilIdle();
    332 
    333   WebRtcRtpDumpHandler::ReleasedDumps dumps(handler_->ReleaseDumps());
    334   EXPECT_FALSE(dumps.incoming_dump_path.empty());
    335   EXPECT_FALSE(dumps.outgoing_dump_path.empty());
    336 }
    337 
    338 TEST_F(WebRtcRtpDumpHandlerTest, StopOngoingDumpsWhileDumping) {
    339   std::string error;
    340   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error));
    341 
    342   EXPECT_CALL(*this, OnStopOngoingDumpsFinished());
    343 
    344   handler_->StopOngoingDumps(
    345       base::Bind(&WebRtcRtpDumpHandlerTest::OnStopOngoingDumpsFinished,
    346                  base::Unretained(this)));
    347 
    348   base::RunLoop().RunUntilIdle();
    349 
    350   WebRtcRtpDumpHandler::ReleasedDumps dumps(handler_->ReleaseDumps());
    351   EXPECT_FALSE(dumps.incoming_dump_path.empty());
    352   EXPECT_FALSE(dumps.outgoing_dump_path.empty());
    353 }
    354 
    355 TEST_F(WebRtcRtpDumpHandlerTest, StopOngoingDumpsWhenAlreadyStopped) {
    356   std::string error;
    357   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error));
    358 
    359   {
    360     EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_));
    361 
    362     handler_->StopDump(RTP_DUMP_BOTH,
    363                        base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished,
    364                                   base::Unretained(this)));
    365     base::RunLoop().RunUntilIdle();
    366   }
    367 
    368   EXPECT_CALL(*this, OnStopOngoingDumpsFinished());
    369   handler_->StopOngoingDumps(
    370       base::Bind(&WebRtcRtpDumpHandlerTest::OnStopOngoingDumpsFinished,
    371                  base::Unretained(this)));
    372 }
    373 
    374 TEST_F(WebRtcRtpDumpHandlerTest, StopOngoingDumpsWhileStoppingOneDump) {
    375   std::string error;
    376   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error));
    377 
    378   testing::InSequence s;
    379   EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_));
    380   EXPECT_CALL(*this, OnStopOngoingDumpsFinished());
    381 
    382   handler_->StopDump(RTP_DUMP_INCOMING,
    383                      base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished,
    384                                 base::Unretained(this)));
    385 
    386   handler_->StopOngoingDumps(
    387       base::Bind(&WebRtcRtpDumpHandlerTest::OnStopOngoingDumpsFinished,
    388                  base::Unretained(this)));
    389 
    390   base::RunLoop().RunUntilIdle();
    391 
    392   WebRtcRtpDumpHandler::ReleasedDumps dumps(handler_->ReleaseDumps());
    393   EXPECT_FALSE(dumps.incoming_dump_path.empty());
    394   EXPECT_FALSE(dumps.outgoing_dump_path.empty());
    395 }
    396 
    397 TEST_F(WebRtcRtpDumpHandlerTest, DeleteHandlerBeforeStopCallback) {
    398   std::string error;
    399 
    400   EXPECT_CALL(*this, OnStopOngoingDumpsFinished())
    401       .WillOnce(testing::InvokeWithoutArgs(
    402           this, &WebRtcRtpDumpHandlerTest::DeleteDumpHandler));
    403 
    404   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error));
    405 
    406   handler_->StopOngoingDumps(
    407       base::Bind(&WebRtcRtpDumpHandlerTest::OnStopOngoingDumpsFinished,
    408                  base::Unretained(this)));
    409 
    410   base::RunLoop().RunUntilIdle();
    411 }
    412