Changeset 1377
- Timestamp:
- 08/13/08 08:40:23 (5 months ago)
- Files:
-
- trunk/ChangeLog (modified) (1 diff)
- trunk/test/test001.cxx (modified) (1 diff)
- trunk/test/test013.cxx (modified) (1 diff)
- trunk/test/test016.cxx (modified) (2 diffs)
- trunk/test/test017.cxx (modified) (3 diffs)
- trunk/test/test018.cxx (modified) (4 diffs)
- trunk/test/test020.cxx (modified) (3 diffs)
- trunk/test/test021.cxx (modified) (3 diffs)
- trunk/test/test023.cxx (modified) (3 diffs)
- trunk/test/test024.cxx (modified) (2 diffs)
- trunk/test/test025.cxx (modified) (4 diffs)
- trunk/test/test026.cxx (modified) (4 diffs)
- trunk/test/test030.cxx (modified) (2 diffs)
- trunk/test/test031.cxx (modified) (3 diffs)
- trunk/test/test032.cxx (modified) (5 diffs)
- trunk/test/test033.cxx (modified) (2 diffs)
- trunk/test/test034.cxx (modified) (3 diffs)
- trunk/test/test035.cxx (modified) (2 diffs)
- trunk/test/test036.cxx (modified) (3 diffs)
- trunk/test/test037.cxx (modified) (5 diffs)
- trunk/test/test039.cxx (modified) (1 diff)
- trunk/test/test046.cxx (modified) (2 diffs)
- trunk/test/test048.cxx (modified) (3 diffs)
- trunk/test/test049.cxx (modified) (4 diffs)
- trunk/test/test050.cxx (modified) (4 diffs)
- trunk/test/test051.cxx (modified) (3 diffs)
- trunk/test/test052.cxx (modified) (3 diffs)
- trunk/test/test053.cxx (modified) (4 diffs)
- trunk/test/test054.cxx (modified) (2 diffs)
- trunk/test/test055.cxx (modified) (3 diffs)
- trunk/test/test056.cxx (modified) (2 diffs)
- trunk/test/test057.cxx (modified) (3 diffs)
- trunk/test/test058.cxx (modified) (4 diffs)
- trunk/test/test059.cxx (modified) (3 diffs)
- trunk/test/test060.cxx (modified) (2 diffs)
- trunk/test/test061.cxx (modified) (2 diffs)
- trunk/test/test062.cxx (modified) (1 diff)
- trunk/test/test063.cxx (modified) (2 diffs)
- trunk/test/test064.cxx (modified) (3 diffs)
- trunk/test/test065.cxx (modified) (3 diffs)
- trunk/test/test066.cxx (modified) (3 diffs)
- trunk/test/test067.cxx (modified) (3 diffs)
- trunk/test/test068.cxx (modified) (2 diffs)
- trunk/test/test069.cxx (modified) (1 diff)
- trunk/test/test070.cxx (modified) (2 diffs)
- trunk/test/test071.cxx (modified) (2 diffs)
- trunk/test/test085.cxx (modified) (1 diff)
- trunk/test/test088.cxx (modified) (1 diff)
- trunk/test/test089.cxx (modified) (1 diff)
- trunk/test/test090.cxx (modified) (1 diff)
- trunk/test/test092.cxx (modified) (2 diffs)
- trunk/test/test_helpers.hxx (modified) (1 diff)
- trunk/test/unit/test_test_helpers.cxx (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/ChangeLog
r1376 r1377 1 2008-08-13 Jeroen T. Vermeulen <jtv@xs4all.nl> 2 test/test001.cxx, test/test013.cxx, test/test016.cxx, test/test017.cxx, 3 test/test018.cxx, test/test020.cxx, test/test021.cxx, test/test023.cxx, 4 test/test024.cxx, test/test025.cxx, test/test026.cxx, test/test030.cxx, 5 test/test031.cxx, test/test032.cxx, test/test033.cxx, test/test034.cxx, 6 test/test035.cxx, test/test036.cxx, test/test037.cxx, test/test038.cxx, 7 test/test035.cxx, test/test046.cxx, test/test048.cxx, test/test049.cxx, 8 test/test050.cxx, test/test051.cxx, test/test052.cxx, test/test053.cxx, 9 test/test054.cxx, test/test055.cxx, test/test056.cxx, test/test057.cxx, 10 test/test058.cxx, test/test059.cxx, test/test060.cxx, test/test061.cxx, 11 test/test062.cxx, test/test063.cxx, test/test064.cxx, test/test065.cxx, 12 test/test066.cxx, test/test067.cxx, test/test068.cxx, test/test069.cxx, 13 test/test070.cxx, test/test071.cxx, test/test085.cxx, test/test088.cxx, 14 test/test089.cxx, test/test090.cxx, test/test092.cxx, 15 test/test_helpers.hxx, test/unit/test_test_helpers.cxx: 16 - Converted lots more tests to test framework 17 - Removed all asserts from tests 18 - New test helper: boundary check 19 - Removed non-encoded "text" output from test062. 1 20 2008-08-12 Jeroen T. Vermeulen <jtv@xs4all.nl> 2 21 test/test011.cxx, test/test012.cxx, test/test013.cxx, test/test014.cxx, trunk/test/test001.cxx
r1375 r1377 1 #include <cassert>2 1 #include <iostream> 3 2 trunk/test/test013.cxx
r1376 r1377 1 #include <cassert>2 1 #include <cstdio> 3 2 #include <iostream> trunk/test/test016.cxx
r1376 r1377 15 15 namespace 16 16 { 17 18 17 void test_016(connection_base &, transaction_base &T) 19 18 { … … 30 29 31 30 // See if back() and tuple comparison work properly 32 if (R.size() < 2)33 throw runtime_error("Not enough results in pg_tables to test, sorry!"); 31 PQXX_CHECK(R.size() >= 2, "Not enough rows in pg_tables to test, sorry!"); 32 34 33 --c; 35 if (c->size() != R.back().size()) 36 throw logic_error("Size mismatch between tuple iterator and back()"); 34 35 PQXX_CHECK_EQUAL( 36 c->size(), 37 R.back().size(), 38 "Size mismatch between tuple iterator and back()."); 39 37 40 const string nullstr; 38 41 for (result::tuple::size_type i = 0; i < c->size(); ++i) 39 if (c[i].as(nullstr) != R.back()[i].as(nullstr))40 throw logic_error("Value mismatch in back()");41 if (c != R.back()) 42 throw logic_error("Something wrong with tuple inequality");43 if (!(c == R.back()))44 throw logic_error("Something wrong with tuple equality");42 PQXX_CHECK_EQUAL( 43 c[i].as(nullstr), 44 R.back()[i].as(nullstr), 45 "Value mismatch in back()."); 46 PQXX_CHECK(c == R.back(), "Tuple equality is broken."); 47 PQXX_CHECK(!(c != R.back()), "Tuple inequality is broken."); 45 48 46 49 // "Commit" the non-transaction. This doesn't really do anything since trunk/test/test017.cxx
r1040 r1377 6 6 #include <pqxx/result> 7 7 8 #include "test_helpers.hxx" 9 8 10 using namespace PGSTD; 9 11 using namespace pqxx; … … 12 14 // Simple test program for libpqxx. Open connection to database, start 13 15 // a dummy transaction to gain nontransactional access, and perform a query. 14 // 15 // Usage: test017 [connect-string] 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 16 namespace 17 { 22 18 class ReadTables : public transactor<nontransaction> 23 19 { … … 44 40 45 41 46 int main(int, char *argv[])42 void test_017(connection_base &C, transaction_base &T) 47 43 { 48 try 49 { 50 connection C(argv[1]); 44 T.abort(); 45 C.perform(ReadTables()); 46 } 47 } // namespace 51 48 52 C.perform(ReadTables()); 53 } 54 catch (const sql_error &e) 55 { 56 // If we're interested in the text of a failed query, we can write separate 57 // exception handling code for this type of exception 58 cerr << "SQL error: " << e.what() << endl 59 << "Query was: '" << e.query() << "'" << endl; 60 return 1; 61 } 62 catch (const exception &e) 63 { 64 // All exceptions thrown by libpqxx are derived from std::exception 65 cerr << "Exception: " << e.what() << endl; 66 return 2; 67 } 68 catch (...) 69 { 70 // This is really unexpected (see above) 71 cerr << "Unhandled exception" << endl; 72 return 100; 73 } 74 75 return 0; 76 } 77 49 PQXX_REGISTER_TEST_T(test_017, nontransaction) trunk/test/test018.cxx
r1175 r1377 10 10 #include <pqxx/transactor> 11 11 12 #include "test_helpers.hxx" 13 12 14 using namespace PGSTD; 13 15 using namespace pqxx; … … 16 18 // Test program for libpqxx. Verify abort behaviour of RobustTransaction. 17 19 // 18 // Usage: test018 [connect-string] [table]19 //20 // Where connect-string is a set of connection options in Postgresql's21 // PQconnectdb() format, eg. "dbname=template1" to select from a database22 // called template1, or "host=foo.bar.net user=smith" to connect to a23 // backend running on host foo.bar.net, logging in as user smith.24 //25 20 // The program will attempt to add an entry to a table called "pqxxevents", 26 21 // with a key column called "year"--and then abort the change. 27 28 22 namespace 29 23 { … … 59 53 } 60 54 }; 61 62 55 63 56 … … 102 95 }; 103 96 97 104 98 string FailedInsert::LastReason; 105 99 100 101 void test_018(connection_base &C, transaction_base &T) 102 { 103 T.abort(); 104 105 const string Table = "pqxxevents"; 106 107 pair<int,int> Before; 108 C.perform(CountEvents(Table, Before)); 109 PQXX_CHECK_EQUAL( 110 Before.second, 111 0, 112 "Already have event for " + to_string(BoringYear) + ", cannot run."); 113 114 const FailedInsert DoomedTransaction(Table); 115 116 { 117 disable_noticer d(C); 118 PQXX_CHECK_THROWS( 119 C.perform(DoomedTransaction), 120 runtime_error, 121 "Not getting expected exception from failing transactor."); 122 } 123 124 pair<int,int> After; 125 C.perform(CountEvents(Table, After)); 126 127 PQXX_CHECK_EQUAL(After.first, Before.first, "Event count changed."); 128 PQXX_CHECK_EQUAL( 129 After.second, 130 Before.second, 131 "Event count for " + to_string(BoringYear) + " changed."); 132 } 106 133 } // namespace 107 134 108 109 int main(int argc, char *argv[]) 110 { 111 try 112 { 113 connection C(argv[1]); 114 115 const string Table = ((argc > 2) ? argv[2] : "pqxxevents"); 116 117 pair<int,int> Before; 118 C.perform(CountEvents(Table, Before)); 119 if (Before.second) 120 throw runtime_error("Table already has an event for " + 121 to_string(BoringYear) + ", " 122 "cannot run."); 123 124 const FailedInsert DoomedTransaction(Table); 125 126 try 127 { 128 disable_noticer d(C); 129 C.perform(DoomedTransaction); 130 } 131 catch (const exception &e) 132 { 133 cout << "(Expected) Doomed transaction failed: " << e.what() << endl; 134 } 135 136 pair<int,int> After; 137 C.perform(CountEvents(Table, After)); 138 139 if (After != Before) 140 throw logic_error("Event counts changed from " 141 "{" + to_string(Before.first) + "," + 142 to_string(Before.second) + "} " 143 "to " 144 "{" + to_string(After.first) + "," + 145 to_string(After.second) + "} " 146 "despite abort. This could be a bug in libpqxx, " 147 "or something else modified the table."); 148 } 149 catch (const sql_error &e) 150 { 151 // If we're interested in the text of a failed query, we can write separate 152 // exception handling code for this type of exception 153 cerr << "SQL error: " << e.what() << endl 154 << "Query was: '" << e.query() << "'" << endl; 155 return 1; 156 } 157 catch (const exception &e) 158 { 159 // All exceptions thrown by libpqxx are derived from std::exception 160 cerr << "Exception: " << e.what() << endl; 161 return 2; 162 } 163 catch (...) 164 { 165 // This is really unexpected (see above) 166 cerr << "Unhandled exception" << endl; 167 return 100; 168 } 169 170 return 0; 171 } 172 135 PQXX_REGISTER_TEST_T(test_018, nontransaction) trunk/test/test020.cxx
r1138 r1377 1 #include <cassert>2 1 #include <iostream> 3 2 … … 5 4 #include <pqxx/nontransaction> 6 5 #include <pqxx/result> 6 7 #include "test_helpers.hxx" 7 8 8 9 using namespace PGSTD; … … 13 14 // verify that the change gets made regardless of whether the NonTransaction is 14 15 // eventually committed or aborted. 15 //16 // Usage: test020 [connect-string] [table]17 //18 // Where connect-string is a set of connection options in Postgresql's19 // PQconnectdb() format, eg. "dbname=template1" to select from a database20 // called template1, or "host=foo.bar.net user=smith" to connect to a21 // backend running on host foo.bar.net, logging in as user smith.22 //23 // The table argument is the table being modified. This defaults to24 // "pqxxevents".25 // It is assumed to consist of an integer key called year, and a string.26 16 namespace 27 17 { 28 18 const unsigned long BoringYear = 1977; 29 19 30 } // namespace31 20 32 int main(int argc, char *argv[])21 void test_020(connection_base &C, transaction_base &T1) 33 22 { 34 try 35 { 36 connection C(argv[1]); 23 const string Table = "pqxxevents"; 37 24 38 const string Table = ((argc > 2) ? argv[2] : "pqxxevents"); 39 40 // Begin a transaction acting on our current connection 41 nontransaction T1(C, "T1"); 42 43 // Verify our start condition before beginning: there must not be a 1977 44 // record already. 45 result R( T1.exec(("SELECT * FROM " + Table + " " 25 // Verify our start condition before beginning: there must not be a 1977 26 // record already. 27 result R( T1.exec(("SELECT * FROM " + Table + " " 46 28 "WHERE year=" + to_string(BoringYear)).c_str()) ); 47 if (R.size() != 0)48 throw runtime_error("There is already a record for " +29 if (R.size() != 0) 30 throw runtime_error("There is already a record for " + 49 31 to_string(BoringYear) + ". " 50 32 "Can't run test."); 51 33 52 // (Not needed, but verify that clear() works on empty containers)53 R.clear();54 if (!R.empty())55 throw logic_error("Result non-empty after clear()!");34 // (Not needed, but verify that clear() works on empty containers) 35 R.clear(); 36 if (!R.empty()) 37 throw logic_error("Result non-empty after clear()!"); 56 38 57 // OK. Having laid that worry to rest, add a record for 1977.58 T1.exec(("INSERT INTO " + Table + " VALUES"59 "(" +60 to_string(BoringYear) + ","61 "'Yawn'"62 ")").c_str());39 // OK. Having laid that worry to rest, add a record for 1977. 40 T1.exec(("INSERT INTO " + Table + " VALUES" 41 "(" + 42 to_string(BoringYear) + "," 43 "'Yawn'" 44 ")").c_str()); 63 45 64 // Abort T1. Since T1 is a NonTransaction, which provides only the65 // transaction class interface without providing any form of transactional66 // integrity, this is not going to undo our work.67 T1.abort();46 // Abort T1. Since T1 is a nontransaction, which provides only the 47 // transaction class interface without providing any form of transactional 48 // integrity, this is not going to undo our work. 49 T1.abort(); 68 50 69 // Verify that our record was added, despite the Abort() 70 nontransaction T2(C, "T2"); 71 R = T2.exec(("SELECT * FROM " + Table + " " 72 "WHERE year=" + to_string(BoringYear)).c_str()); 73 if (R.size() != 1) 74 throw runtime_error("Expected to find 1 record for " + 75 to_string(BoringYear) + ", found " + 76 to_string(R.size()) + ". " 77 "This could be a bug in libpqxx, " 78 "or something else modified the table."); 51 // Verify that our record was added, despite the Abort() 52 nontransaction T2(C, "T2"); 53 R = T2.exec(("SELECT * FROM " + Table + " " 54 "WHERE year=" + to_string(BoringYear)).c_str()); 79 55 80 if (R.capacity() < R.size()) 81 throw logic_error("Result's capacity is too small!"); 56 PQXX_CHECK_EQUAL( 57 R.size(), 58 1u, 59 "Found wrong number of rows for " + to_string(BoringYear) + "."); 82 60 83 R.clear(); 84 if (!R.empty()) 85 throw logic_error("result::clear() doesn't work!"); 61 PQXX_CHECK(R.capacity() >= R.size(), "Result's capacity is too small."); 86 62 87 // Now remove our record again 88 T2.exec(("DELETE FROM " + Table + " " 89 "WHERE year=" + to_string(BoringYear)).c_str()); 63 R.clear(); 64 PQXX_CHECK(R.empty(), "result::clear() doesn't work."); 90 65 91 T2.commit(); 66 // Now remove our record again 67 T2.exec(("DELETE FROM " + Table + " " 68 "WHERE year=" + to_string(BoringYear)).c_str()); 92 69 93 // And again, verify results 94 nontransaction T3(C, "T3"); 70 T2.commit(); 95 71 96 R = T3.exec(("SELECT * FROM " + Table + " " 97 "WHERE year=" + to_string(BoringYear)).c_str()); 98 if (R.size() != 0) 99 throw runtime_error("Expected record for " + to_string(BoringYear) + " " 100 "to be gone but found " + to_string(R.size()) + ". " 101 "This could be a bug in libpqxx, " 102 "or something else modified the table."); 103 } 104 catch (const sql_error &e) 105 { 106 // If we're interested in the text of a failed query, we can write separate 107 // exception handling code for this type of exception 108 cerr << "SQL error: " << e.what() << endl 109 << "Query was: '" << e.query() << "'" << endl; 110 return 1; 111 } 112 catch (const exception &e) 113 { 114 // All exceptions thrown by libpqxx are derived from std::exception 115 cerr << "Exception: " << e.what() << endl; 116 return 2; 117 } 118 catch (...) 119 { 120 // This is really unexpected (see above) 121 cerr << "Unhandled exception" << endl; 122 return 100; 123 } 72 // And again, verify results 73 nontransaction T3(C, "T3"); 124 74 125 return 0; 75 R = T3.exec(("SELECT * FROM " + Table + " " 76 "WHERE year=" + to_string(BoringYear)).c_str()); 77 78 PQXX_CHECK_EQUAL(R.size(), 0u, "Record still found after removal."); 126 79 } 80 } // namespace 127 81 82 PQXX_REGISTER_TEST_T(test_020, nontransaction) trunk/test/test021.cxx
r428 r1377 1 #include <cassert>2 1 #include <iostream> 3 2 … … 5 4 #include <pqxx/transaction> 6 5 #include <pqxx/result> 6 7 #include "test_helpers.hxx" 7 8 8 9 using namespace PGSTD; … … 12 13 // Simple test program for libpqxx. Open a lazy connection to database, start 13 14 // a transaction, and perform a query inside it. 14 // 15 // Usage: test021 [connect-string] 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 int main(int, char *argv[]) 15 namespace 22 16 { 23 try 17 void test_021(connection_base &, transaction_base &) 18 { 19 lazyconnection C; 20 C.process_notice("Printing details on deferred connection\n"); 21 const string HostName = (C.hostname() ? C.hostname() : "<local>"); 22 C.process_notice(string() + 23 "database=" + C.dbname() + ", " 24 "username=" + C.username() + ", " 25 "hostname=" + HostName + ", " 26 "port=" + to_string(C.port()) + ", " 27 "options='" + C.options() + "', " 28 "backendpid=" + to_string(C.backendpid()) + "\n"); 29 30 work T(C, "test_021"); 31 32 // By now our connection should really have been created 33 C.process_notice("Printing details on actual connection\n"); 34 C.process_notice(string() + 35 "database=" + C.dbname() + ", " 36 "username=" + C.username() + ", " 37 "hostname=" + HostName + ", " 38 "port=" + to_string(C.port()) + ", " 39 "options='" + C.options() + "', " 40 "backendpid=" + to_string(C.backendpid()) + "\n"); 41 42 string P; 43 from_string(C.port(), P); 44 PQXX_CHECK_EQUAL(P, to_string(C.port()), "Port string conversion is broken."); 45 PQXX_CHECK_EQUAL(to_string(P), P, "Port string conversion is broken."); 46 47 result R( T.exec("SELECT * FROM pg_tables") ); 48 49 T.process_notice(to_string(R.size()) + " " 50 "result tuples in transaction " + 51 T.name() + 52 "\n"); 53 54 // Process each successive result tuple 55 for (result::const_iterator c = R.begin(); c != R.end(); ++c) 24 56 { 25 const string ConnectString = (argv[1] ? argv[1] : ""); 26 // Request a connection to the backend, but defer actual creation 27 lazyconnection C(ConnectString); 57 string N; 58 c[0].to(N); 28 59 29 C.process_notice("Printing details on deferred connection\n"); 30 const string HostName = (C.hostname() ? C.hostname() : "<local>"); 31 C.process_notice(string() + 32 "database=" + C.dbname() + ", " 33 "username=" + C.username() + ", " 34 "hostname=" + HostName + ", " 35 "port=" + to_string(C.port()) + ", " 36 "options='" + C.options() + "', " 37 "backendpid=" + to_string(C.backendpid()) + "\n"); 38 39 work T(C, "test21"); 40 41 // By now our connection should really have been created 42 C.process_notice("Printing details on actual connection\n"); 43 C.process_notice(string() + 44 "database=" + C.dbname() + ", " 45 "username=" + C.username() + ", " 46 "hostname=" + HostName + ", " 47 "port=" + to_string(C.port()) + ", " 48 "options='" + C.options() + "', " 49 "backendpid=" + to_string(C.backendpid()) + "\n"); 50 51 string P; 52 from_string(C.port(), P); 53 if (P != to_string(C.port())) 54 throw runtime_error("from_string(const char[],std::string &) " 55 "inconsistent with to_string(const char[])"); 56 if (to_string(P) != P) 57 throw runtime_error("to_string(std::string) turns '" + P + "' " 58 "into '" + to_string(P) + "'"); 59 60 result R( T.exec("SELECT * FROM pg_tables") ); 61 62 T.process_notice(to_string(R.size()) + " " 63 "result tuples in transaction " + 64 T.name() + 65 "\n"); 66 67 // Process each successive result tuple 68 for (result::const_iterator c = R.begin(); c != R.end(); ++c) 69 { 70 string N; 71 c[0].to(N); 72 73 cout << '\t' << to_string(c.num()) << '\t' << N << endl; 74 } 75 76 T.commit(); 77 } 78 catch (const sql_error &e) 79 { 80 cerr << "SQL error: " << e.what() << endl 81 << "Query was: '" << e.query() << "'" << endl; 82 return 1; 83 } 84 catch (const exception &e) 85 { 86 cerr << "Exception: " << e.what() << endl; 87 return 2; 88 } 89 catch (...) 90 { 91 cerr << "Unhandled exception" << endl; 92 return 100; 60 cout << '\t' << to_string(c.num()) << '\t' << N << endl; 93 61 } 94 62 95 return 0;63 T.commit(); 96 64 } 65 } // namespace 97 66 67 PQXX_REGISTER_TEST_NODB(test_021) trunk/test/test023.cxx
r1258 r1377 9 9 #include <pqxx/result> 10 10 11 #include "test_helpers.hxx" 11 12 12 13 using namespace PGSTD; … … 16 17 // Example program for libpqxx. Send notification to self, using deferred 17 18 // connection. 18 //19 // Usage: test02320 21 22 19 namespace 23 20 { … … 75 72 }; 76 73 74 75 void test_023(connection_base &, transaction_base &) 76 { 77 lazyconnection C; 78 cout << "Adding listener..." << endl; 79 TestListener L(C); 80 81 cout << "Sending notification..." << endl; 82 C.perform(Notify(L.name())); 83 84 int notifs = 0; 85 for (int i=0; (i < 20) && !L.Done(); ++i) 86 { 87 PQXX_CHECK_EQUAL(notifs, 0, "Got unexpected notifications."); 88 pqxx::internal::sleep_seconds(1); 89 notifs = C.get_notifs(); 90 cout << "."; 91 } 92 cout << endl; 93 94 PQXX_CHECK(L.Done(), "No notification received."); 95 96 PQXX_CHECK_EQUAL(notifs, 1, "Unexpected number of notifications."); 97 } 77 98 } // namespace 78 99 79 int main() 80 { 81 try 82 { 83 lazyconnection C; 84 cout << "Adding listener..." << endl; 85 TestListener L(C); 86 87 cout << "Sending notification..." << endl; 88 C.perform(Notify(L.name())); 89 90 int notifs = 0; 91 for (int i=0; (i < 20) && !L.Done(); ++i) 92 { 93 if (notifs) 94 throw logic_error("Got " + to_string(notifs) + " " 95 "unexpected notifications!"); 96 pqxx::internal::sleep_seconds(1); 97 notifs = C.get_notifs(); 98 cout << "."; 99 } 100 cout << endl; 101 102 if (!L.Done()) 103 { 104 cout << "No notification received!" << endl; 105 return 1; 106 } 107 if (notifs != 1) 108 throw logic_error("Expected 1 notification, got " + to_string(notifs)); 109 } 110 catch (const sql_error &e) 111 { 112 cerr << "SQL error: " << e.what() << endl 113 << "Query was: '" << e.query() << "'" << endl; 114 return 1; 115 } 116 catch (const exception &e) 117 { 118 // All exceptions thrown by libpqxx are derived from std::exception 119 cerr << "Exception: " << e.what() << endl; 120 return 2; 121 } 122 catch (...) 123 { 124 // This is really unexpected (see above) 125 cerr << "Unhandled exception" << endl; 126 return 100; 127 } 128 129 return 0; 130 } 131 100 PQXX_REGISTER_TEST_NODB(test_023) trunk/test/test024.cxx
r1138 r1377 5 5 #include <pqxx/tablewriter> 6 6 #include <pqxx/transaction> 7 8 #include "test_helpers.hxx" 7 9 8 10 using namespace PGSTD; … … 13 15 // tablewriter on a deferred connection. This data will be used by subsequent 14 16 // tests. Any data previously in the table will be deleted. 15 // 16 // Usage: test024 [connect-string] [tablename] 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 21 // backend running on host foo.bar.net, logging in as user smith. 22 // 23 // The tablename argument determines which table the data will be written to. 24 // If none is given, it defaults to "pqxxorgevents". 25 int main(int argc, char *argv[]) 17 namespace 26 18 { 19 void test_024(connection_base &, transaction_base &) 20 { 21 // Set up a deferred connection to the backend 22 lazyconnection C; 23 24 string TableName("pqxxorgevents"); 25 26 cout << "Dropping old " << TableName << endl; 27 27 try 28 28 { 29 // Set up a deferred connection to the backend 30 lazyconnection C(argv[1]); 31 32 string TableName((argc > 2) ? argv[2] : "pqxxorgevents"); 33 34 cout << "Dropping old " << TableName << endl; 35 try 36 { 37 work Drop(C, "drop_" + TableName); 38 Drop.exec("DROP TABLE " + TableName); 39 Drop.commit(); 40 } 41 catch (const exception &e) 42 { 43 cerr << "Couldn't drop table: " << e.what() << endl; 44 } 45 46 work T(C, "test5"); 47 48 T.exec("CREATE TABLE " + TableName + "(year INTEGER, event VARCHAR)"); 49 50 // NOTE: start a nested block here to ensure that our stream W is closed 51 // before we attempt to commit our transaction T. Otherwise we might end 52 // up committing T before all data going into W had been written. 53 { 54 tablewriter W(T, TableName); 55 56 const char *const CData[][2] = 57 { 58 { "71", "jtv" }, 59 { "38", "time_t overflow" }, 60 { "1", "'911' WTC attack" }, 61 { "81", "C:\\>" }, 62 { "1978", "bloody\t\tcold" }, 63 { "99", "" }, 64 { "2002", "libpqxx" }, 65 { "1989", "Ode an die Freiheit" }, 66 { "2001", "New millennium" }, 67 { "1974", "" }, 68 { "97", "Asian crisis" }, 69 { "01", "A Space Odyssey" }, 70 {0,0} 71 }; 72 73 cout << "Writing data to " << TableName << endl; 74 75 // Insert tuple of data using "begin" and "end" abstraction 76 for (int i=0; CData[i][0]; ++i) 77 W.insert(&CData[i][0], &CData[i][2]); 78 79 // Insert tuple of data held in container 80 vector<string> MoreData; 81 MoreData.push_back("10"); 82 MoreData.push_back("Odyssey Two"); 83 W.insert(MoreData); 84 85 // Now that MoreData has been inserted, we can get rid of the original 86 // and use it for something else. And this time, we use the insertion 87 // operator. 88 MoreData[0] = "3001"; 89 MoreData[1] = "Final Odyssey"; 90 W << MoreData; 91 92 // (destruction of W occurs here) 93 } 94 95 T.commit(); 96 } 97 catch (const sql_error &e) 98 { 99 cerr << "SQL error: " << e.what() << endl 100 << "Query was: '" << e.query() << "'" << endl; 101 return 1; 29 work Drop(C, "drop_" + TableName); 30 Drop.exec("DROP TABLE " + TableName); 31 Drop.commit(); 102 32 } 103 33 catch (const exception &e) 104 34 { 105 // All exceptions thrown by libpqxx are derived from std::exception 106 cerr << "Exception: " << e.what() << endl; 107 return 2; 108 } 109 catch (...) 110 { 111 // This is really unexpected (see above) 112 cerr << "Unhandled exception" << endl; 113 return 100; 35 cerr << "Couldn't drop table: " << e.what() << endl; 114 36 } 115 37 116 return 0; 38 work T(C, "test5"); 39 40 T.exec("CREATE TABLE " + TableName + "(year INTEGER, event VARCHAR)"); 41 42 // NOTE: start a nested block here to ensure that our stream W is closed 43 // before we attempt to commit our transaction T. Otherwise we might end 44 // up committing T before all data going into W had been written. 45 { 46 tablewriter W(T, TableName); 47 48 const char *const CData[][2] = 49 { 50 { "71", "jtv" }, 51 { "38", "time_t overflow" }, 52 { "1", "'911' WTC attack" }, 53 { "81", "C:\\>" }, 54 { "1978", "bloody\t\tcold" }, 55 { "99", "" }, 56 { "2002", "libpqxx" }, 57 { "1989", "Ode an die Freiheit" }, 58 { "2001", "New millennium" }, 59 { "1974", "" }, 60 { "97", "Asian crisis" }, 61 { "01", "A Space Odyssey" }, 62 {0,0} 63 }; 64 65 cout << "Writing data to " << TableName << endl; 66 67 // Insert tuple of data using "begin" and "end" abstraction 68 for (int i=0; CData[i][0]; ++i) 69 W.insert(&CData[i][0], &CData[i][2]); 70 71 // Insert tuple of data held in container 72 vector<string> MoreData; 73 MoreData.push_back("10"); 74 MoreData.push_back("Odyssey Two"); 75 W.insert(MoreData); 76 77 // Now that MoreData has been inserted, we can get rid of the original 78 // and use it for something else. And this time, we use the insertion 79 // operator. 80 MoreData[0] = "3001"; 81 MoreData[1] = "Final Odyssey"; 82 W << MoreData; 83 84 // (destruction of W occurs here) 85 } 86 87 T.commit(); 117 88 } 89 } // namespace 118 90 91 PQXX_REGISTER_TEST_NODB(test_024) trunk/test/test025.cxx
r1138 r1377 9 9 #include <pqxx/transactor> 10 10 11 #include "test_helpers.hxx" 12 11 13 using namespace PGSTD; 12 14 using namespace pqxx; … … 16 18 // another using a tablereader and a tablewriter. Any data already in the 17 19 // destination table is overwritten. Lazy connections are used. 18 //19 // Usage: test025 [connect-string] [orgtable] [dsttable]20 //21 // Where the connect-string is a set of connection options in Postgresql's22 // PQconnectdb() format, eg. "dbname=template1" to select from a database23 // called template1, or "host=foo.bar.net user=smith" to connect to a backend24 // running on host foo.bar.net, logging in as user smith.25 //26 // The sample program assumes that both orgtable and dsttable are tables that27 // exist in the database that connect-string (whether the default or one28 // specified explicitly on the command line) connects to.29 //30 // The default origin table name is "pqxxorgevents"; the default destination31 // table is "pqxxevents".32 33 20 namespace 34 21 { 35 36 22 class CreateTable : public transactor<> 37 23 { … … 69 55 void CheckState(tablereader &R) 70 56 { 71 if (!R != !bool(R)) 72 throw logic_error("tablereader " + R.name() + " in inconsistent state!"); 57 PQXX_CHECK_EQUAL( 58 !R, 59 !bool(R), 60 "tablereader " + R.name() + " is in an inconsistent state."); 73 61 } 74 62 … … 114 102 115 103 116 } 104 void test_025(connection_base &, transaction_base &) 105 { 106 // Set up two connections to the backend: one to read our original table, 107 // and another to write our copy 108 lazyconnection orgC(""), dstC(NULL); 117 109 118 int main(int argc, char *argv[]) 119 { 110 // Select our original and destination table names 111 const string orgTable = "pqxxorgevents"; 112 const string dstTable = "pqxxevents"; 113 114 // Set up a transaction to access the original table from 115 work orgTrans(orgC, "test25org"); 116 117 // Attempt to create table. Ignore errors, as they're probably one of: 118 // (1) Table already exists--fine with us 119 // (2) Something else is wrong--we'll just fail later on anyway 120 120 try 121 121 { 122 const char *ConnStr = argv[1]; 123 124 // Set up two connections to the backend: one to read our original table, 125 // and another to write our copy 126 lazyconnection orgC(ConnStr), dstC(ConnStr); 127 128 // Select our original and destination table names 129 const string orgTable = ((argc > 2) ? argv[2] : "pqxxorgevents"); 130 const string dstTable = ((argc > 3) ? argv[3] : "pqxxevents"); 131 132 // Set up a transaction to access the original table from 133 work orgTrans(orgC, "test25org"); 134 135 // Attempt to create table. Ignore errors, as they're probably one of: 136 // (1) Table already exists--fine with us 137 // (2) Something else is wrong--we'll just fail later on anyway 138 try 139 { 140 dstC.perform(CreateTable(dstTable)); 141 } 142 catch (const sql_error &) 143 { 144 } 145 146
