// 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 <limits>
#include <memory>

#include "dawn/common/Assert.h"
#include "dawn/common/StringViewUtils.h"
#include "dawn/tests/StringViewMatchers.h"
#include "dawn/tests/unittests/wire/WireFutureTest.h"
#include "dawn/tests/unittests/wire/WireTest.h"
#include "dawn/wire/WireClient.h"

namespace wgpu {
// Define a stream operator for wgpu::MapMode so that it can be found on resolution for test name
// generation.
// TODO(dawn:2205) Remove this in favor of custom serializer.
static std::ostream& operator<<(std::ostream& os, const MapMode& param) {
    switch (param) {
        case wgpu::MapMode::Read:
            os << "Read";
            break;
        case wgpu::MapMode::Write:
            os << "Write";
            break;
        default:
            DAWN_UNREACHABLE();
    }
    return os;
}
}  // namespace wgpu

namespace dawn::wire {
namespace {

using testing::_;
using testing::InvokeWithoutArgs;
using testing::Return;
using testing::SizedString;

// For the buffer tests, we make passing a map mode optional to reuse the same test fixture for
// tests that test multiple modes and tests that are mode specific. By making it an optional, it
// allows us to determine whether the map mode is necessary when generating the test names.
using MapMode = std::optional<wgpu::MapMode>;
DAWN_WIRE_FUTURE_TEST_PARAM_STRUCT(WireBufferParam, MapMode);

using WireBufferMappingTestBase =
    WireFutureTestWithParams<wgpu::BufferMapCallback<void>*, WireBufferParam>;

// General mapping tests that either do not care about the specific mapping mode, or apply to both.
class WireBufferMappingTests : public WireBufferMappingTestBase {
  protected:
    void SetUp() override {
        WireBufferMappingTestBase::SetUp();
        apiBuffer = api.GetNewBuffer();

        if (GetParam().mMapMode) {
            SetupBuffer(GetMapMode());
        }
    }

    void TearDown() override {
        // We must lose all references to objects before calling parent TearDown to avoid
        // referencing the proc table after it gets cleared.
        buffer = nullptr;

        WireBufferMappingTestBase::TearDown();
    }

    void MapAsync(wgpu::MapMode mode, size_t offset, size_t size) {
        this->mFutureIDs.push_back(buffer
                                       .MapAsync(mode, offset, size, this->GetParam().callbackMode,
                                                 this->mMockCb.Callback())
                                       .id);
    }

    wgpu::MapMode GetMapMode() {
        DAWN_ASSERT(GetParam().mMapMode);
        return *GetParam().mMapMode;
    }

    void SetupBuffer(wgpu::MapMode mapMode) {
        wgpu::BufferUsage usage = wgpu::BufferUsage::MapRead;
        if (mapMode == wgpu::MapMode::Read) {
            usage = wgpu::BufferUsage::MapRead;
        } else if (mapMode == wgpu::MapMode::Write) {
            usage = wgpu::BufferUsage::MapWrite;
        }

        wgpu::BufferDescriptor descriptor = {};
        descriptor.size = kBufferSize;
        descriptor.usage = usage;
        buffer = device.CreateBuffer(&descriptor);

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

    // Sets up the correct mapped range call expectations given the map mode.
    void ExpectMappedRangeCall(uint64_t bufferSize, void* bufferContent) {
        wgpu::MapMode mapMode = GetMapMode();
        if (mapMode == wgpu::MapMode::Read) {
            EXPECT_CALL(api, BufferGetConstMappedRange(apiBuffer, 0, bufferSize))
                .WillOnce(Return(bufferContent));
        } else if (mapMode == wgpu::MapMode::Write) {
            EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, bufferSize))
                .WillOnce(Return(bufferContent));
        }
    }

    // Test to exercise client functions that should override server response for callbacks.
    template <typename CancelFn, typename ExpFn>
    void TestEarlyMapCancelled(CancelFn cancelMapping,
                               ExpFn addExpectations,
                               wgpu::MapAsyncStatus expected,
                               const char* expectedMessage,
                               bool calledInCancelFn) {
        wgpu::MapMode mapMode = GetMapMode();
        MapAsync(mapMode, 0, kBufferSize);

        uint32_t bufferContent = 31337;
        EXPECT_CALL(
            api, OnBufferMapAsync(apiBuffer, static_cast<WGPUMapMode>(mapMode), 0, kBufferSize, _))
            .WillOnce(InvokeWithoutArgs([&] {
                api.CallBufferMapAsyncCallback(apiBuffer, WGPUMapAsyncStatus_Success,
                                               kEmptyOutputStringView);
            }));
        ExpectMappedRangeCall(kBufferSize, &bufferContent);
        addExpectations();

        // The callback should get called with the expected status, regardless if the server has
        // responded.
        if (calledInCancelFn) {
            // In spontaneous mode, the callback gets called as a part of the cancel function.
            ExpectWireCallbacksWhen([&](auto& mockCb) {
                EXPECT_CALL(mockCb, Call(expected, SizedString(expectedMessage))).Times(1);

                cancelMapping();
            });
            FlushClient();
            FlushCallbacks();
        } else {
            // Otherwise, the callback will fire when we flush them.
            cancelMapping();
            FlushClient();
            ExpectWireCallbacksWhen([&](auto& mockCb) {
                EXPECT_CALL(mockCb, Call(expected, SizedString(expectedMessage))).Times(1);

                FlushCallbacks();
            });
        }
    }

    // Test to exercise client functions that should override server error response for callbacks.
    template <typename CancelFn, typename ExpFn>
    void TestEarlyMapErrorCancelled(CancelFn cancelMapping,
                                    ExpFn addExpectations,
                                    wgpu::MapAsyncStatus expected,
                                    const char* expectedMessage,
                                    bool calledInCancelFn) {
        wgpu::MapMode mapMode = GetMapMode();
        MapAsync(mapMode, 0, kBufferSize);

        EXPECT_CALL(
            api, OnBufferMapAsync(apiBuffer, static_cast<WGPUMapMode>(mapMode), 0, kBufferSize, _))
            .WillOnce(InvokeWithoutArgs([&] {
                api.CallBufferMapAsyncCallback(apiBuffer, WGPUMapAsyncStatus_Error,
                                               ToOutputStringView("Validation error"));
            }));

        // Ensure that the server had a chance to respond if relevant.
        FlushClient();
        FlushFutures();

        addExpectations();

        // The callback should get called with the expected status status, not server-side error,
        // even if the request fails on the server side.
        if (calledInCancelFn) {
            // In spontaneous mode, the callback gets called as a part of the cancel function.
            ExpectWireCallbacksWhen([&](auto& mockCb) {
                EXPECT_CALL(mockCb, Call(expected, SizedString(expectedMessage))).Times(1);

                cancelMapping();
            });
            FlushClient();
            FlushCallbacks();
        } else {
            // Otherwise, the callback will fire when we flush them.
            cancelMapping();
            FlushClient();
            ExpectWireCallbacksWhen([&](auto& mockCb) {
                EXPECT_CALL(mockCb, Call(expected, SizedString(expectedMessage))).Times(1);

                FlushCallbacks();
            });
        }
    }

    // Test to exercise client functions that would cancel callbacks don't cause the callback to be
    // fired twice.
    template <typename CancelFn, typename ExpFn>
    void TestCancelInCallback(CancelFn cancelMapping, ExpFn addExpectations) {
        wgpu::MapMode mapMode = GetMapMode();
        MapAsync(mapMode, 0, kBufferSize);

        uint32_t bufferContent = 31337;
        EXPECT_CALL(
            api, OnBufferMapAsync(apiBuffer, static_cast<WGPUMapMode>(mapMode), 0, kBufferSize, _))
            .WillOnce(InvokeWithoutArgs([&] {
                api.CallBufferMapAsyncCallback(apiBuffer, WGPUMapAsyncStatus_Success,
                                               kEmptyOutputStringView);
            }));
        ExpectMappedRangeCall(kBufferSize, &bufferContent);

        // Ensure that the server had a chance to respond if relevant.
        FlushClient();
        FlushFutures();

        addExpectations();

        ExpectWireCallbacksWhen([&](auto& mockCb) {
            EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).WillOnce([&]() {
                cancelMapping();
            });

            FlushCallbacks();
        });

        // Make sure that the cancel function is called and flush more callbacks to ensure that
        // nothing else happens.
        FlushClient();
        FlushFutures();
        FlushCallbacks();
    }

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

DAWN_INSTANTIATE_WIRE_FUTURE_TEST_P(WireBufferMappingTests,
                                    {wgpu::MapMode::Read, wgpu::MapMode::Write});

// Check that things work correctly when a validation error happens when mapping the buffer.
TEST_P(WireBufferMappingTests, ErrorWhileMapping) {
    wgpu::MapMode mapMode = GetMapMode();
    MapAsync(mapMode, 0, kBufferSize);

    EXPECT_CALL(api,
                OnBufferMapAsync(apiBuffer, static_cast<WGPUMapMode>(mapMode), 0, kBufferSize, _))
        .WillOnce(InvokeWithoutArgs([&] {
            api.CallBufferMapAsyncCallback(apiBuffer, WGPUMapAsyncStatus_Error,
                                           ToOutputStringView("Validation error"));
        }));

    FlushClient();
    FlushFutures();

    ExpectWireCallbacksWhen([&](auto& mockCb) {
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Error, SizedString("Validation error")))
            .Times(1);

        FlushCallbacks();
    });

    EXPECT_EQ(nullptr, buffer.GetConstMappedRange(0, kBufferSize));
}

// Check the map callback when the map request would have worked, but Unmap() was called.
TEST_P(WireBufferMappingTests, UnmapCalledTooEarly) {
    TestEarlyMapCancelled([&]() { buffer.Unmap(); },
                          [&]() { EXPECT_CALL(api, BufferUnmap(apiBuffer)); },
                          wgpu::MapAsyncStatus::Aborted,
                          "Buffer was unmapped before mapping was resolved.", IsSpontaneous());
}

// Check that if Unmap() was called early client-side, we disregard server-side validation errors.
TEST_P(WireBufferMappingTests, UnmapCalledTooEarlyServerSideError) {
    TestEarlyMapErrorCancelled([&]() { buffer.Unmap(); },
                               [&]() { EXPECT_CALL(api, BufferUnmap(apiBuffer)); },
                               wgpu::MapAsyncStatus::Aborted,
                               "Buffer was unmapped before mapping was resolved.", IsSpontaneous());
}

// Check the map callback when the map request would have worked, but Destroy() was called.
TEST_P(WireBufferMappingTests, DestroyCalledTooEarly) {
    TestEarlyMapCancelled([&]() { buffer.Destroy(); },
                          [&]() { EXPECT_CALL(api, BufferDestroy(apiBuffer)); },
                          wgpu::MapAsyncStatus::Aborted,
                          "Buffer was destroyed before mapping was resolved.", IsSpontaneous());
}

// Check that if Destroy() was called early client-side, we disregard server-side validation errors.
TEST_P(WireBufferMappingTests, DestroyCalledTooEarlyServerSideError) {
    TestEarlyMapErrorCancelled(
        [&]() { buffer.Destroy(); }, [&]() { EXPECT_CALL(api, BufferDestroy(apiBuffer)); },
        wgpu::MapAsyncStatus::Aborted, "Buffer was destroyed before mapping was resolved.",
        IsSpontaneous());
}

// Check the map callback when the map request would have worked, but the device was released.
TEST_P(WireBufferMappingTests, DeviceReleasedTooEarly) {
    TestEarlyMapCancelled([&]() { device = nullptr; },
                          [&]() {
                              EXPECT_CALL(api, DeviceRelease(apiDevice));
                          },
                          wgpu::MapAsyncStatus::Aborted,
                          "The Device was lost before mapping was resolved.", false);
}

// Check that if device is released early client-side, we disregard server-side validation errors.
TEST_P(WireBufferMappingTests, DeviceReleasedTooEarlyServerSideError) {
    TestEarlyMapErrorCancelled(
        [&]() { device = nullptr; },
        [&]() {
            EXPECT_CALL(api, DeviceRelease(apiDevice));
        },
        wgpu::MapAsyncStatus::Aborted, "The Device was lost before mapping was resolved.", false);
}

// Check the map callback when the map request would have worked, but the device was destroyed.
TEST_P(WireBufferMappingTests, DeviceDestroyedTooEarly) {
    TestEarlyMapCancelled(
        [&]() { device.Destroy(); }, [&]() { EXPECT_CALL(api, DeviceDestroy(apiDevice)); },
        wgpu::MapAsyncStatus::Aborted, "The Device was lost before mapping was resolved.", false);
}

// Check that if device is destroyed early client-side, we disregard server-side validation errors.
TEST_P(WireBufferMappingTests, DeviceDestroyedTooEarlyServerSideError) {
    TestEarlyMapErrorCancelled(
        [&]() { device.Destroy(); }, [&]() { EXPECT_CALL(api, DeviceDestroy(apiDevice)); },
        wgpu::MapAsyncStatus::Aborted, "The Device was lost before mapping was resolved.", false);
}

// Test that the callback isn't fired twice when Unmap() is called inside the callback.
TEST_P(WireBufferMappingTests, UnmapInsideMapCallback) {
    TestCancelInCallback([&]() { buffer.Unmap(); },
                         [&]() { EXPECT_CALL(api, BufferUnmap(apiBuffer)); });
}

// Test that the callback isn't fired twice when Destroy() is called inside the callback.
TEST_P(WireBufferMappingTests, DestroyInsideMapCallback) {
    TestCancelInCallback([&]() { buffer.Destroy(); },
                         [&]() { EXPECT_CALL(api, BufferDestroy(apiBuffer)); });
}

// Test that the callback isn't fired twice when Release() is called inside the callback with the
// last ref.
TEST_P(WireBufferMappingTests, ReleaseInsideMapCallback) {
    TestCancelInCallback([&]() { buffer = nullptr; },
                         [&]() { EXPECT_CALL(api, BufferRelease(apiBuffer)); });
}

// Tests specific to mapping for reading.
class WireBufferMappingReadTests : public WireBufferMappingTests {
  protected:
    void SetUp() override {
        WireBufferMappingTests::SetUp();
        SetupBuffer(wgpu::MapMode::Read);
    }
};

DAWN_INSTANTIATE_WIRE_FUTURE_TEST_P(WireBufferMappingReadTests);

// Check mapping for reading a succesfully created buffer.
TEST_P(WireBufferMappingReadTests, MappingSuccess) {
    MapAsync(wgpu::MapMode::Read, 0, kBufferSize);

    uint32_t bufferContent = 31337;
    EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _))
        .WillOnce(InvokeWithoutArgs([&] {
            api.CallBufferMapAsyncCallback(apiBuffer, WGPUMapAsyncStatus_Success,
                                           kEmptyOutputStringView);
        }));
    EXPECT_CALL(api, BufferGetConstMappedRange(apiBuffer, 0, kBufferSize))
        .WillOnce(Return(&bufferContent));

    FlushClient();
    FlushFutures();
    ExpectWireCallbacksWhen([&](auto& mockCb) {
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);

        FlushCallbacks();
    });

    EXPECT_EQ(bufferContent,
              *static_cast<const uint32_t*>(buffer.GetConstMappedRange(0, kBufferSize)));
    EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
    buffer.Unmap();
    FlushClient();
}

// Check that an error map read while a buffer is already mapped won't changed the result of get
// mapped range.
TEST_P(WireBufferMappingReadTests, MappingErrorWhileAlreadyMapped) {
    // Successful map
    MapAsync(wgpu::MapMode::Read, 0, kBufferSize);

    uint32_t bufferContent = 31337;
    EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _))
        .WillOnce(InvokeWithoutArgs([&] {
            api.CallBufferMapAsyncCallback(apiBuffer, WGPUMapAsyncStatus_Success,
                                           kEmptyOutputStringView);
        }));
    EXPECT_CALL(api, BufferGetConstMappedRange(apiBuffer, 0, kBufferSize))
        .WillOnce(Return(&bufferContent));

    FlushClient();
    FlushFutures();
    ExpectWireCallbacksWhen([&](auto& mockCb) {
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);

        FlushCallbacks();
    });

    // Map failure while the buffer is already mapped
    MapAsync(wgpu::MapMode::Read, 0, kBufferSize);

    EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _))
        .WillOnce(InvokeWithoutArgs([&] {
            api.CallBufferMapAsyncCallback(apiBuffer, WGPUMapAsyncStatus_Error,
                                           ToOutputStringView("Already mapped"));
        }));

    FlushClient();
    FlushFutures();
    ExpectWireCallbacksWhen([&](auto& mockCb) {
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Error, SizedString("Already mapped")))
            .Times(1);

        FlushCallbacks();
    });

    EXPECT_EQ(bufferContent,
              *static_cast<const uint32_t*>(buffer.GetConstMappedRange(0, kBufferSize)));
}

// Tests specific to mapping for writing.
class WireBufferMappingWriteTests : public WireBufferMappingTests {
  protected:
    void SetUp() override {
        WireBufferMappingTests::SetUp();
        SetupBuffer(wgpu::MapMode::Write);
    }
};

DAWN_INSTANTIATE_WIRE_FUTURE_TEST_P(WireBufferMappingWriteTests);

// Check mapping for writing a succesfully created buffer.
TEST_P(WireBufferMappingWriteTests, MappingSuccess) {
    MapAsync(wgpu::MapMode::Write, 0, kBufferSize);

    uint32_t serverBufferContent = 31337;
    uint32_t updatedContent = 4242;

    EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _))
        .WillOnce(InvokeWithoutArgs([&] {
            api.CallBufferMapAsyncCallback(apiBuffer, WGPUMapAsyncStatus_Success,
                                           kEmptyOutputStringView);
        }));
    EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, kBufferSize))
        .WillOnce(Return(&serverBufferContent));

    // The map write callback always gets a buffer full of zeroes.
    FlushClient();
    FlushFutures();
    ExpectWireCallbacksWhen([&](auto& mockCb) {
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);

        FlushCallbacks();
    });

    uint32_t* lastMapWritePointer = static_cast<uint32_t*>(buffer.GetMappedRange(0, kBufferSize));
    ASSERT_EQ(0u, *lastMapWritePointer);

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

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

    FlushClient();

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

// Check that an error map write while a buffer is already mapped.
TEST_P(WireBufferMappingWriteTests, MappingErrorWhileAlreadyMapped) {
    // Successful map
    MapAsync(wgpu::MapMode::Write, 0, kBufferSize);

    uint32_t bufferContent = 31337;
    EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _))
        .WillOnce(InvokeWithoutArgs([&] {
            api.CallBufferMapAsyncCallback(apiBuffer, WGPUMapAsyncStatus_Success,
                                           kEmptyOutputStringView);
        }));
    EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, kBufferSize))
        .WillOnce(Return(&bufferContent));

    FlushClient();
    FlushFutures();
    ExpectWireCallbacksWhen([&](auto& mockCb) {
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);

        FlushCallbacks();
    });

    // Map failure while the buffer is already mapped
    MapAsync(wgpu::MapMode::Write, 0, kBufferSize);
    EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _))
        .WillOnce(InvokeWithoutArgs([&] {
            api.CallBufferMapAsyncCallback(apiBuffer, WGPUMapAsyncStatus_Error,
                                           ToOutputStringView("Already mapped"));
        }));

    FlushClient();
    FlushFutures();
    ExpectWireCallbacksWhen([&](auto& mockCb) {
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Error, SizedString("Already mapped")))
            .Times(1);

        FlushCallbacks();
    });

    EXPECT_NE(nullptr, static_cast<const uint32_t*>(buffer.GetConstMappedRange(0, kBufferSize)));
}

// Tests specific to mapped at creation.
class WireBufferMappedAtCreationTests : public WireBufferMappingTests {
  protected:
    void SetUp() override {
        WireBufferMappingTestBase::SetUp();
        apiBuffer = api.GetNewBuffer();
    }
};

DAWN_INSTANTIATE_WIRE_FUTURE_TEST_P(WireBufferMappedAtCreationTests);

// Test successful buffer creation with mappedAtCreation=true
TEST_F(WireBufferMappedAtCreationTests, Success) {
    wgpu::BufferDescriptor descriptor = {};
    descriptor.size = kBufferSize;
    descriptor.mappedAtCreation = true;

    uint32_t apiBufferData = 1234;
    EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
    EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));

    buffer = device.CreateBuffer(&descriptor);
    FlushClient();

    EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
    buffer.Unmap();
    FlushClient();
}

// Test that releasing a buffer mapped at creation does not call Unmap
TEST_F(WireBufferMappedAtCreationTests, ReleaseBeforeUnmap) {
    wgpu::BufferDescriptor descriptor = {};
    descriptor.size = kBufferSize;
    descriptor.mappedAtCreation = true;

    uint32_t apiBufferData = 1234;
    EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
    EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));

    buffer = device.CreateBuffer(&descriptor);
    FlushClient();

    EXPECT_CALL(api, BufferRelease(apiBuffer)).Times(1);
    buffer = nullptr;
    FlushClient();
}

// Test that it is valid to map a buffer after it is mapped at creation and unmapped.
TEST_P(WireBufferMappedAtCreationTests, MapSuccess) {
    wgpu::BufferDescriptor descriptor = {};
    descriptor.size = kBufferSize;
    descriptor.usage = wgpu::BufferUsage::MapWrite;
    descriptor.mappedAtCreation = true;

    uint32_t apiBufferData = 1234;
    EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
    EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));

    buffer = device.CreateBuffer(&descriptor);
    FlushClient();

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

    MapAsync(wgpu::MapMode::Write, 0, kBufferSize);

    EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _))
        .WillOnce(InvokeWithoutArgs([&] {
            api.CallBufferMapAsyncCallback(apiBuffer, WGPUMapAsyncStatus_Success,
                                           kEmptyOutputStringView);
        }));
    EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, kBufferSize))
        .WillOnce(Return(&apiBufferData));
    FlushClient();
    FlushFutures();

    ExpectWireCallbacksWhen([&](auto& mockCb) {
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);

        FlushCallbacks();
    });
}

// Test that it is invalid to map a buffer after mappedAtCreation but before Unmap
TEST_P(WireBufferMappedAtCreationTests, MapFailure) {
    wgpu::BufferDescriptor descriptor = {};
    descriptor.size = kBufferSize;
    descriptor.mappedAtCreation = true;

    uint32_t apiBufferData = 1234;
    EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
    EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));

    buffer = device.CreateBuffer(&descriptor);
    FlushClient();

    MapAsync(wgpu::MapMode::Write, 0, kBufferSize);

    // Note that the validation logic is entirely on the native side so we inject the validation
    // error here and flush the server response to mock the expected behavior.
    EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _))
        .WillOnce(InvokeWithoutArgs([&] {
            api.CallBufferMapAsyncCallback(apiBuffer, WGPUMapAsyncStatus_Error,
                                           ToOutputStringView("Already mapped"));
        }));

    FlushClient();
    FlushFutures();
    ExpectWireCallbacksWhen([&](auto& mockCb) {
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Error, SizedString("Already mapped")))
            .Times(1);

        FlushCallbacks();
    });

    EXPECT_NE(nullptr, static_cast<const uint32_t*>(buffer.GetConstMappedRange(0, kBufferSize)));

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

    FlushClient();
}

// Tests that releasing a buffer created after the client has already disconnected doesn't crash.
// This is a regression test for crbug.com/479440916.
TEST_F(WireBufferMappedAtCreationTests, DisconnectThenCreateRelease) {
    GetWireClient()->Disconnect();

    wgpu::BufferDescriptor descriptor = {};
    descriptor.size = kBufferSize;
    descriptor.mappedAtCreation = true;

    buffer = device.CreateBuffer(&descriptor);
    buffer = nullptr;
    FlushClient();
}

// Tests that destroying a buffer created after the client has already disconnected doesn't crash.
// This is a regression test for crbug.com/479440916.
TEST_F(WireBufferMappedAtCreationTests, DisconnectThenCreateDestroy) {
    GetWireClient()->Disconnect();

    wgpu::BufferDescriptor descriptor = {};
    descriptor.size = kBufferSize;
    descriptor.mappedAtCreation = true;

    buffer = device.CreateBuffer(&descriptor);
    buffer.Destroy();
    FlushClient();
}

// Tests that unmapping a buffer created after the client has already disconnected doesn't crash.
// This is a regression test for crbug.com/479440916.
TEST_F(WireBufferMappedAtCreationTests, DisconnectThenCreateUnmap) {
    GetWireClient()->Disconnect();

    wgpu::BufferDescriptor descriptor = {};
    descriptor.size = kBufferSize;
    descriptor.mappedAtCreation = true;

    buffer = device.CreateBuffer(&descriptor);
    buffer.Unmap();
    FlushClient();
}

// Check that trying to create a buffer of size MAX_SIZE_T won't get OOM error at the client side.
TEST_F(WireBufferMappingTests, MaxSizeMappableBufferOOMDirectly) {
    size_t kOOMSize = std::numeric_limits<size_t>::max();

    // Check for mappedAtCreation.
    {
        wgpu::BufferDescriptor descriptor = {};
        descriptor.usage = wgpu::BufferUsage::CopySrc;
        descriptor.size = kOOMSize;
        descriptor.mappedAtCreation = true;

        device.CreateBuffer(&descriptor);
        FlushClient();
    }

    // Check for MapRead usage.
    {
        wgpu::BufferDescriptor descriptor = {};
        descriptor.usage = wgpu::BufferUsage::MapRead;
        descriptor.size = kOOMSize;

        device.CreateBuffer(&descriptor);
        EXPECT_CALL(api, DeviceCreateErrorBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
        EXPECT_CALL(api, BufferRelease(apiBuffer)).Times(1);
        FlushClient();
    }

    // Check for MapWrite usage.
    {
        wgpu::BufferDescriptor descriptor = {};
        descriptor.usage = wgpu::BufferUsage::MapWrite;
        descriptor.size = kOOMSize;

        device.CreateBuffer(&descriptor);
        EXPECT_CALL(api, DeviceCreateErrorBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
        EXPECT_CALL(api, BufferRelease(apiBuffer)).Times(1);
        FlushClient();
    }
}

// Test that registering a callback then wire disconnect calls the callback with
// CallbackCancelled.
TEST_P(WireBufferMappingTests, MapThenDisconnect) {
    wgpu::MapMode mapMode = GetMapMode();
    MapAsync(mapMode, 0, kBufferSize);

    uint32_t bufferContent = 0;
    EXPECT_CALL(api,
                OnBufferMapAsync(apiBuffer, static_cast<WGPUMapMode>(mapMode), 0, kBufferSize, _))
        .WillOnce(InvokeWithoutArgs([&] {
            api.CallBufferMapAsyncCallback(apiBuffer, WGPUMapAsyncStatus_Success,
                                           kEmptyOutputStringView);
        }));
    ExpectMappedRangeCall(kBufferSize, &bufferContent);

    FlushClient();
    ExpectWireCallbacksWhen([&](auto& mockCb) {
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::CallbackCancelled, _)).Times(1);

        GetWireClient()->Disconnect();
    });
}

// Test that registering a callback after wire disconnect calls the callback with
// CallbackCancelled.
TEST_P(WireBufferMappingTests, MapAfterDisconnect) {
    wgpu::MapMode mapMode = GetMapMode();
    GetWireClient()->Disconnect();

    ExpectWireCallbacksWhen([&](auto& mockCb) {
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::CallbackCancelled, _)).Times(1);

        MapAsync(mapMode, 0, kBufferSize);
    });
}

// Test that mapping again while pending map cause an error on the callback.
TEST_P(WireBufferMappingTests, PendingMapImmediateError) {
    wgpu::MapMode mapMode = GetMapMode();
    MapAsync(mapMode, 0, kBufferSize);

    // Calls for the first successful map.
    uint32_t bufferContent = 0;
    EXPECT_CALL(api,
                OnBufferMapAsync(apiBuffer, static_cast<WGPUMapMode>(mapMode), 0, kBufferSize, _))
        .WillOnce(InvokeWithoutArgs([&] {
            api.CallBufferMapAsyncCallback(apiBuffer, WGPUMapAsyncStatus_Success,
                                           kEmptyOutputStringView);
        }));
    ExpectMappedRangeCall(kBufferSize, &bufferContent);

    if (IsSpontaneous()) {
        // In spontaneous mode, the second map on the pending immediately calls the callback.
        ExpectWireCallbacksWhen([&](auto& mockCb) {
            EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Error,
                                     SizedString("Buffer already has an outstanding map pending.")))
                .Times(1);

            MapAsync(mapMode, 0, kBufferSize);
        });

        FlushClient();
        FlushFutures();
        ExpectWireCallbacksWhen([&](auto& mockCb) {
            EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);

            FlushCallbacks();
        });
    } else {
        // Otherwise, the callback will fire alongside the success one when we flush the callbacks.
        MapAsync(mapMode, 0, kBufferSize);

        FlushClient();
        FlushFutures();
        ExpectWireCallbacksWhen([&](auto& mockCb) {
            EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Error,
                                     SizedString("Buffer already has an outstanding map pending.")))
                .Times(1);
            EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);

            FlushCallbacks();
        });
    }
}

// Test that GetMapState() returns map state as expected
TEST_P(WireBufferMappingTests, GetMapState) {
    wgpu::MapMode mapMode = GetMapMode();
    uint32_t bufferContent = 31337;

    // Server-side success case
    {
        // Map state should initially be unmapped.
        ASSERT_EQ(buffer.GetMapState(), wgpu::BufferMapState::Unmapped);

        EXPECT_CALL(
            api, OnBufferMapAsync(apiBuffer, static_cast<WGPUMapMode>(mapMode), 0, kBufferSize, _))
            .WillOnce(InvokeWithoutArgs([&] {
                api.CallBufferMapAsyncCallback(apiBuffer, WGPUMapAsyncStatus_Success,
                                               kEmptyOutputStringView);
            }));
        ExpectMappedRangeCall(kBufferSize, &bufferContent);
        MapAsync(mapMode, 0, kBufferSize);

        // Map state should become pending immediately after map async call.
        ASSERT_EQ(buffer.GetMapState(), wgpu::BufferMapState::Pending);
        FlushClient();

        // Map state should be pending until receiving a response from server.
        ASSERT_EQ(buffer.GetMapState(), wgpu::BufferMapState::Pending);
        FlushFutures();

        // Map state should still be pending until the callback has been called.
        ASSERT_EQ(buffer.GetMapState(), wgpu::BufferMapState::Pending);
        ExpectWireCallbacksWhen([&](auto& mockCb) {
            EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).WillOnce([&]() {
                ASSERT_EQ(buffer.GetMapState(), wgpu::BufferMapState::Mapped);
            });

            FlushCallbacks();
        });

        // Mapping succeeded.
        ASSERT_EQ(buffer.GetMapState(), wgpu::BufferMapState::Mapped);
    }

    EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
    buffer.Unmap();
    FlushClient();
    ASSERT_EQ(buffer.GetMapState(), wgpu::BufferMapState::Unmapped);

    // Server-side error case
    {
        EXPECT_CALL(
            api, OnBufferMapAsync(apiBuffer, static_cast<WGPUMapMode>(mapMode), 0, kBufferSize, _))
            .WillOnce(InvokeWithoutArgs([&] {
                api.CallBufferMapAsyncCallback(apiBuffer, WGPUMapAsyncStatus_Error,
                                               ToOutputStringView("Error"));
            }));

        // Map state should initially be unmapped.
        ASSERT_EQ(buffer.GetMapState(), wgpu::BufferMapState::Unmapped);
        MapAsync(mapMode, 0, kBufferSize);

        // Map state should become pending immediately after map async call.
        ASSERT_EQ(buffer.GetMapState(), wgpu::BufferMapState::Pending);
        FlushClient();

        // Map state should be pending until receiving a response from server.
        ASSERT_EQ(buffer.GetMapState(), wgpu::BufferMapState::Pending);
        FlushFutures();

        // Map state should still be pending until the callback has been called.
        ASSERT_EQ(buffer.GetMapState(), wgpu::BufferMapState::Pending);
        ExpectWireCallbacksWhen([&](auto& mockCb) {
            EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Error, SizedString("Error")))
                .WillOnce(
                    [&]() { ASSERT_EQ(buffer.GetMapState(), wgpu::BufferMapState::Unmapped); });

            FlushCallbacks();
        });

        // Mapping failed
        ASSERT_EQ(buffer.GetMapState(), wgpu::BufferMapState::Unmapped);
    }
}

// Test that requests inside user callbacks before disconnect are called.
TEST_P(WireBufferMappingTests, MapInsideCallbackBeforeDisconnect) {
    wgpu::MapMode mapMode = GetMapMode();
    MapAsync(mapMode, 0, kBufferSize);

    uint32_t bufferContent = 0;
    EXPECT_CALL(api,
                OnBufferMapAsync(apiBuffer, static_cast<WGPUMapMode>(mapMode), 0, kBufferSize, _))
        .WillOnce(InvokeWithoutArgs([&] {
            api.CallBufferMapAsyncCallback(apiBuffer, WGPUMapAsyncStatus_Success,
                                           kEmptyOutputStringView);
        }));
    ExpectMappedRangeCall(kBufferSize, &bufferContent);

    FlushClient();

    static constexpr size_t kNumRequests = 10;
    ExpectWireCallbacksWhen([&](auto& mockCb) {
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::CallbackCancelled, _))
            .Times(kNumRequests + 1)
            .WillOnce([&]() {
                for (size_t i = 0; i < kNumRequests; i++) {
                    MapAsync(mapMode, 0, kBufferSize);
                }
            })
            .WillRepeatedly(Return());

        GetWireClient()->Disconnect();
    });
}

// Test that requests inside user callbacks before buffer destroy are called.
TEST_P(WireBufferMappingTests, MapInsideCallbackBeforeDestroy) {
    wgpu::MapMode mapMode = GetMapMode();
    MapAsync(mapMode, 0, kBufferSize);

    uint32_t bufferContent = 0;
    EXPECT_CALL(api,
                OnBufferMapAsync(apiBuffer, static_cast<WGPUMapMode>(mapMode), 0, kBufferSize, _))
        .WillOnce(InvokeWithoutArgs([&] {
            api.CallBufferMapAsyncCallback(apiBuffer, WGPUMapAsyncStatus_Success,
                                           kEmptyOutputStringView);
        }));
    ExpectMappedRangeCall(kBufferSize, &bufferContent);

    FlushClient();
    FlushFutures();

    static constexpr size_t kNumRequests = 10;
    if (IsSpontaneous()) {
        // In spontaneous mode, when the success callback fires, the first MapAsync request
        // generated by the callback is queued, then all subsequent requests' callbacks are
        // immediately called with Error because there's already a pending map. Finally, when we
        // call Destroy, the queued request's callback is then called with Aborted.
        ExpectWireCallbacksWhen([&](auto& mockCb) {
            EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).WillOnce([&]() {
                for (size_t i = 0; i < kNumRequests; i++) {
                    MapAsync(mapMode, 0, kBufferSize);
                }
            });
            EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Error,
                                     SizedString("Buffer already has an outstanding map pending.")))
                .Times(kNumRequests - 1);

            FlushCallbacks();
        });
        ExpectWireCallbacksWhen([&](auto& mockCb) {
            EXPECT_CALL(mockCb,
                        Call(wgpu::MapAsyncStatus::Aborted,
                             SizedString("Buffer was destroyed before mapping was resolved.")))
                .Times(1);

            buffer.Destroy();
        });
        FlushCallbacks();
    } else {
        // In non-spontaneous modes, the first callback doesn't trigger any other immediate
        // callbacks, but internally, all but the first MapAsync call's callback is set to be ready
        // with Error because there's already a pending map. When we call Destroy, the first
        // pending request is then marked ready with Aborted. The callbacks all run when we flush
        // them.
        ExpectWireCallbacksWhen([&](auto& mockCb) {
            EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).WillOnce([&]() {
                for (size_t i = 0; i < kNumRequests; i++) {
                    MapAsync(mapMode, 0, kBufferSize);
                }
            });

            FlushCallbacks();
        });
        buffer.Destroy();
        ExpectWireCallbacksWhen([&](auto& mockCb) {
            EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Error,
                                     SizedString("Buffer already has an outstanding map pending.")))
                .Times(kNumRequests - 1);
            EXPECT_CALL(mockCb,
                        Call(wgpu::MapAsyncStatus::Aborted,
                             SizedString("Buffer was destroyed before mapping was resolved.")))
                .Times(1);

            FlushCallbacks();
        });
    }
}

}  // anonymous namespace
}  // namespace dawn::wire
