// Copyright 2016 The Fuchsia 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 <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <threads.h>
#include <unistd.h>

#include <algorithm>
#include <iostream>
#include <random>
#include <string>
#include <vector>

#include <fbl/unique_fd.h>

#include "src/storage/fs_test/fs_test_fixture.h"

namespace fs_test {
namespace {

enum Status { kFail = -1, kBusy = 0, kDone = 1 };

constexpr int kBufSize = 65536;

static_assert(kBufSize == kBufSize / sizeof(uint64_t) * sizeof(uint64_t),
              "kBufSize not multiple of uint64_t");

class Worker;

class RwWorkersTest : public FilesystemTest {
 public:
  RwWorkersTest();

 protected:
  Status DoWork();

  std::vector<Worker> workers_;
  std::vector<thrd_t> threads_;
};

class Worker {
 public:
  using WorkFn = Status (Worker::*)(void);

  Worker(const std::string& where, const char* fn, WorkFn work, uint32_t size, uint32_t flags);

  Status status() const { return status_; }
  const std::string name() const { return name_; }

  Status Work() {
    status_ = (this->*work_)();
    return status_;
  }

  Status Rw(bool do_read);
  Status Writer();

 private:
  Status Verify();

  WorkFn work_;
  const std::default_random_engine::result_type seed_;
  std::default_random_engine data_random_;
  std::default_random_engine io_size_random_;

  fbl::unique_fd fd_;
  Status status_ = Status::kBusy;
  const uint32_t size_;
  const uint32_t flags_;
  uint32_t pos_ = 0;

  union {
    uint8_t u8[kBufSize];
    uint64_t u64[kBufSize / sizeof(uint64_t)];
  } buffer_;

  const std::string name_;
};

constexpr uint32_t kUseRandomIoSize = 1;

Status Worker::Rw(bool do_read) {
  if (pos_ == size_) {
    return kDone;
  }

  // offset into buffer
  uint32_t off = pos_ % kBufSize;

  // fill our content buffer if it's empty
  if (off == 0) {
    std::uniform_int_distribution<uint64_t> dist;
    for (unsigned n = 0; n < (kBufSize / sizeof(uint64_t)); n++) {
      buffer_.u64[n] = dist(data_random_);
    }
  }

  // data in buffer available to write
  uint32_t xfer = kBufSize - off;

  // do not exceed our desired size
  if (xfer > (size_ - pos_)) {
    xfer = size_ - pos_;
  }

  if ((flags_ & kUseRandomIoSize) && (xfer > 3000)) {
    xfer = 3000 + (std::uniform_int_distribution<uint32_t>()(io_size_random_) % (xfer - 3000));
  }

  ssize_t r;
  if (do_read) {
    uint8_t buffer[kBufSize];
    if ((r = read(fd_.get(), buffer, xfer)) < 0) {
      std::cout << "worker('" << name_ << "') read failed @" << pos_ << ": " << strerror(errno)
                << std::endl;
      return kFail;
    }
    if (memcmp(buffer, buffer_.u8 + off, r)) {
      std::cout << "worker('" << name_ << ") verify failed @" << pos_ << std::endl;
      return kFail;
    }
  } else {
    if ((r = write(fd_.get(), buffer_.u8 + off, xfer)) < 0) {
      std::cout << "worker('" << name_ << "') write failed @" << pos_ << ": " << strerror(errno)
                << std::endl;
      return kFail;
    }
  }

  // advance
  pos_ += r;
  return kBusy;
}

Status Worker::Verify() { return Rw(true); }

Status Worker::Writer() {
  Status r = Rw(false);
  if (r == kDone) {
    if (lseek(fd_.get(), 0, SEEK_SET) != 0) {
      std::cout << "worker('" << name_ << "') seek failed: " << strerror(errno) << std::endl;
      return kFail;
    }
    // Reset data_random_.
    data_random_.seed(seed_);
    pos_ = 0;
    work_ = &Worker::Verify;
    return kBusy;
  }
  return r;
}

Worker::Worker(const std::string& where, const char* fn, WorkFn work, uint32_t size, uint32_t flags)
    : work_(work),
      seed_(std::random_device()()),
      data_random_(seed_),
      io_size_random_(seed_),
      size_(size),
      flags_(flags),
      name_(where + fn) {
  fd_ = fbl::unique_fd(open(name_.c_str(), O_RDWR | O_CREAT | O_EXCL, 0644));
  EXPECT_TRUE(fd_);
}

Status RwWorkersTest::DoWork() {
  int busy_count = 0;
  for (Worker& w : workers_) {
    if (w.status() == kBusy) {
      busy_count++;
      if (w.Work() == kFail) {
        EXPECT_EQ(unlink(w.name().c_str()), 0);
        return kFail;
      }
      if (w.status() == kDone) {
        std::cout << "worker('" << w.name() << "') finished" << std::endl;
        EXPECT_EQ(unlink(w.name().c_str()), 0);
      }
    }
  }
  return busy_count ? kBusy : kDone;
}

TEST_P(RwWorkersTest, SingleThread) {
  Status r;
  do {
    r = DoWork();
    ASSERT_NE(r, kFail);
  } while (r != kDone);
}

constexpr uint32_t KiB(int n) { return n * 1024; }
constexpr uint32_t MiB(int n) { return n * 1024; }

constexpr struct {
  const char* name;
  uint32_t size;
  uint32_t flags;
} kWork[] = {
    {"file0000", KiB(512), kUseRandomIoSize},
    {"file0001", MiB(10), kUseRandomIoSize},
    {"file0002", KiB(512), kUseRandomIoSize},
    {"file0003", KiB(512), kUseRandomIoSize},
    {"file0004", KiB(512), 0},
    {"file0005", MiB(20), 0},
    {"file0006", KiB(512), 0},
    {"file0007", KiB(512), 0},
};

RwWorkersTest::RwWorkersTest() {
  // Assemble the work.
  for (const auto& work : kWork) {
    workers_.push_back(
        Worker(fs().mount_path(), work.name, &Worker::Writer, work.size, work.flags));
  }
}

int DoThreadedWork(void* arg) {
  Worker* w = static_cast<Worker*>(arg);

  std::cout << "work thread(" << w->name() << ") started" << std::endl;
  while (w->Work() == kBusy) {
    thrd_yield();
  }

  std::cout << "work thread(" << w->name() << ") " << (w->status() == kDone ? "finished" : "failed")
            << std::endl;
  EXPECT_EQ(unlink(w->name().c_str()), 0);

  return w->status();
}

TEST_P(RwWorkersTest, Concurrent) {
  std::vector<thrd_t> threads;

  for (Worker& w : workers_) {
    // start the workers on separate threads
    thrd_t t;
    ASSERT_EQ(thrd_create(&t, DoThreadedWork, &w), thrd_success);
    threads.push_back(t);
  }

  for (thrd_t t : threads) {
    int rc;
    ASSERT_EQ(thrd_join(t, &rc), thrd_success);
    ASSERT_EQ(rc, kDone) << "Thread joined, but failed";
  }
}

INSTANTIATE_TEST_SUITE_P(/*no prefix*/, RwWorkersTest, testing::ValuesIn(AllTestFilesystems()),
                         testing::PrintToStringParamName());

}  // namespace
}  // namespace fs_test
