Changeset 1377

Show
Ignore:
Timestamp:
08/13/08 08:40:23 (5 months ago)
Author:
jtv
Message:

More test framework migration.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/ChangeLog

    r1376 r1377  
     12008-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. 
    1202008-08-12  Jeroen T. Vermeulen <jtv@xs4all.nl> 
    221 test/test011.cxx, test/test012.cxx, test/test013.cxx, test/test014.cxx,  
  • trunk/test/test001.cxx

    r1375 r1377  
    1 #include <cassert> 
    21#include <iostream> 
    32 
  • trunk/test/test013.cxx

    r1376 r1377  
    1 #include <cassert> 
    21#include <cstdio> 
    32#include <iostream> 
  • trunk/test/test016.cxx

    r1376 r1377  
    1515namespace 
    1616{ 
    17  
    1817void test_016(connection_base &, transaction_base &T) 
    1918{ 
     
    3029 
    3130  // 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 
    3433  --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 
    3740  const string nullstr; 
    3841  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."); 
    4548 
    4649  // "Commit" the non-transaction.  This doesn't really do anything since 
  • trunk/test/test017.cxx

    r1040 r1377  
    66#include <pqxx/result> 
    77 
     8#include "test_helpers.hxx" 
     9 
    810using namespace PGSTD; 
    911using namespace pqxx; 
     
    1214// Simple test program for libpqxx.  Open connection to database, start 
    1315// 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  
     16namespace 
     17
    2218class ReadTables : public transactor<nontransaction> 
    2319{ 
     
    4440 
    4541 
    46 int main(int, char *argv[]
     42void test_017(connection_base &C, transaction_base &T
    4743{ 
    48   try 
    49   { 
    50     connection C(argv[1]); 
     44  T.abort(); 
     45  C.perform(ReadTables()); 
     46
     47} // namespace 
    5148 
    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  
     49PQXX_REGISTER_TEST_T(test_017, nontransaction) 
  • trunk/test/test018.cxx

    r1175 r1377  
    1010#include <pqxx/transactor> 
    1111 
     12#include "test_helpers.hxx" 
     13 
    1214using namespace PGSTD; 
    1315using namespace pqxx; 
     
    1618// Test program for libpqxx.  Verify abort behaviour of RobustTransaction. 
    1719// 
    18 // Usage: test018 [connect-string] [table] 
    19 // 
    20 // Where connect-string is a set of connection options in Postgresql's 
    21 // PQconnectdb() format, eg. "dbname=template1" to select from a database 
    22 // called template1, or "host=foo.bar.net user=smith" to connect to a 
    23 // backend running on host foo.bar.net, logging in as user smith. 
    24 // 
    2520// The program will attempt to add an entry to a table called "pqxxevents", 
    2621// with a key column called "year"--and then abort the change. 
    27  
    2822namespace 
    2923{ 
     
    5953  } 
    6054}; 
    61  
    6255 
    6356 
     
    10295}; 
    10396 
     97 
    10498string FailedInsert::LastReason; 
    10599 
     100 
     101void 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} 
    106133} // namespace 
    107134 
    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  
     135PQXX_REGISTER_TEST_T(test_018, nontransaction) 
  • trunk/test/test020.cxx

    r1138 r1377  
    1 #include <cassert> 
    21#include <iostream> 
    32 
     
    54#include <pqxx/nontransaction> 
    65#include <pqxx/result> 
     6 
     7#include "test_helpers.hxx" 
    78 
    89using namespace PGSTD; 
     
    1314// verify that the change gets made regardless of whether the NonTransaction is 
    1415// eventually committed or aborted. 
    15 // 
    16 // Usage: test020 [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 
    21 // backend running on host foo.bar.net, logging in as user smith. 
    22 // 
    23 // The table argument is the table being modified.  This defaults to 
    24 // "pqxxevents". 
    25 // It is assumed to consist of an integer key called year, and a string. 
    2616namespace 
    2717{ 
    2818const unsigned long BoringYear = 1977; 
    2919 
    30 } // namespace 
    3120 
    32 int main(int argc, char *argv[]
     21void test_020(connection_base &C, transaction_base &T1
    3322{ 
    34   try 
    35   { 
    36     connection C(argv[1]); 
     23  const string Table = "pqxxevents"; 
    3724 
    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 + " " 
    4628                       "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 " + 
    4931                          to_string(BoringYear) + ". " 
    5032                          "Can't run test."); 
    5133 
    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()!"); 
    5638 
    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()); 
    6345 
    64     // Abort T1.  Since T1 is a NonTransaction, which provides only the 
    65     // transaction class interface without providing any form of transactional 
    66     // 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(); 
    6850 
    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()); 
    7955 
    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) + "."); 
    8260 
    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."); 
    8662 
    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."); 
    9065 
    91     T2.commit(); 
     66  // Now remove our record again 
     67  T2.exec(("DELETE FROM " + Table + " " 
     68           "WHERE year=" + to_string(BoringYear)).c_str()); 
    9269 
    93     // And again, verify results 
    94     nontransaction T3(C, "T3"); 
     70  T2.commit(); 
    9571 
    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"); 
    12474 
    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."); 
    12679} 
     80} // namespace 
    12781 
     82PQXX_REGISTER_TEST_T(test_020, nontransaction) 
  • trunk/test/test021.cxx

    r428 r1377  
    1 #include <cassert> 
    21#include <iostream> 
    32 
     
    54#include <pqxx/transaction> 
    65#include <pqxx/result> 
     6 
     7#include "test_helpers.hxx" 
    78 
    89using namespace PGSTD; 
     
    1213// Simple test program for libpqxx.  Open a lazy connection to database, start 
    1314// 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[]) 
     15namespace 
    2216{ 
    23   try 
     17void 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) 
    2456  { 
    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); 
    2859 
    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; 
    9361  } 
    9462 
    95   return 0
     63  T.commit()
    9664} 
     65} // namespace 
    9766 
     67PQXX_REGISTER_TEST_NODB(test_021) 
  • trunk/test/test023.cxx

    r1258 r1377  
    99#include <pqxx/result> 
    1010 
     11#include "test_helpers.hxx" 
    1112 
    1213using namespace PGSTD; 
     
    1617// Example program for libpqxx.  Send notification to self, using deferred 
    1718// connection. 
    18 // 
    19 // Usage: test023 
    20  
    21  
    2219namespace 
    2320{ 
     
    7572}; 
    7673 
     74 
     75void 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} 
    7798} // namespace 
    7899 
    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  
     100PQXX_REGISTER_TEST_NODB(test_023) 
  • trunk/test/test024.cxx

    r1138 r1377  
    55#include <pqxx/tablewriter> 
    66#include <pqxx/transaction> 
     7 
     8#include "test_helpers.hxx" 
    79 
    810using namespace PGSTD; 
     
    1315// tablewriter on a deferred connection.  This data will be used by subsequent 
    1416// 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[]) 
     17namespace 
    2618{ 
     19void 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; 
    2727  try 
    2828  { 
    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(); 
    10232  } 
    10333  catch (const exception &e) 
    10434  { 
    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; 
    11436  } 
    11537 
    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(); 
    11788} 
     89} // namespace 
    11890 
     91PQXX_REGISTER_TEST_NODB(test_024) 
  • trunk/test/test025.cxx

    r1138 r1377  
    99#include <pqxx/transactor> 
    1010 
     11#include "test_helpers.hxx" 
     12 
    1113using namespace PGSTD; 
    1214using namespace pqxx; 
     
    1618// another using a tablereader and a tablewriter.  Any data already in the 
    1719// 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's 
    22 // PQconnectdb() format, eg. "dbname=template1" to select from a database 
    23 // called template1, or "host=foo.bar.net user=smith" to connect to a backend 
    24 // running on host foo.bar.net, logging in as user smith. 
    25 // 
    26 // The sample program assumes that both orgtable and dsttable are tables that 
    27 // exist in the database that connect-string (whether the default or one 
    28 // specified explicitly on the command line) connects to. 
    29 // 
    30 // The default origin table name is "pqxxorgevents"; the default destination 
    31 // table is "pqxxevents". 
    32  
    3320namespace 
    3421{ 
    35  
    3622class CreateTable : public transactor<> 
    3723{ 
     
    6955void CheckState(tablereader &R) 
    7056{ 
    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."); 
    7361} 
    7462 
     
    114102 
    115103 
    116 
     104void 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); 
    117109 
    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 
    120120  try 
    121121  { 
    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