// Copyright 2019 The Chromium OS 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 <gio/gio.h>
#include <glib.h>

#include <memory>
#include <string>
#include <vector>

#include <base/logging.h>
#include <base/message_loop/message_loop.h>
#include <base/run_loop.h>
#include <gtest/gtest.h>

#include "glib-bridge/glib_bridge.h"

namespace glib_bridge {

namespace {
constexpr base::TimeDelta kTestTimeout = base::TimeDelta::FromSeconds(1);
}  // namespace

class GlibBridgeTest : public ::testing::Test {
 public:
  GlibBridgeTest() : glib_bridge_(new GlibBridge(&message_loop_)) {}
  ~GlibBridgeTest() override {}

  void Finish() { run_loop_.Quit(); }

 protected:
  void Start() {
    // Set up timeout
    message_loop_.task_runner()->PostDelayedTask(
        FROM_HERE, run_loop_.QuitClosure(), kTestTimeout);
    run_loop_.Run();
  }

 private:
  base::MessageLoopForIO message_loop_;
  base::RunLoop run_loop_;
  std::unique_ptr<GlibBridge> glib_bridge_;

  DISALLOW_COPY_AND_ASSIGN(GlibBridgeTest);
};

TEST_F(GlibBridgeTest, ReadFileCallback) {
  struct UserData {
    GlibBridgeTest* test;
    ssize_t bytes_read;
  };
  UserData user_data{this, 0};

  GFile* dev_file = g_file_new_for_path("/dev/zero");
  ASSERT_NE(dev_file, nullptr);
  GFileInputStream* istream = g_file_read(dev_file, nullptr, nullptr);
  ASSERT_NE(istream, nullptr);

  constexpr int kBufSize = 64;
  char buf[kBufSize];
  memset(buf, 1, kBufSize);
  auto read_results_ready = [](GObject* source, GAsyncResult* res,
                               gpointer user_data) {
    UserData* ud = reinterpret_cast<UserData*>(user_data);
    ud->bytes_read = g_input_stream_read_finish(
        reinterpret_cast<GInputStream*>(source), res, nullptr);
    ud->test->Finish();
  };
  g_input_stream_read_async(
      reinterpret_cast<GInputStream*>(istream), buf, kBufSize,
      G_PRIORITY_DEFAULT, nullptr,
      static_cast<GAsyncReadyCallback>(read_results_ready), &user_data);
  Start();

  ASSERT_EQ(user_data.bytes_read, kBufSize);
  char expected_buf[kBufSize];
  memset(expected_buf, 0, kBufSize);
  ASSERT_EQ(memcmp(buf, expected_buf, kBufSize), 0);

  g_object_unref(istream);
  g_object_unref(dev_file);
}

TEST_F(GlibBridgeTest, WriteFileCallback) {
  struct UserData {
    GlibBridgeTest* test;
    ssize_t bytes_written;
  };
  UserData user_data{this, 0};

  GFile* dev_file = g_file_new_for_path("/dev/null");
  ASSERT_NE(dev_file, nullptr);
  GFileOutputStream* ostream =
      g_file_append_to(dev_file, G_FILE_CREATE_NONE, nullptr, nullptr);
  ASSERT_NE(ostream, nullptr);

  const std::string buf("foobar");
  auto write_done = [](GObject* source, GAsyncResult* res, gpointer user_data) {
    UserData* ud = reinterpret_cast<UserData*>(user_data);
    ud->bytes_written = g_output_stream_write_finish(
        reinterpret_cast<GOutputStream*>(source), res, nullptr);
    ud->test->Finish();
  };
  g_output_stream_write_async(
      reinterpret_cast<GOutputStream*>(ostream), buf.data(), buf.size(),
      G_PRIORITY_DEFAULT, nullptr, static_cast<GAsyncReadyCallback>(write_done),
      &user_data);
  Start();

  ASSERT_EQ(user_data.bytes_written, buf.size());

  g_object_unref(ostream);
  g_object_unref(dev_file);
}

TEST_F(GlibBridgeTest, IdleCallback) {
  struct UserData {
    GlibBridgeTest* test;
    bool called;
  };
  UserData user_data{this, false};

  auto idle_callback = [](gpointer user_data) {
    UserData* ud = reinterpret_cast<UserData*>(user_data);
    ud->called = true;
    ud->test->Finish();
    return G_SOURCE_REMOVE;
  };

  g_idle_add(static_cast<GSourceFunc>(idle_callback), &user_data);
  Start();

  ASSERT_TRUE(user_data.called);
}

TEST_F(GlibBridgeTest, TimeoutOnceCallback) {
  struct UserData {
    GlibBridgeTest* test;
    bool called;
  };
  UserData user_data{this, false};

  auto timer_callback = [](gpointer user_data) {
    UserData* ud = reinterpret_cast<UserData*>(user_data);
    ud->called = true;
    ud->test->Finish();
    return G_SOURCE_REMOVE;
  };

  constexpr uint kTimeoutIntervalMs = 200;
  g_timeout_add(kTimeoutIntervalMs, static_cast<GSourceFunc>(timer_callback),
                &user_data);
  Start();

  ASSERT_TRUE(user_data.called);
}

TEST_F(GlibBridgeTest, TimeoutMultiCallback) {
  constexpr int kTarget = 5;
  struct UserData {
    GlibBridgeTest* test;
    int counter;
  };
  UserData user_data{this, 0};

  auto timer_callback = [](gpointer user_data) -> gboolean {
    UserData* ud = reinterpret_cast<UserData*>(user_data);
    ud->counter++;
    if (ud->counter == kTarget) {
      ud->test->Finish();
      return G_SOURCE_REMOVE;
    }
    return G_SOURCE_CONTINUE;
  };

  constexpr uint kTimeoutIntervalMs = 100;
  g_timeout_add(kTimeoutIntervalMs, static_cast<GSourceFunc>(timer_callback),
                &user_data);
  Start();

  ASSERT_EQ(user_data.counter, kTarget);
}

TEST_F(GlibBridgeTest, MultipleTimeouts) {
  constexpr uint kNumFlags = 5;
  struct UserData {
    GlibBridgeTest* test;
    int counter;
    bool called[kNumFlags];
  };
  UserData user_data{this, 0, {false}};

  auto timer_callback = [](gpointer user_data) {
    UserData* ud = reinterpret_cast<UserData*>(user_data);
    ud->called[ud->counter] = true;
    ud->counter++;
    if (ud->counter == kNumFlags)
      ud->test->Finish();
    return G_SOURCE_REMOVE;
  };

  constexpr uint kTimeoutIntervalMs = 100;
  for (int i = 0; i < kNumFlags; i++) {
    g_timeout_add(kTimeoutIntervalMs * (i + 1),
                  static_cast<GSourceFunc>(timer_callback), &user_data);
  }
  Start();

  for (int i = 0; i < kNumFlags; i++)
    ASSERT_TRUE(user_data.called[i]);
}

namespace multi_io_test {

constexpr int kBufSize = 64;

struct UserData;
struct IoJob {
  IoJob(GFile* file, GFileInputStream* istream, UserData* user_data)
      : file(file), istream(istream), buf(kBufSize, 1), user_data(user_data) {}

  GFile* file;
  GFileInputStream* istream;
  std::vector<char> buf;
  bool complete = false;
  UserData* user_data;
};

struct UserData {
  GlibBridgeTest* test;
  std::vector<IoJob> io_jobs;
};

gboolean AllCompleteCheck(gpointer user_data) {
  UserData* ud = reinterpret_cast<UserData*>(user_data);
  bool all_complete = true;
  for (const IoJob& io_job : ud->io_jobs)
    all_complete &= io_job.complete;
  if (all_complete)
    ud->test->Finish();
  return G_SOURCE_REMOVE;
}

void ReadResultsReady(GObject* source, GAsyncResult* res, gpointer user_data) {
  IoJob* job = reinterpret_cast<IoJob*>(user_data);
  job->complete =
      g_input_stream_read_finish(reinterpret_cast<GInputStream*>(source), res,
                                 nullptr) >= 0;
  g_idle_add(static_cast<GSourceFunc>(&AllCompleteCheck), job->user_data);
}

TEST_F(GlibBridgeTest, MultipleReadAndIdleCallbacks) {
  UserData user_data{this};
  constexpr int kNumFiles = 5;
  for (int i = 0; i < kNumFiles; i++) {
    GFile* dev_file = g_file_new_for_path("/dev/zero");
    ASSERT_NE(dev_file, nullptr);
    GFileInputStream* istream = g_file_read(dev_file, nullptr, nullptr);
    ASSERT_NE(istream, nullptr);
    user_data.io_jobs.emplace_back(dev_file, istream, &user_data);
  }

  for (IoJob& io_job : user_data.io_jobs) {
    g_input_stream_read_async(
        reinterpret_cast<GInputStream*>(io_job.istream), &io_job.buf[0],
        io_job.buf.size(), G_PRIORITY_DEFAULT, nullptr,
        static_cast<GAsyncReadyCallback>(&ReadResultsReady), &io_job);
  }
  Start();

  bool all_complete = true;
  for (const IoJob& io_job : user_data.io_jobs) {
    all_complete &= io_job.complete;
    std::vector<char> expected_buf(io_job.buf.size(), 0);
    ASSERT_EQ(io_job.buf, expected_buf);

    g_object_unref(io_job.istream);
    g_object_unref(io_job.file);
  }
  ASSERT_TRUE(all_complete);
}

}  // namespace multi_io_test

}  // namespace glib_bridge
