Changeset 1359

Show
Ignore:
Timestamp:
07/31/08 02:12:39 (5 months ago)
Author:
jtv
Message:

Converted more tests to test framework.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/test/test085.cxx

    r1344 r1359  
    77#include <pqxx/pqxx> 
    88 
     9#include "test_helpers.hxx" 
     10 
    911using namespace PGSTD; 
    1012using namespace pqxx; 
    1113 
     14// Test program for libpqxx.  Define and use prepared statements. 
     15 
     16#define COMPARE_RESULTS(name, lhs, rhs) \ 
     17  PQXX_CHECK_EQUAL(     \ 
     18        rhs,            \ 
     19        lhs,            \ 
     20        "Executing " name " as prepared statement yields different results.") \ 
     21  PQXX_CHECK_EQUAL(lhs.empty(), false, "Result for " name " is empty.") 
     22 
     23 
    1224namespace 
    1325{ 
    14 void compare_results(string name, result lhs, result rhs) 
    15 
    16   if (lhs != rhs) 
    17     throw logic_error("Executing " + name + " as prepared statement " 
    18           "yields different results from direct execution"); 
    19  
    20   if (lhs.empty()) 
    21     throw logic_error("Results being compared are empty.  Not much point!"); 
    22 
    23  
    24  
     26/// Dereference result element as string 
     27struct deref_field 
     28
     29  string operator()(const result::field &f) const { return f.c_str(); } 
     30}; 
     31
     32 
     33namespace pqxx 
     34
     35// Support string conversion for result objects for debug output. 
     36template<> struct string_traits<result> 
     37
     38  static const char *name() { return "pqxx::result"; } 
     39  static bool has_null() { return true; } 
     40  static bool is_null(result r) { return r.empty(); } 
     41  static result null() { return result(); } 
     42  static void from_string(const char Str[], result &Obj); // Not needed 
     43  static string to_string(result Obj) 
     44  { 
     45    if (is_null(Obj)) return "<empty>"; 
     46 
     47    string out; 
     48    for (result::const_iterator row = Obj.begin(); row != Obj.end(); ++row) 
     49    { 
     50      out += "{" + 
     51        separated_list(", ", row.begin(), row.end(), deref_field()) + 
     52        "}"; 
     53    } 
     54    return out; 
     55  } 
     56}; 
     57
     58 
     59 
     60namespace 
     61
    2562string stringize(transaction_base &t, const string &arg) 
    2663{ 
     
    70107} 
    71108 
    72 } // namespace 
    73  
    74  
    75 // Test program for libpqxx.  Define and use prepared statements. 
    76 // 
    77 // Usage: test085 
    78 int main() 
     109 
     110void test_085(connection_base &C, transaction_base &T) 
    79111{ 
    80112  try 
     
    86118     * Later backend versions do not suffer from this problem. 
    87119     */ 
    88     const string QN_readpgtables = "ReadPGTables", 
     120    const string 
    89121          Q_readpgtables = "SELECT * FROM pg_tables", 
    90           QN_seetable = "SeeTable", 
    91122          Q_seetable = Q_readpgtables + " WHERE tablename LIKE $1", 
    92           QN_seetables = "SeeTables", 
    93123          Q_seetables = Q_seetable + " OR tablename LIKE $2"; 
    94124 
    95     lazyconnection C; 
    96  
    97125    cout << "Preparing a simple statement..." << endl; 
    98     C.prepare(QN_readpgtables, Q_readpgtables); 
    99     nontransaction T(C, "test85"); 
    100  
    101     try 
    102     { 
    103       // See if a basic prepared statement works just like a regular query 
    104       cout << "Basic correctness check on prepared statement..." << endl; 
    105       compare_results(QN_readpgtables, 
    106         T.prepared(QN_readpgtables).exec(), 
     126    C.prepare("ReadPGTables", Q_readpgtables); 
     127 
     128    // See if a basic prepared statement works just like a regular query 
     129    cout << "Basic correctness check on prepared statement..." << endl; 
     130    PQXX_CHECK_EQUAL( 
     131        T.prepared(string("ReadPGTables")).exec(), 
     132        T.exec(Q_readpgtables), 
     133        "ReadPGTables"); 
     134 
     135    // Try prepare_now() on an already prepared statement 
     136    C.prepare_now("ReadPGTables"); 
     137 
     138    // Pro forma check: same thing but with name passed as C-style string 
     139    COMPARE_RESULTS("ReadPGTables_char", 
     140        T.prepared("ReadPGTables").exec(), 
    107141        T.exec(Q_readpgtables)); 
    108     } 
    109     catch (const exception &) 
    110     { 
    111       if (!C.supports(connection_base::cap_prepared_statements)) 
    112       { 
    113         cout << "Backend version does not support prepared statements.  " 
    114                 "Skipping." 
    115              << endl; 
    116         return 0; 
    117       } 
    118       throw; 
    119     } 
    120  
    121     // Try prepare_now() on an already prepared statement 
    122     C.prepare_now(QN_readpgtables); 
    123  
    124     // Pro forma check: same thing but with name passed as C-style string 
    125     compare_results(QN_readpgtables+"_char", 
    126         T.prepared(QN_readpgtables.c_str()).exec(), 
    127         T.exec(Q_readpgtables)); 
    128142 
    129143    cout << "Dropping prepared statement..." << endl; 
    130     C.unprepare(QN_readpgtables); 
    131  
    132     bool failed = true; 
    133     try 
    134     { 
    135       disable_noticer d(C); 
    136       C.prepare_now(QN_readpgtables); 
    137       failed = false; 
    138     } 
    139     catch (const exception &e) 
    140     { 
    141       cout << "(Expected) " << e.what() << endl; 
    142     } 
    143     if (!failed) 
    144       throw runtime_error("prepare_now() succeeded on dropped statement"); 
    145  
     144    C.unprepare("ReadPGTables"); 
     145 
     146    PQXX_CHECK_THROWS( 
     147        C.prepare_now("ReadPGTables"), 
     148        exception, 
     149        "prepare_now() succeeded on dropped statement.") 
    146150 
    147151    // Just to try and confuse things, "unprepare" twice 
    148152    cout << "Testing error detection and handling..." << endl; 
    149     try { C.unprepare(QN_readpgtables); } 
     153    try { C.unprepare("ReadPGTables"); } 
    150154    catch (const exception &e) { cout << "(Expected) " << e.what() << endl; } 
    151155 
    152156    // Verify that attempt to execute unprepared statement fails 
    153     bool failsOK = true; 
    154     try { T.prepared(QN_readpgtables).exec(); failsOK = false; } 
    155     catch (const exception &e) { cout << "(Expected) " << e.what() << endl; } 
    156     if (!failsOK) throw logic_error("Execute unprepared statement didn't fail"); 
     157    PQXX_CHECK_THROWS( 
     158        T.prepared("ReadPGTables").exec(), 
     159        exception, 
     160        "Execute unprepared statement didn't fail.") 
    157161 
    158162    // Re-prepare the same statement and test again 
    159     C.prepare(QN_readpgtables, Q_readpgtables); 
    160     C.prepare_now(QN_readpgtables); 
    161     compare_results(QN_readpgtables+"_2", 
    162         T.prepared(QN_readpgtables).exec(), 
     163    C.prepare("ReadPGTables", Q_readpgtables); 
     164    C.prepare_now("ReadPGTables"); 
     165    COMPARE_RESULTS("ReadPGTables_2", 
     166        T.prepared("ReadPGTables").exec(), 
    163167        T.exec(Q_readpgtables)); 
    164168 
    165169    // Double preparation of identical statement should be ignored... 
    166     C.prepare(QN_readpgtables, Q_readpgtables); 
    167     compare_results(QN_readpgtables+"_double", 
    168         T.prepared(QN_readpgtables).exec(), 
     170    C.prepare("ReadPGTables", Q_readpgtables); 
     171    COMPARE_RESULTS("ReadPGTables_double", 
     172        T.prepared("ReadPGTables").exec(), 
    169173        T.exec(Q_readpgtables)); 
    170174 
    171175    // ...But a modified definition shouldn't 
    172     try 
    173     { 
    174       failsOK = true; 
    175       C.prepare(QN_readpgtables, Q_readpgtables + " ORDER BY tablename"); 
    176       failsOK = false; 
    177     } 
    178     catch (const exception &e) 
    179     { 
    180       cout << "(Expected) " << e.what() << endl; 
    181     } 
    182     if (!failsOK) 
    183       throw logic_error("Bad redefinition of statement went unnoticed"); 
     176    PQXX_CHECK_THROWS( 
     177        C.prepare("ReadPGTables", Q_readpgtables + " ORDER BY tablename"), 
     178        exception, 
     179        "Bad redefinition of statement went unnoticed.") 
    184180 
    185181    cout << "Testing prepared statement with parameter..." << endl; 
    186182 
    187     C.prepare(QN_seetable, Q_seetable)("varchar", pqxx::prepare::treat_string); 
     183    C.prepare("SeeTable", Q_seetable)("varchar", pqxx::prepare::treat_string); 
    188184 
    189185    vector<string> args; 
    190186    args.push_back("pg_type"); 
    191     compare_results(QN_seetable+"_seq", 
    192         T.prepared(QN_seetable)(args[0]).exec(), 
     187    COMPARE_RESULTS("SeeTable_seq", 
     188        T.prepared("SeeTable")(args[0]).exec(), 
    193189        T.exec(subst(T,Q_seetable,args))); 
    194190 
    195191    cout << "Testing prepared statement with 2 parameters..." << endl; 
    196192 
    197     C.prepare(QN_seetables, Q_seetables) 
     193    C.prepare("SeeTables", Q_seetables) 
    198194      ("varchar",pqxx::prepare::treat_string) 
    199195      ("varchar",pqxx::prepare::treat_string); 
    200196    args.push_back("pg_index"); 
    201     compare_results(QN_seetables+"_seq", 
    202       T.prepared(QN_seetables)(args[0])(args[1]).exec(), 
     197    COMPARE_RESULTS("SeeTables_seq", 
     198      T.prepared("SeeTables")(args[0])(args[1]).exec(), 
    203199      T.exec(subst(T,Q_seetables,args))); 
    204200 
     
    207203    ptrs.push_back(0); 
    208204    ptrs.push_back("pg_index"); 
    209     compare_results(QN_seetables+"_null1", 
    210         T.prepared(QN_seetables)(ptrs[0])(ptrs[1]).exec(), 
     205    COMPARE_RESULTS("SeeTables_null1", 
     206        T.prepared("SeeTables")(ptrs[0])(ptrs[1]).exec(), 
    211207        T.exec(subst(T,Q_seetables,ptrs))); 
    212     compare_results(QN_seetables+"_null2", 
    213         T.prepared(QN_seetables)(ptrs[0])(ptrs[1]).exec(), 
    214         T.prepared(QN_seetables)()(ptrs[1]).exec()); 
    215     compare_results(QN_seetables+"_null3", 
    216         T.prepared(QN_seetables)(ptrs[0])(ptrs[1]).exec(), 
    217         T.prepared(QN_seetables)("somestring",false)(ptrs[1]).exec()); 
    218     compare_results(QN_seetables+"_null4", 
    219         T.prepared(QN_seetables)(ptrs[0])(ptrs[1]).exec(), 
    220         T.prepared(QN_seetables)(42,false)(ptrs[1]).exec()); 
    221     compare_results(QN_seetables+"_null5", 
    222         T.prepared(QN_seetables)(ptrs[0])(ptrs[1]).exec(), 
    223         T.prepared(QN_seetables)(0,false)(ptrs[1]).exec()); 
     208    COMPARE_RESULTS("SeeTables_null2", 
     209        T.prepared("SeeTables")(ptrs[0])(ptrs[1]).exec(), 
     210        T.prepared("SeeTables")()(ptrs[1]).exec()); 
     211    COMPARE_RESULTS("SeeTables_null3", 
     212        T.prepared("SeeTables")(ptrs[0])(ptrs[1]).exec(), 
     213        T.prepared("SeeTables")("somestring",false)(ptrs[1]).exec()); 
     214    COMPARE_RESULTS("SeeTables_null4", 
     215        T.prepared("SeeTables")(ptrs[0])(ptrs[1]).exec(), 
     216        T.prepared("SeeTables")(42,false)(ptrs[1]).exec()); 
     217    COMPARE_RESULTS("SeeTables_null5", 
     218        T.prepared("SeeTables")(ptrs[0])(ptrs[1]).exec(), 
     219        T.prepared("SeeTables")(0,false)(ptrs[1]).exec()); 
    224220 
    225221    cout << "Testing wrong numbers of parameters..." << endl; 
    226     try 
    227     { 
    228       failsOK = true; 
    229       T.prepared(QN_seetables)()()("hi mom!").exec(); 
    230       failsOK = false; 
    231     } 
    232     catch (const exception &e) 
    233     { 
    234       cout << "(Expected) " << e.what() << endl; 
    235     } 
    236     if (!failsOK) 
    237       throw logic_error("No error for too many parameters"); 
    238     try 
    239     { 
    240       failsOK = true; 
    241       T.prepared(QN_seetables)("who, me?").exec(); 
    242       failsOK = false; 
    243     } 
    244     catch (const exception &e) 
    245     { 
    246       cout << "(Expected) " << e.what() << endl; 
    247     } 
    248     if (!failsOK) 
    249       throw logic_error("No error for too few parameters"); 
    250  
    251     cout << "Done." << endl; 
     222    PQXX_CHECK_THROWS( 
     223        T.prepared("SeeTables")()()("hi mom!").exec(), 
     224        exception, 
     225        "No error for too many parameters.") 
     226 
     227    PQXX_CHECK_THROWS( 
     228        T.prepared("SeeTables")("who, me?").exec(), 
     229        exception, 
     230        "No error for too few parameters.") 
    252231  } 
    253232  catch (const feature_not_supported &e) 
     
    255234    cout << "Backend version does not support prepared statements.  Skipping." 
    256235         << endl; 
    257     return 0; 
    258   } 
    259   catch (const sql_error &e) 
    260   { 
    261     cerr << "SQL error: " << e.what() << endl 
    262          << "Query was: " << e.query() << endl; 
    263     return 1; 
    264   } 
    265   catch (const exception &e) 
    266   { 
    267     // All exceptions thrown by libpqxx are derived from std::exception 
    268     cerr << "Exception: " << e.what() << endl; 
    269     return 2; 
    270   } 
    271   catch (...) 
    272   { 
    273     // This is really unexpected (see above) 
    274     cerr << "Unhandled exception" << endl; 
    275     return 100; 
    276   } 
    277  
    278   return 0; 
    279 
    280  
    281  
     236  } 
     237
     238 
     239} // namespace 
     240 
     241 
     242int main() 
     243
     244  test::TestCase<lazyconnection, nontransaction> test085("test_085", test_085); 
     245  return test::pqxxtest(test085); 
     246
     247