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

#include <limits>
#include <memory>
#include <vector>

#include "dawn/common/Platform.h"
#include "dawn/tests/MockCallback.h"
#include "dawn/tests/unittests/validation/ValidationTest.h"
#include "gmock/gmock.h"

using testing::_;
using testing::HasSubstr;
using testing::MockCppCallback;
using testing::TestParamInfo;
using testing::Values;
using testing::WithParamInterface;

using MockMapAsyncCallback = MockCppCallback<void (*)(wgpu::MapAsyncStatus, wgpu::StringView)>;

class BufferValidationTest : public ValidationTest {
  protected:
    wgpu::Buffer CreateMapReadBuffer(uint64_t size) {
        wgpu::BufferDescriptor descriptor;
        descriptor.size = size;
        descriptor.usage = wgpu::BufferUsage::MapRead;

        return device.CreateBuffer(&descriptor);
    }

    wgpu::Buffer CreateMapWriteBuffer(uint64_t size) {
        wgpu::BufferDescriptor descriptor;
        descriptor.size = size;
        descriptor.usage = wgpu::BufferUsage::MapWrite;

        return device.CreateBuffer(&descriptor);
    }

    wgpu::Buffer BufferMappedAtCreation(uint64_t size, wgpu::BufferUsage usage) {
        wgpu::BufferDescriptor descriptor;
        descriptor.size = size;
        descriptor.usage = usage;
        descriptor.mappedAtCreation = true;

        return device.CreateBuffer(&descriptor);
    }

    wgpu::Queue queue;

    void SetUp() override {
        ValidationTest::SetUp();
        queue = device.GetQueue();
    }
};

// Test case where creation should succeed
TEST_F(BufferValidationTest, CreationSuccess) {
    // Success
    {
        wgpu::BufferDescriptor descriptor;
        descriptor.size = 4;
        descriptor.usage = wgpu::BufferUsage::Uniform;

        device.CreateBuffer(&descriptor);
    }
}

// Test case where creation should succeed
TEST_F(BufferValidationTest, CreationMaxBufferSize) {
    // Success when at limit
    {
        wgpu::BufferDescriptor descriptor;
        descriptor.size = GetSupportedLimits().maxBufferSize;
        descriptor.usage = wgpu::BufferUsage::Uniform;

        device.CreateBuffer(&descriptor);
    }
    // Error once it is pass the (default) limit on the device. (Note that MaxLimitTests tests at
    // max possible limit given the adapters.)
    {
        wgpu::BufferDescriptor descriptor;
        ASSERT_TRUE(GetSupportedLimits().maxBufferSize < std::numeric_limits<uint32_t>::max());
        descriptor.size = GetSupportedLimits().maxBufferSize + 1;
        descriptor.usage = wgpu::BufferUsage::Uniform;

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

// Test restriction on usages must not be None (0)
TEST_F(BufferValidationTest, CreationMapUsageNotZero) {
    // Zero (None) usage is an error
    {
        wgpu::BufferDescriptor descriptor;
        descriptor.size = 4;
        descriptor.usage = wgpu::BufferUsage::None;

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

// Test restriction on usages allowed with MapRead and MapWrite
TEST_F(BufferValidationTest, CreationMapUsageRestrictions) {
    // MapRead with CopyDst is ok
    {
        wgpu::BufferDescriptor descriptor;
        descriptor.size = 4;
        descriptor.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;

        device.CreateBuffer(&descriptor);
    }

    // MapRead with something else is an error
    {
        wgpu::BufferDescriptor descriptor;
        descriptor.size = 4;
        descriptor.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::Uniform;

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

    // MapWrite with CopySrc is ok
    {
        wgpu::BufferDescriptor descriptor;
        descriptor.size = 4;
        descriptor.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::CopySrc;

        device.CreateBuffer(&descriptor);
    }

    // MapWrite with something else is an error
    {
        wgpu::BufferDescriptor descriptor;
        descriptor.size = 4;
        descriptor.usage = wgpu::BufferUsage::MapWrite | wgpu::BufferUsage::Uniform;

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

class BufferMappingValidationTest : public BufferValidationTest,
                                    public WithParamInterface<wgpu::MapMode> {
  protected:
    wgpu::Buffer CreateBuffer(uint64_t size) {
        switch (GetParam()) {
            case wgpu::MapMode::Read:
                return CreateMapReadBuffer(size);
            case wgpu::MapMode::Write:
                return CreateMapWriteBuffer(size);
            default:
                DAWN_UNREACHABLE();
        }
        DAWN_UNREACHABLE();
    }

    wgpu::Buffer CreateMappedAtCreationBuffer(uint64_t size) {
        switch (GetParam()) {
            case wgpu::MapMode::Read:
                return BufferMappedAtCreation(size, wgpu::BufferUsage::MapRead);
            case wgpu::MapMode::Write:
                return BufferMappedAtCreation(size, wgpu::BufferUsage::MapWrite);
            default:
                DAWN_UNREACHABLE();
        }
        DAWN_UNREACHABLE();
    }

    void AssertMapAsyncError(wgpu::Buffer buffer,
                             wgpu::MapMode mode,
                             size_t offset,
                             size_t size,
                             bool deviceError = true) {
        // We use a new mock callback here so that the validation on the call happens as soon as the
        // scope of this call ends. This is possible since we are using Spontaneous mode.
        MockMapAsyncCallback mockCb;

        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Error, _)).Times(1);
        if (deviceError) {
            ASSERT_DEVICE_ERROR(buffer.MapAsync(
                mode, offset, size, wgpu::CallbackMode::AllowSpontaneous, mockCb.Callback()));
        } else {
            buffer.MapAsync(mode, offset, size, wgpu::CallbackMode::AllowSpontaneous,
                            mockCb.Callback());
        }
    }
};

INSTANTIATE_TEST_SUITE_P(,
                         BufferMappingValidationTest,
                         testing::Values(wgpu::MapMode::Read, wgpu::MapMode::Write),
                         [](const TestParamInfo<BufferMappingValidationTest::ParamType>& info) {
                             switch (info.param) {
                                 case wgpu::MapMode::Read:
                                     return "Read";
                                 case wgpu::MapMode::Write:
                                     return "Write";
                                 default:
                                     DAWN_UNREACHABLE();
                             }
                             DAWN_UNREACHABLE();
                         });

// Test the success case for mapping buffer.
TEST_P(BufferMappingValidationTest, MapAsync_Success) {
    wgpu::Buffer buffer = CreateBuffer(4);

    MockMapAsyncCallback mockCb;
    EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);

    buffer.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback());
    WaitForAllOperations();
    buffer.Unmap();
}

// Test map async with a buffer that's an error
TEST_P(BufferMappingValidationTest, MapAsync_ErrorBuffer) {
    wgpu::BufferDescriptor desc;
    desc.size = 4;
    desc.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::MapWrite;
    wgpu::Buffer buffer;
    ASSERT_DEVICE_ERROR(buffer = device.CreateBuffer(&desc));

    AssertMapAsyncError(buffer, GetParam(), 0, 4);
}

// Test map async with an invalid offset and size alignment.
TEST_P(BufferMappingValidationTest, MapAsync_OffsetSizeAlignment) {
    // Control case, offset aligned to 8 and size to 4 is valid
    {
        wgpu::Buffer buffer = CreateBuffer(12);

        MockMapAsyncCallback mockCb;
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);
        buffer.MapAsync(GetParam(), 8, 4, wgpu::CallbackMode::AllowProcessEvents,
                        mockCb.Callback());
        WaitForAllOperations();
    }

    // Error case, offset aligned to 4 is an error.
    {
        wgpu::Buffer buffer = CreateBuffer(12);
        AssertMapAsyncError(buffer, GetParam(), 4, 4);
    }

    // Error case, size aligned to 2 is an error.
    {
        wgpu::Buffer buffer = CreateBuffer(8);
        AssertMapAsyncError(buffer, GetParam(), 0, 6);
    }
}

// Test map async with an invalid offset and size OOB checks
TEST_P(BufferMappingValidationTest, MapAsync_OffsetSizeOOB) {
    // Valid case: full buffer is ok.
    {
        wgpu::Buffer buffer = CreateBuffer(8);

        MockMapAsyncCallback mockCb;
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);
        buffer.MapAsync(GetParam(), 0, 8, wgpu::CallbackMode::AllowProcessEvents,
                        mockCb.Callback());
        WaitForAllOperations();
    }
    // Valid case: range in the middle of the buffer is ok.
    {
        wgpu::Buffer buffer = CreateBuffer(16);

        MockMapAsyncCallback mockCb;
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);
        buffer.MapAsync(GetParam(), 8, 4, wgpu::CallbackMode::AllowProcessEvents,
                        mockCb.Callback());
        WaitForAllOperations();
    }
    // Valid case: empty range at the end of the buffer is ok.
    {
        wgpu::Buffer buffer = CreateBuffer(8);

        MockMapAsyncCallback mockCb;
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);
        buffer.MapAsync(GetParam(), 8, 0, wgpu::CallbackMode::AllowProcessEvents,
                        mockCb.Callback());
        WaitForAllOperations();
    }

    // Error case, offset is larger than the buffer size (even if size is 0).
    {
        wgpu::Buffer buffer = CreateBuffer(12);
        AssertMapAsyncError(buffer, GetParam(), 16, 0);
    }
    // Error case, offset + size is larger than the buffer
    {
        wgpu::Buffer buffer = CreateBuffer(12);
        AssertMapAsyncError(buffer, GetParam(), 8, 8);
    }
    // Error case, offset + size is larger than the buffer, overflow case.
    {
        wgpu::Buffer buffer = CreateBuffer(12);
        AssertMapAsyncError(buffer, GetParam(), 8, std::numeric_limits<size_t>::max() & ~size_t(7));
    }
}

// Test map async with a buffer that has the wrong usage
TEST_P(BufferMappingValidationTest, MapAsync_WrongUsage) {
    {
        wgpu::BufferDescriptor desc;
        desc.usage = wgpu::BufferUsage::Vertex;
        desc.size = 4;
        wgpu::Buffer buffer = device.CreateBuffer(&desc);

        AssertMapAsyncError(buffer, GetParam(), 0, 4);
    }
    {
        wgpu::Buffer buffer =
            GetParam() == wgpu::MapMode::Read ? CreateMapWriteBuffer(4) : CreateMapReadBuffer(4);
        AssertMapAsyncError(buffer, GetParam(), 0, 4);
    }
}

// Test map async with a wrong mode
TEST_P(BufferMappingValidationTest, MapAsync_WrongMode) {
    {
        wgpu::Buffer buffer = CreateBuffer(4);
        AssertMapAsyncError(buffer, wgpu::MapMode::None, 0, 4);
    }
    {
        wgpu::Buffer buffer = CreateBuffer(4);
        AssertMapAsyncError(buffer, wgpu::MapMode::Read | wgpu::MapMode::Write, 0, 4);
    }
}

// Test map async with a buffer that's already mapped
TEST_P(BufferMappingValidationTest, MapAsync_AlreadyMapped) {
    {
        wgpu::Buffer buffer = CreateBuffer(4);

        MockMapAsyncCallback mockCb;
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);
        buffer.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents,
                        mockCb.Callback());
        WaitForAllOperations();

        AssertMapAsyncError(buffer, GetParam(), 0, 4);
    }
    {
        wgpu::Buffer buffer = CreateMappedAtCreationBuffer(4);
        AssertMapAsyncError(buffer, GetParam(), 0, 4);
    }
}

// Test MapAsync() immediately causes a pending map error
TEST_P(BufferMappingValidationTest, MapAsync_PendingMap) {
    // TODO(crbug.com/42241221): Inject a validation error from the wire client, so that behavior
    // is consistent between native and wire.
    bool validationError = !UsesWire();

    // Overlapping range
    {
        wgpu::Buffer buffer = CreateBuffer(4);

        // The first map async call should succeed while the second one should fail
        MockMapAsyncCallback mockCb;
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);
        buffer.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents,
                        mockCb.Callback());

        AssertMapAsyncError(buffer, GetParam(), 0, 4, validationError);
        WaitForAllOperations();
    }

    // Non-overlapping range
    {
        wgpu::Buffer buffer = CreateBuffer(16);

        // The first map async call should succeed while the second one should fail
        MockMapAsyncCallback mockCb;
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);
        buffer.MapAsync(GetParam(), 0, 8, wgpu::CallbackMode::AllowProcessEvents,
                        mockCb.Callback());

        AssertMapAsyncError(buffer, GetParam(), 8, 8, validationError);
        WaitForAllOperations();
    }
}

// Test map async with a buffer that's destroyed
TEST_P(BufferMappingValidationTest, MapAsync_Destroy) {
    wgpu::Buffer buffer = CreateBuffer(4);
    buffer.Destroy();
    AssertMapAsyncError(buffer, GetParam(), 0, 4);
}

// Test map async but unmapping before the result is ready.
TEST_P(BufferMappingValidationTest, MapAsync_UnmapBeforeResult) {
    wgpu::Buffer buffer = CreateBuffer(4);

    MockMapAsyncCallback mockCb;
    EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Aborted, HasSubstr("unmapped"))).Times(1);

    buffer.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback());
    buffer.Unmap();
    WaitForAllOperations();
}

// When a MapAsync is cancelled with Unmap it might still be in flight, test doing a new request
// works as expected and we don't get the cancelled request's data.
TEST_P(BufferMappingValidationTest, MapAsync_UnmapBeforeResultAndMapAgain) {
    wgpu::Buffer buffer = CreateBuffer(16);

    MockMapAsyncCallback mockCb;
    EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Aborted, HasSubstr("unmapped"))).Times(1);
    EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);

    buffer.MapAsync(GetParam(), 0, 8, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback());
    buffer.Unmap();
    buffer.MapAsync(GetParam(), 8, 8, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback());

    WaitForAllOperations();

    // Check that only the second MapAsync had an effect
    ASSERT_EQ(nullptr, buffer.GetConstMappedRange(0));
    ASSERT_NE(nullptr, buffer.GetConstMappedRange(8));
}

// Test map async but destroying before the result is ready.
TEST_P(BufferMappingValidationTest, MapAsync_DestroyBeforeResult) {
    wgpu::Buffer buffer = CreateBuffer(4);

    MockMapAsyncCallback mockCb;
    EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Aborted, HasSubstr("destroyed"))).Times(1);

    buffer.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback());
    buffer.Destroy();
    WaitForAllOperations();
}

// Test map async but dropping the last reference before the result is ready.
TEST_P(BufferMappingValidationTest, MapAsync_DroppedBeforeResult) {
    wgpu::Buffer buffer = CreateBuffer(4);

    MockMapAsyncCallback mockCb;
    EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Aborted, HasSubstr("destroyed"))).Times(1);

    buffer.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback());
    buffer = nullptr;
    WaitForAllOperations();
}

// Test that the MapCallback isn't fired twice when unmap() is called inside the callback
TEST_P(BufferMappingValidationTest, MapAsync_UnmapCalledInCallback) {
    wgpu::Buffer buffer = CreateBuffer(4);

    MockMapAsyncCallback mockCb;
    EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).WillOnce([&] { buffer.Unmap(); });

    buffer.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback());
    WaitForAllOperations();
}

// Test that the MapCallback isn't fired twice when destroy() is called inside the callback
TEST_P(BufferMappingValidationTest, MapAsync_DestroyCalledInCallback) {
    wgpu::Buffer buffer = CreateBuffer(4);

    MockMapAsyncCallback mockCb;
    EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).WillOnce([&] { buffer.Destroy(); });

    buffer.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback());
    WaitForAllOperations();
}

// Test MapAsync call in MapAsync success callback
TEST_P(BufferMappingValidationTest, MapAsync_RetryInSuccessCallback) {
    wgpu::Buffer buffer = CreateBuffer(4);

    MockMapAsyncCallback mockCb;
    EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).WillOnce([&] {
        // MapAsync call on destroyed buffer should be invalid
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Error, HasSubstr("already mapped")))
            .Times(1);
        ASSERT_DEVICE_ERROR(buffer.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowSpontaneous,
                                            mockCb.Callback()));
    });

    buffer.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback());
    WaitForAllOperations();
}

// Test MapAsync call in MapAsync validation error callback
TEST_P(BufferMappingValidationTest, MapAsync_RetryInErrorCallback) {
    wgpu::Buffer buffer = CreateBuffer(4);

    MockMapAsyncCallback mockCb;
    EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Error, _)).WillOnce([&] {
        // Retry with valid parameter and it should succeed
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);
        buffer.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents,
                        mockCb.Callback());
    });

    // Wrong map mode on buffer is invalid and it should reject with validation error
    ASSERT_DEVICE_ERROR(buffer.MapAsync(
        GetParam() == wgpu::MapMode::Read ? wgpu::MapMode::Write : wgpu::MapMode::Read, 0, 4,
        wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback()));
    WaitForAllOperations();
}

// Test MapAsync call in MapAsync unmapped callback
TEST_P(BufferMappingValidationTest, MapAsync_RetryInUnmappedCallback) {
    wgpu::Buffer buffer = CreateBuffer(4);

    MockMapAsyncCallback mockCb;
    EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Aborted, _)).WillOnce([&] {
        // MapAsync call on unmapped buffer should be valid
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);
        buffer.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents,
                        mockCb.Callback());
    });

    buffer.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback());
    buffer.Unmap();
    WaitForAllOperations();
}

// Test MapAsync call in MapAsync destroyed callback
TEST_P(BufferMappingValidationTest, MapAsync_RetryInDestroyedCallback) {
    wgpu::Buffer buffer = CreateBuffer(4);

    MockMapAsyncCallback mockCb;
    EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Aborted, _)).WillOnce([&] {
        // MapAsync call on destroyed buffer should be invalid
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Error, HasSubstr("destroyed"))).Times(1);
        ASSERT_DEVICE_ERROR(buffer.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowSpontaneous,
                                            mockCb.Callback()));
    });

    buffer.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback());
    buffer.Destroy();
    WaitForAllOperations();
}

// Test that destroying the device cancels the mapping operation.
TEST_P(BufferMappingValidationTest, DestroyDeviceWhilePending) {
    wgpu::Buffer buffer = CreateBuffer(4);

    MockMapAsyncCallback mockCb;
    EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Aborted, _)).Times(1);
    buffer.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback());

    ExpectDeviceDestruction();
    device.Destroy();

    WaitForAllOperations();
    ASSERT_EQ(wgpu::BufferMapState::Unmapped, buffer.GetMapState());
}

// Test that destroying the device cancels the mapping operation.
TEST_P(BufferMappingValidationTest, DestroyDeviceAfterMapping) {
    // TODO(https://crbug.com/42240407): Unmap buffers in the wire client when
    // device.Destroy() is called.
    DAWN_SKIP_TEST_IF(UsesWire());

    wgpu::Buffer buffer = CreateBuffer(4);

    MockMapAsyncCallback mockCb;
    EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);
    buffer.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback());
    WaitForAllOperations();

    ASSERT_EQ(wgpu::BufferMapState::Mapped, buffer.GetMapState());

    ExpectDeviceDestruction();
    device.Destroy();

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

// Test the success case for mappedAtCreation
TEST_F(BufferValidationTest, MappedAtCreationSuccess) {
    BufferMappedAtCreation(4, wgpu::BufferUsage::MapWrite);
}

// Test the success case for mappedAtCreation for a non-mappable usage
TEST_F(BufferValidationTest, NonMappableMappedAtCreationSuccess) {
    BufferMappedAtCreation(4, wgpu::BufferUsage::CopySrc);
}

// Test there is an error when mappedAtCreation is set but the size isn't aligned to 4.
TEST_F(BufferValidationTest, MappedAtCreationSizeAlignment) {
    ASSERT_DEVICE_ERROR(BufferMappedAtCreation(2, wgpu::BufferUsage::MapWrite));
}

// Test that if CreateBuffer OOMs while mapping at creation, it returns null.
TEST_F(BufferValidationTest, MappedAtCreationOOM) {
    uint64_t kStupidLarge = uint64_t(1) << uint64_t(63);

    // Buffer would fail validation due to invalid usage combination
    {
        wgpu::Buffer buffer = BufferMappedAtCreation(
            kStupidLarge, wgpu::BufferUsage::Storage | wgpu::BufferUsage::MapRead);
        ASSERT_EQ(nullptr, buffer.Get());
    }

    // Buffer would fail validation due to maxBufferSize
    {
        wgpu::Buffer buffer = BufferMappedAtCreation(
            kStupidLarge, wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead);
        ASSERT_EQ(nullptr, buffer.Get());
    }
}

// Test that destroying the device cancels the mapping operation.
TEST_F(BufferValidationTest, MappedAtCreationThenDestroyDevice) {
    // TODO(https://crbug.com/42240407): Unmap buffers in the wire client when
    // device.Destroy() is called.
    DAWN_SKIP_TEST_IF(UsesWire());

    wgpu::Buffer buffer = BufferMappedAtCreation(4, wgpu::BufferUsage::CopySrc);

    ASSERT_EQ(wgpu::BufferMapState::Mapped, buffer.GetMapState());

    ExpectDeviceDestruction();
    device.Destroy();

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

// Test that it is valid to destroy an error buffer
TEST_F(BufferValidationTest, DestroyErrorBuffer) {
    wgpu::BufferDescriptor desc;
    desc.size = 4;
    desc.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::MapWrite;
    wgpu::Buffer buf;
    ASSERT_DEVICE_ERROR(buf = device.CreateBuffer(&desc));

    buf.Destroy();
}

// Test that it is valid to Destroy an unmapped buffer
TEST_P(BufferMappingValidationTest, DestroyUnmappedBuffer) {
    wgpu::Buffer buffer = CreateBuffer(4);
    buffer.Destroy();
}

// Test that it is valid to Destroy a destroyed buffer
TEST_P(BufferMappingValidationTest, DestroyDestroyedBuffer) {
    wgpu::Buffer buffer = CreateBuffer(4);
    buffer.Destroy();
    buffer.Destroy();
}

// Test that it is valid to Unmap an error buffer
TEST_F(BufferValidationTest, UnmapErrorBuffer) {
    wgpu::BufferDescriptor desc;
    desc.size = 4;
    desc.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::MapWrite;
    wgpu::Buffer buf;
    ASSERT_DEVICE_ERROR(buf = device.CreateBuffer(&desc));

    buf.Unmap();
}

// Test that it is valid to Unmap a destroyed buffer
TEST_P(BufferMappingValidationTest, UnmapDestroyedBuffer) {
    wgpu::Buffer buffer = CreateBuffer(4);
    buffer.Destroy();
    buffer.Unmap();
}

// Test that unmap then mapping a destroyed buffer is an error.
// Regression test for crbug.com/1388920.
TEST_P(BufferMappingValidationTest, MapDestroyedBufferAfterUnmap) {
    wgpu::Buffer buffer = CreateBuffer(4);
    buffer.Destroy();
    buffer.Unmap();

    MockMapAsyncCallback mockCb;
    EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Error, HasSubstr("destroyed"))).Times(1);
    ASSERT_DEVICE_ERROR(buffer.MapAsync(GetParam(), 0, wgpu::kWholeMapSize,
                                        wgpu::CallbackMode::AllowSpontaneous, mockCb.Callback()));

    WaitForAllOperations();
}

// Test that it is valid to submit a buffer in a queue with a map usage if it is unmapped
TEST_F(BufferValidationTest, SubmitBufferWithMapUsage) {
    wgpu::BufferDescriptor descriptorA;
    descriptorA.size = 4;
    descriptorA.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::MapWrite;

    wgpu::BufferDescriptor descriptorB;
    descriptorB.size = 4;
    descriptorB.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead;

    wgpu::Buffer bufA = device.CreateBuffer(&descriptorA);
    wgpu::Buffer bufB = device.CreateBuffer(&descriptorB);

    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    encoder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
    wgpu::CommandBuffer commands = encoder.Finish();
    queue.Submit(1, &commands);
}

// Test that it is invalid to submit a mapped buffer in a queue
TEST_F(BufferValidationTest, SubmitMappedBuffer) {
    wgpu::BufferDescriptor descriptorA;
    descriptorA.size = 4;
    descriptorA.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::MapWrite;

    wgpu::BufferDescriptor descriptorB;
    descriptorB.size = 4;
    descriptorB.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead;
    {
        wgpu::Buffer bufA = device.CreateBuffer(&descriptorA);
        wgpu::Buffer bufB = device.CreateBuffer(&descriptorB);

        MockMapAsyncCallback mockCb;
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);
        bufA.MapAsync(wgpu::MapMode::Write, 0, 4, wgpu::CallbackMode::AllowProcessEvents,
                      mockCb.Callback());

        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        encoder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
        wgpu::CommandBuffer commands = encoder.Finish();
        ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
        WaitForAllOperations();
    }
    {
        wgpu::Buffer bufA = device.CreateBuffer(&descriptorA);
        wgpu::Buffer bufB = device.CreateBuffer(&descriptorB);

        MockMapAsyncCallback mockCb;
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);
        bufB.MapAsync(wgpu::MapMode::Read, 0, 4, wgpu::CallbackMode::AllowProcessEvents,
                      mockCb.Callback());

        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        encoder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
        wgpu::CommandBuffer commands = encoder.Finish();
        ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
        WaitForAllOperations();
    }
    {
        wgpu::BufferDescriptor mappedBufferDesc = descriptorA;
        mappedBufferDesc.mappedAtCreation = true;
        wgpu::Buffer bufA = device.CreateBuffer(&mappedBufferDesc);
        wgpu::Buffer bufB = device.CreateBuffer(&descriptorB);

        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        encoder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
        wgpu::CommandBuffer commands = encoder.Finish();
        ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
        WaitForAllOperations();
    }
    {
        wgpu::BufferDescriptor mappedBufferDesc = descriptorB;
        mappedBufferDesc.mappedAtCreation = true;
        wgpu::Buffer bufA = device.CreateBuffer(&descriptorA);
        wgpu::Buffer bufB = device.CreateBuffer(&mappedBufferDesc);

        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        encoder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
        wgpu::CommandBuffer commands = encoder.Finish();
        ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
        WaitForAllOperations();
    }
}

// Test that it is invalid to submit a destroyed buffer in a queue
TEST_F(BufferValidationTest, SubmitDestroyedBuffer) {
    wgpu::BufferDescriptor descriptorA;
    descriptorA.size = 4;
    descriptorA.usage = wgpu::BufferUsage::CopySrc;

    wgpu::BufferDescriptor descriptorB;
    descriptorB.size = 4;
    descriptorB.usage = wgpu::BufferUsage::CopyDst;

    wgpu::Buffer bufA = device.CreateBuffer(&descriptorA);
    wgpu::Buffer bufB = device.CreateBuffer(&descriptorB);

    bufA.Destroy();
    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    encoder.CopyBufferToBuffer(bufA, 0, bufB, 0, 4);
    wgpu::CommandBuffer commands = encoder.Finish();
    ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
}

// Test that a map usage is not required to call Unmap
TEST_F(BufferValidationTest, UnmapWithoutMapUsage) {
    wgpu::BufferDescriptor descriptor;
    descriptor.size = 4;
    descriptor.usage = wgpu::BufferUsage::CopyDst;
    wgpu::Buffer buf = device.CreateBuffer(&descriptor);

    buf.Unmap();
}

// Test that it is valid to call Unmap on a buffer that is not mapped
TEST_P(BufferMappingValidationTest, UnmapUnmappedBuffer) {
    wgpu::Buffer buffer = CreateBuffer(4);

    // Buffer starts unmapped. Unmap shouldn't fail.
    buffer.Unmap();

    MockMapAsyncCallback mockCb;
    EXPECT_CALL(mockCb, Call).Times(1);
    buffer.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowSpontaneous, mockCb.Callback());
    buffer.Unmap();

    // Unmapping a second time shouldn't fail.
    buffer.Unmap();
}

// Test that it is invalid to call GetMappedRange on an unmapped buffer.
TEST_F(BufferValidationTest, GetMappedRange_OnUnmappedBuffer) {
    {
        // Unmapped at creation case.
        wgpu::BufferDescriptor desc;
        desc.size = 4;
        desc.usage = wgpu::BufferUsage::CopySrc;
        wgpu::Buffer buf = device.CreateBuffer(&desc);

        ASSERT_NO_DEVICE_LOG({
            ASSERT_EQ(nullptr, buf.GetMappedRange());
            ASSERT_EQ(nullptr, buf.GetConstMappedRange());
        });
    }

    // Unmapped after mappedAtCreation case.
    {
        wgpu::Buffer buf = BufferMappedAtCreation(4, wgpu::BufferUsage::CopySrc);
        buf.Unmap();

        ASSERT_EQ(nullptr, buf.GetMappedRange());
        ASSERT_EQ(nullptr, buf.GetConstMappedRange());
    }
}

// Test that it is invalid to call GetMappedRange on an unmapped buffer.
TEST_P(BufferMappingValidationTest, GetMappedRange_OnUnmappedBuffer) {
    // Unmapped after valid mapping.
    wgpu::Buffer buf = CreateBuffer(4);

    MockMapAsyncCallback mockCb;
    EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);
    buf.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback());
    WaitForAllOperations();
    buf.Unmap();

    ASSERT_EQ(nullptr, buf.GetMappedRange());
    ASSERT_EQ(nullptr, buf.GetConstMappedRange());
}

// Test that it is invalid to call GetMappedRange on a destroyed buffer.
TEST_F(BufferValidationTest, GetMappedRange_OnDestroyedBuffer) {
    // Destroyed after creation case.
    {
        wgpu::BufferDescriptor desc;
        desc.size = 4;
        desc.usage = wgpu::BufferUsage::CopySrc;
        wgpu::Buffer buf = device.CreateBuffer(&desc);
        buf.Destroy();

        ASSERT_EQ(nullptr, buf.GetMappedRange());
        ASSERT_EQ(nullptr, buf.GetConstMappedRange());
    }

    // Destroyed after mappedAtCreation case.
    {
        wgpu::Buffer buf = BufferMappedAtCreation(4, wgpu::BufferUsage::CopySrc);
        buf.Destroy();

        ASSERT_EQ(nullptr, buf.GetMappedRange());
        ASSERT_EQ(nullptr, buf.GetConstMappedRange());
    }
}

// Test that it is invalid to call GetMappedRange on a destroyed buffer.
TEST_P(BufferMappingValidationTest, GetMappedRange_OnDestroyedBuffer) {
    // Destroyed after MapAsync case.
    wgpu::Buffer buf = CreateBuffer(4);

    MockMapAsyncCallback mockCb;
    EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);
    buf.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback());
    WaitForAllOperations();
    buf.Destroy();

    ASSERT_EQ(nullptr, buf.GetMappedRange());
    ASSERT_EQ(nullptr, buf.GetConstMappedRange());
}

// Test that it is invalid to call GetMappedRange on a buffer after MapAsync for reading
TEST_F(BufferValidationTest, GetMappedRange_NonConstOnMappedForReading) {
    wgpu::Buffer buf = CreateMapReadBuffer(4);

    MockMapAsyncCallback mockCb;
    EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);
    buf.MapAsync(wgpu::MapMode::Read, 0, 4, wgpu::CallbackMode::AllowProcessEvents,
                 mockCb.Callback());
    WaitForAllOperations();

    ASSERT_DEVICE_LOG(ASSERT_EQ(nullptr, buf.GetMappedRange()), wgpu::LoggingType::Error,
                      testing::HasSubstr("Use GetConstMappedRange instead"));

    ASSERT_NO_DEVICE_LOG(ASSERT_NE(nullptr, buf.GetConstMappedRange()));
}

// Test valid cases to call GetMappedRange on a buffer.
TEST_F(BufferValidationTest, GetMappedRange_ValidBufferStateCases) {
    // GetMappedRange after mappedAtCreation case.
    {
        wgpu::Buffer buffer = BufferMappedAtCreation(4, wgpu::BufferUsage::CopySrc);
        ASSERT_NE(buffer.GetConstMappedRange(), nullptr);
        ASSERT_EQ(buffer.GetConstMappedRange(), buffer.GetMappedRange());
    }
}

// Test valid cases to call GetMappedRange on a buffer.
TEST_P(BufferMappingValidationTest, GetMappedRange_ValidBufferStateCases) {
    // GetMappedRange after MapAsync case.
    wgpu::Buffer buf = CreateBuffer(4);

    MockMapAsyncCallback mockCb;
    EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);
    buf.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback());
    WaitForAllOperations();

    ASSERT_NE(buf.GetConstMappedRange(), nullptr);
    if (GetParam() == wgpu::MapMode::Write) {
        ASSERT_EQ(buf.GetConstMappedRange(), buf.GetMappedRange());
    }
}

// Test valid cases to call GetMappedRange on an error buffer.
// (Note it's impossible to test a buffer that's OOM; CreateBuffer will return null in that case.)
TEST_F(BufferValidationTest, GetMappedRange_OnErrorBuffer) {
    // GetMappedRange after mappedAtCreation a zero-sized buffer returns a non-nullptr.
    // This is to check we don't do a malloc(0).
    {
        wgpu::Buffer buffer;
        ASSERT_DEVICE_ERROR(buffer = BufferMappedAtCreation(
                                0, wgpu::BufferUsage::Storage | wgpu::BufferUsage::MapRead));

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

    // GetMappedRange after mappedAtCreation non-OOM returns a non-nullptr.
    {
        wgpu::Buffer buffer;
        ASSERT_DEVICE_ERROR(buffer = BufferMappedAtCreation(
                                4, wgpu::BufferUsage::Storage | wgpu::BufferUsage::MapRead));

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

// Test validation of the GetMappedRange parameters
TEST_P(BufferMappingValidationTest, GetMappedRange_OffsetSizeOOB) {
    MockMapAsyncCallback mockCb;
    EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(11);

    // Valid case: full range is ok
    {
        wgpu::Buffer buffer = CreateBuffer(8);
        buffer.MapAsync(GetParam(), 0, 8, wgpu::CallbackMode::AllowProcessEvents,
                        mockCb.Callback());
        WaitForAllOperations();
        EXPECT_NE(buffer.GetConstMappedRange(0, 8), nullptr);
    }

    // Valid case: full range is ok with defaulted MapAsync size
    {
        wgpu::Buffer buffer = CreateBuffer(8);
        buffer.MapAsync(GetParam(), 0, wgpu::kWholeMapSize, wgpu::CallbackMode::AllowProcessEvents,
                        mockCb.Callback());
        WaitForAllOperations();
        EXPECT_NE(buffer.GetConstMappedRange(0, 8), nullptr);
    }

    // Valid case: full range is ok with defaulted MapAsync size and defaulted GetMappedRangeSize
    {
        wgpu::Buffer buffer = CreateBuffer(8);
        buffer.MapAsync(GetParam(), 0, wgpu::kWholeMapSize, wgpu::CallbackMode::AllowProcessEvents,
                        mockCb.Callback());
        WaitForAllOperations();
        EXPECT_NE(buffer.GetConstMappedRange(0, wgpu::kWholeMapSize), nullptr);
    }

    // Valid case: empty range at the end is ok
    {
        wgpu::Buffer buffer = CreateBuffer(8);
        buffer.MapAsync(GetParam(), 0, 8, wgpu::CallbackMode::AllowProcessEvents,
                        mockCb.Callback());
        WaitForAllOperations();
        EXPECT_NE(buffer.GetConstMappedRange(8, 0), nullptr);
    }

    // Valid case: range in the middle is ok.
    {
        wgpu::Buffer buffer = CreateBuffer(16);
        buffer.MapAsync(GetParam(), 0, 16, wgpu::CallbackMode::AllowProcessEvents,
                        mockCb.Callback());
        WaitForAllOperations();
        EXPECT_NE(buffer.GetConstMappedRange(8, 4), nullptr);
    }

    // Error case: offset is larger than the mapped range (even with size = 0)
    {
        wgpu::Buffer buffer = CreateBuffer(8);
        buffer.MapAsync(GetParam(), 0, 8, wgpu::CallbackMode::AllowProcessEvents,
                        mockCb.Callback());
        WaitForAllOperations();
        EXPECT_EQ(buffer.GetConstMappedRange(9, 0), nullptr);
        EXPECT_EQ(buffer.GetConstMappedRange(16, 0), nullptr);
        EXPECT_EQ(buffer.GetConstMappedRange(std::numeric_limits<size_t>::max(), 0), nullptr);
    }

    // Error case: offset is larger than the buffer size (even with size = 0)
    {
        wgpu::Buffer buffer = CreateBuffer(16);
        buffer.MapAsync(GetParam(), 8, 8, wgpu::CallbackMode::AllowProcessEvents,
                        mockCb.Callback());
        WaitForAllOperations();
        EXPECT_EQ(buffer.GetConstMappedRange(16, 4), nullptr);
        EXPECT_EQ(buffer.GetConstMappedRange(24, 0), nullptr);
        EXPECT_EQ(buffer.GetConstMappedRange(std::numeric_limits<size_t>::max(), 0), nullptr);
    }

    // Error case: offset + size is larger than the mapped range
    {
        wgpu::Buffer buffer = CreateBuffer(12);
        buffer.MapAsync(GetParam(), 0, 12, wgpu::CallbackMode::AllowProcessEvents,
                        mockCb.Callback());
        WaitForAllOperations();
        EXPECT_EQ(buffer.GetConstMappedRange(8, 5), nullptr);
        EXPECT_EQ(buffer.GetConstMappedRange(8, 8), nullptr);
    }

    // Error case: offset + size is larger than the mapped range, overflow case
    {
        wgpu::Buffer buffer = CreateBuffer(12);
        buffer.MapAsync(GetParam(), 0, 12, wgpu::CallbackMode::AllowProcessEvents,
                        mockCb.Callback());
        WaitForAllOperations();
        // set size to (max - 1) to avoid being equal to kWholeMapSize
        EXPECT_EQ(buffer.GetConstMappedRange(8, std::numeric_limits<size_t>::max() - 1), nullptr);
    }

    // Error case: size is larger than the mapped range when using default kWholeMapSize
    {
        wgpu::Buffer buffer = CreateBuffer(12);
        buffer.MapAsync(GetParam(), 0, 8, wgpu::CallbackMode::AllowProcessEvents,
                        mockCb.Callback());
        WaitForAllOperations();
        EXPECT_EQ(buffer.GetConstMappedRange(0), nullptr);
    }

    // Error case: offset is before the start of the range (even with size = 0)
    {
        wgpu::Buffer buffer = CreateBuffer(12);
        buffer.MapAsync(GetParam(), 8, 4, wgpu::CallbackMode::AllowProcessEvents,
                        mockCb.Callback());
        WaitForAllOperations();
        EXPECT_EQ(buffer.GetConstMappedRange(7, 4), nullptr);
        EXPECT_EQ(buffer.GetConstMappedRange(0, 4), nullptr);
        EXPECT_EQ(buffer.GetConstMappedRange(0, 12), nullptr);
        EXPECT_EQ(buffer.GetConstMappedRange(0, 0), nullptr);
    }
}

// Test that the buffer creation parameters are correctly reflected for succesfully created buffers.
TEST_F(BufferValidationTest, CreationParameterReflectionForValidBuffer) {
    // Test reflection on two succesfully created but different buffers. The reflected data should
    // be different!
    {
        wgpu::BufferDescriptor desc;
        desc.size = 16;
        desc.usage = wgpu::BufferUsage::Uniform;
        wgpu::Buffer buf = device.CreateBuffer(&desc);

        EXPECT_EQ(wgpu::BufferUsage::Uniform, buf.GetUsage());
        EXPECT_EQ(16u, buf.GetSize());
    }
    {
        wgpu::BufferDescriptor desc;
        desc.size = 32;
        desc.usage = wgpu::BufferUsage::Storage;
        wgpu::Buffer buf = device.CreateBuffer(&desc);

        EXPECT_EQ(wgpu::BufferUsage::Storage, buf.GetUsage());
        EXPECT_EQ(32u, buf.GetSize());
    }
}

// Test that the buffer creation parameters are correctly reflected for buffers invalid because of
// validation errors.
TEST_F(BufferValidationTest, CreationParameterReflectionForErrorBuffer) {
    wgpu::BufferDescriptor desc;
    desc.usage = wgpu::BufferUsage::Uniform;
    desc.size = 19;
    desc.mappedAtCreation = true;

    // Error! MappedAtCreation requires size % 4 == 0.
    wgpu::Buffer buf;
    ASSERT_DEVICE_ERROR(buf = device.CreateBuffer(&desc));

    // Reflection data is still exactly what was in the descriptor.
    EXPECT_EQ(wgpu::BufferUsage::Uniform, buf.GetUsage());
    EXPECT_EQ(19u, buf.GetSize());
}

// Test that the buffer creation parameters are correctly reflected for buffers invalid because of
// OOM.
TEST_F(BufferValidationTest, CreationParameterReflectionForOOMBuffer) {
    constexpr uint64_t kAmazinglyLargeSize = 0x1234'5678'90AB'CDEF;
    wgpu::BufferDescriptor desc;
    desc.usage = wgpu::BufferUsage::Storage;
    desc.size = kAmazinglyLargeSize;

    // OOM!
    wgpu::Buffer buf;
    ASSERT_DEVICE_ERROR(buf = device.CreateBuffer(&desc));

    // Reflection data is still exactly what was in the descriptor.
    EXPECT_EQ(wgpu::BufferUsage::Storage, buf.GetUsage());
    EXPECT_EQ(kAmazinglyLargeSize, buf.GetSize());
}

// Test that buffer reflection doesn't show internal usages
TEST_F(BufferValidationTest, CreationParameterReflectionNoInternalUsage) {
    wgpu::BufferDescriptor desc;
    desc.size = 16;
    // QueryResolve also adds kInternalStorageBuffer for processing of queries.
    desc.usage = wgpu::BufferUsage::QueryResolve;
    wgpu::Buffer buf = device.CreateBuffer(&desc);

    // The reflection shouldn't show kInternalStorageBuffer
    EXPECT_EQ(wgpu::BufferUsage::QueryResolve, buf.GetUsage());
    EXPECT_EQ(16u, buf.GetSize());
}

// Test that GetMapState() shows expected buffer map state
TEST_F(BufferValidationTest, GetMapState) {
    // MappedAtCreation + Unmap
    {
        wgpu::Buffer buf = BufferMappedAtCreation(4, wgpu::BufferUsage::CopySrc);
        EXPECT_EQ(wgpu::BufferMapState::Mapped, buf.GetMapState());
        buf.Unmap();
        EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
    }

    // MappedAtCreation + Destroy
    {
        wgpu::Buffer buf = BufferMappedAtCreation(4, wgpu::BufferUsage::CopySrc);
        EXPECT_EQ(wgpu::BufferMapState::Mapped, buf.GetMapState());
        buf.Destroy();
        EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
    }
}

// Test that GetMapState() shows expected buffer map state
TEST_P(BufferMappingValidationTest, GetMapState) {
    // MapAsync + Unmap
    {
        wgpu::Buffer buf = CreateBuffer(4);
        EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());

        MockMapAsyncCallback mockCb;
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);
        buf.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback());
        EXPECT_EQ(wgpu::BufferMapState::Pending, buf.GetMapState());

        WaitForAllOperations();
        EXPECT_EQ(wgpu::BufferMapState::Mapped, buf.GetMapState());

        buf.Unmap();
        EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
    }

    // MapAsync + Unmap before the callback
    {
        wgpu::Buffer buf = CreateBuffer(4);
        EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());

        MockMapAsyncCallback mockCb;
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Aborted, _)).Times(1);
        buf.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback());
        EXPECT_EQ(wgpu::BufferMapState::Pending, buf.GetMapState());

        buf.Unmap();
        EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());

        WaitForAllOperations();
        EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
    }

    // MapAsync + Destroy
    {
        wgpu::Buffer buf = CreateBuffer(4);
        EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());

        MockMapAsyncCallback mockCb;
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1);
        buf.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback());
        EXPECT_EQ(wgpu::BufferMapState::Pending, buf.GetMapState());

        WaitForAllOperations();
        EXPECT_EQ(wgpu::BufferMapState::Mapped, buf.GetMapState());

        buf.Destroy();
        EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
    }

    // MapAsync + Destroy before the callback
    {
        wgpu::Buffer buf = CreateBuffer(4);
        EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());

        MockMapAsyncCallback mockCb;
        EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Aborted, _)).Times(1);
        buf.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback());
        EXPECT_EQ(wgpu::BufferMapState::Pending, buf.GetMapState());

        buf.Destroy();
        EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());

        WaitForAllOperations();
        EXPECT_EQ(wgpu::BufferMapState::Unmapped, buf.GetMapState());
    }
}

class BufferMapExtendedUsagesValidationTest : public BufferValidationTest {
  protected:
    void SetUp() override {
        DAWN_SKIP_TEST_IF(UsesWire());
        BufferValidationTest::SetUp();
    }

    std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
        return {wgpu::FeatureName::BufferMapExtendedUsages};
    }
};

// Test that MapRead or MapWrite can be combined with any other usage when creating
// a buffer.
TEST_F(BufferMapExtendedUsagesValidationTest, CreationMapUsageReadOrWriteNoRestrictions) {
    constexpr wgpu::BufferUsage kNonMapUsages[] = {
        wgpu::BufferUsage::CopySrc,  wgpu::BufferUsage::CopyDst,      wgpu::BufferUsage::Index,
        wgpu::BufferUsage::Vertex,   wgpu::BufferUsage::Uniform,      wgpu::BufferUsage::Storage,
        wgpu::BufferUsage::Indirect, wgpu::BufferUsage::QueryResolve,
    };

    // MapRead with anything is ok
    {
        wgpu::BufferDescriptor descriptor;
        descriptor.size = 4;

        for (const auto otherUsage : kNonMapUsages) {
            descriptor.usage = wgpu::BufferUsage::MapRead | otherUsage;

            device.CreateBuffer(&descriptor);
        }
    }

    // MapWrite with anything is ok
    {
        wgpu::BufferDescriptor descriptor;
        descriptor.size = 4;

        for (const auto otherUsage : kNonMapUsages) {
            descriptor.usage = wgpu::BufferUsage::MapWrite | otherUsage;

            device.CreateBuffer(&descriptor);
        }
    }

    // MapRead | MapWrite with anything is ok
    {
        wgpu::BufferDescriptor descriptor;
        descriptor.size = 4;

        for (const auto otherUsage : kNonMapUsages) {
            descriptor.usage =
                wgpu::BufferUsage::MapRead | wgpu::BufferUsage::MapWrite | otherUsage;

            device.CreateBuffer(&descriptor);
        }
    }
}
