// Copyright 2017 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 "tests/unittests/validation/ValidationTest.h"

#include "common/Assert.h"
#include "dawn/dawn.h"
#include "dawn_native/DawnNative.h"
#include "dawn_native/NullBackend.h"

ValidationTest::ValidationTest() {
    mInstance = std::make_unique<dawn_native::Instance>();
    mInstance->DiscoverDefaultAdapters();

    std::vector<dawn_native::Adapter> adapters = mInstance->GetAdapters();

    // Validation tests run against the null backend, find the corresponding adapter
    bool foundNullAdapter = false;
    dawn_native::Adapter nullAdapter;
    for (auto adapter : adapters) {
        if (adapter.GetBackendType() == dawn_native::BackendType::Null) {
            nullAdapter = adapter;
            foundNullAdapter = true;
            break;
        }
    }

    ASSERT(foundNullAdapter);
    device = dawn::Device::Acquire(nullAdapter.CreateDevice());

    dawnProcTable procs = dawn_native::GetProcs();
    dawnSetProcs(&procs);

    device.SetErrorCallback(ValidationTest::OnDeviceError, static_cast<dawnCallbackUserdata>(reinterpret_cast<uintptr_t>(this)));
}

ValidationTest::~ValidationTest() {
    // We need to destroy Dawn objects before setting the procs to null otherwise the dawn*Release
    // will call a nullptr
    device = dawn::Device();
    dawnSetProcs(nullptr);
}

void ValidationTest::TearDown() {
    ASSERT_FALSE(mExpectError);

    for (auto& expectation : mExpectations) {
        std::string name = expectation.debugName;
        if (name.empty()) {
            name = "<no debug name set>";
        }

        ASSERT_TRUE(expectation.gotStatus) << "Didn't get a status for " << name;

        ASSERT_NE(DAWN_BUILDER_ERROR_STATUS_UNKNOWN, expectation.status) << "Got unknown status for " << name;

        bool wasSuccess = expectation.status == DAWN_BUILDER_ERROR_STATUS_SUCCESS;
        ASSERT_EQ(expectation.expectSuccess, wasSuccess)
            << "Got wrong status value for " << name
            << ", status was " << expectation.status << " with \"" << expectation.statusMessage << "\"";
    }
}

void ValidationTest::StartExpectDeviceError() {
    mExpectError = true;
    mError = false;
}
bool ValidationTest::EndExpectDeviceError() {
    mExpectError = false;
    return mError;
}
std::string ValidationTest::GetLastDeviceErrorMessage() const {
    return mDeviceErrorMessage;
}

dawn::RenderPassDescriptor ValidationTest::CreateSimpleRenderPass() {
        dawn::TextureDescriptor descriptor;
        descriptor.dimension = dawn::TextureDimension::e2D;
        descriptor.size.width = 640;
        descriptor.size.height = 480;
        descriptor.size.depth = 1;
        descriptor.arraySize = 1;
        descriptor.sampleCount = 1;
        descriptor.format = dawn::TextureFormat::R8G8B8A8Unorm;
        descriptor.levelCount = 1;
        descriptor.usage = dawn::TextureUsageBit::OutputAttachment;

        auto colorBuffer = device.CreateTexture(&descriptor);
        auto colorView = colorBuffer.CreateDefaultTextureView();
        dawn::RenderPassColorAttachmentDescriptor colorAttachment;
        colorAttachment.attachment = colorView;
        colorAttachment.resolveTarget = nullptr;
        colorAttachment.clearColor = { 0.0f, 0.0f, 0.0f, 0.0f };
        colorAttachment.loadOp = dawn::LoadOp::Clear;
        colorAttachment.storeOp = dawn::StoreOp::Store;
        return device.CreateRenderPassDescriptorBuilder()
            .SetColorAttachments(1, &colorAttachment)
            .GetResult();
}

void ValidationTest::OnDeviceError(const char* message, dawnCallbackUserdata userdata) {
    auto self = reinterpret_cast<ValidationTest*>(static_cast<uintptr_t>(userdata));
    self->mDeviceErrorMessage = message;

    // Skip this one specific error that is raised when a builder is used after it got an error
    // this is important because we don't want to wrap all creation tests in ASSERT_DEVICE_ERROR.
    // Yes the error message is misleading.
    if (self->mDeviceErrorMessage == "Builder cannot be used after GetResult") {
        return;
    }

    ASSERT_TRUE(self->mExpectError) << "Got unexpected device error: " << message;
    ASSERT_FALSE(self->mError) << "Got two errors in expect block";
    self->mError = true;
}

void ValidationTest::OnBuilderErrorStatus(dawnBuilderErrorStatus status, const char* message, dawn::CallbackUserdata userdata1, dawn::CallbackUserdata userdata2) {
    auto* self = reinterpret_cast<ValidationTest*>(static_cast<uintptr_t>(userdata1));
    size_t index = static_cast<size_t>(userdata2);

    ASSERT_LT(index, self->mExpectations.size());

    auto& expectation = self->mExpectations[index];
    ASSERT_FALSE(expectation.gotStatus);
    expectation.gotStatus = true;
    expectation.status = status;
    expectation.statusMessage = message;
}

ValidationTest::DummyRenderPass ValidationTest::CreateDummyRenderPass() {
    DummyRenderPass dummy;
    dummy.width = 400;
    dummy.height = 400;
    dummy.attachmentFormat = dawn::TextureFormat::R8G8B8A8Unorm;

    dawn::TextureDescriptor descriptor;
    descriptor.dimension = dawn::TextureDimension::e2D;
    descriptor.size.width = dummy.width;
    descriptor.size.height = dummy.height;
    descriptor.size.depth = 1;
    descriptor.arraySize = 1;
    descriptor.sampleCount = 1;
    descriptor.format = dummy.attachmentFormat;
    descriptor.levelCount = 1;
    descriptor.usage = dawn::TextureUsageBit::OutputAttachment;
    dummy.attachment = device.CreateTexture(&descriptor);

    dawn::TextureView view = dummy.attachment.CreateDefaultTextureView();
    dawn::RenderPassColorAttachmentDescriptor colorAttachment;
    colorAttachment.attachment = view;
    colorAttachment.resolveTarget = nullptr;
    colorAttachment.clearColor = { 0.0f, 0.0f, 0.0f, 0.0f };
    colorAttachment.loadOp = dawn::LoadOp::Clear;
    colorAttachment.storeOp = dawn::StoreOp::Store;
    dummy.renderPass = AssertWillBeSuccess(device.CreateRenderPassDescriptorBuilder())
        .SetColorAttachments(1, &colorAttachment)
        .GetResult();

    return dummy;
}
