| 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 "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 | 
|  | 17 class FakeDumpWriter : public WebRtcRtpDumpWriter { | 
|  | 18  public: | 
|  | 19   explicit 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 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 | 
|  | 102 TEST_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 dumps_0(handler_->ReleaseDumps()); | 
|  | 120     EXPECT_TRUE(dumps_0.incoming_dump_path.empty()); | 
|  | 121     EXPECT_TRUE(dumps_0.outgoing_dump_path.empty()); | 
|  | 122 | 
|  | 123     EXPECT_TRUE(handler_->StartDump(types[i], &error)); | 
|  | 124     base::RunLoop().RunUntilIdle(); | 
|  | 125 | 
|  | 126     // Only StopDump is allowed in STATE_STARTED. | 
|  | 127     EXPECT_FALSE(handler_->StartDump(types[i], &error)); | 
|  | 128 | 
|  | 129     WebRtcRtpDumpHandler::ReleasedDumps dumps_1(handler_->ReleaseDumps()); | 
|  | 130     EXPECT_TRUE(dumps_1.incoming_dump_path.empty()); | 
|  | 131     EXPECT_TRUE(dumps_1.outgoing_dump_path.empty()); | 
|  | 132 | 
|  | 133     EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)); | 
|  | 134     handler_->StopDump(types[i], | 
|  | 135                        base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | 
|  | 136                                   base::Unretained(this))); | 
|  | 137     base::RunLoop().RunUntilIdle(); | 
|  | 138 | 
|  | 139     // Only ReleaseDump is allowed in STATE_STOPPED. | 
|  | 140     EXPECT_FALSE(handler_->StartDump(types[i], &error)); | 
|  | 141 | 
|  | 142     EXPECT_CALL(*this, OnStopDumpFinished(false, testing::_)); | 
|  | 143     handler_->StopDump(types[i], | 
|  | 144                        base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | 
|  | 145                                   base::Unretained(this))); | 
|  | 146 | 
|  | 147     WebRtcRtpDumpHandler::ReleasedDumps dumps_2(handler_->ReleaseDumps()); | 
|  | 148     if (types[i] == RTP_DUMP_INCOMING || types[i] == RTP_DUMP_BOTH) | 
|  | 149       EXPECT_FALSE(dumps_2.incoming_dump_path.empty()); | 
|  | 150 | 
|  | 151     if (types[i] == RTP_DUMP_OUTGOING || types[i] == RTP_DUMP_BOTH) | 
|  | 152       EXPECT_FALSE(dumps_2.outgoing_dump_path.empty()); | 
|  | 153 | 
|  | 154     base::RunLoop().RunUntilIdle(); | 
|  | 155     ResetDumpHandler(base::FilePath(), true); | 
|  | 156   } | 
|  | 157 } | 
|  | 158 | 
|  | 159 TEST_F(WebRtcRtpDumpHandlerTest, StoppedWhenMaxSizeReached) { | 
|  | 160   std::string error; | 
|  | 161 | 
|  | 162   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_INCOMING, &error)); | 
|  | 163 | 
|  | 164   std::vector<uint8> buffer(100, 0); | 
|  | 165   handler_->OnRtpPacket(buffer.data(), buffer.size(), buffer.size(), true); | 
|  | 166   base::RunLoop().RunUntilIdle(); | 
|  | 167 | 
|  | 168   // Dumping should have been stopped, so ready to release. | 
|  | 169   WebRtcRtpDumpHandler::ReleasedDumps dumps = handler_->ReleaseDumps(); | 
|  | 170   EXPECT_FALSE(dumps.incoming_dump_path.empty()); | 
|  | 171 } | 
|  | 172 | 
|  | 173 TEST_F(WebRtcRtpDumpHandlerTest, PacketIgnoredIfDumpingNotStarted) { | 
|  | 174   std::vector<uint8> buffer(100, 0); | 
|  | 175   handler_->OnRtpPacket(buffer.data(), buffer.size(), buffer.size(), true); | 
|  | 176   handler_->OnRtpPacket(buffer.data(), buffer.size(), buffer.size(), false); | 
|  | 177   base::RunLoop().RunUntilIdle(); | 
|  | 178 } | 
|  | 179 | 
|  | 180 TEST_F(WebRtcRtpDumpHandlerTest, PacketIgnoredIfDumpingStopped) { | 
|  | 181   std::string error; | 
|  | 182 | 
|  | 183   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_INCOMING, &error)); | 
|  | 184 | 
|  | 185   EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)); | 
|  | 186   handler_->StopDump(RTP_DUMP_INCOMING, | 
|  | 187                      base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | 
|  | 188                                 base::Unretained(this))); | 
|  | 189 | 
|  | 190   std::vector<uint8> buffer(100, 0); | 
|  | 191   handler_->OnRtpPacket(buffer.data(), buffer.size(), buffer.size(), true); | 
|  | 192   base::RunLoop().RunUntilIdle(); | 
|  | 193 } | 
|  | 194 | 
|  | 195 TEST_F(WebRtcRtpDumpHandlerTest, CannotStartMoreThanFiveDumps) { | 
|  | 196   std::string error; | 
|  | 197 | 
|  | 198   handler_.reset(); | 
|  | 199 | 
|  | 200   scoped_ptr<WebRtcRtpDumpHandler> handlers[6]; | 
|  | 201 | 
|  | 202   for (size_t i = 0; i < arraysize(handlers); ++i) { | 
|  | 203     handlers[i].reset(new WebRtcRtpDumpHandler(base::FilePath())); | 
|  | 204 | 
|  | 205     if (i < arraysize(handlers) - 1) { | 
|  | 206       EXPECT_TRUE(handlers[i]->StartDump(RTP_DUMP_INCOMING, &error)); | 
|  | 207     } else { | 
|  | 208       EXPECT_FALSE(handlers[i]->StartDump(RTP_DUMP_INCOMING, &error)); | 
|  | 209     } | 
|  | 210   } | 
|  | 211 } | 
|  | 212 | 
|  | 213 TEST_F(WebRtcRtpDumpHandlerTest, StartStopIncomingThenStartStopOutgoing) { | 
|  | 214   std::string error; | 
|  | 215 | 
|  | 216   EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)).Times(2); | 
|  | 217 | 
|  | 218   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_INCOMING, &error)); | 
|  | 219   handler_->StopDump(RTP_DUMP_INCOMING, | 
|  | 220                      base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | 
|  | 221                                 base::Unretained(this))); | 
|  | 222 | 
|  | 223   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_OUTGOING, &error)); | 
|  | 224   handler_->StopDump(RTP_DUMP_OUTGOING, | 
|  | 225                      base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | 
|  | 226                                 base::Unretained(this))); | 
|  | 227 | 
|  | 228   base::RunLoop().RunUntilIdle(); | 
|  | 229 } | 
|  | 230 | 
|  | 231 TEST_F(WebRtcRtpDumpHandlerTest, StartIncomingStartOutgoingThenStopBoth) { | 
|  | 232   std::string error; | 
|  | 233 | 
|  | 234   EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)); | 
|  | 235 | 
|  | 236   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_INCOMING, &error)); | 
|  | 237   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_OUTGOING, &error)); | 
|  | 238 | 
|  | 239   handler_->StopDump(RTP_DUMP_INCOMING, | 
|  | 240                      base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | 
|  | 241                                 base::Unretained(this))); | 
|  | 242 | 
|  | 243   base::RunLoop().RunUntilIdle(); | 
|  | 244 } | 
|  | 245 | 
|  | 246 TEST_F(WebRtcRtpDumpHandlerTest, StartBothThenStopIncomingStopOutgoing) { | 
|  | 247   std::string error; | 
|  | 248 | 
|  | 249   EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)).Times(2); | 
|  | 250 | 
|  | 251   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error)); | 
|  | 252 | 
|  | 253   handler_->StopDump(RTP_DUMP_INCOMING, | 
|  | 254                      base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | 
|  | 255                                 base::Unretained(this))); | 
|  | 256   handler_->StopDump(RTP_DUMP_OUTGOING, | 
|  | 257                      base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | 
|  | 258                                 base::Unretained(this))); | 
|  | 259 | 
|  | 260   base::RunLoop().RunUntilIdle(); | 
|  | 261 } | 
|  | 262 | 
|  | 263 TEST_F(WebRtcRtpDumpHandlerTest, DumpsCleanedUpIfNotReleased) { | 
|  | 264   base::ScopedTempDir temp_dir; | 
|  | 265   ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 
|  | 266   ResetDumpHandler(temp_dir.path(), true); | 
|  | 267 | 
|  | 268   base::FilePath incoming_dump, outgoing_dump; | 
|  | 269   WriteFakeDumpFiles(temp_dir.path(), &incoming_dump, &outgoing_dump); | 
|  | 270 | 
|  | 271   std::string error; | 
|  | 272   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error)); | 
|  | 273 | 
|  | 274   EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)); | 
|  | 275   handler_->StopDump(RTP_DUMP_BOTH, | 
|  | 276                      base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | 
|  | 277                                 base::Unretained(this))); | 
|  | 278   base::RunLoop().RunUntilIdle(); | 
|  | 279 | 
|  | 280   handler_.reset(); | 
|  | 281   base::RunLoop().RunUntilIdle(); | 
|  | 282 | 
|  | 283   EXPECT_FALSE(base::PathExists(incoming_dump)); | 
|  | 284   EXPECT_FALSE(base::PathExists(outgoing_dump)); | 
|  | 285 } | 
|  | 286 | 
|  | 287 TEST_F(WebRtcRtpDumpHandlerTest, DumpDeletedIfEndDumpFailed) { | 
|  | 288   base::ScopedTempDir temp_dir; | 
|  | 289   ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 
|  | 290 | 
|  | 291   // Make the writer return failure on EndStream. | 
|  | 292   ResetDumpHandler(temp_dir.path(), false); | 
|  | 293 | 
|  | 294   base::FilePath incoming_dump, outgoing_dump; | 
|  | 295   WriteFakeDumpFiles(temp_dir.path(), &incoming_dump, &outgoing_dump); | 
|  | 296 | 
|  | 297   std::string error; | 
|  | 298   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error)); | 
|  | 299   EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)).Times(2); | 
|  | 300 | 
|  | 301   handler_->StopDump(RTP_DUMP_INCOMING, | 
|  | 302                      base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | 
|  | 303                                 base::Unretained(this))); | 
|  | 304   base::RunLoop().RunUntilIdle(); | 
|  | 305 | 
|  | 306   EXPECT_FALSE(base::PathExists(incoming_dump)); | 
|  | 307   EXPECT_TRUE(base::PathExists(outgoing_dump)); | 
|  | 308 | 
|  | 309   handler_->StopDump(RTP_DUMP_OUTGOING, | 
|  | 310                      base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | 
|  | 311                                 base::Unretained(this))); | 
|  | 312   base::RunLoop().RunUntilIdle(); | 
|  | 313   EXPECT_FALSE(base::PathExists(outgoing_dump)); | 
|  | 314 } | 
|  | 315 | 
|  | 316 TEST_F(WebRtcRtpDumpHandlerTest, StopOngoingDumpsWhileStoppingDumps) { | 
|  | 317   std::string error; | 
|  | 318   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error)); | 
|  | 319 | 
|  | 320   testing::InSequence s; | 
|  | 321   EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)); | 
|  | 322   EXPECT_CALL(*this, OnStopOngoingDumpsFinished()); | 
|  | 323 | 
|  | 324   handler_->StopDump(RTP_DUMP_BOTH, | 
|  | 325                      base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | 
|  | 326                                 base::Unretained(this))); | 
|  | 327 | 
|  | 328   handler_->StopOngoingDumps( | 
|  | 329       base::Bind(&WebRtcRtpDumpHandlerTest::OnStopOngoingDumpsFinished, | 
|  | 330                  base::Unretained(this))); | 
|  | 331 | 
|  | 332   base::RunLoop().RunUntilIdle(); | 
|  | 333 | 
|  | 334   WebRtcRtpDumpHandler::ReleasedDumps dumps(handler_->ReleaseDumps()); | 
|  | 335   EXPECT_FALSE(dumps.incoming_dump_path.empty()); | 
|  | 336   EXPECT_FALSE(dumps.outgoing_dump_path.empty()); | 
|  | 337 } | 
|  | 338 | 
|  | 339 TEST_F(WebRtcRtpDumpHandlerTest, StopOngoingDumpsWhileDumping) { | 
|  | 340   std::string error; | 
|  | 341   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error)); | 
|  | 342 | 
|  | 343   EXPECT_CALL(*this, OnStopOngoingDumpsFinished()); | 
|  | 344 | 
|  | 345   handler_->StopOngoingDumps( | 
|  | 346       base::Bind(&WebRtcRtpDumpHandlerTest::OnStopOngoingDumpsFinished, | 
|  | 347                  base::Unretained(this))); | 
|  | 348 | 
|  | 349   base::RunLoop().RunUntilIdle(); | 
|  | 350 | 
|  | 351   WebRtcRtpDumpHandler::ReleasedDumps dumps(handler_->ReleaseDumps()); | 
|  | 352   EXPECT_FALSE(dumps.incoming_dump_path.empty()); | 
|  | 353   EXPECT_FALSE(dumps.outgoing_dump_path.empty()); | 
|  | 354 } | 
|  | 355 | 
|  | 356 TEST_F(WebRtcRtpDumpHandlerTest, StopOngoingDumpsWhenAlreadyStopped) { | 
|  | 357   std::string error; | 
|  | 358   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error)); | 
|  | 359 | 
|  | 360   { | 
|  | 361     EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)); | 
|  | 362 | 
|  | 363     handler_->StopDump(RTP_DUMP_BOTH, | 
|  | 364                        base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | 
|  | 365                                   base::Unretained(this))); | 
|  | 366     base::RunLoop().RunUntilIdle(); | 
|  | 367   } | 
|  | 368 | 
|  | 369   EXPECT_CALL(*this, OnStopOngoingDumpsFinished()); | 
|  | 370   handler_->StopOngoingDumps( | 
|  | 371       base::Bind(&WebRtcRtpDumpHandlerTest::OnStopOngoingDumpsFinished, | 
|  | 372                  base::Unretained(this))); | 
|  | 373 } | 
|  | 374 | 
|  | 375 TEST_F(WebRtcRtpDumpHandlerTest, StopOngoingDumpsWhileStoppingOneDump) { | 
|  | 376   std::string error; | 
|  | 377   EXPECT_TRUE(handler_->StartDump(RTP_DUMP_BOTH, &error)); | 
|  | 378 | 
|  | 379   testing::InSequence s; | 
|  | 380   EXPECT_CALL(*this, OnStopDumpFinished(true, testing::_)); | 
|  | 381   EXPECT_CALL(*this, OnStopOngoingDumpsFinished()); | 
|  | 382 | 
|  | 383   handler_->StopDump(RTP_DUMP_INCOMING, | 
|  | 384                      base::Bind(&WebRtcRtpDumpHandlerTest::OnStopDumpFinished, | 
|  | 385                                 base::Unretained(this))); | 
|  | 386 | 
|  | 387   handler_->StopOngoingDumps( | 
|  | 388       base::Bind(&WebRtcRtpDumpHandlerTest::OnStopOngoingDumpsFinished, | 
|  | 389                  base::Unretained(this))); | 
|  | 390 | 
|  | 391   base::RunLoop().RunUntilIdle(); | 
|  | 392 | 
|  | 393   WebRtcRtpDumpHandler::ReleasedDumps dumps(handler_->ReleaseDumps()); | 
|  | 394   EXPECT_FALSE(dumps.incoming_dump_path.empty()); | 
|  | 395   EXPECT_FALSE(dumps.outgoing_dump_path.empty()); | 
|  | 396 } | 
| OLD | NEW | 
|---|