test_bdb.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:44k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: test_bdb.cpp,v $
  4.  * PRODUCTION Revision 1000.5  2004/06/01 18:37:53  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.46
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: test_bdb.cpp,v 1000.5 2004/06/01 18:37:53 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author: Anatoliy Kuznetsov
  35.  *
  36.  * File Description: Test application for NCBI Berkeley DB library (BDB)
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <corelib/ncbiapp.hpp>
  41. #include <corelib/ncbiargs.hpp>
  42. #include <corelib/ncbifile.hpp>
  43. #include <corelib/ncbitime.hpp>
  44. #include <stdio.h>
  45. #include <bdb/bdb_expt.hpp>
  46. #include <bdb/bdb_types.hpp>
  47. #include <bdb/bdb_file.hpp>
  48. #include <bdb/bdb_env.hpp>
  49. #include <bdb/bdb_cursor.hpp>
  50. #include <bdb/bdb_blob.hpp>
  51. #include <bdb/bdb_map.hpp>
  52. #include <bdb/bdb_blobcache.hpp>
  53. #include <bdb/bdb_filedump.hpp>
  54. #include <bdb/bdb_trans.hpp>
  55. #include <bdb/bdb_query.hpp>
  56. #include <bdb/bdb_query_parser.hpp>
  57. #include <test/test_assert.h>  /* This header must go last */
  58. USING_NCBI_SCOPE;
  59. static const char* s_TestStrTempl = "Test str %i";
  60. static const char* s_StrKeyTempl = "%i test key %i";
  61. ////////////////////////////////
  62. // Test functions, classes, etc.
  63. //
  64. //////////////////////////////////////////////////////////////////
  65. // 
  66. // Structure implements simple database table with integer id primary key
  67. //
  68. //
  69. struct TestDBF1 : public CBDB_IdFile
  70. {
  71.     CBDB_FieldInt4      idata;
  72.     CBDB_FieldString    str;
  73.     CBDB_FieldInt4      i2;
  74.     CBDB_FieldInt2      ishort;
  75.     
  76.     TestDBF1()
  77.     {
  78.         BindData("idata", &idata);
  79.         BindData("str", &str, 256);
  80.         BindData("i2", &i2);
  81.         BindData("ishort", &ishort);
  82.     }
  83. };
  84. struct TestDBF1L : public CBDB_IdFile
  85. {
  86.     CBDB_FieldInt4      idata;
  87.     CBDB_FieldLString   str;
  88.     CBDB_FieldInt4      i2;
  89.     CBDB_FieldInt2      ishort;
  90.     
  91.     TestDBF1L()
  92.     {
  93.         BindData("idata", &idata);
  94.         BindData("str", &str, 256);
  95.         BindData("i2", &i2);
  96.         BindData("ishort", &ishort);
  97.         SetLegacyStringsCheck(true);        
  98.     }
  99. };
  100. // Utility function to check record consistency 
  101. template<class T>
  102. void ValidateRecord(const T& dbf1, unsigned int id)
  103. {
  104.     char buf[256];
  105.     sprintf(buf, s_TestStrTempl, id);
  106.     int idata1 = dbf1.idata;
  107.     unsigned int id_key = dbf1.IdKey;
  108.     string s;
  109.     s = dbf1.str;
  110.     int i21 = dbf1.i2;
  111.     assert(s == string(buf));
  112.     assert(id_key == id);
  113.     assert(idata1 == (int)(400 + id));
  114.     assert(i21 == (int)(id + 3));    
  115. }
  116. const char* s_TestFileName = "testbase.db";
  117. const char* s_TestFileName2= "testbase2.db";
  118. const char* s_TestFileName3= "testbase3.db";
  119. const char* s_db_map1 = "i2s.db";
  120. const char* s_db_map2 = "ii2s.db";
  121. const unsigned int s_RecsInTable = 100;
  122. //////////////////////////////////////////////////////////////////
  123. // 
  124. // Structure implements simple database table with case insensitive string 
  125. // as a primary key
  126. //
  127. //
  128. struct TestDBF2 : public CBDB_File
  129. {
  130.     CBDB_FieldStringCase  str_key;
  131.     CBDB_FieldInt4        idata;
  132.     CBDB_FieldString      str;
  133.     CBDB_FieldInt4        i2;
  134.     TestDBF2()
  135.     {
  136.         BindKey("strkey", &str_key, 256);
  137.         BindData("idata", &idata);
  138.         BindData("str", &str, 256);
  139.         BindData("i2", &i2);
  140.     }
  141. };
  142. // Utility function to check record consistency 
  143. void ValidateRecord(const TestDBF2& dbf2, unsigned i)
  144. {
  145.     char buf[256];
  146.     sprintf(buf, s_StrKeyTempl, i, i);
  147.     string s = (const char*)dbf2.str_key;
  148.     assert(s == string(buf));
  149.     assert(dbf2.idata == (int)(400+i));
  150.     sprintf(buf, s_TestStrTempl, i);
  151.     s = (const char*)dbf2.str;
  152.     assert(s == string(buf));
  153.     assert((int)dbf2.i2 == (int)(i+3));
  154. }
  155. struct TestDBF3 : public CBDB_File
  156. {
  157.     CBDB_FieldInt4        ikey;
  158.     CBDB_FieldInt4        idata;
  159.     TestDBF3()
  160.     {
  161.         BindKey("ikey",   &ikey);
  162.         BindData("idata", &idata);
  163.     }
  164. };
  165. //////////////////////////////////////////////////////////////////
  166. //
  167. // 
  168. // BDB transaction test
  169. //
  170. //
  171. static
  172. void s_TEST_BDB_Transaction(void)
  173. {
  174.     cout << "======== Transactions test." << endl;
  175.     CBDB_Env env;
  176.     env.OpenWithTrans(".");
  177.     
  178.     TestDBF3  dbf3;
  179.     
  180.     dbf3.SetEnv(env);
  181.    
  182.     dbf3.Open("trans_test.db", CBDB_File::eReadWriteCreate);
  183.     cout << dbf3.CountRecs() << endl;
  184.     CBDB_Transaction trans(env);
  185.     dbf3.SetTransaction(&trans);
  186.     dbf3.ikey = 10;
  187.     dbf3.idata = 11;
  188.     dbf3.Insert();
  189.     dbf3.ikey = 12;
  190.     dbf3.idata = 13;
  191.     dbf3.Insert();
  192.     trans.Commit();
  193.     dbf3.ikey = 10;
  194.     EBDB_ErrCode ret = dbf3.Fetch();
  195.     assert (ret == eBDB_Ok);
  196.     
  197.     int idata = dbf3.idata;
  198.     assert(idata == 11);
  199.     dbf3.ikey = 10;
  200.     dbf3.idata = 20;
  201.     dbf3.UpdateInsert();
  202.     ret = dbf3.Fetch();
  203.     assert (ret == eBDB_Ok);
  204.     idata = dbf3.idata;
  205.     assert(idata == 20);
  206.     dbf3.ikey = 12;
  207.     ret = dbf3.Fetch();
  208.     assert (ret == eBDB_Ok);
  209.     idata = dbf3.idata;
  210.     assert(idata == 13);
  211.     trans.Abort();
  212.     dbf3.SetTransaction(0);
  213.     dbf3.ikey = 10;
  214.     ret = dbf3.Fetch();
  215.     assert (ret == eBDB_Ok);
  216.     
  217.     idata = dbf3.idata;
  218.     assert(idata == 11);
  219.     cout << "======== Transactions test ok." << endl;
  220. }
  221. //////////////////////////////////////////////////////////////////
  222. //
  223. // 
  224. // BDB types test
  225. //
  226. //
  227. static void s_TEST_BDB_Types(void)
  228. {
  229.     cout << "======== BDB types test." << endl;
  230.     TestDBF1  dbf1;
  231.     cout << "======== BDB types test ok." << endl;
  232. }
  233. //////////////////////////////////////////////////////////////////
  234. //
  235. // 
  236. // BDB Id table fill test
  237. //
  238. //
  239. static 
  240. void s_IdTableFill(TestDBF1& dbf, unsigned int records)
  241. {
  242.     for (unsigned int i = 1; i < records; ++i) {
  243.         char buf[256];
  244.         sprintf(buf, s_TestStrTempl, i);
  245.         dbf.IdKey = i;
  246.         dbf.idata = 400+i;
  247.         dbf.str = buf;
  248.         dbf.i2.Set(i+3);
  249.         int i2 = dbf.i2;
  250.         assert (i2 == (int)(i+3));
  251.         assert(!dbf.idata.IsNull());
  252.         EBDB_ErrCode err = dbf.Insert();
  253.         assert(err == eBDB_Ok);
  254.         assert(dbf.idata.IsNull());
  255.     }
  256. }
  257. static void s_TEST_BDB_IdTable_Fill(void)
  258. {
  259.     cout << "======== Id table filling test." << endl;
  260.     CBDB_Env env;
  261.     env.OpenWithLocks(0);
  262.     env.OpenErrFile("err_test.txt");
  263.     TestDBF1  dbf1;
  264.     dbf1.SetEnv(env);
  265.     dbf1.SetPageSize(32 * 1024);
  266.     dbf1.SetCacheSize(5 * (1024 * 1024));
  267.     dbf1.Open(s_TestFileName, CBDB_File::eCreate);
  268.     assert(dbf1.idata.IsNull());
  269.     // Fill the table
  270.     unsigned i;
  271.     s_IdTableFill(dbf1, s_RecsInTable);
  272.     
  273.     // Trying to put duplicate record
  274.     dbf1.IdKey = 1;
  275.     dbf1.idata = 400 + 1;
  276.     dbf1.str = "test";
  277.     EBDB_ErrCode err = dbf1.Insert();
  278.     assert(err == eBDB_KeyDup);
  279.     cout << "Table " << s_TestFileName 
  280.          << " loaded ok. Checking consistency." 
  281.          << endl;
  282.     // Read the table check if all records are in place
  283.     dbf1.Reopen(CBDB_File::eReadOnly);
  284.     for (i = 1; i < s_RecsInTable; ++i) {
  285.         dbf1.IdKey = i;
  286.         EBDB_ErrCode ret = dbf1.Fetch();
  287.         assert (ret == eBDB_Ok);
  288.         ValidateRecord(dbf1, i);
  289.     } // for
  290.     {{
  291.     TestDBF1  dbf11;
  292.     dbf11.Attach(dbf1);
  293.     for (i = 1; i < s_RecsInTable; ++i) {
  294.         dbf11.IdKey = i;
  295.         EBDB_ErrCode ret = dbf11.Fetch();
  296.         assert (ret == eBDB_Ok);
  297.         ValidateRecord(dbf11, i);
  298.         // Checking that attached buffer doesn't change status of the main one
  299.         dbf1.IdKey = 1;
  300.         ret = dbf1.Fetch();
  301.         assert (ret == eBDB_Ok);
  302.         ValidateRecord(dbf1, 1);
  303.         ValidateRecord(dbf11, i);
  304.     } // for
  305.     }}
  306.     {{
  307.     TestDBF1L  dbf11;
  308.     dbf11.Open(s_TestFileName, CBDB_File::eReadWrite);
  309.     for (i = 1; i < s_RecsInTable; ++i) {
  310.         dbf11.IdKey = i;
  311.         EBDB_ErrCode ret = dbf11.Fetch();
  312.         assert (ret == eBDB_Ok);
  313.         ValidateRecord(dbf11, i);
  314.     } // for
  315.     string s = "123";
  316.     s.append(1, (char)0);
  317.     s.append("123");
  318.     cout << "(" << s << ")" << s.length() << endl;
  319.     dbf11.IdKey = 1000;
  320.     dbf11.idata = 1000;
  321.     dbf11.str = s;
  322.     dbf11.Insert();
  323.     dbf11.IdKey = 1000;
  324.     EBDB_ErrCode ret = dbf11.Fetch();
  325.     assert (ret == eBDB_Ok);
  326.     string s2 = dbf11.str;
  327.     string s3 = dbf11.str.GetString();
  328.     size_t l2 = s2.length();
  329.     size_t l3 = s3.length();
  330.     assert(s3 == s);
  331.     assert(s2 == s);
  332.     assert(l2 == l3);
  333.     // Dumping the database to screen
  334.     CBDB_FileDumper dump;
  335.     dump.Dump(cout, dbf11);
  336.     }}
  337.     cout << "======== Id table filling test ok." << endl;
  338. }
  339. static void s_TEST_BDB_IdTable_FillStress(void)
  340. {
  341.     cout << "======== Id table filling stress test." << endl;
  342.     CBDB_Env env;
  343.     env.SetCacheSize(150 * (1024 * 1024));
  344.     env.OpenWithLocks(0);
  345.     TestDBF1  dbf1;
  346.     dbf1.SetEnv(env);
  347.     dbf1.Open(s_TestFileName, CBDB_File::eCreate);
  348.     assert(dbf1.idata.IsNull());
  349.     // Fill the table
  350.     unsigned i;
  351.     const unsigned int recs = 1000000;
  352.     s_IdTableFill(dbf1, recs);
  353.     cout << "Table loaded..." << endl;    
  354.     // Read the table check if all records are in place
  355.     dbf1.Reopen(CBDB_File::eReadOnly);
  356.     for (i = 1; i < recs; ++i) {
  357.         dbf1.IdKey = i;
  358.         EBDB_ErrCode ret = dbf1.Fetch();
  359.         assert (ret == eBDB_Ok);
  360.         ValidateRecord(dbf1, i);
  361.     } // for
  362.     cout << "Check 1 complete" << endl;
  363.     dbf1.Reopen(CBDB_File::eReadOnly);
  364.     for (i = 1; i < recs; ++i) {
  365.         {{
  366.             CBDB_FileCursor cur(dbf1);
  367.             cur.SetCondition(CBDB_FileCursor::eEQ);
  368.             cur.From << i;
  369.             EBDB_ErrCode ret = cur.FetchFirst();
  370.             assert (ret == eBDB_Ok);
  371.             ValidateRecord(dbf1, i);
  372.         }}
  373.     } // for
  374.     cout << "======== Id table stress filling test ok." << endl;
  375. }
  376. class CTestScanner : public CBDB_FileScanner
  377. {
  378. public:
  379.     CTestScanner(CBDB_File& db_file)
  380.     : CBDB_FileScanner(db_file)
  381.     {}
  382.     virtual EScanAction OnRecordFound()
  383.     {
  384.         return eContinue;
  385.     }
  386. protected:
  387.     
  388. };
  389. static void s_TEST_BDB_Query(void)
  390. {
  391.     bool bres;
  392.     cout << "======== Query test." << endl;
  393.     TestDBF1  dbf1;
  394.     dbf1.Open(s_TestFileName, CBDB_File::eReadOnly);
  395.     dbf1.IdKey = 1;
  396.     dbf1.Fetch();
  397.     CTestScanner  scanner(dbf1);
  398.     CBDB_Query    query;
  399.     {{
  400.         const char* ch = " test";
  401.         CBDB_Query    query;
  402.         BDB_PrintQueryTree(cout, query);
  403.         BDB_ParseQuery(ch, &query);
  404.         BDB_PrintQueryTree(cout, query);
  405.     }}
  406.     {{
  407.         const char* ch = "  '2' And ((name3 OR 1) & name3)";
  408.         CBDB_Query    query;
  409.         BDB_ParseQuery(ch, &query);
  410.         BDB_PrintQueryTree(cout, query);
  411.     }}
  412.     // Testing the query evaluation logic
  413.     //
  414.     // "1" == "2" => false
  415.     {{
  416.     CBDB_Query::TQueryClause* eq_node = 
  417.           CBDB_Query::NewOperatorNode(CBDB_QueryNode::eEQ, "1", "2");
  418.     query.SetQueryClause(eq_node);
  419.     bres = scanner.StaticEvaluate(query);
  420.     assert(!bres);
  421.     BDB_PrintQueryTree(cout, query);
  422.     }}
  423.     {{
  424.     const char* ch = "'1' = 2";
  425.     BDB_ParseQuery(ch, &query);
  426.     bres = scanner.StaticEvaluate(query);
  427.     assert(!bres);
  428.     }}
  429.     {{
  430.     const char* ch = "not '1' = 2";
  431.     BDB_ParseQuery(ch, &query);
  432.     bres = scanner.StaticEvaluate(query);
  433.     cout << endl;
  434.     BDB_PrintQueryTree(cout, query);
  435.     assert(bres);
  436.     }}
  437.     {{
  438.     const char* ch = "'1' != 2";
  439.     BDB_ParseQuery(ch, &query);
  440.     bres = scanner.StaticEvaluate(query);
  441.     assert(bres);
  442.     }}
  443.     {{
  444.     const char* ch = "'1' <> 2";
  445.     BDB_ParseQuery(ch, &query);
  446.     bres = scanner.StaticEvaluate(query);
  447.     assert(bres);
  448.     }}
  449.     {{
  450.     const char* ch = "'1' < 2";
  451.     BDB_ParseQuery(ch, &query);
  452.     bres = scanner.StaticEvaluate(query);
  453.     assert(bres);
  454.     }}
  455.     {{
  456.     const char* ch = "'1' <= 1";
  457.     BDB_ParseQuery(ch, &query);
  458.     bres = scanner.StaticEvaluate(query);
  459.     assert(bres);
  460.     }}
  461.     {{
  462.     const char* ch = "'1' >= 1";
  463.     BDB_ParseQuery(ch, &query);
  464.     bres = scanner.StaticEvaluate(query);
  465.     assert(bres);
  466.     }}
  467.     {{
  468.     const char* ch = "'2' > 1";
  469.     BDB_ParseQuery(ch, &query);
  470.     bres = scanner.StaticEvaluate(query);
  471.     assert(bres);
  472.     }}
  473.     // "2" == "2" => true
  474.     {{
  475.     CBDB_Query::TQueryClause* eq_node = 
  476.           CBDB_Query::NewOperatorNode(CBDB_QueryNode::eEQ, "2", "2");
  477.     query.SetQueryClause(eq_node);
  478.     bres = scanner.StaticEvaluate(query);
  479.     assert(bres);
  480.     }}
  481.     {{    
  482.     const char* ch = "2 = 2";
  483.     BDB_ParseQuery(ch, &query);
  484.     bres = scanner.StaticEvaluate(query);
  485.     assert(bres);
  486.     }}
  487.     // ("1" == "1" AND "2" == "2") => true
  488.     {{
  489.     CBDB_Query::TQueryClause* eq_node1 = 
  490.           CBDB_Query::NewOperatorNode(CBDB_QueryNode::eEQ, "2", "2");
  491.     CBDB_Query::TQueryClause* eq_node2 = 
  492.           CBDB_Query::NewOperatorNode(CBDB_QueryNode::eEQ, "1", "1");
  493.     CBDB_Query::TQueryClause* and_node =
  494.         new CBDB_Query::TQueryClause(CBDB_QueryNode::eAnd);
  495.     and_node->AddNode(eq_node1);
  496.     and_node->AddNode(eq_node2);
  497.     query.SetQueryClause(and_node);
  498.     bres = scanner.StaticEvaluate(query);
  499.     assert(bres);
  500.     }}
  501.     {{    
  502.     const char* ch = "(1=1 AND 2=2)";
  503.     BDB_ParseQuery(ch, &query);
  504.     bres = scanner.StaticEvaluate(query);
  505.     assert(bres);
  506.     }}
  507.     // ("1" == "1" AND "2" == "0") => false
  508.     {{
  509.     CBDB_Query::TQueryClause* eq_node1 = 
  510.           CBDB_Query::NewOperatorNode(CBDB_QueryNode::eEQ, "2", "0");
  511.     CBDB_Query::TQueryClause* eq_node2 = 
  512.           CBDB_Query::NewOperatorNode(CBDB_QueryNode::eEQ, "1", "1");
  513.     CBDB_Query::TQueryClause* and_node =
  514.         new CBDB_Query::TQueryClause(CBDB_QueryNode::eAnd);
  515.     and_node->AddNode(eq_node1);
  516.     and_node->AddNode(eq_node2);
  517.     query.SetQueryClause(and_node);
  518.     bres = scanner.StaticEvaluate(query);
  519.     assert(!bres);
  520.     BDB_PrintQueryTree(cout, query);
  521.     }}
  522.     {{
  523.     const char* ch = "('1'='1' AND '2'='0')";
  524.     BDB_ParseQuery(ch, &query);
  525.     bres = scanner.StaticEvaluate(query);
  526.     assert(!bres);
  527.     }}
  528.     // ("1" == "1" OR "2" == "0") => true
  529.     {{
  530.     CBDB_Query::TQueryClause* eq_node1 = 
  531.           CBDB_Query::NewOperatorNode(CBDB_QueryNode::eEQ, "2", "0");
  532.     CBDB_Query::TQueryClause* eq_node2 = 
  533.           CBDB_Query::NewOperatorNode(CBDB_QueryNode::eEQ, "1", "1");
  534.     CBDB_Query::TQueryClause* and_node =
  535.         new CBDB_Query::TQueryClause(CBDB_QueryNode::eOr);
  536.     and_node->AddNode(eq_node1);
  537.     and_node->AddNode(eq_node2);
  538.     query.SetQueryClause(and_node);
  539.     bres = scanner.StaticEvaluate(query);
  540.     assert(bres);
  541.     }}
  542.     {{
  543.     const char* ch = "('1'='1' OR '2'='0')";
  544.     BDB_ParseQuery(ch, &query);
  545.     bres = scanner.StaticEvaluate(query);
  546.     assert(bres);
  547.     }}
  548.     
  549.     // Testing the query evaluation involving data fields
  550.     //
  551.     // (id = 1) =>true
  552.     {{
  553.     CBDB_Query::TQueryClause* eq_node = 
  554.           CBDB_Query::NewOperatorNode(CBDB_QueryNode::eEQ, "id", "1");
  555.     query.SetQueryClause(eq_node);
  556.     bres = scanner.StaticEvaluate(query);
  557.     assert(bres);
  558.     }}
  559.     {{
  560.     const char* ch = "id = '1'";
  561.     BDB_ParseQuery(ch, &query);
  562.     bres = scanner.StaticEvaluate(query);
  563.     assert(bres);
  564.     }}
  565.     // ("id" == "1" AND "idata" == "401") => true
  566.     {{
  567.     CBDB_Query::TQueryClause* eq_node1 = 
  568.           CBDB_Query::NewOperatorNode(CBDB_QueryNode::eEQ, "id", "1");
  569.     CBDB_Query::TQueryClause* eq_node2 = 
  570.           CBDB_Query::NewOperatorNode(CBDB_QueryNode::eEQ, "idata", "401");
  571.     CBDB_Query::TQueryClause* and_node =
  572.         new CBDB_Query::TQueryClause(CBDB_QueryNode::eAnd);
  573.     and_node->AddNode(eq_node1);
  574.     and_node->AddNode(eq_node2);
  575.     query.SetQueryClause(and_node);
  576.     bres = scanner.StaticEvaluate(query);
  577.     assert(bres);
  578.     BDB_PrintQueryTree(cout, query);
  579.     }}
  580.     {{
  581.     const char* ch = "id = '1' AND idata = '401'";
  582.     BDB_ParseQuery(ch, &query);
  583.     bres = scanner.StaticEvaluate(query);
  584.     assert(bres);
  585.     }}
  586.     {{
  587.     const char* ch = "test";
  588.     BDB_ParseQuery(ch, &query);
  589.     bres = scanner.StaticEvaluate(query);
  590.     assert(bres);
  591.     }}
  592.     {{
  593.     const char* ch = "yyy";
  594.     BDB_ParseQuery(ch, &query);
  595.     bres = scanner.StaticEvaluate(query);
  596.     assert(!bres);
  597.     }}
  598.     {{
  599.     const char* ch = "id = '1' AND test";
  600.     BDB_ParseQuery(ch, &query);
  601.     bres = scanner.StaticEvaluate(query);
  602.     assert(bres);
  603.     }}
  604.     {{
  605.     const char* ch = "NOT test AND test";
  606.     BDB_ParseQuery(ch, &query);
  607.     bres = scanner.StaticEvaluate(query);
  608.     BDB_PrintQueryTree(cout, query);
  609.     assert(!bres);
  610.     }}
  611.     cout << "======== Query test ok." << endl;
  612. }
  613. static void s_TEST_BDB_IdTable_Fill2(void)
  614. {
  615.     cout << "======== Id table filling test 2." << endl;
  616.     CBDB_Env env;
  617.     env.OpenWithLocks(0);
  618.     TestDBF1L  dbf1;
  619.     dbf1.SetEnv(env);
  620.     dbf1.SetPageSize(32 * 1024);
  621.     dbf1.SetCacheSize(5 * (1024 * 1024));
  622.     dbf1.Open(s_TestFileName, CBDB_File::eCreate);
  623.     assert(dbf1.idata.IsNull());
  624.     // Fill the table
  625.     unsigned i;
  626.     
  627.     for (i = 1; i < s_RecsInTable; ++i) {
  628.         char buf[256];
  629.         sprintf(buf, s_TestStrTempl, i);
  630.         dbf1.IdKey = i;
  631.         dbf1.idata = 400+i;
  632.         dbf1.str = buf;
  633.         dbf1.i2.Set(i+3);
  634.         int i2 = dbf1.i2;
  635.         assert (i2 == (int)(i+3));
  636.         assert(!dbf1.idata.IsNull());
  637.         EBDB_ErrCode err = dbf1.Insert();
  638.         assert(err == eBDB_Ok);
  639.         assert(dbf1.idata.IsNull());
  640.     }
  641.     // Trying to put duplicate record
  642.     dbf1.IdKey = 1;
  643.     dbf1.idata = 400 + 1;
  644.     dbf1.str = "test";
  645.     EBDB_ErrCode err = dbf1.Insert();
  646.     assert(err == eBDB_KeyDup);
  647.     cout << "Table " << s_TestFileName 
  648.          << " loaded ok. Checking consistency." 
  649.          << endl;
  650.     // Read the table check if all records are in place
  651.     dbf1.Reopen(CBDB_File::eReadOnly);
  652.     for (i = 1; i < s_RecsInTable; ++i) {
  653.         dbf1.IdKey = i;
  654.         EBDB_ErrCode ret = dbf1.Fetch();
  655.         assert (ret == eBDB_Ok);
  656.         ValidateRecord(dbf1, i);
  657.     } // for
  658.     {{
  659.     TestDBF1  dbf11;
  660.     dbf11.Attach(dbf1);
  661.     for (i = 1; i < s_RecsInTable; ++i) {
  662.         dbf11.IdKey = i;
  663.         EBDB_ErrCode ret = dbf11.Fetch();
  664.         assert (ret == eBDB_Ok);
  665.         ValidateRecord(dbf11, i);
  666.         // Checking that attached buffer doesn't change status of the main one
  667.         dbf1.IdKey = 1;
  668.         ret = dbf1.Fetch();
  669.         assert (ret == eBDB_Ok);
  670.         ValidateRecord(dbf1, 1);
  671.         ValidateRecord(dbf11, i);
  672.     } // for
  673.     }}
  674.     {{
  675.     TestDBF1L  dbf11;
  676.     dbf11.Open(s_TestFileName, CBDB_File::eReadWrite);
  677.     for (i = 1; i < s_RecsInTable; ++i) {
  678.         dbf11.IdKey = i;
  679.         EBDB_ErrCode ret = dbf11.Fetch();
  680.         assert (ret == eBDB_Ok);
  681.         ValidateRecord(dbf11, i);
  682.     } // for
  683.     // Dumping the database to screen
  684.     CBDB_FileDumper dump;
  685.     dump.Dump(cout, dbf11);
  686.     }}
  687.     cout << "======== Id table filling test 2 ok." << endl;
  688. }
  689. //////////////////////////////////////////////////////////////////
  690. //
  691. // 
  692. // DBD Id table cursor test
  693. //
  694. //
  695. static void s_TEST_BDB_IdTable_Cursor(void)
  696. {
  697.     cout << "======== Id table cursor test." << endl;
  698.     TestDBF1  dbf1;
  699.     dbf1.Open(s_TestFileName, CBDB_File::eReadOnly);
  700.     // Search point test
  701.     unsigned search_id = s_RecsInTable / 2;
  702.     if (search_id == 0) {
  703.         cout << "Too few records to test cursor operation." << endl;
  704.         assert(0);
  705.     }
  706.     // -----------------------------------
  707.     {{
  708.     cout << "Testing Eq cursor" << endl;
  709.     CBDB_FileCursor cur1(dbf1);
  710.     cur1.SetCondition(CBDB_FileCursor::eEQ);
  711.     cur1.From << search_id;
  712.     
  713.     unsigned recs_fetched = 0;
  714.     while (cur1.Fetch() == eBDB_Ok) {
  715.         unsigned fetched_id = dbf1.IdKey;
  716.         assert(search_id == fetched_id);
  717.         ValidateRecord(dbf1, fetched_id);
  718.         ++recs_fetched;
  719.     }
  720.     assert(recs_fetched == 1);
  721.     }}
  722.     // -----------------------------------
  723.     {{
  724.     cout << "Testing reusable Eq cursor" << endl;
  725.     search_id = s_RecsInTable / 2;
  726.     CBDB_FileCursor cur1(dbf1);
  727.     cur1.SetCondition(CBDB_FileCursor::eEQ);
  728.     for ( ;search_id > 0; --search_id) {
  729.         cur1.From << search_id;
  730.     
  731.         unsigned recs_fetched = 0;
  732.         while (cur1.Fetch() == eBDB_Ok) {
  733.             unsigned fetched_id = dbf1.IdKey;
  734.             assert(search_id == fetched_id);
  735.             ValidateRecord(dbf1, fetched_id);
  736.             ++recs_fetched;
  737.         }
  738.         assert(recs_fetched == 1);
  739.     } // for
  740.     }}
  741.     // -----------------------------------
  742.     {{
  743.     cout << "Testing forward GE - LE cursor" << endl;
  744.     search_id = s_RecsInTable / 2;
  745.     CBDB_FileCursor cur1(dbf1);
  746.     cur1.SetCondition(CBDB_FileCursor::eGE, CBDB_FileCursor::eLE);
  747.     cur1.From << search_id;
  748.     cur1.To   << s_RecsInTable - 1;
  749.     unsigned recs_fetched = 0;
  750.     for (unsigned i = search_id; cur1.Fetch() == eBDB_Ok; ++i) {
  751.         unsigned fetched_id = dbf1.IdKey;
  752.         assert(i == fetched_id);
  753.         ValidateRecord(dbf1, fetched_id);
  754.         ++recs_fetched;
  755.     }
  756.     assert(recs_fetched == (s_RecsInTable) - search_id);
  757.     }}
  758.     // -----------------------------------
  759.     {{
  760.     cout << "Testing forward GE - LT cursor" << endl;
  761.     search_id = s_RecsInTable / 2;
  762.     CBDB_FileCursor cur1(dbf1);
  763.     cur1.SetCondition(CBDB_FileCursor::eGE, CBDB_FileCursor::eLT);
  764.     cur1.From << search_id;
  765.     cur1.To   << s_RecsInTable - 1;
  766.     unsigned recs_fetched = 0;
  767.     for (unsigned i = search_id; cur1.Fetch() == eBDB_Ok; ++i) {
  768.         unsigned fetched_id = dbf1.IdKey;
  769.         assert(i == fetched_id);
  770.         ValidateRecord(dbf1, fetched_id);
  771.         ++recs_fetched;
  772.     }
  773.     assert(recs_fetched == (s_RecsInTable-1) - search_id);
  774.     }}
  775.     // -----------------------------------
  776.     {{
  777.     cout << "Testing forward GT - LT cursor" << endl;
  778.     search_id = s_RecsInTable / 2;
  779.     CBDB_FileCursor cur1(dbf1);
  780.     cur1.SetCondition(CBDB_FileCursor::eGT, CBDB_FileCursor::eLT);
  781.     cur1.From << search_id;
  782.     cur1.To   << s_RecsInTable - 1;
  783.     unsigned recs_fetched = 0;
  784.     for (unsigned i = search_id+1; cur1.Fetch() == eBDB_Ok; ++i) {
  785.         unsigned fetched_id = dbf1.IdKey;
  786.         assert(i == fetched_id);
  787.         ValidateRecord(dbf1, fetched_id);
  788.         ++recs_fetched;
  789.     }
  790.     assert(recs_fetched == (s_RecsInTable-2) - search_id);
  791.     }}
  792.     // -----------------------------------
  793.     {{
  794.     cout << "Testing backward LE - GE cursor" << endl;
  795.     search_id = s_RecsInTable / 2;
  796.     CBDB_FileCursor cur1(dbf1);
  797.     cur1.SetCondition(CBDB_FileCursor::eLE, CBDB_FileCursor::eGE);
  798.     cur1.From << search_id;
  799.     cur1.To   << 1;
  800.     unsigned recs_fetched = 0;
  801.     for (unsigned i = search_id; cur1.Fetch() == eBDB_Ok; --i) {
  802.         unsigned fetched_id = dbf1.IdKey;
  803.         assert(i == fetched_id);
  804.         ValidateRecord(dbf1, fetched_id);
  805.         ++recs_fetched;
  806.     }
  807.     assert(recs_fetched == search_id);
  808.     }}
  809.     // -----------------------------------
  810.     {{
  811.     cout << "Testing backward LE - GT cursor" << endl;
  812.     search_id = s_RecsInTable / 2;
  813.     CBDB_FileCursor cur1(dbf1);
  814.     cur1.SetCondition(CBDB_FileCursor::eLE, CBDB_FileCursor::eGT);
  815.     cur1.From << search_id;
  816.     cur1.To   << 1;
  817.     unsigned recs_fetched = 0;
  818.     for (unsigned i = search_id; cur1.Fetch() == eBDB_Ok; --i) {
  819.         unsigned fetched_id = dbf1.IdKey;
  820.         assert(i == fetched_id);
  821.         ValidateRecord(dbf1, fetched_id);
  822.         ++recs_fetched;
  823.     }
  824.     assert(recs_fetched == search_id - 1);
  825.     }}
  826.     // -----------------------------------
  827.     {{
  828.     cout << "Testing backward LT - GT cursor" << endl;
  829.     search_id = s_RecsInTable / 2;
  830.     CBDB_FileCursor cur1(dbf1);
  831.     cur1.SetCondition(CBDB_FileCursor::eLT, CBDB_FileCursor::eGT);
  832.     cur1.From << search_id;
  833.     cur1.To   << 1;
  834.     unsigned recs_fetched = 0;
  835.     for (unsigned i = search_id-1; cur1.Fetch() == eBDB_Ok; --i) {
  836.         unsigned fetched_id = dbf1.IdKey;
  837.         assert(i == fetched_id);
  838.         ValidateRecord(dbf1, fetched_id);
  839.         ++recs_fetched;
  840.     }
  841.     assert(recs_fetched == search_id - 2);
  842.     }}
  843.     // -----------------------------------
  844.     // TO DO: Test illegitimate cases, suppoed to return empty set
  845.     dbf1.Close();
  846.     cout << "======== Id table cursor test ok." << endl;    
  847. }
  848. //////////////////////////////////////////////////////////////////
  849. //
  850. // 
  851. // LOB test
  852. //
  853. //
  854. static void s_TEST_BDB_LOB_File(void)
  855. {
  856.     cout << "======== LOB file test." << endl;    
  857.     CBDB_LobFile lob;
  858.     lob.Open("lobtest.db", "lob", CBDB_LobFile::eCreate);
  859.     const char* test_data = "This is a LOB test data";
  860.     unsigned lob_len = ::strlen(test_data)+1;
  861.     EBDB_ErrCode ret = lob.Insert(1, test_data, lob_len);
  862.     assert(ret == eBDB_Ok);
  863.     cout << "Testing two-phase read." << endl;
  864.     lob.Reopen(CBDB_LobFile::eReadOnly);
  865.     
  866.     ret = lob.Fetch(1);
  867.     assert(ret == eBDB_Ok);
  868.     unsigned len1 = lob.LobSize();
  869.     assert(len1 == lob_len);
  870.     char buf[256] = {0,};
  871.     ret = lob.GetData(buf, sizeof(buf));
  872.     assert(ret == eBDB_Ok);
  873.     if (strcmp(buf, test_data) != 0) {
  874.         cout << "LOB content comparison error!" << endl;
  875.         cout << "LobData:" << buf << endl;
  876.         assert(0);
  877.     }
  878.     buf[0] = 0;
  879.     // Reallocate read cannot be used in some cases.
  880.     // Under Windows if BerkeleyDB libdb*.lib has been build with runtime 
  881.     // different from application runtime reallocate will crash the application
  882.     // In this test case test_bdb is build with "Multithreaded Debug DLL" runtime
  883.     // and Berkeley DB with uses "Mutithereaded DLL". Reallocation is not possible
  884.     // in this configuration.
  885. #ifndef _DEBUG
  886.     cout << "Testing reallocate read." << endl;
  887.     unsigned buf_size = 5;         // insufficient memory to get the BLOB
  888.     void* buf2=::malloc(buf_size); 
  889.     // Here we create a check buf if reallocate fails for some reasons
  890.     // chances are it will result in checkblock signature failure
  891.     unsigned check_buf_size = 2000;
  892.     unsigned* check_buf = new unsigned[check_buf_size];
  893.     unsigned i;
  894.     for (i = 0; i < buf_size; ++i) {
  895.         check_buf[i] = i;
  896.     }
  897.     
  898.     ret = lob.Fetch(1, &buf2, 5, CBDB_LobFile::eReallocAllowed);
  899.     assert(ret == eBDB_Ok);
  900.     unsigned new_buf_size = lob.LobSize();
  901.     assert(buf_size < new_buf_size);
  902.     if (strcmp((char*)buf2, test_data) != 0) {
  903.         cout << "LOB content comparison error!" << endl;
  904.         cout << "LobData:" << buf2 << endl;
  905.         assert(0);
  906.     }
  907.     
  908.     ::free(buf2);   // should not crash here
  909.     // Check the signature
  910.     for (i = 0; i < buf_size; ++i) {
  911.         assert(check_buf[i] == i);
  912.     }
  913. #endif
  914.     cout << "======== LOB file test ok." << endl;
  915. }
  916. //////////////////////////////////////////////////////////////////
  917. //
  918. // 
  919. // LOB test
  920. //
  921. //
  922. struct BLobTestDBF1 : public CBDB_BLobFile
  923. {
  924.     CBDB_FieldInt4        i1;
  925.     CBDB_FieldInt4        i2;
  926.     BLobTestDBF1()
  927.     {
  928.         BindKey("i1", &i1);
  929.         BindKey("i2", &i2);
  930.     }
  931. };
  932. static void s_TEST_BDB_BLOB_File(void)
  933. {
  934.     cout << "======== BLob file test." << endl;    
  935.     BLobTestDBF1 blob;
  936.     blob.Open("blobtest.db", "blob", CBDB_LobFile::eCreate);
  937.     const char* test_data = "This is a BLOB test data";
  938.     unsigned lob_len = ::strlen(test_data)+1;
  939.     blob.i1 = 1;
  940.     blob.i2 = 2;
  941.     EBDB_ErrCode ret = blob.Insert(test_data, lob_len);
  942.     assert(ret == eBDB_Ok);
  943.     blob.i1 = 1;
  944.     blob.i2 = 3;
  945.     const char* test_data2 
  946.         = "This is a BLOB test data.TEst test test test....BDB. test.";
  947.     lob_len = ::strlen(test_data2)+1;
  948.     ret = blob.Insert(test_data2, lob_len);
  949.     assert(ret == eBDB_Ok);
  950.     {{
  951.     blob.i1 = 1;
  952.     blob.i2 = 4;
  953.     CBDB_BLobStream* bstream = blob.CreateStream();
  954.     unsigned len = strlen(test_data);
  955.     for (unsigned i = 0; i < len+1; ++i) {
  956.         char ch = test_data[i];
  957.         bstream->Write(&ch, 1);
  958.     }
  959.     delete bstream;
  960.     blob.i1 = 1;
  961.     blob.i2 = 4;
  962.     ret = blob.Fetch();
  963.     assert(ret == eBDB_Ok);
  964.     unsigned len1 = blob.LobSize();
  965.     assert(len1 == strlen(test_data)+1);
  966.     char buf[256] = {0,};
  967.     ret = blob.GetData(buf, sizeof(buf));
  968.     assert(ret == eBDB_Ok);
  969.     if (strcmp(buf, test_data) != 0) {
  970.         cout << "BLOB content comparison error!" << endl;
  971.         cout << "BLobData:" << buf << endl;
  972.         assert(0);
  973.     }
  974.     }}
  975.     cout << "Testing two-phase read." << endl;
  976.     blob.Reopen(CBDB_LobFile::eReadOnly);
  977.     
  978.     blob.i1 = 1;
  979.     blob.i2 = 2;
  980.     ret = blob.Fetch();
  981.     assert(ret == eBDB_Ok);
  982.     unsigned len1 = blob.LobSize();
  983.     assert(len1 == strlen(test_data)+1);
  984.     char buf[256] = {0,};
  985.     ret = blob.GetData(buf, sizeof(buf));
  986.     assert(ret == eBDB_Ok);
  987.     if (strcmp(buf, test_data) != 0) {
  988.         cout << "BLOB content comparison error!" << endl;
  989.         cout << "BLobData:" << buf << endl;
  990.         assert(0);
  991.     }
  992.     buf[0] = 0;
  993.     cout << "Testing BLOB based cursor" << endl;
  994.     CBDB_FileCursor cur(blob);
  995.     cur.SetCondition(CBDB_FileCursor::eEQ);
  996.     cur.From << 1;
  997.     const char* tdata = test_data;
  998.     while (cur.Fetch() == eBDB_Ok) {
  999.     
  1000.         assert(blob.i2 == 2 || blob.i2 == 3 || blob.i2 == 4);
  1001.         unsigned len = blob.LobSize();
  1002.         ret = blob.GetData(buf, sizeof(buf));
  1003.         assert(ret == eBDB_Ok);
  1004.         if (strcmp(buf, tdata) != 0) {
  1005.             int i2 = blob.i2;
  1006.             if (i2 == 4) {
  1007.                 assert(strcmp(buf, test_data) ==0);
  1008.             }
  1009.             else {
  1010.                 cout << "BLOB content comparison error!" << endl;
  1011.                 cout << "BLobData:" << buf << endl;
  1012.                 assert(0);
  1013.             }
  1014.         }
  1015.         cout << "Lob len=" << len << endl;
  1016.         tdata = test_data2;
  1017.     }
  1018.     cout << "Testing read stream" << endl;
  1019.     blob.i1 = 1;
  1020.     blob.i2 = 2;
  1021.     CBDB_BLobStream* bstream = blob.CreateStream();
  1022.     char ch;
  1023.     size_t bytes_read = 0;
  1024.     size_t pending = bstream->PendingCount();
  1025.     
  1026.     for(int i=0;;++i) {
  1027.         bstream->Read(&ch, 1, &bytes_read);
  1028.         if (bytes_read == 0)
  1029.             break;
  1030.         assert(ch == test_data[i]);
  1031.         size_t pend = bstream->PendingCount();
  1032.         assert(pend == pending - 1);
  1033.         pending = pend;
  1034.     }
  1035.     delete bstream;
  1036.     cout << "======== BLob file test ok." << endl;
  1037. }
  1038. //////////////////////////////////////////////////////////////////
  1039. //
  1040. // 
  1041. // Id table record delete test
  1042. //
  1043. //
  1044. static void s_TEST_BDB_IdTable_DeleteInsert(void)
  1045. {
  1046.     cout << "======== BDB Id Table Delete/Insert test." << endl;
  1047.     TestDBF1  dbf1;
  1048.     dbf1.Open(s_TestFileName, CBDB_File::eReadWrite);
  1049.     
  1050.     
  1051.     unsigned int search_id = s_RecsInTable / 2;
  1052.     dbf1.IdKey = search_id;
  1053.     
  1054.     EBDB_ErrCode err = dbf1.Delete();
  1055.     assert(err == eBDB_Ok);
  1056.     dbf1.IdKey = search_id;
  1057.     err = dbf1.Fetch();
  1058.     assert(err == eBDB_NotFound);
  1059.     dbf1.IdKey = search_id;
  1060.     dbf1.idata = 800;
  1061.     dbf1.str = "123456789";
  1062.     dbf1.i2.Set(300);
  1063.     dbf1.Insert();
  1064.     dbf1.IdKey = search_id;
  1065.     err = dbf1.Fetch();
  1066.     assert(err == eBDB_Ok);
  1067.     // Test UpdateInsert
  1068.     dbf1.Reopen(CBDB_File::eReadWrite);
  1069.     dbf1.IdKey = 2;
  1070.     dbf1.idata = 250;
  1071.     dbf1.str = "test";
  1072.     err = dbf1.UpdateInsert();
  1073.     assert(err == eBDB_Ok);
  1074.     dbf1.IdKey = 2;
  1075.     dbf1.idata = 0;
  1076.     err = dbf1.Fetch();
  1077.     assert(err == eBDB_Ok);
  1078.     int idata = dbf1.idata;
  1079.     assert(idata == 250);
  1080.     dbf1.Close();
  1081.     cout << "======== BDB Id Table Delete/Insert test ok." << endl;
  1082. }
  1083. //////////////////////////////////////////////////////////////////
  1084. //
  1085. // 
  1086. // BDB string key table fill test
  1087. //
  1088. //
  1089. static void s_TEST_BDB_StrTable_Fill(void)
  1090. {
  1091.     cout << "======== StrKey table filling test." << endl;
  1092.     TestDBF2  dbf;
  1093.     dbf.Open(s_TestFileName2, CBDB_File::eCreate);
  1094.     // Fill the table
  1095.     unsigned i;
  1096.     for (i = 1; i < s_RecsInTable; ++i) {
  1097.         char buf[256];
  1098.         sprintf(buf, s_StrKeyTempl, i, i);
  1099.         dbf.str_key = buf;
  1100.         dbf.idata = 400+i;
  1101.         sprintf(buf, s_TestStrTempl, i);
  1102.         dbf.str = buf;
  1103.         dbf.i2.Set(i+3);
  1104.         int i2 = dbf.i2;
  1105.         assert (i2 == (int)(i+3));
  1106.         EBDB_ErrCode err = dbf.Insert();
  1107.         assert(err == eBDB_Ok);
  1108.     }
  1109.     cout << "Table " << s_TestFileName2 
  1110.          << " loaded ok. Checking consistency." 
  1111.          << endl;
  1112.     // Read the table check if all records are in place
  1113.     dbf.Reopen(CBDB_File::eReadOnly);
  1114.     for (i = 1; i < s_RecsInTable; ++i) {
  1115.         char buf[256];
  1116.         sprintf(buf, s_StrKeyTempl, i, i);
  1117.         dbf.str_key = buf;
  1118.         EBDB_ErrCode err = dbf.Fetch();
  1119.         assert (err == eBDB_Ok);
  1120.         ValidateRecord(dbf, i);
  1121.     } // for
  1122.     cout << "======== StrKey table filling test ok." << endl;
  1123. }
  1124. //////////////////////////////////////////////////////////////////
  1125. //
  1126. // 
  1127. // Database record structure to test with duplicate records
  1128. //
  1129. //
  1130. struct TestDuplicateKeys : public CBDB_File
  1131. {
  1132.     CBDB_FieldInt4        idata;
  1133.     CBDB_FieldString      str;
  1134.     TestDuplicateKeys() 
  1135.     : CBDB_File(CBDB_File::eDuplicatesEnable)
  1136.     {
  1137.         BindKey("idata", &idata);
  1138.         BindData("str", &str, 256);
  1139.     }
  1140. };
  1141. //////////////////////////////////////////////////////////////////
  1142. //
  1143. // 
  1144. // BDB string key table fill test
  1145. //
  1146. //
  1147. static void s_TEST_BDB_Duplicates(void)
  1148. {
  1149.     cout << "======== Duplicate keys test." << endl;
  1150.     TestDuplicateKeys  dbf;
  1151.     dbf.Open(s_TestFileName3, CBDB_File::eCreate);
  1152.     // Fill the table
  1153.     dbf.idata = 1;
  1154.     dbf.str = "Str1";
  1155.     EBDB_ErrCode ret = dbf.Insert();
  1156.     assert (ret == eBDB_Ok);
  1157.     
  1158.     dbf.idata = 1;
  1159.     dbf.str = "Str11";
  1160.     ret = dbf.Insert();
  1161.     assert (ret == eBDB_Ok);
  1162.     dbf.idata = 10;
  1163.     dbf.str = "Str100";
  1164.     ret = dbf.Insert();
  1165.     assert (ret == eBDB_Ok);
  1166.     {{
  1167.         CBDB_FileCursor cur(dbf);
  1168.         cur.SetCondition(CBDB_FileCursor::eEQ);
  1169.         cur.From << 1;
  1170.         unsigned int recs_fetched = 0;
  1171.         while (cur.Fetch() == eBDB_Ok) {
  1172.             unsigned idata = dbf.idata;
  1173.             assert(idata == 1);
  1174.             string str = (const char*)dbf.str;
  1175.             assert(str == "Str1" || str == "Str11");
  1176.             ++recs_fetched;
  1177.         }
  1178.         assert(recs_fetched == 2);
  1179.     }}
  1180.     dbf.idata = 1;
  1181.     ret = dbf.Delete();
  1182.     assert (ret == eBDB_Ok);
  1183.     {{
  1184.         CBDB_FileCursor cur(dbf);
  1185.         cur.SetCondition(CBDB_FileCursor::eEQ);
  1186.         cur.From << 1;
  1187.         unsigned int recs_fetched = 0;
  1188.         while (cur.Fetch() == eBDB_Ok) {
  1189.             assert(0);
  1190.             ++recs_fetched;
  1191.         }
  1192.         assert(recs_fetched == 0);
  1193.     }}
  1194.     cout << "======== Duplicate keys test ok." << endl;
  1195. }
  1196. //////////////////////////////////////////////////////////////////
  1197. //
  1198. // 
  1199. // db_map test
  1200. //
  1201. //
  1202. bool CheckMapDataValid_i2s(int first, const string& second)
  1203. {
  1204.     char szBuf[256];
  1205.     sprintf(szBuf, "Data%i", first);
  1206.     return second == string(szBuf);
  1207. }
  1208. static void s_TEST_db_map(void)
  1209. {
  1210.     cout << "======== db_map test." << endl;
  1211.     db_map<int, string>  i2s;
  1212.     i2s.open(s_db_map1, ios_base::out|ios_base::trunc);
  1213.     i2s.insert(pair<const int, string>(1, "Data1"));
  1214.     i2s.insert(pair<const int, string>(2, "Data2"));
  1215.     i2s.insert(pair<const int, string>(3, "Data3"));
  1216.     string v = i2s[2];
  1217.     assert(v == "Data2");
  1218.     {{
  1219.     db_map<int, string>::const_iterator it(i2s.begin());
  1220.     while (it.valid()) {
  1221.         bool b = CheckMapDataValid_i2s((*it).first, (*it).second);
  1222.         assert(b);
  1223.         ++it;
  1224.     }
  1225.     }}
  1226.     {{
  1227.     db_map<int, string>::const_iterator it(i2s.begin());
  1228.     db_map<int, string>::const_iterator it_end(i2s.end());
  1229.     for (;it != it_end; ++it) {
  1230.         bool b = CheckMapDataValid_i2s(it->first, it->second);
  1231.         assert(b);
  1232.     }
  1233.     }}
  1234.     i2s.clear();
  1235.     size_t sz = i2s.size();
  1236.     assert(sz == 0);
  1237.     // testing string -> int case
  1238.     db_map<string, int>  s2i;
  1239.     s2i.open("s2i.db", ios_base::out|ios_base::trunc);
  1240.     s2i.insert(pair<const string, int>("Data1", 1));
  1241.     s2i.insert(pair<const string, int>("Data2", 2));
  1242.     s2i.insert(pair<const string, int>("Data3", 3));
  1243.     int i = s2i[string("Data2")];
  1244.     assert(i == 2);
  1245.     cout << "======== db_map test ok." << endl;
  1246. }
  1247. static void s_TEST_db_multimap(void)
  1248. {
  1249.     cout << "======== db_multimap test." << endl;
  1250.     db_multimap<int, string>  ii2s;
  1251.     ii2s.open(s_db_map2, ios_base::out|ios_base::trunc);
  1252.     ii2s.insert(pair<const int, string>(1, "Data1"));
  1253.     ii2s.insert(pair<const int, string>(2, "Data2"));
  1254.     ii2s.insert(pair<const int, string>(3, "Data3"));
  1255.     ii2s.insert(pair<const int, string>(3, "Data31"));
  1256.     size_t sz = ii2s.size();
  1257.     assert(sz == 4);
  1258.     sz = 0;
  1259.     {{
  1260.     db_multimap<int, string>::const_iterator it(ii2s.find(3));
  1261.     while (it.valid()) {
  1262.         const string& data = it->second;
  1263.         if (sz == 0) {
  1264.             assert(data == "Data3");
  1265.         } else {
  1266.             assert(data == "Data31");
  1267.         }
  1268.         ++sz;
  1269.         ++it;
  1270.     }
  1271.     }}
  1272.     assert(sz == 2);
  1273.     ii2s.erase(3);
  1274.     sz = ii2s.size();
  1275.     assert(sz == 2);
  1276.     cout << "======== db_multimap test ok." << endl;
  1277. }
  1278. static void s_TEST_ICache(void)
  1279. {
  1280.     cout << "======== ICache test." << endl;
  1281.     vector<int> data;
  1282.     data.push_back(10);
  1283.     data.push_back(20);
  1284.     data.push_back(30);
  1285.     data.push_back(40);
  1286.     const void* dp = &data[0];
  1287.     CBDB_Cache  bdb_cache;
  1288.     int top = bdb_cache.GetTimeStampPolicy();
  1289.     bdb_cache.SetTimeStampPolicy(top, 30);
  1290.     bdb_cache.Open(".", "bcache", CBDB_Cache::eNoLock, 1024*1024 * 100);
  1291.     bdb_cache.Store("test_key1", 1, "", dp, data.size() * sizeof(int));
  1292.     vector<int> data2;
  1293.     size_t sz = bdb_cache.GetSize("test_key1", 1, "");
  1294.     assert(sz);
  1295.     sz = sz / sizeof(int);
  1296.     assert(sz == data.size());
  1297.     data2.resize(sz);
  1298.     void* dp2 = &data2[0];
  1299.     bool res = bdb_cache.Read("test_key1", 1, "", dp2, sz * sizeof(int));
  1300.     assert(data2[0] == data[0]);
  1301.     assert(data2[1] == data[1]);
  1302.     assert(data2[2] == data[2]);
  1303.     assert(data2[3] == data[3]);
  1304. }
  1305. ////////////////////////////////
  1306. // Test application
  1307. //
  1308. class CBDB_Test : public CNcbiApplication
  1309. {
  1310. public:
  1311.     void Init(void);
  1312.     int Run(void);
  1313. };
  1314. void CBDB_Test::Init(void)
  1315. {
  1316.     SetDiagPostLevel(eDiag_Warning);
  1317.     SetDiagPostFlag(eDPF_File);
  1318.     SetDiagPostFlag(eDPF_Line);
  1319.     auto_ptr<CArgDescriptions> d(new CArgDescriptions);
  1320.     d->SetUsageContext("test_bdb",
  1321.                        "test BDB library");
  1322.     SetupArgDescriptions(d.release());
  1323. }
  1324. int CBDB_Test::Run(void)
  1325. {
  1326.     cout << "Run BDB test" << endl << endl;
  1327.     try
  1328.     {
  1329.         s_TEST_BDB_Types();
  1330.         s_TEST_BDB_IdTable_Fill();
  1331.         // s_TEST_BDB_IdTable_Fill2();
  1332.         s_TEST_BDB_IdTable_Cursor();
  1333.         s_TEST_BDB_IdTable_DeleteInsert();
  1334.         s_TEST_BDB_LOB_File();
  1335.         s_TEST_BDB_BLOB_File();
  1336.         s_TEST_BDB_StrTable_Fill();
  1337.         s_TEST_BDB_Duplicates();
  1338.         s_TEST_BDB_Transaction();
  1339.         s_TEST_db_map();
  1340.         s_TEST_db_multimap();
  1341.         s_TEST_ICache();
  1342.         s_TEST_BDB_Query();
  1343.         s_TEST_BDB_IdTable_FillStress();
  1344.     }
  1345.     catch (CBDB_ErrnoException& ex)
  1346.     {
  1347.         cout << "Error! DBD errno exception:" << ex.what();
  1348.         return 1;
  1349.     }
  1350.     catch (CBDB_LibException& ex)
  1351.     {
  1352.         cout << "Error! DBD library exception:" << ex.what();
  1353.         return 1;
  1354.     }
  1355.     cout << endl;
  1356.     cout << "TEST execution completed successfully!" << endl << endl;
  1357.     return 0;
  1358. }
  1359. ///////////////////////////////////
  1360. // APPLICATION OBJECT  and  MAIN
  1361. //
  1362. int main(int argc, const char* argv[])
  1363. {
  1364.     // Execute main application function
  1365.     return CBDB_Test().AppMain(argc, argv, 0, eDS_Default, 0);
  1366. }
  1367. /*
  1368.  * ===========================================================================
  1369.  * $Log: test_bdb.cpp,v $
  1370.  * Revision 1000.5  2004/06/01 18:37:53  gouriano
  1371.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.46
  1372.  *
  1373.  * Revision 1.46  2004/05/25 18:48:51  kuznets
  1374.  * Added cache RAM size parameter to CBDB_Cache::Open.
  1375.  *
  1376.  * Revision 1.45  2004/05/17 20:55:27  gorelenk
  1377.  * Added include of PCH ncbi_pch.hpp
  1378.  *
  1379.  * Revision 1.44  2004/04/28 12:18:27  kuznets
  1380.  * Remove obsolete IntCache test
  1381.  *
  1382.  * Revision 1.43  2004/03/23 16:37:55  kuznets
  1383.  * Implemented NOT predicate
  1384.  *
  1385.  * Revision 1.42  2004/03/23 14:51:19  kuznets
  1386.  * Implemented logical NOT, <, <=, >, >=
  1387.  *
  1388.  * Revision 1.41  2004/03/12 12:41:50  kuznets
  1389.  * + stress test for cursors
  1390.  *
  1391.  * Revision 1.40  2004/03/10 16:22:22  kuznets
  1392.  * + more tests
  1393.  *
  1394.  * Revision 1.39  2004/03/10 16:19:55  kuznets
  1395.  * + test case for single word queries
  1396.  *
  1397.  * Revision 1.38  2004/03/08 13:36:09  kuznets
  1398.  * One more test case for queries
  1399.  *
  1400.  * Revision 1.37  2004/03/01 14:07:11  kuznets
  1401.  * + test case for queries
  1402.  *
  1403.  * Revision 1.36  2004/02/04 19:16:50  kuznets
  1404.  * Fixed compilation bug (Workshop)
  1405.  *
  1406.  * Revision 1.35  2004/02/04 17:05:47  kuznets
  1407.  * Minor fix (compilation).
  1408.  *
  1409.  * Revision 1.34  2004/02/04 15:13:11  kuznets
  1410.  * + test case for length prefixed strings, when source std::string
  1411.  * contains zero chars.
  1412.  *
  1413.  * Revision 1.33  2003/12/23 22:32:24  ucko
  1414.  * Rename the second s_TEST_BDB_IdTable_Fill, but don't run it yet
  1415.  * because it crashes. :-/
  1416.  *
  1417.  * Revision 1.32  2003/12/22 18:58:02  kuznets
  1418.  * Added l-string test
  1419.  *
  1420.  * Revision 1.31  2003/12/12 19:13:31  kuznets
  1421.  * Transaction test: minor change file opening option.
  1422.  *
  1423.  * Revision 1.30  2003/12/12 14:09:53  kuznets
  1424.  * + s_TEST_BDB_Transaction()
  1425.  *
  1426.  * Revision 1.29  2003/11/26 13:09:44  kuznets
  1427.  * Re-enables icache test
  1428.  *
  1429.  * Revision 1.28  2003/11/25 19:58:37  kuznets
  1430.  * Temporary disabled ICache test (fails on Solaris)
  1431.  *
  1432.  * Revision 1.27  2003/11/25 19:36:54  kuznets
  1433.  * + test for ICache implementation
  1434.  *
  1435.  * Revision 1.26  2003/11/14 04:31:10  ucko
  1436.  * bytes_read should be size_t, not unsigned.
  1437.  *
  1438.  * Revision 1.25  2003/10/27 14:21:15  kuznets
  1439.  * + DBD dumper test
  1440.  *
  1441.  * Revision 1.24  2003/10/24 13:41:51  kuznets
  1442.  * Tested blob stream PendingCount
  1443.  *
  1444.  * Revision 1.23  2003/10/20 20:15:54  kuznets
  1445.  * Cache test improved
  1446.  *
  1447.  * Revision 1.22  2003/10/20 19:59:03  kuznets
  1448.  * + Unit test for Int cache
  1449.  *
  1450.  * Revision 1.21  2003/10/15 18:14:33  kuznets
  1451.  * Changed test to work with alternative page size and larger cache.
  1452.  *
  1453.  * Revision 1.20  2003/09/29 16:54:58  kuznets
  1454.  * Reverting unnecessary commit
  1455.  *
  1456.  * Revision 1.19  2003/09/29 16:27:07  kuznets
  1457.  * Cleaned up 64-bit compilation warnings
  1458.  *
  1459.  * Revision 1.18  2003/09/17 18:19:02  kuznets
  1460.  * Added test for BLOB streaming
  1461.  *
  1462.  * Revision 1.17  2003/09/16 15:15:16  kuznets
  1463.  * Test corrected to use Int2 field
  1464.  *
  1465.  * Revision 1.16  2003/08/27 20:05:33  kuznets
  1466.  * Added test working with file locking environment
  1467.  *
  1468.  * Revision 1.15  2003/07/25 15:35:59  kuznets
  1469.  * Added simple db_map<string, int> test
  1470.  *
  1471.  * Revision 1.14  2003/07/24 15:44:44  kuznets
  1472.  * Clened up several compiler warnings
  1473.  *
  1474.  * Revision 1.13  2003/07/23 20:23:37  kuznets
  1475.  * + test for clean, erase (db_map)
  1476.  *
  1477.  * Revision 1.12  2003/07/22 19:21:56  kuznets
  1478.  * Added test case for CBDB_File::Attach function
  1479.  *
  1480.  * Revision 1.11  2003/07/22 16:38:30  kuznets
  1481.  * Polishing test
  1482.  *
  1483.  * Revision 1.10  2003/07/22 15:21:17  kuznets
  1484.  * Sketched two tet cases for db_map and db_multimap
  1485.  *
  1486.  * Revision 1.9  2003/07/09 14:29:47  kuznets
  1487.  * Added DB_DUP mode test.
  1488.  *
  1489.  * Revision 1.8  2003/05/27 18:05:08  kuznets
  1490.  * Fixed compilation warnings
  1491.  *
  1492.  * Revision 1.7  2003/05/08 13:44:04  kuznets
  1493.  * Minor test improvements
  1494.  *
  1495.  * Revision 1.6  2003/05/07 14:13:45  kuznets
  1496.  * + test case for cursor reading of BLOB storage.
  1497.  *
  1498.  * Revision 1.5  2003/05/05 20:15:35  kuznets
  1499.  * Added CBDB_BLobFile
  1500.  *
  1501.  * Revision 1.4  2003/05/02 14:10:57  kuznets
  1502.  * Added test for UpdateInsert
  1503.  *
  1504.  * Revision 1.3  2003/04/29 20:50:22  kuznets
  1505.  * Code cleanup
  1506.  *
  1507.  * Revision 1.2  2003/04/29 19:04:13  kuznets
  1508.  * +Test makefiles
  1509.  *
  1510.  * Revision 1.1  2003/04/28 18:12:52  kuznets
  1511.  * Initial revision
  1512.  *
  1513.  *
  1514.  * ===========================================================================
  1515.  */