// Copyright 2019 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 "src/developer/memory/monitor/high_water.h"

#include <fcntl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fdio/namespace.h>
#include <lib/gtest/real_loop_fixture.h>
#include <lib/memfs/memfs.h>
#include <lib/syslog/cpp/macros.h>

#include <gtest/gtest.h>
#include <src/lib/files/file.h>
#include <src/lib/files/path.h>

#include "src/developer/memory/metrics/capture.h"
#include "src/developer/memory/metrics/tests/test_utils.h"

using namespace memory;

namespace monitor {
namespace {

const char kMemfsDir[] = "/data";

// Mounts a memfs filesystem at a given path and unmounts it when this object
// goes out of scope.
class ScopedMemfs {
 public:
  // Creates a new memfs filesystem at the given path.
  static zx_status_t InstallAt(const char* path, async_dispatcher_t* dispatcher,
                               std::unique_ptr<ScopedMemfs>* out) {
    fdio_ns_t* ns;
    zx_status_t status = fdio_ns_get_installed(&ns);
    if (status != ZX_OK) {
      return status;
    }

    memfs_filesystem_t* fs;
    zx_handle_t root;
    status = memfs_create_filesystem(dispatcher, &fs, &root);
    if (status != ZX_OK) {
      return status;
    }

    status = fdio_ns_bind(ns, path, root);
    if (status != ZX_OK) {
      memfs_free_filesystem(fs, nullptr);
      return status;
    }

    *out = std::make_unique<ScopedMemfs>(fs, path);
    return ZX_OK;
  }

  ScopedMemfs(memfs_filesystem_t* fs, const char* path) : fs_(fs), path_(path) {}

  ~ScopedMemfs() {
    fdio_ns_t* ns;
    sync_completion_t completion;
    memfs_free_filesystem(fs_, &completion);
    FX_CHECK(sync_completion_wait(&completion, ZX_TIME_INFINITE) == ZX_OK)
        << "Failed to unmount memfs";
    FX_CHECK(fdio_ns_get_installed(&ns) == ZX_OK) << "Failed to read namespaces";
    FX_CHECK(fdio_ns_unbind(ns, path_) == ZX_OK) << "Failed to unbind memfs filesystem";
  }

 private:
  memfs_filesystem_t* fs_;
  const char* path_;
};

class HighWaterUnitTest : public gtest::RealLoopFixture {
 protected:
  int memfs_dir_;

 private:
  void SetUp() override {
    RealLoopFixture::SetUp();
    // Install memfs on a different async loop thread to resolve some deadlock
    // when doing blocking file operations on our test loop.
    FX_CHECK(ScopedMemfs::InstallAt(kMemfsDir, memfs_loop_.dispatcher(), &data_) == ZX_OK);
    memfs_loop_.StartThread();
    memfs_dir_ = open(kMemfsDir, O_RDONLY | O_DIRECTORY);
    ASSERT_LT(0, memfs_dir_);
  }

  void TearDown() override {
    RealLoopFixture::TearDown();
    data_.reset();
    close(memfs_dir_);
    memfs_loop_.Shutdown();
  }

  //  private:
  async::Loop memfs_loop_{&kAsyncLoopConfigNoAttachToCurrentThread};
  std::unique_ptr<ScopedMemfs> data_;
};

TEST_F(HighWaterUnitTest, Basic) {
  CaptureSupplier cs({{
                          .kmem = {.free_bytes = 100},
                      },
                      {.kmem = {.free_bytes = 100},
                       .vmos =
                           {
                               {.koid = 1, .name = "v1", .committed_bytes = 101},
                           },
                       .processes = {
                           {.koid = 2, .name = "p1", .vmos = {1}},
                       }}});
  ASSERT_FALSE(files::IsFileAt(memfs_dir_, "latest.txt"));
  HighWater hw(kMemfsDir, zx::msec(10), 100, dispatcher(),
               [&cs](Capture* c, CaptureLevel l) { return cs.GetCapture(c, l); });
  ASSERT_FALSE(files::IsFileAt(memfs_dir_, "latest.txt"));
  ASSERT_FALSE(files::IsFileAt(memfs_dir_, "previous.txt"));
  ASSERT_FALSE(files::IsFileAt(memfs_dir_, "latest_digest.txt"));
  ASSERT_FALSE(files::IsFileAt(memfs_dir_, "previous_digest.txt"));
  RunLoopUntil([&cs] { return cs.empty(); });
  EXPECT_TRUE(files::IsFileAt(memfs_dir_, "latest.txt"));
  EXPECT_TRUE(files::IsFileAt(memfs_dir_, "latest_digest.txt"));
  EXPECT_FALSE(hw.GetHighWater().empty());
  EXPECT_FALSE(hw.GetHighWaterDigest().empty());
}

TEST_F(HighWaterUnitTest, RunTwice) {
  ASSERT_FALSE(files::IsFileAt(memfs_dir_, "previous.txt"));
  ASSERT_FALSE(files::IsFileAt(memfs_dir_, "latest.txt"));
  ASSERT_FALSE(files::IsFileAt(memfs_dir_, "previous_digest.txt"));
  ASSERT_FALSE(files::IsFileAt(memfs_dir_, "latest_digest.txt"));
  {
    CaptureSupplier cs({{
                            .kmem = {.free_bytes = 100},
                        },
                        {.kmem = {.free_bytes = 100},
                         .vmos =
                             {
                                 {.koid = 1, .name = "v1", .committed_bytes = 101},
                             },
                         .processes = {
                             {.koid = 2, .name = "p1", .vmos = {1}},
                         }}});
    HighWater hw(kMemfsDir, zx::msec(10), 100, dispatcher(),
                 [&cs](Capture* c, CaptureLevel l) { return cs.GetCapture(c, l); });
    RunLoopUntil([&cs] { return cs.empty(); });
    EXPECT_FALSE(hw.GetHighWater().empty());
  }
  EXPECT_TRUE(files::IsFileAt(memfs_dir_, "latest.txt"));
  EXPECT_TRUE(files::IsFileAt(memfs_dir_, "latest_digest.txt"));
  EXPECT_FALSE(files::IsFileAt(memfs_dir_, "previous.txt"));
  EXPECT_FALSE(files::IsFileAt(memfs_dir_, "previous_digest.txt"));
  {
    CaptureSupplier cs({{
                            .kmem = {.free_bytes = 100},
                        },
                        {.kmem = {.free_bytes = 100},
                         .vmos =
                             {
                                 {.koid = 1, .name = "v1", .committed_bytes = 101},
                             },
                         .processes = {
                             {.koid = 2, .name = "p1", .vmos = {1}},
                         }}});
    HighWater hw(kMemfsDir, zx::msec(10), 100, dispatcher(),
                 [&cs](Capture* c, CaptureLevel l) { return cs.GetCapture(c, l); });
    RunLoopUntil([&cs] { return cs.empty(); });
    EXPECT_FALSE(hw.GetHighWater().empty());
    EXPECT_FALSE(hw.GetPreviousHighWater().empty());
    EXPECT_FALSE(hw.GetHighWaterDigest().empty());
    EXPECT_FALSE(hw.GetPreviousHighWaterDigest().empty());
  }
  EXPECT_TRUE(files::IsFileAt(memfs_dir_, "latest.txt"));
  EXPECT_TRUE(files::IsFileAt(memfs_dir_, "latest_digest.txt"));
  EXPECT_TRUE(files::IsFileAt(memfs_dir_, "previous.txt"));
  EXPECT_TRUE(files::IsFileAt(memfs_dir_, "previous_digest.txt"));
}

}  // namespace
}  // namespace monitor
