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;
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;
continue;
}
+ expected = line.find("Expected error:");
+ if(expected!=string::npos)
+ {
+ target = &test_case.expected_error;
+ continue;
+ }
+
*target += line;
*target += '\n';
}
{
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)
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);
}