// Copyright 2020 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/virtualization/tests/guest_console.h"

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

#include <gtest/gtest.h>

#include "src/virtualization/tests/socket.h"

namespace {

class FakeSocket : public SocketInterface {
 public:
  explicit FakeSocket(std::vector<std::string> responses) : responses_(std::move(responses)) {}

  zx_status_t Send(zx::time deadline, const std::string& message) override { return ZX_OK; }

  zx_status_t Receive(zx::time deadline, std::string* result) override {
    if (reads_performed_ >= responses_.size()) {
      return ZX_ERR_PEER_CLOSED;
    }
    *result = responses_.at(reads_performed_);
    reads_performed_++;
    return ZX_OK;
  }

  zx_status_t WaitForClosed(zx::time deadline) override { return ZX_OK; }

 private:
  size_t reads_performed_ = 0;
  std::vector<std::string> responses_;
};

TEST(GuestConsole, WaitForMarkerEmpty) {
  auto socket = std::make_unique<FakeSocket>(std::vector<std::string>{});
  GuestConsole console(std::move(socket));

  // Ensure an empty read returns success, and clears out result.
  std::string result = "non-empty";
  EXPECT_EQ(console.WaitForMarker("", zx::time::infinite(), &result), ZX_OK);
  EXPECT_EQ(result, "");

  // A non-empty marker read should return an error.
  EXPECT_EQ(console.WaitForMarker("x", zx::time::infinite(), &result), ZX_ERR_PEER_CLOSED);
}

TEST(GuestConsole, WaitForMarkerSimple) {
  auto socket = std::make_unique<FakeSocket>(std::vector<std::string>{"marker"});
  GuestConsole console(std::move(socket));

  std::string result;
  EXPECT_EQ(console.WaitForMarker("marker", zx::time::infinite(), &result), ZX_OK);
  EXPECT_EQ(result, "");
}

TEST(GuestConsole, WaitForMarkerContentBefore) {
  auto socket = std::make_unique<FakeSocket>(std::vector<std::string>{"xxxmarker"});
  GuestConsole console(std::move(socket));

  std::string result;
  EXPECT_EQ(console.WaitForMarker("marker", zx::time::infinite(), &result), ZX_OK);
  EXPECT_EQ(result, "xxx");
}

TEST(GuestConsole, WaitForMarkerContentAfterPreserved) {
  auto socket = std::make_unique<FakeSocket>(std::vector<std::string>{"xxxmarkeryyy", "second"});
  GuestConsole console(std::move(socket));

  std::string result;
  EXPECT_EQ(console.WaitForMarker("marker", zx::time::infinite(), &result), ZX_OK);
  EXPECT_EQ(result, "xxx");

  EXPECT_EQ(console.WaitForMarker("second", zx::time::infinite(), &result), ZX_OK);
  EXPECT_EQ(result, "yyy");
}

TEST(GuestConsole, WaitForMarkerSplitMarker) {
  // "xxx" + "marker" + "yyy" + "second"
  auto socket = std::make_unique<FakeSocket>(
      std::vector<std::string>{"xx", "xm", "ar", "keryyys", "econ", "d"});
  GuestConsole console(std::move(socket));

  std::string result;
  EXPECT_EQ(console.WaitForMarker("marker", zx::time::infinite(), &result), ZX_OK);
  EXPECT_EQ(result, "xxx");

  EXPECT_EQ(console.WaitForMarker("second", zx::time::infinite(), &result), ZX_OK);
  EXPECT_EQ(result, "yyy");
}

}  // namespace
