X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=tests%2Fglsl%2Fglslcompiler.cpp;h=30805db3ff80a2b8be88c2ad868c1bcbd33ea253;hb=1f870744029d50f29a060ddf68b8b7c40c6ef1ed;hp=f38db45caa6c5638e06044a624055ef2f0e63ed4;hpb=e195322eb1251f2eb0d6dfb8c2dc0fff02e5fcfc;p=libs%2Fgl.git diff --git a/tests/glsl/glslcompiler.cpp b/tests/glsl/glslcompiler.cpp index f38db45c..30805db3 100644 --- a/tests/glsl/glslcompiler.cpp +++ b/tests/glsl/glslcompiler.cpp @@ -16,7 +16,10 @@ private: { std::string name; std::string source; + Msp::GL::SL::Compiler::Mode compile_mode; + std::map spec_values; std::map expected_output; + std::string expected_error; }; std::list test_cases; @@ -30,6 +33,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; @@ -52,6 +58,7 @@ const GlslCompilerTest::TestCase &GlslCompilerTest::load_test_case(const string IO::BufferedFile file(fn); TestCase test_case; test_case.name = FS::basename(fn); + test_case.compile_mode = GL::SL::Compiler::PROGRAM; string *target = &test_case.source; while(!file.eof()) { @@ -62,10 +69,10 @@ const GlslCompilerTest::TestCase &GlslCompilerTest::load_test_case(const string if(line=="*/") continue; - string::size_type expected = line.find("Expected output:"); - if(expected!=string::npos) + string::size_type pos = line.find("Expected output:"); + if(pos!=string::npos) { - string stage = strip(line.substr(expected+16)); + string stage = strip(line.substr(pos+16)); if(stage=="vertex") target = &test_case.expected_output[GL::SL::Stage::VERTEX]; else if(stage=="geometry") @@ -77,6 +84,41 @@ const GlslCompilerTest::TestCase &GlslCompilerTest::load_test_case(const string continue; } + pos = line.find("Expected error:"); + if(pos!=string::npos) + { + target = &test_case.expected_error; + continue; + } + + pos = line.find("Compile mode:"); + if(pos!=string::npos) + { + string mode = strip(line.substr(pos+13)); + if(mode=="module") + test_case.compile_mode = GL::SL::Compiler::MODULE; + else if(mode=="program") + test_case.compile_mode = GL::SL::Compiler::PROGRAM; + else + throw runtime_error("Unknown compile mode "+mode); + continue; + } + + pos = line.find("Specialize:"); + if(pos!=string::npos) + { + vector parts = split(line.substr(pos+11)); + int value = 0; + if(parts[1]=="true") + value = 1; + else if(parts[1]=="false") + value = 0; + else + value = lexical_cast(parts[1]); + test_case.spec_values[parts[0]] = value; + continue; + } + *target += line; *target += '\n'; } @@ -88,8 +130,27 @@ const GlslCompilerTest::TestCase &GlslCompilerTest::load_test_case(const string void GlslCompilerTest::run_test_case(const TestCase *test_case) { GL::SL::Compiler compiler(GL::SL::Features::all()); - compiler.set_source(test_case->source, ""); - compiler.compile(GL::SL::Compiler::PROGRAM); + 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) @@ -104,31 +165,88 @@ void GlslCompilerTest::run_test_case(const TestCase *test_case) for(unsigned j=0; j"); + verify_output(output, i->second); + } - GL::SL::Tokenizer expected_tkn; - expected_tkn.begin(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))); +} - while(1) +void GlslCompilerTest::verify_output(const string &output, const string &expected) +{ + GL::SL::Tokenizer tokenizer; + tokenizer.begin(output, ""); + + GL::SL::Tokenizer expected_tkn; + expected_tkn.begin(expected, ""); + + while(1) + { + string token = expected_tkn.parse_token(); + + try { - 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; + tokenizer.expect(token); } + catch(const GL::SL::invalid_shader_source &exc) + { + fail(exc.what()); + } + + if(token.empty()) + break; } +} - 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_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) + { + ++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)); + } + } + + while(i!=output.end() && isspace(*i)) + ++i; + while(j!=expected.end() && isspace(*j)) + ++j; + + if(i!=output.end()) + fail(format("Extra error line: %s", extract_line(output, i))); + if(j!=expected.end()) + fail(format("Missing error line: %s", extract_line(expected, 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); }