00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef __TEST_DRIVER_HH
00018 # define __TEST_DRIVER_HH
00019
00020 # include <memory>
00021 # include "../dataset/dataset.hh"
00022 # include <iostream>
00023 # include "../axioms/axioms.hh"
00024 # include "../utils/type_to_string.hh"
00025 # include "../type_traits/always_false.hh"
00026 # include "../type_traits/identity.hh"
00027
00028 namespace catsfoot {
00029
00030 template <typename T, typename U>
00031 struct printable;
00032
00033 namespace details {
00035 template <
00036 typename Stream,
00037 typename T,
00038 ENABLE_IF(printable<Stream&, T>)>
00039 void print_if_printable(Stream& s, T&& t) {
00040 s << t;
00041 }
00042
00044 template <
00045 typename Stream,
00046 typename T,
00047 ENABLE_IF_NOT(printable<Stream&, T>),
00048 typename = void>
00049 void print_if_printable(Stream& s, T&&) {
00050 s << "Values of type " << type_to_string<T>() << " are not printable";
00051 }
00052
00054 void display_values() {
00055 }
00056
00058 template <typename T, typename... U>
00059 void display_values(T&& t, U&&... u) {
00060 std::cerr << " * ";
00061 if (std::is_same<typename std::remove_reference<T>::type, T&&>::value) {
00062 std::cerr << "Moved variable not printable.";
00063 }
00064 else
00065 print_if_printable(std::cerr, std::forward<T>(t));
00066 std::cerr << std::endl;
00067 display_values(std::forward<U>(u)...);
00068 }
00069
00070 template <typename... T>
00071 struct tester;
00072
00073 template <>
00074 struct tester<> {
00075 template <typename Generator, typename Fun, typename... Params,
00076 typename Stream>
00077 static bool call_gen_final(Stream& s,
00078 Generator&, Fun f, Params&&... values) {
00079 try {
00080 f((std::forward<Params>(values))...);
00081 return true;
00082 } catch (axiom_failure af) {
00083 s << "-----------------------------------------"
00084 "---------------------------------------" << std::endl;
00085 s << af.msg() << std::endl;
00086 s << "Values were: " << std::endl;
00087 display_values(std::forward<Params>(values)...);
00088 s << std::endl;
00089 return false;
00090 }
00091 }
00092 template <typename Generator, typename Fun, typename... Params,
00093 typename Stream>
00094 static bool call_gen(Stream& s,
00095 Generator& g, Fun f, Params&&... values) {
00096 return call_gen_final(s, g, f, *std::forward<Params>(values)...);
00097 }
00098 };
00099
00100
00101 template <typename T, typename... U>
00102 struct tester<T, U...> {
00103 template <typename Generator, typename Fun, typename... Params,
00104 typename Stream>
00105 static bool call_gen(Stream& s, Generator& g, Fun f,
00106 Params&&... values) {
00107 auto container = g.get(selector<T>{});
00108 bool ret = true;
00109 for (auto i = container.begin();
00110 i != container.end(); ++i) {
00111 bool ret2 =
00112 tester<U...>::call_gen(s, g,
00113 f,
00114 std::forward<Params>(values)...,
00115 i);
00116 ret = ret && ret2;
00117 }
00118 return ret;
00119 }
00120 };
00121 }
00122
00124 template <typename Generator,
00125 typename... T, typename Stream = decltype(std::cerr)>
00126 bool test(Generator& g,
00127 void f(T...),
00128 std::string name = "<unknown>",
00129 Stream& s = std::cerr) {
00130 if (details::tester<T...>::call_gen(s, g, f)) {
00131 s << name << ": passed." << std::endl;
00132 return true;
00133 } else {
00134 s << name << ": failed." << std::endl;
00135 return false;
00136 }
00137 }
00138
00149 template <typename Fun, typename... Params>
00150 bool catch_errors(Fun f, Params&&... values) {
00151 default_generator d;
00152 return details::tester<>::call_gen_final(std::cerr,
00153 d,
00154 f,
00155 std::forward<Params>(values)...);
00156 }
00157 }
00158
00159 #endif