// Copyright 2021 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 "dawn/dawn_proc.h"
#include "dawn/native/DawnNative.h"
#include "dawn/native/Device.h"
#include "dawn/native/dawn_platform.h"
#include "dawn/tests/MockCallback.h"
#include "dawn/utils/SystemUtils.h"
#include "dawn/utils/WGPUHelpers.h"

#include <gtest/gtest.h>

namespace {

    using namespace testing;

    class DeviceCreationTest : public Test {
      protected:
        void SetUp() override {
            dawnProcSetProcs(&dawn::native::GetProcs());

            instance = std::make_unique<dawn::native::Instance>();
            instance->DiscoverDefaultAdapters();
            for (dawn::native::Adapter& nativeAdapter : instance->GetAdapters()) {
                wgpu::AdapterProperties properties;
                nativeAdapter.GetProperties(&properties);

                if (properties.backendType == wgpu::BackendType::Null) {
                    adapter = wgpu::Adapter(nativeAdapter.Get());
                    break;
                }
            }
            ASSERT_NE(adapter, nullptr);
        }

        void TearDown() override {
            adapter = nullptr;
            instance = nullptr;
            dawnProcSetProcs(nullptr);
        }

        std::unique_ptr<dawn::native::Instance> instance;
        wgpu::Adapter adapter;
    };

    // Test successful call to CreateDevice with no descriptor
    TEST_F(DeviceCreationTest, CreateDeviceNoDescriptorSuccess) {
        wgpu::Device device = adapter.CreateDevice();
        EXPECT_NE(device, nullptr);
    }

    // Test successful call to CreateDevice with descriptor.
    TEST_F(DeviceCreationTest, CreateDeviceSuccess) {
        wgpu::DeviceDescriptor desc = {};
        wgpu::Device device = adapter.CreateDevice(&desc);
        EXPECT_NE(device, nullptr);
    }

    // Test successful call to CreateDevice with toggle descriptor.
    TEST_F(DeviceCreationTest, CreateDeviceWithTogglesSuccess) {
        wgpu::DeviceDescriptor desc = {};
        wgpu::DawnTogglesDeviceDescriptor togglesDesc = {};
        desc.nextInChain = &togglesDesc;

        const char* toggle = "skip_validation";
        togglesDesc.forceEnabledToggles = &toggle;
        togglesDesc.forceEnabledTogglesCount = 1;

        wgpu::Device device = adapter.CreateDevice(&desc);
        EXPECT_NE(device, nullptr);

        auto toggles = dawn::native::GetTogglesUsed(device.Get());
        EXPECT_THAT(toggles, testing::Contains(testing::StrEq(toggle)));
    }

    TEST_F(DeviceCreationTest, CreateDeviceWithCacheSuccess) {
        // Default device descriptor should have an empty cache isolation key.
        {
            wgpu::DeviceDescriptor desc = {};
            wgpu::Device device = adapter.CreateDevice(&desc);
            EXPECT_NE(device, nullptr);

            EXPECT_THAT(dawn::native::FromAPI(device.Get())->GetCacheIsolationKey(),
                        testing::StrEq(""));
        }
        // Device descriptor with empty cache descriptor should have an empty cache isolation key.
        {
            wgpu::DeviceDescriptor desc = {};
            wgpu::DawnCacheDeviceDescriptor cacheDesc = {};
            desc.nextInChain = &cacheDesc;

            wgpu::Device device = adapter.CreateDevice(&desc);
            EXPECT_NE(device, nullptr);

            EXPECT_THAT(dawn::native::FromAPI(device.Get())->GetCacheIsolationKey(),
                        testing::StrEq(""));
        }
        // Specified cache isolation key should be retained.
        {
            wgpu::DeviceDescriptor desc = {};
            wgpu::DawnCacheDeviceDescriptor cacheDesc = {};
            desc.nextInChain = &cacheDesc;

            const char* isolationKey = "isolation key";
            cacheDesc.isolationKey = isolationKey;

            wgpu::Device device = adapter.CreateDevice(&desc);
            EXPECT_NE(device, nullptr);

            EXPECT_THAT(dawn::native::FromAPI(device.Get())->GetCacheIsolationKey(),
                        testing::StrEq(isolationKey));
        }
    }

    // Test successful call to RequestDevice with descriptor
    TEST_F(DeviceCreationTest, RequestDeviceSuccess) {
        WGPUDevice cDevice;
        {
            MockCallback<WGPURequestDeviceCallback> cb;
            EXPECT_CALL(cb, Call(WGPURequestDeviceStatus_Success, NotNull(), nullptr, this))
                .WillOnce(SaveArg<1>(&cDevice));

            wgpu::DeviceDescriptor desc = {};
            adapter.RequestDevice(&desc, cb.Callback(), cb.MakeUserdata(this));
        }

        wgpu::Device device = wgpu::Device::Acquire(cDevice);
        EXPECT_NE(device, nullptr);
    }

    // Test successful call to RequestDevice with a null descriptor
    TEST_F(DeviceCreationTest, RequestDeviceNullDescriptorSuccess) {
        WGPUDevice cDevice;
        {
            MockCallback<WGPURequestDeviceCallback> cb;
            EXPECT_CALL(cb, Call(WGPURequestDeviceStatus_Success, NotNull(), nullptr, this))
                .WillOnce(SaveArg<1>(&cDevice));

            adapter.RequestDevice(nullptr, cb.Callback(), cb.MakeUserdata(this));
        }

        wgpu::Device device = wgpu::Device::Acquire(cDevice);
        EXPECT_NE(device, nullptr);
    }

    // Test failing call to RequestDevice with invalid feature
    TEST_F(DeviceCreationTest, RequestDeviceFailure) {
        MockCallback<WGPURequestDeviceCallback> cb;
        EXPECT_CALL(cb, Call(WGPURequestDeviceStatus_Error, nullptr, NotNull(), this)).Times(1);

        wgpu::DeviceDescriptor desc = {};
        wgpu::FeatureName invalidFeature = static_cast<wgpu::FeatureName>(WGPUFeatureName_Force32);
        desc.requiredFeatures = &invalidFeature;
        desc.requiredFeaturesCount = 1;

        adapter.RequestDevice(&desc, cb.Callback(), cb.MakeUserdata(this));
    }

}  // anonymous namespace
