import pytest from unittest.mock import patch, MagicMock def test_blur_pipeline_import(): with patch("src.shader_manager.gl") as mock_gl: from src.shader_manager import BlurPipeline pipeline = BlurPipeline() assert pipeline is not None assert pipeline.scene_fbo is None assert pipeline.blur_fbo_a is None assert pipeline.blur_fbo_b is None assert pipeline.scene_tex is None assert pipeline.blur_tex_a is None assert pipeline.blur_tex_b is None assert pipeline.h_blur_program is None assert pipeline.v_blur_program is None def test_blur_pipeline_setup_fbos(): with patch("src.shader_manager.gl") as mock_gl: tex_counter = iter([10, 20, 30]) fbo_counter = iter([1, 2, 3]) mock_gl.glGenTextures.side_effect = lambda n: next(tex_counter) mock_gl.glGenFramebuffers.side_effect = lambda n: next(fbo_counter) from src.shader_manager import BlurPipeline pipeline = BlurPipeline() pipeline.setup_fbos(800, 600) assert mock_gl.glGenFramebuffers.called assert mock_gl.glGenTextures.called assert pipeline.scene_fbo is not None assert pipeline.blur_fbo_a is not None assert pipeline.blur_fbo_b is not None def test_blur_pipeline_compile_shaders(): with patch("src.shader_manager.gl") as mock_gl: mock_gl.glCreateProgram.return_value = 100 mock_gl.glCreateShader.return_value = 200 mock_gl.glGetShaderiv.return_value = mock_gl.GL_TRUE mock_gl.glGetProgramiv.return_value = mock_gl.GL_TRUE from src.shader_manager import BlurPipeline pipeline = BlurPipeline() pipeline.compile_blur_shaders() assert mock_gl.glCreateProgram.called assert pipeline.h_blur_program is not None assert pipeline.v_blur_program is not None def test_blur_pipeline_wide_tap_distribution(): with patch("src.shader_manager.gl") as mock_gl: mock_gl.glCreateProgram.return_value = 100 mock_gl.glCreateShader.return_value = 200 mock_gl.glGetShaderiv.return_value = mock_gl.GL_TRUE mock_gl.glGetProgramiv.return_value = mock_gl.GL_TRUE from src.shader_manager import BlurPipeline pipeline = BlurPipeline() pipeline.compile_blur_shaders() assert mock_gl.glShaderSource.called shader_sources = [call.args[1] for call in mock_gl.glShaderSource.call_args_list] frag_sources = [s for s in shader_sources if 'texture(' in s and 'offset' in s] assert len(frag_sources) >= 2 for src in frag_sources: texture_calls = src.count('texture(u_texture') assert texture_calls >= 11, f"Expected at least 11 texture samples for wide tap distribution, got {texture_calls}" def test_blur_pipeline_render_deepsea_to_fbo(): with patch("src.shader_manager.gl") as mock_gl: tex_counter = iter([10, 20, 30]) fbo_counter = iter([1, 2, 3]) mock_gl.glGenTextures.side_effect = lambda n: next(tex_counter) mock_gl.glGenFramebuffers.side_effect = lambda n: next(fbo_counter) mock_gl.glCreateProgram.return_value = 300 mock_gl.glCreateShader.return_value = 400 mock_gl.glGetShaderiv.return_value = mock_gl.GL_TRUE mock_gl.glGetProgramiv.return_value = mock_gl.GL_TRUE from src.shader_manager import BlurPipeline pipeline = BlurPipeline() pipeline.setup_fbos(800, 600) pipeline.compile_deepsea_shader() pipeline.render_deepsea_to_fbo(800, 600, 0.0) assert mock_gl.glBindFramebuffer.called assert mock_gl.glUseProgram.called assert mock_gl.glDrawArrays.called def test_blur_pipeline_deepsea_shader_compilation(): with patch("src.shader_manager.gl") as mock_gl: mock_gl.glCreateProgram.return_value = 500 mock_gl.glCreateShader.return_value = 600 mock_gl.glGetShaderiv.return_value = mock_gl.GL_TRUE mock_gl.glGetProgramiv.return_value = mock_gl.GL_TRUE from src.shader_manager import BlurPipeline pipeline = BlurPipeline() pipeline.compile_deepsea_shader() assert mock_gl.glCreateProgram.called assert pipeline.deepsea_program is not None def test_blur_pipeline_prepare_blur(): with patch("src.shader_manager.gl") as mock_gl: mock_gl.glGenFramebuffers.return_value = None mock_gl.glGenTextures.return_value = None from src.shader_manager import BlurPipeline pipeline = BlurPipeline() pipeline.scene_fbo = 1 pipeline.scene_tex = 10 pipeline.blur_fbo_a = 2 pipeline.blur_tex_a = 20 pipeline.blur_fbo_b = 3 pipeline.blur_tex_b = 30 pipeline.h_blur_program = 100 pipeline.v_blur_program = 101 pipeline.prepare_blur(800, 600, 0.0) assert mock_gl.glBindFramebuffer.called assert mock_gl.glUseProgram.called def test_blur_pipeline_prepare_global_blur(): with patch("src.shader_manager.gl") as mock_gl: tex_counter = iter([10, 20, 30]) fbo_counter = iter([1, 2, 3]) mock_gl.glGenTextures.side_effect = lambda n: next(tex_counter) mock_gl.glGenFramebuffers.side_effect = lambda n: next(fbo_counter) mock_gl.glCreateProgram.return_value = 100 mock_gl.glCreateShader.return_value = 200 mock_gl.glGetShaderiv.return_value = mock_gl.GL_TRUE mock_gl.glGetProgramiv.return_value = mock_gl.GL_TRUE from src.shader_manager import BlurPipeline pipeline = BlurPipeline() pipeline.setup_fbos(800, 600) pipeline.compile_deepsea_shader() pipeline.compile_blur_shaders() pipeline.prepare_global_blur(800, 600, 0.0) assert mock_gl.glBindFramebuffer.called assert mock_gl.glUseProgram.called assert mock_gl.glViewport.called blur_tex = pipeline.get_blur_texture() assert blur_tex is not None assert blur_tex == 30 def test_blur_pipeline_high_dpi_scaling(): with patch("src.shader_manager.gl") as mock_gl: tex_counter = iter([10, 20, 30]) fbo_counter = iter([1, 2, 3]) mock_gl.glGenTextures.side_effect = lambda n: next(tex_counter) mock_gl.glGenFramebuffers.side_effect = lambda n: next(fbo_counter) mock_gl.glCreateProgram.return_value = 100 mock_gl.glCreateShader.return_value = 200 mock_gl.glGetShaderiv.return_value = mock_gl.GL_TRUE mock_gl.glGetProgramiv.return_value = mock_gl.GL_TRUE from src.shader_manager import BlurPipeline pipeline = BlurPipeline() fb_scale = 2.0 pipeline.setup_fbos(800, 600, fb_scale) assert pipeline._fb_width == (800 * int(fb_scale)) // 4 assert pipeline._fb_height == (600 * int(fb_scale)) // 4 assert pipeline._fb_scale == int(fb_scale) def test_blur_pipeline_cleanup(): with patch("src.shader_manager.gl") as mock_gl: from src.shader_manager import BlurPipeline pipeline = BlurPipeline() pipeline.scene_fbo = 1 pipeline.blur_fbo_a = 2 pipeline.blur_fbo_b = 3 pipeline.scene_tex = 10 pipeline.blur_tex_a = 20 pipeline.blur_tex_b = 30 pipeline.h_blur_program = 100 pipeline.v_blur_program = 101 pipeline.cleanup() assert mock_gl.glDeleteFramebuffers.called assert mock_gl.glDeleteTextures.called assert mock_gl.glDeleteProgram.called def test_shader_manager_initialization_and_compilation(): # Import inside test to allow patching OpenGL before import if needed # In this case, we patch the OpenGL.GL functions used by ShaderManager with patch("src.shader_manager.gl") as mock_gl: mock_gl.glCreateProgram.return_value = 1 mock_gl.glCreateShader.return_value = 2 mock_gl.glGetShaderiv.return_value = mock_gl.GL_TRUE mock_gl.glGetProgramiv.return_value = mock_gl.GL_TRUE from src.shader_manager import ShaderManager manager = ShaderManager() # Basic vertex and fragment shader source vert_src = "void main() {}" frag_src = "void main() {}" program_id = manager.compile_shader(vert_src, frag_src) assert program_id == 1 assert mock_gl.glCreateProgram.called assert mock_gl.glCreateShader.called def test_shader_manager_uniform_update(): # Mock OpenGL.GL functions with patch("src.shader_manager.gl") as mock_gl: from src.shader_manager import ShaderManager manager = ShaderManager() # Set a mock program ID manager.program = 1 # Mock glGetUniformLocation to return some valid locations # u_time -> 10, u_resolution -> 20 def mock_get_loc(prog, name): if name == "u_time": return 10 if name == "u_resolution": return 20 return -1 mock_gl.glGetUniformLocation.side_effect = mock_get_loc # Call the method manager.update_uniforms({"u_time": 1.5, "u_resolution": (800, 600)}) # Assert calls mock_gl.glGetUniformLocation.assert_any_call(1, "u_time") mock_gl.glGetUniformLocation.assert_any_call(1, "u_resolution") mock_gl.glUniform1f.assert_called_once_with(10, 1.5) mock_gl.glUniform2f.assert_called_once_with(20, 800, 600)