// Copyright 2013 The Flutter 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 "flutter/testing/testing.h"
#include "impeller/renderer/backend/vulkan/command_encoder_vk.h"
#include "impeller/renderer/backend/vulkan/pass_bindings_cache.h"
#include "impeller/renderer/backend/vulkan/test/mock_vulkan.h"

namespace impeller {
namespace testing {

namespace {
int32_t CountStringViewInstances(const std::vector<std::string>& strings,
                                 std::string_view target) {
  int32_t count = 0;
  for (const std::string& str : strings) {
    if (str == target) {
      count++;
    }
  }
  return count;
}
}  // namespace

TEST(PassBindingsCacheTest, bindPipeline) {
  auto context = MockVulkanContextBuilder().Build();
  PassBindingsCache cache;
  auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
  auto buffer = encoder->GetCommandBuffer();
  VkPipeline vk_pipeline = reinterpret_cast<VkPipeline>(0xfeedface);
  vk::Pipeline pipeline(vk_pipeline);
  cache.BindPipeline(buffer, vk::PipelineBindPoint::eGraphics, pipeline);
  cache.BindPipeline(buffer, vk::PipelineBindPoint::eGraphics, pipeline);
  std::shared_ptr<std::vector<std::string>> functions =
      GetMockVulkanFunctions(context->GetDevice());
  EXPECT_EQ(CountStringViewInstances(*functions, "vkCmdBindPipeline"), 1);
}

TEST(PassBindingsCacheTest, setStencilReference) {
  auto context = MockVulkanContextBuilder().Build();
  PassBindingsCache cache;
  auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
  auto buffer = encoder->GetCommandBuffer();
  cache.SetStencilReference(
      buffer, vk::StencilFaceFlagBits::eVkStencilFrontAndBack, 123);
  cache.SetStencilReference(
      buffer, vk::StencilFaceFlagBits::eVkStencilFrontAndBack, 123);
  std::shared_ptr<std::vector<std::string>> functions =
      GetMockVulkanFunctions(context->GetDevice());
  EXPECT_EQ(CountStringViewInstances(*functions, "vkCmdSetStencilReference"),
            1);
}

TEST(PassBindingsCacheTest, setScissor) {
  auto context = MockVulkanContextBuilder().Build();
  PassBindingsCache cache;
  auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
  auto buffer = encoder->GetCommandBuffer();
  vk::Rect2D scissors;
  cache.SetScissor(buffer, 0, 1, &scissors);
  cache.SetScissor(buffer, 0, 1, &scissors);
  std::shared_ptr<std::vector<std::string>> functions =
      GetMockVulkanFunctions(context->GetDevice());
  EXPECT_EQ(CountStringViewInstances(*functions, "vkCmdSetScissor"), 1);
}

TEST(PassBindingsCacheTest, setViewport) {
  auto context = MockVulkanContextBuilder().Build();
  PassBindingsCache cache;
  auto encoder = std::make_unique<CommandEncoderFactoryVK>(context)->Create();
  auto buffer = encoder->GetCommandBuffer();
  vk::Viewport viewports;
  cache.SetViewport(buffer, 0, 1, &viewports);
  cache.SetViewport(buffer, 0, 1, &viewports);
  std::shared_ptr<std::vector<std::string>> functions =
      GetMockVulkanFunctions(context->GetDevice());
  EXPECT_EQ(CountStringViewInstances(*functions, "vkCmdSetViewport"), 1);
}

}  // namespace testing
}  // namespace impeller
