Changeset 1379

Show
Ignore:
Timestamp:
08/15/08 00:31:44 (5 months ago)
Author:
jtv
Message:

Run all tests in directory as single program.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/ChangeLog

    r1378 r1379  
     12008-08-15  Jeroen T. Vermeulen <jtv@xs4all.nl> 
     2 test/Makefile.am.template, test/runner.cxx, test/test027.cxx, 
     3 test/test028.cxx, test/test029.cxx, test/test039.cxx, test/test_helpers.hxx, 
     4 test/unit/Makefile.am.template, test/unit/runner.cxx: 
     5  - Missed some spots in converting to test framework 
     6  - Run all tests in directory as single program! 
     7  - Test build & run now 20% faster on my laptop 
     8  - Should be easier to build tests with Visual C++'s stupid project files 
    192008-08-14  Jeroen T. Vermeulen <jtv@xs4all.nl> 
    210 test/test072.cxx, test/test073.cxx, test/test074.cxx, test/test075.cxx, 
  • trunk/test/Makefile.am.template

    r1300 r1379  
    1919# PGDATABASE, PGHOST, PGPORT, PGUSER 
    2020 
    21 TESTS = \ 
     21runner_SOURCES = \ 
    2222###MAKTEMPLATE:FOREACH test/test*.cxx 
    23   ###BASENAME###
     23  ###BASENAME###.cxx
    2424###MAKTEMPLATE:ENDFOREACH 
    25   # (end) 
     25  runner.cxx 
    2626 
     27runner_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} 
     28 
     29TESTS = runner 
    2730check_PROGRAMS = ${TESTS} 
    2831 
    29 ###MAKTEMPLATE:FOREACH test/test*.cxx 
    30 ###BASENAME###_SOURCES = ###BASENAME###.cxx 
    31 ###BASENAME###_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} 
     32# ###MAKTEMPLATE:FOREACH test/test*.cxx 
     33# ###BASENAME###_SOURCES = ###BASENAME###.cxx 
     34# ###BASENAME###_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} 
    3235 
  • trunk/test/test027.cxx

    r1138 r1379  
    77#include <pqxx/transaction> 
    88 
     9#include "test_helpers.hxx" 
     10 
    911using namespace PGSTD; 
    1012using namespace pqxx; 
     
    1315// Test program for libpqxx.  Read a table using a tablereader, which may be 
    1416// faster than a conventional query, on a lazy connection. 
    15 // 
    16 // Usage: test027 [connect-string] [table] 
    17 // 
    18 // Where connect-string is a set of connection options in Postgresql's 
    19 // PQconnectdb() format, eg. "dbname=template1" to select from a database 
    20 // called template1, or "host=foo.bar.net user=smith" to connect to a backend 
    21 // running on host foo.bar.net, logging in as user smith. 
    22 // 
    23 // The default table name is "pqxxevents" as used by other test programs. 
    24 // PostgreSQL currently implements pg_tables as a view, which cannot be read by 
    25 // using the COPY command.  Otherwise, pg_tables would have made a better 
    26 // default value here. 
    27 int main(int argc, char *argv[]) 
     17namespace 
    2818{ 
    29   try 
     19void test_027(connection_base &, transaction_base &T) 
     20
     21  const string Table = "pqxxevents"; 
     22 
     23  vector<string> R, First; 
     24 
    3025  { 
    31     // Set up a connection to the backend 
    32     lazyconnection C(argv[1]); 
     26    // Set up a tablereader stream to read data from table pg_tables 
     27    tablereader Stream(T, Table); 
    3328 
    34     string Table = "pqxxevents"; 
    35     if (argc > 2) Table = argv[2]; 
     29    // Read results into string vectors and print them 
     30    for (int n=0; (Stream >> R); ++n) 
     31    { 
     32      // Keep the first row for later consistency check 
     33      if (n == 0) First = R; 
    3634 
    37     // Begin a transaction acting on our current connection 
    38     work T(C, "test27"); 
    39  
    40     vector<string> R, First; 
    41  
    42     { 
    43       // Set up a tablereader stream to read data from table pg_tables 
    44       tablereader Stream(T, Table); 
    45  
    46       // Read results into string vectors and print them 
    47       for (int n=0; (Stream >> R); ++n) 
    48       { 
    49         // Keep the first row for later consistency check 
    50         if (n == 0) First = R; 
    51  
    52         cout << n << ":\t"; 
    53         for (vector<string>::const_iterator i = R.begin(); i != R.end(); ++i) 
    54           cout << *i << '\t'; 
    55         cout << endl; 
    56         R.clear(); 
    57       } 
    58     } 
    59  
    60     // Verify the contents we got for the first row 
    61     if (!First.empty()) 
    62     { 
    63       tablereader Verify(T, Table); 
    64       string Line; 
    65  
    66       if (!Verify.get_raw_line(Line)) 
    67         throw logic_error("tablereader got rows the first time around, " 
    68                           "but none the second time!"); 
    69  
    70       cout << "First tuple was: " << endl << Line << endl; 
    71  
    72       Verify.tokenize(Line, R); 
    73       if (R != First) 
    74         throw logic_error("Got different results re-parsing first tuple!"); 
     35      cout << n << ":\t"; 
     36      for (vector<string>::const_iterator i = R.begin(); i != R.end(); ++i) 
     37        cout << *i << '\t'; 
     38      cout << endl; 
     39      R.clear(); 
    7540    } 
    7641  } 
    77   catch (const sql_error &e) 
     42 
     43  // Verify the contents we got for the first row 
     44  if (!First.empty()) 
    7845  { 
    79     cerr << "SQL error: " << e.what() << endl 
    80          << "Query was: '" << e.query() << "'" << endl; 
    81     return 1; 
     46    tablereader Verify(T, Table); 
     47    string Line; 
     48 
     49    PQXX_CHECK( 
     50        Verify.get_raw_line(Line), 
     51        "tablereader got rows on the first read, but not on the second."); 
     52 
     53    cout << "First tuple was: " << endl << Line << endl; 
     54 
     55    Verify.tokenize(Line, R); 
     56    PQXX_CHECK_EQUAL( 
     57        R, 
     58        First, 
     59        "Re-parsing the first tuple yields different results."); 
    8260  } 
    83   catch (const exception &e) 
    84   { 
    85     cerr << "Exception: " << e.what() << endl; 
    86     return 2; 
    87   } 
    88   catch (...) 
    89   { 
    90     cerr << "Unhandled exception" << endl; 
    91     return 100; 
    92   } 
     61
     62} // namespace 
    9363 
    94   return 0; 
    95 
    96  
     64PQXX_REGISTER_TEST_C(test_027, lazyconnection) 
  • trunk/test/test028.cxx

    r1138 r1379  
    88#include <pqxx/transaction> 
    99 
     10#include "test_helpers.hxx" 
     11 
    1012using namespace PGSTD; 
    1113using namespace pqxx; 
     
    1416// Test program for libpqxx.  Create a table and write data to it, using 
    1517// tablewriter's back_insert_iterator, and on a lazy connection. 
    16 // 
    17 // Usage: test028 [connect-string] [table] 
    18 // 
    19 // Where the connect-string is a set of connection options in Postgresql's 
    20 // PQconnectdb() format, eg. "dbname=template1" to select from a database 
    21 // called template1, or "host=foo.bar.net user=smith" to connect to a backend 
    22 // running on host foo.bar.net, logging in as user smith. 
    23 // 
    24 // The default table name is "testtable." 
    25  
    2618namespace 
    2719{ 
     
    7163  size_t Rows = 0; 
    7264 
    73   if (!Count[0][0].to(Rows)) throw runtime_error("NULL row count!"); 
     65  PQXX_CHECK(Count[0][0].to(Rows), "Row count is NULL."); 
    7466  cout << Rows << " rows in table." << endl; 
    7567 
    76   if (Rows != Contents.size()) 
    77     throw runtime_error("Found " + 
    78                         string(Count[0][0].c_str()) + 
    79                         " rows in table--after writing " + 
    80                         to_string(Contents.size()) + 
    81                         "!"); 
    82  
     68  PQXX_CHECK_EQUAL(Rows, Contents.size(), "Got different number of rows back."); 
    8369  // TODO: Compare table contents to Contents 
    8470} 
     71 
     72 
     73void test_028(connection_base &, transaction_base &T) 
     74{ 
     75  PrepareContents(); 
     76 
     77  // Select our original and destination table names 
     78  const string TableName = "testtable"; 
     79 
     80  // Create table.  If the table already existed, better to fail now. 
     81  T.exec("CREATE TABLE " + TableName + "(content VARCHAR)"); 
     82 
     83  FillTable(T, TableName); 
     84  CheckTable(T, TableName); 
     85 
     86  T.exec("DROP TABLE " + TableName); 
     87  T.commit(); 
    8588} 
     89} // namespace 
    8690 
    87 int main(int argc, char *argv[]) 
    88 
    89   try 
    90   { 
    91     PrepareContents(); 
    92  
    93     // Set up two connections to the backend: one to read our original table, 
    94     // and another to write our copy 
    95     lazyconnection C(argv[1]); 
    96  
    97     // Select our original and destination table names 
    98     string TableName = "testtable"; 
    99     if (argc > 2) TableName = argv[2]; 
    100  
    101     work T(C, "test28"); 
    102  
    103     // Create table.  If the table already existed, better to fail now. 
    104     T.exec("CREATE TABLE " + TableName + "(content VARCHAR)"); 
    105  
    106     FillTable(T, TableName); 
    107     CheckTable(T, TableName); 
    108  
    109     T.exec("DROP TABLE " + TableName); 
    110     T.commit(); 
    111   } 
    112   catch (const sql_error &e) 
    113   { 
    114     cerr << "SQL error: " << e.what() << endl 
    115          << "Query was: '" << e.query() << "'" << endl; 
    116     return 1; 
    117   } 
    118   catch (const exception &e) 
    119   { 
    120     cerr << "Exception: " << e.what() << endl; 
    121     return 2; 
    122   } 
    123   catch (...) 
    124   { 
    125     cerr << "Unhandled exception" << endl; 
    126     return 100; 
    127   } 
    128  
    129   return 0; 
    130 
    131  
     91PQXX_REGISTER_TEST_C(test_028, lazyconnection) 
  • trunk/test/test029.cxx

    r1138 r1379  
    88#include <pqxx/result> 
    99 
     10#include "test_helpers.hxx" 
     11 
    1012using namespace PGSTD; 
    1113using namespace pqxx; 
     
    1517// abort it, and verify that it "never happened."  Use lazy connection. 
    1618// 
    17 // Usage: test029 [connect-string] 
    18 // 
    19 // Where connect-string is a set of connection options in Postgresql's 
    20 // PQconnectdb() format, eg. "dbname=template1" to select from a database 
    21 // called template1, or "host=foo.bar.net user=smith" to connect to a 
    22 // backend running on host foo.bar.net, logging in as user smith. 
    23 // 
    2419// The program will attempt to add an entry to a table called "pqxxevents", 
    2520// with a key column called "year"--and then abort the change. 
    26  
    2721namespace 
    2822{ 
    29  
    3023// Let's take a boring year that is not going to be in the "pqxxevents" table 
    3124const int BoringYear = 1977; 
     
    5447 
    5548 
    56  
    5749// Try adding a record, then aborting it, and check whether the abort was 
    5850// performed correctly. 
     
    7567    EventCounts = CountEvents(Doomed); 
    7668 
    77     if (EventCounts.second) 
    78       throw runtime_error("Can't run, year " + 
    79                           to_string(BoringYear) + " " 
    80                           "is already in table " + 
    81                           Table); 
     69    PQXX_CHECK_EQUAL( 
     70        EventCounts.second, 
     71        0, 
     72        "Can't run; " + to_string(BoringYear) + " is already in the table."); 
    8273 
    8374    // Now let's try to introduce a tuple for our Boring Year 
     
    8576      tablewriter W(Doomed, Table); 
    8677 
    87       if (W.name() != Table) 
    88         throw logic_error("Set tablewriter name to '" + Table + "', " 
    89                 "but now it's '" + W.name() + "'"); 
     78      PQXX_CHECK_EQUAL(W.name(), Table, "tablewriter name is not what I set."); 
    9079 
    9180      const string Literal = W.generate(BoringTuple); 
    9281      const string Expected = to_string(BoringYear) + "\t" + BoringTuple[1]; 
    93       if (Literal != Expected) 
    94         throw logic_error("tablewriter writes new tuple as '" + 
    95                           Literal + "', " 
    96                           "ought to be '" + 
    97                           Expected + "'"); 
     82      PQXX_CHECK_EQUAL(Literal, Expected, "tablewriter mangles new tuple."); 
    9883 
    9984      W.push_back(BoringTuple); 
     
    10186 
    10287    const pair<int,int> Recount = CountEvents(Doomed); 
    103     if (Recount.second != 1) 
    104       throw runtime_error("Expected to find one event for " + 
    105                           to_string(BoringYear) + ", " 
    106                           "found " + 
    107                           to_string(Recount.second)); 
    108  
    109     if (Recount.first != EventCounts.first+1) 
    110       throw runtime_error("Number of events changed from " + 
    111                           to_string(EventCounts.first) + " " 
    112                           "to " + 
    113                           to_string(Recount.first) + "; " 
    114                           "expected " + 
    115                           to_string(EventCounts.first + 1)); 
     88    PQXX_CHECK_EQUAL(Recount.second, 1, "Unexpected number of events."); 
     89    PQXX_CHECK_EQUAL( 
     90        Recount.first, 
     91        EventCounts.first+1, 
     92        "Number of events changed."); 
    11693 
    11794    // Okay, we've added an entry but we don't really want to.  Abort it 
     
    128105 
    129106  const pair<int,int> NewEvents = CountEvents(Checkup); 
    130   if (NewEvents.first != EventCounts.first) 
    131     throw runtime_error("Number of events changed from " + 
    132                         to_string(EventCounts.first) + " " 
    133                         "to " + 
    134                         to_string(NewEvents.first) + "; " 
    135                         "this may be due to a bug in libpqxx, or the table " 
    136                         "was modified by some other process."); 
     107  PQXX_CHECK_EQUAL( 
     108        NewEvents.first, 
     109        EventCounts.first, 
     110        "Wrong number of events."); 
    137111 
    138   if (NewEvents.second) 
    139     throw runtime_error("Found " + 
    140                         to_string(NewEvents.second) + " " 
    141                         "events in " + 
    142                         to_string(BoringYear) + "; " 
    143                         "wasn't expecting any.  This may be due to a bug in " 
    144                         "libpqxx, or the table was modified by some other " 
    145                         "process."); 
     112  PQXX_CHECK_EQUAL(NewEvents.second, 0, "Found unexpected events."); 
    146113} 
    147114 
     115 
     116void test_029(connection_base &, transaction_base &) 
     117{ 
     118  lazyconnection C; 
     119 
     120  // Test abort semantics, both with explicit and implicit abort 
     121  Test(C, true); 
     122  Test(C, false); 
     123} 
    148124} // namespace 
    149125 
    150  
    151 int main(int, char *argv[]) 
    152 
    153   try 
    154   { 
    155     lazyconnection C(argv[1]); 
    156  
    157     // Test abort semantics, both with explicit and implicit abort 
    158     Test(C, true); 
    159     Test(C, false); 
    160  
    161   } 
    162   catch (const sql_error &e) 
    163   { 
    164     cerr << "SQL error: " << e.what() << endl 
    165          << "Query was: '" << e.query() << "'" << endl; 
    166     return 1; 
    167   } 
    168   catch (const exception &e) 
    169   { 
    170     cerr << "Exception: " << e.what() << endl; 
    171     return 2; 
    172   } 
    173   catch (...) 
    174   { 
    175     cerr << "Unhandled exception" << endl; 
    176     return 100; 
    177   } 
    178  
    179   return 0; 
    180 
    181  
     126PQXX_REGISTER_TEST_NODB(test_029) 
  • trunk/test/test039.cxx

    r1377 r1379  
    44#include <pqxx/nontransaction> 
    55#include <pqxx/result> 
     6 
     7#include "test_helpers.hxx" 
    68 
    79using namespace PGSTD; 
     
    1214// verify that the change gets made regardless of whether the NonTransaction is 
    1315// eventually committed or aborted.  A lazy connection is used. 
    14 // 
    15 // Usage: test039 [connect-string] [table] 
    16 // 
    17 // Where connect-string is a set of connection options in Postgresql's 
    18 // PQconnectdb() format, eg. "dbname=template1" to select from a database 
    19 // called template1, or "host=foo.bar.net user=smith" to connect to a 
    20 // backend running on host foo.bar.net, logging in as user smith. 
    21 // 
    22 // The table argument is the table being modified.  This defaults to 
    23 // "pqxxevents". 
    24 // It is assumed to consist of an integer key called year, and a string. 
    2516namespace 
    2617{ 
    2718int BoringYear = 1977; 
    2819 
    29 } // namespace 
    3020 
    31 int main(int argc, char *argv[]
     21void test_039(connection_base &C, transaction_base &T1
    3222{ 
    33   try 
    34   { 
    35     lazyconnection C(argv[1]); 
     23  const string Table = "pqxxevents"; 
    3624 
    37     const string Table = ((argc > 2) ? argv[2] : "pqxxevents"); 
    3825 
    39     nontransaction T1(C, "T1"); 
     26  // Verify our start condition before beginning: there must not be a 1977 
     27  // record already. 
     28  result R( T1.exec("SELECT * FROM " + Table + " " 
     29                      "WHERE year=" + to_string(BoringYear)) ); 
    4030 
    41     // Verify our start condition before beginning: there must not be a 1977 
    42     // record already. 
    43     result R( T1.exec("SELECT * FROM " + Table + " " 
    44                       "WHERE year=" + to_string(BoringYear)) ); 
    45     if (R.size() != 0) 
    46       throw runtime_error("There is already a record for " + 
    47                           to_string(BoringYear) + ". " 
    48                           "Can't run test."); 
     31  PQXX_CHECK_EQUAL( 
     32        R.size(), 
     33        0u, 
     34        "Already have a row for " + to_string(BoringYear) + ", cannot test."); 
    4935 
    50     // (Not needed, but verify that clear() works on empty containers) 
    51     R.clear(); 
    52     if (!R.empty()) 
    53       throw logic_error("Result non-empty after clear()!"); 
     36  // (Not needed, but verify that clear() works on empty containers) 
     37  R.clear(); 
     38  PQXX_CHECK(R.empty(), "Result is non-empty after clear()."); 
    5439 
    55     // OK.  Having laid that worry to rest, add a record for 1977. 
    56     T1.exec("INSERT INTO " + Table + " VALUES" 
     40  // OK.  Having laid that worry to rest, add a record for 1977. 
     41  T1.exec("INSERT INTO " + Table + " VALUES" 
    5742            "(" + 
    5843            to_string(BoringYear) + "," 
     
    6045            ")"); 
    6146 
    62     // Abort T1.  Since T1 is a NonTransaction, which provides only the 
    63     // transaction class interface without providing any form of transactional 
    64     // integrity, this is not going to undo our work. 
    65     T1.abort(); 
     47  // Abort T1.  Since T1 is a NonTransaction, which provides only the 
     48  // transaction class interface without providing any form of transactional 
     49  // integrity, this is not going to undo our work. 
     50  T1.abort(); 
    6651 
    67     // Verify that our record was added, despite the Abort() 
    68     nontransaction T2(C, "T2"); 
    69     R = T2.exec("SELECT * FROM " + Table + " " 
     52  // Verify that our record was added, despite the Abort() 
     53  nontransaction T2(C, "T2"); 
     54  R = T2.exec("SELECT * FROM " + Table + " " 
    7055                "WHERE year=" + to_string(BoringYear)); 
    71     if (R.size() != 1) 
    72       throw runtime_error("Expected to find 1 record for " + 
    73                           to_string(BoringYear) + ", found " + 
    74                           to_string(R.size()) + ". " 
    75                           "This could be a bug in libpqxx, " 
    76                           "or something else modified the table."); 
     56  PQXX_CHECK_EQUAL(R.size(), 1u, "Unexpected result size."); 
    7757 
    78     if (R.capacity() < R.size()) 
    79       throw logic_error("Result's capacity is too small!"); 
     58  PQXX_CHECK(R.capacity() >= R.size(), "Result's capacity is too small."); 
    8059 
    81     R.clear(); 
    82     if (!R.empty()) 
    83       throw logic_error("result::clear() doesn't work!"); 
     60  R.clear(); 
     61  PQXX_CHECK(R.empty(), "result::clear() is broken."); 
    8462 
    85     // Now remove our record again 
    86     T2.exec("DELETE FROM " + Table + " " 
     63  // Now remove our record again 
     64  T2.exec("DELETE FROM " + Table + " " 
    8765            "WHERE year=" + to_string(BoringYear)); 
    8866 
    89     T2.commit(); 
     67  T2.commit(); 
    9068 
    91     // And again, verify results 
    92     nontransaction T3(C, "T3"); 
     69  // And again, verify results 
     70  nontransaction T3(C, "T3"); 
    9371 
    94     R = T3.exec("SELECT * FROM " + Table + " " 
     72  R = T3.exec("SELECT * FROM " + Table + " " 
    9573                "WHERE year=" + to_string(BoringYear)); 
    96     if (R.size() != 0) 
    97       throw runtime_error("Expected record for " + to_string(BoringYear) + " " 
    98                           "to be gone but found " + to_string(R.size()) + ". " 
    99                           "This could be a bug in libpqxx, " 
    100                           "or something else modified the table."); 
    101   } 
    102   catch (const sql_error &e) 
    103   { 
    104     cerr << "SQL error: " << e.what() << endl 
    105          << "Query was: '" << e.query() << "'" << endl; 
    106     return 1; 
    107   } 
    108   catch (const exception &e) 
    109   { 
    110     // All exceptions thrown by libpqxx are derived from std::exception 
    111     cerr << "Exception: " << e.what() << endl; 
    112     return 2; 
    113   } 
    114   catch (...) 
    115   { 
    116     // This is really unexpected (see above) 
    117     cerr << "Unhandled exception" << endl; 
    118     return 100; 
    119   } 
    12074 
    121   return 0
     75  PQXX_CHECK_EQUAL(R.size(), 0u, "Record is not gone as expected.")
    12276} 
     77} // namespace 
    12378 
     79PQXX_REGISTER_TEST_CT(test_039, lazyconnection, nontransaction) 
  • trunk/test/test_helpers.hxx

    r1377 r1379  
    11#include <iostream> 
     2#include <map> 
    23#include <new> 
    34#include <stdexcept> 
     
    1011namespace test 
    1112{ 
    12  
    1313class test_failure : public PGSTD::logic_error 
    1414{ 
     
    6464PGSTD::string select_series(connection_base &conn, int lowest, int highest) 
    6565{ 
    66   if (pqxx::test::have_generate_series(conn)) 
     66  if (have_generate_series(conn)) 
    6767    return 
    6868        "SELECT generate_series(" + 
     
    7878 
    7979 
    80 /// Base class for libpqxx tests.  Sets up a connection and transaction. 
    81 template<typename CONNECTION=connection, typename TRANSACTION=work> 
    82 class TestCase 
     80class base_test; 
     81typedef PGSTD::map<PGSTD::string, base_test *> test_map; 
     82const test_map &register_test(base_test *); 
     83 
     84 
     85/// Base class for test cases. 
     86class base_test 
    8387{ 
    8488public: 
    8589  typedef void (*testfunc)(connection_base &, transaction_base &); 
    86  
     90  base_test(const PGSTD::string &tname, testfunc func) : 
     91        m_name(tname), 
     92        m_func(func) 
     93  { 
     94    register_test(this); 
     95  } 
     96  virtual int run() =0; 
     97  virtual ~base_test() =0; 
     98  const PGSTD::string &name() const throw () { return m_name; } 
     99private: 
     100  PGSTD::string m_name; 
     101protected: 
     102  testfunc m_func; 
     103}; 
     104 
     105 
     106/// Runner class for libpqxx tests.  Sets up a connection and transaction. 
     107template<typename CONNECTION=connection, typename TRANSACTION=work> 
     108class test_case : public base_test 
     109
     110public: 
    87111  // func takes connection and transaction as arguments. 
    88   TestCase(const PGSTD::string &name, testfunc func) : 
     112  test_case(const PGSTD::string &tname, testfunc func) : 
     113    base_test(tname, func), 
    89114    m_conn(), 
    90     m_trans(m_conn, name), 
    91     m_func(func) 
     115    m_trans(m_conn, tname) 
    92116  { 
    93117    // Workaround for older backend versions that lack generate_series(). 
     
    95119  } 
    96120 
    97   // Invoke test function with its expected arguments 
    98   void operator()() { m_func(m_conn, m_trans); } 
     121  ~test_case() {} 
    99122 
    100123  // Run test, catching errors & returning Unix-style success value 
    101   int run() 
     124  virtual int run() 
    102125  { 
    103126    try 
    104127    { 
    105       (*this)(); 
     128      m_func(m_conn, m_trans); 
    106129    } 
    107130    catch (const test_failure &e) 
     
    139162  CONNECTION m_conn; 
    140163  TRANSACTION m_trans; 
    141   testfunc m_func; 
    142164}; 
    143165 
     
    145167// Register a function taking (connection_base &, transaction_base &) as a test. 
    146168#define PQXX_REGISTER_TEST(function) \ 
    147         int main() \ 
    148         { \ 
    149           pqxx::test::TestCase<> test(#function, (function)); \ 
    150           return test.run(); \ 
     169        namespace \ 
     170        { \ 
     171        pqxx::test::test_case<> test(#function, function); \ 
    151172        } 
    152173 
    153174// Register a test function using given connection and transaction types. 
    154175#define PQXX_REGISTER_TEST_CT(function, connection_type, transaction_type) \ 
    155         int main() \ 
    156         { \ 
    157           pqxx::test::TestCase<connection_type, transaction_type> \ 
    158                 test(#function, (function)); \ 
    159           return test.run(); \ 
     176        namespace \ 
     177        { \ 
     178        pqxx::test::test_case<connection_type, transaction_type> \ 
     179                test(#function, function); \ 
    160180        } 
    161181 
     
    163183// default "connection"). 
    164184#define PQXX_REGISTER_TEST_C(function, connection_type) \ 
    165         int main() \ 
    166         { \ 
    167           pqxx::test::TestCase<connection_type> test(#function, (function)); \ 
    168           return test.run(); \ 
    169         } 
     185        PQXX_REGISTER_TEST_CT(function, connection_type, pqxx::work) 
    170186 
    171187// Register a test function using a given transaction type (default is "work"). 
     
    178194        PQXX_REGISTER_TEST_CT( \ 
    179195                function, \ 
    180                  pqxx::nullconnection, \ 
    181                  pqxx::nontransaction) 
     196                pqxx::nullconnection, \ 
     197                pqxx::nontransaction) 
     198 
     199 
     200#define PQXX_RUN_TESTS \ 
     201        namespace pqxx \ 
     202        { \ 
     203        namespace test \ 
     204        { \ 
     205        base_test::~base_test() {} \ 
     206        const test_map &register_test(base_test *tc) \ 
     207        { \ 
     208          static test_map tests; \ 
     209          if (tc) tests[tc->name()] = tc; \ 
     210          return tests; \ 
     211        } \ 
     212        } \ 
     213        } \ 
     214        int main() \ 
     215        { \ 
     216          pqxx::test::run_tests(); \ 
     217        } 
     218 
     219inline void run_tests() 
     220
     221  const test_map &tests = register_test(NULL); 
     222  for (test_map::const_iterator i = tests.begin(); i != tests.end(); ++i) 
     223  { 
     224    PGSTD::cout << "Running: " << i->first << PGSTD::endl; 
     225    i->second->run(); 
     226  } 
     227
    182228 
    183229 
     
    185231#define PQXX_CHECK_NOTREACHED(desc) \ 
    186232        pqxx::test::check_notreached(__FILE__, __LINE__, (desc)) 
    187 void check_notreached(const char file[], int line, PGSTD::string desc) 
     233inline void check_notreached(const char file[], int line, PGSTD::string desc) 
    188234{ 
    189235  throw test_failure(file, line, desc); 
     
    193239#define PQXX_CHECK(condition, desc) \ 
    194240        pqxx::test::check(__FILE__, __LINE__, (condition), #condition, (desc)) 
    195 void check( 
     241inline void check( 
    196242        const char file[], 
    197243        int line, 
     
    201247{ 
    202248  if (!condition) 
    203     throw test_failure(file, line, desc + " (failed expression: " + text + ")"); 
     249    throw test_failure( 
     250        file, 
     251        line, 
     252        desc + " (failed expression: " + text + ")"); 
    204253} 
    205254 
     
    229278        "expected=" + to_string(expected) + ", " 
    230279        "actual=" + to_string(actual) + ")"; 
    231   throw pqxx::test::test_failure(file, line, fulldesc); 
     280  throw test_failure(file, line, fulldesc); 
    232281} 
    233282 
     
    256305        desc + " (" + text1 + " == " + text2 + ": " 
    257306        "both are " + to_string(value2) + ")"; 
    258   throw pqxx::test::test_failure(file, line, fulldesc); 
     307  throw test_failure(file, line, fulldesc); 
    259308} 
    260309 
     
    318367        "upper=" + to_string(upper) + ", " 
    319368        "value=" + to_string(value) + ")"; 
    320     throw pqxx::test::test_failure(file, line, fulldesc); 
     369    throw test_failure(file, line, fulldesc); 
    321370  } 
    322371 
     
    327376        text + " is below lower bound " + lower_text + ": " + 
    328377        to_string(value) + " < " + to_string(lower) + ")"; 
    329     throw pqxx::test::test_failure(file, line, fulldesc); 
     378    throw test_failure(file, line, fulldesc); 
    330379  } 
    331380 
     
    336385        text + " is not below upper bound " + upper_text + ": " + 
    337386        to_string(value) + " >= " + to_string(upper) + ")"; 
    338     throw pqxx::test::test_failure(file, line, fulldesc); 
    339   } 
    340 
    341  
     387    throw test_failure(file, line, fulldesc); 
     388  } 
     389
    342390} // namespace test 
    343391 
     
    345393namespace 
    346394{ 
    347 PGSTD::string deref_field(const result::field &f) { return f.c_str(); } 
     395PGSTD::string deref_field(const pqxx::result::field &f) { return f.c_str(); } 
    348396} // namespace 
    349397 
  • trunk/test/unit/Makefile.am.template

    r1291 r1379  
    99MAINTAINERCLEANFILES=Makefile.in 
    1010 
    11 TESTS = \ 
     11runner_SOURCES = \ 
    1212###MAKTEMPLATE:FOREACH test/unit/test_*.cxx 
    13   ###BASENAME###
     13  ###BASENAME###.cxx
    1414###MAKTEMPLATE:ENDFOREACH 
    15   # (end) 
     15  runner.cxx 
    1616 
     17runner_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} 
     18 
     19TESTS = runner 
    1720check_PROGRAMS = ${TESTS} 
    1821 
    19 ###MAKTEMPLATE:FOREACH test/unit/test_*.cxx 
    20 ###BASENAME###_SOURCES = ###BASENAME###.cxx 
    21 ###BASENAME###_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} 
     22# ###MAKTEMPLATE:FOREACH test/unit/test_*.cxx 
     23# ###BASENAME###_SOURCES = ###BASENAME###.cxx 
     24# ###BASENAME###_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} 
    2225