]> git.tdb.fi Git - libs/gl.git/commitdiff
Make the GLSL compiler tester able to verify errors
authorMikko Rasa <tdb@tdb.fi>
Thu, 4 Mar 2021 12:49:59 +0000 (14:49 +0200)
committerMikko Rasa <tdb@tdb.fi>
Thu, 4 Mar 2021 15:32:05 +0000 (17:32 +0200)
tests/glsl/glslcompiler.cpp

index f38db45caa6c5638e06044a624055ef2f0e63ed4..70ccf3b200f733504d89583396e1fb9594c3d9d8 100644 (file)
@@ -17,6 +17,7 @@ private:
                std::string name;
                std::string source;
                std::map<Msp::GL::SL::Stage::Type, std::string> expected_output;
+               std::string expected_error;
        };
 
        std::list<TestCase> test_cases;
@@ -30,6 +31,9 @@ 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 &);
 };
 
 using namespace std;
@@ -77,6 +81,13 @@ const GlslCompilerTest::TestCase &GlslCompilerTest::load_test_case(const string
                        continue;
                }
 
+               expected = line.find("Expected error:");
+               if(expected!=string::npos)
+               {
+                       target = &test_case.expected_error;
+                       continue;
+               }
+
                *target += line;
                *target += '\n';
        }
@@ -89,7 +100,21 @@ void GlslCompilerTest::run_test_case(const TestCase *test_case)
 {
        GL::SL::Compiler compiler(GL::SL::Features::all());
        compiler.set_source(test_case->source, "<test>");
-       compiler.compile(GL::SL::Compiler::PROGRAM);
+       try
+       {
+               compiler.compile(GL::SL::Compiler::PROGRAM);
+       }
+       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;
+       }
 
        auto stages = compiler.get_stages();
        for(auto s: stages)
@@ -104,31 +129,83 @@ void GlslCompilerTest::run_test_case(const TestCase *test_case)
                for(unsigned j=0; j<lines.size(); ++j)
                        debug(format("%3d: %s", j+1, lines[j]));
 
-               GL::SL::Tokenizer tokenizer;
-               tokenizer.begin(output, "<output>");
+               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)
+{
+       GL::SL::Tokenizer tokenizer;
+       tokenizer.begin(output, "<output>");
+
+       GL::SL::Tokenizer expected_tkn;
+       expected_tkn.begin(expected, "<expected>");
+
+       while(1)
+       {
+               string token = expected_tkn.parse_token();
 
-               GL::SL::Tokenizer expected_tkn;
-               expected_tkn.begin(i->second, "<expected>");
+               try
+               {
+                       tokenizer.expect(token);
+               }
+               catch(const GL::SL::invalid_shader_source &exc)
+               {
+                       fail(exc.what());
+               }
 
-               while(1)
+               if(token.empty())
+                       break;
+       }
+}
+
+void GlslCompilerTest::verify_error(const string &output, const string &expected)
+{
+       auto i = output.begin();
+       auto j = expected.begin();
+       bool space = true;
+       while(i!=output.end() && j!=expected.end())
+       {
+               if(*i==*j)
                {
-                       string token = expected_tkn.parse_token();
-
-                       try
-                       {
-                               tokenizer.expect(token);
-                       }
-                       catch(const GL::SL::invalid_shader_source &exc)
-                       {
-                               fail(exc.what());
-                       }
-
-                       if(token.empty())
-                               break;
+                       ++i;
+                       ++j;
+               }
+               else if(isspace(*i) && isspace(*j))
+               {
+                       ++i;
+                       ++j;
+                       space = true;
+               }
+               else if(space && isspace(*i))
+                       ++i;
+               else if(space && isspace(*j))
+                       ++j;
+               else
+               {
+                       string out_line = extract_line(output, i);
+                       string expect_line = extract_line(expected, j);
+                       fail(format("Incorrect error line:\n%s\nExpected:\n%s", out_line, expect_line));
                }
        }
 
-       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)));
+       while(i!=output.end() && isspace(*i))
+               ++i;
+       while(j!=expected.end() && isspace(*j))
+               ++j;
+}
+
+string GlslCompilerTest::extract_line(const string &text, const string::const_iterator &iter)
+{
+       string::const_iterator begin = iter;
+       for(; (begin!=text.begin() && *begin!='\n'); --begin) ;
+       if(*begin=='\n')
+               ++begin;
+       string::const_iterator end = iter;
+       for(; (end!=text.end() && *end!='\n'); ++end) ;
+       return string(begin, end);
 }