// Copyright 2019 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <gtest/gtest.h>

#include "dawn/dawn_proc.h"
#include "dawn_native/Instance.h"
#include "dawn_native/null/DeviceNull.h"
#include "dawn_wire/WireClient.h"
#include "utils/TerribleCommandBuffer.h"

namespace {

    // dawn_wire and dawn_native contain duplicated code for the handling of GetProcAddress
    // so we run the tests against both implementations. This enum is used as a test parameters to
    // know which implementation to test.
    enum class DawnFlavor {
        Native,
        Wire,
    };

    std::ostream& operator<<(std::ostream& stream, DawnFlavor flavor) {
        switch (flavor) {
            case DawnFlavor::Native:
                stream << "dawn_native";
                break;

            case DawnFlavor::Wire:
                stream << "dawn_wire";
                break;

            default:
                UNREACHABLE();
                break;
        }
        return stream;
    }

    class GetProcAddressTests : public testing::TestWithParam<DawnFlavor> {
      public:
        GetProcAddressTests()
            : testing::TestWithParam<DawnFlavor>(),
              mNativeInstance(dawn_native::InstanceBase::Create()),
              mNativeAdapter(mNativeInstance.Get()) {
        }

        void SetUp() override {
            switch (GetParam()) {
                case DawnFlavor::Native: {
                    mDevice = wgpu::Device::Acquire(
                        reinterpret_cast<WGPUDevice>(mNativeAdapter.APICreateDevice()));
                    mProcs = dawn_native::GetProcs();
                    break;
                }

                case DawnFlavor::Wire: {
                    mC2sBuf = std::make_unique<utils::TerribleCommandBuffer>();

                    dawn::wire::WireClientDescriptor clientDesc = {};
                    clientDesc.serializer = mC2sBuf.get();
                    mWireClient = std::make_unique<dawn::wire::WireClient>(clientDesc);

                    mDevice = wgpu::Device::Acquire(mWireClient->ReserveDevice().device);
                    mProcs = dawn::wire::client::GetProcs();
                    break;
                }

                default:
                    UNREACHABLE();
                    break;
            }

            dawnProcSetProcs(&mProcs);
        }

        void TearDown() override {
            // Destroy the device before freeing the instance or the wire client in the destructor
            mDevice = wgpu::Device();
        }

      protected:
        Ref<dawn_native::InstanceBase> mNativeInstance;
        dawn_native::null::Adapter mNativeAdapter;

        std::unique_ptr<utils::TerribleCommandBuffer> mC2sBuf;
        std::unique_ptr<dawn::wire::WireClient> mWireClient;

        wgpu::Device mDevice;
        DawnProcTable mProcs;
    };

    // Test GetProcAddress with and without devices on some valid examples
    TEST_P(GetProcAddressTests, ValidExamples) {
        ASSERT_EQ(mProcs.getProcAddress(nullptr, "wgpuDeviceCreateBuffer"),
                  reinterpret_cast<WGPUProc>(mProcs.deviceCreateBuffer));
        ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), "wgpuDeviceCreateBuffer"),
                  reinterpret_cast<WGPUProc>(mProcs.deviceCreateBuffer));
        ASSERT_EQ(mProcs.getProcAddress(nullptr, "wgpuQueueSubmit"),
                  reinterpret_cast<WGPUProc>(mProcs.queueSubmit));
        ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), "wgpuQueueSubmit"),
                  reinterpret_cast<WGPUProc>(mProcs.queueSubmit));
    }

    // Test GetProcAddress with and without devices on nullptr procName
    TEST_P(GetProcAddressTests, Nullptr) {
        ASSERT_EQ(mProcs.getProcAddress(nullptr, nullptr), nullptr);
        ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), nullptr), nullptr);
    }

    // Test GetProcAddress with and without devices on some invalid
    TEST_P(GetProcAddressTests, InvalidExamples) {
        ASSERT_EQ(mProcs.getProcAddress(nullptr, "wgpuDeviceDoSomething"), nullptr);
        ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), "wgpuDeviceDoSomething"), nullptr);

        // Trigger the condition where lower_bound will return the end of the procMap.
        ASSERT_EQ(mProcs.getProcAddress(nullptr, "zzzzzzz"), nullptr);
        ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), "zzzzzzz"), nullptr);
        ASSERT_EQ(mProcs.getProcAddress(nullptr, "ZZ"), nullptr);
        ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), "ZZ"), nullptr);

        // Some more potential corner cases.
        ASSERT_EQ(mProcs.getProcAddress(nullptr, ""), nullptr);
        ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), ""), nullptr);
        ASSERT_EQ(mProcs.getProcAddress(nullptr, "0"), nullptr);
        ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), "0"), nullptr);
    }

    // Test that GetProcAddress supports freestanding function that are handled specially
    TEST_P(GetProcAddressTests, FreeStandingFunctions) {
        ASSERT_EQ(mProcs.getProcAddress(nullptr, "wgpuGetProcAddress"),
                  reinterpret_cast<WGPUProc>(mProcs.getProcAddress));
        ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), "wgpuGetProcAddress"),
                  reinterpret_cast<WGPUProc>(mProcs.getProcAddress));

        ASSERT_EQ(mProcs.getProcAddress(nullptr, "wgpuCreateInstance"),
                  reinterpret_cast<WGPUProc>(mProcs.createInstance));
        ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), "wgpuCreateInstance"),
                  reinterpret_cast<WGPUProc>(mProcs.createInstance));
    }

    INSTANTIATE_TEST_SUITE_P(,
                             GetProcAddressTests,
                             testing::Values(DawnFlavor::Native, DawnFlavor::Wire),
                             testing::PrintToStringParamName());

    TEST(GetProcAddressInternalTests, CheckDawnNativeProcMapOrder) {
        std::vector<const char*> names = dawn_native::GetProcMapNamesForTesting();
        for (size_t i = 1; i < names.size(); i++) {
            ASSERT_LT(std::string(names[i - 1]), std::string(names[i]));
        }
    }

    TEST(GetProcAddressInternalTests, CheckDawnWireClientProcMapOrder) {
        std::vector<const char*> names = dawn::wire::client::GetProcMapNamesForTesting();
        for (size_t i = 1; i < names.size(); i++) {
            ASSERT_LT(std::string(names[i - 1]), std::string(names[i]));
        }
    }
}  // anonymous namespace
