// 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 "sdk/lib/ui/scenic/cpp/session.h"

#include <lib/gtest/test_loop_fixture.h>
#include <lib/zx/channel.h>
#include <zircon/types.h>

#include <gtest/gtest.h>

#include "lib/ui/scenic/cpp/commands.h"

namespace {

class MockScenicSession : public scenic::Session {
 public:
  MockScenicSession(fuchsia::ui::scenic::SessionPtr client) : Session(std::move(client)) {}

  void Flush() override {
    num_flushed_++;
    commands_.clear();
  }

  int64_t num_flushed_ = 0;
  size_t num_commands() { return commands_.size(); }
  int64_t num_bytes() { return commands_num_bytes_; }
  int64_t num_handles() { return commands_num_handles_; }
};

class ScenicSessionFlushTest : public ::gtest::TestLoopFixture {
 public:
  ScenicSessionFlushTest() = default;
  ~ScenicSessionFlushTest() override = default;

  std::unique_ptr<MockScenicSession> session_;

 protected:
  void SetUp() override {
    zx::channel client_end, server_end;
    zx::channel::create(0, &client_end, &server_end);
    fuchsia::ui::scenic::SessionPtr client;
    client.Bind(std::move(client_end));
    session_ = std::make_unique<MockScenicSession>(std::move(client));
  }

  void TearDown() override { session_.reset(); }
};

TEST_F(ScenicSessionFlushTest, AddOneInputCommand) {
  fuchsia::ui::input::SendPointerInputCmd send_pointer_input_cmd;

  fuchsia::ui::input::Command input_cmd;
  input_cmd.set_send_pointer_input(send_pointer_input_cmd);

  fuchsia::ui::scenic::Command cmd;
  cmd.set_input(std::move(input_cmd));

  session_->Enqueue(std::move(cmd));

  EXPECT_EQ(session_->num_flushed_, 1);
  EXPECT_EQ(session_->num_commands(), 0u);
  EXPECT_EQ(session_->num_bytes(),
            // See commands_sizing_test.cc for details.
            scenic::kEnqueueRequestBaseNumBytes + 104u);
  EXPECT_EQ(session_->num_handles(),
            // See commands_sizing_test.cc for details.
            0u);
}

TEST_F(ScenicSessionFlushTest, AddTwoInputCommands) {
  for (int64_t i = 0; i < 2; ++i) {
    fuchsia::ui::input::SendPointerInputCmd send_pointer_input_cmd;

    fuchsia::ui::input::Command input_cmd;
    input_cmd.set_send_pointer_input(send_pointer_input_cmd);

    fuchsia::ui::scenic::Command cmd;
    cmd.set_input(std::move(input_cmd));

    session_->Enqueue(std::move(cmd));
  }

  EXPECT_EQ(session_->num_flushed_, 2);
  EXPECT_EQ(session_->num_commands(), 0u);

  // The overriden Flush does not reset byte and handle counts, so we accumulate each
  // command's size.
  EXPECT_EQ(session_->num_bytes(),
            // See commands_sizing_test.cc for details.
            scenic::kEnqueueRequestBaseNumBytes + 2 * 104u);
  EXPECT_EQ(session_->num_handles(),
            // See commands_sizing_test.cc for details.
            0u);
}

TEST_F(ScenicSessionFlushTest, AddTenNonInputCommandsThenOneInputCommand) {
  for (int64_t i = 0; i < 10; ++i) {
    fuchsia::ui::gfx::MemoryArgs memory_args;

    fuchsia::ui::gfx::ResourceArgs resource_args;
    resource_args.set_memory(std::move(memory_args));

    fuchsia::ui::gfx::CreateResourceCmd create_resource_cmd;
    create_resource_cmd.resource = std::move(resource_args);

    fuchsia::ui::gfx::Command gfx_cmd;
    gfx_cmd.set_create_resource(std::move(create_resource_cmd));

    fuchsia::ui::scenic::Command cmd;
    cmd.set_gfx(std::move(gfx_cmd));

    session_->Enqueue(std::move(cmd));
  }

  // We accumulate all commands (without ever flushing).
  EXPECT_EQ(session_->num_flushed_, 0u);
  EXPECT_EQ(session_->num_commands(), 10u);
  EXPECT_EQ(session_->num_bytes(),
            // See commands_sizing_test.cc for details.
            scenic::kEnqueueRequestBaseNumBytes + 10 * 104u);
  EXPECT_EQ(session_->num_handles(),
            // See commands_sizing_test.cc for details.
            10 * 1u);

  {
    fuchsia::ui::input::SendPointerInputCmd send_pointer_input_cmd;

    fuchsia::ui::input::Command input_cmd;
    input_cmd.set_send_pointer_input(send_pointer_input_cmd);

    fuchsia::ui::scenic::Command cmd;
    cmd.set_input(std::move(input_cmd));

    session_->Enqueue(std::move(cmd));
  }

  // Since input commands are eagerly flushed, we send all eleven commands at
  // once.
  EXPECT_EQ(session_->num_flushed_, 1u);
  EXPECT_EQ(session_->num_commands(), 0u);
  EXPECT_EQ(session_->num_bytes(),
            // See commands_sizing_test.cc for details.
            scenic::kEnqueueRequestBaseNumBytes + 11 * 104u);
  EXPECT_EQ(session_->num_handles(),
            // See commands_sizing_test.cc for details.
            10 * 1u);
}

TEST_F(ScenicSessionFlushTest, AddNonInputCommandThenPresent) {
  // Enqueue CreateResourceCmd
  {
    fuchsia::ui::gfx::MemoryArgs memory_args;

    fuchsia::ui::gfx::ResourceArgs resource_args;
    resource_args.set_memory(std::move(memory_args));

    fuchsia::ui::gfx::CreateResourceCmd create_resource_cmd;
    create_resource_cmd.resource = std::move(resource_args);

    fuchsia::ui::gfx::Command gfx_cmd;
    gfx_cmd.set_create_resource(std::move(create_resource_cmd));

    fuchsia::ui::scenic::Command cmd;
    cmd.set_gfx(std::move(gfx_cmd));

    session_->Enqueue(std::move(cmd));
  }

  // The enqueued command has not been flushed, but will be when we present.
  EXPECT_EQ(session_->num_flushed_, 0);

  // Present
  auto callback = [&](fuchsia::images::PresentationInfo info) {};
  session_->Present(0u, std::move(callback));

  // And check that we've flushed.
  EXPECT_EQ(session_->num_flushed_, 1);
}

TEST_F(ScenicSessionFlushTest, AddNonInputCommandThenPresent2) {
  // Enqueue CreateResourceCmd
  {
    fuchsia::ui::gfx::MemoryArgs memory_args;

    fuchsia::ui::gfx::ResourceArgs resource_args;
    resource_args.set_memory(std::move(memory_args));

    fuchsia::ui::gfx::CreateResourceCmd create_resource_cmd;
    create_resource_cmd.resource = std::move(resource_args);

    fuchsia::ui::gfx::Command gfx_cmd;
    gfx_cmd.set_create_resource(std::move(create_resource_cmd));

    fuchsia::ui::scenic::Command cmd;
    cmd.set_gfx(std::move(gfx_cmd));

    session_->Enqueue(std::move(cmd));
  }

  // The enqueued command has not been flushed, but will be when we present.
  EXPECT_EQ(session_->num_flushed_, 0);

  // Present2
  auto callback = [&](fuchsia::scenic::scheduling::FuturePresentationTimes info) {};
  session_->Present2(0u, 0u, std::move(callback));

  // And check that we've flushed.
  EXPECT_EQ(session_->num_flushed_, 1);
}

}  // namespace
