//
// Copyright 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

#include "gmock/gmock.h"
#include "gtest/gtest.h"

#include "libANGLE/Fence.h"
#include "libANGLE/renderer/FenceNVImpl.h"
#include "libANGLE/renderer/SyncImpl.h"

using ::testing::_;
using ::testing::DoAll;
using ::testing::Return;
using ::testing::SetArgumentPointee;

namespace
{

//
// FenceNV tests
//

class MockFenceNVImpl : public rx::FenceNVImpl
{
  public:
    virtual ~MockFenceNVImpl() { destroy(); }

    MOCK_METHOD2(set, angle::Result(const gl::Context *, GLenum));
    MOCK_METHOD2(test, angle::Result(const gl::Context *, GLboolean *));
    MOCK_METHOD1(finish, angle::Result(const gl::Context *));

    MOCK_METHOD0(destroy, void());
};

class FenceNVTest : public testing::Test
{
  protected:
    virtual void SetUp()
    {
        mImpl = new MockFenceNVImpl;
        EXPECT_CALL(*mImpl, destroy());
        mFence = new gl::FenceNV(mImpl);
    }

    virtual void TearDown() { delete mFence; }

    MockFenceNVImpl *mImpl;
    gl::FenceNV *mFence;
};

TEST_F(FenceNVTest, DestructionDeletesImpl)
{
    MockFenceNVImpl *impl = new MockFenceNVImpl;
    EXPECT_CALL(*impl, destroy()).Times(1).RetiresOnSaturation();

    gl::FenceNV *fence = new gl::FenceNV(impl);
    delete fence;

    // Only needed because the mock is leaked if bugs are present,
    // which logs an error, but does not cause the test to fail.
    // Ordinarily mocks are verified when destroyed.
    testing::Mock::VerifyAndClear(impl);
}

TEST_F(FenceNVTest, SetAndTestBehavior)
{
    EXPECT_CALL(*mImpl, set(_, _)).WillOnce(Return(angle::Result::Continue)).RetiresOnSaturation();
    EXPECT_FALSE(mFence->isSet());
    EXPECT_EQ(angle::Result::Continue, mFence->set(nullptr, GL_ALL_COMPLETED_NV));
    EXPECT_TRUE(mFence->isSet());
    // Fake the behavior of testing the fence before and after it's passed.
    EXPECT_CALL(*mImpl, test(_, _))
        .WillOnce(DoAll(SetArgumentPointee<1>(static_cast<GLboolean>(GL_FALSE)),
                        Return(angle::Result::Continue)))
        .WillOnce(DoAll(SetArgumentPointee<1>(static_cast<GLboolean>(GL_TRUE)),
                        Return(angle::Result::Continue)))
        .RetiresOnSaturation();
    GLboolean out;
    EXPECT_EQ(angle::Result::Continue, mFence->test(nullptr, &out));
    EXPECT_EQ(GL_FALSE, out);
    EXPECT_EQ(angle::Result::Continue, mFence->test(nullptr, &out));
    EXPECT_EQ(GL_TRUE, out);
}

//
// Sync tests
//

class MockSyncImpl : public rx::SyncImpl
{
  public:
    virtual ~MockSyncImpl() { destroy(); }

    MOCK_METHOD3(set, angle::Result(const gl::Context *, GLenum, GLbitfield));
    MOCK_METHOD4(clientWait, angle::Result(const gl::Context *, GLbitfield, GLuint64, GLenum *));
    MOCK_METHOD3(serverWait, angle::Result(const gl::Context *, GLbitfield, GLuint64));
    MOCK_METHOD2(getStatus, angle::Result(const gl::Context *, GLint *));

    MOCK_METHOD0(destroy, void());
};

class FenceSyncTest : public testing::Test
{
  protected:
    virtual void SetUp()
    {
        mImpl = new MockSyncImpl;
        EXPECT_CALL(*mImpl, destroy());
        mFence = new gl::Sync(mImpl, 1);
        mFence->addRef();
    }

    virtual void TearDown() { mFence->release(nullptr); }

    MockSyncImpl *mImpl;
    gl::Sync *mFence;
};

TEST_F(FenceSyncTest, DestructionDeletesImpl)
{
    MockSyncImpl *impl = new MockSyncImpl;
    EXPECT_CALL(*impl, destroy()).Times(1).RetiresOnSaturation();

    gl::Sync *fence = new gl::Sync(impl, 1);
    fence->addRef();
    fence->release(nullptr);

    // Only needed because the mock is leaked if bugs are present,
    // which logs an error, but does not cause the test to fail.
    // Ordinarily mocks are verified when destroyed.
    testing::Mock::VerifyAndClear(impl);
}

TEST_F(FenceSyncTest, SetAndGetStatusBehavior)
{
    EXPECT_CALL(*mImpl, set(_, _, _))
        .WillOnce(Return(angle::Result::Continue))
        .RetiresOnSaturation();
    EXPECT_EQ(angle::Result::Continue, mFence->set(nullptr, GL_SYNC_GPU_COMMANDS_COMPLETE, 0));
    EXPECT_EQ(static_cast<GLenum>(GL_SYNC_GPU_COMMANDS_COMPLETE), mFence->getCondition());
    // Fake the behavior of testing the fence before and after it's passed.
    EXPECT_CALL(*mImpl, getStatus(_, _))
        .WillOnce(DoAll(SetArgumentPointee<1>(GL_UNSIGNALED), Return(angle::Result::Continue)))
        .WillOnce(DoAll(SetArgumentPointee<1>(GL_SIGNALED), Return(angle::Result::Continue)))
        .RetiresOnSaturation();
    GLint out;
    EXPECT_EQ(angle::Result::Continue, mFence->getStatus(nullptr, &out));
    EXPECT_EQ(GL_UNSIGNALED, out);
    EXPECT_EQ(angle::Result::Continue, mFence->getStatus(nullptr, &out));
    EXPECT_EQ(GL_SIGNALED, out);
}

}  // namespace
