//
// Copyright 2015 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.
//
// validationES unit tests:
//   Unit tests for general ES validation functions.
//

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "libANGLE/ContextState.h"
#include "libANGLE/VaryingPacking.h"
#include "libANGLE/renderer/FramebufferImpl_mock.h"
#include "libANGLE/renderer/ProgramImpl_mock.h"
#include "libANGLE/renderer/TextureImpl_mock.h"
#include "libANGLE/validationES.h"
#include "tests/angle_unittests_utils.h"

using namespace gl;
using namespace rx;
using testing::_;
using testing::NiceMock;
using testing::Return;

namespace
{

class MockValidationContext : public ValidationContext
{
  public:
    MockValidationContext(const ValidationContext *shareContext,
                          TextureManager *shareTextures,
                          const Version &version,
                          State *state,
                          const Caps &caps,
                          const TextureCapsMap &textureCaps,
                          const Extensions &extensions,
                          const Limitations &limitations,
                          bool skipValidation)
        : ValidationContext(shareContext,
                            shareTextures,
                            version,
                            state,
                            caps,
                            textureCaps,
                            extensions,
                            limitations,
                            skipValidation)
    {
    }

    MOCK_METHOD1(handleError, void(const Error &));
};

// Test that ANGLE generates an INVALID_OPERATION when validating index data that uses a value
// larger than MAX_ELEMENT_INDEX. Not specified in the GLES 3 spec, it's undefined behaviour,
// but we want a test to ensure we maintain this behaviour.
// TODO(jmadill): Re-enable when framebuffer sync state doesn't happen in validation.
TEST(ValidationESTest, DISABLED_DrawElementsWithMaxIndexGivesError)
{
    auto framebufferImpl = MakeFramebufferMock();
    auto programImpl     = MakeProgramMock();

    // TODO(jmadill): Generalize some of this code so we can re-use it for other tests.
    NiceMock<MockGLFactory> mockFactory;
    EXPECT_CALL(mockFactory, createFramebuffer(_)).WillOnce(Return(framebufferImpl));
    EXPECT_CALL(mockFactory, createProgram(_)).WillOnce(Return(programImpl));
    EXPECT_CALL(mockFactory, createVertexArray(_)).WillOnce(Return(nullptr));

    State state;
    Caps caps;
    TextureCapsMap textureCaps;
    Extensions extensions;
    Limitations limitations;

    // Set some basic caps.
    caps.maxElementIndex     = 100;
    caps.maxDrawBuffers      = 1;
    caps.maxColorAttachments = 1;
    state.initialize(caps, extensions, Version(3, 0), false, true, true, false);

    NiceMock<MockTextureImpl> *textureImpl = new NiceMock<MockTextureImpl>();
    EXPECT_CALL(mockFactory, createTexture(_)).WillOnce(Return(textureImpl));
    EXPECT_CALL(*textureImpl, setStorage(_, _, _, _, _)).WillOnce(Return(NoError()));
    EXPECT_CALL(*textureImpl, destructor()).Times(1).RetiresOnSaturation();

    Texture *texture = new Texture(&mockFactory, 0, GL_TEXTURE_2D);
    texture->addRef();
    texture->setStorage(nullptr, GL_TEXTURE_2D, 1, GL_RGBA8, Extents(1, 1, 0));

    VertexArray *vertexArray = new VertexArray(&mockFactory, 0, 1, 1);
    Framebuffer *framebuffer = new Framebuffer(caps, &mockFactory, 1);
    framebuffer->setAttachment(nullptr, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex::Make2D(0),
                               texture);

    Program *program = new Program(&mockFactory, nullptr, 1);

    state.setVertexArrayBinding(vertexArray);
    state.setDrawFramebufferBinding(framebuffer);
    state.setProgram(nullptr, program);

    NiceMock<MockValidationContext> testContext(nullptr, nullptr, Version(3, 0), &state, caps,
                                                textureCaps, extensions, limitations, false);

    // Set the expectation for the validation error here.
    Error expectedError(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage);
    EXPECT_CALL(testContext, handleError(expectedError)).Times(1);

    // Call once with maximum index, and once with an excessive index.
    GLuint indexData[] = {0, 1, static_cast<GLuint>(caps.maxElementIndex - 1),
                          3, 4, static_cast<GLuint>(caps.maxElementIndex)};
    EXPECT_TRUE(
        ValidateDrawElementsCommon(&testContext, GL_TRIANGLES, 3, GL_UNSIGNED_INT, indexData, 1));
    EXPECT_FALSE(
        ValidateDrawElementsCommon(&testContext, GL_TRIANGLES, 6, GL_UNSIGNED_INT, indexData, 2));

    texture->release();

    state.setVertexArrayBinding(nullptr);
    state.setDrawFramebufferBinding(nullptr);
    state.setProgram(nullptr, nullptr);

    SafeDelete(vertexArray);
    SafeDelete(framebuffer);
    SafeDelete(program);
}

}  // anonymous namespace
