Changeset 1379
- Timestamp:
- 08/15/08 00:31:44 (5 months ago)
- Files:
-
- trunk/ChangeLog (modified) (1 diff)
- trunk/test/Makefile.am.template (modified) (1 diff)
- trunk/test/runner.cxx (added)
- trunk/test/test027.cxx (modified) (2 diffs)
- trunk/test/test028.cxx (modified) (3 diffs)
- trunk/test/test029.cxx (modified) (7 diffs)
- trunk/test/test039.cxx (modified) (3 diffs)
- trunk/test/test_helpers.hxx (modified) (18 diffs)
- trunk/test/unit/Makefile.am.template (modified) (1 diff)
- trunk/test/unit/runner.cxx (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/ChangeLog
r1378 r1379 1 2008-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 1 9 2008-08-14 Jeroen T. Vermeulen <jtv@xs4all.nl> 2 10 test/test072.cxx, test/test073.cxx, test/test074.cxx, test/test075.cxx, trunk/test/Makefile.am.template
r1300 r1379 19 19 # PGDATABASE, PGHOST, PGPORT, PGUSER 20 20 21 TESTS = \21 runner_SOURCES = \ 22 22 ###MAKTEMPLATE:FOREACH test/test*.cxx 23 ###BASENAME### \23 ###BASENAME###.cxx \ 24 24 ###MAKTEMPLATE:ENDFOREACH 25 # (end)25 runner.cxx 26 26 27 runner_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} 28 29 TESTS = runner 27 30 check_PROGRAMS = ${TESTS} 28 31 29 # ##MAKTEMPLATE:FOREACH test/test*.cxx30 # ##BASENAME###_SOURCES = ###BASENAME###.cxx31 # ##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} 32 35 trunk/test/test027.cxx
r1138 r1379 7 7 #include <pqxx/transaction> 8 8 9 #include "test_helpers.hxx" 10 9 11 using namespace PGSTD; 10 12 using namespace pqxx; … … 13 15 // Test program for libpqxx. Read a table using a tablereader, which may be 14 16 // 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[]) 17 namespace 28 18 { 29 try 19 void test_027(connection_base &, transaction_base &T) 20 { 21 const string Table = "pqxxevents"; 22 23 vector<string> R, First; 24 30 25 { 31 // Set up a connection to the backend32 lazyconnection C(argv[1]);26 // Set up a tablereader stream to read data from table pg_tables 27 tablereader Stream(T, Table); 33 28 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; 36 34 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(); 75 40 } 76 41 } 77 catch (const sql_error &e) 42 43 // Verify the contents we got for the first row 44 if (!First.empty()) 78 45 { 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."); 82 60 } 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 93 63 94 return 0; 95 } 96 64 PQXX_REGISTER_TEST_C(test_027, lazyconnection) trunk/test/test028.cxx
r1138 r1379 8 8 #include <pqxx/transaction> 9 9 10 #include "test_helpers.hxx" 11 10 12 using namespace PGSTD; 11 13 using namespace pqxx; … … 14 16 // Test program for libpqxx. Create a table and write data to it, using 15 17 // 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's20 // PQconnectdb() format, eg. "dbname=template1" to select from a database21 // called template1, or "host=foo.bar.net user=smith" to connect to a backend22 // running on host foo.bar.net, logging in as user smith.23 //24 // The default table name is "testtable."25 26 18 namespace 27 19 { … … 71 63 size_t Rows = 0; 72 64 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."); 74 66 cout << Rows << " rows in table." << endl; 75 67 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."); 83 69 // TODO: Compare table contents to Contents 84 70 } 71 72 73 void 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(); 85 88 } 89 } // namespace 86 90 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 91 PQXX_REGISTER_TEST_C(test_028, lazyconnection) trunk/test/test029.cxx
r1138 r1379 8 8 #include <pqxx/result> 9 9 10 #include "test_helpers.hxx" 11 10 12 using namespace PGSTD; 11 13 using namespace pqxx; … … 15 17 // abort it, and verify that it "never happened." Use lazy connection. 16 18 // 17 // Usage: test029 [connect-string]18 //19 // Where connect-string is a set of connection options in Postgresql's20 // PQconnectdb() format, eg. "dbname=template1" to select from a database21 // called template1, or "host=foo.bar.net user=smith" to connect to a22 // backend running on host foo.bar.net, logging in as user smith.23 //24 19 // The program will attempt to add an entry to a table called "pqxxevents", 25 20 // with a key column called "year"--and then abort the change. 26 27 21 namespace 28 22 { 29 30 23 // Let's take a boring year that is not going to be in the "pqxxevents" table 31 24 const int BoringYear = 1977; … … 54 47 55 48 56 57 49 // Try adding a record, then aborting it, and check whether the abort was 58 50 // performed correctly. … … 75 67 EventCounts = CountEvents(Doomed); 76 68 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."); 82 73 83 74 // Now let's try to introduce a tuple for our Boring Year … … 85 76 tablewriter W(Doomed, Table); 86 77 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."); 90 79 91 80 const string Literal = W.generate(BoringTuple); 92 81 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."); 98 83 99 84 W.push_back(BoringTuple); … … 101 86 102 87 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."); 116 93 117 94 // Okay, we've added an entry but we don't really want to. Abort it … … 128 105 129 106 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."); 137 111 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."); 146 113 } 147 114 115 116 void 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 } 148 124 } // namespace 149 125 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 126 PQXX_REGISTER_TEST_NODB(test_029) trunk/test/test039.cxx
r1377 r1379 4 4 #include <pqxx/nontransaction> 5 5 #include <pqxx/result> 6 7 #include "test_helpers.hxx" 6 8 7 9 using namespace PGSTD; … … 12 14 // verify that the change gets made regardless of whether the NonTransaction is 13 15 // 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's18 // PQconnectdb() format, eg. "dbname=template1" to select from a database19 // called template1, or "host=foo.bar.net user=smith" to connect to a20 // backend running on host foo.bar.net, logging in as user smith.21 //22 // The table argument is the table being modified. This defaults to23 // "pqxxevents".24 // It is assumed to consist of an integer key called year, and a string.25 16 namespace 26 17 { 27 18 int BoringYear = 1977; 28 19 29 } // namespace30 20 31 int main(int argc, char *argv[])21 void test_039(connection_base &C, transaction_base &T1) 32 22 { 33 try 34 { 35 lazyconnection C(argv[1]); 23 const string Table = "pqxxevents"; 36 24 37 const string Table = ((argc > 2) ? argv[2] : "pqxxevents");38 25 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)) ); 40 30 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."); 49 35 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()."); 54 39 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" 57 42 "(" + 58 43 to_string(BoringYear) + "," … … 60 45 ")"); 61 46 62 // Abort T1. Since T1 is a NonTransaction, which provides only the63 // transaction class interface without providing any form of transactional64 // 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(); 66 51 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 + " " 70 55 "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."); 77 57 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."); 80 59 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."); 84 62 85 // Now remove our record again86 T2.exec("DELETE FROM " + Table + " "63 // Now remove our record again 64 T2.exec("DELETE FROM " + Table + " " 87 65 "WHERE year=" + to_string(BoringYear)); 88 66 89 T2.commit();67 T2.commit(); 90 68 91 // And again, verify results92 nontransaction T3(C, "T3");69 // And again, verify results 70 nontransaction T3(C, "T3"); 93 71 94 R = T3.exec("SELECT * FROM " + Table + " "72 R = T3.exec("SELECT * FROM " + Table + " " 95 73 "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() << endl105 << "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::exception111 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 }120 74 121 return 0;75 PQXX_CHECK_EQUAL(R.size(), 0u, "Record is not gone as expected."); 122 76 } 77 } // namespace 123 78 79 PQXX_REGISTER_TEST_CT(test_039, lazyconnection, nontransaction) trunk/test/test_helpers.hxx
r1377 r1379 1 1 #include <iostream> 2 #include <map> 2 3 #include <new> 3 4 #include <stdexcept> … … 10 11 namespace test 11 12 { 12 13 13 class test_failure : public PGSTD::logic_error 14 14 { … … 64 64 PGSTD::string select_series(connection_base &conn, int lowest, int highest) 65 65 { 66 if ( pqxx::test::have_generate_series(conn))66 if (have_generate_series(conn)) 67 67 return 68 68 "SELECT generate_series(" + … … 78 78 79 79 80 /// Base class for libpqxx tests. Sets up a connection and transaction. 81 template<typename CONNECTION=connection, typename TRANSACTION=work> 82 class TestCase 80 class base_test; 81 typedef PGSTD::map<PGSTD::string, base_test *> test_map; 82 const test_map ®ister_test(base_test *); 83 84 85 /// Base class for test cases. 86 class base_test 83 87 { 84 88 public: 85 89 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; } 99 private: 100 PGSTD::string m_name; 101 protected: 102 testfunc m_func; 103 }; 104 105 106 /// Runner class for libpqxx tests. Sets up a connection and transaction. 107 template<typename CONNECTION=connection, typename TRANSACTION=work> 108 class test_case : public base_test 109 { 110 public: 87 111 // 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), 89 114 m_conn(), 90 m_trans(m_conn, name), 91 m_func(func) 115 m_trans(m_conn, tname) 92 116 { 93 117 // Workaround for older backend versions that lack generate_series(). … … 95 119 } 96 120 97 // Invoke test function with its expected arguments 98 void operator()() { m_func(m_conn, m_trans); } 121 ~test_case() {} 99 122 100 123 // Run test, catching errors & returning Unix-style success value 101 int run()124 virtual int run() 102 125 { 103 126 try 104 127 { 105 (*this)();128 m_func(m_conn, m_trans); 106 129 } 107 130 catch (const test_failure &e) … … 139 162 CONNECTION m_conn; 140 163 TRANSACTION m_trans; 141 testfunc m_func;142 164 }; 143 165 … … 145 167 // Register a function taking (connection_base &, transaction_base &) as a test. 146 168 #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); \ 151 172 } 152 173 153 174 // Register a test function using given connection and transaction types. 154 175 #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); \ 160 180 } 161 181 … … 163 183 // default "connection"). 164 184 #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) 170 186 171 187 // Register a test function using a given transaction type (default is "work"). … … 178 194 PQXX_REGISTER_TEST_CT( \ 179 195 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 ®ister_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 219 inline 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 } 182 228 183 229 … … 185 231 #define PQXX_CHECK_NOTREACHED(desc) \ 186 232 pqxx::test::check_notreached(__FILE__, __LINE__, (desc)) 187 void check_notreached(const char file[], int line, PGSTD::string desc)233 inline void check_notreached(const char file[], int line, PGSTD::string desc) 188 234 { 189 235 throw test_failure(file, line, desc); … … 193 239 #define PQXX_CHECK(condition, desc) \ 194 240 pqxx::test::check(__FILE__, __LINE__, (condition), #condition, (desc)) 195 void check(241 inline void check( 196 242 const char file[], 197 243 int line, … … 201 247 { 202 248 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 + ")"); 204 253 } 205 254 … … 229 278 "expected=" + to_string(expected) + ", " 230 279 "actual=" + to_string(actual) + ")"; 231 throw pqxx::test::test_failure(file, line, fulldesc);280 throw test_failure(file, line, fulldesc); 232 281 } 233 282 … … 256 305 desc + " (" + text1 + " == " + text2 + ": " 257 306 "both are " + to_string(value2) + ")"; 258 throw pqxx::test::test_failure(file, line, fulldesc);307 throw test_failure(file, line, fulldesc); 259 308 } 260 309 … … 318 367 "upper=" + to_string(upper) + ", " 319 368 "value=" + to_string(value) + ")"; 320 throw pqxx::test::test_failure(file, line, fulldesc);369 throw test_failure(file, line, fulldesc); 321 370 } 322 371 … … 327 376 text + " is below lower bound " + lower_text + ": " + 328 377 to_string(value) + " < " + to_string(lower) + ")"; 329 throw pqxx::test::test_failure(file, line, fulldesc);378 throw test_failure(file, line, fulldesc); 330 379 } 331 380 … … 336 385 text + " is not below upper bound " + upper_text + ": " + 337 386 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 } 342 390 } // namespace test 343 391 … … 345 393 namespace 346 394 { 347 PGSTD::string deref_field(const result::field &f) { return f.c_str(); }395 PGSTD::string deref_field(const pqxx::result::field &f) { return f.c_str(); } 348 396 } // namespace 349 397 trunk/test/unit/Makefile.am.template
r1291 r1379 9 9 MAINTAINERCLEANFILES=Makefile.in 10 10 11 TESTS = \11 runner_SOURCES = \ 12 12 ###MAKTEMPLATE:FOREACH test/unit/test_*.cxx 13 ###BASENAME### \13 ###BASENAME###.cxx \ 14 14 ###MAKTEMPLATE:ENDFOREACH 15 # (end)15 runner.cxx 16 16 17 runner_LDADD = $(top_builddir)/src/libpqxx.la ${POSTGRES_LIB} 18 19 TESTS = runner 17 20 check_PROGRAMS = ${TESTS} 18 21 19 # ##MAKTEMPLATE:FOREACH test/unit/test_*.cxx20 # ##BASENAME###_SOURCES = ###BASENAME###.cxx21 # ##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} 22 25
