1from unittest.mock import MagicMock, call 2 3import pytest 4from PyQt5.QtGui import QOpenGLShader 5 6from UM.View.GL.ShaderProgram import ShaderProgram, InvalidShaderProgramError 7import os 8 9def test_ShaderProgramInit(): 10 # Creating it just shouldn't fail. 11 shader = ShaderProgram() 12 13 14def test_loadEmpty(): 15 shader = ShaderProgram() 16 with pytest.raises(InvalidShaderProgramError): 17 shader.load(os.path.join(os.path.dirname(os.path.abspath(__file__)), "Shaders", "empty.shader")) 18 19 20def test_loadInvalid(): 21 shader = ShaderProgram() 22 with pytest.raises(InvalidShaderProgramError): 23 shader.load(os.path.join(os.path.dirname(os.path.abspath(__file__)), "Shaders", "invalid.shader")) 24 25 with pytest.raises(InvalidShaderProgramError): 26 shader.load(os.path.join(os.path.dirname(os.path.abspath(__file__)), "Shaders", "invalid2.shader")) 27 28def test_load(): 29 shader = ShaderProgram() 30 31 mocked_shader_program = MagicMock() 32 33 shader._shader_program = mocked_shader_program 34 shader.load(os.path.join(os.path.dirname(os.path.abspath(__file__)), "Shaders", "test.shader")) 35 36 # It should be called 3 times, once for vertex, once for fragment and once for geometry 37 call_arg_list = mocked_shader_program.addShaderFromSourceCode.call_args_list 38 assert call(QOpenGLShader.Vertex, "vertex_code") in call_arg_list 39 assert call(QOpenGLShader.Fragment, "fragment_code") in call_arg_list 40 assert call(QOpenGLShader.Geometry, "geometry_code") in call_arg_list 41 42 43def test_bindAndRelease(): 44 shader = ShaderProgram() 45 46 mocked_shader_program = MagicMock() 47 shader._shader_program = mocked_shader_program 48 shader.bind() 49 assert mocked_shader_program.bind.call_count == 1 50 51 # Doing it without releasing in between shouldn't cause another bind. 52 shader.bind() 53 assert mocked_shader_program.bind.call_count == 1 54 55 shader.release() 56 assert mocked_shader_program.release.call_count == 1 57 58 shader.release() 59 assert mocked_shader_program.release.call_count == 1 60 61 # We left it unbound, so now binding should work. 62 shader.bind() 63 assert mocked_shader_program.bind.call_count == 2 64 65 66enable_attribute_data = [("int", 2, 3, 0x1404, 1), 67 ("float", 5, 9, 0x1406, 1), 68 ("vector2f", 2, 32, 0x1406, 2), 69 ("vector3f", 2000, 90, 0x1406, 3), 70 ("vector4f", 12, 1, 0x1406, 4)] 71 72 73@pytest.mark.parametrize("type, offset, stride, type_result, tuple_size", enable_attribute_data) 74def test_enableDisableAttribute(type, offset, stride, type_result, tuple_size): 75 shader = ShaderProgram() 76 77 mocked_shader_program = MagicMock() 78 shader._shader_program = mocked_shader_program 79 80 attribute_index = MagicMock() 81 82 mocked_shader_program.attributeLocation = MagicMock(return_value = attribute_index) 83 84 shader.enableAttribute("blorp", type, offset, stride) 85 86 # Validate 87 mocked_shader_program.setAttributeBuffer.assert_called_once_with(attribute_index, type_result, offset, tuple_size, stride) 88 mocked_shader_program.enableAttributeArray.assert_called_once_with(attribute_index) 89 90 # Disable it again 91 shader.disableAttribute("blorp") 92 mocked_shader_program.disableAttributeArray.assert_called_once_with(attribute_index) 93 94 # Disable unknown attribute 95 shader.disableAttribute("BEEP") 96 mocked_shader_program.disableAttributeArray.assert_called_once_with(attribute_index) 97 98