Home | History | Annotate | Download | only in payload_consumer
      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 
     47 namespace chromeos_update_engine {
     48 
     49 using base::FilePath;
     50 using base::ReadFileToString;
     51 using base::WriteFile;
     52 using std::string;
     53 using std::unique_ptr;
     54 using std::vector;
     55 using test_utils::ScopedTempFile;
     56 using testing::AtLeast;
     57 using testing::InSequence;
     58 using testing::Return;
     59 using testing::_;
     60 
     61 class DownloadActionTest : public ::testing::Test { };
     62 
     63 namespace {
     64 
     65 class 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 
    104 class 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 
    122 void StartProcessorInRunLoop(ActionProcessor* processor,
    123                              MockHttpFetcher* http_fetcher) {
    124   processor->StartProcessing();
    125   http_fetcher->SetOffset(1);
    126 }
    127 
    128 void 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   // We pull off the first byte from data and seek past it.
    143   string hash = HashCalculator::HashOfBytes(&data[1], data.size() - 1);
    144   uint64_t size = data.size();
    145   InstallPlan install_plan;
    146   install_plan.payload_type = InstallPayloadType::kDelta;
    147   install_plan.payload_size = size;
    148   install_plan.payload_hash = 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(_, 1 + 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 
    203 TEST(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 
    212 TEST(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 
    224 TEST(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 
    236 TEST(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 
    245 namespace {
    246 class TerminateEarlyTestProcessorDelegate : public ActionProcessorDelegate {
    247  public:
    248   void ProcessingStopped(const ActionProcessor* processor) {
    249     brillo::MessageLoop::current()->BreakLoop();
    250   }
    251 };
    252 
    253 void TerminateEarlyTestStarter(ActionProcessor* processor) {
    254   processor->StartProcessing();
    255   CHECK(processor->IsRunning());
    256   processor->StopProcessing();
    257 }
    258 
    259 void 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     feeder_action.set_obj(install_plan);
    276     FakeSystemState fake_system_state_;
    277     MockPrefs prefs;
    278     DownloadAction download_action(
    279         &prefs,
    280         fake_system_state_.boot_control(),
    281         fake_system_state_.hardware(),
    282         &fake_system_state_,
    283         new MockHttpFetcher(data.data(), data.size(), nullptr));
    284     download_action.SetTestFileWriter(&writer);
    285     MockDownloadActionDelegate download_delegate;
    286     if (use_download_delegate) {
    287       download_action.set_delegate(&download_delegate);
    288       EXPECT_CALL(download_delegate, BytesReceived(_, _, _)).Times(0);
    289     }
    290     TerminateEarlyTestProcessorDelegate delegate;
    291     ActionProcessor processor;
    292     processor.set_delegate(&delegate);
    293     processor.EnqueueAction(&feeder_action);
    294     processor.EnqueueAction(&download_action);
    295     BondActions(&feeder_action, &download_action);
    296 
    297     loop.PostTask(FROM_HERE,
    298                   base::Bind(&TerminateEarlyTestStarter, &processor));
    299     loop.Run();
    300     EXPECT_FALSE(loop.PendingTasks());
    301   }
    302 
    303   // 1 or 0 chunks should have come through
    304   const off_t resulting_file_size(utils::FileSize(temp_file.path()));
    305   EXPECT_GE(resulting_file_size, 0);
    306   if (resulting_file_size != 0)
    307     EXPECT_EQ(kMockHttpFetcherChunkSize,
    308               static_cast<size_t>(resulting_file_size));
    309 }
    310 
    311 }  // namespace
    312 
    313 TEST(DownloadActionTest, TerminateEarlyTest) {
    314   TestTerminateEarly(true);
    315 }
    316 
    317 TEST(DownloadActionTest, TerminateEarlyNoDownloadDelegateTest) {
    318   TestTerminateEarly(false);
    319 }
    320 
    321 class DownloadActionTestAction;
    322 
    323 template<>
    324 class ActionTraits<DownloadActionTestAction> {
    325  public:
    326   typedef InstallPlan OutputObjectType;
    327   typedef InstallPlan InputObjectType;
    328 };
    329 
    330 // This is a simple Action class for testing.
    331 class DownloadActionTestAction : public Action<DownloadActionTestAction> {
    332  public:
    333   DownloadActionTestAction() : did_run_(false) {}
    334   typedef InstallPlan InputObjectType;
    335   typedef InstallPlan OutputObjectType;
    336   ActionPipe<InstallPlan>* in_pipe() { return in_pipe_.get(); }
    337   ActionPipe<InstallPlan>* out_pipe() { return out_pipe_.get(); }
    338   ActionProcessor* processor() { return processor_; }
    339   void PerformAction() {
    340     did_run_ = true;
    341     ASSERT_TRUE(HasInputObject());
    342     EXPECT_TRUE(expected_input_object_ == GetInputObject());
    343     ASSERT_TRUE(processor());
    344     processor()->ActionComplete(this, ErrorCode::kSuccess);
    345   }
    346   string Type() const { return "DownloadActionTestAction"; }
    347   InstallPlan expected_input_object_;
    348   bool did_run_;
    349 };
    350 
    351 namespace {
    352 // This class is an ActionProcessorDelegate that simply terminates the
    353 // run loop when the ActionProcessor has completed processing. It's used
    354 // only by the test PassObjectOutTest.
    355 class PassObjectOutTestProcessorDelegate : public ActionProcessorDelegate {
    356  public:
    357   void ProcessingDone(const ActionProcessor* processor, ErrorCode code) {
    358     brillo::MessageLoop::current()->BreakLoop();
    359   }
    360 };
    361 
    362 }  // namespace
    363 
    364 TEST(DownloadActionTest, PassObjectOutTest) {
    365   brillo::FakeMessageLoop loop(nullptr);
    366   loop.SetAsCurrent();
    367 
    368   DirectFileWriter writer;
    369   EXPECT_EQ(0, writer.Open("/dev/null", O_WRONLY | O_CREAT, 0));
    370 
    371   // takes ownership of passed in HttpFetcher
    372   InstallPlan install_plan;
    373   install_plan.payload_size = 1;
    374   install_plan.payload_hash = HashCalculator::HashOfString("x");
    375   ObjectFeederAction<InstallPlan> feeder_action;
    376   feeder_action.set_obj(install_plan);
    377   MockPrefs prefs;
    378   FakeSystemState fake_system_state_;
    379   DownloadAction download_action(&prefs,
    380                                  fake_system_state_.boot_control(),
    381                                  fake_system_state_.hardware(),
    382                                  &fake_system_state_,
    383                                  new MockHttpFetcher("x", 1, nullptr));
    384   download_action.SetTestFileWriter(&writer);
    385 
    386   DownloadActionTestAction test_action;
    387   test_action.expected_input_object_ = install_plan;
    388   BondActions(&feeder_action, &download_action);
    389   BondActions(&download_action, &test_action);
    390 
    391   ActionProcessor processor;
    392   PassObjectOutTestProcessorDelegate delegate;
    393   processor.set_delegate(&delegate);
    394   processor.EnqueueAction(&feeder_action);
    395   processor.EnqueueAction(&download_action);
    396   processor.EnqueueAction(&test_action);
    397 
    398   loop.PostTask(FROM_HERE,
    399                 base::Bind([&processor] { processor.StartProcessing(); }));
    400   loop.Run();
    401   EXPECT_FALSE(loop.PendingTasks());
    402 
    403   EXPECT_EQ(true, test_action.did_run_);
    404 }
    405 
    406 // Test fixture for P2P tests.
    407 class P2PDownloadActionTest : public testing::Test {
    408  protected:
    409   P2PDownloadActionTest()
    410     : start_at_offset_(0),
    411       fake_um_(fake_system_state_.fake_clock()) {}
    412 
    413   ~P2PDownloadActionTest() override {}
    414 
    415   // Derived from testing::Test.
    416   void SetUp() override {
    417     loop_.SetAsCurrent();
    418   }
    419 
    420   // Derived from testing::Test.
    421   void TearDown() override {
    422     EXPECT_FALSE(loop_.PendingTasks());
    423   }
    424 
    425   // To be called by tests to setup the download. The
    426   // |starting_offset| parameter is for where to resume.
    427   void SetupDownload(off_t starting_offset) {
    428     start_at_offset_ = starting_offset;
    429     // Prepare data 10 kB of data.
    430     data_.clear();
    431     for (unsigned int i = 0; i < 10 * 1000; i++)
    432       data_ += 'a' + (i % 25);
    433 
    434     // Setup p2p.
    435     FakeP2PManagerConfiguration *test_conf = new FakeP2PManagerConfiguration();
    436     p2p_manager_.reset(P2PManager::Construct(
    437         test_conf, nullptr, &fake_um_, "cros_au", 3,
    438         base::TimeDelta::FromDays(5)));
    439     fake_system_state_.set_p2p_manager(p2p_manager_.get());
    440   }
    441 
    442   // To be called by tests to perform the download. The
    443   // |use_p2p_to_share| parameter is used to indicate whether the
    444   // payload should be shared via p2p.
    445   void StartDownload(bool use_p2p_to_share) {
    446     EXPECT_CALL(*fake_system_state_.mock_payload_state(),
    447                 GetUsingP2PForSharing())
    448         .WillRepeatedly(Return(use_p2p_to_share));
    449 
    450     ScopedTempFile output_temp_file;
    451     TestDirectFileWriter writer;
    452     EXPECT_EQ(
    453         0, writer.Open(output_temp_file.path().c_str(), O_WRONLY | O_CREAT, 0));
    454     InstallPlan install_plan;
    455     install_plan.payload_size = data_.length();
    456     install_plan.payload_hash = "1234hash";
    457     ObjectFeederAction<InstallPlan> feeder_action;
    458     feeder_action.set_obj(install_plan);
    459     MockPrefs prefs;
    460     http_fetcher_ = new MockHttpFetcher(data_.c_str(),
    461                                         data_.length(),
    462                                         nullptr);
    463     // Note that DownloadAction takes ownership of the passed in HttpFetcher.
    464     download_action_.reset(new DownloadAction(&prefs,
    465                                               fake_system_state_.boot_control(),
    466                                               fake_system_state_.hardware(),
    467                                               &fake_system_state_,
    468                                               http_fetcher_));
    469     download_action_->SetTestFileWriter(&writer);
    470     BondActions(&feeder_action, download_action_.get());
    471     DownloadActionTestProcessorDelegate delegate(ErrorCode::kSuccess);
    472     delegate.expected_data_ = brillo::Blob(data_.begin() + start_at_offset_,
    473                                            data_.end());
    474     delegate.path_ = output_temp_file.path();
    475     processor_.set_delegate(&delegate);
    476     processor_.EnqueueAction(&feeder_action);
    477     processor_.EnqueueAction(download_action_.get());
    478 
    479     loop_.PostTask(FROM_HERE, base::Bind(
    480         &P2PDownloadActionTest::StartProcessorInRunLoopForP2P,
    481         base::Unretained(this)));
    482     loop_.Run();
    483   }
    484 
    485   // Mainloop used to make StartDownload() synchronous.
    486   brillo::FakeMessageLoop loop_{nullptr};
    487 
    488   // The DownloadAction instance under test.
    489   unique_ptr<DownloadAction> download_action_;
    490 
    491   // The HttpFetcher used in the test.
    492   MockHttpFetcher* http_fetcher_;
    493 
    494   // The P2PManager used in the test.
    495   unique_ptr<P2PManager> p2p_manager_;
    496 
    497   // The ActionProcessor used for running the actions.
    498   ActionProcessor processor_;
    499 
    500   // A fake system state.
    501   FakeSystemState fake_system_state_;
    502 
    503   // The data being downloaded.
    504   string data_;
    505 
    506  private:
    507   // Callback used in StartDownload() method.
    508   void StartProcessorInRunLoopForP2P() {
    509     processor_.StartProcessing();
    510     http_fetcher_->SetOffset(start_at_offset_);
    511   }
    512 
    513   // The requested starting offset passed to SetupDownload().
    514   off_t start_at_offset_;
    515 
    516   chromeos_update_manager::FakeUpdateManager fake_um_;
    517 };
    518 
    519 TEST_F(P2PDownloadActionTest, IsWrittenTo) {
    520   if (!test_utils::IsXAttrSupported(FilePath("/tmp"))) {
    521     LOG(WARNING) << "Skipping test because /tmp does not support xattr. "
    522                  << "Please update your system to support this feature.";
    523     return;
    524   }
    525 
    526   SetupDownload(0);     // starting_offset
    527   StartDownload(true);  // use_p2p_to_share
    528 
    529   // Check the p2p file and its content matches what was sent.
    530   string file_id = download_action_->p2p_file_id();
    531   EXPECT_NE("", file_id);
    532   EXPECT_EQ(static_cast<int>(data_.length()),
    533             p2p_manager_->FileGetSize(file_id));
    534   EXPECT_EQ(static_cast<int>(data_.length()),
    535             p2p_manager_->FileGetExpectedSize(file_id));
    536   string p2p_file_contents;
    537   EXPECT_TRUE(ReadFileToString(p2p_manager_->FileGetPath(file_id),
    538                                &p2p_file_contents));
    539   EXPECT_EQ(data_, p2p_file_contents);
    540 }
    541 
    542 TEST_F(P2PDownloadActionTest, DeleteIfHoleExists) {
    543   if (!test_utils::IsXAttrSupported(FilePath("/tmp"))) {
    544     LOG(WARNING) << "Skipping test because /tmp does not support xattr. "
    545                  << "Please update your system to support this feature.";
    546     return;
    547   }
    548 
    549   SetupDownload(1000);  // starting_offset
    550   StartDownload(true);  // use_p2p_to_share
    551 
    552   // DownloadAction should convey that the file is not being shared.
    553   // and that we don't have any p2p files.
    554   EXPECT_EQ(download_action_->p2p_file_id(), "");
    555   EXPECT_EQ(p2p_manager_->CountSharedFiles(), 0);
    556 }
    557 
    558 TEST_F(P2PDownloadActionTest, CanAppend) {
    559   if (!test_utils::IsXAttrSupported(FilePath("/tmp"))) {
    560     LOG(WARNING) << "Skipping test because /tmp does not support xattr. "
    561                  << "Please update your system to support this feature.";
    562     return;
    563   }
    564 
    565   SetupDownload(1000);  // starting_offset
    566 
    567   // Prepare the file with existing data before starting to write to
    568   // it via DownloadAction.
    569   string file_id = utils::CalculateP2PFileId("1234hash", data_.length());
    570   ASSERT_TRUE(p2p_manager_->FileShare(file_id, data_.length()));
    571   string existing_data;
    572   for (unsigned int i = 0; i < 1000; i++)
    573     existing_data += '0' + (i % 10);
    574   ASSERT_EQ(WriteFile(p2p_manager_->FileGetPath(file_id), existing_data.c_str(),
    575                       1000), 1000);
    576 
    577   StartDownload(true);  // use_p2p_to_share
    578 
    579   // DownloadAction should convey the same file_id and the file should
    580   // have the expected size.
    581   EXPECT_EQ(download_action_->p2p_file_id(), file_id);
    582   EXPECT_EQ(static_cast<ssize_t>(data_.length()),
    583             p2p_manager_->FileGetSize(file_id));
    584   EXPECT_EQ(static_cast<ssize_t>(data_.length()),
    585             p2p_manager_->FileGetExpectedSize(file_id));
    586   string p2p_file_contents;
    587   // Check that the first 1000 bytes wasn't touched and that we
    588   // appended the remaining as appropriate.
    589   EXPECT_TRUE(ReadFileToString(p2p_manager_->FileGetPath(file_id),
    590                                &p2p_file_contents));
    591   EXPECT_EQ(existing_data, p2p_file_contents.substr(0, 1000));
    592   EXPECT_EQ(data_.substr(1000), p2p_file_contents.substr(1000));
    593 }
    594 
    595 TEST_F(P2PDownloadActionTest, DeletePartialP2PFileIfResumingWithoutP2P) {
    596   if (!test_utils::IsXAttrSupported(FilePath("/tmp"))) {
    597     LOG(WARNING) << "Skipping test because /tmp does not support xattr. "
    598                  << "Please update your system to support this feature.";
    599     return;
    600   }
    601 
    602   SetupDownload(1000);  // starting_offset
    603 
    604   // Prepare the file with all existing data before starting to write
    605   // to it via DownloadAction.
    606   string file_id = utils::CalculateP2PFileId("1234hash", data_.length());
    607   ASSERT_TRUE(p2p_manager_->FileShare(file_id, data_.length()));
    608   string existing_data;
    609   for (unsigned int i = 0; i < 1000; i++)
    610     existing_data += '0' + (i % 10);
    611   ASSERT_EQ(WriteFile(p2p_manager_->FileGetPath(file_id), existing_data.c_str(),
    612                       1000), 1000);
    613 
    614   // Check that the file is there.
    615   EXPECT_EQ(1000, p2p_manager_->FileGetSize(file_id));
    616   EXPECT_EQ(1, p2p_manager_->CountSharedFiles());
    617 
    618   StartDownload(false);  // use_p2p_to_share
    619 
    620   // DownloadAction should have deleted the p2p file. Check that it's gone.
    621   EXPECT_EQ(-1, p2p_manager_->FileGetSize(file_id));
    622   EXPECT_EQ(0, p2p_manager_->CountSharedFiles());
    623 }
    624 
    625 }  // namespace chromeos_update_engine
    626