// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "crazy_linker_system_mock.h"

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

#include "crazy_linker_util.h"
#include "crazy_linker_system.h"

// Unit-testing support code. This should never be compiled into
// the production code.

namespace {

using crazy::String;
using crazy::Vector;

void Panic(const char* msg, ...) {
  va_list args;
  fprintf(stderr, "PANIC: ");
  va_start(args, msg);
  vfprintf(stderr, msg, args);
  va_end(args);
  fprintf(stderr, "\n");
  exit(1);
}

// Models a simple list of pointers to objects, which are owned by the
// list itself.
template <class T>
class List {
 public:
  List() : entries_() {}

  ~List() { Reset(); }

  void Reset() {
    for (size_t n = 0; n < entries_.GetCount(); ++n) {
      T* entry = entries_[n];
      delete entry;
      entries_[n] = NULL;
    }
    entries_.Resize(0);
  }

  // Add an item to the list, transfer ownership to it.
  void PushBack(T* item) { entries_.PushBack(item); }

  size_t GetCount() const { return entries_.GetCount(); }

  T* operator[](size_t index) { return entries_[index]; }

 private:
  crazy::Vector<T*> entries_;
};

// Models a single file entry in a mock file system.
class MockFileEntry {
 public:
  MockFileEntry() : path_(), data_() {}

  ~MockFileEntry() {}

  const char* GetPath() const { return path_.c_str(); }
  const char* GetData() const { return data_.c_str(); }
  size_t GetDataSize() const { return data_.size(); }

  void SetPath(const char* path) { path_.Assign(path); }

  void SetData(const char* data, size_t data_size) {
    data_.Assign(data, data_size);
  }

 private:
  crazy::String path_;
  crazy::String data_;
};

// Models a single mock environment variable value.
class MockEnvEntry {
 public:
  MockEnvEntry(const char* var_name, const char* var_value)
      : var_name_(var_name), var_value_(var_value) {}

  const String& GetName() const { return var_name_; }
  const String& GetValue() const { return var_value_; }

 private:
  crazy::String var_name_;
  crazy::String var_value_;
};

class MockFileHandle {
 public:
  MockFileHandle(MockFileEntry* entry) : entry_(entry), offset_(0) {}
  ~MockFileHandle() {}

  bool IsEof() const { return offset_ >= entry_->GetDataSize(); }

  bool GetString(char* buffer, size_t buffer_size) {
    const char* data = entry_->GetData();
    size_t data_size = entry_->GetDataSize();

    if (offset_ >= data_size || buffer_size == 0)
      return false;

    while (buffer_size > 1) {
      char ch = data[offset_++];
      *buffer++ = ch;
      buffer_size--;
      if (ch == '\n')
        break;
    }
    *buffer = '\0';
    return true;
  }

  ssize_t Read(void* buffer, size_t buffer_size) {
    if (buffer_size == 0)
      return 0;

    const char* data = entry_->GetData();
    size_t data_size = entry_->GetDataSize();

    size_t avail = data_size - offset_;
    if (avail == 0)
      return 0;

    if (buffer_size > avail)
      buffer_size = avail;

    ::memcpy(buffer, data + offset_, buffer_size);
    offset_ += buffer_size;

    return static_cast<int>(buffer_size);
  }

  off_t SeekTo(off_t offset) {
    if (offset < 0) {
      errno = EINVAL;
      return -1;
    }

    const char* data = entry_->GetData();
    size_t data_size = entry_->GetDataSize();

    if (offset > static_cast<off_t>(data_size)) {
      errno = EINVAL;
      return -1;
    }

    offset_ = static_cast<size_t>(offset);
    return 0;
  }

  void* Map(void* address, size_t length, int prot, int flags, off_t offset) {
    const char* data = entry_->GetData();
    size_t data_size = entry_->GetDataSize();
    if (offset_ >= data_size) {
      errno = EINVAL;
      return nullptr;
    }

    // Allocate an anonymous memory mapping, then copy the file contents
    // into it.
    void* map =
        mmap(address, length, PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    if (map == MAP_FAILED) {
      return nullptr;
    }

    size_t avail = data_size - offset_;
    if (avail > length)
      avail = length;

    ::memcpy(map, data + offset_, avail);

    // Restore desired protection after the write.
    mprotect(map, length, prot);

    // Done.
    return map;
  }

  int64_t GetFileSize() const {
    return static_cast<int64_t>(entry_->GetDataSize());
  }

 private:
  MockFileEntry* entry_;
  size_t offset_;
};

// Convenience class for the table of all active file descriptors in the
// mock system.
class MockFileHandleTable {
 public:
  // Constructor.
  MockFileHandleTable() = default;

  // Destructor.
  ~MockFileHandleTable() {
    for (size_t n = 0; n < handles_.GetCount(); ++n) {
      delete handles_[n];
    }
  }

  // Find the MockFileHandle corresponding to |fd|, or nullptr if this
  // is an unknown value.
  MockFileHandle* Find(int fd) const {
    if (fd < 0 || static_cast<size_t>(fd) >= handles_.GetCount()) {
      return nullptr;
    }
    return handles_[fd];
  }

  // Allocate a new file descriptor value associated with a MockFileHandle
  // instance. This takes ownership of the instance.
  int AllocateFd(MockFileHandle* handle) {
    size_t n = 0;
    for (; n < handles_.GetCount(); ++n) {
      if (!handles_[n]) {
        // Found a free descriptor in the table.
        handles_[n] = handle;
        return static_cast<int>(n);
      }
    }
    // Allocate new descriptor value.
    handles_.PushBack(handle);
    return static_cast<int>(n);
  }

  // Deallocate a file descriptor by value.
  bool DeallocateFd(int fd) {
    if (!Find(fd)) {
      return false;
    }
    delete handles_[fd];
    handles_[fd] = nullptr;
    return true;
  }

 private:
  Vector<MockFileHandle*> handles_;
};

class MockSystem {
 public:
  MockSystem() : files_(), environment_() {}

  ~MockSystem() { Reset(); }

  void SetCurrentDir(const char* path) { current_dir_ = path; }

  String GetCurrentDir() const { return current_dir_; }

  void AddFileEntry(MockFileEntry* entry) { files_.PushBack(entry); }

  void AddEnvEntry(MockEnvEntry* entry) { environment_.PushBack(entry); }

  MockFileEntry* FindFileEntry(const char* path) {
    for (size_t n = 0; n < files_.GetCount(); ++n) {
      MockFileEntry* entry = files_[n];
      if (entry->GetPath() && !strcmp(path, entry->GetPath()))
        return entry;
    }
    return NULL;
  }

  MockEnvEntry* FindEnvEntry(const char* var_name) {
    for (size_t n = 0; n < environment_.GetCount(); ++n) {
      MockEnvEntry* entry = environment_[n];
      if (!strcmp(entry->GetName().c_str(), var_name))
        return entry;
    }
    return NULL;
  }

  int OpenFd(const char* path, crazy::FileOpenMode open_mode) {
    // TODO(digit): Add write support.
    if (open_mode != crazy::FILE_OPEN_READ_ONLY)
      Panic("Unsupported open mode (%d): %s", open_mode, path);

    MockFileEntry* entry = FindFileEntry(path);
    if (!entry) {
      errno = ENOENT;
      return -1;
    }

    return handles_.AllocateFd(new MockFileHandle(entry));
  }

  MockFileHandle* FindFileHandle(int fd) const { return handles_.Find(fd); }

  void CloseFd(int fd) {
    if (!handles_.DeallocateFd(fd)) {
      Panic("Closing invalid file descriptor %d", fd);
    }
  }

  void Reset() {
    files_.Reset();
    environment_.Reset();
    current_dir_ = "/";
  }

  void Check() {
    if (!active_)
      Panic("No mock file system setup!");
  }

  void Activate() {
    if (active_)
      Panic("Double mock file system activation!");

    active_ = true;
  }

  void Deactivate() {
    if (!active_)
      Panic("Double mock file system deactivation!");

    active_ = false;
  }

 private:
  List<MockFileEntry> files_;
  List<MockEnvEntry> environment_;
  MockFileHandleTable handles_;
  String current_dir_;
  bool active_;
};

MockSystem s_mock_fs;

}  // namespace

namespace crazy {

#ifdef UNIT_TEST

bool PathExists(const char* path) {
  s_mock_fs.Check();
  return s_mock_fs.FindFileEntry(path) != NULL;
}

bool PathIsFile(const char* path) {
  // TODO(digit): Change this when support for mock directories is added.
  return PathExists(path);
}

String GetCurrentDirectory() {
  s_mock_fs.Check();
  return s_mock_fs.GetCurrentDir();
}

const char* GetEnv(const char* var_name) {
  s_mock_fs.Check();
  MockEnvEntry* entry = s_mock_fs.FindEnvEntry(var_name);
  if (!entry)
    return NULL;
  else
    return entry->GetValue().c_str();
}

ssize_t FileDescriptor::Read(void* buffer, size_t buffer_size) {
  s_mock_fs.Check();
  MockFileHandle* handle = s_mock_fs.FindFileHandle(fd_);
  if (!handle) {
    errno = EBADF;
    return -1;
  }
  return handle->Read(buffer, buffer_size);
}

off_t FileDescriptor::SeekTo(off_t offset) {
  s_mock_fs.Check();
  MockFileHandle* handle = s_mock_fs.FindFileHandle(fd_);
  if (!handle) {
    errno = EBADF;
    return -1;
  }
  return handle->SeekTo(offset);
}

void* FileDescriptor::Map(void* address,
                          size_t length,
                          int prot,
                          int flags,
                          off_t offset) {
  s_mock_fs.Check();
  MockFileHandle* handle = s_mock_fs.FindFileHandle(fd_);
  if (!handle) {
    errno = EBADF;
    return nullptr;
  }
  if ((offset & 4095) != 0) {
    errno = EINVAL;
    return nullptr;
  }
  return handle->Map(address, length, prot, flags, offset);
}

int64_t FileDescriptor::GetFileSize() const {
  s_mock_fs.Check();
  MockFileHandle* handle = s_mock_fs.FindFileHandle(fd_);
  if (!handle) {
    errno = EBADF;
    return -1;
  }
  return handle->GetFileSize();
}

// static
int FileDescriptor::DoOpenReadOnly(const char* path) {
  s_mock_fs.Check();
  return s_mock_fs.OpenFd(path, FILE_OPEN_READ_ONLY);
}

// static
int FileDescriptor::DoOpenReadWrite(const char* path) {
  s_mock_fs.Check();
  return s_mock_fs.OpenFd(path, FILE_OPEN_READ_WRITE);
}

// static
void FileDescriptor::DoClose(int fd) {
  s_mock_fs.Check();
  s_mock_fs.CloseFd(fd);
}

SystemMock::SystemMock() { s_mock_fs.Activate(); }

SystemMock::~SystemMock() {
  s_mock_fs.Deactivate();
  s_mock_fs.Reset();
}

void SystemMock::AddRegularFile(const char* path,
                                const char* data,
                                size_t data_size) {
  s_mock_fs.Check();

  MockFileEntry* entry = new MockFileEntry();
  entry->SetPath(path);
  entry->SetData(data, data_size);

  s_mock_fs.AddFileEntry(entry);
}

void SystemMock::AddEnvVariable(const char* var_name, const char* var_value) {
  s_mock_fs.Check();

  MockEnvEntry* env = new MockEnvEntry(var_name, var_value);
  s_mock_fs.AddEnvEntry(env);
}

void SystemMock::SetCurrentDir(const char* path) {
  s_mock_fs.Check();
  s_mock_fs.SetCurrentDir(path);
}

#endif  // UNIT_TEST

}  // namespace crazy
