Jamie Madill | e79b1e1 | 2015-11-04 16:36:37 -0500 | [diff] [blame] | 1 | // |
| 2 | // Copyright 2015 The ANGLE Project Authors. All rights reserved. |
| 3 | // Use of this source code is governed by a BSD-style license that can be |
| 4 | // found in the LICENSE file. |
| 5 | // |
| 6 | // validationES unit tests: |
| 7 | // Unit tests for general ES validation functions. |
| 8 | // |
| 9 | |
| 10 | #include <gmock/gmock.h> |
| 11 | #include <gtest/gtest.h> |
| 12 | |
| 13 | #include "libANGLE/Data.h" |
| 14 | #include "libANGLE/renderer/FramebufferImpl_mock.h" |
| 15 | #include "libANGLE/renderer/ProgramImpl_mock.h" |
| 16 | #include "libANGLE/renderer/TextureImpl_mock.h" |
| 17 | #include "libANGLE/validationES.h" |
| 18 | #include "tests/angle_unittests_utils.h" |
| 19 | |
| 20 | using namespace gl; |
| 21 | using namespace rx; |
| 22 | using testing::_; |
Jamie Madill | 60ec6ea | 2016-01-22 15:27:19 -0500 | [diff] [blame] | 23 | using testing::NiceMock; |
Jamie Madill | e79b1e1 | 2015-11-04 16:36:37 -0500 | [diff] [blame] | 24 | using testing::Return; |
| 25 | |
| 26 | namespace |
| 27 | { |
| 28 | |
| 29 | class MockFactory : public NullFactory |
| 30 | { |
| 31 | public: |
| 32 | MOCK_METHOD1(createFramebuffer, FramebufferImpl *(const gl::Framebuffer::Data &)); |
| 33 | MOCK_METHOD1(createProgram, ProgramImpl *(const gl::Program::Data &)); |
| 34 | MOCK_METHOD1(createVertexArray, VertexArrayImpl *(const gl::VertexArray::Data &)); |
| 35 | }; |
| 36 | |
| 37 | class MockValidationContext : public ValidationContext |
| 38 | { |
| 39 | public: |
| 40 | MockValidationContext(GLint clientVersion, |
| 41 | const State &state, |
| 42 | const Caps &caps, |
| 43 | const TextureCapsMap &textureCaps, |
| 44 | const Extensions &extensions, |
| 45 | const ResourceManager *resourceManager, |
Jamie Madill | 46e6c7a | 2016-01-18 14:42:30 -0500 | [diff] [blame] | 46 | const Limitations &limitations, |
| 47 | bool skipValidation); |
Jamie Madill | e79b1e1 | 2015-11-04 16:36:37 -0500 | [diff] [blame] | 48 | |
| 49 | MOCK_METHOD1(recordError, void(const Error &)); |
| 50 | }; |
| 51 | |
| 52 | MockValidationContext::MockValidationContext(GLint clientVersion, |
| 53 | const State &state, |
| 54 | const Caps &caps, |
| 55 | const TextureCapsMap &textureCaps, |
| 56 | const Extensions &extensions, |
| 57 | const ResourceManager *resourceManager, |
Jamie Madill | 46e6c7a | 2016-01-18 14:42:30 -0500 | [diff] [blame] | 58 | const Limitations &limitations, |
| 59 | bool skipValidation) |
Jamie Madill | e79b1e1 | 2015-11-04 16:36:37 -0500 | [diff] [blame] | 60 | : ValidationContext(clientVersion, |
| 61 | state, |
| 62 | caps, |
| 63 | textureCaps, |
| 64 | extensions, |
| 65 | resourceManager, |
Jamie Madill | 46e6c7a | 2016-01-18 14:42:30 -0500 | [diff] [blame] | 66 | limitations, |
| 67 | skipValidation) |
Jamie Madill | e79b1e1 | 2015-11-04 16:36:37 -0500 | [diff] [blame] | 68 | { |
| 69 | } |
| 70 | |
| 71 | // Test that ANGLE generates an INVALID_OPERATION when validating index data that uses a value |
| 72 | // larger than MAX_ELEMENT_INDEX. Not specified in the GLES 3 spec, it's undefined behaviour, |
| 73 | // but we want a test to ensure we maintain this behaviour. |
| 74 | TEST(ValidationESTest, DrawElementsWithMaxIndexGivesError) |
| 75 | { |
Jamie Madill | 60ec6ea | 2016-01-22 15:27:19 -0500 | [diff] [blame] | 76 | auto framebufferImpl = MakeFramebufferMock(); |
| 77 | auto programImpl = MakeProgramMock(); |
| 78 | |
Jamie Madill | e79b1e1 | 2015-11-04 16:36:37 -0500 | [diff] [blame] | 79 | // TODO(jmadill): Generalize some of this code so we can re-use it for other tests. |
Jamie Madill | 60ec6ea | 2016-01-22 15:27:19 -0500 | [diff] [blame] | 80 | NiceMock<MockFactory> mockFactory; |
Jamie Madill | e79b1e1 | 2015-11-04 16:36:37 -0500 | [diff] [blame] | 81 | EXPECT_CALL(mockFactory, createFramebuffer(_)).WillOnce(Return(framebufferImpl)); |
| 82 | EXPECT_CALL(mockFactory, createProgram(_)).WillOnce(Return(programImpl)); |
| 83 | EXPECT_CALL(mockFactory, createVertexArray(_)).WillOnce(Return(nullptr)); |
| 84 | |
| 85 | State state; |
| 86 | Caps caps; |
| 87 | TextureCapsMap textureCaps; |
| 88 | Extensions extensions; |
| 89 | Limitations limitations; |
| 90 | |
| 91 | // Set some basic caps. |
| 92 | caps.maxElementIndex = 100; |
| 93 | caps.maxDrawBuffers = 1; |
| 94 | caps.maxColorAttachments = 1; |
Geoff Lang | 70d0f49 | 2015-12-10 17:45:46 -0500 | [diff] [blame] | 95 | state.initialize(caps, extensions, 3, false); |
Jamie Madill | e79b1e1 | 2015-11-04 16:36:37 -0500 | [diff] [blame] | 96 | |
Jamie Madill | 60ec6ea | 2016-01-22 15:27:19 -0500 | [diff] [blame] | 97 | NiceMock<MockTextureImpl> *textureImpl = new NiceMock<MockTextureImpl>(); |
Jamie Madill | e79b1e1 | 2015-11-04 16:36:37 -0500 | [diff] [blame] | 98 | EXPECT_CALL(*textureImpl, setStorage(_, _, _, _)).WillOnce(Return(Error(GL_NO_ERROR))); |
| 99 | EXPECT_CALL(*textureImpl, destructor()).Times(1).RetiresOnSaturation(); |
Jamie Madill | 60ec6ea | 2016-01-22 15:27:19 -0500 | [diff] [blame] | 100 | |
Jamie Madill | e79b1e1 | 2015-11-04 16:36:37 -0500 | [diff] [blame] | 101 | Texture *texture = new Texture(textureImpl, 0, GL_TEXTURE_2D); |
| 102 | texture->addRef(); |
| 103 | texture->setStorage(GL_TEXTURE_2D, 1, GL_RGBA8, Extents(1, 1, 0)); |
| 104 | |
| 105 | VertexArray *vertexArray = new VertexArray(&mockFactory, 0, 1); |
| 106 | Framebuffer *framebuffer = new Framebuffer(caps, &mockFactory, 1); |
| 107 | framebuffer->setAttachment(GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex::Make2D(0), texture); |
| 108 | |
| 109 | Program *program = new Program(&mockFactory, nullptr, 1); |
| 110 | |
| 111 | state.setVertexArrayBinding(vertexArray); |
| 112 | state.setDrawFramebufferBinding(framebuffer); |
| 113 | state.setProgram(program); |
| 114 | |
Jamie Madill | 60ec6ea | 2016-01-22 15:27:19 -0500 | [diff] [blame] | 115 | NiceMock<MockValidationContext> testContext(3, state, caps, textureCaps, extensions, nullptr, |
| 116 | limitations, false); |
Jamie Madill | e79b1e1 | 2015-11-04 16:36:37 -0500 | [diff] [blame] | 117 | |
| 118 | // Set the expectation for the validation error here. |
| 119 | Error expectedError(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage); |
| 120 | EXPECT_CALL(testContext, recordError(expectedError)).Times(1); |
| 121 | |
| 122 | // Call once with maximum index, and once with an excessive index. |
| 123 | GLuint indexData[] = {0, 1, static_cast<GLuint>(caps.maxElementIndex - 1), |
| 124 | 3, 4, static_cast<GLuint>(caps.maxElementIndex)}; |
| 125 | IndexRange indexRange; |
| 126 | EXPECT_TRUE(ValidateDrawElements(&testContext, GL_TRIANGLES, 3, GL_UNSIGNED_INT, indexData, 1, |
| 127 | &indexRange)); |
| 128 | EXPECT_FALSE(ValidateDrawElements(&testContext, GL_TRIANGLES, 6, GL_UNSIGNED_INT, indexData, 2, |
| 129 | &indexRange)); |
| 130 | |
| 131 | texture->release(); |
Jamie Madill | daa8c27 | 2015-11-18 14:13:55 -0500 | [diff] [blame] | 132 | |
| 133 | state.setVertexArrayBinding(nullptr); |
| 134 | state.setDrawFramebufferBinding(nullptr); |
| 135 | state.setProgram(nullptr); |
| 136 | |
Jamie Madill | e79b1e1 | 2015-11-04 16:36:37 -0500 | [diff] [blame] | 137 | SafeDelete(vertexArray); |
| 138 | SafeDelete(framebuffer); |
| 139 | SafeDelete(program); |
| 140 | } |
| 141 | |
| 142 | } // anonymous namespace |