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

#include "dawn/wire/WireClient.h"

using namespace testing;
using namespace dawn::wire;

namespace {

    // Mock classes to add expectations on the wire calling callbacks
    class MockDeviceErrorCallback {
      public:
        MOCK_METHOD(void, Call, (WGPUErrorType type, const char* message, void* userdata));
    };

    std::unique_ptr<StrictMock<MockDeviceErrorCallback>> mockDeviceErrorCallback;
    void ToMockDeviceErrorCallback(WGPUErrorType type, const char* message, void* userdata) {
        mockDeviceErrorCallback->Call(type, message, userdata);
    }

    class MockDevicePopErrorScopeCallback {
      public:
        MOCK_METHOD(void, Call, (WGPUErrorType type, const char* message, void* userdata));
    };

    std::unique_ptr<StrictMock<MockDevicePopErrorScopeCallback>> mockDevicePopErrorScopeCallback;
    void ToMockDevicePopErrorScopeCallback(WGPUErrorType type,
                                           const char* message,
                                           void* userdata) {
        mockDevicePopErrorScopeCallback->Call(type, message, userdata);
    }

    class MockDeviceLoggingCallback {
      public:
        MOCK_METHOD(void, Call, (WGPULoggingType type, const char* message, void* userdata));
    };

    std::unique_ptr<StrictMock<MockDeviceLoggingCallback>> mockDeviceLoggingCallback;
    void ToMockDeviceLoggingCallback(WGPULoggingType type, const char* message, void* userdata) {
        mockDeviceLoggingCallback->Call(type, message, userdata);
    }

    class MockDeviceLostCallback {
      public:
        MOCK_METHOD(void, Call, (WGPUDeviceLostReason reason, const char* message, void* userdata));
    };

    std::unique_ptr<StrictMock<MockDeviceLostCallback>> mockDeviceLostCallback;
    void ToMockDeviceLostCallback(WGPUDeviceLostReason reason,
                                  const char* message,
                                  void* userdata) {
        mockDeviceLostCallback->Call(reason, message, userdata);
    }

}  // anonymous namespace

class WireErrorCallbackTests : public WireTest {
  public:
    WireErrorCallbackTests() {
    }
    ~WireErrorCallbackTests() override = default;

    void SetUp() override {
        WireTest::SetUp();

        mockDeviceErrorCallback = std::make_unique<StrictMock<MockDeviceErrorCallback>>();
        mockDeviceLoggingCallback = std::make_unique<StrictMock<MockDeviceLoggingCallback>>();
        mockDevicePopErrorScopeCallback =
            std::make_unique<StrictMock<MockDevicePopErrorScopeCallback>>();
        mockDeviceLostCallback = std::make_unique<StrictMock<MockDeviceLostCallback>>();
    }

    void TearDown() override {
        WireTest::TearDown();

        mockDeviceErrorCallback = nullptr;
        mockDeviceLoggingCallback = nullptr;
        mockDevicePopErrorScopeCallback = nullptr;
        mockDeviceLostCallback = nullptr;
    }

    void FlushServer() {
        WireTest::FlushServer();

        Mock::VerifyAndClearExpectations(&mockDeviceErrorCallback);
        Mock::VerifyAndClearExpectations(&mockDevicePopErrorScopeCallback);
    }
};

// Test the return wire for device error callbacks
TEST_F(WireErrorCallbackTests, DeviceErrorCallback) {
    wgpuDeviceSetUncapturedErrorCallback(device, ToMockDeviceErrorCallback, this);

    // Setting the error callback should stay on the client side and do nothing
    FlushClient();

    // Calling the callback on the server side will result in the callback being called on the
    // client side
    api.CallDeviceSetUncapturedErrorCallbackCallback(apiDevice, WGPUErrorType_Validation,
                                                     "Some error message");

    EXPECT_CALL(*mockDeviceErrorCallback,
                Call(WGPUErrorType_Validation, StrEq("Some error message"), this))
        .Times(1);

    FlushServer();
}

// Test the return wire for device user warning callbacks
TEST_F(WireErrorCallbackTests, DeviceLoggingCallback) {
    wgpuDeviceSetLoggingCallback(device, ToMockDeviceLoggingCallback, this);

    // Setting the injected warning callback should stay on the client side and do nothing
    FlushClient();

    // Calling the callback on the server side will result in the callback being called on the
    // client side
    api.CallDeviceSetLoggingCallbackCallback(apiDevice, WGPULoggingType_Info, "Some message");

    EXPECT_CALL(*mockDeviceLoggingCallback, Call(WGPULoggingType_Info, StrEq("Some message"), this))
        .Times(1);

    FlushServer();
}

// Test the return wire for error scopes.
TEST_F(WireErrorCallbackTests, PushPopErrorScopeCallback) {
    EXPECT_CALL(api, DevicePushErrorScope(apiDevice, WGPUErrorFilter_Validation)).Times(1);
    wgpuDevicePushErrorScope(device, WGPUErrorFilter_Validation);
    FlushClient();

    WGPUErrorCallback callback;
    void* userdata;
    EXPECT_CALL(api, OnDevicePopErrorScope(apiDevice, _, _))
        .WillOnce(DoAll(SaveArg<1>(&callback), SaveArg<2>(&userdata), Return(true)));
    wgpuDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this);
    FlushClient();

    EXPECT_CALL(*mockDevicePopErrorScopeCallback,
                Call(WGPUErrorType_Validation, StrEq("Some error message"), this))
        .Times(1);
    callback(WGPUErrorType_Validation, "Some error message", userdata);
    FlushServer();
}

// Test the return wire for error scopes when callbacks return in a various orders.
TEST_F(WireErrorCallbackTests, PopErrorScopeCallbackOrdering) {
    // Two error scopes are popped, and the first one returns first.
    {
        EXPECT_CALL(api, DevicePushErrorScope(apiDevice, WGPUErrorFilter_Validation)).Times(2);
        wgpuDevicePushErrorScope(device, WGPUErrorFilter_Validation);
        wgpuDevicePushErrorScope(device, WGPUErrorFilter_Validation);
        FlushClient();

        WGPUErrorCallback callback1;
        WGPUErrorCallback callback2;
        void* userdata1;
        void* userdata2;
        EXPECT_CALL(api, OnDevicePopErrorScope(apiDevice, _, _))
            .WillOnce(DoAll(SaveArg<1>(&callback1), SaveArg<2>(&userdata1), Return(true)))
            .WillOnce(DoAll(SaveArg<1>(&callback2), SaveArg<2>(&userdata2), Return(true)));
        wgpuDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this);
        wgpuDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this + 1);
        FlushClient();

        EXPECT_CALL(*mockDevicePopErrorScopeCallback,
                    Call(WGPUErrorType_Validation, StrEq("First error message"), this))
            .Times(1);
        callback1(WGPUErrorType_Validation, "First error message", userdata1);
        FlushServer();

        EXPECT_CALL(*mockDevicePopErrorScopeCallback,
                    Call(WGPUErrorType_Validation, StrEq("Second error message"), this + 1))
            .Times(1);
        callback2(WGPUErrorType_Validation, "Second error message", userdata2);
        FlushServer();
    }

    // Two error scopes are popped, and the second one returns first.
    {
        EXPECT_CALL(api, DevicePushErrorScope(apiDevice, WGPUErrorFilter_Validation)).Times(2);
        wgpuDevicePushErrorScope(device, WGPUErrorFilter_Validation);
        wgpuDevicePushErrorScope(device, WGPUErrorFilter_Validation);
        FlushClient();

        WGPUErrorCallback callback1;
        WGPUErrorCallback callback2;
        void* userdata1;
        void* userdata2;
        EXPECT_CALL(api, OnDevicePopErrorScope(apiDevice, _, _))
            .WillOnce(DoAll(SaveArg<1>(&callback1), SaveArg<2>(&userdata1), Return(true)))
            .WillOnce(DoAll(SaveArg<1>(&callback2), SaveArg<2>(&userdata2), Return(true)));
        wgpuDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this);
        wgpuDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this + 1);
        FlushClient();

        EXPECT_CALL(*mockDevicePopErrorScopeCallback,
                    Call(WGPUErrorType_Validation, StrEq("Second error message"), this + 1))
            .Times(1);
        callback2(WGPUErrorType_Validation, "Second error message", userdata2);
        FlushServer();

        EXPECT_CALL(*mockDevicePopErrorScopeCallback,
                    Call(WGPUErrorType_Validation, StrEq("First error message"), this))
            .Times(1);
        callback1(WGPUErrorType_Validation, "First error message", userdata1);
        FlushServer();
    }
}

// Test the return wire for error scopes in flight when the device is destroyed.
TEST_F(WireErrorCallbackTests, PopErrorScopeDeviceInFlightDestroy) {
    EXPECT_CALL(api, DevicePushErrorScope(apiDevice, WGPUErrorFilter_Validation)).Times(1);
    wgpuDevicePushErrorScope(device, WGPUErrorFilter_Validation);
    FlushClient();

    EXPECT_CALL(api, OnDevicePopErrorScope(apiDevice, _, _)).WillOnce(Return(true));
    wgpuDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this);
    FlushClient();

    // Incomplete callback called in Device destructor. This is resolved after the end of this test.
    EXPECT_CALL(*mockDevicePopErrorScopeCallback,
                Call(WGPUErrorType_Unknown, ValidStringMessage(), this))
        .Times(1);
}

// Test that registering a callback then wire disconnect calls the callback with
// DeviceLost.
TEST_F(WireErrorCallbackTests, PopErrorScopeThenDisconnect) {
    EXPECT_CALL(api, DevicePushErrorScope(apiDevice, WGPUErrorFilter_Validation)).Times(1);
    wgpuDevicePushErrorScope(device, WGPUErrorFilter_Validation);

    EXPECT_CALL(api, OnDevicePopErrorScope(apiDevice, _, _)).WillOnce(Return(true));
    wgpuDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this);
    FlushClient();

    EXPECT_CALL(*mockDevicePopErrorScopeCallback,
                Call(WGPUErrorType_DeviceLost, ValidStringMessage(), this))
        .Times(1);
    GetWireClient()->Disconnect();
}

// Test that registering a callback after wire disconnect calls the callback with
// DeviceLost.
TEST_F(WireErrorCallbackTests, PopErrorScopeAfterDisconnect) {
    EXPECT_CALL(api, DevicePushErrorScope(apiDevice, WGPUErrorFilter_Validation)).Times(1);
    wgpuDevicePushErrorScope(device, WGPUErrorFilter_Validation);
    FlushClient();

    GetWireClient()->Disconnect();

    EXPECT_CALL(*mockDevicePopErrorScopeCallback,
                Call(WGPUErrorType_DeviceLost, ValidStringMessage(), this))
        .Times(1);
    wgpuDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this);
}

// Empty stack (We are emulating the errors that would be callback-ed from native).
TEST_F(WireErrorCallbackTests, PopErrorScopeEmptyStack) {
        WGPUErrorCallback callback;
        void* userdata;
        EXPECT_CALL(api, OnDevicePopErrorScope(apiDevice, _, _))
            .WillOnce(DoAll(SaveArg<1>(&callback), SaveArg<2>(&userdata), Return(true)));
        wgpuDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this);
        FlushClient();

        EXPECT_CALL(*mockDevicePopErrorScopeCallback,
                    Call(WGPUErrorType_Validation, StrEq("No error scopes to pop"), this))
            .Times(1);
        callback(WGPUErrorType_Validation, "No error scopes to pop", userdata);
        FlushServer();
}

// Test the return wire for device lost callback
TEST_F(WireErrorCallbackTests, DeviceLostCallback) {
    wgpuDeviceSetDeviceLostCallback(device, ToMockDeviceLostCallback, this);

    // Setting the error callback should stay on the client side and do nothing
    FlushClient();

    // Calling the callback on the server side will result in the callback being called on the
    // client side
    api.CallDeviceSetDeviceLostCallbackCallback(apiDevice, WGPUDeviceLostReason_Undefined,
                                                "Some error message");

    EXPECT_CALL(*mockDeviceLostCallback,
                Call(WGPUDeviceLostReason_Undefined, StrEq("Some error message"), this))
        .Times(1);

    FlushServer();
}
