]> git.tdb.fi Git - libs/gl.git/commitdiff
Refactor the GLSL compiler test cases with a helper class
authorMikko Rasa <tdb@tdb.fi>
Tue, 16 Mar 2021 18:04:30 +0000 (20:04 +0200)
committerMikko Rasa <tdb@tdb.fi>
Tue, 16 Mar 2021 18:04:30 +0000 (20:04 +0200)
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

index 30805db3ff80a2b8be88c2ad868c1bcbd33ea253..0fd0855489d63ca4f6a5de05c30c0615a9307c89 100644 (file)
@@ -7,11 +7,9 @@
 #include <msp/strings/utils.h>
 #include <msp/test/test.h>
 
-#include <msp/io/print.h>
-
-class GlslCompilerTest: public Msp::Test::RegisteredTest<GlslCompilerTest>
+class GlslCompilerHelper
 {
-private:
+protected:
        struct TestCase
        {
                std::string name;
@@ -24,36 +22,39 @@ private:
 
        std::list<TestCase> 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<GlslCompilerTest>, 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<string> 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, "<test>");
-               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; j<lines.size(); ++j)
-                       debug(format("%3d: %s", j+1, lines[j]));
-
-               verify_output(output, i->second);
-       }
-
-       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, "<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, "<test>");
+               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; j<lines.size(); ++j)
+                       debug(format("%3d: %s", j+1, lines[j]));
+
+               verify_output(output, i->second);
+       }
+
+       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)));
+}