1// 2// Copyright (C) 2011 The Android Open Source Project 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// http://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15// 16 17#include "update_engine/payload_consumer/download_action.h" 18 19#include <gmock/gmock.h> 20#include <gtest/gtest.h> 21 22#include <memory> 23#include <string> 24#include <utility> 25#include <vector> 26 27#include <base/bind.h> 28#include <base/files/file_path.h> 29#include <base/files/file_util.h> 30#include <base/location.h> 31#include <base/strings/stringprintf.h> 32#include <brillo/bind_lambda.h> 33#include <brillo/message_loops/fake_message_loop.h> 34#include <brillo/message_loops/message_loop.h> 35 36#include "update_engine/common/action_pipe.h" 37#include "update_engine/common/hash_calculator.h" 38#include "update_engine/common/mock_http_fetcher.h" 39#include "update_engine/common/mock_prefs.h" 40#include "update_engine/common/test_utils.h" 41#include "update_engine/common/utils.h" 42#include "update_engine/fake_p2p_manager_configuration.h" 43#include "update_engine/fake_system_state.h" 44#include "update_engine/payload_consumer/mock_download_action.h" 45#include "update_engine/update_manager/fake_update_manager.h" 46 47namespace chromeos_update_engine { 48 49using base::FilePath; 50using base::ReadFileToString; 51using base::WriteFile; 52using std::string; 53using std::unique_ptr; 54using std::vector; 55using test_utils::ScopedTempFile; 56using testing::AtLeast; 57using testing::InSequence; 58using testing::Return; 59using testing::_; 60 61class DownloadActionTest : public ::testing::Test { }; 62 63namespace { 64 65class DownloadActionTestProcessorDelegate : public ActionProcessorDelegate { 66 public: 67 explicit DownloadActionTestProcessorDelegate(ErrorCode expected_code) 68 : processing_done_called_(false), 69 expected_code_(expected_code) {} 70 ~DownloadActionTestProcessorDelegate() override { 71 EXPECT_TRUE(processing_done_called_); 72 } 73 void ProcessingDone(const ActionProcessor* processor, 74 ErrorCode code) override { 75 brillo::MessageLoop::current()->BreakLoop(); 76 brillo::Blob found_data; 77 ASSERT_TRUE(utils::ReadFile(path_, &found_data)); 78 if (expected_code_ != ErrorCode::kDownloadWriteError) { 79 ASSERT_EQ(expected_data_.size(), found_data.size()); 80 for (unsigned i = 0; i < expected_data_.size(); i++) { 81 EXPECT_EQ(expected_data_[i], found_data[i]); 82 } 83 } 84 processing_done_called_ = true; 85 } 86 87 void ActionCompleted(ActionProcessor* processor, 88 AbstractAction* action, 89 ErrorCode code) override { 90 const string type = action->Type(); 91 if (type == DownloadAction::StaticType()) { 92 EXPECT_EQ(expected_code_, code); 93 } else { 94 EXPECT_EQ(ErrorCode::kSuccess, code); 95 } 96 } 97 98 string path_; 99 brillo::Blob expected_data_; 100 bool processing_done_called_; 101 ErrorCode expected_code_; 102}; 103 104class TestDirectFileWriter : public DirectFileWriter { 105 public: 106 TestDirectFileWriter() : fail_write_(0), current_write_(0) {} 107 void set_fail_write(int fail_write) { fail_write_ = fail_write; } 108 109 virtual bool Write(const void* bytes, size_t count) { 110 if (++current_write_ == fail_write_) { 111 return false; 112 } 113 return DirectFileWriter::Write(bytes, count); 114 } 115 116 private: 117 // If positive, fail on the |fail_write_| call to Write. 118 int fail_write_; 119 int current_write_; 120}; 121 122void StartProcessorInRunLoop(ActionProcessor* processor, 123 MockHttpFetcher* http_fetcher) { 124 processor->StartProcessing(); 125 http_fetcher->SetOffset(1); 126} 127 128void TestWithData(const brillo::Blob& data, 129 int fail_write, 130 bool use_download_delegate) { 131 brillo::FakeMessageLoop loop(nullptr); 132 loop.SetAsCurrent(); 133 FakeSystemState fake_system_state; 134 135 // TODO(adlr): see if we need a different file for build bots 136 ScopedTempFile output_temp_file; 137 TestDirectFileWriter writer; 138 EXPECT_EQ( 139 0, writer.Open(output_temp_file.path().c_str(), O_WRONLY | O_CREAT, 0)); 140 writer.set_fail_write(fail_write); 141 142 uint64_t size = data.size() - 1; 143 InstallPlan install_plan; 144 install_plan.payloads.push_back( 145 {.size = size, .type = InstallPayloadType::kDelta}); 146 // We pull off the first byte from data and seek past it. 147 EXPECT_TRUE(HashCalculator::RawHashOfBytes( 148 &data[1], data.size() - 1, &install_plan.payloads[0].hash)); 149 install_plan.source_slot = 0; 150 install_plan.target_slot = 1; 151 // We mark both slots as bootable. Only the target slot should be unbootable 152 // after the download starts. 153 fake_system_state.fake_boot_control()->SetSlotBootable( 154 install_plan.source_slot, true); 155 fake_system_state.fake_boot_control()->SetSlotBootable( 156 install_plan.target_slot, true); 157 ObjectFeederAction<InstallPlan> feeder_action; 158 feeder_action.set_obj(install_plan); 159 MockPrefs prefs; 160 MockHttpFetcher* http_fetcher = new MockHttpFetcher(data.data(), 161 data.size(), 162 nullptr); 163 // takes ownership of passed in HttpFetcher 164 DownloadAction download_action(&prefs, 165 fake_system_state.boot_control(), 166 fake_system_state.hardware(), 167 &fake_system_state, 168 http_fetcher); 169 download_action.SetTestFileWriter(&writer); 170 BondActions(&feeder_action, &download_action); 171 MockDownloadActionDelegate download_delegate; 172 if (use_download_delegate) { 173 InSequence s; 174 download_action.set_delegate(&download_delegate); 175 if (data.size() > kMockHttpFetcherChunkSize) 176 EXPECT_CALL(download_delegate, 177 BytesReceived(_, kMockHttpFetcherChunkSize, _)); 178 EXPECT_CALL(download_delegate, BytesReceived(_, _, _)).Times(AtLeast(1)); 179 } 180 ErrorCode expected_code = ErrorCode::kSuccess; 181 if (fail_write > 0) 182 expected_code = ErrorCode::kDownloadWriteError; 183 DownloadActionTestProcessorDelegate delegate(expected_code); 184 delegate.expected_data_ = brillo::Blob(data.begin() + 1, data.end()); 185 delegate.path_ = output_temp_file.path(); 186 ActionProcessor processor; 187 processor.set_delegate(&delegate); 188 processor.EnqueueAction(&feeder_action); 189 processor.EnqueueAction(&download_action); 190 191 loop.PostTask(FROM_HERE, 192 base::Bind(&StartProcessorInRunLoop, &processor, http_fetcher)); 193 loop.Run(); 194 EXPECT_FALSE(loop.PendingTasks()); 195 196 EXPECT_TRUE(fake_system_state.fake_boot_control()->IsSlotBootable( 197 install_plan.source_slot)); 198 EXPECT_FALSE(fake_system_state.fake_boot_control()->IsSlotBootable( 199 install_plan.target_slot)); 200} 201} // namespace 202 203TEST(DownloadActionTest, SimpleTest) { 204 brillo::Blob small; 205 const char* foo = "foo"; 206 small.insert(small.end(), foo, foo + strlen(foo)); 207 TestWithData(small, 208 0, // fail_write 209 true); // use_download_delegate 210} 211 212TEST(DownloadActionTest, LargeTest) { 213 brillo::Blob big(5 * kMockHttpFetcherChunkSize); 214 char c = '0'; 215 for (unsigned int i = 0; i < big.size(); i++) { 216 big[i] = c; 217 c = ('9' == c) ? '0' : c + 1; 218 } 219 TestWithData(big, 220 0, // fail_write 221 true); // use_download_delegate 222} 223 224TEST(DownloadActionTest, FailWriteTest) { 225 brillo::Blob big(5 * kMockHttpFetcherChunkSize); 226 char c = '0'; 227 for (unsigned int i = 0; i < big.size(); i++) { 228 big[i] = c; 229 c = ('9' == c) ? '0' : c + 1; 230 } 231 TestWithData(big, 232 2, // fail_write 233 true); // use_download_delegate 234} 235 236TEST(DownloadActionTest, NoDownloadDelegateTest) { 237 brillo::Blob small; 238 const char* foo = "foofoo"; 239 small.insert(small.end(), foo, foo + strlen(foo)); 240 TestWithData(small, 241 0, // fail_write 242 false); // use_download_delegate 243} 244 245namespace { 246class TerminateEarlyTestProcessorDelegate : public ActionProcessorDelegate { 247 public: 248 void ProcessingStopped(const ActionProcessor* processor) { 249 brillo::MessageLoop::current()->BreakLoop(); 250 } 251}; 252 253void TerminateEarlyTestStarter(ActionProcessor* processor) { 254 processor->StartProcessing(); 255 CHECK(processor->IsRunning()); 256 processor->StopProcessing(); 257} 258 259void TestTerminateEarly(bool use_download_delegate) { 260 brillo::FakeMessageLoop loop(nullptr); 261 loop.SetAsCurrent(); 262 263 brillo::Blob data(kMockHttpFetcherChunkSize + 264 kMockHttpFetcherChunkSize / 2); 265 memset(data.data(), 0, data.size()); 266 267 ScopedTempFile temp_file; 268 { 269 DirectFileWriter writer; 270 EXPECT_EQ(0, writer.Open(temp_file.path().c_str(), O_WRONLY | O_CREAT, 0)); 271 272 // takes ownership of passed in HttpFetcher 273 ObjectFeederAction<InstallPlan> feeder_action; 274 InstallPlan install_plan; 275 install_plan.payloads.resize(1); 276 feeder_action.set_obj(install_plan); 277 FakeSystemState fake_system_state_; 278 MockPrefs prefs; 279 DownloadAction download_action( 280 &prefs, 281 fake_system_state_.boot_control(), 282 fake_system_state_.hardware(), 283 &fake_system_state_, 284 new MockHttpFetcher(data.data(), data.size(), nullptr)); 285 download_action.SetTestFileWriter(&writer); 286 MockDownloadActionDelegate download_delegate; 287 if (use_download_delegate) { 288 download_action.set_delegate(&download_delegate); 289 EXPECT_CALL(download_delegate, BytesReceived(_, _, _)).Times(0); 290 } 291 TerminateEarlyTestProcessorDelegate delegate; 292 ActionProcessor processor; 293 processor.set_delegate(&delegate); 294 processor.EnqueueAction(&feeder_action); 295 processor.EnqueueAction(&download_action); 296 BondActions(&feeder_action, &download_action); 297 298 loop.PostTask(FROM_HERE, 299 base::Bind(&TerminateEarlyTestStarter, &processor)); 300 loop.Run(); 301 EXPECT_FALSE(loop.PendingTasks()); 302 } 303 304 // 1 or 0 chunks should have come through 305 const off_t resulting_file_size(utils::FileSize(temp_file.path())); 306 EXPECT_GE(resulting_file_size, 0); 307 if (resulting_file_size != 0) 308 EXPECT_EQ(kMockHttpFetcherChunkSize, 309 static_cast<size_t>(resulting_file_size)); 310} 311 312} // namespace 313 314TEST(DownloadActionTest, TerminateEarlyTest) { 315 TestTerminateEarly(true); 316} 317 318TEST(DownloadActionTest, TerminateEarlyNoDownloadDelegateTest) { 319 TestTerminateEarly(false); 320} 321 322class DownloadActionTestAction; 323 324template<> 325class ActionTraits<DownloadActionTestAction> { 326 public: 327 typedef InstallPlan OutputObjectType; 328 typedef InstallPlan InputObjectType; 329}; 330 331// This is a simple Action class for testing. 332class DownloadActionTestAction : public Action<DownloadActionTestAction> { 333 public: 334 DownloadActionTestAction() : did_run_(false) {} 335 typedef InstallPlan InputObjectType; 336 typedef InstallPlan OutputObjectType; 337 ActionPipe<InstallPlan>* in_pipe() { return in_pipe_.get(); } 338 ActionPipe<InstallPlan>* out_pipe() { return out_pipe_.get(); } 339 ActionProcessor* processor() { return processor_; } 340 void PerformAction() { 341 did_run_ = true; 342 ASSERT_TRUE(HasInputObject()); 343 EXPECT_TRUE(expected_input_object_ == GetInputObject()); 344 ASSERT_TRUE(processor()); 345 processor()->ActionComplete(this, ErrorCode::kSuccess); 346 } 347 string Type() const { return "DownloadActionTestAction"; } 348 InstallPlan expected_input_object_; 349 bool did_run_; 350}; 351 352namespace { 353// This class is an ActionProcessorDelegate that simply terminates the 354// run loop when the ActionProcessor has completed processing. It's used 355// only by the test PassObjectOutTest. 356class PassObjectOutTestProcessorDelegate : public ActionProcessorDelegate { 357 public: 358 void ProcessingDone(const ActionProcessor* processor, ErrorCode code) { 359 brillo::MessageLoop::current()->BreakLoop(); 360 } 361}; 362 363} // namespace 364 365TEST(DownloadActionTest, PassObjectOutTest) { 366 brillo::FakeMessageLoop loop(nullptr); 367 loop.SetAsCurrent(); 368 369 DirectFileWriter writer; 370 EXPECT_EQ(0, writer.Open("/dev/null", O_WRONLY | O_CREAT, 0)); 371 372 // takes ownership of passed in HttpFetcher 373 InstallPlan install_plan; 374 install_plan.payloads.push_back({.size = 1}); 375 EXPECT_TRUE( 376 HashCalculator::RawHashOfData({'x'}, &install_plan.payloads[0].hash)); 377 ObjectFeederAction<InstallPlan> feeder_action; 378 feeder_action.set_obj(install_plan); 379 MockPrefs prefs; 380 FakeSystemState fake_system_state_; 381 DownloadAction download_action(&prefs, 382 fake_system_state_.boot_control(), 383 fake_system_state_.hardware(), 384 &fake_system_state_, 385 new MockHttpFetcher("x", 1, nullptr)); 386 download_action.SetTestFileWriter(&writer); 387 388 DownloadActionTestAction test_action; 389 test_action.expected_input_object_ = install_plan; 390 BondActions(&feeder_action, &download_action); 391 BondActions(&download_action, &test_action); 392 393 ActionProcessor processor; 394 PassObjectOutTestProcessorDelegate delegate; 395 processor.set_delegate(&delegate); 396 processor.EnqueueAction(&feeder_action); 397 processor.EnqueueAction(&download_action); 398 processor.EnqueueAction(&test_action); 399 400 loop.PostTask( 401 FROM_HERE, 402 base::Bind( 403 [](ActionProcessor* processor) { processor->StartProcessing(); }, 404 base::Unretained(&processor))); 405 loop.Run(); 406 EXPECT_FALSE(loop.PendingTasks()); 407 408 EXPECT_EQ(true, test_action.did_run_); 409} 410 411// Test fixture for P2P tests. 412class P2PDownloadActionTest : public testing::Test { 413 protected: 414 P2PDownloadActionTest() 415 : start_at_offset_(0), 416 fake_um_(fake_system_state_.fake_clock()) {} 417 418 ~P2PDownloadActionTest() override {} 419 420 // Derived from testing::Test. 421 void SetUp() override { 422 loop_.SetAsCurrent(); 423 } 424 425 // Derived from testing::Test. 426 void TearDown() override { 427 EXPECT_FALSE(loop_.PendingTasks()); 428 } 429 430 // To be called by tests to setup the download. The 431 // |starting_offset| parameter is for where to resume. 432 void SetupDownload(off_t starting_offset) { 433 start_at_offset_ = starting_offset; 434 // Prepare data 10 kB of data. 435 data_.clear(); 436 for (unsigned int i = 0; i < 10 * 1000; i++) 437 data_ += 'a' + (i % 25); 438 439 // Setup p2p. 440 FakeP2PManagerConfiguration *test_conf = new FakeP2PManagerConfiguration(); 441 p2p_manager_.reset(P2PManager::Construct( 442 test_conf, nullptr, &fake_um_, "cros_au", 3, 443 base::TimeDelta::FromDays(5))); 444 fake_system_state_.set_p2p_manager(p2p_manager_.get()); 445 } 446 447 // To be called by tests to perform the download. The 448 // |use_p2p_to_share| parameter is used to indicate whether the 449 // payload should be shared via p2p. 450 void StartDownload(bool use_p2p_to_share) { 451 EXPECT_CALL(*fake_system_state_.mock_payload_state(), 452 GetUsingP2PForSharing()) 453 .WillRepeatedly(Return(use_p2p_to_share)); 454 455 ScopedTempFile output_temp_file; 456 TestDirectFileWriter writer; 457 EXPECT_EQ( 458 0, writer.Open(output_temp_file.path().c_str(), O_WRONLY | O_CREAT, 0)); 459 InstallPlan install_plan; 460 install_plan.payloads.push_back( 461 {.size = data_.length(), 462 .hash = {'1', '2', '3', '4', 'h', 'a', 's', 'h'}}); 463 ObjectFeederAction<InstallPlan> feeder_action; 464 feeder_action.set_obj(install_plan); 465 MockPrefs prefs; 466 http_fetcher_ = new MockHttpFetcher(data_.c_str(), 467 data_.length(), 468 nullptr); 469 // Note that DownloadAction takes ownership of the passed in HttpFetcher. 470 download_action_.reset(new DownloadAction(&prefs, 471 fake_system_state_.boot_control(), 472 fake_system_state_.hardware(), 473 &fake_system_state_, 474 http_fetcher_)); 475 download_action_->SetTestFileWriter(&writer); 476 BondActions(&feeder_action, download_action_.get()); 477 DownloadActionTestProcessorDelegate delegate(ErrorCode::kSuccess); 478 delegate.expected_data_ = brillo::Blob(data_.begin() + start_at_offset_, 479 data_.end()); 480 delegate.path_ = output_temp_file.path(); 481 processor_.set_delegate(&delegate); 482 processor_.EnqueueAction(&feeder_action); 483 processor_.EnqueueAction(download_action_.get()); 484 485 loop_.PostTask(FROM_HERE, base::Bind( 486 &P2PDownloadActionTest::StartProcessorInRunLoopForP2P, 487 base::Unretained(this))); 488 loop_.Run(); 489 } 490 491 // Mainloop used to make StartDownload() synchronous. 492 brillo::FakeMessageLoop loop_{nullptr}; 493 494 // The DownloadAction instance under test. 495 unique_ptr<DownloadAction> download_action_; 496 497 // The HttpFetcher used in the test. 498 MockHttpFetcher* http_fetcher_; 499 500 // The P2PManager used in the test. 501 unique_ptr<P2PManager> p2p_manager_; 502 503 // The ActionProcessor used for running the actions. 504 ActionProcessor processor_; 505 506 // A fake system state. 507 FakeSystemState fake_system_state_; 508 509 // The data being downloaded. 510 string data_; 511 512 private: 513 // Callback used in StartDownload() method. 514 void StartProcessorInRunLoopForP2P() { 515 processor_.StartProcessing(); 516 http_fetcher_->SetOffset(start_at_offset_); 517 } 518 519 // The requested starting offset passed to SetupDownload(). 520 off_t start_at_offset_; 521 522 chromeos_update_manager::FakeUpdateManager fake_um_; 523}; 524 525TEST_F(P2PDownloadActionTest, IsWrittenTo) { 526 if (!test_utils::IsXAttrSupported(FilePath("/tmp"))) { 527 LOG(WARNING) << "Skipping test because /tmp does not support xattr. " 528 << "Please update your system to support this feature."; 529 return; 530 } 531 532 SetupDownload(0); // starting_offset 533 StartDownload(true); // use_p2p_to_share 534 535 // Check the p2p file and its content matches what was sent. 536 string file_id = download_action_->p2p_file_id(); 537 EXPECT_NE("", file_id); 538 EXPECT_EQ(static_cast<int>(data_.length()), 539 p2p_manager_->FileGetSize(file_id)); 540 EXPECT_EQ(static_cast<int>(data_.length()), 541 p2p_manager_->FileGetExpectedSize(file_id)); 542 string p2p_file_contents; 543 EXPECT_TRUE(ReadFileToString(p2p_manager_->FileGetPath(file_id), 544 &p2p_file_contents)); 545 EXPECT_EQ(data_, p2p_file_contents); 546} 547 548TEST_F(P2PDownloadActionTest, DeleteIfHoleExists) { 549 if (!test_utils::IsXAttrSupported(FilePath("/tmp"))) { 550 LOG(WARNING) << "Skipping test because /tmp does not support xattr. " 551 << "Please update your system to support this feature."; 552 return; 553 } 554 555 SetupDownload(1000); // starting_offset 556 StartDownload(true); // use_p2p_to_share 557 558 // DownloadAction should convey that the file is not being shared. 559 // and that we don't have any p2p files. 560 EXPECT_EQ(download_action_->p2p_file_id(), ""); 561 EXPECT_EQ(p2p_manager_->CountSharedFiles(), 0); 562} 563 564TEST_F(P2PDownloadActionTest, CanAppend) { 565 if (!test_utils::IsXAttrSupported(FilePath("/tmp"))) { 566 LOG(WARNING) << "Skipping test because /tmp does not support xattr. " 567 << "Please update your system to support this feature."; 568 return; 569 } 570 571 SetupDownload(1000); // starting_offset 572 573 // Prepare the file with existing data before starting to write to 574 // it via DownloadAction. 575 string file_id = utils::CalculateP2PFileId( 576 {'1', '2', '3', '4', 'h', 'a', 's', 'h'}, data_.length()); 577 ASSERT_TRUE(p2p_manager_->FileShare(file_id, data_.length())); 578 string existing_data; 579 for (unsigned int i = 0; i < 1000; i++) 580 existing_data += '0' + (i % 10); 581 ASSERT_EQ(WriteFile(p2p_manager_->FileGetPath(file_id), existing_data.c_str(), 582 1000), 1000); 583 584 StartDownload(true); // use_p2p_to_share 585 586 // DownloadAction should convey the same file_id and the file should 587 // have the expected size. 588 EXPECT_EQ(download_action_->p2p_file_id(), file_id); 589 EXPECT_EQ(static_cast<ssize_t>(data_.length()), 590 p2p_manager_->FileGetSize(file_id)); 591 EXPECT_EQ(static_cast<ssize_t>(data_.length()), 592 p2p_manager_->FileGetExpectedSize(file_id)); 593 string p2p_file_contents; 594 // Check that the first 1000 bytes wasn't touched and that we 595 // appended the remaining as appropriate. 596 EXPECT_TRUE(ReadFileToString(p2p_manager_->FileGetPath(file_id), 597 &p2p_file_contents)); 598 EXPECT_EQ(existing_data, p2p_file_contents.substr(0, 1000)); 599 EXPECT_EQ(data_.substr(1000), p2p_file_contents.substr(1000)); 600} 601 602TEST_F(P2PDownloadActionTest, DeletePartialP2PFileIfResumingWithoutP2P) { 603 if (!test_utils::IsXAttrSupported(FilePath("/tmp"))) { 604 LOG(WARNING) << "Skipping test because /tmp does not support xattr. " 605 << "Please update your system to support this feature."; 606 return; 607 } 608 609 SetupDownload(1000); // starting_offset 610 611 // Prepare the file with all existing data before starting to write 612 // to it via DownloadAction. 613 string file_id = utils::CalculateP2PFileId( 614 {'1', '2', '3', '4', 'h', 'a', 's', 'h'}, data_.length()); 615 ASSERT_TRUE(p2p_manager_->FileShare(file_id, data_.length())); 616 string existing_data; 617 for (unsigned int i = 0; i < 1000; i++) 618 existing_data += '0' + (i % 10); 619 ASSERT_EQ(WriteFile(p2p_manager_->FileGetPath(file_id), existing_data.c_str(), 620 1000), 1000); 621 622 // Check that the file is there. 623 EXPECT_EQ(1000, p2p_manager_->FileGetSize(file_id)); 624 EXPECT_EQ(1, p2p_manager_->CountSharedFiles()); 625 626 StartDownload(false); // use_p2p_to_share 627 628 // DownloadAction should have deleted the p2p file. Check that it's gone. 629 EXPECT_EQ(-1, p2p_manager_->FileGetSize(file_id)); 630 EXPECT_EQ(0, p2p_manager_->CountSharedFiles()); 631} 632 633} // namespace chromeos_update_engine 634