// Copyright 2025 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 <condition_variable>
#include <mutex>
#include <utility>

#include "dawn/common/Log.h"
#include "dawn/common/Ref.h"
#include "dawn/native/Error.h"
#include "dawn/utils/TestUtils.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "mocks/BufferMock.h"
#include "mocks/DawnMockTest.h"

using testing::_;
using testing::ByMove;
using testing::Eq;
using testing::HasSubstr;
using testing::Return;

namespace dawn::native {
namespace {

constexpr size_t kBufferSize = 16;
constexpr std::string_view kValidationErrorMessage = "Concurrent buffer operations are not allowed";

class WaitableEvent {
  public:
    void Signal() {
        std::scoped_lock lock(mMutex);
        mSignaled = true;
        mCv.notify_all();
    }
    void Wait() {
        std::unique_lock<std::mutex> lock(mMutex);
        while (!mSignaled) {
            mCv.wait(lock);
        }
    }

  private:
    std::mutex mMutex;
    std::condition_variable mCv;
    bool mSignaled = false;
};

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

class BufferBaseTest : public DawnMockTest {
  protected:
    void SetUp() override {
        DawnMockTest::SetUp();
        BufferDescriptor desc = {};
        desc.size = kBufferSize;
        desc.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::MapWrite;

        mBufferMock = AcquireRef(new BufferMock(mDeviceMock, &desc));
        EXPECT_CALL(*mDeviceMock, CreateBufferImpl).WillOnce(Return(mBufferMock));
        mBuffer = device.CreateBuffer(ToCppAPI(&desc));
    }

    void TearDown() override {
        mBuffer = {};
        mBufferMock = {};
        DawnMockTest::TearDown();
    }

    Ref<BufferMock> mBufferMock;
    wgpu::Buffer mBuffer;
};

// Test that MapAsyncImpl() throwing an error causes map async callback to return an error status.
TEST_F(BufferBaseTest, MapAsyncImplError) {
    constexpr std::string_view kErrorText = "Platform error";

    EXPECT_CALL(*mBufferMock.Get(), MapAsyncImpl).WillOnce([&]() -> MaybeError {
        return DAWN_FORMAT_INTERNAL_ERROR(kErrorText);
    });

    // Internal error will cause device loss as well.
    EXPECT_CALL(mDeviceLostCallback,
                Call(_, wgpu::DeviceLostReason::Unknown, HasSubstr(kErrorText)));

    MockMapAsyncCallback cb;
    EXPECT_CALL(cb, Call(Eq(wgpu::MapAsyncStatus::Error), Eq(kErrorText)));
    mBuffer.MapAsync(wgpu::MapMode::Write, 0, kBufferSize, wgpu::CallbackMode::AllowSpontaneous,
                     cb.Callback());
}

// Tests calling MapAsync() while the buffer is being used by queue fails.
TEST_F(BufferBaseTest, MapAsyncWhileUsedByQueueFails) {
    EXPECT_CALL(mDeviceErrorCallback,
                Call(_, wgpu::ErrorType::Validation, HasSubstr(kValidationErrorMessage)));

    ResultOrError<BufferBase::ScopedUseBuffer> validate = mBufferMock->ValidateCanUseOnQueueNow();
    ASSERT_TRUE(validate.IsSuccess());
    auto scopedUse = validate.AcquireSuccess();

    MockMapAsyncCallback cb;
    EXPECT_CALL(cb, Call(Eq(wgpu::MapAsyncStatus::Error), _));
    mBuffer.MapAsync(wgpu::MapMode::Write, 0, kBufferSize, wgpu::CallbackMode::AllowSpontaneous,
                     cb.Callback());
}

// Tests calling Unmap() while the buffer is being used by queue fails.
TEST_F(BufferBaseTest, UnmapWhileUsedByQueueFails) {
    EXPECT_CALL(mDeviceErrorCallback,
                Call(_, wgpu::ErrorType::Validation, HasSubstr(kValidationErrorMessage)));

    ResultOrError<BufferBase::ScopedUseBuffer> validate = mBufferMock->ValidateCanUseOnQueueNow();
    ASSERT_TRUE(validate.IsSuccess());
    auto scopedUse = validate.AcquireSuccess();

    mBuffer.Unmap();
}

class BufferBaseThreadedTest : public BufferBaseTest {
  public:
    BufferBaseThreadedTest() : BufferBaseTest() {
        mRequiredFeatures.push_back(wgpu::FeatureName::ImplicitDeviceSynchronization);
    }
};

// Tests calling MapAsync() on one thread and then Unmap() on another thread works.
TEST_F(BufferBaseThreadedTest, MapAsyncThenUnmap) {
    WaitableEvent event;
    EXPECT_CALL(*mBufferMock.Get(), MapAsyncImpl).Times(1);
    EXPECT_CALL(*mBufferMock.Get(), UnmapImpl).Times(1);

    utils::RunInParallel(2, [&](uint32_t index) {
        if (index == 0) {
            MockMapAsyncCallback cb;
            EXPECT_CALL(cb, Call(Eq(wgpu::MapAsyncStatus::Success), _))
                .WillOnce([&event](wgpu::MapAsyncStatus, wgpu::StringView) { event.Signal(); });
            mBuffer.MapAsync(wgpu::MapMode::Write, 0, kBufferSize,
                             wgpu::CallbackMode::AllowSpontaneous, cb.Callback());
        } else {
            event.Wait();
            mBuffer.Unmap();
        }
    });
}

// Tests calling Unmap() on one thread and then Unmap() concurrently on another thread.
// The second Unmap() should throw a validation error and do nothing.
TEST_F(BufferBaseThreadedTest, ConcurrentUnmap) {
    WaitableEvent event;
    EXPECT_CALL(*mBufferMock.Get(), MapAsyncImpl);
    EXPECT_CALL(*mBufferMock.Get(), UnmapImpl).WillOnce([&]() { event.Wait(); });

    EXPECT_CALL(mDeviceErrorCallback,
                Call(_, wgpu::ErrorType::Validation, HasSubstr(kValidationErrorMessage)))
        .Times(1);

    MockMapAsyncCallback cb;
    EXPECT_CALL(cb, Call(Eq(wgpu::MapAsyncStatus::Success), _));
    mBuffer.MapAsync(wgpu::MapMode::Write, 0, kBufferSize, wgpu::CallbackMode::AllowSpontaneous,
                     cb.Callback());

    utils::RunInParallel(2, [&](uint32_t) {
        mBuffer.Unmap();
        event.Signal();
    });
}

// Tests calling Unmap() on one thread and then GetMappedRange() concurrently on another thread.
// GetMappedRange() will return a null since the buffer has already started being unmapped.
TEST_F(BufferBaseThreadedTest, ConcurrentUnmapGetMappedRange) {
    WaitableEvent mappedRangeEvent;
    WaitableEvent unmapEvent;
    EXPECT_CALL(*mBufferMock.Get(), UnmapImpl).WillOnce([&]() {
        mappedRangeEvent.Signal();
        unmapEvent.Wait();
    });

    MockMapAsyncCallback cb;
    EXPECT_CALL(cb, Call(Eq(wgpu::MapAsyncStatus::Success), _));
    mBuffer.MapAsync(wgpu::MapMode::Write, 0, kBufferSize, wgpu::CallbackMode::AllowSpontaneous,
                     cb.Callback());

    utils::RunInParallel(2, [&](uint32_t index) {
        if (index == 0) {
            mBuffer.Unmap();
        } else {
            mappedRangeEvent.Wait();
            EXPECT_EQ(mBuffer.GetMappedRange(), nullptr);
            unmapEvent.Signal();
        }
    });
    ProcessEvents();
}

// Tests calling MapAsync() on one thread and then MapAsync() concurrently on another thread.
// The second MapAsync() should throw a validation error and callback should fail.
TEST_F(BufferBaseThreadedTest, ConcurrentMap) {
    WaitableEvent event;
    EXPECT_CALL(*mBufferMock.Get(), MapAsyncImpl)
        .WillOnce([&](wgpu::MapMode mode, uint64_t offset, uint64_t size) -> MaybeError {
            event.Wait();
            return {};
        });

    EXPECT_CALL(mDeviceErrorCallback,
                Call(_, wgpu::ErrorType::Validation, HasSubstr(kValidationErrorMessage)));

    MockMapAsyncCallback cb;
    EXPECT_CALL(cb, Call(Eq(wgpu::MapAsyncStatus::Success), _));
    EXPECT_CALL(cb, Call(Eq(wgpu::MapAsyncStatus::Error), _));

    utils::RunInParallel(2, [&](uint32_t) {
        mBuffer.MapAsync(wgpu::MapMode::Write, 0, kBufferSize, wgpu::CallbackMode::AllowSpontaneous,
                         cb.Callback());
        event.Signal();
    });
}

// Tests calling MapAsync() on one thread and then Unmap() concurrently on another thread. Unmap
// will throw a validation error.
TEST_F(BufferBaseThreadedTest, ConcurrentMapUnmap) {
    WaitableEvent unmapStartEvent;
    WaitableEvent unmapDoneEvent;
    EXPECT_CALL(*mBufferMock.Get(), MapAsyncImpl).WillOnce([&]() -> MaybeError {
        unmapStartEvent.Signal();
        unmapDoneEvent.Wait();
        return {};
    });

    EXPECT_CALL(mDeviceErrorCallback,
                Call(_, wgpu::ErrorType::Validation, HasSubstr(kValidationErrorMessage)));

    std::thread mapThread([&]() {
        MockMapAsyncCallback cb;
        EXPECT_CALL(cb, Call(Eq(wgpu::MapAsyncStatus::Success), _));
        mBuffer.MapAsync(wgpu::MapMode::Write, 0, kBufferSize, wgpu::CallbackMode::AllowSpontaneous,
                         cb.Callback());
    });
    std::thread unmapThread([&]() {
        unmapStartEvent.Wait();
        mBuffer.Unmap();
        unmapDoneEvent.Signal();
    });

    mapThread.join();
    unmapThread.join();
}

// Tests calling MapAsync() on one thread and then Destroy() concurrently on another thread.
// Destroy() should throw a validation error and wait for MapAsync() to finish before destroying the
// object.
TEST_F(BufferBaseThreadedTest, ConcurrentMapDestroy) {
    WaitableEvent destroyEvent;
    WaitableEvent errorEvent;
    EXPECT_CALL(*mBufferMock.Get(), MapAsyncImpl)
        .WillOnce([&](wgpu::MapMode mode, uint64_t offset, uint64_t size) -> MaybeError {
            destroyEvent.Signal();
            errorEvent.Wait();
            return {};
        });

    EXPECT_CALL(mDeviceErrorCallback,
                Call(_, wgpu::ErrorType::Validation, HasSubstr(kValidationErrorMessage)))
        .WillOnce([&]() { errorEvent.Signal(); });

    EXPECT_CALL(*mBufferMock.Get(), DestroyImpl);
    // Map shouldn't complete since buffer is destroyed first.
    EXPECT_CALL(*mBufferMock.Get(), FinalizeMapImpl).Times(0);

    std::thread mapThread([&]() {
        MockMapAsyncCallback cb;
        EXPECT_CALL(cb, Call(Eq(wgpu::MapAsyncStatus::Aborted), _));
        mBuffer.MapAsync(wgpu::MapMode::Write, 0, kBufferSize, wgpu::CallbackMode::AllowSpontaneous,
                         cb.Callback());
    });
    std::thread destroyThread([&]() {
        destroyEvent.Wait();
        mBuffer.Destroy();
    });

    mapThread.join();
    destroyThread.join();
}

// Tests calling Unmap() on one thread and then Destroy() concurrently on another thread. Destroy()
// should throw a validation error and wait for unmap to finish before destroying the object.
TEST_F(BufferBaseThreadedTest, ConcurrentUnmapDestroy) {
    WaitableEvent destroyEvent;
    WaitableEvent errorEvent;
    EXPECT_CALL(*mBufferMock.Get(), UnmapImpl).WillOnce([&]() {
        destroyEvent.Signal();
        errorEvent.Wait();
    });
    EXPECT_CALL(mDeviceErrorCallback,
                Call(_, wgpu::ErrorType::Validation, HasSubstr(kValidationErrorMessage)))
        .WillOnce([&]() { errorEvent.Signal(); });

    MockMapAsyncCallback cb;
    EXPECT_CALL(cb, Call(Eq(wgpu::MapAsyncStatus::Success), _));
    mBuffer.MapAsync(wgpu::MapMode::Write, 0, kBufferSize, wgpu::CallbackMode::AllowSpontaneous,
                     cb.Callback());

    std::thread unmapThread([&]() { mBuffer.Unmap(); });
    std::thread destroyThread([&]() {
        destroyEvent.Wait();
        mBuffer.Destroy();
    });

    unmapThread.join();
    destroyThread.join();
}

}  // namespace
}  // namespace dawn::native
