#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;
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;
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>");
}
}
-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();
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) ;
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)));
+}