Home | History | Annotate | Download | only in unittest
      1 // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
      2 
      3 #pragma once
      4 
      5 #include <iostream>
      6 #include <iomanip>
      7 #include <exception>
      8 #include <sstream>
      9 #include <utility>
     10 #include <memory>
     11 #include <cstddef>
     12 
     13 struct empty_testcase{ void run(){} const char* name(){return 0;} };
     14 
     15 template <std::size_t offset>
     16 struct testcase : empty_testcase{};
     17 
     18 
     19 template <std::size_t begin, std::size_t end>
     20 struct testrange {
     21     void run(std::size_t& pass, std::size_t& fail)
     22     {
     23         using namespace std;
     24         {   testcase<begin> a_case;
     25             if (a_case.name()) {
     26                 std::size_t p=0, f=0;
     27                 cout << "TEST: Running " << a_case.name() << endl;
     28                 try {
     29                     a_case.run();
     30                     ++p;
     31                 } catch (logic_error& e) {
     32                     cerr << "ERRORS:" << endl;
     33                     cerr << "  " << e.what() << endl;
     34                     ++f;
     35                 }
     36                 pass += p; fail += f;
     37             }
     38         }
     39         const std::size_t rem = (end-begin-1);
     40         testrange<begin+1, begin+1+rem/2>().run(pass, fail);
     41         testrange<begin+1+rem/2, end>().run(pass, fail);
     42     }
     43 };
     44 
     45 template <std::size_t begin>
     46 struct testrange<begin,begin> {
     47     void run(std::size_t& pass, std::size_t& fail) {};
     48 };
     49 
     50 #define TEST(fun_name) \
     51 void fun_name (); \
     52 template <> \
     53 struct testcase<__LINE__> { \
     54     const char* name() { return(#fun_name); } \
     55     void run() { fun_name(); } \
     56 }; \
     57 void fun_name()
     58 
     59 #define Q_(e) #e
     60 #define Q(e)  Q_(e)
     61 #define TASSERT(expr) \
     62     { auto e = (expr); if (!e) { throw std::logic_error(__FILE__ "(" Q(__LINE__) "): TASSERT("#expr")"); }  }
     63 
     64 struct errmsg
     65 {
     66     std::shared_ptr<std::stringstream> msg;
     67     errmsg() : msg(new std::stringstream)
     68     {}
     69 
     70     template <class T>
     71     errmsg& operator<<(T value)
     72     {
     73         (*msg) << value;
     74         return *this;
     75     }
     76     std::string str() { return msg->str(); }
     77 };
     78 
     79 #define TEST_WHERE  __FILE__ "(" Q(__LINE__) "): "
     80 #define VERIFY(expr) \
     81     { auto e = (expr); if (!e) { throw std::logic_error(TEST_WHERE "VERIFY("#expr")"); }  }
     82 #define VERIFY_EQ(expected, actual) \
     83     { auto e = (expected); auto a = (actual); \
     84       if (!(e == a)) { \
     85         throw std::logic_error( \
     86           (errmsg() << TEST_WHERE << "(" << e << ")!=(" << a << ") in VERIFY_EQ("#expected","#actual")").str() );}}
     87 
     88 
     89