// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gpu/command_buffer/tests/webgpu_test.h"

#include <dawn/dawn_proc.h>
#include <dawn/dawn_thread_dispatch_proc.h>

#include "base/command_line.h"
#include "base/test/bind.h"
#include "base/test/test_simple_task_runner.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
#include "components/viz/test/test_gpu_service_holder.h"
#include "gpu/command_buffer/client/webgpu_cmd_helper.h"
#include "gpu/command_buffer/client/webgpu_implementation.h"
#include "gpu/command_buffer/service/service_utils.h"
#include "gpu/command_buffer/service/webgpu_decoder.h"
#include "gpu/config/gpu_test_config.h"
#include "gpu/ipc/in_process_command_buffer.h"
#include "gpu/ipc/webgpu_in_process_context.h"
#include "gpu/webgpu/callback.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace gpu {

namespace {

void CountCallback(int* count) {
  (*count)++;
}

}  // anonymous namespace

#define SKIP_TEST_IF(condition) \
  if (condition)                \
  GTEST_SKIP() << #condition

WebGPUTest::Options::Options() = default;

std::map<std::pair<WGPUDevice, wgpu::ErrorType>, /* matched */ bool>
    WebGPUTest::s_expected_errors = {};

WebGPUTest::WebGPUTest() = default;
WebGPUTest::~WebGPUTest() = default;

bool WebGPUTest::WebGPUSupported() const {
  // Nexus 5X does not support WebGPU
  if (GPUTestBotConfig::CurrentConfigMatches("Android Qualcomm 0x4010800")) {
    return false;
  }

  // Pixel 2 does not support WebGPU
  if (GPUTestBotConfig::CurrentConfigMatches("Android Qualcomm 0x5040001")) {
    return false;
  }

  return true;
}

bool WebGPUTest::WebGPUSharedImageSupported() const {
  // Currently WebGPUSharedImage is only implemented on Mac, Linux, Windows
  // and ChromeOS.
#if (BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
     BUILDFLAG(IS_WIN)) &&                                                 \
    BUILDFLAG(USE_DAWN)
  // TODO(crbug.com/40166640): Re-enable on AMD when the RX 5500 XT issues are
  // resolved.
  return !GPUTestBotConfig::CurrentConfigMatches("Linux AMD");
#else
  return false;
#endif
}

void WebGPUTest::SetUp() {
  SKIP_TEST_IF(!WebGPUSupported());
}

void WebGPUTest::TearDown() {
  adapter_ = nullptr;
  instance_ = nullptr;
  cmd_helper_ = nullptr;
  context_ = nullptr;
}

void WebGPUTest::Initialize(const Options& options) {
  // Some tests that inherit from WebGPUTest call Initialize in SetUp, which
  // won't be skipped even if the SKIP_TEST_IF in WebGPUTest::SetUp() is
  // triggered. As a result, to avoid potential crashes, skip initializing if
  // this device has been marked as not supporting WebGPU.
  if (!WebGPUSupported()) {
    return;
  }

  gpu::GpuPreferences gpu_preferences;
  gpu_preferences.enable_webgpu = true;
  gpu_preferences.use_passthrough_cmd_decoder =
      gles2::UsePassthroughCommandDecoder(
          base::CommandLine::ForCurrentProcess());
  if (options.use_skia_graphite) {
    gpu_preferences.gr_context_type = gpu::GrContextType::kGraphiteDawn;
  } else {
#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && BUILDFLAG(USE_DAWN)
    gpu_preferences.use_vulkan = gpu::VulkanImplementationName::kNative;
    gpu_preferences.gr_context_type = gpu::GrContextType::kVulkan;
#endif
  }
  gpu_preferences.enable_unsafe_webgpu = options.enable_unsafe_webgpu;
  if (!options.adapter_blocklist) {
    gpu_preferences.disabled_dawn_features_list = {"adapter_blocklist"};
  }

  gpu_service_holder_ =
      std::make_unique<viz::TestGpuServiceHolder>(gpu_preferences);

  context_ = std::make_unique<WebGPUInProcessContext>();
  ContextResult result =
      context_->Initialize(gpu_service_holder_->task_executor());
  ASSERT_EQ(result, ContextResult::kSuccess) << "Context failed to initialize";

  cmd_helper_ = std::make_unique<webgpu::WebGPUCmdHelper>(
      context_->GetCommandBufferForTest());

  webgpu_impl()->SetLostContextCallback(base::BindLambdaForTesting(
      []() { GTEST_FAIL() << "Context lost unexpectedly."; }));

  // Use the wire procs for the test main thread.
  dawnProcSetPerThreadProcs(&dawn::wire::client::GetProcs());

  instance_ = wgpu::Instance(webgpu()->GetAPIChannel()->GetWGPUInstance());

  wgpu::RequestAdapterOptions ra_options = {};
  ra_options.forceFallbackAdapter = options.force_fallback_adapter;
  ra_options.featureLevel = options.feature_level;

  bool done = false;
  instance_.RequestAdapter(
      &ra_options, wgpu::CallbackMode::AllowSpontaneous,
      [&](wgpu::RequestAdapterStatus status, wgpu::Adapter adapter,
          wgpu::StringView message) {
        if (!options.force_fallback_adapter) {
          // If we don't force a particular adapter, we
          // should always find one.
          EXPECT_EQ(status, wgpu::RequestAdapterStatus::Success);
          EXPECT_NE(adapter, nullptr);
        }
        this->adapter_ = std::move(adapter);
        done = true;
      });
  webgpu()->FlushCommands();
  while (!done) {
    RunPendingTasks();
  }
}

webgpu::WebGPUInterface* WebGPUTest::webgpu() const {
  return context_->GetImplementation();
}

webgpu::WebGPUImplementation* WebGPUTest::webgpu_impl() const {
  return context_->GetImplementation();
}

webgpu::WebGPUCmdHelper* WebGPUTest::webgpu_cmds() const {
  return cmd_helper_.get();
}

SharedImageInterface* WebGPUTest::GetSharedImageInterface() const {
  return context_->GetCommandBufferForTest()->GetSharedImageInterface();
}

webgpu::WebGPUDecoder* WebGPUTest::GetDecoder() const {
  return context_->GetCommandBufferForTest()->GetWebGPUDecoderForTest();
}

void WebGPUTest::RunPendingTasks() {
  context_->GetTaskRunner()->RunPendingTasks();
  gpu_service_holder_->ScheduleGpuMainTask(base::BindOnce(
      [](webgpu::WebGPUDecoder* decoder) {
        if (decoder->HasPollingWork()) {
          decoder->PerformPollingWork();
        }
      },
      GetDecoder()));
}

void WebGPUTest::WaitForCompletion(wgpu::Device device) {
  // Wait for any work submitted to the queue to be finished. The guarantees of
  // Dawn are that all previous operations will have been completed and more
  // importantly the callbacks will have been called.
  wgpu::FutureWaitInfo wait_info = {device.GetQueue().OnSubmittedWorkDone(
      wgpu::CallbackMode::WaitAnyOnly,
      [](wgpu::QueueWorkDoneStatus, wgpu::StringView) {})};

  while (!wait_info.completed) {
    instance_.WaitAny(1, &wait_info, 0);
    webgpu()->FlushCommands();
    RunPendingTasks();
  }
}

void WebGPUTest::PollUntilIdle() {
  if (!context_ || !gpu_service_holder_) {
    // Never initialized. Test skipped or failed in setup.
    return;
  }
  webgpu()->FlushCommands();
  base::WaitableEvent wait;
  gpu_service_holder_->ScheduleGpuMainTask(
      base::BindLambdaForTesting([&wait, decoder = GetDecoder()]() {
        while (decoder->HasPollingWork()) {
          base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
          decoder->PerformPollingWork();
        }
        wait.Signal();
      }));
  wait.Wait();
  context_->GetTaskRunner()->RunPendingTasks();
}

wgpu::Device WebGPUTest::GetNewDevice(
    std::vector<wgpu::FeatureName> requiredFeatures) {
  wgpu::Device device;
  bool done = false;

  DCHECK(adapter_);
  wgpu::DeviceDescriptor device_desc = {};
  device_desc.requiredFeatureCount = requiredFeatures.size();
  device_desc.requiredFeatures = requiredFeatures.data();

  device_desc.SetDeviceLostCallback(
      wgpu::CallbackMode::AllowSpontaneous,
      [](const wgpu::Device&, wgpu::DeviceLostReason reason,
         wgpu::StringView message) {
        if (reason == wgpu::DeviceLostReason::Destroyed) {
          return;
        }
        GTEST_FAIL() << "Unexpected device lost (" << reason
                     << "): " << message;
      });
  device_desc.SetUncapturedErrorCallback([](const wgpu::Device& device,
                                            wgpu::ErrorType type,
                                            wgpu::StringView message) {
    auto it = s_expected_errors.find(std::make_pair(device.Get(), type));
    if (it != s_expected_errors.end() && !it->second) {
      it->second = true;
      return;
    }
    GTEST_FAIL() << "Unexpected error (" << type << "): " << message;
  });

  adapter_.RequestDevice(
      &device_desc, wgpu::CallbackMode::AllowSpontaneous,
      [&](wgpu::RequestDeviceStatus status, wgpu::Device created_device,
          wgpu::StringView message) {
        // Fail the test with error message if returned status is not success
        if (status != wgpu::RequestDeviceStatus::Success) {
          if (message.length != 0) {
            GTEST_FAIL() << "RequestDevice returns unexpected message: "
                         << message;
          } else {
            GTEST_FAIL()
                << "RequestDevice returns unexpected status without message.";
          }
        }
        device = std::move(created_device);
        done = true;
      });
  webgpu()->FlushCommands();
  while (!done) {
    base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
    RunPendingTasks();
  }

  EXPECT_NE(device, nullptr);
  return device;
}

TEST_F(WebGPUTest, FlushNoCommands) {
  Initialize(WebGPUTest::Options());

  webgpu()->FlushCommands();
}

// Referred from GLES2ImplementationTest/ReportLoss
TEST_F(WebGPUTest, ReportLoss) {
  Initialize(WebGPUTest::Options());

  GpuControlClient* webgpu_as_client = webgpu_impl();
  int lost_count = 0;
  webgpu_impl()->SetLostContextCallback(
      base::BindOnce(&CountCallback, &lost_count));
  EXPECT_EQ(0, lost_count);

  webgpu_as_client->OnGpuControlLostContext();
  // The lost context callback should be run when WebGPUImplementation is
  // notified of the loss.
  EXPECT_EQ(1, lost_count);
}

// Referred from GLES2ImplementationTest/ReportLossReentrant
TEST_F(WebGPUTest, ReportLossReentrant) {
  Initialize(WebGPUTest::Options());

  GpuControlClient* webgpu_as_client = webgpu_impl();
  int lost_count = 0;
  webgpu_impl()->SetLostContextCallback(
      base::BindOnce(&CountCallback, &lost_count));
  EXPECT_EQ(0, lost_count);

  webgpu_as_client->OnGpuControlLostContextMaybeReentrant();
  // The lost context callback should not be run yet to avoid calling back into
  // clients re-entrantly, and having them re-enter WebGPUImplementation.
  EXPECT_EQ(0, lost_count);
}

TEST_F(WebGPUTest, RequestAdapterAfterContextLost) {
  Initialize(WebGPUTest::Options());

  webgpu_impl()->SetLostContextCallback(base::DoNothing());
  webgpu_impl()->OnGpuControlLostContext();

  bool called = false;
  wgpu::RequestAdapterOptions ra_options = {};
  instance_.RequestAdapter(
      &ra_options, wgpu::CallbackMode::AllowSpontaneous,
      [&](wgpu::RequestAdapterStatus status, wgpu::Adapter adapter,
          wgpu::StringView message) {
        EXPECT_EQ(adapter, nullptr);
        called = true;
      });
  webgpu()->FlushCommands();
  RunPendingTasks();
  EXPECT_TRUE(called);
}

TEST_F(WebGPUTest, RequestDeviceAfterContextLost) {
  Initialize(WebGPUTest::Options());

  webgpu_impl()->SetLostContextCallback(base::DoNothing());
  webgpu_impl()->OnGpuControlLostContext();

  bool called = false;

  DCHECK(adapter_);
  wgpu::DeviceDescriptor device_desc = {};
  adapter_.RequestDevice(&device_desc, wgpu::CallbackMode::AllowSpontaneous,
                         [&](wgpu::RequestDeviceStatus status,
                             wgpu::Device device, wgpu::StringView message) {
                           EXPECT_EQ(device, nullptr);
                           called = true;
                         });
  webgpu()->FlushCommands();
  RunPendingTasks();
  EXPECT_TRUE(called);
}

TEST_F(WebGPUTest, RequestDeviceWithUnsupportedFeature) {
  Initialize(WebGPUTest::Options());

  // Create device with unsupported features, expect to fail to create and
  // return nullptr
  wgpu::FeatureName invalid_feature = static_cast<wgpu::FeatureName>(-2);

  wgpu::Device device;
  bool done = false;

  DCHECK(adapter_);
  wgpu::DeviceDescriptor device_desc = {};
  device_desc.requiredFeatureCount = 1;
  device_desc.requiredFeatures = &invalid_feature;

  adapter_.RequestDevice(
      &device_desc, wgpu::CallbackMode::AllowSpontaneous,
      [&](wgpu::RequestDeviceStatus status, wgpu::Device created_device,
          wgpu::StringView message) {
        device = std::move(created_device);
        done = true;
      });
  webgpu()->FlushCommands();

  while (!done) {
    RunPendingTasks();
  }
  EXPECT_EQ(device, nullptr);

  // Create device again with supported features, expect success and not
  // blocked by the last failure
  GetNewDevice();
}

TEST_F(WebGPUTest, SPIRVIsDisallowed) {
  auto options = WebGPUTest::Options();
  options.enable_unsafe_webgpu = false;
  Initialize(options);

  wgpu::Device device = GetNewDevice();

  // Make a invalid ShaderModuleDescriptor because it contains SPIR-V.
  wgpu::ShaderSourceSPIRV spirvDesc;
  spirvDesc.codeSize = 0;
  spirvDesc.code = nullptr;

  wgpu::ShaderModuleDescriptor desc;
  desc.nextInChain = &spirvDesc;

  // Make sure creation fails, and for the correct reason.
  device.PushErrorScope(wgpu::ErrorFilter::Validation);
  device.CreateShaderModule(&desc);
  bool got_error = false;
  device.PopErrorScope(wgpu::CallbackMode::AllowSpontaneous,
                       [&](wgpu::PopErrorScopeStatus status,
                           wgpu::ErrorType type, wgpu::StringView message) {
                         // We match on this string to make sure the shader
                         // module creation fails because SPIR-V is disallowed
                         // and not because codeSize=0.
                         EXPECT_THAT(message, testing::HasSubstr("SPIR"));
                         EXPECT_EQ(type, wgpu::ErrorType::Validation);
                         got_error = true;
                       });

  WaitForCompletion(device);
  EXPECT_TRUE(got_error);
}

TEST_F(WebGPUTest, ExplicitFallbackAdapterIsDisallowed) {
  auto options = WebGPUTest::Options();
  options.force_fallback_adapter = true;
  options.enable_unsafe_webgpu = false;
  options.adapter_blocklist = true;
  // Initialize attempts to create an adapter.
  Initialize(options);

  // No fallback adapter should be available.
  EXPECT_EQ(adapter_, nullptr);
}

TEST_F(WebGPUTest, ImplicitFallbackAdapterIsDisallowed) {
  auto options = WebGPUTest::Options();
  options.enable_unsafe_webgpu = false;
  // Initialize attempts to create an adapter.
  Initialize(options);

  if (adapter_) {
    wgpu::AdapterInfo info;
    adapter_.GetInfo(&info);
    // If we got an Adapter, it must not be a CPU adapter.
    EXPECT_NE(info.adapterType, wgpu::AdapterType::CPU);
  }
}

TEST_F(WebGPUTest, CompatibilityMode) {
  auto options = WebGPUTest::Options();
  options.feature_level = wgpu::FeatureLevel::Compatibility;
  options.enable_unsafe_webgpu = true;
  // Initialize attempts to create an adapter.
  Initialize(options);

  // Compatibility adapter should be available.
  EXPECT_NE(adapter_, nullptr);

  // A compat defaulting adapter could optionally have the CoreFeaturesAndLimits
  // feature.
}

TEST_F(WebGPUTest, NonCompatibilityMode) {
  auto options = WebGPUTest::Options();
  options.feature_level = wgpu::FeatureLevel::Core;
  options.enable_unsafe_webgpu = true;
  // Initialize attempts to create an adapter.
  Initialize(options);

  // Non-compatibility adapter should be available.
  EXPECT_NE(adapter_, nullptr);

  // A core defaulting adapter must have the CoreFeaturesAndLimits feature.
  EXPECT_TRUE(adapter_.HasFeature(wgpu::FeatureName::CoreFeaturesAndLimits));
}

}  // namespace gpu
