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

using namespace testing;
using namespace dawn_wire;

namespace {

    // Mock classes to add expectations on the wire calling callbacks
    class MockBufferMapReadCallback {
      public:
        MOCK_METHOD4(Call,
                     void(WGPUBufferMapAsyncStatus status,
                          const uint32_t* ptr,
                          uint64_t dataLength,
                          void* userdata));
    };

    std::unique_ptr<StrictMock<MockBufferMapReadCallback>> mockBufferMapReadCallback;
    void ToMockBufferMapReadCallback(WGPUBufferMapAsyncStatus status,
                                     const void* ptr,
                                     uint64_t dataLength,
                                     void* userdata) {
        // Assume the data is uint32_t to make writing matchers easier
        mockBufferMapReadCallback->Call(status, static_cast<const uint32_t*>(ptr), dataLength,
                                        userdata);
    }

    class MockBufferMapWriteCallback {
      public:
        MOCK_METHOD4(Call,
                     void(WGPUBufferMapAsyncStatus status,
                          uint32_t* ptr,
                          uint64_t dataLength,
                          void* userdata));
    };

    std::unique_ptr<StrictMock<MockBufferMapWriteCallback>> mockBufferMapWriteCallback;
    uint32_t* lastMapWritePointer = nullptr;
    void ToMockBufferMapWriteCallback(WGPUBufferMapAsyncStatus status,
                                      void* ptr,
                                      uint64_t dataLength,
                                      void* userdata) {
        // Assume the data is uint32_t to make writing matchers easier
        lastMapWritePointer = static_cast<uint32_t*>(ptr);
        mockBufferMapWriteCallback->Call(status, lastMapWritePointer, dataLength, userdata);
    }

    class MockBufferCreateMappedCallback {
      public:
        MOCK_METHOD5(Call,
                     void(WGPUBufferMapAsyncStatus status,
                          WGPUBuffer buffer,
                          uint32_t* ptr,
                          uint64_t dataLength,
                          void* userdata));
    };

    std::unique_ptr<StrictMock<MockBufferCreateMappedCallback>> mockCreateBufferMappedCallback;
    uint32_t* lastCreateMappedPointer = nullptr;
    void ToMockCreateBufferMappedCallback(WGPUBufferMapAsyncStatus status,
                                          WGPUCreateBufferMappedResult result,
                                          void* userdata) {
        // Assume the data is uint32_t to make writing matchers easier
        lastCreateMappedPointer = static_cast<uint32_t*>(result.data);
        // Unpack WGPUCreateBufferMappedResult to make writing matchers easier
        mockCreateBufferMappedCallback->Call(status, result.buffer, lastCreateMappedPointer,
                                             result.dataLength, userdata);
    }

}  // anonymous namespace

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

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

        mockBufferMapReadCallback = std::make_unique<StrictMock<MockBufferMapReadCallback>>();
        mockBufferMapWriteCallback = std::make_unique<StrictMock<MockBufferMapWriteCallback>>();
        mockCreateBufferMappedCallback =
            std::make_unique<StrictMock<MockBufferCreateMappedCallback>>();

        WGPUBufferDescriptor descriptor;
        descriptor.nextInChain = nullptr;
        descriptor.label = nullptr;
        descriptor.size = kBufferSize;

        apiBuffer = api.GetNewBuffer();
        buffer = wgpuDeviceCreateBuffer(device, &descriptor);

        EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _))
            .WillOnce(Return(apiBuffer))
            .RetiresOnSaturation();
        FlushClient();
    }

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

        // Delete mocks so that expectations are checked
        mockBufferMapReadCallback = nullptr;
        mockBufferMapWriteCallback = nullptr;
        mockCreateBufferMappedCallback = nullptr;
    }

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

        Mock::VerifyAndClearExpectations(&mockBufferMapReadCallback);
        Mock::VerifyAndClearExpectations(&mockBufferMapWriteCallback);
        Mock::VerifyAndClearExpectations(&mockCreateBufferMappedCallback);
    }

  protected:
    static constexpr uint64_t kBufferSize = sizeof(uint32_t);
    // A successfully created buffer
    WGPUBuffer buffer;
    WGPUBuffer apiBuffer;
};

// MapRead-specific tests

// Check mapping for reading a succesfully created buffer
TEST_F(WireBufferMappingTests, MappingForReadSuccessBuffer) {
    wgpuBufferMapReadAsync(buffer, ToMockBufferMapReadCallback, nullptr);

    uint32_t bufferContent = 31337;
    EXPECT_CALL(api, OnBufferMapReadAsyncCallback(apiBuffer, _, _))
        .WillOnce(InvokeWithoutArgs([&]() {
            api.CallMapReadCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success, &bufferContent,
                                    kBufferSize);
        }));

    FlushClient();

    EXPECT_CALL(*mockBufferMapReadCallback,
                Call(WGPUBufferMapAsyncStatus_Success, Pointee(Eq(bufferContent)), kBufferSize, _))
        .Times(1);

    FlushServer();

    wgpuBufferUnmap(buffer);
    EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);

    FlushClient();
}

// Check that things work correctly when a validation error happens when mapping the buffer for
// reading
TEST_F(WireBufferMappingTests, ErrorWhileMappingForRead) {
    wgpuBufferMapReadAsync(buffer, ToMockBufferMapReadCallback, nullptr);

    EXPECT_CALL(api, OnBufferMapReadAsyncCallback(apiBuffer, _, _))
        .WillOnce(InvokeWithoutArgs([&]() {
            api.CallMapReadCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error, nullptr, 0);
        }));

    FlushClient();

    EXPECT_CALL(*mockBufferMapReadCallback, Call(WGPUBufferMapAsyncStatus_Error, nullptr, 0, _))
        .Times(1);

    FlushServer();
}

// Check that the map read callback is called with UNKNOWN when the buffer is destroyed before the
// request is finished
TEST_F(WireBufferMappingTests, DestroyBeforeReadRequestEnd) {
    wgpuBufferMapReadAsync(buffer, ToMockBufferMapReadCallback, nullptr);

    // Return success
    EXPECT_CALL(api, OnBufferMapReadAsyncCallback(apiBuffer, _, _))
        .WillOnce(InvokeWithoutArgs([&]() {
            api.CallMapReadCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success, nullptr, 0);
        }));

    // Destroy before the client gets the success, so the callback is called with unknown.
    EXPECT_CALL(*mockBufferMapReadCallback, Call(WGPUBufferMapAsyncStatus_Unknown, nullptr, 0, _))
        .Times(1);
    wgpuBufferRelease(buffer);
    EXPECT_CALL(api, BufferRelease(apiBuffer));

    FlushClient();
    FlushServer();
}

// Check the map read callback is called with UNKNOWN when the map request would have worked, but
// Unmap was called
TEST_F(WireBufferMappingTests, UnmapCalledTooEarlyForRead) {
    wgpuBufferMapReadAsync(buffer, ToMockBufferMapReadCallback, nullptr);

    uint32_t bufferContent = 31337;
    EXPECT_CALL(api, OnBufferMapReadAsyncCallback(apiBuffer, _, _))
        .WillOnce(InvokeWithoutArgs([&]() {
            api.CallMapReadCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success, &bufferContent,
                                    kBufferSize);
        }));

    FlushClient();

    // Oh no! We are calling Unmap too early!
    EXPECT_CALL(*mockBufferMapReadCallback, Call(WGPUBufferMapAsyncStatus_Unknown, nullptr, 0, _))
        .Times(1);
    wgpuBufferUnmap(buffer);

    // The callback shouldn't get called, even when the request succeeded on the server side
    FlushServer();
}

// Check that an error map read callback gets nullptr while a buffer is already mapped
TEST_F(WireBufferMappingTests, MappingForReadingErrorWhileAlreadyMappedGetsNullptr) {
    // Successful map
    wgpuBufferMapReadAsync(buffer, ToMockBufferMapReadCallback, nullptr);

    uint32_t bufferContent = 31337;
    EXPECT_CALL(api, OnBufferMapReadAsyncCallback(apiBuffer, _, _))
        .WillOnce(InvokeWithoutArgs([&]() {
            api.CallMapReadCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success, &bufferContent,
                                    kBufferSize);
        }))
        .RetiresOnSaturation();

    FlushClient();

    EXPECT_CALL(*mockBufferMapReadCallback,
                Call(WGPUBufferMapAsyncStatus_Success, Pointee(Eq(bufferContent)), kBufferSize, _))
        .Times(1);

    FlushServer();

    // Map failure while the buffer is already mapped
    wgpuBufferMapReadAsync(buffer, ToMockBufferMapReadCallback, nullptr);
    EXPECT_CALL(api, OnBufferMapReadAsyncCallback(apiBuffer, _, _))
        .WillOnce(InvokeWithoutArgs([&]() {
            api.CallMapReadCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error, nullptr, 0);
        }));

    FlushClient();

    EXPECT_CALL(*mockBufferMapReadCallback, Call(WGPUBufferMapAsyncStatus_Error, nullptr, 0, _))
        .Times(1);

    FlushServer();
}

// Test that the MapReadCallback isn't fired twice when unmap() is called inside the callback
TEST_F(WireBufferMappingTests, UnmapInsideMapReadCallback) {
    wgpuBufferMapReadAsync(buffer, ToMockBufferMapReadCallback, nullptr);

    uint32_t bufferContent = 31337;
    EXPECT_CALL(api, OnBufferMapReadAsyncCallback(apiBuffer, _, _))
        .WillOnce(InvokeWithoutArgs([&]() {
            api.CallMapReadCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success, &bufferContent,
                                    kBufferSize);
        }));

    FlushClient();

    EXPECT_CALL(*mockBufferMapReadCallback,
                Call(WGPUBufferMapAsyncStatus_Success, Pointee(Eq(bufferContent)), kBufferSize, _))
        .WillOnce(InvokeWithoutArgs([&]() { wgpuBufferUnmap(buffer); }));

    FlushServer();

    EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);

    FlushClient();
}

// Test that the MapReadCallback isn't fired twice the buffer external refcount reaches 0 in the
// callback
TEST_F(WireBufferMappingTests, DestroyInsideMapReadCallback) {
    wgpuBufferMapReadAsync(buffer, ToMockBufferMapReadCallback, nullptr);

    uint32_t bufferContent = 31337;
    EXPECT_CALL(api, OnBufferMapReadAsyncCallback(apiBuffer, _, _))
        .WillOnce(InvokeWithoutArgs([&]() {
            api.CallMapReadCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success, &bufferContent,
                                    kBufferSize);
        }));

    FlushClient();

    EXPECT_CALL(*mockBufferMapReadCallback,
                Call(WGPUBufferMapAsyncStatus_Success, Pointee(Eq(bufferContent)), kBufferSize, _))
        .WillOnce(InvokeWithoutArgs([&]() { wgpuBufferRelease(buffer); }));

    FlushServer();

    EXPECT_CALL(api, BufferRelease(apiBuffer));

    FlushClient();
}

// MapWrite-specific tests

// Check mapping for writing a succesfully created buffer
TEST_F(WireBufferMappingTests, MappingForWriteSuccessBuffer) {
    wgpuBufferMapWriteAsync(buffer, ToMockBufferMapWriteCallback, nullptr);

    uint32_t serverBufferContent = 31337;
    uint32_t updatedContent = 4242;
    uint32_t zero = 0;

    EXPECT_CALL(api, OnBufferMapWriteAsyncCallback(apiBuffer, _, _))
        .WillOnce(InvokeWithoutArgs([&]() {
            api.CallMapWriteCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success,
                                     &serverBufferContent, kBufferSize);
        }));

    FlushClient();

    // The map write callback always gets a buffer full of zeroes.
    EXPECT_CALL(*mockBufferMapWriteCallback,
                Call(WGPUBufferMapAsyncStatus_Success, Pointee(Eq(zero)), kBufferSize, _))
        .Times(1);

    FlushServer();

    // Write something to the mapped pointer
    *lastMapWritePointer = updatedContent;

    wgpuBufferUnmap(buffer);
    EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);

    FlushClient();

    // After the buffer is unmapped, the content of the buffer is updated on the server
    ASSERT_EQ(serverBufferContent, updatedContent);
}

// Check that things work correctly when a validation error happens when mapping the buffer for
// writing
TEST_F(WireBufferMappingTests, ErrorWhileMappingForWrite) {
    wgpuBufferMapWriteAsync(buffer, ToMockBufferMapWriteCallback, nullptr);

    EXPECT_CALL(api, OnBufferMapWriteAsyncCallback(apiBuffer, _, _))
        .WillOnce(InvokeWithoutArgs([&]() {
            api.CallMapWriteCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error, nullptr, 0);
        }));

    FlushClient();

    EXPECT_CALL(*mockBufferMapWriteCallback, Call(WGPUBufferMapAsyncStatus_Error, nullptr, 0, _))
        .Times(1);

    FlushServer();
}

// Check that the map write callback is called with UNKNOWN when the buffer is destroyed before the
// request is finished
TEST_F(WireBufferMappingTests, DestroyBeforeWriteRequestEnd) {
    wgpuBufferMapWriteAsync(buffer, ToMockBufferMapWriteCallback, nullptr);

    // Return success
    EXPECT_CALL(api, OnBufferMapWriteAsyncCallback(apiBuffer, _, _))
        .WillOnce(InvokeWithoutArgs([&]() {
            api.CallMapWriteCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success, nullptr, 0);
        }));

    // Destroy before the client gets the success, so the callback is called with unknown.
    EXPECT_CALL(*mockBufferMapWriteCallback, Call(WGPUBufferMapAsyncStatus_Unknown, nullptr, 0, _))
        .Times(1);
    wgpuBufferRelease(buffer);
    EXPECT_CALL(api, BufferRelease(apiBuffer));

    FlushClient();
    FlushServer();
}

// Check the map read callback is called with UNKNOWN when the map request would have worked, but
// Unmap was called
TEST_F(WireBufferMappingTests, UnmapCalledTooEarlyForWrite) {
    wgpuBufferMapWriteAsync(buffer, ToMockBufferMapWriteCallback, nullptr);

    uint32_t bufferContent = 31337;
    EXPECT_CALL(api, OnBufferMapWriteAsyncCallback(apiBuffer, _, _))
        .WillOnce(InvokeWithoutArgs([&]() {
            api.CallMapWriteCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success, &bufferContent,
                                     kBufferSize);
        }));

    FlushClient();

    // Oh no! We are calling Unmap too early!
    EXPECT_CALL(*mockBufferMapWriteCallback, Call(WGPUBufferMapAsyncStatus_Unknown, nullptr, 0, _))
        .Times(1);
    wgpuBufferUnmap(buffer);

    // The callback shouldn't get called, even when the request succeeded on the server side
    FlushServer();
}

// Check that an error map read callback gets nullptr while a buffer is already mapped
TEST_F(WireBufferMappingTests, MappingForWritingErrorWhileAlreadyMappedGetsNullptr) {
    // Successful map
    wgpuBufferMapWriteAsync(buffer, ToMockBufferMapWriteCallback, nullptr);

    uint32_t bufferContent = 31337;
    uint32_t zero = 0;
    EXPECT_CALL(api, OnBufferMapWriteAsyncCallback(apiBuffer, _, _))
        .WillOnce(InvokeWithoutArgs([&]() {
            api.CallMapWriteCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success, &bufferContent,
                                     kBufferSize);
        }))
        .RetiresOnSaturation();

    FlushClient();

    EXPECT_CALL(*mockBufferMapWriteCallback,
                Call(WGPUBufferMapAsyncStatus_Success, Pointee(Eq(zero)), kBufferSize, _))
        .Times(1);

    FlushServer();

    // Map failure while the buffer is already mapped
    wgpuBufferMapWriteAsync(buffer, ToMockBufferMapWriteCallback, nullptr);
    EXPECT_CALL(api, OnBufferMapWriteAsyncCallback(apiBuffer, _, _))
        .WillOnce(InvokeWithoutArgs([&]() {
            api.CallMapWriteCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error, nullptr, 0);
        }));

    FlushClient();

    EXPECT_CALL(*mockBufferMapWriteCallback, Call(WGPUBufferMapAsyncStatus_Error, nullptr, 0, _))
        .Times(1);

    FlushServer();
}

// Test that the MapWriteCallback isn't fired twice when unmap() is called inside the callback
TEST_F(WireBufferMappingTests, UnmapInsideMapWriteCallback) {
    wgpuBufferMapWriteAsync(buffer, ToMockBufferMapWriteCallback, nullptr);

    uint32_t bufferContent = 31337;
    uint32_t zero = 0;
    EXPECT_CALL(api, OnBufferMapWriteAsyncCallback(apiBuffer, _, _))
        .WillOnce(InvokeWithoutArgs([&]() {
            api.CallMapWriteCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success, &bufferContent,
                                     kBufferSize);
        }));

    FlushClient();

    EXPECT_CALL(*mockBufferMapWriteCallback,
                Call(WGPUBufferMapAsyncStatus_Success, Pointee(Eq(zero)), kBufferSize, _))
        .WillOnce(InvokeWithoutArgs([&]() { wgpuBufferUnmap(buffer); }));

    FlushServer();

    EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);

    FlushClient();
}

// Test that the MapWriteCallback isn't fired twice the buffer external refcount reaches 0 in the
// callback
TEST_F(WireBufferMappingTests, DestroyInsideMapWriteCallback) {
    wgpuBufferMapWriteAsync(buffer, ToMockBufferMapWriteCallback, nullptr);

    uint32_t bufferContent = 31337;
    uint32_t zero = 0;
    EXPECT_CALL(api, OnBufferMapWriteAsyncCallback(apiBuffer, _, _))
        .WillOnce(InvokeWithoutArgs([&]() {
            api.CallMapWriteCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success, &bufferContent,
                                     kBufferSize);
        }));

    FlushClient();

    EXPECT_CALL(*mockBufferMapWriteCallback,
                Call(WGPUBufferMapAsyncStatus_Success, Pointee(Eq(zero)), kBufferSize, _))
        .WillOnce(InvokeWithoutArgs([&]() { wgpuBufferRelease(buffer); }));

    FlushServer();

    EXPECT_CALL(api, BufferRelease(apiBuffer));

    FlushClient();
}

// Test successful CreateBufferMapped
TEST_F(WireBufferMappingTests, CreateBufferMappedSuccess) {
    WGPUBufferDescriptor descriptor;
    descriptor.nextInChain = nullptr;
    descriptor.label = nullptr;
    descriptor.size = 4;

    WGPUBuffer apiBuffer = api.GetNewBuffer();
    WGPUCreateBufferMappedResult apiResult;
    uint32_t apiBufferData = 1234;
    apiResult.buffer = apiBuffer;
    apiResult.data = reinterpret_cast<uint8_t*>(&apiBufferData);
    apiResult.dataLength = 4;

    WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);

    EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
        .WillOnce(Return(apiResult))
        .RetiresOnSaturation();

    FlushClient();

    wgpuBufferUnmap(result.buffer);
    EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);

    FlushClient();
}

// Test that releasing after CreateBufferMapped does not call Unmap
TEST_F(WireBufferMappingTests, ReleaseAfterCreateBufferMapped) {
    WGPUBufferDescriptor descriptor;
    descriptor.nextInChain = nullptr;
    descriptor.label = nullptr;
    descriptor.size = 4;

    WGPUBuffer apiBuffer = api.GetNewBuffer();
    WGPUCreateBufferMappedResult apiResult;
    uint32_t apiBufferData = 1234;
    apiResult.buffer = apiBuffer;
    apiResult.data = reinterpret_cast<uint8_t*>(&apiBufferData);
    apiResult.dataLength = 4;

    WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);

    EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
        .WillOnce(Return(apiResult))
        .RetiresOnSaturation();

    FlushClient();

    wgpuBufferRelease(result.buffer);
    EXPECT_CALL(api, BufferRelease(apiBuffer)).Times(1);

    FlushClient();
}

// Test that it is valid to map a buffer after CreateBufferMapped and Unmap
TEST_F(WireBufferMappingTests, CreateBufferMappedThenMapSuccess) {
    WGPUBufferDescriptor descriptor;
    descriptor.nextInChain = nullptr;
    descriptor.label = nullptr;
    descriptor.size = 4;

    WGPUBuffer apiBuffer = api.GetNewBuffer();
    WGPUCreateBufferMappedResult apiResult;
    uint32_t apiBufferData = 9863;
    apiResult.buffer = apiBuffer;
    apiResult.data = reinterpret_cast<uint8_t*>(&apiBufferData);
    apiResult.dataLength = 4;

    WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);

    EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
        .WillOnce(Return(apiResult))
        .RetiresOnSaturation();

    FlushClient();

    wgpuBufferUnmap(result.buffer);
    EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);

    FlushClient();

    wgpuBufferMapWriteAsync(result.buffer, ToMockBufferMapWriteCallback, nullptr);

    uint32_t zero = 0;
    EXPECT_CALL(api, OnBufferMapWriteAsyncCallback(apiBuffer, _, _))
        .WillOnce(InvokeWithoutArgs([&]() {
            api.CallMapWriteCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success, &apiBufferData,
                                     kBufferSize);
        }));

    FlushClient();

    EXPECT_CALL(*mockBufferMapWriteCallback,
                Call(WGPUBufferMapAsyncStatus_Success, Pointee(Eq(zero)), kBufferSize, _))
        .Times(1);

    FlushServer();
}

// Test that it is invalid to map a buffer after CreateBufferMapped before Unmap
TEST_F(WireBufferMappingTests, CreateBufferMappedThenMapFailure) {
    WGPUBufferDescriptor descriptor;
    descriptor.nextInChain = nullptr;
    descriptor.label = nullptr;
    descriptor.size = 4;

    WGPUBuffer apiBuffer = api.GetNewBuffer();
    WGPUCreateBufferMappedResult apiResult;
    uint32_t apiBufferData = 9863;
    apiResult.buffer = apiBuffer;
    apiResult.data = reinterpret_cast<uint8_t*>(&apiBufferData);
    apiResult.dataLength = 4;

    WGPUCreateBufferMappedResult result = wgpuDeviceCreateBufferMapped(device, &descriptor);

    EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
        .WillOnce(Return(apiResult))
        .RetiresOnSaturation();

    FlushClient();

    wgpuBufferMapWriteAsync(result.buffer, ToMockBufferMapWriteCallback, nullptr);

    EXPECT_CALL(api, OnBufferMapWriteAsyncCallback(apiBuffer, _, _))
        .WillOnce(InvokeWithoutArgs([&]() {
            api.CallMapWriteCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error, nullptr, 0);
        }));

    FlushClient();

    EXPECT_CALL(*mockBufferMapWriteCallback, Call(WGPUBufferMapAsyncStatus_Error, nullptr, 0, _))
        .Times(1);

    FlushServer();

    wgpuBufferUnmap(result.buffer);
    EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);

    FlushClient();
}

// Test successful CreateBufferMappedAsync
TEST_F(WireBufferMappingTests, CreateBufferMappedAsyncSuccess) {
    WGPUBufferDescriptor descriptor;
    descriptor.nextInChain = nullptr;
    descriptor.label = nullptr;
    descriptor.size = kBufferSize;

    WGPUCreateBufferMappedResult apiResult;
    uint32_t serverBufferContent = 31337;
    apiResult.buffer = apiBuffer;
    apiResult.data = reinterpret_cast<uint8_t*>(&serverBufferContent);
    apiResult.dataLength = kBufferSize;

    uint32_t updatedContent = 4242;
    uint32_t zero = 0;

    wgpuDeviceCreateBufferMappedAsync(device, &descriptor, ToMockCreateBufferMappedCallback,
                                      nullptr);

    EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
        .WillOnce(Return(apiResult))
        .RetiresOnSaturation();

    FlushClient();

    WGPUBuffer buffer;
    // The callback always gets a buffer full of zeroes.
    EXPECT_CALL(*mockCreateBufferMappedCallback,
                Call(WGPUBufferMapAsyncStatus_Success, _, Pointee(Eq(zero)), kBufferSize, _))
        .WillOnce(::testing::SaveArg<1>(&buffer));

    FlushServer();

    // Write something to the mapped pointer
    *lastCreateMappedPointer = updatedContent;

    wgpuBufferUnmap(buffer);
    EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);

    FlushClient();

    // After the buffer is unmapped, the content of the buffer is updated on the server
    ASSERT_EQ(serverBufferContent, updatedContent);
}

// Test CreateBufferMappedAsync with map error
TEST_F(WireBufferMappingTests, CreateBufferMappedAsyncMapError) {
    WGPUBufferDescriptor descriptor;
    descriptor.nextInChain = nullptr;
    descriptor.label = nullptr;

    WGPUCreateBufferMappedResult apiResult;
    apiResult.buffer = apiBuffer;
    apiResult.data = nullptr;  // error mapping
    apiResult.dataLength = kBufferSize;

    wgpuDeviceCreateBufferMappedAsync(device, &descriptor, ToMockCreateBufferMappedCallback,
                                      nullptr);

    EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
        .WillOnce(Return(apiResult))
        .RetiresOnSaturation();

    FlushClient();

    WGPUBuffer buffer;
    EXPECT_CALL(*mockCreateBufferMappedCallback,
                Call(WGPUBufferMapAsyncStatus_Error, _, nullptr, 0, _))
        .WillOnce(::testing::SaveArg<1>(&buffer));

    FlushServer();

    wgpuBufferUnmap(buffer);
    EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);

    FlushClient();
}

// Test that the CreateBufferMappedCallback isn't fired twice when unmap() is called inside the
// callback
TEST_F(WireBufferMappingTests, UnmapInsideCreateBufferMappedAsyncCallback) {
    WGPUBufferDescriptor descriptor;
    descriptor.nextInChain = nullptr;
    descriptor.label = nullptr;
    descriptor.size = kBufferSize;

    WGPUCreateBufferMappedResult apiResult;
    uint32_t serverBufferContent = 31337;
    apiResult.buffer = apiBuffer;
    apiResult.data = reinterpret_cast<uint8_t*>(&serverBufferContent);
    apiResult.dataLength = kBufferSize;

    uint32_t zero = 0;

    wgpuDeviceCreateBufferMappedAsync(device, &descriptor, ToMockCreateBufferMappedCallback,
                                      nullptr);

    EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
        .WillOnce(Return(apiResult))
        .RetiresOnSaturation();

    FlushClient();

    WGPUBuffer buffer;
    // The callback always gets a buffer full of zeroes.
    EXPECT_CALL(*mockCreateBufferMappedCallback,
                Call(WGPUBufferMapAsyncStatus_Success, _, Pointee(Eq(zero)), kBufferSize, _))
        .WillOnce(DoAll(::testing::SaveArg<1>(&buffer),
                        InvokeWithoutArgs([&]() { wgpuBufferUnmap(buffer); })));

    FlushServer();

    EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);

    FlushClient();
}

// Test that the CreateBufferMappedCallback isn't fired twice when the buffer is deleted inside
// the callback
TEST_F(WireBufferMappingTests, ReleaseInsideCreateBufferMappedAsyncCallback) {
    WGPUBufferDescriptor descriptor;
    descriptor.nextInChain = nullptr;
    descriptor.label = nullptr;
    descriptor.size = kBufferSize;

    WGPUCreateBufferMappedResult apiResult;
    uint32_t serverBufferContent = 31337;
    apiResult.buffer = apiBuffer;
    apiResult.data = reinterpret_cast<uint8_t*>(&serverBufferContent);
    apiResult.dataLength = kBufferSize;

    uint32_t zero = 0;

    wgpuDeviceCreateBufferMappedAsync(device, &descriptor, ToMockCreateBufferMappedCallback,
                                      nullptr);

    EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
        .WillOnce(Return(apiResult))
        .RetiresOnSaturation();

    FlushClient();

    WGPUBuffer buffer;
    // The callback always gets a buffer full of zeroes.
    EXPECT_CALL(*mockCreateBufferMappedCallback,
                Call(WGPUBufferMapAsyncStatus_Success, _, Pointee(Eq(zero)), kBufferSize, _))
        .WillOnce(DoAll(::testing::SaveArg<1>(&buffer),
                        InvokeWithoutArgs([&]() { wgpuBufferRelease(buffer); })));

    FlushServer();

    EXPECT_CALL(api, BufferRelease(apiBuffer));

    FlushClient();
}

// Test that the CreateBufferMappedCallback isn't fired twice when the buffer is destroyed inside
// the callback
TEST_F(WireBufferMappingTests, DestroyInsideCreateBufferMappedAsyncCallback) {
    WGPUBufferDescriptor descriptor;
    descriptor.nextInChain = nullptr;
    descriptor.label = nullptr;
    descriptor.size = kBufferSize;

    WGPUCreateBufferMappedResult apiResult;
    uint32_t serverBufferContent = 31337;
    apiResult.buffer = apiBuffer;
    apiResult.data = reinterpret_cast<uint8_t*>(&serverBufferContent);
    apiResult.dataLength = kBufferSize;

    uint32_t zero = 0;

    wgpuDeviceCreateBufferMappedAsync(device, &descriptor, ToMockCreateBufferMappedCallback,
                                      nullptr);

    EXPECT_CALL(api, DeviceCreateBufferMapped(apiDevice, _))
        .WillOnce(Return(apiResult))
        .RetiresOnSaturation();

    FlushClient();

    WGPUBuffer buffer;
    // The callback always gets a buffer full of zeroes.
    EXPECT_CALL(*mockCreateBufferMappedCallback,
                Call(WGPUBufferMapAsyncStatus_Success, _, Pointee(Eq(zero)), kBufferSize, _))
        .WillOnce(DoAll(::testing::SaveArg<1>(&buffer),
                        InvokeWithoutArgs([&]() { wgpuBufferDestroy(buffer); })));

    FlushServer();

    EXPECT_CALL(api, BufferDestroy(apiBuffer));

    FlushClient();
}
