Libcdbxx test
/* test.cc
* This file is part of cdbxx library
* Copyright (c) 2004 by Stanislav Ievlev
*
* This file is covered by the GNU Library General Public License,
* which should be included with libcdbxx as the file COPYING.
*/
#include <iostream>
#include <stdexcept>
#include <cstdio>
#include <algorithm>
#include <unistd.h>
#include <fcntl.h>
#include "cdbxx/db.hh"
#include "cdbxx/map.hh"
struct test_struct
{
test_struct():a_(3),b_('3') {}
int a_;
char b_;
};
const std::string test_str("some value");
const int max = 50;
void show(const cdbxx::data_pair& field)
{
static int i = 0;
if ((i < max) && (i != field.first.as<const int>()))
throw std::runtime_error("wrong key");
++i;
if (i > max) return;
if (cdbxx::string(field.second) != test_str)
throw std::runtime_error("wrong string value");
cdbxx::vector<char> content(field.second);
content.get().push_back('\000');//append zero symbol to compare as a strings
if (&content.get()[0] != test_str) throw std::runtime_error("wrong vector value");
}
void no_here(const cdbxx::data_pair&)
{
throw std::runtime_error("this was an empty database");
}
int
main()
{
int ret = EXIT_SUCCESS;
const char db_name1[]="./test1.cdb";
const char db_name2[]="./test2.cdb";
const char db_name3[]="./test3.cdb";
const char empty_db[]="./empty.cdb";
const char map_name[]="./map.cdb";
//simple filling of the database
std::cout << " 1";
try
{
cdbxx::out_db new_database(db_name1);
std::vector<int> key(1);
std::vector<char> value(test_str.begin(), test_str.end());
for (int i = 0;i < max;++i)
{
key[0] = i;
new_database.insert(key, value);
}
//test insert with key as a string
new_database.insert("some key", value);
//test insert with key as a struct
test_struct struct_value;
new_database.insert("struct key",&struct_value);
}
catch (std::runtime_error e)
{
std::cerr << "catch:" << e.what() << std::endl;
ret = EXIT_FAILURE;
}
catch (...)
{
std::cerr << "unknown exception\n";
ret = EXIT_FAILURE;
}
//catch if value exist
std::cout << " 2";
try
{
cdbxx::out_db new_database(db_name2);
std::vector<int> key(1);
std::vector<char> value(test_str.begin(), test_str.end());
for (int i = 1;i < 3;++i)
{
key[0] = 55;
new_database.insert(key, value); //must catch exception on second loop
}
ret = EXIT_FAILURE;
std::cerr << "we must catch insertion of duplicate here\n";
}
catch (std::runtime_error)
{
//catch here
}
catch (...)
{
std::cerr << "unknown exception\n";
ret = EXIT_FAILURE;
}
//read database
std::cout << " 3";
try
{
cdbxx::in_db old_database(db_name1);
std::for_each(old_database.begin(), old_database.end(), show);
}
catch (std::runtime_error e)
{
std::cerr << "catch:" << e.what() << std::endl;
ret = EXIT_FAILURE;
}
catch (...)
{
std::cerr << "unknown exception\n";
ret = EXIT_FAILURE;
}
//search in database
std::cout << " 4";
try
{
cdbxx::in_db old_database(db_name1);
cdbxx::iterator it = old_database.find("some key");
if (it == old_database.end() || (cdbxx::string(it->second) != test_str))
throw std::runtime_error("problems with find: search for existing value (key as string)");
std::vector<int> key(1);
key[0] = 1;
cdbxx::iterator it2 = old_database.find(key);
if (it2 == old_database.end() || (cdbxx::string(it2->second) != test_str))
throw std::runtime_error("problems with find: search for existing value (key as vector)");
cdbxx::iterator it3 = old_database.find("unknown key");
if (it3 != old_database.end())
throw std::runtime_error("problems with find: search for noexisting value");
//search for a struct
cdbxx::iterator it4 = old_database.find("struct key");
if (it4 == old_database.end())
throw std::runtime_error("problems with find: search for struct value");
else
{
const test_struct *st_value = it4->second.as_ptr<const test_struct>();
if ((st_value->a_ != 3) || (st_value->b_ != '3'))
throw std::runtime_error("wrong struct was returned");
}
}
catch (std::runtime_error e)
{
std::cerr << "catch:" << e.what() << std::endl;
ret = EXIT_FAILURE;
}
catch (...)
{
std::cerr << "unknown exception\n";
ret = EXIT_FAILURE;
}
//open non existing database
std::cout << " 5";
try
{
cdbxx::in_db old_database("./non-existend-databse.cdb");
ret = EXIT_FAILURE;//we must catch exception
std::cerr<<"non existent database: cannot catch exception\n";
}
catch (cdbxx::open_error)
{
//ok if here
}
catch (std::runtime_error e)
{
std::cerr << "catch:" << e.what() << std::endl;
ret = EXIT_FAILURE;
}
catch (...)
{
std::cerr << "unknown exception\n";
ret = EXIT_FAILURE;
}
//open on wrong descriptors
std::cout<< " 6";
try
{
const int test_value = 36;
int fd = open(db_name3,O_RDWR|O_CREAT,0644);
//first: fill with values
{
std::vector<int> value(1);
value[0] = test_value;
cdbxx::out_db out(fd);
out.insert("key",value);
}
//then try to read
{
cdbxx::in_db in(fd);
cdbxx::iterator it = in.find("key");
if (it == in.end())
throw std::runtime_error("unable to find existing key");
if (it->second.as<const int>() != test_value)
throw std::runtime_error("reading wrong value");
}
close(fd);
}
catch (std::runtime_error e)
{
std::cerr << "catch:" << e.what() << std::endl;
ret = EXIT_FAILURE;
}
catch (...)
{
std::cerr << "unknown exception\n";
ret = EXIT_FAILURE;
}
//working with empty database
std::cout << " 7";
try
{
{
cdbxx::out_db new_database(empty_db);
}
{
cdbxx::in_db old_database(empty_db);
std::for_each(old_database.begin(),old_database.end(),no_here);
}
}
catch (std::runtime_error& e)
{
//catch here
std::cerr << "catch:" << e.what() << std::endl;
ret = EXIT_FAILURE;
}
catch (...)
{
std::cerr << "unknown exception\n";
ret = EXIT_FAILURE;
}
//std::map like interface
std::cout << " 8";
try
{
{
cdbxx::out_map<int,std::string> m(map_name);
m.set(1,"aaa");
}
{
cdbxx::in_map<int,std::string> m(map_name);
if (m.get(1) != "aaa")
throw std::runtime_error("getting strange value");
}
}
catch (std::runtime_error& e)
{
//catch here
std::cerr << "catch:" << e.what() << std::endl;
ret = EXIT_FAILURE;
}
catch (...)
{
std::cerr << "unknown exception\n";
ret = EXIT_FAILURE;
}
std::remove(db_name1);
std::remove(db_name2);
std::remove(db_name3);
std::remove(empty_db);
std::remove(map_name);
std::cout << "- "<<((EXIT_SUCCESS == ret)?"ok":"failed")<<std::endl;
return ret;
}