//
// Copyright (C) 2012 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#ifndef UPDATE_ENGINE_COMMON_TEST_UTILS_H_
#define UPDATE_ENGINE_COMMON_TEST_UTILS_H_

#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

// Streams used for gtest's PrintTo() functions.
#include <iostream>  // NOLINT(readability/streams)
#include <memory>
#include <string>
#include <vector>

#include <base/files/file_path.h>
#include <base/files/scoped_temp_dir.h>
#include <gtest/gtest.h>

#include "update_engine/common/action.h"
#include "update_engine/common/testing_constants.h"
#include "update_engine/common/utils.h"
#include "update_engine/update_metadata.pb.h"

// These are some handy functions for unittests.

namespace chromeos_update_engine {

// PrintTo() functions are used by gtest to log these objects. These PrintTo()
// functions must be defined in the same namespace as the first argument.
void PrintTo(const Extent& extent, ::std::ostream* os);
void PrintTo(const ErrorCode& error_code, ::std::ostream* os);

namespace test_utils {

// 300 byte pseudo-random string. Not null terminated.
// This does not gzip compress well.
extern const uint8_t kRandomString[300];

// Writes the data passed to path. The file at path will be overwritten if it
// exists. Returns true on success, false otherwise.
bool WriteFileVector(const std::string& path, const brillo::Blob& data);
bool WriteFileString(const std::string& path, const std::string& data);

// Binds provided |filename| to an unused loopback device, whose name is written
// to the string pointed to by |out_lo_dev_name|. The new loop device will be
// read-only unless |writable| is set to true. Returns true on success, false
// otherwise (along with corresponding test failures), in which case the content
// of |out_lo_dev_name| is unknown.
bool BindToUnusedLoopDevice(const std::string& filename,
                            bool writable,
                            std::string* out_lo_dev_name);
bool UnbindLoopDevice(const std::string& lo_dev_name);

// Returns true iff a == b
bool ExpectVectorsEq(const brillo::Blob& a, const brillo::Blob& b);

inline int System(const std::string& cmd) {
  return system(cmd.c_str());
}

// Reads a symlink from disk. Returns empty string on failure.
std::string Readlink(const std::string& path);

void FillWithData(brillo::Blob* buffer);

// Class to unmount FS when object goes out of scope
class ScopedFilesystemUnmounter {
 public:
  explicit ScopedFilesystemUnmounter(const std::string& mountpoint)
      : mountpoint_(mountpoint), should_unmount_(true) {}
  ~ScopedFilesystemUnmounter() {
    if (should_unmount_) {
      utils::UnmountFilesystem(mountpoint_);
    }
  }
  void set_should_unmount(bool unmount) { should_unmount_ = unmount; }

 private:
  const std::string mountpoint_;
  bool should_unmount_;
  DISALLOW_COPY_AND_ASSIGN(ScopedFilesystemUnmounter);
};

class ScopedLoopbackDeviceBinder {
 public:
  ScopedLoopbackDeviceBinder(const std::string& file,
                             bool writable,
                             std::string* dev) {
    is_bound_ = BindToUnusedLoopDevice(file, writable, &dev_);
    EXPECT_TRUE(is_bound_);

    if (is_bound_ && dev)
      *dev = dev_;
  }

  ~ScopedLoopbackDeviceBinder() {
    if (!is_bound_)
      return;

    for (int retry = 0; retry < 5; retry++) {
      if (UnbindLoopDevice(dev_))
        return;
      sleep(1);
    }
    ADD_FAILURE();
  }

  const std::string& dev() const {
    EXPECT_TRUE(is_bound_);
    return dev_;
  }

  bool is_bound() const { return is_bound_; }

 private:
  std::string dev_;
  bool is_bound_;
  DISALLOW_COPY_AND_ASSIGN(ScopedLoopbackDeviceBinder);
};

class ScopedLoopMounter {
 public:
  explicit ScopedLoopMounter(const std::string& file_path,
                             std::string* mnt_path,
                             unsigned long flags);  // NOLINT(runtime/int)

 private:
  // These objects must be destructed in the following order:
  //   ScopedFilesystemUnmounter (the file system must be unmounted first)
  //   ScopedLoopbackDeviceBinder (then the loop device can be deleted)
  //   ScopedDirRemover (then the mount point can be deleted)
  base::ScopedTempDir temp_dir_;
  std::unique_ptr<ScopedLoopbackDeviceBinder> loop_binder_;
  std::unique_ptr<ScopedFilesystemUnmounter> unmounter_;
};

// Returns the path where the build artifacts are stored. This is the directory
// where the unittest executable is being run from.
base::FilePath GetBuildArtifactsPath();
// Returns the path of the build artifact specified in |relative_path|.
std::string GetBuildArtifactsPath(const std::string& relative_path);

}  // namespace test_utils

// Useful actions for test. These need to be defined in the
// chromeos_update_engine namespace.

class NoneType;

template <typename T>
class ObjectFeederAction;

template <typename T>
class ActionTraits<ObjectFeederAction<T>> {
 public:
  typedef T OutputObjectType;
  typedef NoneType InputObjectType;
};

// This is a simple Action class for testing. It feeds an object into
// another action.
template <typename T>
class ObjectFeederAction : public Action<ObjectFeederAction<T>> {
 public:
  typedef NoneType InputObjectType;
  typedef T OutputObjectType;
  void PerformAction() {
    LOG(INFO) << "feeder running!";
    CHECK(this->processor_);
    if (this->HasOutputPipe()) {
      this->SetOutputObject(out_obj_);
    }
    this->processor_->ActionComplete(this, ErrorCode::kSuccess);
  }
  static std::string StaticType() { return "ObjectFeederAction"; }
  std::string Type() const { return StaticType(); }
  void set_obj(const T& out_obj) { out_obj_ = out_obj; }

 private:
  T out_obj_;
};

template <typename T>
class ObjectCollectorAction;

template <typename T>
class ActionTraits<ObjectCollectorAction<T>> {
 public:
  typedef NoneType OutputObjectType;
  typedef T InputObjectType;
};

// This is a simple Action class for testing. It receives an object from
// another action.
template <typename T>
class ObjectCollectorAction : public Action<ObjectCollectorAction<T>> {
 public:
  typedef T InputObjectType;
  typedef NoneType OutputObjectType;
  void PerformAction() {
    LOG(INFO) << "collector running!";
    ASSERT_TRUE(this->processor_);
    if (this->HasInputObject()) {
      object_ = this->GetInputObject();
    }
    this->processor_->ActionComplete(this, ErrorCode::kSuccess);
  }
  static std::string StaticType() { return "ObjectCollectorAction"; }
  std::string Type() const { return StaticType(); }
  const T& object() const { return object_; }

 private:
  T object_;
};

}  // namespace chromeos_update_engine

#endif  // UPDATE_ENGINE_COMMON_TEST_UTILS_H_
