Mercurial > public > fructose_gen
changeset 0:d098192f01d9
Initial commit to the repository.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Sat, 19 Mar 2011 19:53:12 -0500 |
parents | |
children | 62a54c46da31 |
files | .hgignore README.markdown fructose_gen.py tests/g.cpp tests/g1.h tests/g2.h tests/g3.h tests/g_expected.cpp tests/test.bash tests/x.cpp tests/x1.h tests/x2.h tests/x3.h tests/x_expected.cpp |
diffstat | 14 files changed, 828 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Sat Mar 19 19:53:12 2011 -0500 @@ -0,0 +1,3 @@ +syntax: glob +*.pyc +*.swp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README.markdown Sat Mar 19 19:53:12 2011 -0500 @@ -0,0 +1,93 @@ +fructose_gen.py +=============== + +Quick Start +----------- + +`fructose_gen.py` is a Python script for auto-generatng the `main()` function +for the C++ testing framework [Fructose][1]. + +Sample usage: + + $ python fructose_gen.py [options] test1.h test2.h ... testN.h > main.cpp + +In this example, `fructose_gen.py` will read the Fructose test files `test1.h` +through `testN.h` and produce on standard output C++ code with a generated +`main()` function. This auto-generated code will instantiate all the test +instances, register the appropriate tests with each instance, and then execute +each test in turn. + +To see usage information and a list of options: + + $ python fructose_gen.py --help + + +Code Generation Styles +---------------------- + +`fructose_gen.py` supports two styles of code generation, described below. + +### xUnit Style ### + +The default style is xUnit style. In this form, `fructose_gen.py` will scan +C++ code looking for classes or structs that inherit from `fructose::test_base<>`. +Inside those classes or structs, member functions that match the following +pattern are assumed to be test functions: + + void testXXXX(const std::string&) + +Upon finding such a function, `fructose_gen.py` will register that member +function as a test with the name "testXXXX". + + +### Generator Style ### + +To remain backward compatible with the `generator` program that ships with +Fructose, invoke `fructose_gen.py` with a `-g` or `--generator` option flag. + +In this style, `fructose_gen.py` will scan files for the `FRUCTOSE_CLASS`, +`FRUCTOSE_STRUCT` and `FRUCTOSE_TEST` macros. See the Fructose documentation +for more information. + + +Caveats +------- + +`fructose_gen.py` is not a true C++ code parser, and in fact is quite simple +in how it operates. This is sufficient for most cases, but please be aware of +the following limitations. + +1. Ensure your class (or struct) definition is all on one line: + + class my_unit_test : public fructose::test_base<my_unit_test> + + If you split the above across multiple lines `fructose_gen.py` will not + recognize your class and will not generate a test instance for it. + +2. `fructose_gen.py` does not understand C-style comments or the preprocessor. + To comment out a test, you can either use C++ comments, or change the function + name slightly to ensure it won't be recognized. Examples: + + /* + ** void test_is_sorted(const std::string& name) // this won't work + */ + + #if 0 + void test_is_sorted(const std::string& name) // this won't work + #endif + + void not_a_test_is_sorted(const std::string& name) // this works + // void test_is_sorted(const std::string& name) // this works + // FRUCTOSE_TEST(is_sorted) // this works + + The above also applies to commenting out test classes. + + +Support +------- +See the [fructose_gen support site][2] hosted at [bitbucket.org][3]. + + +[1]: http://fructose.sourceforge.net/ +[2]: https://bitbucket.org/bgneal/fructose_gen +[3]: https://bitbucket.org
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fructose_gen.py Sat Mar 19 19:53:12 2011 -0500 @@ -0,0 +1,222 @@ +#!/usr/bin/env python +""" +Copyright (C) 2011 by Brian Neal <bgneal@gmail.com> + +fructose_gen.py - A program to auto-generate the main() routine for the C++ +testing framework Fructose. + +""" +from __future__ import with_statement +import re +import optparse +import sys + + +USAGE = "usage: %prog [options] test1.h test2.h ... > main.cpp" +DESCRIPTION = "Generates the main() routine for the Fructose C++ testing framework" +VERSION = "%prog 0.1" +INDENT_CNT = 4 +INDENT = " " * INDENT_CNT + + +def strip_comments(s): + """ + A simple function to strip out C++ style // comments from a string. + This function is really dumb; it doesn't know about string literals, etc., + but it should suit our purposes for finding commented out test classes and + cases. + + """ + i = s.find('//') + return s if i == -1 else s[:i] + + +class TestClass(object): + """ + This class represents a Fructose test class. + Each test class has a name attribute and a list of test case names + (strings). + + """ + def __init__(self, name): + self.name = name + self.test_cases = [] + + +class TestFile(object): + """ + A class to represent a Fructose unit test file. + Each test file has a filename attribute and a list of test classes. + + """ + def __init__(self, filename): + self.filename = filename + self.test_classes = [] + + +class TestFileParser(object): + """ + Base class for parsing Fructose unit test files. + """ + def __init__(self, filename): + self.test_file = TestFile(filename) + + def parse(self): + """ + Parse the file by reading it line by line. + Returns a TestFile object that contains the test classes found within. + + """ + with open(self.test_file.filename, 'r') as f: + for line in f: + s = strip_comments(line) + if s: + self._parse_line(s) + + return self.test_file + + def _parse_line(self, line): + """ + Parses each line of the test file, calling into derived classes to + find test classes and test cases. + + """ + test_class = self._parse_test_class(line) + if test_class: + self.test_file.test_classes.append(test_class) + else: + test_case = self._parse_test_case(line) + if len(self.test_file.test_classes) and test_case: + self.test_file.test_classes[-1].test_cases.append(test_case) + + def _parse_test_class(self, line): + """Derived classes override this""" + raise NotImplementedError + + def _parse_test_case(self, line): + """Derived classes override this""" + raise NotImplementedError + + +class GeneratorFileParser(TestFileParser): + """ + This class parses Fructose test files using the generator style of code + generation. + + """ + CLASS_RE = re.compile(r'\bFRUCTOSE_(?:CLASS|STRUCT)\s*\(\s*([a-zA-Z_]\w*)\s*\)') + CASE_RE = re.compile(r'\bFRUCTOSE_TEST\s*\(\s*([a-zA-Z_]\w*)\s*\)') + + def _parse_test_class(self, line): + m = self.CLASS_RE.search(line) + return TestClass(m.group(1)) if m else None + + def _parse_test_case(self, line): + m = self.CASE_RE.search(line) + return m.group(1) if m else None + + +class XunitFileParser(TestFileParser): + """ + This class parses Fructose test files using the xUnit style of code + generation. + + """ + CLASS_RE = re.compile(r'\b(?:struct|class)\s+([a-zA-Z_]\w*)\s+:\s+public' + r'\s+(?:fructose\s*::\s*)?test_base\s*<\s*\1\s*>') + + CASE_RE = re.compile(r'\bvoid\s+(test\w+)\s*\(const\s+(?:std::)?string\s*&' + r'(?:\s+[a-zA-Z_]\w+)?\s*\)') + + def _parse_test_class(self, line): + m = self.CLASS_RE.search(line) + return TestClass(m.group(1)) if m else None + + def _parse_test_case(self, line): + m = self.CASE_RE.search(line) + return m.group(1) if m else None + + +def generate_test_instance(test_class): + """ + Generates the code to instantiate a test instance, register and run the + tests. + + """ + type_name = test_class.name + instance = type_name + '_instance' + + print "%s{" % INDENT + block_indent = INDENT * 2 + print "%s%s %s;" % (block_indent, type_name, instance) + for test_case in test_class.test_cases: + print '%s%s.add_test("%s", &%s::%s);' % ( + block_indent, + instance, + test_case, + type_name, + test_case, + ) + print "%sconst int r = %s.run(argc, argv);" % (block_indent, instance) + print "%sretval = retval == EXIT_SUCCESS ? r : EXIT_FAILURE;" % block_indent + print "%s}" % INDENT + + + +def generate_main(test_files): + """ + Generates the main() file given a list of TestFile objects. + + """ + for test_file in test_files: + print '#include "%s"' % test_file.filename + + print '\n#include <stdlib.h>\n' + print 'int main(int argc, char* argv[])\n{' + print '%sint retval = EXIT_SUCCESS;\n' % INDENT + + for test_file in test_files: + for test_class in test_file.test_classes: + generate_test_instance(test_class) + + print '\n%sreturn retval;\n}' % INDENT + + +def main(argv=None): + + parser = optparse.OptionParser(usage=USAGE, description=DESCRIPTION, + version=VERSION) + parser.set_defaults( + generator=False, + ) + parser.add_option("-g", "--generator", action="store_true", + help="use generator style code generation [default: %default]") + + opts, args = parser.parse_args(args=argv) + + xunit = not opts.generator + + parser_class = XunitFileParser if xunit else GeneratorFileParser + + if len(args) == 0: + sys.exit("No input files") + + test_files = [] + for test_file in args: + + test_parser = parser_class(test_file) + try: + test_files.append(test_parser.parse()) + except IOError, ex: + sys.stderr.write("Error parsing %s: %s, skipping" % (test_file, ex)) + + generate_main(test_files) + + +if __name__ == '__main__': + try: + main() + except IOError, ex: + sys.exit("IO Error: %s" % ex) + except KeyboardInterrupt: + sys.exit("Control-C interrupt")
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/g.cpp Sat Mar 19 19:53:12 2011 -0500 @@ -0,0 +1,41 @@ +#include "g1.h" +#include "g2.h" +#include "g3.h" + +#include <stdlib.h> + +int main(int argc, char* argv[]) +{ + int retval = EXIT_SUCCESS; + + { + sample_test sample_test_instance; + sample_test_instance.add_test("test42", &sample_test::test42); + sample_test_instance.add_test("beast", &sample_test::beast); + sample_test_instance.add_test("fivealive", &sample_test::fivealive); + const int r = sample_test_instance.run(argc, argv); + retval = retval == EXIT_SUCCESS ? r : EXIT_FAILURE; + } + { + misc_tests misc_tests_instance; + misc_tests_instance.add_test("exceptions", &misc_tests::exceptions); + misc_tests_instance.add_test("loopdata", &misc_tests::loopdata); + misc_tests_instance.add_test("floatingpoint", &misc_tests::floatingpoint); + const int r = misc_tests_instance.run(argc, argv); + retval = retval == EXIT_SUCCESS ? r : EXIT_FAILURE; + } + { + exception_test exception_test_instance; + exception_test_instance.add_test("array_bounds", &exception_test::array_bounds); + exception_test_instance.add_test("should_catch_std_exceptions", &exception_test::should_catch_std_exceptions); + const int r = exception_test_instance.run(argc, argv); + retval = retval == EXIT_SUCCESS ? r : EXIT_FAILURE; + } + { + MyTest MyTest_instance; + const int r = MyTest_instance.run(argc, argv); + retval = retval == EXIT_SUCCESS ? r : EXIT_FAILURE; + } + + return retval; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/g1.h Sat Mar 19 19:53:12 2011 -0500 @@ -0,0 +1,29 @@ +#ifndef FRUCTOSE_MAIN_TEST_X1_H +#define FRUCTOSE_MAIN_TEST_X1_H + +#include "fructose/fructose.h" + +const int life_the_available_tests_and_everything = 42; +const int the_neighbour_of_the_beast = 668; +const int is_alive = 6; + +FRUCTOSE_CLASS(sample_test) +{ +public: + FRUCTOSE_TEST(test42) + { + fructose_assert(life_the_available_tests_and_everything == 6*7); + } + + FRUCTOSE_TEST(beast) + { + fructose_assert(the_neighbour_of_the_beast == 668); + } + + FRUCTOSE_TEST(fivealive) + { + const int five = 5; + fructose_assert_eq(five, is_alive); + } +}; +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/g2.h Sat Mar 19 19:53:12 2011 -0500 @@ -0,0 +1,68 @@ +#ifndef FRUCTOSE_MAIN_TEST_X2_H +#define FRUCTOSE_MAIN_TEST_X2_H + +#include <stdexcept> +#include <cmath> + +#include "fructose/fructose.h" + +// These tests are rigged so that some of them fail. +// The tests include exercising floating point comparisons +// and exception handling. + +namespace { + void throw_a_runtime_error() + { + throw std::runtime_error("this is a runtime error"); + } +} + +FRUCTOSE_STRUCT(misc_tests) +{ + FRUCTOSE_TEST(exceptions) + { + fructose_assert_exception(throw_a_runtime_error(), std::logic_error); + fructose_assert_no_exception(throw_a_runtime_error()); + } + + FRUCTOSE_TEST(loopdata) + { + static const struct { + int line_number; + int a; + int b; + int expected_result; + } data[] = { + {__LINE__, 3, 4, 12} + , {__LINE__, 1, 50, 50} + , {__LINE__, 5, 12, 60} + , {__LINE__, 6, 6, 37} + , {__LINE__, 7, 10, 70} + }; + + for (std::size_t i = 0; i < sizeof(data)/sizeof(data[0]); ++i) + { + if (verbose()) + { + std::cout << "Testing to see if " + << data[i].a << " * " << data[i].b + << " = " << data[i].expected_result + << std::endl; + } + int result = data[i].a * data[i].b; + fructose_loop1_assert(data[i].line_number, i, + result == data[i].expected_result); + } + } + + FRUCTOSE_TEST(floatingpoint) + { + double my_pi = 3.141592654; + double calc_pi = 4.0 * atan(1.0); + fructose_assert_double_eq_rel_abs(my_pi, calc_pi, 0.01, 0.01); + fructose_assert_double_eq(my_pi, calc_pi); + fructose_assert_double_ne(my_pi, calc_pi); + fructose_assert_double_ne_rel_abs(my_pi, calc_pi, 0.01, 0.01); + } +}; +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/g3.h Sat Mar 19 19:53:12 2011 -0500 @@ -0,0 +1,64 @@ +#ifndef FRUCTOSE_MAIN_TEST_X3_H +#define FRUCTOSE_MAIN_TEST_X3_H + +#include <stdexcept> +#include <vector> + +#include "fructose/fructose.h" + +struct my_logic_error : public std::logic_error +{ + my_logic_error(const char* message) : std::logic_error(message) {} +}; + +struct my_runtime_error : public std::runtime_error +{ + my_runtime_error(const char* message) : std::runtime_error(message) {} +}; + +FRUCTOSE_CLASS(exception_test) +{ +public: + FRUCTOSE_TEST(array_bounds) + { + std::vector<int> v; + v.push_back(1234); + fructose_assert_exception(v.at(2), std::out_of_range); + } + + FRUCTOSE_TEST(should_catch_std_exceptions) + { + fructose_assert_exception(throw my_logic_error("a coding error has been detected"), + std::logic_error); + fructose_assert_exception(throw my_runtime_error("my runtime error"), + std::runtime_error); + fructose_assert_exception(throw my_logic_error("another coding error has been detected"), + std::exception); + fructose_assert_exception(throw my_runtime_error("my runtime error"), + std::exception); + } + + //FRUCTOSE_TEST(commented_out) + //{ + // fructose_assert(false); + //} +}; + +// FRUCTOSE_CLASS(MyTest) +// { +// public: +// void testIt(const std::string&) +// { +// fructose_assert(true); +// } +// }; + +FRUCTOSE_CLASS(MyTest) +{ +public: + void testIt(const std::string&) + { + fructose_assert(true); + } +}; +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/g_expected.cpp Sat Mar 19 19:53:12 2011 -0500 @@ -0,0 +1,41 @@ +#include "g1.h" +#include "g2.h" +#include "g3.h" + +#include <stdlib.h> + +int main(int argc, char* argv[]) +{ + int retval = EXIT_SUCCESS; + + { + sample_test sample_test_instance; + sample_test_instance.add_test("test42", &sample_test::test42); + sample_test_instance.add_test("beast", &sample_test::beast); + sample_test_instance.add_test("fivealive", &sample_test::fivealive); + const int r = sample_test_instance.run(argc, argv); + retval = retval == EXIT_SUCCESS ? r : EXIT_FAILURE; + } + { + misc_tests misc_tests_instance; + misc_tests_instance.add_test("exceptions", &misc_tests::exceptions); + misc_tests_instance.add_test("loopdata", &misc_tests::loopdata); + misc_tests_instance.add_test("floatingpoint", &misc_tests::floatingpoint); + const int r = misc_tests_instance.run(argc, argv); + retval = retval == EXIT_SUCCESS ? r : EXIT_FAILURE; + } + { + exception_test exception_test_instance; + exception_test_instance.add_test("array_bounds", &exception_test::array_bounds); + exception_test_instance.add_test("should_catch_std_exceptions", &exception_test::should_catch_std_exceptions); + const int r = exception_test_instance.run(argc, argv); + retval = retval == EXIT_SUCCESS ? r : EXIT_FAILURE; + } + { + MyTest MyTest_instance; + const int r = MyTest_instance.run(argc, argv); + retval = retval == EXIT_SUCCESS ? r : EXIT_FAILURE; + } + + return retval; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test.bash Sat Mar 19 19:53:12 2011 -0500 @@ -0,0 +1,23 @@ +#!/bin/bash + +INCLUDES="-I../../fructose/include -I../../tclap-1.2.0/include" + +../fructose_gen.py x1.h x2.h x3.h > x.cpp +#g++ -o x.out $INCLUDES x.cpp + +../fructose_gen.py --generator g1.h g2.h g3.h > g.cpp +#g++ -o g.out $INCLUDES g.cpp + +diff x_expected.cpp x.cpp >/dev/null +if [ $? -eq 0 ]; then + echo "xunit style passed" +else + echo "xunit style failed" +fi + +diff g_expected.cpp g.cpp >/dev/null +if [ $? -eq 0 ]; then + echo "generator style passed" +else + echo "generator style failed" +fi
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/x.cpp Sat Mar 19 19:53:12 2011 -0500 @@ -0,0 +1,42 @@ +#include "x1.h" +#include "x2.h" +#include "x3.h" + +#include <stdlib.h> + +int main(int argc, char* argv[]) +{ + int retval = EXIT_SUCCESS; + + { + sample_test sample_test_instance; + sample_test_instance.add_test("test42", &sample_test::test42); + sample_test_instance.add_test("testbeast", &sample_test::testbeast); + sample_test_instance.add_test("testfivealive", &sample_test::testfivealive); + const int r = sample_test_instance.run(argc, argv); + retval = retval == EXIT_SUCCESS ? r : EXIT_FAILURE; + } + { + misc_tests misc_tests_instance; + misc_tests_instance.add_test("testexceptions", &misc_tests::testexceptions); + misc_tests_instance.add_test("testloopdata", &misc_tests::testloopdata); + misc_tests_instance.add_test("testfloatingpoint", &misc_tests::testfloatingpoint); + const int r = misc_tests_instance.run(argc, argv); + retval = retval == EXIT_SUCCESS ? r : EXIT_FAILURE; + } + { + exception_test exception_test_instance; + exception_test_instance.add_test("test_array_bounds", &exception_test::test_array_bounds); + exception_test_instance.add_test("test_should_catch_std_exceptions", &exception_test::test_should_catch_std_exceptions); + const int r = exception_test_instance.run(argc, argv); + retval = retval == EXIT_SUCCESS ? r : EXIT_FAILURE; + } + { + MyTest MyTest_instance; + MyTest_instance.add_test("testIt", &MyTest::testIt); + const int r = MyTest_instance.run(argc, argv); + retval = retval == EXIT_SUCCESS ? r : EXIT_FAILURE; + } + + return retval; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/x1.h Sat Mar 19 19:53:12 2011 -0500 @@ -0,0 +1,28 @@ +#ifndef FRUCTOSE_MAIN_TEST_X1_H +#define FRUCTOSE_MAIN_TEST_X1_H + +#include "fructose/fructose.h" + +const int life_the_available_tests_and_everything = 42; +const int the_neighbour_of_the_beast = 668; +const int is_alive = 6; + +struct sample_test : public fructose::test_base<sample_test> +{ + void test42(const std::string& test_name) + { + fructose_assert(life_the_available_tests_and_everything == 6*7); + } + + void testbeast(const std::string& test_name) + { + fructose_assert(the_neighbour_of_the_beast == 668); + } + + void testfivealive(const std::string& test_name) + { + const int five = 5; + fructose_assert_eq(five, is_alive); + } +}; +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/x2.h Sat Mar 19 19:53:12 2011 -0500 @@ -0,0 +1,69 @@ +#ifndef FRUCTOSE_MAIN_TEST_X2_H +#define FRUCTOSE_MAIN_TEST_X2_H + +#include <stdexcept> +#include <cmath> + +#include "fructose/fructose.h" + +// These tests are rigged so that some of them fail. +// The tests include exercising floating point comparisons +// and exception handling. + +namespace { + void throw_a_runtime_error() + { + throw std::runtime_error("this is a runtime error"); + } +} + +class misc_tests : public fructose::test_base<misc_tests> +{ +public: + void testexceptions(const std::string& test_name) + { + fructose_assert_exception(throw_a_runtime_error(), std::logic_error); + fructose_assert_no_exception(throw_a_runtime_error()); + } + + void testloopdata(const std::string& test_name) + { + static const struct { + int line_number; + int a; + int b; + int expected_result; + } data[] = { + {__LINE__, 3, 4, 12} + , {__LINE__, 1, 50, 50} + , {__LINE__, 5, 12, 60} + , {__LINE__, 6, 6, 37} + , {__LINE__, 7, 10, 70} + }; + + for (std::size_t i = 0; i < sizeof(data)/sizeof(data[0]); ++i) + { + if (verbose()) + { + std::cout << "Testing to see if " + << data[i].a << " * " << data[i].b + << " = " << data[i].expected_result + << std::endl; + } + int result = data[i].a * data[i].b; + fructose_loop1_assert(data[i].line_number, i, + result == data[i].expected_result); + } + } + + void testfloatingpoint(const std::string& test_name) + { + double my_pi = 3.141592654; + double calc_pi = 4.0 * atan(1.0); + fructose_assert_double_eq_rel_abs(my_pi, calc_pi, 0.01, 0.01); + fructose_assert_double_eq(my_pi, calc_pi); + fructose_assert_double_ne(my_pi, calc_pi); + fructose_assert_double_ne_rel_abs(my_pi, calc_pi, 0.01, 0.01); + } +}; +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/x3.h Sat Mar 19 19:53:12 2011 -0500 @@ -0,0 +1,63 @@ +#ifndef FRUCTOSE_MAIN_TEST_X3_H +#define FRUCTOSE_MAIN_TEST_X3_H + +#include <stdexcept> +#include <vector> + +#include "fructose/fructose.h" + +struct my_logic_error : public std::logic_error +{ + my_logic_error(const char* message) : std::logic_error(message) {} +}; + +struct my_runtime_error : public std::runtime_error +{ + my_runtime_error(const char* message) : std::runtime_error(message) {} +}; + +struct exception_test : public fructose::test_base<exception_test> +{ + void test_array_bounds(const std::string&) + { + std::vector<int> v; + v.push_back(1234); + fructose_assert_exception(v.at(2), std::out_of_range); + } + + void test_should_catch_std_exceptions(const std::string& ) + { + fructose_assert_exception(throw my_logic_error("a coding error has been detected"), + std::logic_error); + fructose_assert_exception(throw my_runtime_error("my runtime error"), + std::runtime_error); + fructose_assert_exception(throw my_logic_error("another coding error has been detected"), + std::exception); + fructose_assert_exception(throw my_runtime_error("my runtime error"), + std::exception); + } + + //void test_commented_out(const std::string&) + //{ + // fructose_assert(false); + //} +}; + +// class MyTest : public fructose::test_base<MyTest> +// { +// public: +// void testIt(const std::string&) +// { +// fructose_assert(true); +// } +// }; + +class MyTest : public fructose::test_base<MyTest> +{ +public: + void testIt(const std::string&) + { + fructose_assert(true); + } +}; +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/x_expected.cpp Sat Mar 19 19:53:12 2011 -0500 @@ -0,0 +1,42 @@ +#include "x1.h" +#include "x2.h" +#include "x3.h" + +#include <stdlib.h> + +int main(int argc, char* argv[]) +{ + int retval = EXIT_SUCCESS; + + { + sample_test sample_test_instance; + sample_test_instance.add_test("test42", &sample_test::test42); + sample_test_instance.add_test("testbeast", &sample_test::testbeast); + sample_test_instance.add_test("testfivealive", &sample_test::testfivealive); + const int r = sample_test_instance.run(argc, argv); + retval = retval == EXIT_SUCCESS ? r : EXIT_FAILURE; + } + { + misc_tests misc_tests_instance; + misc_tests_instance.add_test("testexceptions", &misc_tests::testexceptions); + misc_tests_instance.add_test("testloopdata", &misc_tests::testloopdata); + misc_tests_instance.add_test("testfloatingpoint", &misc_tests::testfloatingpoint); + const int r = misc_tests_instance.run(argc, argv); + retval = retval == EXIT_SUCCESS ? r : EXIT_FAILURE; + } + { + exception_test exception_test_instance; + exception_test_instance.add_test("test_array_bounds", &exception_test::test_array_bounds); + exception_test_instance.add_test("test_should_catch_std_exceptions", &exception_test::test_should_catch_std_exceptions); + const int r = exception_test_instance.run(argc, argv); + retval = retval == EXIT_SUCCESS ? r : EXIT_FAILURE; + } + { + MyTest MyTest_instance; + MyTest_instance.add_test("testIt", &MyTest::testIt); + const int r = MyTest_instance.run(argc, argv); + retval = retval == EXIT_SUCCESS ? r : EXIT_FAILURE; + } + + return retval; +}