From 1e3605edd174bce94bb21b662c7a83f79f1df37f Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 16 Mar 2021 20:04:30 +0200 Subject: [PATCH] Refactor the GLSL compiler test cases with a helper class I'm not super pleased with the virtual fail function in the helper, but no better ideas came to mind so it can be like that for now. --- tests/glsl/glslcompiler.cpp | 137 +++++++++++++++++++----------------- 1 file changed, 73 insertions(+), 64 deletions(-) diff --git a/tests/glsl/glslcompiler.cpp b/tests/glsl/glslcompiler.cpp index 30805db3..0fd08554 100644 --- a/tests/glsl/glslcompiler.cpp +++ b/tests/glsl/glslcompiler.cpp @@ -7,11 +7,9 @@ #include #include -#include - -class GlslCompilerTest: public Msp::Test::RegisteredTest +class GlslCompilerHelper { -private: +protected: struct TestCase { std::string name; @@ -24,36 +22,39 @@ private: std::list test_cases; + void load_all_test_cases(const Msp::FS::Path &); + const TestCase &load_test_case(const std::string &); + + void verify_output(const std::string &, const std::string &); + void verify_error(const std::string &, const std::string &); + std::string extract_line(const std::string &, const std::string::const_iterator &); + virtual void fail(const std::string &) = 0; +}; + +class GlslCompilerTest: public Msp::Test::RegisteredTest, private GlslCompilerHelper +{ public: GlslCompilerTest(); static const char *get_name() { return "GLSL compiler"; } private: - const TestCase &load_test_case(const std::string &); - void run_test_case(const TestCase *); - void verify_output(const std::string &, const std::string &); - void verify_error(const std::string &, const std::string &); - std::string extract_line(const std::string &, const std::string::const_iterator &); + virtual void fail(const std::string &m) { Test::fail(m); } }; using namespace std; using namespace Msp; -GlslCompilerTest::GlslCompilerTest() +void GlslCompilerHelper::load_all_test_cases(const FS::Path &tests_dir) { - FS::Path tests_dir = "glsl"; list test_files = FS::list_filtered(tests_dir, "\\.glsl$"); test_files.sort(); for(const auto &fn: test_files) load_test_case((tests_dir/fn).str()); - - for(const auto &tc: test_cases) - add(&GlslCompilerTest::run_test_case, &tc, tc.name); } -const GlslCompilerTest::TestCase &GlslCompilerTest::load_test_case(const string &fn) +const GlslCompilerHelper::TestCase &GlslCompilerHelper::load_test_case(const string &fn) { IO::BufferedFile file(fn); TestCase test_case; @@ -127,53 +128,7 @@ const GlslCompilerTest::TestCase &GlslCompilerTest::load_test_case(const string return test_cases.back(); } -void GlslCompilerTest::run_test_case(const TestCase *test_case) -{ - GL::SL::Compiler compiler(GL::SL::Features::all()); - try - { - compiler.set_source(test_case->source, ""); - if(test_case->compile_mode==GL::SL::Compiler::PROGRAM) - compiler.specialize(test_case->spec_values); - compiler.compile(test_case->compile_mode); - } - catch(const GL::SL::invalid_shader_source &exc) - { - if(!test_case->expected_error.empty()) - { - debug("Errors from compile:"); - debug(exc.what()); - verify_error(exc.what(), test_case->expected_error); - return; - } - throw; - } - - if(!test_case->expected_error.empty()) - fail("Error expected but none thrown"); - - auto stages = compiler.get_stages(); - for(auto s: stages) - { - auto i = test_case->expected_output.find(s); - if(i==test_case->expected_output.end()) - fail(format("Compiler produced extra stage %s", GL::SL::Stage::get_stage_name(s))); - - string output = compiler.get_stage_glsl(s); - debug(format("Output for stage %s:", GL::SL::Stage::get_stage_name(s))); - auto lines = split_fields(output, '\n'); - for(unsigned j=0; jsecond); - } - - for(const auto &s: test_case->expected_output) - if(find(stages, s.first)==stages.end()) - fail(format("Compiler didn't produce stage %s", GL::SL::Stage::get_stage_name(s.first))); -} - -void GlslCompilerTest::verify_output(const string &output, const string &expected) +void GlslCompilerHelper::verify_output(const string &output, const string &expected) { GL::SL::Tokenizer tokenizer; tokenizer.begin(output, ""); @@ -199,7 +154,7 @@ void GlslCompilerTest::verify_output(const string &output, const string &expecte } } -void GlslCompilerTest::verify_error(const string &output, const string &expected) +void GlslCompilerHelper::verify_error(const string &output, const string &expected) { auto i = output.begin(); auto j = expected.begin(); @@ -240,7 +195,7 @@ void GlslCompilerTest::verify_error(const string &output, const string &expected fail(format("Missing error line: %s", extract_line(expected, j))); } -string GlslCompilerTest::extract_line(const string &text, const string::const_iterator &iter) +string GlslCompilerHelper::extract_line(const string &text, const string::const_iterator &iter) { string::const_iterator begin = iter; for(; (begin!=text.begin() && *begin!='\n'); --begin) ; @@ -250,3 +205,57 @@ string GlslCompilerTest::extract_line(const string &text, const string::const_it for(; (end!=text.end() && *end!='\n'); ++end) ; return string(begin, end); } + + +GlslCompilerTest::GlslCompilerTest() +{ + load_all_test_cases("glsl"); + for(const auto &tc: test_cases) + add(&GlslCompilerTest::run_test_case, &tc, tc.name); +} + +void GlslCompilerTest::run_test_case(const TestCase *test_case) +{ + GL::SL::Compiler compiler(GL::SL::Features::all()); + try + { + compiler.set_source(test_case->source, ""); + if(test_case->compile_mode==GL::SL::Compiler::PROGRAM) + compiler.specialize(test_case->spec_values); + compiler.compile(test_case->compile_mode); + } + catch(const GL::SL::invalid_shader_source &exc) + { + if(!test_case->expected_error.empty()) + { + debug("Errors from compile:"); + debug(exc.what()); + verify_error(exc.what(), test_case->expected_error); + return; + } + throw; + } + + if(!test_case->expected_error.empty()) + fail("Error expected but none thrown"); + + auto stages = compiler.get_stages(); + for(auto s: stages) + { + auto i = test_case->expected_output.find(s); + if(i==test_case->expected_output.end()) + fail(format("Compiler produced extra stage %s", GL::SL::Stage::get_stage_name(s))); + + string output = compiler.get_stage_glsl(s); + debug(format("Output for stage %s:", GL::SL::Stage::get_stage_name(s))); + auto lines = split_fields(output, '\n'); + for(unsigned j=0; jsecond); + } + + for(const auto &s: test_case->expected_output) + if(find(stages, s.first)==stages.end()) + fail(format("Compiler didn't produce stage %s", GL::SL::Stage::get_stage_name(s.first))); +} -- 2.43.0