// Copyright 2021 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 <utility>
#include <vector>

#include "src/dawn/native/Device.h"
#include "src/dawn/native/dawn_platform.h"
#include "src/dawn/tests/MockCallback.h"
#include "src/dawn/tests/StringViewMatchers.h"
#include "src/dawn/tests/unittests/validation/ValidationTest.h"

namespace dawn {
namespace {

using testing::_;
using testing::EmptySizedString;
using testing::InSequence;
using testing::IsNull;
using testing::MockCppCallback;
using testing::NonEmptySizedString;
using testing::NotNull;
using testing::WithArgs;

class RequestDeviceValidationTest : public ValidationTest {
  protected:
    using MockDeviceLostCallback = MockCppCallback<wgpu::DeviceLostCallback<void>*>;

    void SetUp() override {
        ValidationTest::SetUp();
        DAWN_SKIP_TEST_IF(UsesWire());
    }

    MockCppCallback<wgpu::RequestDeviceCallback<void>*> mRequestDeviceCallback;
};

// Test that requesting a device without specifying limits is valid.
TEST_F(RequestDeviceValidationTest, NoRequiredLimits) {
    wgpu::DeviceDescriptor descriptor;

    EXPECT_CALL(mRequestDeviceCallback,
                Call(wgpu::RequestDeviceStatus::Success, NotNull(), EmptySizedString()))
        .WillOnce(WithArgs<1>([](wgpu::Device device) {
            // Check one of the default limits.
            wgpu::Limits limits;
            device.GetLimits(&limits);
            EXPECT_EQ(limits.maxBindGroups, 4u);
        }));
    adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                          mRequestDeviceCallback.Callback());
}

// Test that requesting a device with the default limits is valid.
TEST_F(RequestDeviceValidationTest, DefaultLimits) {
    wgpu::Limits limits = {};
    wgpu::DeviceDescriptor descriptor;
    descriptor.requiredLimits = &limits;

    EXPECT_CALL(mRequestDeviceCallback,
                Call(wgpu::RequestDeviceStatus::Success, NotNull(), EmptySizedString()))
        .WillOnce(WithArgs<1>([](wgpu::Device device) {
            // Check one of the default limits.
            wgpu::Limits limits;
            device.GetLimits(&limits);
            EXPECT_EQ(limits.maxTextureArrayLayers, 256u);
        }));
    adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                          mRequestDeviceCallback.Callback());
}

// Test that requesting a device where a required limit is above the maximum value.
TEST_F(RequestDeviceValidationTest, HigherIsBetter) {
    wgpu::Limits limits = {};
    wgpu::DeviceDescriptor descriptor;
    descriptor.requiredLimits = &limits;

    wgpu::Limits supportedLimits;
    EXPECT_EQ(adapter.GetLimits(&supportedLimits), wgpu::Status::Success);

    // If we can support better than the default, test below the max.
    if (supportedLimits.maxBindGroups > 4u) {
        limits.maxBindGroups = supportedLimits.maxBindGroups - 1;
        EXPECT_CALL(mRequestDeviceCallback,
                    Call(wgpu::RequestDeviceStatus::Success, NotNull(), EmptySizedString()))
            .WillOnce(WithArgs<1>([&](wgpu::Device device) {
                wgpu::Limits limits;
                device.GetLimits(&limits);

                // Check we got exactly the request.
                EXPECT_EQ(limits.maxBindGroups, supportedLimits.maxBindGroups - 1);
                // Check another default limit.
                EXPECT_EQ(limits.maxTextureArrayLayers, 256u);
            }));
        adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                              mRequestDeviceCallback.Callback());
    }

    // Test the max.
    limits.maxBindGroups = supportedLimits.maxBindGroups;
    EXPECT_CALL(mRequestDeviceCallback,
                Call(wgpu::RequestDeviceStatus::Success, NotNull(), EmptySizedString()))
        .WillOnce(WithArgs<1>([&](wgpu::Device device) {
            wgpu::Limits limits;
            device.GetLimits(&limits);

            // Check we got exactly the request.
            EXPECT_EQ(limits.maxBindGroups, supportedLimits.maxBindGroups);
            // Check another default limit.
            EXPECT_EQ(limits.maxTextureArrayLayers, 256u);
        }));
    adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                          mRequestDeviceCallback.Callback());

    // Test above the max.
    limits.maxBindGroups = supportedLimits.maxBindGroups + 1;
    EXPECT_CALL(mRequestDeviceCallback,
                Call(wgpu::RequestDeviceStatus::Error, IsNull(), NonEmptySizedString()))
        .Times(1);
    adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                          mRequestDeviceCallback.Callback());

    // Test worse than the default
    limits.maxBindGroups = 3u;
    EXPECT_CALL(mRequestDeviceCallback,
                Call(wgpu::RequestDeviceStatus::Success, NotNull(), EmptySizedString()))
        .WillOnce(WithArgs<1>([&](wgpu::Device device) {
            wgpu::Limits limits;
            device.GetLimits(&limits);

            // Check we got the default.
            EXPECT_EQ(limits.maxBindGroups, 4u);
        }));
    adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                          mRequestDeviceCallback.Callback());
}

// Test that requesting a device where a required limit is below the minimum value.
TEST_F(RequestDeviceValidationTest, LowerIsBetter) {
    wgpu::Limits limits = {};
    wgpu::DeviceDescriptor descriptor;
    descriptor.requiredLimits = &limits;

    wgpu::Limits supportedLimits;
    EXPECT_EQ(adapter.GetLimits(&supportedLimits), wgpu::Status::Success);

    // Test below the min.
    limits.minUniformBufferOffsetAlignment = supportedLimits.minUniformBufferOffsetAlignment / 2;
    EXPECT_CALL(mRequestDeviceCallback,
                Call(wgpu::RequestDeviceStatus::Error, IsNull(), NonEmptySizedString()))
        .Times(1);
    adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                          mRequestDeviceCallback.Callback());

    // Test the min.
    limits.minUniformBufferOffsetAlignment = supportedLimits.minUniformBufferOffsetAlignment;
    EXPECT_CALL(mRequestDeviceCallback,
                Call(wgpu::RequestDeviceStatus::Success, NotNull(), EmptySizedString()))
        .WillOnce(WithArgs<1>([&](wgpu::Device device) {
            wgpu::Limits limits;
            device.GetLimits(&limits);

            // Check we got exactly the request.
            EXPECT_EQ(limits.minUniformBufferOffsetAlignment,
                      supportedLimits.minUniformBufferOffsetAlignment);
            // Check another default limit.
            EXPECT_EQ(limits.maxTextureArrayLayers, 256u);
        }));
    adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                          mRequestDeviceCallback.Callback());

    // IF we can support better than the default, test above the min.
    if (supportedLimits.minUniformBufferOffsetAlignment > 256u) {
        limits.minUniformBufferOffsetAlignment =
            supportedLimits.minUniformBufferOffsetAlignment * 2;
        EXPECT_CALL(mRequestDeviceCallback,
                    Call(wgpu::RequestDeviceStatus::Success, NotNull(), EmptySizedString()))
            .WillOnce(WithArgs<1>([&](wgpu::Device device) {
                wgpu::Limits limits;
                device.GetLimits(&limits);

                // Check we got exactly the request.
                EXPECT_EQ(limits.minUniformBufferOffsetAlignment,
                          supportedLimits.minUniformBufferOffsetAlignment * 2);
                // Check another default limit.
                EXPECT_EQ(limits.maxTextureArrayLayers, 256u);
            }));
        adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                              mRequestDeviceCallback.Callback());
    }

    // Test worse than the default
    limits.minUniformBufferOffsetAlignment = 2u * 256u;
    EXPECT_CALL(mRequestDeviceCallback,
                Call(wgpu::RequestDeviceStatus::Success, NotNull(), EmptySizedString()))
        .WillOnce(WithArgs<1>([&](wgpu::Device device) {
            wgpu::Limits limits;
            device.GetLimits(&limits);

            // Check we got the default.
            EXPECT_EQ(limits.minUniformBufferOffsetAlignment, 256u);
        }));
    adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                          mRequestDeviceCallback.Callback());
}

// Test that if an error occurs when requesting a device, the device lost callback is called
// appropriately.
TEST_F(RequestDeviceValidationTest, ErrorTriggersDeviceLost) {
    // Invalid descriptor chains:
    //   - ChainedStruct: This should cause an early validation error.
    //   - DawnFakeDeviceInitializeErrorForTesting: This should cause an internal device error.
    wgpu::ChainedStruct chain1;
    wgpu::DawnFakeDeviceInitializeErrorForTesting chain2;
    std::array<wgpu::ChainedStruct*, 2> chains = {&chain1, &chain2};

    for (const auto* chain : chains) {
        SCOPED_TRACE(absl::StrFormat("Chain SType: %s", chain->sType));
        {
            wgpu::DeviceDescriptor descriptor;
            descriptor.nextInChain = chain;

            // Device lost callback mode: AllowSpontaneous.
            MockDeviceLostCallback lostCb;
            descriptor.SetDeviceLostCallback(wgpu::CallbackMode::AllowSpontaneous,
                                             lostCb.Callback());

            // When in spontaneous mode, the request device callback should fire immediately before
            // the device lost callback.
            InSequence s;
            EXPECT_CALL(mRequestDeviceCallback,
                        Call(wgpu::RequestDeviceStatus::Error, IsNull(), NonEmptySizedString()))
                .Times(1);
            EXPECT_CALL(lostCb, Call(_, wgpu::DeviceLostReason::FailedCreation, _)).Times(1);
            adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                                  mRequestDeviceCallback.Callback());
        }
        {
            wgpu::DeviceDescriptor descriptor;
            descriptor.nextInChain = chain;

            // Device lost callback mode: AllowProcessEvents.
            MockDeviceLostCallback lostCb;
            descriptor.SetDeviceLostCallback(wgpu::CallbackMode::AllowProcessEvents,
                                             lostCb.Callback());

            EXPECT_CALL(mRequestDeviceCallback,
                        Call(wgpu::RequestDeviceStatus::Error, IsNull(), NonEmptySizedString()))
                .Times(1);
            adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                                  mRequestDeviceCallback.Callback());

            // When in a non-spontaneous mode for the device lost, the request device callback
            // should fire, but the device lost callback should only fire when the Instance level
            // API is called.
            EXPECT_CALL(lostCb, Call(_, wgpu::DeviceLostReason::FailedCreation, _)).Times(1);
            instance.ProcessEvents();
        }
    }
}

// Test that RG11B10UfloatRenderable is implicitly enabled when TextureFormatsTier1 is active.
TEST_F(RequestDeviceValidationTest, TextureFormatsTier1ImpliesRG11B10UfloatRenderable) {
    wgpu::DeviceDescriptor descriptor = {};
    std::vector<wgpu::FeatureName> features = {wgpu::FeatureName::TextureFormatsTier1};
    descriptor.requiredFeatures = features.data();
    descriptor.requiredFeatureCount = features.size();

    EXPECT_CALL(mRequestDeviceCallback,
                Call(wgpu::RequestDeviceStatus::Success, NotNull(), EmptySizedString()))
        .WillOnce(WithArgs<1>([](wgpu::Device device) {
            EXPECT_TRUE(device.HasFeature(wgpu::FeatureName::RG11B10UfloatRenderable));
        }));
    adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                          mRequestDeviceCallback.Callback());
}

// Test that TextureFormatsTier1 is implicitly enabled when TextureFormatsTier2 is active.
TEST_F(RequestDeviceValidationTest, TextureFormatsTier2ImpliesTextureFormatsTier1) {
    wgpu::DeviceDescriptor descriptor = {};
    std::vector<wgpu::FeatureName> features = {wgpu::FeatureName::TextureFormatsTier2};
    descriptor.requiredFeatures = features.data();
    descriptor.requiredFeatureCount = features.size();

    EXPECT_CALL(mRequestDeviceCallback,
                Call(wgpu::RequestDeviceStatus::Success, NotNull(), EmptySizedString()))
        .WillOnce(WithArgs<1>([](wgpu::Device device) {
            EXPECT_TRUE(device.HasFeature(wgpu::FeatureName::TextureFormatsTier1));
        }));
    adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                          mRequestDeviceCallback.Callback());
}

class DeviceTickValidationTest : public ValidationTest {};

// Device destroy before API-level Tick should always result in no-op and false.
TEST_F(DeviceTickValidationTest, DestroyDeviceBeforeAPITick) {
    ExpectDeviceDestruction();
    device.Destroy();
    device.Tick();
}

class DeviceGetAHardwareBufferPropertiesValidationTest : public ValidationTest {
    void SetUp() override {
        ValidationTest::SetUp();
        DAWN_SKIP_TEST_IF(UsesWire());
    }
};

// Test that calling GetAHardwareBufferProperties will generate an error
// if the required feature is not present.
TEST_F(DeviceGetAHardwareBufferPropertiesValidationTest,
       GetAHardwareBufferPropertiesRequiresAHBFeature) {
    // The parameter values shouldn't matter, as the call should fail validation
    // before calling into the implementation (verified by checking the error
    // message).
    void* handle = nullptr;
    wgpu::AHardwareBufferProperties* properties = nullptr;

    ASSERT_DEVICE_ERROR(
        device.GetAHardwareBufferProperties(handle, properties),
        testing::HasSubstr(
            "without the FeatureName::SharedTextureMemoryAHardwareBuffer feature being set"));
}

class RequestDeviceCoreValidationTest : public RequestDeviceValidationTest {
    // Create a core-defaulting adapter
    bool UseCompatibilityMode() const override { return false; }
};

// Test that requiring wgpu::FeatureName::CoreFeaturesAndLimits explicitly when calling
// RequestingDevice on a core-defaulting adapter gives a device with core limits.
TEST_F(RequestDeviceCoreValidationTest, Explicit) {
    wgpu::DeviceDescriptor descriptor = {};
    std::vector<wgpu::FeatureName> features = {wgpu::FeatureName::CoreFeaturesAndLimits};
    descriptor.requiredFeatures = features.data();
    descriptor.requiredFeatureCount = features.size();

    EXPECT_CALL(mRequestDeviceCallback,
                Call(wgpu::RequestDeviceStatus::Success, NotNull(), EmptySizedString()))
        .WillOnce(WithArgs<1>([](wgpu::Device device) {
            EXPECT_TRUE(device.HasFeature(wgpu::FeatureName::CoreFeaturesAndLimits));
            // Check one of limits to be greater than compat tier.
            dawn::utils::ComboLimits limits;
            device.GetLimits(limits.GetLinked());
            EXPECT_GT(limits.maxStorageBuffersInVertexStage, 0u);
        }));
    adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                          mRequestDeviceCallback.Callback());
}

// Test that calling RequestingDevice on a core-defaulting adapter gives a device with core
// limits on default.
TEST_F(RequestDeviceCoreValidationTest, Implicit) {
    wgpu::DeviceDescriptor descriptor = {};

    EXPECT_CALL(mRequestDeviceCallback,
                Call(wgpu::RequestDeviceStatus::Success, NotNull(), EmptySizedString()))
        .WillOnce(WithArgs<1>([](wgpu::Device device) {
            EXPECT_TRUE(device.HasFeature(wgpu::FeatureName::CoreFeaturesAndLimits));
            // Check one of limits to be greater than compat tier.
            dawn::utils::ComboLimits limits;
            device.GetLimits(limits.GetLinked());
            EXPECT_GT(limits.maxStorageBuffersInVertexStage, 0u);
        }));
    adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                          mRequestDeviceCallback.Callback());
}

class RequestDeviceCompatValidationTest : public RequestDeviceValidationTest {
    // Create a compat-defaulting adapter
    bool UseCompatibilityMode() const override { return true; }
};

// Test that requiring wgpu::FeatureName::CoreFeaturesAndLimits when calling RequestingDevice on a
// compat-defaulting adapter gives a device with core limits.
TEST_F(RequestDeviceCompatValidationTest, CreateCore) {
    wgpu::DeviceDescriptor descriptor = {};
    std::vector<wgpu::FeatureName> features = {wgpu::FeatureName::CoreFeaturesAndLimits};
    descriptor.requiredFeatures = features.data();
    descriptor.requiredFeatureCount = features.size();

    EXPECT_CALL(mRequestDeviceCallback,
                Call(wgpu::RequestDeviceStatus::Success, NotNull(), EmptySizedString()))
        .WillOnce(WithArgs<1>([](wgpu::Device device) {
            EXPECT_TRUE(device.HasFeature(wgpu::FeatureName::CoreFeaturesAndLimits));
            // Check one of limits to be greater than compat tier.
            dawn::utils::ComboLimits limits;
            device.GetLimits(limits.GetLinked());
            EXPECT_GT(limits.maxStorageBuffersInVertexStage, 0u);
        }));
    adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                          mRequestDeviceCallback.Callback());
}

// Test that calling RequestingDevice on a compat-defaulting adapter gives a device with compat
// limits on default.
TEST_F(RequestDeviceCompatValidationTest, CreateCompat) {
    wgpu::DeviceDescriptor descriptor = {};

    EXPECT_CALL(mRequestDeviceCallback,
                Call(wgpu::RequestDeviceStatus::Success, NotNull(), EmptySizedString()))
        .WillOnce(WithArgs<1>([](wgpu::Device device) {
            EXPECT_FALSE(device.HasFeature(wgpu::FeatureName::CoreFeaturesAndLimits));
            // Check one of limits to be compat tier.
            dawn::utils::ComboLimits limits;
            device.GetLimits(limits.GetLinked());
            EXPECT_EQ(limits.maxStorageBuffersInVertexStage, 0u);
        }));
    adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                          mRequestDeviceCallback.Callback());
}

class RequestDeviceWithImmediateDataValidationTest : public ValidationTest {
  protected:
    void SetUp() override {
        ValidationTest::SetUp();
        DAWN_SKIP_TEST_IF(UsesWire());
    }

    MockCppCallback<void (*)(wgpu::RequestDeviceStatus, wgpu::Device, wgpu::StringView)>
        mRequestDeviceCallback;
};

// Test that requesting a device where a required immediate data range byte size limit is below
// the max always returns one with the max.
TEST_F(RequestDeviceWithImmediateDataValidationTest, AlwaysMax) {
    wgpu::Limits limits = {};

    wgpu::DeviceDescriptor descriptor;
    descriptor.requiredLimits = &limits;

    wgpu::Limits supportedLimits;
    EXPECT_EQ(adapter.GetLimits(&supportedLimits), wgpu::Status::Success);

    uint32_t supportedImmediateDataLimit = supportedLimits.maxImmediateSize;

    // DeviceNull has a maxImmediateSize of 64, larger than 16.
    constexpr uint32_t smallerImmediateDataLimit = 16;
    EXPECT_GT(supportedImmediateDataLimit, smallerImmediateDataLimit);

    // Test below the max.
    limits.maxImmediateSize = smallerImmediateDataLimit;
    EXPECT_CALL(mRequestDeviceCallback,
                Call(wgpu::RequestDeviceStatus::Success, NotNull(), EmptySizedString()))
        .WillOnce(WithArgs<1>([&](wgpu::Device device) {
            wgpu::Limits deviceLimits;
            device.GetLimits(&deviceLimits);
            // Check we got the max.
            EXPECT_EQ(deviceLimits.maxImmediateSize, supportedImmediateDataLimit);
        }));
    adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                          mRequestDeviceCallback.Callback());

    // Test the max.
    limits.maxImmediateSize = supportedImmediateDataLimit;
    EXPECT_CALL(mRequestDeviceCallback,
                Call(wgpu::RequestDeviceStatus::Success, NotNull(), EmptySizedString()))
        .WillOnce(WithArgs<1>([&](wgpu::Device device) {
            wgpu::Limits deviceLimits;
            device.GetLimits(&deviceLimits);

            // Check we got the max.
            EXPECT_EQ(deviceLimits.maxImmediateSize, supportedImmediateDataLimit);
        }));
    adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                          mRequestDeviceCallback.Callback());

    // Test above the max.
    limits.maxImmediateSize = supportedImmediateDataLimit + 4;
    EXPECT_CALL(mRequestDeviceCallback,
                Call(wgpu::RequestDeviceStatus::Error, IsNull(), NonEmptySizedString()))
        .Times(1);
    adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                          mRequestDeviceCallback.Callback());

    // Test even smaller
    limits.maxImmediateSize = smallerImmediateDataLimit / 2;
    EXPECT_CALL(mRequestDeviceCallback,
                Call(wgpu::RequestDeviceStatus::Success, NotNull(), EmptySizedString()))
        .WillOnce(WithArgs<1>([&](wgpu::Device device) {
            wgpu::Limits deviceLimits;
            device.GetLimits(&deviceLimits);
            // Check we got the max.
            EXPECT_EQ(deviceLimits.maxImmediateSize, supportedImmediateDataLimit);
        }));
    adapter.RequestDevice(&descriptor, wgpu::CallbackMode::AllowSpontaneous,
                          mRequestDeviceCallback.Callback());
}

}  // anonymous namespace
}  // namespace dawn
