test_bdb.cpp

来自「ncbi源码」· C++ 代码 · 共 2,043 行 · 第 1/3 页

CPP
2,043
字号
/* * =========================================================================== * PRODUCTION $Log: test_bdb.cpp,v $ * PRODUCTION Revision 1000.5  2004/06/01 18:37:53  gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.46 * PRODUCTION * =========================================================================== *//*  $Id: test_bdb.cpp,v 1000.5 2004/06/01 18:37:53 gouriano Exp $ * =========================================================================== * *                            PUBLIC DOMAIN NOTICE *               National Center for Biotechnology Information * *  This software/database is a "United States Government Work" under the *  terms of the United States Copyright Act.  It was written as part of *  the author's official duties as a United States Government employee and *  thus cannot be copyrighted.  This software/database is freely available *  to the public for use. The National Library of Medicine and the U.S. *  Government have not placed any restriction on its use or reproduction. * *  Although all reasonable efforts have been taken to ensure the accuracy *  and reliability of the software and data, the NLM and the U.S. *  Government do not and cannot warrant the performance or results that *  may be obtained by using this software or data. The NLM and the U.S. *  Government disclaim all warranties, express or implied, including *  warranties of performance, merchantability or fitness for any particular *  purpose. * *  Please cite the author in any work or product based on this material. * * =========================================================================== * * Author: Anatoliy Kuznetsov * * File Description: Test application for NCBI Berkeley DB library (BDB) * */#include <ncbi_pch.hpp>#include <corelib/ncbiapp.hpp>#include <corelib/ncbiargs.hpp>#include <corelib/ncbifile.hpp>#include <corelib/ncbitime.hpp>#include <stdio.h>#include <bdb/bdb_expt.hpp>#include <bdb/bdb_types.hpp>#include <bdb/bdb_file.hpp>#include <bdb/bdb_env.hpp>#include <bdb/bdb_cursor.hpp>#include <bdb/bdb_blob.hpp>#include <bdb/bdb_map.hpp>#include <bdb/bdb_blobcache.hpp>#include <bdb/bdb_filedump.hpp>#include <bdb/bdb_trans.hpp>#include <bdb/bdb_query.hpp>#include <bdb/bdb_query_parser.hpp>#include <test/test_assert.h>  /* This header must go last */USING_NCBI_SCOPE;static const char* s_TestStrTempl = "Test str %i";static const char* s_StrKeyTempl = "%i test key %i";////////////////////////////////// Test functions, classes, etc.////////////////////////////////////////////////////////////////////// // Structure implements simple database table with integer id primary key////struct TestDBF1 : public CBDB_IdFile{    CBDB_FieldInt4      idata;    CBDB_FieldString    str;    CBDB_FieldInt4      i2;    CBDB_FieldInt2      ishort;        TestDBF1()    {        BindData("idata", &idata);        BindData("str", &str, 256);        BindData("i2", &i2);        BindData("ishort", &ishort);    }};struct TestDBF1L : public CBDB_IdFile{    CBDB_FieldInt4      idata;    CBDB_FieldLString   str;    CBDB_FieldInt4      i2;    CBDB_FieldInt2      ishort;        TestDBF1L()    {        BindData("idata", &idata);        BindData("str", &str, 256);        BindData("i2", &i2);        BindData("ishort", &ishort);        SetLegacyStringsCheck(true);            }};// Utility function to check record consistency template<class T>void ValidateRecord(const T& dbf1, unsigned int id){    char buf[256];    sprintf(buf, s_TestStrTempl, id);    int idata1 = dbf1.idata;    unsigned int id_key = dbf1.IdKey;    string s;    s = dbf1.str;    int i21 = dbf1.i2;    assert(s == string(buf));    assert(id_key == id);    assert(idata1 == (int)(400 + id));    assert(i21 == (int)(id + 3));    }const char* s_TestFileName = "testbase.db";const char* s_TestFileName2= "testbase2.db";const char* s_TestFileName3= "testbase3.db";const char* s_db_map1 = "i2s.db";const char* s_db_map2 = "ii2s.db";const unsigned int s_RecsInTable = 100;//////////////////////////////////////////////////////////////////// // Structure implements simple database table with case insensitive string // as a primary key////struct TestDBF2 : public CBDB_File{    CBDB_FieldStringCase  str_key;    CBDB_FieldInt4        idata;    CBDB_FieldString      str;    CBDB_FieldInt4        i2;    TestDBF2()    {        BindKey("strkey", &str_key, 256);        BindData("idata", &idata);        BindData("str", &str, 256);        BindData("i2", &i2);    }};// Utility function to check record consistency void ValidateRecord(const TestDBF2& dbf2, unsigned i){    char buf[256];    sprintf(buf, s_StrKeyTempl, i, i);    string s = (const char*)dbf2.str_key;    assert(s == string(buf));    assert(dbf2.idata == (int)(400+i));    sprintf(buf, s_TestStrTempl, i);    s = (const char*)dbf2.str;    assert(s == string(buf));    assert((int)dbf2.i2 == (int)(i+3));}struct TestDBF3 : public CBDB_File{    CBDB_FieldInt4        ikey;    CBDB_FieldInt4        idata;    TestDBF3()    {        BindKey("ikey",   &ikey);        BindData("idata", &idata);    }};////////////////////////////////////////////////////////////////////// // BDB transaction test////staticvoid s_TEST_BDB_Transaction(void){    cout << "======== Transactions test." << endl;    CBDB_Env env;    env.OpenWithTrans(".");        TestDBF3  dbf3;        dbf3.SetEnv(env);       dbf3.Open("trans_test.db", CBDB_File::eReadWriteCreate);    cout << dbf3.CountRecs() << endl;    CBDB_Transaction trans(env);    dbf3.SetTransaction(&trans);    dbf3.ikey = 10;    dbf3.idata = 11;    dbf3.Insert();    dbf3.ikey = 12;    dbf3.idata = 13;    dbf3.Insert();    trans.Commit();    dbf3.ikey = 10;    EBDB_ErrCode ret = dbf3.Fetch();    assert (ret == eBDB_Ok);        int idata = dbf3.idata;    assert(idata == 11);    dbf3.ikey = 10;    dbf3.idata = 20;    dbf3.UpdateInsert();    ret = dbf3.Fetch();    assert (ret == eBDB_Ok);    idata = dbf3.idata;    assert(idata == 20);    dbf3.ikey = 12;    ret = dbf3.Fetch();    assert (ret == eBDB_Ok);    idata = dbf3.idata;    assert(idata == 13);    trans.Abort();    dbf3.SetTransaction(0);    dbf3.ikey = 10;    ret = dbf3.Fetch();    assert (ret == eBDB_Ok);        idata = dbf3.idata;    assert(idata == 11);    cout << "======== Transactions test ok." << endl;}////////////////////////////////////////////////////////////////////// // BDB types test////static void s_TEST_BDB_Types(void){    cout << "======== BDB types test." << endl;    TestDBF1  dbf1;    cout << "======== BDB types test ok." << endl;}////////////////////////////////////////////////////////////////////// // BDB Id table fill test////static void s_IdTableFill(TestDBF1& dbf, unsigned int records){    for (unsigned int i = 1; i < records; ++i) {        char buf[256];        sprintf(buf, s_TestStrTempl, i);        dbf.IdKey = i;        dbf.idata = 400+i;        dbf.str = buf;        dbf.i2.Set(i+3);        int i2 = dbf.i2;        assert (i2 == (int)(i+3));        assert(!dbf.idata.IsNull());        EBDB_ErrCode err = dbf.Insert();        assert(err == eBDB_Ok);        assert(dbf.idata.IsNull());    }}static void s_TEST_BDB_IdTable_Fill(void){    cout << "======== Id table filling test." << endl;    CBDB_Env env;    env.OpenWithLocks(0);    env.OpenErrFile("err_test.txt");    TestDBF1  dbf1;    dbf1.SetEnv(env);    dbf1.SetPageSize(32 * 1024);    dbf1.SetCacheSize(5 * (1024 * 1024));    dbf1.Open(s_TestFileName, CBDB_File::eCreate);    assert(dbf1.idata.IsNull());    // Fill the table    unsigned i;    s_IdTableFill(dbf1, s_RecsInTable);        // Trying to put duplicate record    dbf1.IdKey = 1;    dbf1.idata = 400 + 1;    dbf1.str = "test";    EBDB_ErrCode err = dbf1.Insert();    assert(err == eBDB_KeyDup);    cout << "Table " << s_TestFileName          << " loaded ok. Checking consistency."          << endl;    // Read the table check if all records are in place    dbf1.Reopen(CBDB_File::eReadOnly);    for (i = 1; i < s_RecsInTable; ++i) {        dbf1.IdKey = i;        EBDB_ErrCode ret = dbf1.Fetch();        assert (ret == eBDB_Ok);        ValidateRecord(dbf1, i);    } // for    {{    TestDBF1  dbf11;    dbf11.Attach(dbf1);    for (i = 1; i < s_RecsInTable; ++i) {        dbf11.IdKey = i;        EBDB_ErrCode ret = dbf11.Fetch();        assert (ret == eBDB_Ok);        ValidateRecord(dbf11, i);        // Checking that attached buffer doesn't change status of the main one        dbf1.IdKey = 1;        ret = dbf1.Fetch();        assert (ret == eBDB_Ok);        ValidateRecord(dbf1, 1);        ValidateRecord(dbf11, i);    } // for    }}    {{    TestDBF1L  dbf11;    dbf11.Open(s_TestFileName, CBDB_File::eReadWrite);    for (i = 1; i < s_RecsInTable; ++i) {        dbf11.IdKey = i;        EBDB_ErrCode ret = dbf11.Fetch();        assert (ret == eBDB_Ok);        ValidateRecord(dbf11, i);    } // for    string s = "123";    s.append(1, (char)0);    s.append("123");    cout << "(" << s << ")" << s.length() << endl;    dbf11.IdKey = 1000;    dbf11.idata = 1000;    dbf11.str = s;    dbf11.Insert();    dbf11.IdKey = 1000;    EBDB_ErrCode ret = dbf11.Fetch();    assert (ret == eBDB_Ok);    string s2 = dbf11.str;    string s3 = dbf11.str.GetString();    size_t l2 = s2.length();    size_t l3 = s3.length();    assert(s3 == s);    assert(s2 == s);    assert(l2 == l3);    // Dumping the database to screen    CBDB_FileDumper dump;    dump.Dump(cout, dbf11);    }}    cout << "======== Id table filling test ok." << endl;}static void s_TEST_BDB_IdTable_FillStress(void){    cout << "======== Id table filling stress test." << endl;    CBDB_Env env;    env.SetCacheSize(150 * (1024 * 1024));    env.OpenWithLocks(0);    TestDBF1  dbf1;    dbf1.SetEnv(env);    dbf1.Open(s_TestFileName, CBDB_File::eCreate);    assert(dbf1.idata.IsNull());    // Fill the table    unsigned i;    const unsigned int recs = 1000000;    s_IdTableFill(dbf1, recs);    cout << "Table loaded..." << endl;        // Read the table check if all records are in place    dbf1.Reopen(CBDB_File::eReadOnly);    for (i = 1; i < recs; ++i) {        dbf1.IdKey = i;        EBDB_ErrCode ret = dbf1.Fetch();        assert (ret == eBDB_Ok);        ValidateRecord(dbf1, i);    } // for    cout << "Check 1 complete" << endl;    dbf1.Reopen(CBDB_File::eReadOnly);    for (i = 1; i < recs; ++i) {        {{            CBDB_FileCursor cur(dbf1);            cur.SetCondition(CBDB_FileCursor::eEQ);            cur.From << i;            EBDB_ErrCode ret = cur.FetchFirst();            assert (ret == eBDB_Ok);            ValidateRecord(dbf1, i);        }}    } // for    cout << "======== Id table stress filling test ok." << endl;}class CTestScanner : public CBDB_FileScanner{public:    CTestScanner(CBDB_File& db_file)    : CBDB_FileScanner(db_file)    {}    virtual EScanAction OnRecordFound()    {        return eContinue;    }protected:    };static void s_TEST_BDB_Query(void){    bool bres;    cout << "======== Query test." << endl;    TestDBF1  dbf1;    dbf1.Open(s_TestFileName, CBDB_File::eReadOnly);    dbf1.IdKey = 1;    dbf1.Fetch();    CTestScanner  scanner(dbf1);    CBDB_Query    query;    {{        const char* ch = " test";        CBDB_Query    query;        BDB_PrintQueryTree(cout, query);        BDB_ParseQuery(ch, &query);        BDB_PrintQueryTree(cout, query);    }}    {{        const char* ch = "  '2' And ((name3 OR 1) & name3)";        CBDB_Query    query;        BDB_ParseQuery(ch, &query);        BDB_PrintQueryTree(cout, query);    }}    // Testing the query evaluation logic    //    // "1" == "2" => false    {{    CBDB_Query::TQueryClause* eq_node =           CBDB_Query::NewOperatorNode(CBDB_QueryNode::eEQ, "1", "2");    query.SetQueryClause(eq_node);    bres = scanner.StaticEvaluate(query);    assert(!bres);    BDB_PrintQueryTree(cout, query);    }}    {{    const char* ch = "'1' = 2";    BDB_ParseQuery(ch, &query);    bres = scanner.StaticEvaluate(query);    assert(!bres);    }}    {{    const char* ch = "not '1' = 2";    BDB_ParseQuery(ch, &query);    bres = scanner.StaticEvaluate(query);    cout << endl;    BDB_PrintQueryTree(cout, query);    assert(bres);    }}    {{    const char* ch = "'1' != 2";    BDB_ParseQuery(ch, &query);    bres = scanner.StaticEvaluate(query);    assert(bres);    }}    {{    const char* ch = "'1' <> 2";    BDB_ParseQuery(ch, &query);    bres = scanner.StaticEvaluate(query);    assert(bres);    }}    {{    const char* ch = "'1' < 2";    BDB_ParseQuery(ch, &query);    bres = scanner.StaticEvaluate(query);    assert(bres);    }}    {{    const char* ch = "'1' <= 1";    BDB_ParseQuery(ch, &query);    bres = scanner.StaticEvaluate(query);    assert(bres);    }}    {{    const char* ch = "'1' >= 1";    BDB_ParseQuery(ch, &query);    bres = scanner.StaticEvaluate(query);    assert(bres);    }}    {{    const char* ch = "'2' > 1";    BDB_ParseQuery(ch, &query);    bres = scanner.StaticEvaluate(query);    assert(bres);    }}    // "2" == "2" => true    {{    CBDB_Query::TQueryClause* eq_node =           CBDB_Query::NewOperatorNode(CBDB_QueryNode::eEQ, "2", "2");    query.SetQueryClause(eq_node);    bres = scanner.StaticEvaluate(query);    assert(bres);    }}    {{        const char* ch = "2 = 2";    BDB_ParseQuery(ch, &query);    bres = scanner.StaticEvaluate(query);    assert(bres);    }}    // ("1" == "1" AND "2" == "2") => true    {{    CBDB_Query::TQueryClause* eq_node1 =           CBDB_Query::NewOperatorNode(CBDB_QueryNode::eEQ, "2", "2");    CBDB_Query::TQueryClause* eq_node2 =           CBDB_Query::NewOperatorNode(CBDB_QueryNode::eEQ, "1", "1");    CBDB_Query::TQueryClause* and_node =        new CBDB_Query::TQueryClause(CBDB_QueryNode::eAnd);    and_node->AddNode(eq_node1);    and_node->AddNode(eq_node2);    query.SetQueryClause(and_node);    bres = scanner.StaticEvaluate(query);    assert(bres);    }}    {{        const char* ch = "(1=1 AND 2=2)";    BDB_ParseQuery(ch, &query);    bres = scanner.StaticEvaluate(query);    assert(bres);    }}    // ("1" == "1" AND "2" == "0") => false    {{

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?