// // manager_test.cxx // graphics // // Created by Sam Jaffe on 6/6/19. // Copyright © 2019 Sam Jaffe. All rights reserved. // #include #include "../src/helper.hpp" #include "game/graphics/manager.hpp" #include "game/graphics/material.hpp" #include "game/graphics/shader.hpp" #include "game/graphics/shader_program.hpp" #include "game/graphics/texture.hpp" using testing::AllOf; using testing::AnyNumber; using testing::Eq; using testing::Ge; using testing::Le; using testing::Ne; using testing::SizeIs; using testing::_; struct mock_manager_impl : graphics::manager { using shader = graphics::shader; using shader_program = graphics::shader_program; using texture = graphics::texture; MOCK_CONST_METHOD2(compile_shader, shader(graphics::shaders::type, std::string const &)); MOCK_CONST_METHOD2(compile_program, shader_program(identity, identity)); shader compile(graphics::shaders::type t, std::string const & s) const { return compile_shader(t, s); } shader_program compile(identity f, identity v) const { return compile_program(f, v); } MOCK_CONST_METHOD3(compile, texture(graphics::textures::format, math::vec2i, void const *)); }; template identity cast(unsigned int id) { return *reinterpret_cast *>(&id); } auto cast_p(unsigned int id) { return cast(id); } class ManagerTest : public testing::Test { public: void SetUp() override; mock_manager_impl mock; private: struct { graphics::texture operator()(math::vec2i const & sz) { return {++i, sz}; } unsigned int i{0}; } next_tex; }; void ManagerTest::SetUp() { using testing::Invoke; using testing::WithArg; // Start with a new set of IDs ON_CALL(mock, compile(_, _, _)) .WillByDefault(WithArg<1>(Invoke(std::ref(next_tex)))); } TEST_F(ManagerTest, DoesNotGreedilyCompile) { EXPECT_CALL(mock, compile(_, _, _)).Times(0); EXPECT_CALL(mock, compile_shader(_, _)).Times(0); EXPECT_CALL(mock, compile_program(_, _)).Times(0); } using MaterialTest = ManagerTest; // TEST_F(MaterialTest, ThrowsExceptionIfNoTexOrUniform) { // EXPECT_CALL(mock, compile(_, _, _)).Times(AnyNumber()); // // TODO (sjaffe): Throw a specific exception here, since throw; kills us // EXPECT_ANY_THROW(mock.get(cast_p(1), "", "")); //} TEST_F(MaterialTest, GeneratesUniformTexturesIfNoTexFile) { using graphics::materials::uniform; EXPECT_CALL(mock, compile(_, make_vector(1, 1), _)).Times(3); EXPECT_NO_THROW(mock.get(cast_p(1), "", "u_normalMap")); } TEST_F(MaterialTest, CreatedMaterialCanBeRefetched) { using graphics::materials::uniform; EXPECT_CALL(mock, compile(_, make_vector(1, 1), _)).Times(3); auto material_id = mock.get(cast_p(1), "", "u_normalMap"); auto material = mock.get(material_id); // Ensure that the material is the 'same one' i.e. // mock.get(mock.get(id)) == mock.get(id) EXPECT_THAT(material, Eq(material_id)); } TEST_F(MaterialTest, UniformMaterialIsOneByOne) { using graphics::materials::uniform; EXPECT_CALL(mock, compile(_, make_vector(1, 1), _)).Times(3); auto material = mock.get(mock.get(cast_p(1), "", "u_normalMap")); // Uniforms are always sized 1x1 EXPECT_THAT(material.size, Eq(make_vector(1, 1))); } TEST_F(MaterialTest, UniformMaterialHasDataBindingToNormalTex) { using graphics::materials::uniform; EXPECT_CALL(mock, compile(_, make_vector(1, 1), _)).Times(3); auto material = mock.get(mock.get(cast_p(1), "", "u_normalMap")); EXPECT_THAT(material.uniforms, SizeIs(1)); // Because we never initialize any textures, we are within the first three // texture ID units. EXPECT_THAT(material.uniforms[0].texture.id, AllOf(Ge(1), Le(3))); // Test the mapping from "u_normalMap" to uniform::NORMAL EXPECT_THAT(material.uniforms[0].uniform_id, Eq(uniform::NORMAL)); } TEST_F(MaterialTest, DifferentProgramMakesDifferentMaterial) { using graphics::materials::uniform; EXPECT_CALL(mock, compile(_, make_vector(1, 1), _)).Times(3); auto id_1 = mock.get(cast_p(1), "", "u_normalMap"); auto id_2 = mock.get(cast_p(2), "", "u_normalMap"); EXPECT_THAT(id_1, Ne(id_2)); } TEST_F(MaterialTest, DifferentProgramDoesntChangeUniformId) { using graphics::materials::uniform; EXPECT_CALL(mock, compile(_, make_vector(1, 1), _)).Times(3); auto mat_1 = mock.get(mock.get(cast_p(1), "", "u_normalMap")); auto mat_2 = mock.get(mock.get(cast_p(2), "", "u_normalMap")); EXPECT_THAT(mat_1.uniforms[0].texture, Eq(mat_2.uniforms[0].texture)); }