// Copyright 2017 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.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include <algorithm>
#include <array>
#include <cstring>
#include <limits>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include "partition_alloc/pointers/raw_ptr.h"
#include "src/dawn/tests/DawnTest.h"
#include "src/dawn/tests/MockCallback.h"
#include "src/dawn/utils/ComboRenderPipelineDescriptor.h"
#include "src/dawn/utils/TestUtils.h"
#include "src/dawn/utils/WGPUHelpers.h"

namespace dawn {
namespace {

using testing::_;
using testing::MockCppCallback;
using testing::StrictMock;

using MockMapAsyncCallback = MockCppCallback<wgpu::BufferMapCallback<void>*>;
using FutureCallbackMode = wgpu::CallbackMode;

DAWN_TEST_PARAM_STRUCT(BufferMappingTestParams, FutureCallbackMode);

class BufferMappingTests : public DawnTestWithParams<BufferMappingTestParams> {
  protected:
    void SetUp() override {
        DawnTestWithParams<BufferMappingTestParams>::SetUp();
        // Wire only supports polling / spontaneous futures.
        DAWN_TEST_UNSUPPORTED_IF(UsesWire() &&
                                 GetParam().mFutureCallbackMode == wgpu::CallbackMode::WaitAnyOnly);
    }

    void MapAsyncAndWait(const wgpu::Buffer& buffer,
                         wgpu::MapMode mode,
                         size_t offset,
                         size_t size,
                         wgpu::BufferMapCallback<> cb = nullptr) {
        wgpu::Future future;

        if (cb) {
            future = buffer.MapAsync(mode, offset, size, GetParam().mFutureCallbackMode, cb);
        } else {
            EXPECT_CALL(mMockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);
            future = buffer.MapAsync(mode, offset, size, GetParam().mFutureCallbackMode,
                                     mMockCb.Callback());
        }

        switch (GetParam().mFutureCallbackMode) {
            case wgpu::CallbackMode::WaitAnyOnly: {
                ASSERT_EQ(GetInstance().WaitAny(future, UINT64_MAX), wgpu::WaitStatus::Success);
                break;
            }
            case wgpu::CallbackMode::AllowProcessEvents:
            case wgpu::CallbackMode::AllowSpontaneous:
                while (GetInstance().WaitAny(future, 0) == wgpu::WaitStatus::TimedOut) {
                    // Flush wire and call instance process events.
                    WaitABit();
                }
                break;
        }
    }

    wgpu::Buffer CreateMapReadBuffer(uint64_t size) {
        wgpu::BufferDescriptor descriptor;
        descriptor.size = size;
        descriptor.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
        return device.CreateBuffer(&descriptor);
    }

    wgpu::Buffer CreateMapWriteBuffer(uint64_t size) {
        wgpu::BufferDescriptor descriptor;
        descriptor.size = size;
        descriptor.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc;
        return device.CreateBuffer(&descriptor);
    }

    wgpu::Buffer CreateUniformBuffer(uint64_t size) {
        wgpu::BufferDescriptor descriptor;
        descriptor.size = size;
        descriptor.usage = wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopyDst;
        return device.CreateBuffer(&descriptor);
    }

    StrictMock<MockMapAsyncCallback> mMockCb;
};

void CheckMapping(const void* actual, const void* expected, size_t size) {
    EXPECT_NE(actual, nullptr);
    if (actual != nullptr) {
        EXPECT_EQ(0, memcmp(actual, expected, size));
    }
}

// Test that the simplest map read works
TEST_P(BufferMappingTests, MapRead_Basic) {
    wgpu::Buffer buffer = CreateMapReadBuffer(4);

    const uint32_t myData = 0x01020304;
    constexpr size_t kSize = sizeof(myData);
    queue.WriteBuffer(buffer, 0, &myData, kSize);

    MapAsyncAndWait(buffer, wgpu::MapMode::Read, 0, 4);
    CheckMapping(buffer.GetConstMappedRange(), &myData, kSize);
    CheckMapping(buffer.GetConstMappedRange(0, kSize), &myData, kSize);
    buffer.Unmap();
}

// Test map-reading a zero-sized buffer.
TEST_P(BufferMappingTests, MapRead_ZeroSized) {
    wgpu::Buffer buffer = CreateMapReadBuffer(0);

    MapAsyncAndWait(buffer, wgpu::MapMode::Read, 0, wgpu::kWholeMapSize);
    ASSERT_NE(buffer.GetConstMappedRange(), nullptr);
    buffer.Unmap();
}

// Test map-reading with a non-zero offset
TEST_P(BufferMappingTests, MapRead_NonZeroOffset) {
    uint32_t myData[3] = {0x01020304, 0x05060708, 0x090A0B0C};

    wgpu::Buffer buffer = CreateMapReadBuffer(sizeof(myData));
    queue.WriteBuffer(buffer, 0, &myData, sizeof(myData));

    MapAsyncAndWait(buffer, wgpu::MapMode::Read, 8, 4);
    ASSERT_EQ(myData[2], *static_cast<const uint32_t*>(buffer.GetConstMappedRange(8)));
    {
        uint32_t readback = 0;
        ASSERT_EQ(wgpu::Status::Success, buffer.ReadMappedRange(8, &readback, sizeof(readback)));
        EXPECT_EQ(readback, myData[2]);
    }
    buffer.Unmap();
}

// Map read and unmap twice. Test that both of these two iterations work.
TEST_P(BufferMappingTests, MapRead_Twice) {
    wgpu::Buffer buffer = CreateMapReadBuffer(4);

    uint32_t myData = 0x01020304;
    queue.WriteBuffer(buffer, 0, &myData, sizeof(myData));

    MapAsyncAndWait(buffer, wgpu::MapMode::Read, 0, 4);
    ASSERT_EQ(myData, *static_cast<const uint32_t*>(buffer.GetConstMappedRange()));
    buffer.Unmap();

    myData = 0x05060708;
    queue.WriteBuffer(buffer, 0, &myData, sizeof(myData));

    MapAsyncAndWait(buffer, wgpu::MapMode::Read, 0, 4);
    ASSERT_EQ(myData, *static_cast<const uint32_t*>(buffer.GetConstMappedRange()));
    buffer.Unmap();
}

// Map read and test multiple get mapped range data
TEST_P(BufferMappingTests, MapRead_MultipleMappedRange) {
    wgpu::Buffer buffer = CreateMapReadBuffer(12);

    uint32_t myData[] = {0x00010203, 0x04050607, 0x08090a0b};
    queue.WriteBuffer(buffer, 0, &myData, 12);

    MapAsyncAndWait(buffer, wgpu::MapMode::Read, 0, 12);
    ASSERT_EQ(myData[0], *static_cast<const uint32_t*>(buffer.GetConstMappedRange(0)));
    ASSERT_EQ(myData[1], *(static_cast<const uint32_t*>(buffer.GetConstMappedRange(0)) + 1));
    ASSERT_EQ(myData[2], *(static_cast<const uint32_t*>(buffer.GetConstMappedRange(0)) + 2));
    ASSERT_EQ(myData[2], *static_cast<const uint32_t*>(buffer.GetConstMappedRange(8)));
    buffer.Unmap();
}

// Test map-reading a large buffer.
TEST_P(BufferMappingTests, MapRead_Large) {
    constexpr uint32_t kDataSize = 1000 * 1000;
    constexpr size_t kByteSize = kDataSize * sizeof(uint32_t);
    wgpu::Buffer buffer = CreateMapReadBuffer(kByteSize);

    std::vector<uint32_t> myData;
    for (uint32_t i = 0; i < kDataSize; ++i) {
        myData.push_back(i);
    }
    queue.WriteBuffer(buffer, 0, myData.data(), kByteSize);

    MapAsyncAndWait(buffer, wgpu::MapMode::Read, 0, kByteSize);
    EXPECT_EQ(nullptr, buffer.GetConstMappedRange(0, kByteSize + 4));
    EXPECT_EQ(0, memcmp(buffer.GetConstMappedRange(), myData.data(), kByteSize));
    EXPECT_EQ(0, memcmp(buffer.GetConstMappedRange(8), myData.data() + 2, kByteSize - 8));
    EXPECT_EQ(
        0, memcmp(buffer.GetConstMappedRange(8, kByteSize - 8), myData.data() + 2, kByteSize - 8));
    buffer.Unmap();

    MapAsyncAndWait(buffer, wgpu::MapMode::Read, 16, kByteSize - 16);
    // Size is too big.
    EXPECT_EQ(nullptr, buffer.GetConstMappedRange(16, kByteSize - 12));
    // Offset defaults to 0 which is less than 16
    EXPECT_EQ(nullptr, buffer.GetConstMappedRange());
    // Offset less than 8 is less than 16
    EXPECT_EQ(nullptr, buffer.GetConstMappedRange(8));

    // Test a couple values.
    EXPECT_EQ(0, memcmp(buffer.GetConstMappedRange(16), myData.data() + 4, kByteSize - 16));
    EXPECT_EQ(0, memcmp(buffer.GetConstMappedRange(24), myData.data() + 6, kByteSize - 24));

    buffer.Unmap();
}

// Test that GetConstMappedRange works inside map-read callback
TEST_P(BufferMappingTests, MapRead_InCallback) {
    constexpr size_t kBufferSize = 12;
    wgpu::Buffer buffer = CreateMapReadBuffer(kBufferSize);

    uint32_t myData[3] = {0x01020304, 0x05060708, 0x090A0B0C};
    static constexpr size_t kSize = sizeof(myData);
    queue.WriteBuffer(buffer, 0, &myData, kSize);

    MapAsyncAndWait(buffer, wgpu::MapMode::Read, 0, kBufferSize,
                    [&](wgpu::MapAsyncStatus status, wgpu::StringView) {
                        ASSERT_EQ(status, wgpu::MapAsyncStatus::Success);

                        CheckMapping(buffer.GetConstMappedRange(), &myData, kSize);
                        CheckMapping(buffer.GetConstMappedRange(0, kSize), &myData, kSize);
                        CheckMapping(buffer.GetConstMappedRange(8, 4), &myData[2],
                                     sizeof(uint32_t));

                        buffer.Unmap();
                    });
}

// Test that the simplest map write works.
TEST_P(BufferMappingTests, MapWrite_Basic) {
    wgpu::Buffer buffer = CreateMapWriteBuffer(4);

    const uint32_t myData1 = 2934875;
    {
        // GetMappedRange and GetConstMappedRange.
        MapAsyncAndWait(buffer, wgpu::MapMode::Write, 0, 4);
        ASSERT_NE(nullptr, buffer.GetMappedRange());
        ASSERT_NE(nullptr, buffer.GetConstMappedRange());
        memcpy(buffer.GetMappedRange(), &myData1, sizeof(myData1));
        buffer.Unmap();
        EXPECT_BUFFER_U32_EQ(myData1, buffer, 0);
    }
    {
        // ReadMappedRange and WriteMappedRange.
        const uint32_t myData2 = 0x0102'0304;
        MapAsyncAndWait(buffer, wgpu::MapMode::Write, 0, 4);
        uint32_t readback = 0;
        ASSERT_EQ(wgpu::Status::Success,
                  static_cast<wgpu::Status>(buffer.ReadMappedRange(0, &readback, sizeof(myData2))));
        EXPECT_EQ(readback, myData1);
        ASSERT_EQ(wgpu::Status::Success,
                  static_cast<wgpu::Status>(buffer.WriteMappedRange(0, &myData2, sizeof(myData2))));
        buffer.Unmap();
        EXPECT_BUFFER_U32_EQ(myData2, buffer, 0);
    }
}

// Test that the simplest map write works with a range.
TEST_P(BufferMappingTests, MapWrite_BasicRange) {
    wgpu::Buffer buffer = CreateMapWriteBuffer(4);

    uint32_t myData = 2934875;
    MapAsyncAndWait(buffer, wgpu::MapMode::Write, 0, 4);
    ASSERT_NE(nullptr, buffer.GetMappedRange(0, 4));
    ASSERT_NE(nullptr, buffer.GetConstMappedRange(0, 4));
    memcpy(buffer.GetMappedRange(), &myData, sizeof(myData));
    buffer.Unmap();

    EXPECT_BUFFER_U32_EQ(myData, buffer, 0);
}

// Test map-writing a zero-sized buffer.
TEST_P(BufferMappingTests, MapWrite_ZeroSized) {
    wgpu::Buffer buffer = CreateMapWriteBuffer(0);

    MapAsyncAndWait(buffer, wgpu::MapMode::Write, 0, wgpu::kWholeMapSize);
    ASSERT_NE(buffer.GetConstMappedRange(), nullptr);
    ASSERT_NE(buffer.GetMappedRange(), nullptr);
    buffer.Unmap();
}

// Test map-writing with a non-zero offset.
TEST_P(BufferMappingTests, MapWrite_NonZeroOffset) {
    // TODO(crbug.com/473894293): [Capture] buffer mapping: investigate.
    DAWN_SUPPRESS_TEST_IF(IsCaptureReplayCheckingEnabled());

    wgpu::Buffer buffer = CreateMapWriteBuffer(20);

    uint32_t myData = 2934875;
    MapAsyncAndWait(buffer, wgpu::MapMode::Write, 8, 4);
    memcpy(buffer.GetMappedRange(8, 4), &myData, sizeof(myData));
    buffer.Unmap();
    EXPECT_BUFFER_U32_EQ(myData, buffer, 8);

    {
        // WriteMappedRange with offset.
        uint32_t myData2 = 12345;
        MapAsyncAndWait(buffer, wgpu::MapMode::Write, 16, 4);
        ASSERT_EQ(wgpu::Status::Success, static_cast<wgpu::Status>(buffer.WriteMappedRange(
                                             16, &myData2, sizeof(myData2))));
        buffer.Unmap();
        EXPECT_BUFFER_U32_EQ(myData, buffer, 8);
        EXPECT_BUFFER_U32_EQ(myData2, buffer, 16);
    }
}

// Map, write and unmap twice. Test that both of these two iterations work.
TEST_P(BufferMappingTests, MapWrite_Twice) {
    wgpu::Buffer buffer = CreateMapWriteBuffer(4);

    uint32_t myData = 2934875;
    MapAsyncAndWait(buffer, wgpu::MapMode::Write, 0, 4);
    memcpy(buffer.GetMappedRange(), &myData, sizeof(myData));
    buffer.Unmap();

    EXPECT_BUFFER_U32_EQ(myData, buffer, 0);

    myData = 9999999;
    MapAsyncAndWait(buffer, wgpu::MapMode::Write, 0, 4);
    memcpy(buffer.GetMappedRange(), &myData, sizeof(myData));
    buffer.Unmap();

    EXPECT_BUFFER_U32_EQ(myData, buffer, 0);
}

// Map write and unmap twice with different ranges and make sure the first write is preserved
TEST_P(BufferMappingTests, MapWrite_TwicePreserve) {
    wgpu::Buffer buffer = CreateMapWriteBuffer(12);

    uint32_t data1 = 0x08090a0b;
    size_t offset1 = 8;
    MapAsyncAndWait(buffer, wgpu::MapMode::Write, offset1, wgpu::kWholeMapSize);
    memcpy(buffer.GetMappedRange(offset1), &data1, sizeof(data1));
    buffer.Unmap();

    uint32_t data2 = 0x00010203;
    size_t offset2 = 0;
    MapAsyncAndWait(buffer, wgpu::MapMode::Write, offset2, wgpu::kWholeMapSize);
    memcpy(buffer.GetMappedRange(offset2), &data2, sizeof(data2));
    buffer.Unmap();

    EXPECT_BUFFER_U32_EQ(data1, buffer, offset1);
    EXPECT_BUFFER_U32_EQ(data2, buffer, offset2);
}

// Map write and unmap twice with overlapping ranges and make sure data is updated correctly
TEST_P(BufferMappingTests, MapWrite_TwiceRangeOverlap) {
    // TODO(crbug.com/473894293): [Capture] buffer mapping: investigate.
    DAWN_SUPPRESS_TEST_IF(IsCaptureReplayCheckingEnabled());

    wgpu::Buffer buffer = CreateMapWriteBuffer(16);

    uint32_t data1[] = {0x01234567, 0x89abcdef};
    size_t offset1 = 8;
    MapAsyncAndWait(buffer, wgpu::MapMode::Write, offset1, 8);
    memcpy(buffer.GetMappedRange(offset1, 8), data1, 8);
    buffer.Unmap();

    EXPECT_BUFFER_U32_EQ(0x00000000, buffer, 0);
    EXPECT_BUFFER_U32_EQ(0x00000000, buffer, 4);
    EXPECT_BUFFER_U32_EQ(0x01234567, buffer, 8);
    EXPECT_BUFFER_U32_EQ(0x89abcdef, buffer, 12);

    uint32_t data2[] = {0x01234567, 0x89abcdef, 0x55555555};
    size_t offset2 = 0;
    MapAsyncAndWait(buffer, wgpu::MapMode::Write, offset2, 12);
    memcpy(buffer.GetMappedRange(offset2, 12), data2, 12);
    buffer.Unmap();

    EXPECT_BUFFER_U32_EQ(0x01234567, buffer, 0);
    EXPECT_BUFFER_U32_EQ(0x89abcdef, buffer, 4);
    EXPECT_BUFFER_U32_EQ(0x55555555, buffer, 8);
    EXPECT_BUFFER_U32_EQ(0x89abcdef, buffer, 12);
}

// Map write and test multiple mapped range data get updated correctly
TEST_P(BufferMappingTests, MapWrite_MultipleMappedRange) {
    wgpu::Buffer buffer = CreateMapWriteBuffer(12);

    uint32_t data1 = 0x08090a0b;
    size_t offset1 = 8;
    uint32_t data2 = 0x00010203;
    size_t offset2 = 0;
    MapAsyncAndWait(buffer, wgpu::MapMode::Write, 0, 12);
    memcpy(buffer.GetMappedRange(offset1), &data1, sizeof(data1));
    memcpy(buffer.GetMappedRange(offset2), &data2, sizeof(data2));
    buffer.Unmap();

    EXPECT_BUFFER_U32_EQ(data1, buffer, offset1);
    EXPECT_BUFFER_U32_EQ(data2, buffer, offset2);
}

// Test mapping a large buffer.
TEST_P(BufferMappingTests, MapWrite_Large) {
    // TODO(crbug.com/473894293): [Capture] buffer mapping: investigate.
    DAWN_SUPPRESS_TEST_IF(IsCaptureReplayCheckingEnabled());

    constexpr uint32_t kDataSize = 1000 * 1000;
    constexpr size_t kByteSize = kDataSize * sizeof(uint32_t);
    wgpu::Buffer buffer = CreateMapWriteBuffer(kDataSize * sizeof(uint32_t));

    std::vector<uint32_t> myData;
    for (uint32_t i = 0; i < kDataSize; ++i) {
        myData.push_back(i);
    }

    MapAsyncAndWait(buffer, wgpu::MapMode::Write, 16, kByteSize - 20);
    EXPECT_EQ(nullptr, buffer.GetMappedRange());
    EXPECT_EQ(nullptr, buffer.GetMappedRange(0));
    EXPECT_EQ(nullptr, buffer.GetMappedRange(8));
    EXPECT_EQ(nullptr, buffer.GetMappedRange(16, kByteSize - 8));
    memcpy(buffer.GetMappedRange(16, kByteSize - 20), myData.data(), kByteSize - 20);
    buffer.Unmap();
    EXPECT_BUFFER_U32_RANGE_EQ(myData.data(), buffer, 16, kDataSize - 5);
}

// Stress test mapping many buffers.
TEST_P(BufferMappingTests, MapWrite_ManySimultaneous) {
    // TODO(crbug.com/454861473): Flakily hangs indefinitely on Mac/AMD 5300M.
    DAWN_SUPPRESS_TEST_IF(IsMacOS() && IsAMD() && IsMetal());

    constexpr uint32_t kDataSize = 1000;
    std::vector<uint32_t> myData;
    for (uint32_t i = 0; i < kDataSize; ++i) {
        myData.push_back(i);
    }

    constexpr uint32_t kBuffers = 100;
    std::array<wgpu::Buffer, kBuffers> buffers;
    uint32_t mapCompletedCount = 0;

    // Create buffers.
    wgpu::BufferDescriptor descriptor;
    descriptor.size = static_cast<uint32_t>(kDataSize * sizeof(uint32_t));
    descriptor.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc;
    for (uint32_t i = 0; i < kBuffers; ++i) {
        buffers[i] = device.CreateBuffer(&descriptor);
    }

    std::array<wgpu::Future, kBuffers> futures;
    for (uint32_t i = 0; i < kBuffers; ++i) {
        futures[i] = buffers[i].MapAsync(
            wgpu::MapMode::Write, 0, descriptor.size, GetParam().mFutureCallbackMode,
            [&mapCompletedCount](wgpu::MapAsyncStatus status, wgpu::StringView) {
                ASSERT_EQ(wgpu::MapAsyncStatus::Success, status);
                mapCompletedCount++;
            });
    }

    switch (GetParam().mFutureCallbackMode) {
        case wgpu::CallbackMode::WaitAnyOnly: {
            std::array<wgpu::FutureWaitInfo, kBuffers> waitInfos;
            for (uint32_t i = 0; i < kBuffers; ++i) {
                waitInfos[i] = {futures[i]};
            }
            size_t count = waitInfos.size();
            wgpu::InstanceLimits instanceLimits;
            wgpu::GetInstanceLimits(&instanceLimits);
            do {
                size_t waitCount = std::min(count, instanceLimits.timedWaitAnyMaxCount);
                auto waitInfoStart = waitInfos.begin() + (count - waitCount);
                GetInstance().WaitAny(waitCount, &*waitInfoStart, UINT64_MAX);
                auto it = std::partition(waitInfoStart, waitInfoStart + waitCount,
                                         [](const auto& info) { return !info.completed; });
                count = std::distance(waitInfos.begin(), it);
            } while (count > 0);
            break;
        }
        case wgpu::CallbackMode::AllowProcessEvents:
        case wgpu::CallbackMode::AllowSpontaneous:
            // Wait for all mappings to complete
            while (mapCompletedCount != kBuffers) {
                WaitABit();
            }
            break;
    }

    // All buffers are mapped, write into them and unmap them all.
    for (uint32_t i = 0; i < kBuffers; ++i) {
        memcpy(buffers[i].GetMappedRange(0, descriptor.size), myData.data(), descriptor.size);
        buffers[i].Unmap();
    }

    // Check the content of the buffers.
    for (uint32_t i = 0; i < kBuffers; ++i) {
        EXPECT_BUFFER_U32_RANGE_EQ(myData.data(), buffers[i], 0, kDataSize);
    }
}

// Test that the map offset isn't updated when the call is an error.
TEST_P(BufferMappingTests, OffsetNotUpdatedOnError) {
    uint32_t data[3] = {0xCA7, 0xB0A7, 0xBA7};
    wgpu::Buffer buffer = CreateMapReadBuffer(sizeof(data));
    queue.WriteBuffer(buffer, 0, data, sizeof(data));

    EXPECT_CALL(mMockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);
    EXPECT_CALL(mMockCb, Call(wgpu::MapAsyncStatus::Error, _)).Times(1);

    // Map the buffer but do not wait on the result yet.
    wgpu::FutureWaitInfo f1 = {buffer.MapAsync(wgpu::MapMode::Read, 8, 4,
                                               GetParam().mFutureCallbackMode, mMockCb.Callback())};

    // Call MapAsync another time, the callback will be rejected with error status
    // and mMapOffset is not updated because the buffer is already being mapped and it doesn't
    // allow multiple MapAsync requests.
    wgpu::FutureWaitInfo f2;
    // TODO(crbug.com/42241221): Inject a validation error from the wire client, so that behavior
    // is consistent between native and wire.
    if (!UsesWire()) {
        ASSERT_DEVICE_ERROR(
            f2 = {buffer.MapAsync(wgpu::MapMode::Read, 0, 4, GetParam().mFutureCallbackMode,
                                  mMockCb.Callback())});
    } else {
        f2 = {buffer.MapAsync(wgpu::MapMode::Read, 0, 4, GetParam().mFutureCallbackMode,
                              mMockCb.Callback())};
    }

    switch (GetParam().mFutureCallbackMode) {
        case wgpu::CallbackMode::WaitAnyOnly: {
            ASSERT_EQ(GetInstance().WaitAny(1, &f1, UINT64_MAX), wgpu::WaitStatus::Success);
            ASSERT_EQ(GetInstance().WaitAny(1, &f2, UINT64_MAX), wgpu::WaitStatus::Success);
            EXPECT_TRUE(f1.completed);
            EXPECT_TRUE(f2.completed);
            break;
        }
        case wgpu::CallbackMode::AllowProcessEvents:
        case wgpu::CallbackMode::AllowSpontaneous:
            WaitForAllOperations();
            break;
    }

    // mMapOffset has not been updated so it should still be 4, which is data[1]
    ASSERT_EQ(0, memcmp(buffer.GetConstMappedRange(8), &data[2], sizeof(uint32_t)));
}

// Test that Get(Const)MappedRange work inside map-write callback.
TEST_P(BufferMappingTests, MapWrite_InCallbackDefault) {
    wgpu::Buffer buffer = CreateMapWriteBuffer(4);

    static constexpr uint32_t myData = 2934875;
    static constexpr size_t kSize = sizeof(myData);

    MapAsyncAndWait(buffer, wgpu::MapMode::Write, 0, kSize,
                    [&](wgpu::MapAsyncStatus status, wgpu::StringView) {
                        EXPECT_NE(nullptr, buffer.GetConstMappedRange());
                        void* ptr = buffer.GetMappedRange();
                        EXPECT_NE(nullptr, ptr);
                        if (ptr != nullptr) {
                            uint32_t data = myData;
                            memcpy(ptr, &data, kSize);
                        }
                        buffer.Unmap();
                    });

    EXPECT_BUFFER_U32_EQ(myData, buffer, 0);
}

// Test that Get(Const)MappedRange with range work inside map-write callback.
TEST_P(BufferMappingTests, MapWrite_InCallbackRange) {
    wgpu::Buffer buffer = CreateMapWriteBuffer(4);

    static constexpr uint32_t myData = 2934875;
    static constexpr size_t kSize = sizeof(myData);

    MapAsyncAndWait(buffer, wgpu::MapMode::Write, 0, kSize,
                    [&](wgpu::MapAsyncStatus status, wgpu::StringView) {
                        EXPECT_NE(nullptr, buffer.GetConstMappedRange(0, kSize));
                        void* ptr = buffer.GetMappedRange(0, kSize);
                        EXPECT_NE(nullptr, ptr);
                        if (ptr != nullptr) {
                            uint32_t data = myData;
                            memcpy(ptr, &data, kSize);
                        }
                        buffer.Unmap();
                    });

    EXPECT_BUFFER_U32_EQ(myData, buffer, 0);
}

// Regression test for crbug.com/dawn/969 where this test
// produced invalid barriers.
TEST_P(BufferMappingTests, MapWrite_ZeroSizedTwice) {
    wgpu::Buffer buffer = CreateMapWriteBuffer(0);

    MapAsyncAndWait(buffer, wgpu::MapMode::Write, 0, wgpu::kWholeMapSize);
    buffer.Unmap();

    MapAsyncAndWait(buffer, wgpu::MapMode::Write, 0, wgpu::kWholeMapSize);
}

// Regression test for crbug.com/1421170 where dropping a buffer which needs
// padding bytes initialization resulted in a use-after-free.
TEST_P(BufferMappingTests, RegressChromium1421170) {
    // Create a mappable buffer of size 7. It will be internally
    // aligned such that the padding bytes need to be zero initialized.
    wgpu::BufferDescriptor descriptor;
    descriptor.size = 7;
    descriptor.usage = wgpu::BufferUsage::MapWrite;
    descriptor.mappedAtCreation = false;
    wgpu::Buffer buffer = device.CreateBuffer(&descriptor);

    // Drop the buffer. The pending commands to zero initialize the
    // padding bytes should stay valid.
    buffer = nullptr;
    // Flush pending commands.
    device.Tick();
}

// Test that writing to a buffer in a compute shader, copying to a MapRead buffer,
// waiting for OnSubmittedWorkDone, then mapping works correctly.
TEST_P(BufferMappingTests, WaitForOnSubmittedWorkDoneThenMap) {
    // WaitAnyOnly is not supported in wire.
    DAWN_TEST_UNSUPPORTED_IF(UsesWire());

    const uint32_t kExpectedValue = 42;
    constexpr size_t kSize = sizeof(kExpectedValue);

    // Create compute pipeline that writes to the buffer.
    wgpu::ComputePipeline pipeline;
    {
        wgpu::ComputePipelineDescriptor csDesc;
        csDesc.compute.module = utils::CreateShaderModule(device, R"(
            struct SSBO {
                value : u32
            }
            @group(0) @binding(0) var<storage, read_write> ssbo : SSBO;

            @compute @workgroup_size(1) fn main() {
                ssbo.value = 42u;
            })");
        pipeline = device.CreateComputePipeline(&csDesc);
    }

    // Create storage buffer for compute shader.
    wgpu::BufferDescriptor storageDesc;
    storageDesc.size = kSize;
    storageDesc.usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc;
    wgpu::Buffer storageBuffer = device.CreateBuffer(&storageDesc);

    // Create MapRead buffer.
    wgpu::BufferDescriptor mapReadDesc;
    mapReadDesc.size = kSize;
    mapReadDesc.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
    wgpu::Buffer mapReadBuffer = device.CreateBuffer(&mapReadDesc);

    // Write to storage buffer and copy to MapRead buffer.
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                                         {{0, storageBuffer, 0, kSize}});
        pass.SetBindGroup(0, bindGroup);
        pass.SetPipeline(pipeline);
        pass.DispatchWorkgroups(1);
        pass.End();

        encoder.CopyBufferToBuffer(storageBuffer, 0, mapReadBuffer, 0, kSize);

        wgpu::CommandBuffer commands = encoder.Finish();
        queue.Submit(1, &commands);
    }

    // Wait for OnSubmittedWorkDone to complete.
    bool workDone = false;
    wgpu::Future workDoneFuture = queue.OnSubmittedWorkDone(
        wgpu::CallbackMode::WaitAnyOnly, [&](wgpu::QueueWorkDoneStatus status, wgpu::StringView) {
            ASSERT_EQ(status, wgpu::QueueWorkDoneStatus::Success);
            workDone = true;
        });

    ASSERT_EQ(GetInstance().WaitAny(workDoneFuture, UINT64_MAX), wgpu::WaitStatus::Success);
    ASSERT_TRUE(workDone);

    // Map the buffer for reading.
    // After waiting for OnSubmittedWorkDone, the MapAsync should be ready immediately,
    // so we use timeout=0 instead of blocking.
    bool mapDone = false;
    wgpu::Future mapFuture =
        mapReadBuffer.MapAsync(wgpu::MapMode::Read, 0, kSize, wgpu::CallbackMode::WaitAnyOnly,
                               [&](wgpu::MapAsyncStatus status, wgpu::StringView) {
                                   ASSERT_EQ(status, wgpu::MapAsyncStatus::Success);
                                   mapDone = true;
                               });

    ASSERT_EQ(GetInstance().WaitAny(mapFuture, 0), wgpu::WaitStatus::Success);
    ASSERT_TRUE(mapDone);

    // Verify buffer content.
    const uint32_t* data = static_cast<const uint32_t*>(mapReadBuffer.GetConstMappedRange());
    ASSERT_NE(data, nullptr);
    EXPECT_EQ(*data, kExpectedValue);

    mapReadBuffer.Unmap();
}

DAWN_INSTANTIATE_TEST_P(BufferMappingTests,
                        {D3D11Backend(), D3D11Backend({"d3d11_disable_cpu_buffers"}),
                         D3D11Backend({"auto_map_backend_buffer", "d3d11_disable_cpu_buffers"}),
                         D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(),
                         OpenGLESBackend({"gl_defer"}), VulkanBackend(), WebGPUBackend()},
                        std::initializer_list<wgpu::CallbackMode>{
                            wgpu::CallbackMode::WaitAnyOnly, wgpu::CallbackMode::AllowProcessEvents,
                            wgpu::CallbackMode::AllowSpontaneous});

class BufferMappingCallbackTests : public BufferMappingTests {
  protected:
    void SubmitCommandBuffer(wgpu::Buffer buffer) {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();

        {
            // Record enough commands to make sure the submission cannot be completed by GPU too
            // quick.
            constexpr int kRepeatCount = 50;
            constexpr int kBufferSize = 1024 * 1024 * 10;
            wgpu::Buffer tempWriteBuffer = CreateMapWriteBuffer(kBufferSize);
            wgpu::Buffer tempReadBuffer = CreateUniformBuffer(kBufferSize);
            for (int i = 0; i < kRepeatCount; ++i) {
                encoder.CopyBufferToBuffer(tempWriteBuffer, 0, tempReadBuffer, 0,
                                           kBufferSize - 1024);
            }
        }

        if (buffer) {
            if (buffer.GetUsage() & wgpu::BufferUsage::CopyDst) {
                encoder.ClearBuffer(buffer);
            } else {
                wgpu::Buffer tempBuffer = CreateMapReadBuffer(buffer.GetSize());
                encoder.CopyBufferToBuffer(buffer, 0, tempBuffer, 0, buffer.GetSize());
            }
        }
        wgpu::CommandBuffer commandBuffer = encoder.Finish();
        queue.Submit(1, &commandBuffer);
    }

    void WaitAll(std::vector<bool>& done, std::vector<wgpu::Future> futures) {
        if (GetParam().mFutureCallbackMode == wgpu::CallbackMode::WaitAnyOnly) {
            std::vector<wgpu::FutureWaitInfo> waitInfos;
            waitInfos.reserve(futures.size());
            for (wgpu::Future f : futures) {
                waitInfos.push_back({f});
            }
            size_t count = waitInfos.size();
            do {
                GetInstance().WaitAny(count, waitInfos.data(), UINT64_MAX);
                auto it = std::partition(waitInfos.begin(), waitInfos.end(),
                                         [](const auto& info) { return !info.completed; });
                count = std::distance(waitInfos.begin(), it);
            } while (count > 0);
        } else {
            do {
                WaitABit();
            } while (std::any_of(done.begin(), done.end(), [](bool done) { return !done; }));
        }
    }
};

TEST_P(BufferMappingCallbackTests, EmptySubmissionAndThenMap) {
    wgpu::Buffer buffer = CreateMapWriteBuffer(4);
    MapAsyncAndWait(buffer, wgpu::MapMode::Write, 0, wgpu::kWholeMapSize);
    buffer.Unmap();

    std::vector<bool> done = {false, false};

    // 1. submission without using buffer.
    SubmitCommandBuffer({});
    wgpu::Future f1 = queue.OnSubmittedWorkDone(
        GetParam().mFutureCallbackMode, [&](wgpu::QueueWorkDoneStatus status, wgpu::StringView) {
            ASSERT_EQ(status, wgpu::QueueWorkDoneStatus::Success);
            done[0] = true;

            // Step 2 callback should be called first, this is the second.
            const std::vector<bool> kExpected = {true, true};
            EXPECT_EQ(done, kExpected);
        });

    // 2.
    wgpu::Future f2 = buffer.MapAsync(wgpu::MapMode::Write, 0, wgpu::kWholeMapSize,
                                      GetParam().mFutureCallbackMode,
                                      [&](wgpu::MapAsyncStatus status, wgpu::StringView) {
                                          ASSERT_EQ(status, wgpu::MapAsyncStatus::Success);
                                          done[1] = true;

                                          // The buffer is not used by step 1, so this callback is
                                          // called first.
                                          const std::vector<bool> kExpected = {false, true};
                                          EXPECT_EQ(done, kExpected);
                                      });

    WaitAll(done, {f1, f2});
}

// Test the spec's promise ordering guarantee that a buffer mapping promise created before a
// onSubmittedWorkDone promise must resolve in that order.
TEST_P(BufferMappingCallbackTests, MapThenWaitWorkDone) {
    wgpu::Buffer buffer = CreateMapWriteBuffer(4);
    MapAsyncAndWait(buffer, wgpu::MapMode::Write, 0, wgpu::kWholeMapSize);
    buffer.Unmap();

    std::vector<bool> done = {false, false};

    // 0. Submit a command buffer which uses the buffer
    SubmitCommandBuffer(buffer);

    // 1. Map the buffer.
    wgpu::Future f1 = buffer.MapAsync(wgpu::MapMode::Write, 0, wgpu::kWholeMapSize,
                                      GetParam().mFutureCallbackMode,
                                      [&](wgpu::MapAsyncStatus status, wgpu::StringView) {
                                          ASSERT_EQ(status, wgpu::MapAsyncStatus::Success);
                                          done[0] = true;

                                          // This callback must be called first.
                                          const std::vector<bool> kExpected = {true, false};
                                          EXPECT_EQ(done, kExpected);
                                      });

    // 2. Wait for command completion.
    wgpu::Future f2 = queue.OnSubmittedWorkDone(
        GetParam().mFutureCallbackMode, [&](wgpu::QueueWorkDoneStatus status, wgpu::StringView) {
            ASSERT_EQ(status, wgpu::QueueWorkDoneStatus::Success);
            done[1] = true;

            // The buffer mapping callback must have been called before this one.
            const std::vector<bool> kExpected = {true, true};
            EXPECT_EQ(done, kExpected);
        });

    WaitAll(done, {f1, f2});

    buffer.Unmap();
}

TEST_P(BufferMappingCallbackTests, EmptySubmissionWriteAndThenMap) {
    wgpu::Buffer buffer = CreateMapReadBuffer(4);
    MapAsyncAndWait(buffer, wgpu::MapMode::Read, 0, wgpu::kWholeMapSize);
    buffer.Unmap();

    std::vector<bool> done = {false, false};

    // With Vulkan Queue::WriteBuffers() doesn't encode any commands which need to be waited on so
    // MapAsync() can happen immediately. On other platforms that isn't the case.
    // Similarly, for MapRead buffers, D3D11's Queue::WriteBuffers() also doesn't encode any
    // commands.
    bool mapCompletesFirst = (IsVulkan() || IsD3D11()) && !IsWebGPUOnWebGPU();

    // 1. submission without using buffer.
    SubmitCommandBuffer({});
    wgpu::Future f1 = queue.OnSubmittedWorkDone(
        GetParam().mFutureCallbackMode, [&](wgpu::QueueWorkDoneStatus status, wgpu::StringView) {
            ASSERT_EQ(status, wgpu::QueueWorkDoneStatus::Success);
            done[0] = true;

            const std::vector<bool> kExpected = {true, mapCompletesFirst};
            EXPECT_EQ(done, kExpected);
        });

    int32_t data = 0x12345678;
    queue.WriteBuffer(buffer, 0, &data, sizeof(data));

    // 2.
    wgpu::Future f2 =
        buffer.MapAsync(wgpu::MapMode::Read, 0, wgpu::kWholeMapSize, GetParam().mFutureCallbackMode,
                        [&](wgpu::MapAsyncStatus status, wgpu::StringView) {
                            ASSERT_EQ(status, wgpu::MapAsyncStatus::Success);
                            done[1] = true;

                            const std::vector<bool> kExpected = {!mapCompletesFirst, true};
                            EXPECT_EQ(done, kExpected);
                        });

    WaitAll(done, {f1, f2});

    buffer.Unmap();
}

DAWN_INSTANTIATE_TEST_P(BufferMappingCallbackTests,
                        {D3D11Backend(), D3D11Backend({"d3d11_disable_cpu_buffers"}),
                         D3D11Backend({"auto_map_backend_buffer", "d3d11_disable_cpu_buffers"}),
                         D3D12Backend(), MetalBackend(), VulkanBackend(), WebGPUBackend()},
                        std::initializer_list<wgpu::CallbackMode>{
                            wgpu::CallbackMode::WaitAnyOnly, wgpu::CallbackMode::AllowProcessEvents,
                            wgpu::CallbackMode::AllowSpontaneous});

class BufferMappedAtCreationTests : public DawnTest {
  protected:
    const void* MapAsyncAndWait(const wgpu::Buffer& buffer, wgpu::MapMode mode, size_t size) {
        bool done = false;
        buffer.MapAsync(mode, 0, size, wgpu::CallbackMode::AllowProcessEvents,
                        [&done](wgpu::MapAsyncStatus status, wgpu::StringView) {
                            EXPECT_EQ(wgpu::MapAsyncStatus::Success, status);
                            done = true;
                        });

        while (!done) {
            WaitABit();
        }

        return buffer.GetConstMappedRange(0, size);
    }

    void UnmapBuffer(const wgpu::Buffer& buffer) { buffer.Unmap(); }

    wgpu::Buffer BufferMappedAtCreation(wgpu::BufferUsage usage, uint64_t size) {
        wgpu::BufferDescriptor descriptor;
        descriptor.size = size;
        descriptor.usage = usage;
        descriptor.mappedAtCreation = true;
        return device.CreateBuffer(&descriptor);
    }

    wgpu::Buffer BufferMappedAtCreationWithData(wgpu::BufferUsage usage,
                                                const std::vector<uint32_t>& data) {
        size_t byteLength = data.size() * sizeof(uint32_t);
        wgpu::Buffer buffer = BufferMappedAtCreation(usage, byteLength);
        memcpy(buffer.GetMappedRange(), data.data(), byteLength);
        return buffer;
    }
};

// Test that the simplest mappedAtCreation works for MapWrite buffers.
TEST_P(BufferMappedAtCreationTests, MapWriteUsageSmall) {
    uint32_t myData = 230502;
    wgpu::Buffer buffer = BufferMappedAtCreationWithData(
        wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc, {myData});
    UnmapBuffer(buffer);
    EXPECT_BUFFER_U32_EQ(myData, buffer, 0);
}

// Test that the simplest mappedAtCreation works for MapRead buffers.
TEST_P(BufferMappedAtCreationTests, MapReadUsageSmall) {
    // TODO(crbug.com/473894293): [Capture] buffer mapping: investigate.
    DAWN_SUPPRESS_TEST_IF(IsCaptureReplayCheckingEnabled());

    uint32_t myData = 230502;
    wgpu::Buffer buffer = BufferMappedAtCreationWithData(wgpu::BufferUsage::MapRead, {myData});
    UnmapBuffer(buffer);

    const void* mappedData = MapAsyncAndWait(buffer, wgpu::MapMode::Read, 4);
    ASSERT_EQ(myData, *reinterpret_cast<const uint32_t*>(mappedData));
    UnmapBuffer(buffer);
}

// Test that the simplest mappedAtCreation works for non-mappable buffers.
TEST_P(BufferMappedAtCreationTests, NonMappableUsageSmall) {
    uint32_t myData = 4239;
    // Test with and without Uniform which may add additional padding at the end of the buffer.
    for (wgpu::BufferUsage extraUsage : {{}, wgpu::BufferUsage::Uniform}) {
        wgpu::Buffer buffer =
            BufferMappedAtCreationWithData(wgpu::BufferUsage::CopySrc | extraUsage, {myData});
        UnmapBuffer(buffer);
        EXPECT_BUFFER_U32_EQ(myData, buffer, 0);
    }
}

// Test mappedAtCreation for a large MapWrite buffer
TEST_P(BufferMappedAtCreationTests, MapWriteUsageLarge) {
    constexpr uint64_t kDataSize = 1000 * 1000;
    std::vector<uint32_t> myData;
    for (uint32_t i = 0; i < kDataSize; ++i) {
        myData.push_back(i);
    }

    wgpu::Buffer buffer = BufferMappedAtCreationWithData(
        wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc, {myData});
    UnmapBuffer(buffer);

    EXPECT_BUFFER_U32_RANGE_EQ(myData.data(), buffer, 0, kDataSize);
}

// Test mappedAtCreation for a large MapRead buffer
TEST_P(BufferMappedAtCreationTests, MapReadUsageLarge) {
    // TODO(crbug.com/473894293): [Capture] buffer mapping: investigate.
    DAWN_SUPPRESS_TEST_IF(IsCaptureReplayCheckingEnabled());

    constexpr uint64_t kDataSize = 1000 * 1000;
    std::vector<uint32_t> myData;
    for (uint32_t i = 0; i < kDataSize; ++i) {
        myData.push_back(i);
    }

    wgpu::Buffer buffer = BufferMappedAtCreationWithData(wgpu::BufferUsage::MapRead, myData);
    UnmapBuffer(buffer);

    const void* mappedData =
        MapAsyncAndWait(buffer, wgpu::MapMode::Read, kDataSize * sizeof(uint32_t));
    ASSERT_EQ(0, memcmp(mappedData, myData.data(), kDataSize * sizeof(uint32_t)));
    UnmapBuffer(buffer);
}

// Test mappedAtCreation for a large non-mappable buffer
TEST_P(BufferMappedAtCreationTests, NonMappableUsageLarge) {
    constexpr uint64_t kDataSize = 1000 * 1000;
    std::vector<uint32_t> myData;
    for (uint32_t i = 0; i < kDataSize; ++i) {
        myData.push_back(i);
    }

    wgpu::Buffer buffer = BufferMappedAtCreationWithData(wgpu::BufferUsage::CopySrc, {myData});
    UnmapBuffer(buffer);

    EXPECT_BUFFER_U32_RANGE_EQ(myData.data(), buffer, 0, kDataSize);
}

// Test destroying a non-mappable buffer mapped at creation.
// This is a regression test for an issue where the D3D12 backend thought the buffer was actually
// mapped and tried to unlock the heap residency (when actually the buffer was using a staging
// buffer)
TEST_P(BufferMappedAtCreationTests, DestroyNonMappableWhileMappedForCreation) {
    wgpu::Buffer buffer = BufferMappedAtCreation(wgpu::BufferUsage::CopySrc, 4);
    buffer.Destroy();
}

// Test destroying a mappable buffer mapped at creation.
TEST_P(BufferMappedAtCreationTests, DestroyMappableWhileMappedForCreation) {
    wgpu::Buffer buffer = BufferMappedAtCreation(wgpu::BufferUsage::MapRead, 4);
    buffer.Destroy();
}

// Test that mapping a buffer is valid after mappedAtCreation and Unmap
TEST_P(BufferMappedAtCreationTests, CreateThenMapSuccess) {
    static uint32_t myData = 230502;
    wgpu::Buffer buffer = BufferMappedAtCreationWithData(
        wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc, {myData});
    UnmapBuffer(buffer);

    EXPECT_BUFFER_U32_EQ(myData, buffer, 0);

    bool done = false;
    buffer.MapAsync(wgpu::MapMode::Write, 0, 4, wgpu::CallbackMode::AllowProcessEvents,
                    [&done](wgpu::MapAsyncStatus status, wgpu::StringView) {
                        EXPECT_EQ(wgpu::MapAsyncStatus::Success, status);
                        done = true;
                    });

    while (!done) {
        WaitABit();
    }

    UnmapBuffer(buffer);
}

// Test that is is invalid to map a buffer twice when using mappedAtCreation
TEST_P(BufferMappedAtCreationTests, CreateThenMapBeforeUnmapFailure) {
    uint32_t myData = 230502;
    wgpu::Buffer buffer = BufferMappedAtCreationWithData(
        wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc, {myData});

    ASSERT_DEVICE_ERROR([&] {
        bool done = false;
        buffer.MapAsync(wgpu::MapMode::Write, 0, 4, wgpu::CallbackMode::AllowProcessEvents,
                        [&done](wgpu::MapAsyncStatus status, wgpu::StringView) {
                            EXPECT_EQ(wgpu::MapAsyncStatus::Error, status);
                            done = true;
                        });

        while (!done) {
            WaitABit();
        }
    }());

    // mappedAtCreation is unaffected by the MapWrite error.
    UnmapBuffer(buffer);
}

// Test that creating a zero-sized buffer mapped is allowed.
TEST_P(BufferMappedAtCreationTests, ZeroSized) {
    wgpu::BufferDescriptor descriptor;
    descriptor.size = 0;
    descriptor.usage = wgpu::BufferUsage::Vertex;
    descriptor.mappedAtCreation = true;
    wgpu::Buffer buffer = device.CreateBuffer(&descriptor);

    ASSERT_NE(nullptr, buffer.GetMappedRange());

    // Check that unmapping the buffer works too.
    UnmapBuffer(buffer);
}

// Test that creating a zero-sized mapppable buffer mapped. (it is a different code path)
TEST_P(BufferMappedAtCreationTests, ZeroSizedMappableBuffer) {
    wgpu::BufferDescriptor descriptor;
    descriptor.size = 0;
    descriptor.usage = wgpu::BufferUsage::MapWrite;
    descriptor.mappedAtCreation = true;
    wgpu::Buffer buffer = device.CreateBuffer(&descriptor);

    ASSERT_NE(nullptr, buffer.GetMappedRange());

    // Check that unmapping the buffer works too.
    UnmapBuffer(buffer);
}

// Test that creating a zero-sized error buffer mapped. (it is a different code path)
TEST_P(BufferMappedAtCreationTests, ZeroSizedErrorBuffer) {
    DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("skip_validation"));

    wgpu::BufferDescriptor descriptor;
    descriptor.size = 0;
    descriptor.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::Storage;
    descriptor.mappedAtCreation = true;
    wgpu::Buffer buffer;
    ASSERT_DEVICE_ERROR(buffer = device.CreateBuffer(&descriptor));

    ASSERT_NE(nullptr, buffer.GetMappedRange());
}

// Test the result of GetMappedRange when mapped at creation.
TEST_P(BufferMappedAtCreationTests, GetMappedRange) {
    wgpu::BufferDescriptor descriptor;
    descriptor.size = 4;
    descriptor.usage = wgpu::BufferUsage::CopyDst;
    descriptor.mappedAtCreation = true;
    wgpu::Buffer buffer = device.CreateBuffer(&descriptor);

    ASSERT_EQ(buffer.GetMappedRange(), buffer.GetConstMappedRange());
    ASSERT_NE(buffer.GetMappedRange(), nullptr);
    buffer.Unmap();
}

// Test the result of GetMappedRange when mapped at creation for a zero-sized buffer.
TEST_P(BufferMappedAtCreationTests, GetMappedRangeZeroSized) {
    wgpu::BufferDescriptor descriptor;
    descriptor.size = 0;
    descriptor.usage = wgpu::BufferUsage::CopyDst;
    descriptor.mappedAtCreation = true;
    wgpu::Buffer buffer = device.CreateBuffer(&descriptor);

    ASSERT_EQ(buffer.GetMappedRange(), buffer.GetConstMappedRange());
    ASSERT_NE(buffer.GetMappedRange(), nullptr);
    buffer.Unmap();
}

DAWN_INSTANTIATE_TEST(BufferMappedAtCreationTests,
                      D3D11Backend(),
                      D3D11Backend({"d3d11_disable_cpu_buffers"}),
                      D3D11Backend({"auto_map_backend_buffer", "d3d11_disable_cpu_buffers"}),
                      D3D12Backend(),
                      D3D12Backend({}, {"use_d3d12_resource_heap_tier2"}),
                      MetalBackend(),
                      OpenGLBackend(),
                      OpenGLESBackend(),
                      OpenGLESBackend({"gl_defer"}),
                      VulkanBackend(),
                      WebGPUBackend());

class BufferTests : public DawnTest {};

// Test that creating a zero-buffer is allowed.
TEST_P(BufferTests, ZeroSizedBuffer) {
    wgpu::BufferDescriptor desc;
    desc.size = 0;
    desc.usage = wgpu::BufferUsage::CopyDst;
    device.CreateBuffer(&desc);
}

// Test that creating a very large buffers fails gracefully.
TEST_P(BufferTests, CreateBufferOOM) {
    // TODO(http://crbug.com/dawn/749): Missing support.
    DAWN_TEST_UNSUPPORTED_IF(IsOpenGL());
    DAWN_TEST_UNSUPPORTED_IF(IsAsan());
    DAWN_TEST_UNSUPPORTED_IF(IsTsan());

    // TODO(crbug.com/452924802): Unable to allocate buffer with validation
    // skipped on WebGPU on WebGPU w/ Metal/Vulkan backends.
    DAWN_SUPPRESS_TEST_IF(IsWebGPUOn(wgpu::BackendType::Metal) && !IsBackendValidationEnabled());
    DAWN_SUPPRESS_TEST_IF(IsWebGPUOn(wgpu::BackendType::Vulkan) && !IsBackendValidationEnabled());

    wgpu::BufferDescriptor descriptor;
    descriptor.usage = wgpu::BufferUsage::CopyDst;

    descriptor.size = std::numeric_limits<uint64_t>::max();
    ASSERT_DEVICE_ERROR(device.CreateBuffer(&descriptor));

    // UINT64_MAX may be special cased. Test a smaller, but really large buffer also fails
    descriptor.size = 1ull << 50;
    ASSERT_DEVICE_ERROR(device.CreateBuffer(&descriptor));
}

// Test that in the creation of buffers validation errors should always be prior to OOM.
TEST_P(BufferTests, CreateBufferOOMWithValidationError) {
    // Fails on TSAN due to allowing too much memory. TSAN max is `0x10000000000` and the test
    // allocates `0x4000000000000000`
    DAWN_SUPPRESS_TEST_IF(IsTsan());

    DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("skip_validation"));

    wgpu::BufferDescriptor descriptor;
    descriptor.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::Uniform;

    descriptor.size = std::numeric_limits<uint64_t>::max();
    ASSERT_DEVICE_ERROR(device.CreateBuffer(&descriptor));

    // UINT64_MAX may be special cased. Test a smaller, but really large buffer also fails
    descriptor.size = 1ull << 50;
    ASSERT_DEVICE_ERROR(device.CreateBuffer(&descriptor));
}

// Test that a very large buffer mappedAtCreation fails gracefully.
TEST_P(BufferTests, BufferMappedAtCreationOOM) {
    // TODO(http://crbug.com/dawn/749): Missing support.
    DAWN_TEST_UNSUPPORTED_IF(IsOpenGL());
    DAWN_TEST_UNSUPPORTED_IF(IsAsan());
    DAWN_TEST_UNSUPPORTED_IF(IsTsan());

    auto Check = [&](bool nonNull, const wgpu::BufferDescriptor* desc) {
        wgpu::Buffer buffer = device.CreateBuffer(desc);
        if (nonNull) {
            ASSERT_NE(nullptr, buffer.Get());
            ASSERT_NE(nullptr, buffer.GetMappedRange());
        } else {
            ASSERT_EQ(nullptr, buffer.Get());
        }
    };

    for (wgpu::BufferUsage usage : {
             wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::None,
             wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::MapWrite,
             wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead,
         }) {
        wgpu::BufferDescriptor descriptor;
        descriptor.usage = usage;
        descriptor.mappedAtCreation = true;

        // Control: test a small buffer works.
        descriptor.size = 4;
        Check(true, &descriptor);

        // Test an enormous buffer fails
        descriptor.size = std::numeric_limits<uint64_t>::max();
        Check(false, &descriptor);

        // UINT64_MAX may be special cased. Test a smaller, but really large buffer also fails
        descriptor.size = 1ull << 50;
        Check(false, &descriptor);
    }
}

// Test OOM cases that can't be reliably triggered, but can be simulated.
TEST_P(BufferTests, BufferMappedAtCreationOOM_Simulated) {
    auto Check = [&](bool mapError, bool deviceError, const wgpu::BufferDescriptor* desc) {
        wgpu::Buffer buffer;
        if (deviceError) {
            ASSERT_DEVICE_ERROR(buffer = device.CreateBuffer(desc));
        } else {
            buffer = device.CreateBuffer(desc);
        }
        if (mapError) {
            ASSERT_EQ(nullptr, buffer.Get());
        } else {
            ASSERT_NE(nullptr, buffer.Get());
            ASSERT_NE(nullptr, buffer.GetMappedRange());
        }
    };

    for (wgpu::BufferUsage usage : {
             wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::None,
             wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::MapWrite,
             wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead,
         }) {
        wgpu::DawnFakeBufferOOMForTesting oomForTesting;
        wgpu::BufferDescriptor descriptor;
        descriptor.nextInChain = &oomForTesting;
        descriptor.size = 4;
        descriptor.usage = usage;
        descriptor.mappedAtCreation = true;

        // Control: test a small buffer works.
        Check(false, false, &descriptor);

        // Test OOM in the wire client before ever sending a command.
        if (UsesWire()) {
            oomForTesting = {};
            oomForTesting.fakeOOMAtWireClientMap = true;
            Check(true, false, &descriptor);
        }

        // Test OOM in Dawn Native. If using the wire, this could cause a
        // non-null client buffer to point to a null server buffer.
        oomForTesting = {};
        oomForTesting.fakeOOMAtNativeMap = true;
        Check(!UsesWire(), false, &descriptor);

        // Test OOM in Dawn Native AND in the device allocation. Similar to previous case.
        oomForTesting = {};
        oomForTesting.fakeOOMAtNativeMap = true;
        oomForTesting.fakeOOMAtDevice = true;
        Check(!UsesWire(), false, &descriptor);

        // Test OOM only in device allocation. There should be no nulls returned at either layer.
        oomForTesting = {};
        oomForTesting.fakeOOMAtDevice = true;
        Check(false, true, &descriptor);
    }
}

// Test calling Queue.Submit() while a mappedAtCreation Buffer is still mapped.
TEST_P(BufferTests, BufferMappedAtCreationSubmitBeforeUnmap) {
    uint32_t size = sizeof(uint32_t);
    wgpu::BufferDescriptor sourceDesc, destDesc;

    sourceDesc.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc;
    sourceDesc.size = size;
    sourceDesc.mappedAtCreation = true;

    destDesc.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
    destDesc.size = size;

    wgpu::Buffer source = device.CreateBuffer(&sourceDesc);
    wgpu::Buffer dest = device.CreateBuffer(&destDesc);

    auto mappedPointer = static_cast<uint32_t*>(source.GetMappedRange());

    queue.Submit(0, nullptr);

    *mappedPointer = 42;

    source.Unmap();

    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    encoder.CopyBufferToBuffer(source, 0, dest, 0, size);
    auto commands = encoder.Finish();
    queue.Submit(1, &commands);
    MapAsyncAndWait(dest, wgpu::MapMode::Read, 0, size);
    auto result = static_cast<const uint32_t*>(dest.GetConstMappedRange());
    ASSERT_EQ(result[0], 42u);
}

TEST_P(BufferTests, CreateErrorBuffer) {
    wgpu::BufferDescriptor desc{.usage = wgpu::BufferUsage::CopySrc, .size = 8};
    wgpu::Buffer buffer;

    desc.mappedAtCreation = false;
    buffer = device.CreateErrorBuffer(&desc);
    ASSERT_NE(buffer, nullptr);

    desc.mappedAtCreation = true;
    buffer = device.CreateErrorBuffer(&desc);
    ASSERT_EQ(buffer, nullptr);

    wgpu::DawnBufferDescriptorErrorInfoFromWireClient ext;
    ext.outOfMemory = true;
    desc.nextInChain = &ext;

    desc.mappedAtCreation = false;
    ASSERT_DEVICE_ERROR(buffer = device.CreateErrorBuffer(&desc));
    ASSERT_NE(buffer, nullptr);

    desc.mappedAtCreation = true;
    buffer = device.CreateErrorBuffer(&desc);
    ASSERT_EQ(buffer, nullptr);
}

// Test that mapping an OOM buffer fails gracefully
TEST_P(BufferTests, CreateBufferOOMMapAsync) {
    // TODO(http://crbug.com/dawn/749): Missing support.
    DAWN_TEST_UNSUPPORTED_IF(IsOpenGL());
    DAWN_TEST_UNSUPPORTED_IF(IsAsan());
    DAWN_TEST_UNSUPPORTED_IF(IsTsan());

    // TODO(crbug.com/452924802): Unable to allocate buffer with validation
    // skipped on WebGPU on WebGPU w/ Metal/Vulkan backends.
    DAWN_SUPPRESS_TEST_IF(IsWebGPUOn(wgpu::BackendType::Metal) && !IsBackendValidationEnabled());
    DAWN_SUPPRESS_TEST_IF(IsWebGPUOn(wgpu::BackendType::Vulkan) && !IsBackendValidationEnabled());

    auto RunTest = [this](const wgpu::BufferDescriptor& descriptor) {
        wgpu::Buffer buffer;
        ASSERT_DEVICE_ERROR(buffer = device.CreateBuffer(&descriptor));

        bool done = false;
        ASSERT_DEVICE_ERROR(buffer.MapAsync((descriptor.usage & wgpu::BufferUsage::MapRead)
                                                ? wgpu::MapMode::Read
                                                : wgpu::MapMode::Write,
                                            0, 4, wgpu::CallbackMode::AllowProcessEvents,
                                            [&done](wgpu::MapAsyncStatus status, wgpu::StringView) {
                                                EXPECT_EQ(wgpu::MapAsyncStatus::Error, status);
                                                done = true;
                                            }));

        while (!done) {
            WaitABit();
        }
    };

    for (wgpu::BufferUsage usage : {
             wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::MapWrite,
             wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead,
         }) {
        wgpu::BufferDescriptor descriptor;
        descriptor.usage = usage;

        // Test an enormous buffer
        descriptor.size = std::numeric_limits<uint64_t>::max();
        RunTest(descriptor);

        // UINT64_MAX may be special cased. Test a smaller, but really large buffer also fails
        descriptor.size = 1ull << 50;
        RunTest(descriptor);
    }
}

DAWN_INSTANTIATE_TEST(BufferTests,
                      D3D11Backend(),
                      D3D12Backend(),
                      MetalBackend(),
                      OpenGLBackend(),
                      OpenGLESBackend(),
                      OpenGLESBackend({"gl_defer"}),
                      VulkanBackend(),
                      WebGPUBackend());

class BufferNoSuballocationTests : public DawnTest {};

// Regression test for crbug.com/1313172
// This tests a buffer. It then performs writeBuffer and immediately destroys
// it. Though writeBuffer references a destroyed buffer, it should not crash.
TEST_P(BufferNoSuballocationTests, WriteBufferThenDestroy) {
    uint32_t myData = 0x01020304;

    wgpu::BufferDescriptor desc;
    desc.size = 1024;
    desc.usage = wgpu::BufferUsage::CopyDst;
    wgpu::Buffer buffer = device.CreateBuffer(&desc);

    // Enqueue a pending write into the buffer.
    constexpr size_t kSize = sizeof(myData);
    queue.WriteBuffer(buffer, 0, &myData, kSize);

    // Destroy the buffer.
    buffer.Destroy();

    // Flush and wait for all commands.
    queue.Submit(0, nullptr);
    WaitForAllOperations();
}

DAWN_INSTANTIATE_TEST(BufferNoSuballocationTests,
                      D3D11Backend({"disable_resource_suballocation"}),
                      D3D12Backend({"disable_resource_suballocation"}),
                      MetalBackend({"disable_resource_suballocation"}),
                      OpenGLBackend({"disable_resource_suballocation"}),
                      OpenGLESBackend({"disable_resource_suballocation"}),
                      VulkanBackend({"disable_resource_suballocation"}),
                      WebGPUBackend({"disable_resource_suballocation"}));

class BufferMapExtendedUsagesTests : public DawnTest {
  protected:
    void GetRequiredLimits(const dawn::utils::ComboLimits& supported,
                           dawn::utils::ComboLimits& required) override {
        required.maxStorageBuffersInVertexStage = supported.maxStorageBuffersInVertexStage;
        required.maxStorageBuffersPerShaderStage = supported.maxStorageBuffersPerShaderStage;
    }

  protected:
    void SetUp() override {
        DawnTest::SetUp();

        DAWN_TEST_UNSUPPORTED_IF(UsesWire());
        // Skip all tests if the required feature is not supported.
        DAWN_TEST_UNSUPPORTED_IF(!SupportsFeatures({wgpu::FeatureName::BufferMapExtendedUsages}));

        // TODO(crbug.com/473894293): [Capture] validation error: no CopyDst usage.
        DAWN_SUPPRESS_TEST_IF(IsCaptureReplayCheckingEnabled());
    }

    std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
        std::vector<wgpu::FeatureName> requiredFeatures = {};
        if (!UsesWire() && SupportsFeatures({wgpu::FeatureName::BufferMapExtendedUsages})) {
            requiredFeatures.push_back(wgpu::FeatureName::BufferMapExtendedUsages);
        }
        return requiredFeatures;
    }

    void MapAsyncAndWait(const wgpu::Buffer& buffer,
                         wgpu::MapMode mode,
                         size_t offset,
                         size_t size) {
        wgpu::Future future = buffer.MapAsync(mode, offset, size, wgpu::CallbackMode::WaitAnyOnly,
                                              [](wgpu::MapAsyncStatus status, wgpu::StringView) {
                                                  ASSERT_EQ(wgpu::MapAsyncStatus::Success, status);
                                              });
        wgpu::FutureWaitInfo waitInfo = {future};
        GetInstance().WaitAny(1, &waitInfo, UINT64_MAX);
        ASSERT_TRUE(waitInfo.completed);
    }

    wgpu::Buffer CreateBufferFromData(const void* data, uint64_t size, wgpu::BufferUsage usage) {
        if (!(usage & wgpu::BufferUsage::MapWrite)) {
            return utils::CreateBufferFromData(device, data, size, usage);
        }

        wgpu::BufferDescriptor descriptor;
        descriptor.size = size;
        descriptor.usage = usage;

        wgpu::Buffer buffer = device.CreateBuffer(&descriptor);

        MapAsyncAndWait(buffer, wgpu::MapMode::Write, 0, size);
        memcpy(buffer.GetMappedRange(), data, size);
        buffer.Unmap();

        return buffer;
    }

    enum class ColorSrc {
        UniformBuffer,
        VertexBuffer,
        StorageBuffer,
    };

    wgpu::RenderPipeline CreateRenderPipelineForTest(
        ColorSrc colorSource,
        wgpu::VertexStepMode vertexBufferStepMode = wgpu::VertexStepMode::Vertex,
        wgpu::VertexFormat vertexBufferFormat = wgpu::VertexFormat::Unorm8x4) {
        utils::ComboRenderPipelineDescriptor pipelineDescriptor;

        std::ostringstream vs;
        vs << R"(
            struct VertexOut {
                @location(0) color : vec4f,
                @builtin(position) position : vec4f,
            }

            const vertexPos = array(
                vec2f(-1.0, -1.0),
                vec2f( 3.0, -1.0),
                vec2f(-1.0,  3.0));
        )";

        switch (colorSource) {
            case ColorSrc::UniformBuffer:
                // Color is from uniform buffer.
                vs << R"(
                struct Uniforms {
                    color : vec4f,
                }
                @binding(0) @group(0) var<uniform> uniforms : Uniforms;

                @vertex
                fn main(@builtin(vertex_index) vertexIndex : u32) -> VertexOut {
                    var output : VertexOut;
                    output.position = vec4f(vertexPos[vertexIndex % 3], 0.0, 1.0);
                    output.color = uniforms.color;
                    return output;
                })";
                break;
            case ColorSrc::VertexBuffer:
                // Color is from vertex buffer.
                vs << R"(
                @vertex
                fn main(@location(0) vertexColor : vec4f,
                        @builtin(vertex_index) vertexIndex : u32) -> VertexOut {
                    var output : VertexOut;
                    output.position = vec4f(vertexPos[vertexIndex % 3], 0.0, 1.0);
                    output.color = vertexColor;
                    return output;
                })";

                pipelineDescriptor.vertex.bufferCount = 1;
                pipelineDescriptor.cBuffers[0].arrayStride =
                    utils::VertexFormatSize(vertexBufferFormat);
                pipelineDescriptor.cBuffers[0].attributeCount = 1;
                pipelineDescriptor.cBuffers[0].stepMode = vertexBufferStepMode;
                pipelineDescriptor.cAttributes[0].format = vertexBufferFormat;
                break;
            case ColorSrc::StorageBuffer:
                vs << R"(
                struct Uniforms {
                    color : vec4f,
                }
                @binding(0) @group(0) var<storage, read> ssbo : Uniforms;

                @vertex
                fn main(@builtin(vertex_index) vertexIndex : u32) -> VertexOut {
                    var output : VertexOut;
                    output.position = vec4f(vertexPos[vertexIndex % 3], 0.0, 1.0);
                    output.color = ssbo.color;
                    return output;
                })";
                break;
        }
        constexpr char fs[] = R"(
            @fragment
            fn main(@location(0) color : vec4f) -> @location(0) vec4f {
                return color;
            })";

        pipelineDescriptor.vertex.module = utils::CreateShaderModule(device, vs.str().c_str());
        pipelineDescriptor.cFragment.module = utils::CreateShaderModule(device, fs);

        pipelineDescriptor.cFragment.targetCount = 1;
        pipelineDescriptor.cTargets[0].format = wgpu::TextureFormat::RGBA8Unorm;

        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDescriptor);
        return pipeline;
    }

    void EncodeAndSubmitRenderPassForTest(const wgpu::RenderPassDescriptor& renderPass,
                                          wgpu::RenderPipeline pipeline,
                                          wgpu::Buffer vertexBuffer,
                                          wgpu::Buffer indexBuffer,
                                          wgpu::BindGroup uniformsBindGroup,
                                          wgpu::CommandEncoder existingEncoder = nullptr) {
        wgpu::CommandEncoder commandEncoder =
            existingEncoder ? std::move(existingEncoder) : device.CreateCommandEncoder();
        wgpu::RenderPassEncoder renderPassEncoder = commandEncoder.BeginRenderPass(&renderPass);
        renderPassEncoder.SetPipeline(pipeline);
        if (uniformsBindGroup) {
            renderPassEncoder.SetBindGroup(0, uniformsBindGroup);
        }
        if (vertexBuffer) {
            renderPassEncoder.SetVertexBuffer(0, vertexBuffer);
        }

        if (indexBuffer) {
            renderPassEncoder.SetIndexBuffer(indexBuffer, wgpu::IndexFormat::Uint16);
            renderPassEncoder.DrawIndexed(3);
        } else {
            renderPassEncoder.Draw(3);
        }
        renderPassEncoder.End();

        wgpu::CommandBuffer commands = commandEncoder.Finish();
        queue.Submit(1, &commands);
    }

    void MixMapWriteAndGPUWriteBufferThenDraw(ColorSrc colorSrc);

    static constexpr wgpu::BufferUsage kMapExtendedUsages[] = {
        wgpu::BufferUsage::CopySrc,  wgpu::BufferUsage::CopyDst,      wgpu::BufferUsage::Index,
        wgpu::BufferUsage::Vertex,   wgpu::BufferUsage::Uniform,      wgpu::BufferUsage::Storage,
        wgpu::BufferUsage::Indirect, wgpu::BufferUsage::QueryResolve,
    };
};

// Test that the map read for any kind of buffer works
TEST_P(BufferMapExtendedUsagesTests, MapReadWithAnyUsage) {
    wgpu::BufferDescriptor descriptor;
    descriptor.size = 4;

    for (const auto otherUsage : kMapExtendedUsages) {
        descriptor.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst | otherUsage;
        wgpu::Buffer buffer = device.CreateBuffer(&descriptor);

        uint32_t myData = 0x01020304;
        constexpr size_t kSize = sizeof(myData);
        queue.WriteBuffer(buffer, 0, &myData, kSize);

        MapAsyncAndWait(buffer, wgpu::MapMode::Read, 0, 4);
        CheckMapping(buffer.GetConstMappedRange(), &myData, kSize);
        CheckMapping(buffer.GetConstMappedRange(0, kSize), &myData, kSize);
        buffer.Unmap();
    }
}

// Test that the map write for any kind of buffer works
TEST_P(BufferMapExtendedUsagesTests, MapWriteWithAnyUsage) {
    wgpu::BufferDescriptor descriptor;
    descriptor.size = 4;

    for (const auto otherUsage : kMapExtendedUsages) {
        descriptor.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc | otherUsage;
        wgpu::Buffer buffer = device.CreateBuffer(&descriptor);

        uint32_t myData = 2934875;
        MapAsyncAndWait(buffer, wgpu::MapMode::Write, 0, 4);
        ASSERT_NE(nullptr, buffer.GetMappedRange());
        ASSERT_NE(nullptr, buffer.GetConstMappedRange());
        memcpy(buffer.GetMappedRange(), &myData, sizeof(myData));
        buffer.Unmap();

        EXPECT_BUFFER_U32_EQ(myData, buffer, 0);
    }
}

// Test that Queue.WriteBuffer works to update a mappable buffer.
TEST_P(BufferMapExtendedUsagesTests, QueueWriteMappableBuffer) {
    wgpu::BufferDescriptor descriptor;
    descriptor.size = 4;
    descriptor.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopyDst |
                       wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::Uniform;
    wgpu::Buffer buffer = device.CreateBuffer(&descriptor);

    uint32_t myData = 0x12345678;
    constexpr size_t kSize = sizeof(myData);
    queue.WriteBuffer(buffer, 0, &myData, kSize);

    EXPECT_BUFFER_U32_EQ(myData, buffer, 0);
}

// Test that mapping a vertex buffer, modifying the data then draw with the buffer works.
TEST_P(BufferMapExtendedUsagesTests, MapWriteVertexBufferAndDraw) {
    const utils::RGBA8 kReds[] = {utils::RGBA8::kRed, utils::RGBA8::kRed, utils::RGBA8::kRed};
    const utils::RGBA8 kGreens[] = {utils::RGBA8::kGreen, utils::RGBA8::kGreen,
                                    utils::RGBA8::kGreen};

    // Create buffer with initial red color data.
    wgpu::Buffer vertexBuffer = CreateBufferFromData(
        kReds, sizeof(kReds), wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::Vertex);

    wgpu::RenderPipeline renderPipeline = CreateRenderPipelineForTest(ColorSrc::VertexBuffer);

    auto redRenderPass = utils::CreateBasicRenderPass(device, 1, 1);
    auto greenRenderPass = utils::CreateBasicRenderPass(device, 1, 1);

    // First render pass: draw with red color vertex buffer.
    EncodeAndSubmitRenderPassForTest(redRenderPass.renderPassInfo, renderPipeline, vertexBuffer,
                                     nullptr, nullptr);

    // Second render pass: draw with green color vertex buffer.
    MapAsyncAndWait(vertexBuffer, wgpu::MapMode::Write, 0, sizeof(kGreens));
    ASSERT_NE(nullptr, vertexBuffer.GetMappedRange());
    memcpy(vertexBuffer.GetMappedRange(), kGreens, sizeof(kGreens));
    vertexBuffer.Unmap();

    EncodeAndSubmitRenderPassForTest(greenRenderPass.renderPassInfo, renderPipeline, vertexBuffer,
                                     nullptr, nullptr);

    EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kRed, redRenderPass.color, 0, 0);
    EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kGreen, greenRenderPass.color, 0, 0);
}

// Test that mapping a index buffer, modifying the data then draw with the buffer works.
TEST_P(BufferMapExtendedUsagesTests, MapWriteIndexBufferAndDraw) {
    const utils::RGBA8 kVertexColors[] = {
        utils::RGBA8::kRed,   utils::RGBA8::kRed,   utils::RGBA8::kRed,
        utils::RGBA8::kGreen, utils::RGBA8::kGreen, utils::RGBA8::kGreen,
    };
    // Last index is unused. It is only to make sure the index buffer's size is multiple of 4.
    const uint16_t kRedIndices[] = {0, 1, 2, 0};
    const uint16_t kGreenIndices[] = {3, 4, 5, 3};

    wgpu::Buffer vertexBuffer =
        CreateBufferFromData(kVertexColors, sizeof(kVertexColors), wgpu::BufferUsage::Vertex);
    wgpu::Buffer indexBuffer = CreateBufferFromData(
        kRedIndices, sizeof(kRedIndices), wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::Index);

    wgpu::RenderPipeline renderPipeline = CreateRenderPipelineForTest(ColorSrc::VertexBuffer);

    auto redRenderPass = utils::CreateBasicRenderPass(device, 1, 1);
    auto greenRenderPass = utils::CreateBasicRenderPass(device, 1, 1);

    // First render pass: draw with red color index buffer.
    EncodeAndSubmitRenderPassForTest(redRenderPass.renderPassInfo, renderPipeline, vertexBuffer,
                                     indexBuffer, nullptr);

    // Second render pass: draw with green color index buffer.
    MapAsyncAndWait(indexBuffer, wgpu::MapMode::Write, 0, sizeof(kGreenIndices));
    ASSERT_NE(nullptr, indexBuffer.GetMappedRange());
    memcpy(indexBuffer.GetMappedRange(), kGreenIndices, sizeof(kGreenIndices));
    indexBuffer.Unmap();

    EncodeAndSubmitRenderPassForTest(greenRenderPass.renderPassInfo, renderPipeline, vertexBuffer,
                                     indexBuffer, nullptr);

    EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kRed, redRenderPass.color, 0, 0);
    EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kGreen, greenRenderPass.color, 0, 0);
}

// Test that mapping an occlusion QueryResolve buffer then draw with the buffer then mapping again
// works.
TEST_P(BufferMapExtendedUsagesTests, MapWriteQueryBufferThenDrawThenMapWrite) {
    constexpr uint64_t kExpectedVal2 = 1;
    constexpr uint64_t kExpectedVal3 = 2;
    constexpr size_t kQueryResolveBufferSize = 3 * sizeof(uint64_t);
    const utils::RGBA8 kReds[] = {utils::RGBA8::kRed, utils::RGBA8::kRed, utils::RGBA8::kRed};

    // Create buffer with initial red color data.
    wgpu::Buffer vertexBuffer =
        CreateBufferFromData(kReds, sizeof(kReds), wgpu::BufferUsage::Vertex);

    wgpu::RenderPipeline renderPipeline = CreateRenderPipelineForTest(ColorSrc::VertexBuffer);

    // Create Occlusion Query Set
    wgpu::QuerySet querySet;
    {
        wgpu::QuerySetDescriptor descriptor;
        descriptor.count = 1;
        descriptor.type = wgpu::QueryType::Occlusion;
        querySet = device.CreateQuerySet(&descriptor);
    }

    // Create QueryResolve buffer with 2nd expected value written to 2nd uint64_t element.
    wgpu::Buffer queryBuffer;
    {
        constexpr uint64_t kInitialData[] = {0, kExpectedVal2, 0};
        queryBuffer =
            CreateBufferFromData(kInitialData, sizeof(kInitialData),
                                 wgpu::BufferUsage::QueryResolve | wgpu::BufferUsage::MapWrite |
                                     wgpu::BufferUsage::CopySrc);
    }

    // Draw with occlusion query resolved to 1st uint64_t element.
    {
        auto renderPass = utils::CreateBasicRenderPass(device, 1, 1);
        renderPass.renderPassInfo.occlusionQuerySet = querySet;
        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder renderPassEncoder =
            commandEncoder.BeginRenderPass(&renderPass.renderPassInfo);
        renderPassEncoder.SetPipeline(renderPipeline);
        renderPassEncoder.SetVertexBuffer(0, vertexBuffer);
        renderPassEncoder.BeginOcclusionQuery(0);
        renderPassEncoder.Draw(3);
        renderPassEncoder.EndOcclusionQuery();
        renderPassEncoder.End();

        commandEncoder.ResolveQuerySet(querySet, 0, 1, queryBuffer, 0);

        wgpu::CommandBuffer commands = commandEncoder.Finish();
        queue.Submit(1, &commands);
    }

    // Map write to 3rd uint64_t element
    {
        constexpr size_t k3rdElemOffset = 2 * sizeof(uint64_t);
        MapAsyncAndWait(queryBuffer, wgpu::MapMode::Write, 0, kQueryResolveBufferSize);
        ASSERT_NE(nullptr, queryBuffer.GetMappedRange());
        memcpy(queryBuffer.GetMappedRange(k3rdElemOffset), &kExpectedVal3, sizeof(kExpectedVal3));
        queryBuffer.Unmap();
    }

    class NonZeroExpectation : public detail::Expectation {
      public:
        testing::AssertionResult Check(const void* data, size_t size) override {
            DAWN_ASSERT(size % sizeof(uint64_t) == 0);
            const uint64_t* actual = static_cast<const uint64_t*>(data);

            if (actual[0] == 0) {
                return testing::AssertionFailure() << "Expected data[0] to be non-zero.\n";
            }

            return testing::AssertionSuccess();
        }
    };

    EXPECT_BUFFER(queryBuffer, 0, sizeof(uint64_t), new NonZeroExpectation());
    EXPECT_BUFFER_U64_EQ(kExpectedVal2, queryBuffer, sizeof(uint64_t));
    EXPECT_BUFFER_U64_EQ(kExpectedVal3, queryBuffer, 2 * sizeof(uint64_t));
}

// Test that mapping a uniform buffer, modifying the data then draw with the buffer works.
TEST_P(BufferMapExtendedUsagesTests, MapWriteUniformBufferAndDraw) {
    const float kRed[] = {1.0f, 0.0f, 0.0f, 1.0f};
    const float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};

    // Create buffer with initial red color data.
    wgpu::Buffer uniformBuffer = CreateBufferFromData(
        &kRed, sizeof(kRed), wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::Uniform);

    wgpu::RenderPipeline renderPipeline = CreateRenderPipelineForTest(ColorSrc::UniformBuffer);
    wgpu::BindGroup uniformsBindGroup = utils::MakeBindGroup(
        device, renderPipeline.GetBindGroupLayout(0), {{0, uniformBuffer, 0, sizeof(kRed)}});

    auto redRenderPass = utils::CreateBasicRenderPass(device, 1, 1);
    auto greenRenderPass = utils::CreateBasicRenderPass(device, 1, 1);

    // First render pass: draw with red color uniform buffer.
    EncodeAndSubmitRenderPassForTest(redRenderPass.renderPassInfo, renderPipeline, nullptr, nullptr,
                                     uniformsBindGroup);

    // Second render pass: draw with green color uniform buffer.
    MapAsyncAndWait(uniformBuffer, wgpu::MapMode::Write, 0, sizeof(kGreen));
    ASSERT_NE(nullptr, uniformBuffer.GetMappedRange());
    memcpy(uniformBuffer.GetMappedRange(), &kGreen, sizeof(kGreen));
    uniformBuffer.Unmap();

    EncodeAndSubmitRenderPassForTest(greenRenderPass.renderPassInfo, renderPipeline, nullptr,
                                     nullptr, uniformsBindGroup);

    EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kRed, redRenderPass.color, 0, 0);
    EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kGreen, greenRenderPass.color, 0, 0);
}

// Test that mapping a storage buffer, modifying the data then draw with the buffer works.
TEST_P(BufferMapExtendedUsagesTests, MapWriteStorageBufferAndDraw) {
    const float kRed[] = {1.0f, 0.0f, 0.0f, 1.0f};
    const float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};

    DAWN_TEST_UNSUPPORTED_IF(GetSupportedLimits().maxStorageBuffersInVertexStage < 1);

    // Create buffer with initial red color data.
    wgpu::Buffer storageBuffer = CreateBufferFromData(
        &kRed, sizeof(kRed), wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::Storage);

    wgpu::RenderPipeline renderPipeline = CreateRenderPipelineForTest(ColorSrc::StorageBuffer);
    wgpu::BindGroup uniformsBindGroup = utils::MakeBindGroup(
        device, renderPipeline.GetBindGroupLayout(0), {{0, storageBuffer, 0, sizeof(kRed)}});

    auto redRenderPass = utils::CreateBasicRenderPass(device, 1, 1);
    auto greenRenderPass = utils::CreateBasicRenderPass(device, 1, 1);

    // First render pass: draw with red color uniform buffer.
    EncodeAndSubmitRenderPassForTest(redRenderPass.renderPassInfo, renderPipeline, nullptr, nullptr,
                                     uniformsBindGroup);

    // Second render pass: draw with green color uniform buffer.
    MapAsyncAndWait(storageBuffer, wgpu::MapMode::Write, 0, sizeof(kGreen));
    ASSERT_NE(nullptr, storageBuffer.GetMappedRange());
    memcpy(storageBuffer.GetMappedRange(), &kGreen, sizeof(kGreen));
    storageBuffer.Unmap();

    EncodeAndSubmitRenderPassForTest(greenRenderPass.renderPassInfo, renderPipeline, nullptr,
                                     nullptr, uniformsBindGroup);

    EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kRed, redRenderPass.color, 0, 0);
    EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kGreen, greenRenderPass.color, 0, 0);
}

// Test that map write a storage buffer, modifying it on GPU, then map read it on CPU works.
TEST_P(BufferMapExtendedUsagesTests, MapWriteThenGPUWriteStorageBufferThenMapRead) {
    const uint32_t kInitialValue = 1;
    const uint32_t kExpectedValue = 2;
    constexpr size_t kSize = sizeof(kExpectedValue);

    wgpu::ComputePipeline pipeline;
    {
        wgpu::ComputePipelineDescriptor csDesc;
        csDesc.compute.module = utils::CreateShaderModule(device, R"(
            struct SSBO {
                value : u32
            }
            @group(0) @binding(0) var<storage, read_write> ssbo : SSBO;

            @compute @workgroup_size(1) fn main() {
                ssbo.value += 1u;
            })");

        pipeline = device.CreateComputePipeline(&csDesc);
    }

    // Create buffer and write initial value.
    wgpu::Buffer ssbo;
    {
        wgpu::BufferDescriptor descriptor;
        descriptor.size = kSize;

        descriptor.usage =
            wgpu::BufferUsage::Storage | wgpu::BufferUsage::MapRead | wgpu::BufferUsage::MapWrite;
        ssbo = device.CreateBuffer(&descriptor);

        MapAsyncAndWait(ssbo, wgpu::MapMode::Write, 0, 4);
        ASSERT_NE(nullptr, ssbo.GetMappedRange());
        memcpy(ssbo.GetMappedRange(), &kInitialValue, sizeof(kInitialValue));
        ssbo.Unmap();
    }

    // Modify the buffer's value in compute shader.
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();

        ASSERT_NE(nullptr, pipeline.Get());
        wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                                         {
                                                             {0, ssbo, 0, kSize},
                                                         });
        pass.SetBindGroup(0, bindGroup);
        pass.SetPipeline(pipeline);
        pass.DispatchWorkgroups(1);
        pass.End();

        wgpu::CommandBuffer commands = encoder.Finish();

        queue.Submit(1, &commands);
    }

    // Read the modified value.
    MapAsyncAndWait(ssbo, wgpu::MapMode::Read, 0, 4);
    CheckMapping(ssbo.GetConstMappedRange(0, kSize), &kExpectedValue, kSize);
    ssbo.Unmap();
}

// Test the follow scenario:
// - map write a buffer
// - modifying it on GPU.
// - map write it again.
// - draw using the buffer.
void BufferMapExtendedUsagesTests::MixMapWriteAndGPUWriteBufferThenDraw(ColorSrc colorSrc) {
    const float kRed[] = {1.0f, 0.0f, 0.0f, 1.0f};
    const float kFinalColor[] = {1.0f, 1.0f, 1.0f, 1.0f};
    constexpr size_t kSize = sizeof(kFinalColor);

    // Create buffer with initial red color data.
    wgpu::Buffer ssbo;
    {
        wgpu::BufferUsage usage =
            wgpu::BufferUsage::Storage | wgpu::BufferUsage::MapRead | wgpu::BufferUsage::MapWrite;

        switch (colorSrc) {
            case ColorSrc::UniformBuffer:
                usage |= wgpu::BufferUsage::Uniform;
                break;
            case ColorSrc::VertexBuffer:
                usage |= wgpu::BufferUsage::Vertex;
                break;
            case ColorSrc::StorageBuffer:
                // already include
                break;
        }
        ssbo = CreateBufferFromData(&kRed, kSize, usage);
    }

    // Compute pipeline
    wgpu::ComputePipeline pipeline;
    {
        wgpu::ComputePipelineDescriptor csDesc;
        csDesc.compute.module = utils::CreateShaderModule(device, R"(
            @group(0) @binding(0) var<storage, read_write> ssbo : vec4f;
            @compute @workgroup_size(1) fn main() {
                ssbo.g = 1.0;
            })");

        pipeline = device.CreateComputePipeline(&csDesc);
    }

    // Modify the buffer's green channel in compute shader.
    {
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();

        ASSERT_NE(nullptr, pipeline.Get());
        wgpu::BindGroup ssboWritebindGroup =
            utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                 {
                                     {0, ssbo, 0, kSize},
                                 });
        pass.SetBindGroup(0, ssboWritebindGroup);
        pass.SetPipeline(pipeline);
        pass.DispatchWorkgroups(1);
        pass.End();

        wgpu::CommandBuffer commands = encoder.Finish();

        queue.Submit(1, &commands);
    }

    // MapWrite and modify the buffer's blue channel
    {
        const float kOne = 1.0f;
        constexpr size_t kBlueChannelOffset = 2 * sizeof(float);
        MapAsyncAndWait(ssbo, wgpu::MapMode::Write, 0, kSize);
        ASSERT_NE(nullptr, ssbo.GetMappedRange());
        memcpy(ssbo.GetMappedRange(kBlueChannelOffset), &kOne, sizeof(kOne));
        ssbo.Unmap();
    }

    // Draw using the color from the buffer.
    {
        // Render pipeline
        wgpu::RenderPipeline renderPipeline = CreateRenderPipelineForTest(
            colorSrc, wgpu::VertexStepMode::Instance, wgpu::VertexFormat::Float32x4);

        wgpu::Buffer vertexBuffer;
        wgpu::BindGroup ssboReadBindGroup;
        switch (colorSrc) {
            case ColorSrc::VertexBuffer:
                vertexBuffer = ssbo;
                break;
            case ColorSrc::UniformBuffer:
            case ColorSrc::StorageBuffer:
                ssboReadBindGroup = utils::MakeBindGroup(
                    device, renderPipeline.GetBindGroupLayout(0), {{0, ssbo, 0, kSize}});
                break;
        }

        auto finalRenderPass = utils::CreateBasicRenderPass(device, 1, 1);
        EncodeAndSubmitRenderPassForTest(finalRenderPass.renderPassInfo, renderPipeline,
                                         vertexBuffer, nullptr, ssboReadBindGroup);

        EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kWhite, finalRenderPass.color, 0, 0);
    }

    // Read the final value.
    MapAsyncAndWait(ssbo, wgpu::MapMode::Read, 0, kSize);
    CheckMapping(ssbo.GetConstMappedRange(0, kSize), &kFinalColor, kSize);
    ssbo.Unmap();
}

TEST_P(BufferMapExtendedUsagesTests, MixMapWriteAndGPUWriteVertexBufferThenDraw) {
    MixMapWriteAndGPUWriteBufferThenDraw(ColorSrc::VertexBuffer);
}

TEST_P(BufferMapExtendedUsagesTests, MixMapWriteAndGPUWriteUniformBufferThenDraw) {
    MixMapWriteAndGPUWriteBufferThenDraw(ColorSrc::UniformBuffer);
}

TEST_P(BufferMapExtendedUsagesTests, MixMapWriteAndGPUWriteStorageBufferThenDraw) {
    DAWN_TEST_UNSUPPORTED_IF(GetSupportedLimits().maxStorageBuffersInVertexStage < 1);
    MixMapWriteAndGPUWriteBufferThenDraw(ColorSrc::StorageBuffer);
}

// Test the follow scenario:
// - map write a storage buffer
// - modifying it on GPU.
// - copy another buffer to the storage buffer.
// - draw using the storage buffer.
TEST_P(BufferMapExtendedUsagesTests,
       MapWriteThenGPUWriteStorageBufferThenCopyFromAnotherBufferThenDraw) {
    DAWN_TEST_UNSUPPORTED_IF(GetSupportedLimits().maxStorageBuffersInVertexStage < 1);

    const float kRed[] = {1.0f, 0.0f, 0.0f, 1.0f};
    const float kBlue[] = {0.0f, 0.0f, 1.0f, 1.0f};
    const float kFinalColor[] = {1.0f, 1.0f, 1.0f, 1.0f};
    constexpr size_t kSize = sizeof(kFinalColor);

    // Create buffer with initial red color data.
    wgpu::Buffer ssbo;
    {
        wgpu::BufferDescriptor descriptor;
        descriptor.size = kSize;

        descriptor.usage =
            wgpu::BufferUsage::Storage | wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopyDst;
        ssbo = device.CreateBuffer(&descriptor);

        MapAsyncAndWait(ssbo, wgpu::MapMode::Write, 0, kSize);
        ASSERT_NE(nullptr, ssbo.GetMappedRange());
        memcpy(ssbo.GetMappedRange(), &kRed, kSize);
        ssbo.Unmap();
    }
    // Create buffer with blue color data.
    wgpu::Buffer blueBuffer =
        utils::CreateBufferFromData(device, &kBlue, sizeof(kBlue), wgpu::BufferUsage::CopySrc);

    // Compute pipeline
    wgpu::ComputePipeline pipeline;
    {
        wgpu::ComputePipelineDescriptor csDesc;
        csDesc.compute.module = utils::CreateShaderModule(device, R"(
            @group(0) @binding(0) var<storage, read_write> ssbo : vec4f;
            @compute @workgroup_size(1) fn main() {
                ssbo.g = 1.0;
            })");

        pipeline = device.CreateComputePipeline(&csDesc);
    }

    // Modify the buffer's green channel in compute shader.

    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    {
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();

        ASSERT_NE(nullptr, pipeline.Get());
        wgpu::BindGroup ssboWritebindGroup =
            utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                 {
                                     {0, ssbo, 0, kSize},
                                 });
        pass.SetBindGroup(0, ssboWritebindGroup);
        pass.SetPipeline(pipeline);
        pass.DispatchWorkgroups(1);
        pass.End();
    }

    // Modify the buffer's blue channel with CopyB2B
    {
        constexpr size_t kBlueChannelOffset = 2 * sizeof(float);
        encoder.CopyBufferToBuffer(blueBuffer, kBlueChannelOffset, ssbo, kBlueChannelOffset,
                                   sizeof(float));
    }

    // Draw using the color from the buffer.
    {
        // Render pipeline
        wgpu::RenderPipeline renderPipeline = CreateRenderPipelineForTest(ColorSrc::StorageBuffer);
        wgpu::BindGroup ssboReadBindGroup = utils::MakeBindGroup(
            device, renderPipeline.GetBindGroupLayout(0), {{0, ssbo, 0, kSize}});

        auto finalRenderPass = utils::CreateBasicRenderPass(device, 1, 1);
        EncodeAndSubmitRenderPassForTest(finalRenderPass.renderPassInfo, renderPipeline, nullptr,
                                         nullptr, ssboReadBindGroup, std::move(encoder));

        EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kWhite, finalRenderPass.color, 0, 0);
    }
}

DAWN_INSTANTIATE_TEST(BufferMapExtendedUsagesTests,
                      D3D11Backend(),
                      D3D11Backend({"d3d11_disable_map_on_default_buffers"}),
                      D3D11Backend({"auto_map_backend_buffer", "d3d11_disable_cpu_buffers"}),
                      D3D12Backend(),
                      MetalBackend(),
                      OpenGLBackend(),
                      OpenGLESBackend(),
                      OpenGLESBackend({"gl_defer"}),
                      VulkanBackend(),
                      WebGPUBackend());

}  // anonymous namespace
}  // namespace dawn
