// Copyright 2024 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <dawn/webgpu_cpp_print.h>
#include <emscripten.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <webgpu/webgpu_cpp.h>

#include <string>
#include <utility>

namespace {

using testing::_;
using testing::HasSubstr;

class InstanceLevelTests : public testing::Test {
  public:
    void SetUp() override {
        wgpu::InstanceDescriptor descriptor = {};
        // The unit tests use wgpuInstanceWaitAny(WGPUFuture, timeoutNS) with timeoutNS > 0
        // which requires TimedWaitAny enabled on the instance.
        static constexpr auto kTimedWaitAny = wgpu::InstanceFeatureName::TimedWaitAny;
        descriptor.requiredFeatureCount = 1;
        descriptor.requiredFeatures = &kTimedWaitAny;
        instance = wgpu::CreateInstance(&descriptor);
    }

  protected:
    wgpu::Adapter RequestAdapter(const wgpu::RequestAdapterOptions* adapterOptions = nullptr) {
        // TODO(crbug.com/404535888): Remove this sleep once we figure out regression.
        static bool sSleepWorkaround = false;
        if (!sSleepWorkaround) {
            // Make the test sleep for an additional 2 seconds before trying to requestAdapter.
            emscripten_sleep(2000);
            sSleepWorkaround = true;
        }

        wgpu::RequestAdapterStatus status;
        wgpu::Adapter result = nullptr;
        EXPECT_EQ(instance.WaitAny(
                      instance.RequestAdapter(
                          adapterOptions, wgpu::CallbackMode::AllowSpontaneous,
                          [&status, &result](wgpu::RequestAdapterStatus s, wgpu::Adapter adapter,
                                             wgpu::StringView message) {
                              status = s;
                              result = std::move(adapter);
                          }),
                      UINT64_MAX),
                  wgpu::WaitStatus::Success);
        EXPECT_EQ(status, wgpu::RequestAdapterStatus::Success);
        return result;
    }

    wgpu::Instance instance;
};

TEST_F(InstanceLevelTests, RequestAdapter) {
    EXPECT_NE(RequestAdapter(), nullptr);
}

class AdapterLevelTests : public InstanceLevelTests {
  public:
    void SetUp() override {
        InstanceLevelTests::SetUp();
        adapter = RequestAdapter();
    }

  protected:
    wgpu::Device RequestDevice(const wgpu::DeviceDescriptor* descriptor = nullptr) {
        wgpu::RequestDeviceStatus status;
        wgpu::Device result = nullptr;
        EXPECT_EQ(
            instance.WaitAny(adapter.RequestDevice(
                                 descriptor, wgpu::CallbackMode::AllowSpontaneous,
                                 [&status, &result](wgpu::RequestDeviceStatus s,
                                                    wgpu::Device device, wgpu::StringView message) {
                                     status = s;
                                     result = std::move(device);
                                 }),
                             UINT64_MAX),
            wgpu::WaitStatus::Success);
        EXPECT_EQ(status, wgpu::RequestDeviceStatus::Success);
        return result;
    }

    wgpu::Adapter adapter;
};

TEST_F(AdapterLevelTests, RequestDevice) {
    EXPECT_NE(RequestDevice(), nullptr);
}

TEST_F(AdapterLevelTests, RequestDeviceThenDestroy) {
    wgpu::Device device = nullptr;
    wgpu::DeviceLostReason reason{};

    wgpu::DeviceDescriptor descriptor = {};
    descriptor.SetDeviceLostCallback(
        wgpu::CallbackMode::AllowSpontaneous,
        [&device, &reason](const wgpu::Device& d, wgpu::DeviceLostReason r, wgpu::StringView) {
            reason = r;
            EXPECT_EQ(device.Get(), d.Get());
        });
    device = RequestDevice(&descriptor);

    auto deviceLostFuture = device.GetLostFuture();
    device.Destroy();
    ASSERT_EQ(instance.WaitAny(deviceLostFuture, UINT64_MAX), wgpu::WaitStatus::Success);
    EXPECT_EQ(reason, wgpu::DeviceLostReason::Destroyed);
}

TEST_F(AdapterLevelTests, RequestDeviceThenDrop) {
    wgpu::DeviceLostReason reason{};

    wgpu::DeviceDescriptor descriptor = {};
    descriptor.SetDeviceLostCallback(
        wgpu::CallbackMode::AllowSpontaneous,
        [&reason](const wgpu::Device& d, wgpu::DeviceLostReason r, wgpu::StringView) {
            reason = r;
            // d should be null even though this is called during wgpuDeviceRelease()
            // so the allocation hasn't been freed yet.
            EXPECT_EQ(nullptr, d.Get());
        });
    wgpu::Device device = RequestDevice(&descriptor);

    auto deviceLostFuture = device.GetLostFuture();
    device = nullptr;
    ASSERT_EQ(instance.WaitAny(deviceLostFuture, UINT64_MAX), wgpu::WaitStatus::Success);
    EXPECT_EQ(reason, wgpu::DeviceLostReason::Destroyed);
}

class DeviceLevelTests : public AdapterLevelTests {
  public:
    void SetUp() override {
        AdapterLevelTests::SetUp();

        wgpu::DeviceDescriptor descriptor = {};
        descriptor.SetDeviceLostCallback(
            wgpu::CallbackMode::AllowSpontaneous,
            [](const wgpu::Device&, wgpu::DeviceLostReason reason, wgpu::StringView) {
                EXPECT_EQ(reason, wgpu::DeviceLostReason::Destroyed);
            });
        descriptor.SetUncapturedErrorCallback(
            [](const wgpu::Device& d, wgpu::ErrorType t, wgpu::StringView m,
               DeviceLevelTests* self) { self->uncapturedErrorCb.Call(d, t, m); },
            this);
        device = RequestDevice(&descriptor);
    }

    void TearDown() override {
        // For teardown, we explicitly wait for the device lost so that we can ensure that errors
        // have been flushed.
        auto deviceLostFuture = device.GetLostFuture();
        device = nullptr;
        EXPECT_EQ(instance.WaitAny(deviceLostFuture, UINT64_MAX), wgpu::WaitStatus::Success);
    }

  protected:
    wgpu::ShaderModule CreateShaderModule(const char* source) {
        wgpu::ShaderSourceWGSL wgsl;
        wgsl.code = source;
        wgpu::ShaderModuleDescriptor desc;
        desc.nextInChain = &wgsl;
        return device.CreateShaderModule(&desc);
    }

    wgpu::Device device;

    // Mock callback used for uncaptured errors so that test writers can add expectations on this
    // callback which will enforce the expectations at teardown of the test.
    testing::StrictMock<
        testing::MockFunction<void(const wgpu::Device&, wgpu::ErrorType, wgpu::StringView)>>
        uncapturedErrorCb;
};

TEST_F(DeviceLevelTests, ValidationError) {
    EXPECT_CALL(uncapturedErrorCb, Call(_, wgpu::ErrorType::Validation, _)).Times(1);

    wgpu::BufferDescriptor desc = {};
    desc.size = 1024;
    desc.usage = static_cast<wgpu::BufferUsage>(UINT64_MAX);
    wgpu::Buffer buffer = device.CreateBuffer(&desc);
}

TEST_F(DeviceLevelTests, PopErrorScope) {
    device.PushErrorScope(wgpu::ErrorFilter::Validation);

    wgpu::BufferDescriptor desc = {};
    desc.size = 1024;
    desc.usage = static_cast<wgpu::BufferUsage>(UINT64_MAX);
    wgpu::Buffer buffer = device.CreateBuffer(&desc);

    wgpu::PopErrorScopeStatus status;
    wgpu::ErrorType type;
    EXPECT_EQ(instance.WaitAny(
                  device.PopErrorScope(wgpu::CallbackMode::AllowSpontaneous,
                                       [&status, &type](wgpu::PopErrorScopeStatus s,
                                                        wgpu::ErrorType t, wgpu::StringView) {
                                           status = s;
                                           type = t;
                                       }),
                  UINT64_MAX),
              wgpu::WaitStatus::Success);
    EXPECT_EQ(status, wgpu::PopErrorScopeStatus::Success);
    EXPECT_EQ(type, wgpu::ErrorType::Validation);
}

TEST_F(DeviceLevelTests, BufferMapAndWorkDone) {
    static constexpr uint32_t kData = 100u;
    size_t kSize = sizeof(uint32_t);

    wgpu::Buffer src;
    wgpu::Buffer dst;
    {
        wgpu::BufferDescriptor desc;
        desc.label = "src";
        desc.size = kSize;
        desc.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::MapWrite;
        src = device.CreateBuffer(&desc);
    }
    {
        wgpu::BufferDescriptor desc;
        desc.label = "dst";
        desc.size = kSize;
        desc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead;
        dst = device.CreateBuffer(&desc);
    }

    // Map the writable buffer and write to it.
    wgpu::MapAsyncStatus writeStatus;
    EXPECT_EQ(instance.WaitAny(
                  src.MapAsync(wgpu::MapMode::Write, 0, kSize, wgpu::CallbackMode::AllowSpontaneous,
                               [&writeStatus](wgpu::MapAsyncStatus status, wgpu::StringView) {
                                   writeStatus = status;
                               }),
                  UINT64_MAX),
              wgpu::WaitStatus::Success);
    ASSERT_EQ(writeStatus, wgpu::MapAsyncStatus::Success);
    auto writeData = static_cast<uint32_t*>(src.GetMappedRange());
    ASSERT_NE(writeData, nullptr);
    *writeData = kData;
    src.Unmap();

    // Copy the buffer to the readable one, and wait for the copy to complete. Note that the wait
    // for the copy is not strictly necessary since the map async call following it will already
    // wait for it, but we do it explicitly here to test the additional entry point.
    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    encoder.CopyBufferToBuffer(src, 0, dst, 0, kSize);
    wgpu::CommandBuffer commands = encoder.Finish();
    wgpu::Queue queue = device.GetQueue();
    queue.Submit(1, &commands);

    wgpu::QueueWorkDoneStatus copyStatus;
    EXPECT_EQ(instance.WaitAny(queue.OnSubmittedWorkDone(
                                   wgpu::CallbackMode::AllowSpontaneous,
                                   [&copyStatus](wgpu::QueueWorkDoneStatus status,
                                                 wgpu::StringView) { copyStatus = status; }),
                               UINT64_MAX),
              wgpu::WaitStatus::Success);
    ASSERT_EQ(copyStatus, wgpu::QueueWorkDoneStatus::Success);

    // Map the readable buffer and verify the contents.
    wgpu::MapAsyncStatus readStatus;
    EXPECT_EQ(instance.WaitAny(
                  dst.MapAsync(wgpu::MapMode::Read, 0, kSize, wgpu::CallbackMode::AllowSpontaneous,
                               [&readStatus](wgpu::MapAsyncStatus status, wgpu::StringView) {
                                   readStatus = status;
                               }),
                  UINT64_MAX),
              wgpu::WaitStatus::Success);
    ASSERT_EQ(readStatus, wgpu::MapAsyncStatus::Success);
    auto readData = static_cast<const uint32_t*>(dst.GetConstMappedRange());
    ASSERT_NE(readData, nullptr);
    EXPECT_EQ(*readData, kData);
    dst.Unmap();
}

TEST_F(DeviceLevelTests, CreateComputePipelineAsync) {
    wgpu::ComputePipelineDescriptor desc;
    desc.compute.module = CreateShaderModule(R"(
        @compute @workgroup_size(1) fn main() {}
    )");

    wgpu::CreatePipelineAsyncStatus status;
    wgpu::ComputePipeline pipeline = nullptr;
    EXPECT_EQ(instance.WaitAny(device.CreateComputePipelineAsync(
                                   &desc, wgpu::CallbackMode::AllowSpontaneous,
                                   [&status, &pipeline](wgpu::CreatePipelineAsyncStatus s,
                                                        wgpu::ComputePipeline p, wgpu::StringView) {
                                       status = s;
                                       pipeline = std::move(p);
                                   }),
                               UINT64_MAX),
              wgpu::WaitStatus::Success);
    EXPECT_EQ(status, wgpu::CreatePipelineAsyncStatus::Success);
    EXPECT_NE(pipeline, nullptr);
}

TEST_F(DeviceLevelTests, CreateRenderPipelineAsync) {
    wgpu::RenderPipelineDescriptor desc;
    desc.vertex.module = CreateShaderModule(R"(
        @vertex fn main() -> @builtin(position) vec4f {
            return vec4f(0.0, 0.0, 0.0, 1.0);
        }
    )");

    wgpu::FragmentState frag;
    frag.module = CreateShaderModule(R"(
        @fragment fn main() -> @location(0) vec4f {
            return vec4f(0.0, 1.0, 0.0, 1.0);
        }
    )");
    wgpu::ColorTargetState target;
    target.format = wgpu::TextureFormat::RGBA8Unorm;
    frag.targetCount = 1;
    frag.targets = &target;
    desc.fragment = &frag;

    wgpu::CreatePipelineAsyncStatus status;
    wgpu::RenderPipeline pipeline = nullptr;
    EXPECT_EQ(instance.WaitAny(device.CreateRenderPipelineAsync(
                                   &desc, wgpu::CallbackMode::AllowSpontaneous,
                                   [&status, &pipeline](wgpu::CreatePipelineAsyncStatus s,
                                                        wgpu::RenderPipeline p, wgpu::StringView) {
                                       status = s;
                                       pipeline = std::move(p);
                                   }),
                               UINT64_MAX),
              wgpu::WaitStatus::Success);
    EXPECT_EQ(status, wgpu::CreatePipelineAsyncStatus::Success);
    EXPECT_NE(pipeline, nullptr);
}

TEST_F(DeviceLevelTests, GetCompilationInfo) {
    wgpu::ShaderModule shader = CreateShaderModule(R"(
        @fragment fn main(@location(0) x : f32) {
            return;
            return;
        }
    )");

    wgpu::CompilationMessageType messageType;
    std::string message;
    bool hasUtf16 = false;
    EXPECT_EQ(instance.WaitAny(
                  shader.GetCompilationInfo(
                      wgpu::CallbackMode::AllowSpontaneous,
                      [&message, &messageType, &hasUtf16](wgpu::CompilationInfoRequestStatus s,
                                                          const wgpu::CompilationInfo* info) {
                          ASSERT_EQ(s, wgpu::CompilationInfoRequestStatus::Success);
                          ASSERT_NE(info, nullptr);
                          ASSERT_EQ(info->messageCount, 1);

                          message = info->messages[0].message;
                          messageType = info->messages[0].type;

                          size_t chainLength = 0;
                          for (const auto* chain = info->messages[0].nextInChain; chain != nullptr;
                               chain = chain->nextInChain) {
                              if (chain->sType == wgpu::SType::DawnCompilationMessageUtf16) {
                                  hasUtf16 = true;
                              }
                              chainLength++;
                          }
                          ASSERT_EQ(chainLength, 1);
                      }),
                  UINT64_MAX),
              wgpu::WaitStatus::Success);
    EXPECT_EQ(messageType, wgpu::CompilationMessageType::Warning);
    EXPECT_TRUE(hasUtf16);
    EXPECT_THAT(message, HasSubstr("unreachable"));
}

}  // namespace
