// Copyright 2019 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/tests/unittests/wire/WireTest.h"

#include "dawn/common/StringViewUtils.h"
#include "dawn/dawn_proc.h"
#include "dawn/tests/MockCallback.h"
#include "dawn/utils/TerribleCommandBuffer.h"
#include "dawn/wire/WireClient.h"
#include "dawn/wire/WireServer.h"

using testing::_;
using testing::AnyNumber;
using testing::AtMost;
using testing::Exactly;
using testing::Mock;
using testing::MockCallback;
using testing::NotNull;
using testing::Return;
using testing::SaveArg;
using testing::StrEq;
using testing::WithArg;

namespace dawn {

namespace {
// WireTest sets the wire proc table as the global proc table.
// Tests that use multiple wires may inherit WireTest multiple times (see
// WireConfusionDeathTest). Refcount how many WireTest instances are running
// to make sure we don't unset the proc table until the test is done.
uint32_t sWireProcTableRefCount = 0;
}  // namespace

WireTest::WireTest() {}

WireTest::~WireTest() {}

wire::client::MemoryTransferService* WireTest::GetClientMemoryTransferService() {
    return nullptr;
}

wire::server::MemoryTransferService* WireTest::GetServerMemoryTransferService() {
    return nullptr;
}

void WireTest::SetUp() {
    DawnProcTable mockProcs;
    api.GetProcTable(&mockProcs);
    SetupIgnoredCallExpectations();

    mS2cBuf = std::make_unique<utils::TerribleCommandBuffer>();
    mC2sBuf = std::make_unique<utils::TerribleCommandBuffer>(mWireServer.get());

    wire::WireServerDescriptor serverDesc = {};
    serverDesc.procs = &mockProcs;
    serverDesc.serializer = mS2cBuf.get();
    serverDesc.memoryTransferService = GetServerMemoryTransferService();

    mWireServer.reset(new wire::WireServer(serverDesc));
    mC2sBuf->SetHandler(mWireServer.get());

    wire::WireClientDescriptor clientDesc = {};
    clientDesc.serializer = mC2sBuf.get();
    clientDesc.memoryTransferService = GetClientMemoryTransferService();

    mWireClient.reset(new wire::WireClient(clientDesc));
    mS2cBuf->SetHandler(mWireClient.get());

    if (sWireProcTableRefCount == 0) {
        dawnProcSetProcs(&wire::client::GetProcs());
    }
    ++sWireProcTableRefCount;

    auto reservedInstance = GetWireClient()->ReserveInstance();
    instance = wgpu::Instance::Acquire(reservedInstance.instance);
    apiInstance = api.GetNewInstance();
    EXPECT_CALL(api, InstanceAddRef(apiInstance));
    EXPECT_TRUE(GetWireServer()->InjectInstance(apiInstance, reservedInstance.handle));

    // Create the adapter for testing.
    apiAdapter = api.GetNewAdapter();
    MockCallback<void (*)(wgpu::RequestAdapterStatus, wgpu::Adapter, wgpu::StringView, void*)>
        adapterCb;
    instance.RequestAdapter(nullptr, wgpu::CallbackMode::AllowSpontaneous, adapterCb.Callback(),
                            adapterCb.MakeUserdata(this));

    EXPECT_CALL(api, OnInstanceRequestAdapter(apiInstance, _, _)).WillOnce([&]() {
        EXPECT_CALL(api, AdapterHasFeature(apiAdapter, _)).WillRepeatedly(Return(false));

        EXPECT_CALL(api, AdapterGetInfo(apiAdapter, NotNull()))
            .WillOnce(WithArg<1>([&](WGPUAdapterInfo* info) {
                *info = {};
                info->vendor = kEmptyOutputStringView;
                info->architecture = kEmptyOutputStringView;
                info->device = kEmptyOutputStringView;
                info->description = kEmptyOutputStringView;
                return WGPUStatus_Success;
            }));

        EXPECT_CALL(api, AdapterGetLimits(apiAdapter, NotNull()))
            .WillOnce(WithArg<1>([&](WGPULimits* limits) {
                *limits = {};
                return WGPUStatus_Success;
            }));

        EXPECT_CALL(api, AdapterGetFeatures(apiAdapter, NotNull()))
            .WillOnce(WithArg<1>([&](WGPUSupportedFeatures* features) { *features = {}; }));

        api.CallInstanceRequestAdapterCallback(apiInstance, WGPURequestAdapterStatus_Success,
                                               apiAdapter, kEmptyOutputStringView);
    });
    FlushClient();
    EXPECT_CALL(adapterCb, Call(wgpu::RequestAdapterStatus::Success, NotNull(), StrEq(""), this))
        .WillOnce(SaveArg<1>(&adapter));
    FlushServer();
    EXPECT_NE(adapter, nullptr);

    // Create the device for testing.
    apiDevice = api.GetNewDevice();
    wgpu::DeviceDescriptor deviceDesc = {};
    deviceDesc.SetDeviceLostCallback(wgpu::CallbackMode::AllowSpontaneous,
                                     deviceLostCallback.Callback());
    deviceDesc.SetUncapturedErrorCallback(uncapturedErrorCallback.TemplatedCallback(),
                                          uncapturedErrorCallback.TemplatedCallbackUserdata());
    EXPECT_CALL(deviceLostCallback, Call).Times(AtMost(1));

    MockCallback<void (*)(wgpu::RequestDeviceStatus, wgpu::Device, wgpu::StringView, void*)>
        deviceCb;
    adapter.RequestDevice(&deviceDesc, wgpu::CallbackMode::AllowSpontaneous, deviceCb.Callback(),
                          deviceCb.MakeUserdata(this));
    EXPECT_CALL(api, OnAdapterRequestDevice(apiAdapter, NotNull(), _))
        .WillOnce(WithArg<1>([&](const WGPUDeviceDescriptor* desc) {
            // Set on device creation to forward callbacks to the client.
            EXPECT_CALL(api, OnDeviceSetLoggingCallback(apiDevice, _)).Times(1);

            // The mock objects currently require us to manually set the callbacks because we
            // are no longer explicitly calling the setters anymore.
            ProcTableAsClass::Object* object =
                reinterpret_cast<ProcTableAsClass::Object*>(apiDevice);
            object->mDeviceLostCallback = desc->deviceLostCallbackInfo.callback;
            object->mDeviceLostUserdata1 = desc->deviceLostCallbackInfo.userdata1;
            object->mDeviceLostUserdata2 = desc->deviceLostCallbackInfo.userdata2;
            object->mUncapturedErrorCallback = desc->uncapturedErrorCallbackInfo.callback;
            object->mUncapturedErrorUserdata1 = desc->uncapturedErrorCallbackInfo.userdata1;
            object->mUncapturedErrorUserdata2 = desc->uncapturedErrorCallbackInfo.userdata2;

            EXPECT_CALL(api, DeviceGetLimits(apiDevice, NotNull()))
                .WillOnce(WithArg<1>([&](WGPULimits* limits) {
                    *limits = {};
                    return WGPUStatus_Success;
                }));

            EXPECT_CALL(api, DeviceGetFeatures(apiDevice, NotNull()))
                .WillOnce(WithArg<1>([&](WGPUSupportedFeatures* features) { *features = {}; }));

            api.CallAdapterRequestDeviceCallback(apiAdapter, WGPURequestDeviceStatus_Success,
                                                 apiDevice, kEmptyOutputStringView);
        }));
    FlushClient();
    EXPECT_CALL(deviceCb, Call(wgpu::RequestDeviceStatus::Success, NotNull(), StrEq(""), this))
        .WillOnce(SaveArg<1>(&device));
    FlushServer();
    EXPECT_NE(device, nullptr);

    // The GetQueue is done on WireClient startup so we expect it now.
    queue = device.GetQueue();
    apiQueue = api.GetNewQueue();
    EXPECT_CALL(api, DeviceGetQueue(apiDevice)).WillOnce(Return(apiQueue));
    FlushClient();

    cDevice = device.Get();
    cQueue = queue.Get();
}

void WireTest::TearDown() {
    instance = nullptr;
    adapter = nullptr;
    device = nullptr;
    queue = nullptr;

    --sWireProcTableRefCount;
    if (sWireProcTableRefCount == 0) {
        dawnProcSetProcs(nullptr);
    }

    // Derived classes should call the base TearDown() first. The client must
    // be reset before any mocks are deleted.
    // Incomplete client callbacks will be called on deletion, so the mocks
    // cannot be null.
    api.IgnoreAllReleaseCalls();
    mS2cBuf->SetHandler(nullptr);
    mWireClient = nullptr;

    if (mWireServer && apiDevice) {
        // These are called on server destruction to clear the callbacks. They must not be
        // called after the server is destroyed.
        EXPECT_CALL(api, OnDeviceSetLoggingCallback(apiDevice, _))
            .Times(Exactly(1))
            .WillOnce(WithArg<1>([](const WGPULoggingCallbackInfo& callbackInfo) {
                EXPECT_EQ(callbackInfo.callback, nullptr);
            }));
    }
    mC2sBuf->SetHandler(nullptr);
    mWireServer = nullptr;
}

// This should be called if |apiDevice| no longer exists on the wire.
// This signals that expectations in |TearDown| shouldn't be added.
void WireTest::DefaultApiDeviceWasReleased() {
    apiDevice = nullptr;
}

// This should be called if |apiAdapter| no longer exists on the wire.
// This signals that expectations in |TearDown| shouldn't be added.
void WireTest::DefaultApiAdapterWasReleased() {
    apiAdapter = nullptr;
}

void WireTest::FlushClient(bool success) {
    ASSERT_EQ(mC2sBuf->Flush(), success);

    Mock::VerifyAndClearExpectations(&api);
    SetupIgnoredCallExpectations();
}

void WireTest::FlushServer(bool success) {
    ASSERT_EQ(mS2cBuf->Flush(), success);
}

wire::WireServer* WireTest::GetWireServer() {
    return mWireServer.get();
}

wire::WireClient* WireTest::GetWireClient() {
    return mWireClient.get();
}

size_t WireTest::GetC2SMaxAllocationSize() {
    return mC2sBuf->GetMaximumAllocationSize();
}

void WireTest::DeleteServer() {
    EXPECT_CALL(api, QueueRelease(apiQueue)).Times(1);
    EXPECT_CALL(api, DeviceRelease(apiDevice)).Times(1);
    EXPECT_CALL(api, AdapterRelease(apiAdapter)).Times(1);
    EXPECT_CALL(api, InstanceRelease(apiInstance)).Times(1);

    if (mWireServer) {
        // These are called on server destruction to clear the callbacks. They must not be
        // called after the server is destroyed.
        EXPECT_CALL(api, OnDeviceSetLoggingCallback(apiDevice, _))
            .Times(Exactly(1))
            .WillOnce(WithArg<1>([](const WGPULoggingCallbackInfo& callbackInfo) {
                EXPECT_EQ(callbackInfo.callback, nullptr);
            }));
    }
    mC2sBuf->SetHandler(nullptr);
    mWireServer = nullptr;
}

void WireTest::DeleteClient() {
    mS2cBuf->SetHandler(nullptr);
    mWireClient = nullptr;
}

void WireTest::SetupIgnoredCallExpectations() {
    EXPECT_CALL(api, InstanceProcessEvents(_)).Times(AnyNumber());
    EXPECT_CALL(api, DeviceTick(_)).Times(AnyNumber());
}

}  // namespace dawn
