Coverage for /Syzygy/ar/ar_transform.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
80.6%58720.C++source

Line-by-line coverage:

   1    :  // Copyright 2014 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  
  15    :  #include "syzygy/ar/ar_transform.h"
  16    :  
  17    :  #include "base/bind.h"
  18    :  #include "base/logging.h"
  19    :  #include "base/files/file_util.h"
  20    :  #include "base/memory/scoped_vector.h"
  21    :  #include "base/strings/stringprintf.h"
  22    :  #include "syzygy/ar/ar_reader.h"
  23    :  #include "syzygy/ar/ar_writer.h"
  24    :  
  25    :  namespace ar {
  26    :  
  27    :  namespace {
  28    :  
  29    :  // Helper struct to delete a file when this object goes out of scope.
  30    :  struct FileDeleter {
  31  E :    explicit FileDeleter(const base::FilePath& path) : path_(path) {
  32  E :    }
  33    :  
  34  E :    ~FileDeleter() {
  35  E :      if (!base::DeleteFile(path_, false))
  36  i :        LOG(WARNING) << "Unable to delete file: " << path_.value();
  37  E :    }
  38    :  
  39    :    const base::FilePath& path_;
  40    :  };
  41    :  
  42    :  }  // namespace
  43    :  
  44  E :  bool ArTransform::Transform() {
  45  E :    DCHECK(!input_archive_.empty());
  46  E :    DCHECK(!output_archive_.empty());
  47  E :    DCHECK(!callback_.is_null());
  48    :  
  49  E :    ArReader reader;
  50  E :    if (!reader.Init(input_archive_))
  51  E :      return false;
  52  E :    LOG(INFO) << "Read " << reader.symbols().size() << " symbols.";
  53    :  
  54    :    // This collection of buffers must outlive the ArWriter below.
  55  E :    ScopedVector<DataBuffer> buffers;
  56    :  
  57    :    // Iterate over the files in the archive.
  58  E :    ArWriter writer;
  59  E :    for (size_t i = 0; i < reader.offsets().size(); ++i) {
  60    :      // Extract the next file.
  61  E :      ParsedArFileHeader header;
  62  E :      scoped_ptr<DataBuffer> buffer(new DataBuffer());
  63  E :      if (!reader.ExtractNext(&header, buffer.get()))
  64  i :        return false;
  65    :  
  66  E :      LOG(INFO) << "Processing file " << (i + 1) << " of "
  67    :                << reader.offsets().size() << ": " << header.name;
  68    :  
  69    :      // Apply the transform to this file.
  70  E :      bool remove = false;
  71  E :      if (!callback_.Run(&header, buffer.get(), &remove))
  72  E :        return false;
  73    :  
  74  E :      if (remove)
  75  E :        continue;
  76    :  
  77    :      // Add the transformed file to the output archive.
  78    :      if (!writer.AddFile(header.name, header.timestamp, header.mode,
  79  E :                          buffer.get())) {
  80  i :        return false;
  81    :      }
  82    :  
  83    :      // Save the buffer so we keep it around until the writer has finished.
  84  E :      buffers.push_back(buffer.release());
  85  E :    }
  86    :  
  87  E :    if (!writer.Write(output_archive_))
  88  i :      return false;
  89  E :    LOG(INFO) << "Wrote " << writer.symbols().size() << " symbols.";
  90    :  
  91  E :    return true;
  92  E :  }
  93    :  
  94    :  OnDiskArTransformAdapter::OnDiskArTransformAdapter(
  95    :      TransformFileOnDiskCallback inner_callback)
  96    :      : inner_callback_(inner_callback),
  97    :        outer_callback_(base::Bind(&OnDiskArTransformAdapter::Transform,
  98    :                                   base::Unretained(this))),
  99  E :        index_(0) {
 100  E :  }
 101    :  
 102  E :  OnDiskArTransformAdapter::~OnDiskArTransformAdapter() {
 103  E :    if (!base::DeleteFile(temp_dir_, true)) {
 104  i :      LOG(WARNING) << "Unable to delete temporary directory: "
 105    :                   << temp_dir_.value();
 106    :    }
 107  E :  }
 108    :  
 109    :  bool OnDiskArTransformAdapter::Transform(ParsedArFileHeader* header,
 110    :                                           DataBuffer* contents,
 111  E :                                           bool* remove) {
 112  E :    if (temp_dir_.empty()) {
 113    :      if (!base::CreateNewTempDirectory(L"OnDiskArTransformAdapter",
 114  E :                                             &temp_dir_)) {
 115  i :        LOG(ERROR) << "Unable to create temporary directory.";
 116  i :        return false;
 117    :      }
 118    :    }
 119    :  
 120    :    // Create input and output file names.
 121    :    base::FilePath input_path = temp_dir_.Append(
 122  E :        base::StringPrintf(L"input-%04d.obj", index_));
 123    :    base::FilePath output_path = temp_dir_.Append(
 124  E :        base::StringPrintf(L"output-%04d.obj", index_));
 125  E :    ++index_;
 126    :  
 127    :    // Set up deleters for these files.
 128  E :    FileDeleter input_deleter(input_path);
 129  E :    FileDeleter output_deleter(output_path);
 130    :  
 131    :    if (base::WriteFile(input_path,
 132    :                        reinterpret_cast<const char*>(contents->data()),
 133    :                        contents->size()) !=
 134  E :            static_cast<int>(contents->size())) {
 135  i :      LOG(ERROR) << "Unable to write file: " << input_path.value();
 136  i :      return false;
 137    :    }
 138    :  
 139    :    // Delegate to the wrapped callback.
 140  E :    if (!inner_callback_.Run(input_path, output_path, header, remove))
 141  i :      return false;
 142    :  
 143    :    // If the file is being removed we don't need to bother reading it.
 144  E :    if (*remove)
 145  E :      return true;
 146    :  
 147    :    // GetFileSize and ReadFile will both fail in this case, but we can provide
 148    :    // a more meaningful error message by first doing this check.
 149  E :    if (!base::PathExists(output_path)) {
 150  E :      LOG(ERROR) << "File does not exist: " << output_path.value();
 151  E :      return false;
 152    :    }
 153    :  
 154    :    // Read the transformed file from disk.
 155  E :    int64 size = 0;
 156  E :    if (!base::GetFileSize(output_path, &size)) {
 157  i :      LOG(ERROR) << "Unable to read size of file: " << output_path.value();
 158  i :      return false;
 159    :    }
 160  E :    contents->resize(size);
 161    :    if (base::ReadFile(output_path,
 162    :                             reinterpret_cast<char*>(contents->data()),
 163    :                             contents->size()) !=
 164  E :            static_cast<int>(contents->size())) {
 165  i :      LOG(ERROR) << "Unable to read file: " << output_path.value();
 166  i :      return false;
 167    :    }
 168    :  
 169  E :    return true;
 170  E :  }
 171    :  
 172    :  }  // namespace ar

Coverage information generated Thu Jan 14 17:40:38 2016.