summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am1
-rw-r--r--src/account.cpp19
-rw-r--r--src/account.h8
-rw-r--r--src/being.h9
-rw-r--r--src/dal/mysqldataprovider.cpp5
-rw-r--r--src/dalstorage.cpp88
-rw-r--r--src/dalstorage.h17
-rw-r--r--src/storage.h10
-rw-r--r--src/tests/testaccount.cpp55
-rw-r--r--src/tests/testcipher.cpp30
-rw-r--r--src/tests/testdataprovider.cpp17
-rw-r--r--src/tests/testrecordset.cpp45
-rw-r--r--src/tests/testsmain.cpp5
-rw-r--r--src/tests/teststorage.cpp509
-rw-r--r--src/tests/teststorage.h65
-rw-r--r--src/utils/countedptr.h163
16 files changed, 696 insertions, 350 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index f15ee46..56003d2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -45,6 +45,7 @@ tmwserv_SOURCES = main.cpp \
dal/dataproviderfactory.cpp \
dal/recordset.h \
dal/recordset.cpp \
+ utils/countedptr.h \
utils/functors.h \
utils/singleton.h \
utils/cipher.h \
diff --git a/src/account.cpp b/src/account.cpp
index 97b723a..c44af2d 100644
--- a/src/account.cpp
+++ b/src/account.cpp
@@ -70,15 +70,8 @@ Account::Account(const std::string& name,
Account::~Account(void)
throw()
{
- for (Beings::iterator it = mCharacters.begin();
- it != mCharacters.end();
- ++it)
- {
- if (*it != 0) {
- delete (*it);
- *it = 0;
- }
- }
+ // mCharacters is a list of smart pointers which will take care about
+ // deallocating the memory so nothing to deallocate here :)
}
@@ -177,9 +170,9 @@ Account::setCharacters(const Beings& characters)
* Add a new character.
*/
void
-Account::addCharacter(Being* character)
+Account::addCharacter(BeingPtr character)
{
- if (character) {
+ if (character.get() != 0) {
mCharacters.push_back(character);
}
}
@@ -204,11 +197,11 @@ Account::getCharacter(const std::string& name)
Beings::iterator it =
std::find_if(mCharacters.begin(),
mCharacters.end(),
- std::bind2nd(obj_name_is<Being*>(), name)
+ std::bind2nd(obj_name_is<BeingPtr>(), name)
);
if (it != mCharacters.end()) {
- return (*it);
+ return (*it).get();
}
return 0;
diff --git a/src/account.h b/src/account.h
index 0291b78..7e1322c 100644
--- a/src/account.h
+++ b/src/account.h
@@ -174,7 +174,7 @@ class Account
* @param character the new character.
*/
void
- addCharacter(Being* character);
+ addCharacter(BeingPtr character);
/**
@@ -225,6 +225,12 @@ class Account
};
+/**
+ * Type definition for a smart pointer to Account.
+ */
+typedef utils::CountedPtr<Account> AccountPtr;
+
+
} // namespace tmwserv
diff --git a/src/being.h b/src/being.h
index 577ec31..2ebbd8c 100644
--- a/src/being.h
+++ b/src/being.h
@@ -30,6 +30,7 @@
#include "defines.h"
#include "object.h"
+#include "utils/countedptr.h"
namespace tmwserv
@@ -285,9 +286,15 @@ class Being: public Object
/**
+ * Type definition for a smart pointer to Being.
+ */
+typedef utils::CountedPtr<Being> BeingPtr;
+
+
+/**
* Type definition for a list of Beings.
*/
-typedef std::vector<Being*> Beings;
+typedef std::vector<BeingPtr> Beings;
} // namespace tmwserv
diff --git a/src/dal/mysqldataprovider.cpp b/src/dal/mysqldataprovider.cpp
index 1813fdd..ca01577 100644
--- a/src/dal/mysqldataprovider.cpp
+++ b/src/dal/mysqldataprovider.cpp
@@ -104,7 +104,10 @@ MySqlDataProvider::connect(const std::string& dbName,
NULL, // use defaut socket
0)) // client flags
{
- throw DbConnectionFailure(mysql_error(mDb));
+ std::string msg(mysql_error(mDb));
+ mysql_close(mDb);
+
+ throw DbConnectionFailure(msg);
}
mIsConnected = true;
diff --git a/src/dalstorage.cpp b/src/dalstorage.cpp
index 1970ed7..ca47c3f 100644
--- a/src/dalstorage.cpp
+++ b/src/dalstorage.cpp
@@ -57,26 +57,8 @@ DALStorage::~DALStorage()
close();
}
- // clean up accounts.
- for (Accounts::iterator it = mAccounts.begin();
- it != mAccounts.end();
- ++it)
- {
- if (it->first != 0) {
- delete it->first;
- }
- }
-
- // clean up characters.
- for (Beings::iterator it = mCharacters.begin();
- it != mCharacters.end();
- ++it)
- {
- if (*it != 0) {
- delete (*it);
- *it = 0;
- }
- }
+ // mAccounts and mCharacters contain smart pointers that will deallocate
+ // the memory so nothing else to do here :)
}
@@ -179,7 +161,7 @@ DALStorage::getAccount(const std::string& userName)
);
if (it != mAccounts.end()) {
- return it->first;
+ return (it->first).get();
}
using namespace dal;
@@ -201,9 +183,9 @@ DALStorage::getAccount(const std::string& userName)
// create an Account instance
// and initialize it with information about the user.
- Account* account = new Account(accountInfo(0, 1),
+ AccountPtr account(new Account(accountInfo(0, 1),
accountInfo(0, 2),
- accountInfo(0, 3));
+ accountInfo(0, 3)));
// specialize the string_to functor to convert
// a string to an unsigned int.
@@ -247,11 +229,11 @@ DALStorage::getAccount(const std::string& userName)
Genders gender;
switch (value)
{
- case 0:
+ case GENDER_MALE:
gender = GENDER_MALE;
break;
- case 1:
+ case GENDER_FEMALE:
gender = GENDER_FEMALE;
break;
@@ -260,13 +242,13 @@ DALStorage::getAccount(const std::string& userName)
break;
};
- Being* being =
+ BeingPtr being(
new Being(charInfo(i, 2), // name
gender, // gender
toUshort(charInfo(i, 4)), // level
toUint(charInfo(i, 5)), // money
stats
- );
+ ));
mCharacters.push_back(being);
beings.push_back(being);
@@ -275,7 +257,7 @@ DALStorage::getAccount(const std::string& userName)
account->setCharacters(beings);
}
- return account;
+ return account.get();
}
catch (const DbSqlQueryExecFailure& e) {
return NULL; // TODO: Throw exception here
@@ -287,9 +269,9 @@ DALStorage::getAccount(const std::string& userName)
* Add a new account.
*/
void
-DALStorage::addAccount(const Account* account)
+DALStorage::addAccount(const AccountPtr& account)
{
- if (account == 0) {
+ if (account.get() == 0) {
// maybe we should throw an exception instead
return;
}
@@ -301,7 +283,7 @@ DALStorage::addAccount(const Account* account)
// the account id is set to 0 because we know nothing about it at the
// moment, it will be updated once saved into the database.
ai.id = 0;
- mAccounts.insert(std::make_pair(const_cast<Account*>(account), ai));
+ mAccounts.insert(std::make_pair(account, ai));
}
@@ -325,12 +307,7 @@ DALStorage::delAccount(const std::string& userName)
{
// this is a newly added account and it has not even been
// saved into the database: remove it immediately.
-
- // TODO: delete the associated characters.
-
- delete it->first;
-
- // TODO: remove from the map.
+ mAccounts.erase(it);
}
break;
@@ -356,6 +333,7 @@ DALStorage::delAccount(const std::string& userName)
}
catch (const dal::DbSqlQueryExecFailure& e) {
// TODO: throw an exception.
+ LOG_ERROR("SQL query failure: " << e.what())
}
}
@@ -366,9 +344,9 @@ DALStorage::delAccount(const std::string& userName)
void
DALStorage::flush(void)
{
- Accounts::const_iterator it = mAccounts.begin();
- Accounts::const_iterator it_end = mAccounts.end();
- for (; it != it_end; ++it) {
+ Accounts::iterator it = mAccounts.begin();
+ Accounts::iterator it_end = mAccounts.end();
+ for (; it != it_end; ) {
switch ((it->second).status) {
case AS_NEW_ACCOUNT:
_addAccount(it->first);
@@ -379,13 +357,15 @@ DALStorage::flush(void)
break;
case AS_ACC_TO_DELETE:
- // TODO: accounts to be deleted must be handled differently
- // as mAccounts will be altered once the accounts are deleted.
+ _delAccount(it->first);
+ mAccounts.erase(it);
break;
default:
break;
}
+
+ ++it;
}
}
@@ -429,9 +409,9 @@ DALStorage::createTable(const std::string& tblName,
* Add an account to the database.
*/
void
-DALStorage::_addAccount(const Account* account)
+DALStorage::_addAccount(const AccountPtr& account)
{
- if (account == 0) {
+ if (account.get() == 0) {
return;
}
@@ -471,7 +451,7 @@ DALStorage::_addAccount(const Account* account)
(account_it->second).id = toUint(accountInfo(0, 0));
// insert the characters.
- Beings& characters = (const_cast<Account*>(account))->getCharacters();
+ Beings& characters = account->getCharacters();
Beings::const_iterator it = characters.begin();
Beings::const_iterator it_end = characters.end();
@@ -505,9 +485,9 @@ DALStorage::_addAccount(const Account* account)
* Update an account from the database.
*/
void
-DALStorage::_updAccount(const Account* account)
+DALStorage::_updAccount(const AccountPtr& account)
{
- if (account == 0) {
+ if (account.get() == 0) {
return;
}
@@ -543,7 +523,7 @@ DALStorage::_updAccount(const Account* account)
mDb->execSql(sql1.str());
// get the list of characters that belong to this account.
- Beings& characters = (const_cast<Account*>(account))->getCharacters();
+ Beings& characters = account->getCharacters();
// insert or update the characters.
Beings::const_iterator it = characters.begin();
@@ -611,6 +591,18 @@ DALStorage::_updAccount(const Account* account)
* Delete an account and its associated data from the database.
*/
void
+DALStorage::_delAccount(const AccountPtr& account)
+{
+ if (account.get() != 0) {
+ _delAccount(account->getName());
+ }
+}
+
+
+/**
+ * Delete an account and its associated data from the database.
+ */
+void
DALStorage::_delAccount(const std::string& userName)
{
using namespace dal;
diff --git a/src/dalstorage.h b/src/dalstorage.h
index 80408f6..637dfa3 100644
--- a/src/dalstorage.h
+++ b/src/dalstorage.h
@@ -81,7 +81,7 @@ class DALStorage: public Storage
* @param account the new account.
*/
void
- addAccount(const Account* account);
+ addAccount(const AccountPtr& account);
/**
@@ -150,7 +150,7 @@ class DALStorage: public Storage
* @exeception tmwserv::dal::DbSqlQueryExecFailure.
*/
void
- _addAccount(const Account* account);
+ _addAccount(const AccountPtr& account);
/**
@@ -161,7 +161,18 @@ class DALStorage: public Storage
* @exception tmwserv::dal::DbSqlQueryExecFailure.
*/
void
- _updAccount(const Account* account);
+ _updAccount(const AccountPtr& account);
+
+
+ /**
+ * Delete an account and its associated data from the database.
+ *
+ * @param account the account to update.
+ *
+ * @exception tmwserv::dal::DbSqlQueryExecFailure.
+ */
+ void
+ _delAccount(const AccountPtr& account);
/**
diff --git a/src/storage.h b/src/storage.h
index 6b8fdc4..3adf1b2 100644
--- a/src/storage.h
+++ b/src/storage.h
@@ -73,10 +73,10 @@ typedef struct {
* Functor to be used as the sorting criterion of the map defined below.
*/
struct account_sort_by_name
- : public std::binary_function<Account*, Account*, bool>
+ : public std::binary_function<AccountPtr, AccountPtr, bool>
{
bool
- operator()(Account* acc1, Account* acc2) const
+ operator()(const AccountPtr& acc1, const AccountPtr& acc2) const
{
return (acc1->getName() < acc2->getName());
}
@@ -91,7 +91,7 @@ struct account_sort_by_name
* only the storage should modify this value, this attribute is for
* internal use.
*/
-typedef std::map<Account*, AccountInfo, account_sort_by_name> Accounts;
+typedef std::map<AccountPtr, AccountInfo, account_sort_by_name> Accounts;
/**
@@ -114,7 +114,7 @@ class account_by_name
* Operator().
*/
bool
- operator()(std::pair<Account*, AccountInfo> elem) const
+ operator()(std::pair<AccountPtr, AccountInfo> elem) const
{
return (elem.first)->getName() == mName;
}
@@ -268,7 +268,7 @@ class Storage
* @param account the new account.
*/
virtual void
- addAccount(const Account* account) = 0;
+ addAccount(const AccountPtr& account) = 0;
/**
diff --git a/src/tests/testaccount.cpp b/src/tests/testaccount.cpp
index 814aaa2..d30c8a7 100644
--- a/src/tests/testaccount.cpp
+++ b/src/tests/testaccount.cpp
@@ -21,6 +21,7 @@
*/
+#include "../utils/logger.h"
#include "testaccount.h"
@@ -37,18 +38,11 @@ using namespace tmwserv;
void
AccountTest::setUp(void)
{
- //RawStatistics stats;
- //stats.strength = 1;
- //stats.agility = 1;
- //stats.vitality = 1;
- //stats.intelligence = 1;
- //stats.dexterity = 1;
- //stats.luck = 1;
const RawStatistics stats = {1, 1, 1, 1, 1, 1};
- Being* sam = new Being("sam", GENDER_MALE, 0, 0, stats);
- Being* merry = new Being("merry", GENDER_MALE, 0, 0, stats);
- Being* pippin = new Being("pippin", GENDER_MALE, 0, 0, stats);
+ BeingPtr sam(new Being("sam", GENDER_MALE, 0, 0, stats));
+ BeingPtr merry(new Being("merry", GENDER_MALE, 0, 0, stats));
+ BeingPtr pippin(new Being("pippin", GENDER_MALE, 0, 0, stats));
mCharacters.push_back(sam);
mCharacters.push_back(merry);
mCharacters.push_back(pippin);
@@ -66,13 +60,6 @@ AccountTest::setUp(void)
void
AccountTest::tearDown(void)
{
- for (Beings::iterator it = mCharacters.begin();
- it != mCharacters.end();
- ++it)
- {
- delete (*it);
- }
-
delete mAccount;
mAccount = 0;
}
@@ -85,6 +72,8 @@ AccountTest::tearDown(void)
void
AccountTest::testCreate1(void)
{
+ LOG("AccountTest::testCreate1()");
+
const std::string name("frodo");
const std::string password("baggins");
const std::string email("frodo@theshire.com");
@@ -105,6 +94,8 @@ AccountTest::testCreate1(void)
void
AccountTest::testCreate2(void)
{
+ LOG("AccountTest::testCreate2()");
+
const std::string name("frodo");
const std::string password("baggins");
const std::string email("frodo@theshire.com");
@@ -118,7 +109,7 @@ AccountTest::testCreate2(void)
CPPUNIT_ASSERT_EQUAL(mCharacters.size(),
mAccount->getCharacters().size());
- Beings& characters = account.getCharacters();
+ const Beings& characters = account.getCharacters();
for (size_t i = 0; i < mCharacters.size(); ++i) {
CPPUNIT_ASSERT_EQUAL(characters[i]->getName(),
@@ -133,15 +124,11 @@ AccountTest::testCreate2(void)
void
AccountTest::testAddCharacter1(void)
{
- RawStatistics stats;
- stats.strength = 1;
- stats.agility = 1;
- stats.vitality = 1;
- stats.intelligence = 1;
- stats.dexterity = 1;
- stats.luck = 1;
+ LOG("AccountTest::testAddCharacter1()");
+
+ RawStatistics stats = {1, 1, 1, 1, 1, 1};
- Being* bilbo = new Being("bilbo", GENDER_MALE, 0, 0, stats);
+ BeingPtr bilbo(new Being("bilbo", GENDER_MALE, 0, 0, stats));
mAccount->addCharacter(bilbo);
@@ -156,8 +143,6 @@ AccountTest::testAddCharacter1(void)
for (size_t i = 0; i < mCharacters.size(); ++i) {
CPPUNIT_ASSERT_EQUAL(names[i], mCharacters[i]->getName());
}
-
- delete bilbo;
}
@@ -167,7 +152,11 @@ AccountTest::testAddCharacter1(void)
void
AccountTest::testAddCharacter2(void)
{
- mAccount->addCharacter(NULL);
+ LOG("AccountTest::testAddCharacter2()");
+
+ BeingPtr nullBeing(0);
+
+ mAccount->addCharacter(nullBeing);
CPPUNIT_ASSERT_EQUAL((size_t) 3, mAccount->getCharacters().size());
@@ -188,9 +177,11 @@ AccountTest::testAddCharacter2(void)
void
AccountTest::testGetCharacter1(void)
{
+ LOG("AccountTest::testGetCharacter1()");
+
const std::string name("merry");
- Being* merry = mAccount->getCharacter(name);
+ const Being* merry = mAccount->getCharacter(name);
CPPUNIT_ASSERT(merry != 0);
CPPUNIT_ASSERT_EQUAL(name, merry->getName());
@@ -203,7 +194,9 @@ AccountTest::testGetCharacter1(void)
void
AccountTest::testGetCharacter2(void)
{
- Being* nobody = mAccount->getCharacter("johndoe");
+ LOG("AccountTest::testGetCharacter2()");
+
+ const Being* nobody = mAccount->getCharacter("johndoe");
CPPUNIT_ASSERT(nobody == 0);
}
diff --git a/src/tests/testcipher.cpp b/src/tests/testcipher.cpp
index d51a440..85e3409 100644
--- a/src/tests/testcipher.cpp
+++ b/src/tests/testcipher.cpp
@@ -24,6 +24,7 @@
#include <string>
#include "../utils/cipher.h"
+#include "../utils/logger.h"
#include "testcipher.h"
@@ -60,8 +61,10 @@ CipherTest::tearDown(void)
void
CipherTest::testMd5_1(void)
{
+ LOG("CipherTest::testMd5_1()");
+
const std::string expected("d41d8cd98f00b204e9800998ecf8427e");
- std::string actual(Cipher::instance().md5(""));
+ const std::string actual(Cipher::instance().md5(""));
CPPUNIT_ASSERT_EQUAL(expected, actual);
}
@@ -73,8 +76,10 @@ CipherTest::testMd5_1(void)
void
CipherTest::testMd5_2(void)
{
+ LOG("CipherTest::testMd5_2()");
+
const std::string expected("0cc175b9c0f1b6a831c399e269772661");
- std::string actual(Cipher::instance().md5("a"));
+ const std::string actual(Cipher::instance().md5("a"));
CPPUNIT_ASSERT_EQUAL(expected, actual);
}
@@ -86,8 +91,10 @@ CipherTest::testMd5_2(void)
void
CipherTest::testMd5_3(void)
{
+ LOG("CipherTest::testMd5_3()");
+
const std::string expected("900150983cd24fb0d6963f7d28e17f72");
- std::string actual(Cipher::instance().md5("abc"));
+ const std::string actual(Cipher::instance().md5("abc"));
CPPUNIT_ASSERT_EQUAL(expected, actual);
}
@@ -99,8 +106,10 @@ CipherTest::testMd5_3(void)
void
CipherTest::testMd5_4(void)
{
+ LOG("CipherTest::testMd5_4()");
+
const std::string expected("f96b697d7cb7938d525a2f31aaf161d0");
- std::string actual(Cipher::instance().md5("message digest"));
+ const std::string actual(Cipher::instance().md5("message digest"));
CPPUNIT_ASSERT_EQUAL(expected, actual);
}
@@ -112,8 +121,11 @@ CipherTest::testMd5_4(void)
void
CipherTest::testMd5_5(void)
{
+ LOG("CipherTest::testMd5_6()");
+
const std::string expected("c3fcd3d76192e4007dfb496cca67e13b");
- std::string actual(Cipher::instance().md5("abcdefghijklmnopqrstuvwxyz"));
+ const std::string actual(
+ Cipher::instance().md5("abcdefghijklmnopqrstuvwxyz"));
CPPUNIT_ASSERT_EQUAL(expected, actual);
}
@@ -125,12 +137,14 @@ CipherTest::testMd5_5(void)
void
CipherTest::testMd5_6(void)
{
+ LOG("CipherTest::testMd5_6()");
+
const std::string expected("d174ab98d277d9f5a5611c2c9f419d9f");
std::string s("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
s += "abcdefghijklmnopqrstuvwxyz";
s += "0123456789";
- std::string actual(Cipher::instance().md5(s));
+ const std::string actual(Cipher::instance().md5(s));
CPPUNIT_ASSERT_EQUAL(expected, actual);
}
@@ -142,13 +156,15 @@ CipherTest::testMd5_6(void)
void
CipherTest::testMd5_7(void)
{
+ LOG("CipherTest::testMd5_7()");
+
const std::string expected("57edf4a22be3c955ac49da2e2107b67a");
std::string s;
for (int i = 0; i < 8; ++i) {
s += "1234567890";
}
- std::string actual(Cipher::instance().md5(s));
+ const std::string actual(Cipher::instance().md5(s));
CPPUNIT_ASSERT_EQUAL(expected, actual);
}
diff --git a/src/tests/testdataprovider.cpp b/src/tests/testdataprovider.cpp
index 06a2b0e..dd5aff4 100644
--- a/src/tests/testdataprovider.cpp
+++ b/src/tests/testdataprovider.cpp
@@ -30,6 +30,7 @@
#endif
#include "../dal/dataproviderfactory.h"
+#include "../utils/logger.h"
#include "testdataprovider.h"
@@ -97,6 +98,8 @@ DataProviderTest::tearDown(void)
void
DataProviderTest::testConnection1(void)
{
+ LOG("DataProviderTest::testConnection1()");
+
#ifdef SQLITE_SUPPORT
std::string dbFile(mDbName);
dbFile += ".db";
@@ -116,6 +119,8 @@ DataProviderTest::testConnection1(void)
void
DataProviderTest::testCreateTable1(void)
{
+ LOG("DataProviderTest::testCreateTable1()");
+
#ifdef SQLITE_SUPPORT
std::string dbFile(mDbName);
dbFile += ".db";
@@ -141,6 +146,8 @@ DataProviderTest::testCreateTable1(void)
void
DataProviderTest::testCreateTable2(void)
{
+ LOG("DataProviderTest::testCreateTable2()");
+
#ifdef SQLITE_SUPPORT
std::string dbFile(mDbName);
dbFile += ".db";
@@ -164,6 +171,8 @@ DataProviderTest::testCreateTable2(void)
void
DataProviderTest::testInsert1(void)
{
+ LOG("DataProviderTest::testInsert1()");
+
#ifdef SQLITE_SUPPORT
std::string dbFile(mDbName);
dbFile += ".db";
@@ -193,6 +202,8 @@ DataProviderTest::testInsert1(void)
void
DataProviderTest::testInsert2(void)
{
+ LOG("DataProviderTest::testInsert2()");
+
#ifdef SQLITE_SUPPORT
std::string dbFile(mDbName);
dbFile += ".db";
@@ -216,6 +227,8 @@ DataProviderTest::testInsert2(void)
void
DataProviderTest::testFetch1(void)
{
+ LOG("DataProviderTest::testFetch1()");
+
#ifdef SQLITE_SUPPORT
std::string dbFile(mDbName);
dbFile += ".db";
@@ -249,6 +262,8 @@ DataProviderTest::testFetch1(void)
void
DataProviderTest::testDisconnection1(void)
{
+ LOG("DataProviderTest::testDisconnection1()");
+
#ifdef SQLITE_SUPPORT
std::string dbFile(mDbName);
dbFile += ".db";
@@ -271,6 +286,8 @@ DataProviderTest::testDisconnection1(void)
void
DataProviderTest::testDisconnection2(void)
{
+ LOG("DataProviderTest::testDisconnection2()");
+
mDb->disconnect();
CPPUNIT_ASSERT(!mDb->isConnected());
}
diff --git a/src/tests/testrecordset.cpp b/src/tests/testrecordset.cpp
index 26a9e01..df9a710 100644
--- a/src/tests/testrecordset.cpp
+++ b/src/tests/testrecordset.cpp
@@ -23,6 +23,7 @@
#include <sstream>
+#include "../utils/logger.h"
#include "testrecordset.h"
@@ -73,6 +74,8 @@ RecordSetTest::tearDown(void)
void
RecordSetTest::testRows1(void)
{
+ LOG("RecordSetTest::testRows1()");
+
CPPUNIT_ASSERT_EQUAL((unsigned int) 0, mEmptyRs.rows());
}
@@ -83,6 +86,8 @@ RecordSetTest::testRows1(void)
void
RecordSetTest::testRows2(void)
{
+ LOG("RecordSetTest::testRows2()");
+
CPPUNIT_ASSERT_EQUAL((unsigned int) 2, mNonEmptyRs.rows());
}
@@ -93,6 +98,8 @@ RecordSetTest::testRows2(void)
void
RecordSetTest::testCols1(void)
{
+ LOG("RecordSetTest::testCols1()");
+
CPPUNIT_ASSERT_EQUAL((unsigned int) 0, mEmptyRs.cols());
}
@@ -103,6 +110,8 @@ RecordSetTest::testCols1(void)
void
RecordSetTest::testCols2(void)
{
+ LOG("RecordSetTest::testCols2()");
+
CPPUNIT_ASSERT_EQUAL((unsigned int) 2, mNonEmptyRs.cols());
}
@@ -113,6 +122,8 @@ RecordSetTest::testCols2(void)
void
RecordSetTest::testIsEmpty1(void)
{
+ LOG("RecordSetTest::testIsEmpty1()");
+
CPPUNIT_ASSERT(mEmptyRs.isEmpty());
}
@@ -123,6 +134,8 @@ RecordSetTest::testIsEmpty1(void)
void
RecordSetTest::testIsEmpty2(void)
{
+ LOG("RecordSetTest::testIsEmpty2()");
+
CPPUNIT_ASSERT(!mNonEmptyRs.isEmpty());
}
@@ -133,6 +146,8 @@ RecordSetTest::testIsEmpty2(void)
void
RecordSetTest::testOperator1(void)
{
+ LOG("RecordSetTest::testOperator1()");
+
// this should throw std::invalid_argument.
mEmptyRs(0, 0);
}
@@ -145,7 +160,9 @@ RecordSetTest::testOperator1(void)
void
RecordSetTest::testOperator2(void)
{
- std::string value("mike");
+ LOG("RecordSetTest::testRows1()");
+
+ const std::string value("mike");
CPPUNIT_ASSERT_EQUAL(value, mNonEmptyRs(1, 1));
}
@@ -159,6 +176,8 @@ RecordSetTest::testOperator2(void)
void
RecordSetTest::testOperator3(void)
{
+ LOG("RecordSetTest::testOperator3()");
+
// this should throw std::out_of_range.
mNonEmptyRs(2, 2);
}
@@ -171,7 +190,9 @@ RecordSetTest::testOperator3(void)
void
RecordSetTest::testOperator4(void)
{
- std::string value("1");
+ LOG("RecordSetTest::testOperator4()");
+
+ const std::string value("1");
CPPUNIT_ASSERT_EQUAL(value, mNonEmptyRs(0, "id"));
}
@@ -184,6 +205,8 @@ RecordSetTest::testOperator4(void)
void
RecordSetTest::testOperator5(void)
{
+ LOG("RecordSetTest::testOperator5()");
+
// this should throw std::out_of_range.
mNonEmptyRs(3, "id");
}
@@ -196,6 +219,8 @@ RecordSetTest::testOperator5(void)
void
RecordSetTest::testOperator6(void)
{
+ LOG("RecordSetTest::testOperator6()");
+
// this should throw std::invalid_argument.
mNonEmptyRs(1, "noname");
}
@@ -207,7 +232,9 @@ RecordSetTest::testOperator6(void)
void
RecordSetTest::testOutputStream1(void)
{
- std::string emptyStr;
+ LOG("RecordSetTest::testOutputStream1()");
+
+ const std::string emptyStr;
std::ostringstream os;
os << mEmptyRs;
@@ -222,6 +249,8 @@ RecordSetTest::testOutputStream1(void)
void
RecordSetTest::testOutputStream2(void)
{
+ LOG("RecordSetTest::testOutputStream2()");
+
std::ostringstream os1;
os1 << "|id|name|" << std::endl << std::endl
<< "|1|john|" << std::endl
@@ -240,8 +269,10 @@ RecordSetTest::testOutputStream2(void)
void
RecordSetTest::testAdd1(void)
{
- std::string id("3");
- std::string name("elena");
+ LOG("RecordSetTest::testAdd1()");
+
+ const std::string id("3");
+ const std::string name("elena");
Row r;
r.push_back(id);
@@ -262,6 +293,8 @@ RecordSetTest::testAdd1(void)
void
RecordSetTest::testAdd2(void)
{
+ LOG("RecordSetTest::testAdd2()");
+
Row r;
r.push_back("4");
@@ -277,6 +310,8 @@ RecordSetTest::testAdd2(void)
void
RecordSetTest::testAdd3(void)
{
+ LOG("RecordSetTest::testAdd3()");
+
Row r;
r.push_back("5");
diff --git a/src/tests/testsmain.cpp b/src/tests/testsmain.cpp
index 70cdc18..2123760 100644
--- a/src/tests/testsmain.cpp
+++ b/src/tests/testsmain.cpp
@@ -26,6 +26,8 @@
#include <physfs.h>
+#include "../utils/logger.h"
+
/**
* Notes:
@@ -45,6 +47,9 @@ int main(int argc, char* argv[])
PHYSFS_addToSearchPath(".", 1);
PHYSFS_setWriteDir(".");
+ // initialize the logger.
+ tmwserv::utils::Logger::instance().setTimestamp(false);
+
using namespace CppUnit;
// get the top level suite from the registry.
diff --git a/src/tests/teststorage.cpp b/src/tests/teststorage.cpp
index 7a7cb7f..977c294 100644
--- a/src/tests/teststorage.cpp
+++ b/src/tests/teststorage.cpp
@@ -38,6 +38,7 @@
#include "../utils/cipher.h"
#include "../utils/functors.h"
+#include "../utils/logger.h"
#include "../dalstoragesql.h"
#include "../storage.h"
#include "teststorage.h"
@@ -99,6 +100,8 @@ StorageTest::tearDown(void)
void
StorageTest::testGetAccount1(void)
{
+ LOG("StorageTest::testGetAccount1()");
+
Storage& myStorage = Storage::instance(mStorageName);
CPPUNIT_ASSERT(myStorage.isOpen());
@@ -124,6 +127,8 @@ StorageTest::testGetAccount1(void)
void
StorageTest::testGetAccount2(void)
{
+ LOG("StorageTest::testGetAccount2()");
+
Storage& myStorage = Storage::instance(mStorageName);
if (!myStorage.isOpen()) {
@@ -142,6 +147,8 @@ StorageTest::testGetAccount2(void)
void
StorageTest::testAddAccount1(void)
{
+ LOG("StorageTest::testAddAccount1()");
+
Storage& myStorage = Storage::instance(mStorageName);
if (!myStorage.isOpen()) {
@@ -151,58 +158,14 @@ StorageTest::testAddAccount1(void)
// TODO: when addAccount will throw exceptions, test the exceptions
// thrown.
// nothing should happen at the moment.
- myStorage.addAccount(NULL);
+ AccountPtr nullAccount(0);
+ myStorage.addAccount(nullAccount);
myStorage.flush();
-#if defined (MYSQL_SUPPORT) || defined (POSTGRESQL_SUPPORT) || \
- defined (SQLITE_SUPPORT)
-
- using namespace tmwserv::dal;
-
- std::auto_ptr<DataProvider> db(DataProviderFactory::createDataProvider());
-
- try {
-#ifdef SQLITE_SUPPORT
- std::string dbFile(mStorageName);
- dbFile += ".db";
- db->connect(dbFile, mStorageUser, mStorageUserPassword);
-#else
- db->connect(mStorageName, mStorageUser, mStorageUserPassword);
-#endif
-
- std::string sql("select * from ");
- sql += ACCOUNTS_TBL_NAME;
- sql += ";";
- const RecordSet& rs = db->execSql(sql);
-
- CPPUNIT_ASSERT(rs.rows() == 3);
-
- const std::string frodo("frodo");
- const std::string merry("merry");
- const std::string pippin("pippin");
-
- CPPUNIT_ASSERT_EQUAL(frodo, rs(0, "username"));
- CPPUNIT_ASSERT_EQUAL(merry, rs(1, "username"));
- CPPUNIT_ASSERT_EQUAL(pippin, rs(2, "username"));
-
- db->disconnect();
- }
- catch (const DbConnectionFailure& e) {
- CPPUNIT_FAIL(e.what());
- }
- catch (const DbSqlQueryExecFailure& e) {
- CPPUNIT_FAIL(e.what());
- }
- catch (const DbDisconnectionFailure& e) {
- CPPUNIT_FAIL(e.what());
- }
- catch (const std::exception& e) {
- CPPUNIT_FAIL(e.what());
- }
- catch (...) {
- CPPUNIT_FAIL("unexpected exception");
- }
-#endif
+ // check the database.
+ Checks checks;
+ checks.set(CHK_DEFAULT_ACCOUNTS);
+ checkDb(checks);
}
@@ -212,6 +175,8 @@ StorageTest::testAddAccount1(void)
void
StorageTest::testAddAccount2(void)
{
+ LOG("StorageTest::testAddAccount2()");
+
Storage& myStorage = Storage::instance(mStorageName);
if (!myStorage.isOpen()) {
@@ -219,91 +184,29 @@ StorageTest::testAddAccount2(void)
}
// prepare new account.
- RawStatistics stats;
- stats.strength = 1;
- stats.agility = 1;
- stats.vitality = 1;
- stats.intelligence = 1;
- stats.dexterity = 1;
- stats.luck = 1;
+ RawStatistics stats = {1, 1, 1, 1, 1, 1};
const std::string sam1("sam1");
const std::string sam2("sam2");
- Being* b1 = new Being(sam1, GENDER_MALE, 0, 0, stats);
- Being* b2 = new Being(sam2, GENDER_MALE, 0, 0, stats);
+ BeingPtr b1(new Being(sam1, GENDER_MALE, 0, 0, stats));
+ BeingPtr b2(new Being(sam2, GENDER_MALE, 0, 0, stats));
Beings characters;
characters.push_back(b1);
characters.push_back(b2);
const std::string sam("sam");
- Account* acc = new Account(sam, sam, "sam@domain", characters);
+ AccountPtr acc(new Account(sam, sam, "sam@domain", characters));
// TODO: when addAccount will throw exceptions, test the exceptions
// thrown.
myStorage.addAccount(acc);
myStorage.flush();
-#if defined (MYSQL_SUPPORT) || defined (POSTGRESQL_SUPPORT) || \
- defined (SQLITE_SUPPORT)
-
- using namespace tmwserv::dal;
-
- std::auto_ptr<DataProvider> db(DataProviderFactory::createDataProvider());
-
- try {
-#ifdef SQLITE_SUPPORT
- std::string dbFile(mStorageName);
- dbFile += ".db";
- db->connect(dbFile, mStorageUser, mStorageUserPassword);
-#else
- db->connect(mStorageName, mStorageUser, mStorageUserPassword);
-#endif
-
- std::string sql("select * from ");
- sql += ACCOUNTS_TBL_NAME;
- sql += ";";
- const RecordSet& rs = db->execSql(sql);
-
- CPPUNIT_ASSERT(rs.rows() == 4);
-
- const std::string frodo("frodo");
- const std::string merry("merry");
- const std::string pippin("pippin");
-
- CPPUNIT_ASSERT_EQUAL(frodo, rs(0, "username"));
- CPPUNIT_ASSERT_EQUAL(merry, rs(1, "username"));
- CPPUNIT_ASSERT_EQUAL(pippin, rs(2, "username"));
- CPPUNIT_ASSERT_EQUAL(sam, rs(3, "username"));
-
- sql = "select * from ";
- sql += CHARACTERS_TBL_NAME;
- sql += " where user_id = 4;";
-
- db->execSql(sql);
-
- CPPUNIT_ASSERT(rs.rows() == 2);
-
- CPPUNIT_ASSERT_EQUAL(sam1, rs(0, "name"));
- CPPUNIT_ASSERT_EQUAL(sam2, rs(1, "name"));
-
- db->disconnect();
- }
- catch (const DbConnectionFailure& e) {
- CPPUNIT_FAIL(e.what());
- }
- catch (const DbSqlQueryExecFailure& e) {
- CPPUNIT_FAIL(e.what());
- }
- catch (const DbDisconnectionFailure& e) {
- CPPUNIT_FAIL(e.what());
- }
- catch (const std::exception& e) {
- CPPUNIT_FAIL(e.what());
- }
- catch (...) {
- CPPUNIT_FAIL("unexpected exception");
- }
-#endif
+ // check the database.
+ Checks checks;
+ checks.set(CHK_NEW_ADDED_ACCOUNT);
+ checks.set(CHK_CHARACTERS_4);
+ checkDb(checks);
}
@@ -313,6 +216,8 @@ StorageTest::testAddAccount2(void)
void
StorageTest::testUpdAccount1(void)
{
+ LOG("StorageTest::testUpdAccount1()");
+
Storage& myStorage = Storage::instance(mStorageName);
CPPUNIT_ASSERT(myStorage.isOpen());
@@ -322,18 +227,12 @@ StorageTest::testUpdAccount1(void)
Account* account = myStorage.getAccount(name);
// create new characters.
- RawStatistics stats;
- stats.strength = 1;
- stats.agility = 1;
- stats.vitality = 1;
- stats.intelligence = 1;
- stats.dexterity = 1;
- stats.luck = 1;
+ RawStatistics stats = {1, 1, 1, 1, 1, 1};
const std::string sam1("sam1");
const std::string sam2("sam2");
- Being* b1 = new Being(sam1, GENDER_MALE, 0, 0, stats);
- Being* b2 = new Being(sam2, GENDER_MALE, 0, 0, stats);
+ BeingPtr b1(new Being(sam1, GENDER_MALE, 0, 0, stats));
+ BeingPtr b2(new Being(sam2, GENDER_MALE, 0, 0, stats));
// add the characters to the account.
account->addCharacter(b1);
@@ -342,66 +241,11 @@ StorageTest::testUpdAccount1(void)
// update the database.
myStorage.flush();
-#if defined (MYSQL_SUPPORT) || defined (POSTGRESQL_SUPPORT) || \
- defined (SQLITE_SUPPORT)
-
- using namespace tmwserv::dal;
-
- std::auto_ptr<DataProvider> db(DataProviderFactory::createDataProvider());
-
- try {
-#ifdef SQLITE_SUPPORT
- std::string dbFile(mStorageName);
- dbFile += ".db";
- db->connect(dbFile, mStorageUser, mStorageUserPassword);
-#else
- db->connect(mStorageName, mStorageUser, mStorageUserPassword);
-#endif
-
- std::string sql("select * from ");
- sql += ACCOUNTS_TBL_NAME;
- sql += ";";
- const RecordSet& rs = db->execSql(sql);
-
- CPPUNIT_ASSERT(rs.rows() == 3);
-
- const std::string frodo("frodo");
- const std::string merry("merry");
- const std::string pippin("pippin");
-
- CPPUNIT_ASSERT_EQUAL(frodo, rs(0, "username"));
- CPPUNIT_ASSERT_EQUAL(merry, rs(1, "username"));
- CPPUNIT_ASSERT_EQUAL(pippin, rs(2, "username"));
-
- sql = "select * from ";
- sql += CHARACTERS_TBL_NAME;
- sql += " where user_id = 1;";
-
- db->execSql(sql);
-
- CPPUNIT_ASSERT(rs.rows() == 2);
-
- CPPUNIT_ASSERT_EQUAL(sam1, rs(0, "name"));
- CPPUNIT_ASSERT_EQUAL(sam2, rs(1, "name"));
-
- db->disconnect();
- }
- catch (const DbConnectionFailure& e) {
- CPPUNIT_FAIL(e.what());
- }
- catch (const DbSqlQueryExecFailure& e) {
- CPPUNIT_FAIL(e.what());
- }
- catch (const DbDisconnectionFailure& e) {
- CPPUNIT_FAIL(e.what());
- }
- catch (const std::exception& e) {
- CPPUNIT_FAIL(e.what());
- }
- catch (...) {
- CPPUNIT_FAIL("unexpected exception");
- }
-#endif
+ // check the database.
+ Checks checks;
+ checks.set(CHK_DEFAULT_ACCOUNTS);
+ checks.set(CHK_CHARACTERS_1);
+ checkDb(checks);
}
@@ -412,6 +256,8 @@ StorageTest::testUpdAccount1(void)
void
StorageTest::testUpdAccount2(void)
{
+ LOG("StorageTest::testUpdAccount2()");
+
Storage& myStorage = Storage::instance(mStorageName);
CPPUNIT_ASSERT(myStorage.isOpen());
@@ -421,18 +267,12 @@ StorageTest::testUpdAccount2(void)
Account* account = myStorage.getAccount(name);
// create new characters.
- RawStatistics stats;
- stats.strength = 1;
- stats.agility = 1;
- stats.vitality = 1;
- stats.intelligence = 1;
- stats.dexterity = 1;
- stats.luck = 1;
+ RawStatistics stats = {1, 1, 1, 1, 1, 1};
const std::string sam1("sam1");
const std::string sam2("sam2");
- Being* b1 = new Being(sam1, GENDER_MALE, 0, 0, stats);
- Being* b2 = new Being(sam2, GENDER_MALE, 0, 0, stats);
+ BeingPtr b1(new Being(sam1, GENDER_MALE, 0, 0, stats));
+ BeingPtr b2(new Being(sam2, GENDER_MALE, 0, 0, stats));
// add the characters to the account.
account->addCharacter(b1);
@@ -528,59 +368,151 @@ StorageTest::testUpdAccount2(void)
void
StorageTest::testDelAccount1(void)
{
+ LOG("StorageTest::testDelAccount1()");
+
Storage& myStorage = Storage::instance(mStorageName);
CPPUNIT_ASSERT(myStorage.isOpen());
myStorage.delAccount("frodo");
-#if defined (MYSQL_SUPPORT) || defined (POSTGRESQL_SUPPORT) || \
- defined (SQLITE_SUPPORT)
+ // check the database.
+ Checks checks;
+ checks.set(CHK_1ST_ACCOUNT_DELETED);
+ checkDb(checks);
+}
- using namespace tmwserv::dal;
- std::auto_ptr<DataProvider> db(DataProviderFactory::createDataProvider());
+/**
+ * Test deleting an account that was added to the storage but not
+ * yet persisted.
+ */
+void
+StorageTest::testDelAccount2(void)
+{
+ LOG("StorageTest::testDelAccount2()");
- try {
-#ifdef SQLITE_SUPPORT
- std::string dbFile(mStorageName);
- dbFile += ".db";
- db->connect(dbFile, mStorageUser, mStorageUserPassword);
-#else
- db->connect(mStorageName, mStorageUser, mStorageUserPassword);
-#endif
+ Storage& myStorage = Storage::instance(mStorageName);
- std::string sql("select * from ");
- sql += ACCOUNTS_TBL_NAME;
- sql += ";";
- const RecordSet& rs = db->execSql(sql);
+ if (!myStorage.isOpen()) {
+ CPPUNIT_FAIL("the storage is not opened.");
+ }
- CPPUNIT_ASSERT(rs.rows() == 2);
+ // prepare new account.
+ RawStatistics stats = {1, 1, 1, 1, 1, 1};
- const std::string merry("merry");
- const std::string pippin("pippin");
+ const std::string sam1("sam1");
+ const std::string sam2("sam2");
+ BeingPtr b1(new Being(sam1, GENDER_MALE, 0, 0, stats));
+ BeingPtr b2(new Being(sam2, GENDER_MALE, 0, 0, stats));
+ Beings characters;
+ characters.push_back(b1);
+ characters.push_back(b2);
- CPPUNIT_ASSERT_EQUAL(merry, rs(0, "username"));
- CPPUNIT_ASSERT_EQUAL(pippin, rs(1, "username"));
+ const std::string sam("sam");
+ AccountPtr acc(new Account(sam, sam, "sam@domain", characters));
- db->disconnect();
- }
- catch (const DbConnectionFailure& e) {
- CPPUNIT_FAIL(e.what());
- }
- catch (const DbSqlQueryExecFailure& e) {
- CPPUNIT_FAIL(e.what());
- }
- catch (const DbDisconnectionFailure& e) {
- CPPUNIT_FAIL(e.what());
+ myStorage.addAccount(acc);
+ myStorage.delAccount(sam);
+
+ // nothing should be added to the database.
+ myStorage.flush();
+
+ // check the database.
+ Checks checks;
+ checks.set(CHK_DEFAULT_ACCOUNTS);
+ checkDb(checks);
+}
+
+
+/**
+ * Test deleting an account that exists in the database and loaded
+ * in memory.
+ */
+void
+StorageTest::testDelAccount3(void)
+{
+ LOG("StorageTest::testDelAccount3()");
+
+ Storage& myStorage = Storage::instance(mStorageName);
+
+ if (!myStorage.isOpen()) {
+ CPPUNIT_FAIL("the storage is not opened.");
}
- catch (const std::exception& e) {
- CPPUNIT_FAIL(e.what());
+
+ // get an existing account.
+ const std::string name("frodo");
+ Account* account = myStorage.getAccount(name);
+
+ CPPUNIT_ASSERT_EQUAL(name, account->getName());
+
+ myStorage.delAccount(name);
+ myStorage.flush();
+
+ // check the database.
+ Checks checks;
+ checks.set(CHK_1ST_ACCOUNT_DELETED);
+ checkDb(checks);
+}
+
+
+/**
+ * Test deleting an account that does not exist.
+ */
+void
+StorageTest::testDelAccount4(void)
+{
+ LOG("StorageTest::testDelAccount4()");
+
+ Storage& myStorage = Storage::instance(mStorageName);
+
+ if (!myStorage.isOpen()) {
+ CPPUNIT_FAIL("the storage is not opened.");
}
- catch (...) {
- CPPUNIT_FAIL("unexpected exception");
+
+ // nothing should happen nor modified in the database.
+ myStorage.delAccount("xxx");
+ myStorage.flush();
+
+ // check the database.
+ Checks checks;
+ checks.set(CHK_DEFAULT_ACCOUNTS);
+ checkDb(checks);
+}
+
+
+/**
+ * Test deleting twice an account that exists in the database and
+ * loaded in memory.
+ */
+void
+StorageTest::testDelAccount5(void)
+{
+ LOG("StorageTest::testDelAccount5()");
+
+ Storage& myStorage = Storage::instance(mStorageName);
+
+ if (!myStorage.isOpen()) {
+ CPPUNIT_FAIL("the storage is not opened.");
}
-#endif
+
+ // get an existing account.
+ const std::string name("frodo");
+ Account* account = myStorage.getAccount(name);
+
+ CPPUNIT_ASSERT_EQUAL(name, account->getName());
+
+ myStorage.delAccount(name);
+ myStorage.flush();
+
+ // delete it again.
+ myStorage.delAccount(name);
+ myStorage.flush();
+
+ // check the database.
+ Checks checks;
+ checks.set(CHK_1ST_ACCOUNT_DELETED);
+ checkDb(checks);
}
@@ -757,3 +689,110 @@ StorageTest::insertAccount(std::auto_ptr<DataProvider>& db,
db->execSql(sql.str());
}
+
+
+/**
+ * Check the state of the database.
+ */
+void
+StorageTest::checkDb(const Checks& what)
+{
+#if defined (MYSQL_SUPPORT) || defined (POSTGRESQL_SUPPORT) || \
+ defined (SQLITE_SUPPORT)
+
+ using namespace tmwserv::dal;
+
+ std::auto_ptr<DataProvider> db(DataProviderFactory::createDataProvider());
+
+ try {
+#ifdef SQLITE_SUPPORT
+ std::string dbFile(mStorageName);
+ dbFile += ".db";
+ db->connect(dbFile, mStorageUser, mStorageUserPassword);
+#else
+ db->connect(mStorageName, mStorageUser, mStorageUserPassword);
+#endif
+
+ std::string sql("select * from ");
+ sql += ACCOUNTS_TBL_NAME;
+ sql += ";";
+ const RecordSet& rs = db->execSql(sql);
+
+ if (what[CHK_DEFAULT_ACCOUNTS]) {
+ CPPUNIT_ASSERT(rs.rows() == 3);
+
+ const std::string frodo("frodo");
+ const std::string merry("merry");
+ const std::string pippin("pippin");
+
+ CPPUNIT_ASSERT_EQUAL(frodo, rs(0, "username"));
+ CPPUNIT_ASSERT_EQUAL(merry, rs(1, "username"));
+ CPPUNIT_ASSERT_EQUAL(pippin, rs(2, "username"));
+ }
+
+ if (what[CHK_1ST_ACCOUNT_DELETED]) {
+ CPPUNIT_ASSERT(rs.rows() == 2);
+
+ const std::string merry("merry");
+ const std::string pippin("pippin");
+
+ CPPUNIT_ASSERT_EQUAL(merry, rs(0, "username"));
+ CPPUNIT_ASSERT_EQUAL(pippin, rs(1, "username"));
+ }
+
+ if (what[CHK_NEW_ADDED_ACCOUNT]) {
+ CPPUNIT_ASSERT(rs.rows() == 4);
+
+ const std::string frodo("frodo");
+ const std::string merry("merry");
+ const std::string pippin("pippin");
+ const std::string sam("sam");
+
+ CPPUNIT_ASSERT_EQUAL(frodo, rs(0, "username"));
+ CPPUNIT_ASSERT_EQUAL(merry, rs(1, "username"));
+ CPPUNIT_ASSERT_EQUAL(pippin, rs(2, "username"));
+ CPPUNIT_ASSERT_EQUAL(sam, rs(3, "username"));
+ }
+
+ if (what[CHK_CHARACTERS_1]) {
+ sql = "select * from ";
+ sql += CHARACTERS_TBL_NAME;
+ sql += " where user_id = 1;";
+ }
+ else if (what[CHK_CHARACTERS_4]) {
+ sql = "select * from ";
+ sql += CHARACTERS_TBL_NAME;
+ sql += " where user_id = 4;";
+ }
+
+ if (what[CHK_CHARACTERS_1] || what[CHK_CHARACTERS_4]) {
+ db->execSql(sql);
+
+ CPPUNIT_ASSERT(rs.rows() == 2);
+
+ const std::string sam1("sam1");
+ const std::string sam2("sam2");
+
+ CPPUNIT_ASSERT_EQUAL(sam1, rs(0, "name"));
+ CPPUNIT_ASSERT_EQUAL(sam2, rs(1, "name"));
+ }
+
+ db->disconnect();
+ }
+ catch (const DbConnectionFailure& e) {
+ CPPUNIT_FAIL(e.what());
+ }
+ catch (const DbSqlQueryExecFailure& e) {
+ CPPUNIT_FAIL(e.what());
+ }
+ catch (const DbDisconnectionFailure& e) {
+ CPPUNIT_FAIL(e.what());
+ }
+ catch (const std::exception& e) {
+ CPPUNIT_FAIL(e.what());
+ }
+ catch (...) {
+ CPPUNIT_FAIL("unexpected exception");
+ }
+#endif
+}
diff --git a/src/tests/teststorage.h b/src/tests/teststorage.h
index da1eae8..8eef60c 100644
--- a/src/tests/teststorage.h
+++ b/src/tests/teststorage.h
@@ -25,6 +25,7 @@
#define _TMWSERV_TEST_STORAGE_H_
+#include <bitset>
#include <vector>
#include <cppunit/extensions/HelperMacros.h>
@@ -59,6 +60,10 @@ class StorageTest: public CppUnit::TestFixture
CPPUNIT_TEST(testUpdAccount1);
CPPUNIT_TEST(testUpdAccount2);
CPPUNIT_TEST(testDelAccount1);
+ CPPUNIT_TEST(testDelAccount2);
+ CPPUNIT_TEST(testDelAccount3);
+ CPPUNIT_TEST(testDelAccount4);
+ CPPUNIT_TEST(testDelAccount5);
CPPUNIT_TEST_SUITE_END();
@@ -129,6 +134,37 @@ class StorageTest: public CppUnit::TestFixture
testDelAccount1(void);
+ /**
+ * Test deleting an account that was added to the storage but not
+ * yet persisted.
+ */
+ void
+ testDelAccount2(void);
+
+
+ /**
+ * Test deleting an account that exists in the database and loaded
+ * in memory.
+ */
+ void
+ testDelAccount3(void);
+
+
+ /**
+ * Test deleting an account that does not exist.
+ */
+ void
+ testDelAccount4(void);
+
+
+ /**
+ * Test deleting twice an account that exists in the database and
+ * loaded in memory.
+ */
+ void
+ testDelAccount5(void);
+
+
private:
/**
* Initialize the storage.
@@ -166,6 +202,35 @@ class StorageTest: public CppUnit::TestFixture
const std::string& name);
+ /**
+ * Enumeration type for the bits.
+ * Each bit represents a particular check.
+ */
+ enum CheckValues {
+ CHK_DEFAULT_ACCOUNTS,
+ CHK_1ST_ACCOUNT_DELETED,
+ CHK_NEW_ADDED_ACCOUNT,
+ CHK_CHARACTERS_1,
+ CHK_CHARACTERS_4,
+ NUM_CHECKS
+ };
+
+
+ /**
+ * Type definition for the checks.
+ */
+ typedef std::bitset<NUM_CHECKS> Checks;
+
+
+ /**
+ * Check the state of the database.
+ *
+ * @param what bitmask that contains information about what to check.
+ */
+ void
+ checkDb(const Checks& what);
+
+
private:
static std::string mStorageName; /**< name of the storage */
static std::string mStorageUser; /**< storage user */
diff --git a/src/utils/countedptr.h b/src/utils/countedptr.h
new file mode 100644
index 0000000..f8dbcd5
--- /dev/null
+++ b/src/utils/countedptr.h
@@ -0,0 +1,163 @@
+/*
+ * The Mana World Server
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with The Mana World; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+
+#ifndef _TMWSERV_COUNTED_PTR_H_
+#define _TMWSERV_COUNTED_PTR_H_
+
+
+namespace tmwserv
+{
+namespace utils
+{
+
+
+/**
+ * Class for counted reference semantics. It deletes the object to which it
+ * refers when the last CountedPtr that refers to it is destroyed.
+ *
+ * @copyright Nicolai M. Josuttis
+ * (The C++ standard library: a tutorial and reference).
+ *
+ * Notes from kindjal:
+ * - should we use the Boost's shared_ptr instead?
+ * - reference-counted smart pointers are very useful if we want automatic
+ * memory management with STL containers (e.g. vector of pointers).
+ */
+template <typename T>
+class CountedPtr
+{
+ public:
+ /**
+ * Constructor.
+ * Initialize pointer with existing pointer.
+ *
+ * It is required that the pointer p is a return value of new.
+ */
+ explicit
+ CountedPtr(T* p = 0)
+ : ptr(p),
+ count(new long(1))
+ {
+ // NOOP
+ }
+
+
+ /**
+ * Destructor.
+ * Delete value if this was the last owner.
+ */
+ ~CountedPtr(void)
+ throw()
+ {
+ dispose();
+ }
+
+
+ /**
+ * Copy pointer (one more owner).
+ */
+ CountedPtr(const CountedPtr<T>& p)
+ throw()
+ : ptr(p.ptr),
+ count(p.count)
+ {
+ ++*count;
+ }
+
+
+ /**
+ * Assignment (unshare old and share new value).
+ */
+ CountedPtr<T>&
+ operator=(const CountedPtr<T>& p)
+ throw()
+ {
+ if (this != &p) {
+ dispose();
+ ptr = p.ptr;
+ count = p.count;
+ ++*count;
+ }
+
+ return *this;
+ }
+
+
+ /**
+ * Access the value to which the pointer refers.
+ */
+ T&
+ operator*(void) const
+ throw()
+ {
+ return *ptr;
+ }
+
+
+ /**
+ * Access the pointer.
+ */
+ T*
+ operator->(void) const
+ throw()
+ {
+ return ptr;
+ }
+
+
+ /**
+ * Get the pointer (mimic std::auto_ptr::get()).
+ */
+ T*
+ get(void) const
+ throw()
+ {
+ return ptr;
+ }
+
+
+ private:
+ /**
+ * Manage the counter and free memory.
+ */
+ void
+ dispose(void)
+ {
+ if (--*count == 0) {
+ delete count;
+ delete ptr;
+ }
+ }
+
+
+ private:
+ T* ptr; /**< pointer to the value */
+ long* count; /**< shared number of owners */
+};
+
+
+} // namespace utils
+} // namespace tmwserv
+
+
+#endif // _TMWSERV_COUNTED_PTR_H_