// 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/wire/WireClient.h"
#include "src/dawn/common/StringViewUtils.h"
#include "src/dawn/tests/StringViewMatchers.h"
#include "src/dawn/tests/unittests/wire/WireFutureTest.h"
#include "src/dawn/tests/unittests/wire/WireTest.h"
#include "src/utils/assert.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() {
        wgpu::MapMode mapMode = GetMapMode();
        if (mapMode == wgpu::MapMode::Read) {
            EXPECT_CALL(api, BufferGetConstMappedRange(apiBuffer, 0, kBufferSize))
                .WillOnce(Return(&mappedBufferContents));
        } else if (mapMode == wgpu::MapMode::Write) {
            EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, kBufferSize))
                .WillOnce(Return(&mappedBufferContents));
        }
    }

    // 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);

        EXPECT_CALL(
            api, OnBufferMapAsync(apiBuffer, static_cast<WGPUMapMode>(mapMode), 0, kBufferSize, _))
            .WillOnce(InvokeWithoutArgs([&] {
                api.CallBufferMapAsyncCallback(apiBuffer, WGPUMapAsyncStatus_Success,
                                               kEmptyOutputStringView);
            }));
        if (mapMode & wgpu::MapMode::Read) {
            ExpectMappedRangeCall();
        }
        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);

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

        // 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();
    }

    // The buffer contents is in a member to ensure it outlives all test bodies (it is passed by
    // pointer as the mocked result of GetMappedRange and can be derefenced anywhere in the test).
    uint32_t mappedBufferContents = 31337;
    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; }, [&]() {}, 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; }, [&]() {}, 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(); },
                         [&]() {
                             if (GetMapMode() & wgpu::MapMode::Write) {
                                 ExpectMappedRangeCall();
                             }
                             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);

    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(&mappedBufferContents));

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

        FlushCallbacks();
    });

    EXPECT_EQ(mappedBufferContents,
              *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);

    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(&mappedBufferContents));

    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(mappedBufferContents,
              *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 updatedContent = 4242;

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

    // 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, BufferGetMappedRange(apiBuffer, 0, kBufferSize))
        .WillOnce(Return(&mappedBufferContents));
    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(mappedBufferContents, 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);

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

    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));
    buffer = device.CreateBuffer(&descriptor);
    FlushClient();

    EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
    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;

    EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
    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));
    buffer = device.CreateBuffer(&descriptor);
    FlushClient();

    EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
    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);
        }));
    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));
    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, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
    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);

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

    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.
    EXPECT_CALL(api,
                OnBufferMapAsync(apiBuffer, static_cast<WGPUMapMode>(mapMode), 0, kBufferSize, _))
        .WillOnce(InvokeWithoutArgs([&] {
            api.CallBufferMapAsyncCallback(apiBuffer, WGPUMapAsyncStatus_Success,
                                           kEmptyOutputStringView);
        }));
    if (mapMode & wgpu::MapMode::Read) {
        ExpectMappedRangeCall();
    }

    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();

    // 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);
            }));
        MapAsync(mapMode, 0, kBufferSize);
        if (mapMode & wgpu::MapMode::Read) {
            ExpectMappedRangeCall();
        }

        // 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);
    }

    if (mapMode & wgpu::MapMode::Write) {
        ExpectMappedRangeCall();
    }
    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);

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

    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);

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

    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
