diff options
Diffstat (limited to 'src/tests')
-rw-r--r-- | src/tests/testaccount.cpp | 207 | ||||
-rw-r--r-- | src/tests/testaccount.h | 116 | ||||
-rw-r--r-- | src/tests/testcipher.cpp | 154 | ||||
-rw-r--r-- | src/tests/testcipher.h | 115 | ||||
-rw-r--r-- | src/tests/testdataprovider.cpp | 334 | ||||
-rw-r--r-- | src/tests/testdataprovider.h | 156 | ||||
-rw-r--r-- | src/tests/testrecordset.cpp | 285 | ||||
-rw-r--r-- | src/tests/testrecordset.h | 215 | ||||
-rw-r--r-- | src/tests/testsmain.cpp | 65 | ||||
-rw-r--r-- | src/tests/teststorage.cpp | 310 | ||||
-rw-r--r-- | src/tests/teststorage.h | 132 |
11 files changed, 2089 insertions, 0 deletions
diff --git a/src/tests/testaccount.cpp b/src/tests/testaccount.cpp new file mode 100644 index 00000000..a4061164 --- /dev/null +++ b/src/tests/testaccount.cpp @@ -0,0 +1,207 @@ +/* + * 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$ + */ + + +#include "testaccount.h" + + +// register the fixture into the 'registry' +CPPUNIT_TEST_SUITE_REGISTRATION(AccountTest); + + +using namespace tmwserv; + + +/** + * Set up fixtures. + */ +void +AccountTest::setUp(void) +{ + Being* sam = new Being("sam", 1, 1, 1, 1, 1, 1, 1, 1); + Being* merry = new Being("merry", 1, 1, 1, 1, 1, 1, 1, 1); + Being* pippin = new Being("pippin", 1, 1, 1, 1, 1, 1, 1, 1); + mCharacters.push_back(sam); + mCharacters.push_back(merry); + mCharacters.push_back(pippin); + + mAccount = new Account("frodo", + "baggins", + "frodo@theshire.com", + mCharacters); +} + + +/** + * Tear down fixtures. + */ +void +AccountTest::tearDown(void) +{ + for (Beings::iterator it = mCharacters.begin(); + it != mCharacters.end(); + ++it) + { + delete (*it); + } + + delete mAccount; + mAccount = 0; +} + + +/** + * Test creating an Account using the default constructor + * and setting the account info using the mutators. + */ +void +AccountTest::testCreate1(void) +{ + const std::string name("frodo"); + const std::string password("baggins"); + const std::string encrypted("d70d266f4c276b5706881a46f43a88b0"); + const std::string email("frodo@theshire.com"); + + Account account; + account.setName(name); + account.setPassword(password); + account.setEmail(email); + account.setCharacters(mCharacters); + + CPPUNIT_ASSERT_EQUAL(account.getName(), name); + CPPUNIT_ASSERT_EQUAL(account.getPassword(), encrypted); + CPPUNIT_ASSERT_EQUAL(account.getEmail(), email); + + CPPUNIT_ASSERT_EQUAL(mAccount->getCharacters().size(), + mCharacters.size()); + + Beings& characters = account.getCharacters(); + + for (int i = 0; i < mCharacters.size(); ++i) { + CPPUNIT_ASSERT_EQUAL(characters[i]->getName(), + mCharacters[i]->getName()); + } +} + + +/** + * Test creating an Account passing the initial account info + * to the constructor. + */ +void +AccountTest::testCreate2(void) +{ + const std::string name("frodo"); + const std::string password("baggins"); + const std::string encrypted("d70d266f4c276b5706881a46f43a88b0"); + const std::string email("frodo@theshire.com"); + + Account account(name, password, email, mCharacters); + + CPPUNIT_ASSERT_EQUAL(account.getName(), name); + CPPUNIT_ASSERT_EQUAL(account.getPassword(), encrypted); + CPPUNIT_ASSERT_EQUAL(account.getEmail(), email); + + CPPUNIT_ASSERT_EQUAL(mAccount->getCharacters().size(), + mCharacters.size()); + + Beings& characters = account.getCharacters(); + + for (int i = 0; i < mCharacters.size(); ++i) { + CPPUNIT_ASSERT_EQUAL(characters[i]->getName(), + mCharacters[i]->getName()); + } +} + + +/** + * Test adding a new character. + */ +void +AccountTest::testAddCharacter1(void) +{ + Being* bilbo = new Being("bilbo", 1, 1, 1, 1, 1, 1, 1, 1); + + mAccount->addCharacter(bilbo); + + CPPUNIT_ASSERT_EQUAL(mAccount->getCharacters().size(), (size_t) 4); + + std::vector<std::string> names; + names.push_back("sam"); + names.push_back("merry"); + names.push_back("pippin"); + names.push_back("bilbo"); + + for (int i = 0; i < mCharacters.size(); ++i) { + CPPUNIT_ASSERT_EQUAL(mCharacters[i]->getName(), names[i]); + } + + delete bilbo; +} + + +/** + * Test passing a NULL pointer to addCharacter(). + */ +void +AccountTest::testAddCharacter2(void) +{ + mAccount->addCharacter(NULL); + + CPPUNIT_ASSERT_EQUAL(mAccount->getCharacters().size(), (size_t) 3); + + std::vector<std::string> names; + names.push_back("sam"); + names.push_back("merry"); + names.push_back("pippin"); + + for (int i = 0; i < mCharacters.size(); ++i) { + CPPUNIT_ASSERT_EQUAL(mCharacters[i]->getName(), names[i]); + } +} + + +/** + * Test the accessor getCharacter() with a valid name. + */ +void +AccountTest::testGetCharacter1(void) +{ + const std::string name("merry"); + + Being* merry = mAccount->getCharacter(name); + + CPPUNIT_ASSERT(merry != 0); + CPPUNIT_ASSERT_EQUAL(merry->getName(), name); +} + + +/** + * Test the accessor getCharacter() with an unexisting name. + */ +void +AccountTest::testGetCharacter2(void) +{ + Being* nobody = mAccount->getCharacter("johndoe"); + + CPPUNIT_ASSERT(nobody == 0); +} diff --git a/src/tests/testaccount.h b/src/tests/testaccount.h new file mode 100644 index 00000000..8806e766 --- /dev/null +++ b/src/tests/testaccount.h @@ -0,0 +1,116 @@ +/* + * 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_TEST_ACCOUNT_H_ +#define _TMWSERV_TEST_ACCOUNT_H_ + + +#include <cppunit/extensions/HelperMacros.h> + +#include "../account.h" + + +/** + * Unit test for the Account class. + */ +class AccountTest: public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(AccountTest); + + // add tests to the test suite. + CPPUNIT_TEST(testCreate1); + CPPUNIT_TEST(testCreate2); + CPPUNIT_TEST(testAddCharacter1); + CPPUNIT_TEST(testAddCharacter2); + CPPUNIT_TEST(testGetCharacter1); + CPPUNIT_TEST(testGetCharacter2); + + CPPUNIT_TEST_SUITE_END(); + + + public: + /** + * Set up fixtures. + */ + void + setUp(void); + + + /** + * Tear down fixtures. + */ + void + tearDown(void); + + + /** + * Test creating an Account using the default constructor + * and setting the account info using the mutators. + */ + void + testCreate1(void); + + + /** + * Test creating an Account passing the initial account info + * to the constructor. + */ + void + testCreate2(void); + + + /** + * Test adding a new character. + */ + void + testAddCharacter1(void); + + + /** + * Test passing a NULL pointer to addCharacter(). + */ + void + testAddCharacter2(void); + + + /** + * Test the accessor getCharacter() with a valid name. + */ + void + testGetCharacter1(void); + + + /** + * Test the accessor getCharacter() with an unexisting name. + */ + void + testGetCharacter2(void); + + + private: + tmwserv::Account* mAccount; /**< the default account */ + Beings mCharacters; /**< a list of beings */ +}; + + +#endif // _TMWSERV_TEST_ACCOUNT_H_ diff --git a/src/tests/testcipher.cpp b/src/tests/testcipher.cpp new file mode 100644 index 00000000..0c40fdf9 --- /dev/null +++ b/src/tests/testcipher.cpp @@ -0,0 +1,154 @@ +/* + * 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$ + */ + + +#include <string> + +#include "../utils/cipher.h" +#include "testcipher.h" + + +// register the fixture into the 'registry' +CPPUNIT_TEST_SUITE_REGISTRATION(CipherTest); + + +using namespace tmwserv::utils; + + +/** + * Set up fixtures. + */ +void +CipherTest::setUp(void) +{ + // NOOP +} + + +/** + * Tear down fixtures. + */ +void +CipherTest::tearDown(void) +{ + // NOOP +} + + +/** + * Test encoding a string with the MD5 digest algorithm. + */ +void +CipherTest::testMd5_1(void) +{ + const std::string expected("d41d8cd98f00b204e9800998ecf8427e"); + std::string actual(Cipher::instance().md5("")); + + CPPUNIT_ASSERT_EQUAL(actual, expected); +} + + +/** + * Test encoding a string with the MD5 digest algorithm. + */ +void +CipherTest::testMd5_2(void) +{ + const std::string expected("0cc175b9c0f1b6a831c399e269772661"); + std::string actual(Cipher::instance().md5("a")); + + CPPUNIT_ASSERT_EQUAL(actual, expected); +} + + +/** + * Test encoding a string with the MD5 digest algorithm. + */ +void +CipherTest::testMd5_3(void) +{ + const std::string expected("900150983cd24fb0d6963f7d28e17f72"); + std::string actual(Cipher::instance().md5("abc")); + + CPPUNIT_ASSERT_EQUAL(actual, expected); +} + + +/** + * Test encoding a string with the MD5 digest algorithm. + */ +void +CipherTest::testMd5_4(void) +{ + const std::string expected("f96b697d7cb7938d525a2f31aaf161d0"); + std::string actual(Cipher::instance().md5("message digest")); + + CPPUNIT_ASSERT_EQUAL(actual, expected); +} + + +/** + * Test encoding a string with the MD5 digest algorithm. + */ +void +CipherTest::testMd5_5(void) +{ + const std::string expected("c3fcd3d76192e4007dfb496cca67e13b"); + std::string actual(Cipher::instance().md5("abcdefghijklmnopqrstuvwxyz")); + + CPPUNIT_ASSERT_EQUAL(actual, expected); +} + + +/** + * Test encoding a string with the MD5 digest algorithm. + */ +void +CipherTest::testMd5_6(void) +{ + const std::string expected("d174ab98d277d9f5a5611c2c9f419d9f"); + + std::string s("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + s += "abcdefghijklmnopqrstuvwxyz"; + s += "0123456789"; + std::string actual(Cipher::instance().md5(s)); + + CPPUNIT_ASSERT_EQUAL(actual, expected); +} + + +/** + * Test encoding a string with the MD5 digest algorithm. + */ +void +CipherTest::testMd5_7(void) +{ + const std::string expected("57edf4a22be3c955ac49da2e2107b67a"); + + std::string s; + for (int i = 0; i < 8; ++i) { + s += "1234567890"; + } + std::string actual(Cipher::instance().md5(s)); + + CPPUNIT_ASSERT_EQUAL(actual, expected); +} diff --git a/src/tests/testcipher.h b/src/tests/testcipher.h new file mode 100644 index 00000000..7db81803 --- /dev/null +++ b/src/tests/testcipher.h @@ -0,0 +1,115 @@ +/* + * 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_TEST_CIPHER_H_ +#define _TMWSERV_TEST_CIPHER_H_ + + +#include <cppunit/extensions/HelperMacros.h> + + +/** + * Unit test for the Cipher class. + */ +class CipherTest: public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(CipherTest); + + // add tests to the test suite. + CPPUNIT_TEST(testMd5_1); + CPPUNIT_TEST(testMd5_2); + CPPUNIT_TEST(testMd5_3); + CPPUNIT_TEST(testMd5_4); + CPPUNIT_TEST(testMd5_5); + CPPUNIT_TEST(testMd5_6); + CPPUNIT_TEST(testMd5_7); + + CPPUNIT_TEST_SUITE_END(); + + + public: + /** + * Set up fixtures. + */ + void + setUp(void); + + + /** + * Tear down fixtures. + */ + void + tearDown(void); + + + /** + * Test encoding a string with the MD5 digest algorithm. + */ + void + testMd5_1(void); + + + /** + * Test encoding a string with the MD5 digest algorithm. + */ + void + testMd5_2(void); + + + /** + * Test encoding a string with the MD5 digest algorithm. + */ + void + testMd5_3(void); + + + /** + * Test encoding a string with the MD5 digest algorithm. + */ + void + testMd5_4(void); + + + /** + * Test encoding a string with the MD5 digest algorithm. + */ + void + testMd5_5(void); + + + /** + * Test encoding a string with the MD5 digest algorithm. + */ + void + testMd5_6(void); + + + /** + * Test encoding a string with the MD5 digest algorithm. + */ + void + testMd5_7(void); +}; + + +#endif // _TMWSERV_TEST_CIPHER_H_ diff --git a/src/tests/testdataprovider.cpp b/src/tests/testdataprovider.cpp new file mode 100644 index 00000000..06a2b0ee --- /dev/null +++ b/src/tests/testdataprovider.cpp @@ -0,0 +1,334 @@ +/* + * 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$ + */ + + +#include <physfs.h> + +#if defined (MYSQL_SUPPORT) +#include <mysql/mysql.h> +#elif defined (POSTGRE_SUPPORT) +#include <libpq-fe.h> +#endif + +#include "../dal/dataproviderfactory.h" + +#include "testdataprovider.h" + + +// register the fixture into the 'registry' +CPPUNIT_TEST_SUITE_REGISTRATION(DataProviderTest); + + +// initialize the static variables. +std::string DataProviderTest::mDbName("tmwteststorage"); +std::string DataProviderTest::mDbUser("guest"); +std::string DataProviderTest::mDbPassword("guest"); +std::string DataProviderTest::mSqlCreateTable( + "create table employees (" + " id integer primary key, " + " name varchar(32) not null);" +); +std::string DataProviderTest::mSqlInsertRow( + "insert into employees values (1, 'john');" +); +std::string DataProviderTest::mSqlFetchRow("select * from employees;"); + + +using namespace tmwserv::dal; + + +/** + * Set up fixtures. + */ +void +DataProviderTest::setUp(void) +{ + // reinitialize the database before each test. + reinitDb(); + + // obtain a data provider. + try { + mDb = DataProviderFactory::createDataProvider(); + } + catch (const std::runtime_error& e) { + CPPUNIT_FAIL(e.what()); + } +} + + +/** + * Tear down fixtures. + */ +void +DataProviderTest::tearDown(void) +{ + mDb->disconnect(); + + delete mDb; + mDb = 0; + + // clean the database after each test. + reinitDb(); +} + + +/** + * Connection to an existing database. + */ +void +DataProviderTest::testConnection1(void) +{ +#ifdef SQLITE_SUPPORT + std::string dbFile(mDbName); + dbFile += ".db"; + + mDb->connect(dbFile, mDbUser, mDbPassword); +#else + mDb->connect(mDbName, mDbUser, mDbPassword); +#endif + + CPPUNIT_ASSERT(mDb->isConnected()); +} + + +/** + * Create a new table in the database. + */ +void +DataProviderTest::testCreateTable1(void) +{ +#ifdef SQLITE_SUPPORT + std::string dbFile(mDbName); + dbFile += ".db"; + + mDb->connect(dbFile, mDbUser, mDbPassword); +#else + mDb->connect(mDbName, mDbUser, mDbPassword); +#endif + + CPPUNIT_ASSERT(mDb->isConnected()); + + const RecordSet& rs = mDb->execSql(mSqlCreateTable); + CPPUNIT_ASSERT(rs.isEmpty()); + + mDb->disconnect(); + CPPUNIT_ASSERT(!mDb->isConnected()); +} + + +/** + * Create the same table one more time in the database. + */ +void +DataProviderTest::testCreateTable2(void) +{ +#ifdef SQLITE_SUPPORT + std::string dbFile(mDbName); + dbFile += ".db"; + + mDb->connect(dbFile, mDbUser, mDbPassword); +#else + mDb->connect(mDbName, mDbUser, mDbPassword); +#endif + + CPPUNIT_ASSERT(mDb->isConnected()); + + mDb->execSql(mSqlCreateTable); + // this should throw tmwserv::dal::DbSqlQueryExecFailure. + mDb->execSql(mSqlCreateTable); +} + + +/** + * Insert a new row to the table. + */ +void +DataProviderTest::testInsert1(void) +{ +#ifdef SQLITE_SUPPORT + std::string dbFile(mDbName); + dbFile += ".db"; + + mDb->connect(dbFile, mDbUser, mDbPassword); +#else + mDb->connect(mDbName, mDbUser, mDbPassword); +#endif + + CPPUNIT_ASSERT(mDb->isConnected()); + + mDb->execSql(mSqlCreateTable); + + const RecordSet& rs = mDb->execSql(mSqlInsertRow); + // an insert query does not return any records + // so the recordset remains empty. + CPPUNIT_ASSERT(rs.isEmpty()); + + mDb->disconnect(); + CPPUNIT_ASSERT(!mDb->isConnected()); +} + + +/** + * Insert the same record again. + */ +void +DataProviderTest::testInsert2(void) +{ +#ifdef SQLITE_SUPPORT + std::string dbFile(mDbName); + dbFile += ".db"; + + mDb->connect(dbFile, mDbUser, mDbPassword); +#else + mDb->connect(mDbName, mDbUser, mDbPassword); +#endif + + CPPUNIT_ASSERT(mDb->isConnected()); + + // this should throw tmwserv::dal::DbSqlQueryExecFailure + // as we are violating the primary key uniqueness. + mDb->execSql(mSqlInsertRow); +} + + +/** + * Fetch data from the table. + */ +void +DataProviderTest::testFetch1(void) +{ +#ifdef SQLITE_SUPPORT + std::string dbFile(mDbName); + dbFile += ".db"; + + mDb->connect(dbFile, mDbUser, mDbPassword); +#else + mDb->connect(mDbName, mDbUser, mDbPassword); +#endif + + CPPUNIT_ASSERT(mDb->isConnected()); + + mDb->execSql(mSqlCreateTable); + mDb->execSql(mSqlInsertRow); + + const RecordSet& rs = mDb->execSql(mSqlFetchRow); + CPPUNIT_ASSERT(!rs.isEmpty()); + + std::string id("1"); + std::string name("john"); + CPPUNIT_ASSERT_EQUAL(id, rs(0, "id")); + CPPUNIT_ASSERT_EQUAL(name, rs(0, "name")); + + mDb->disconnect(); + CPPUNIT_ASSERT(!mDb->isConnected()); +} + + +/** + * Disconnection from an open database. + */ +void +DataProviderTest::testDisconnection1(void) +{ +#ifdef SQLITE_SUPPORT + std::string dbFile(mDbName); + dbFile += ".db"; + + mDb->connect(dbFile, mDbUser, mDbPassword); +#else + mDb->connect(mDbName, mDbUser, mDbPassword); +#endif + + CPPUNIT_ASSERT(mDb->isConnected()); + + mDb->disconnect(); + CPPUNIT_ASSERT(!mDb->isConnected()); +} + + +/** + * Disconnection from a closed database. + */ +void +DataProviderTest::testDisconnection2(void) +{ + mDb->disconnect(); + CPPUNIT_ASSERT(!mDb->isConnected()); +} + + +/** + * Reinitialize the database. + */ +void +DataProviderTest::reinitDb(void) +{ + // we are not using DataProvider::execSql() to execute the SQL queries + // here as the class is the purpose of these tests. + +#if defined (MYSQL_SUPPORT) + { + // initialize the MySQL library. + MYSQL* db = mysql_init(NULL); + + if (!db) { + CPPUNIT_FAIL("unable to initialize the MySQL library: no memory"); + } + + // connect to the database. + if (!mysql_real_connect(db, + NULL, + mDbUser.c_str(), + mDbPassword.c_str(), + mDbName.c_str(), + 0, + NULL, + 0)) + { + CPPUNIT_FAIL(mysql_error(db)); + } + + // drop the table. + std::string sql("drop table employees;"); + if (mysql_query(db, sql.c_str()) != 0) { + // ignore, the table may not exist. + } + + // close the connection and free memory. + mysql_close(db); + mysql_library_end(); + db = 0; + } +#elif defined (POSTGRE_SUPPORT) + // TODO: drop tables. +#else // SQLITE_SUPPORT + std::string dbFile(mDbName); + dbFile += ".db"; + + // ensure that the database file does not exist. + if (PHYSFS_exists(dbFile.c_str())) { + if (PHYSFS_delete(dbFile.c_str()) == 0) { + CPPUNIT_FAIL(PHYSFS_getLastError()); + } + } +#endif +} diff --git a/src/tests/testdataprovider.h b/src/tests/testdataprovider.h new file mode 100644 index 00000000..1f0a082c --- /dev/null +++ b/src/tests/testdataprovider.h @@ -0,0 +1,156 @@ +/* + * 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_TEST_DATA_PROVIDER_H_ +#define _TMWSERV_TEST_DATA_PROVIDER_H_ + + +#include <cppunit/extensions/HelperMacros.h> + +#include "../dal/dalexcept.h" +#include "../dal/dataprovider.h" + + +/** + * Requirements: + * - if using MySQL or PostgreSQL as backends, then make sure that a user + * named 'guest' with the password 'guest' has enough privileges to + * create tables and populate them in a database named 'tmwteststorage' + * prior to running the teststorage unit tests. + */ + + +using namespace tmwserv::dal; + + +/** + * Unit test for the DataProvider class. + */ +class DataProviderTest: public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(DataProviderTest); + + // add tests to the test suite. + CPPUNIT_TEST(testConnection1); + CPPUNIT_TEST(testCreateTable1); + CPPUNIT_TEST_EXCEPTION(testCreateTable2, DbSqlQueryExecFailure); + CPPUNIT_TEST(testInsert1); + CPPUNIT_TEST_EXCEPTION(testInsert2, DbSqlQueryExecFailure); + CPPUNIT_TEST(testFetch1); + CPPUNIT_TEST(testDisconnection1); + CPPUNIT_TEST(testDisconnection2); + + CPPUNIT_TEST_SUITE_END(); + + + public: + /** + * Set up fixtures. + */ + void + setUp(void); + + + /** + * Tear down fixtures. + */ + void + tearDown(void); + + + /** + * Connection to an existing database. + */ + void + testConnection1(void); + + + /** + * Create a new table in the database. + */ + void + testCreateTable1(void); + + + /** + * Create the same table one more time in the database. + */ + void + testCreateTable2(void); + + + /** + * Insert a new record into the table. + */ + void + testInsert1(void); + + + /** + * Insert the same record again. + */ + void + testInsert2(void); + + + /** + * Fetch data from the table. + */ + void + testFetch1(void); + + + /** + * Disconnection from an open database. + */ + void + testDisconnection1(void); + + + /** + * Disconnection from a closed database. + */ + void + testDisconnection2(void); + + + private: + /** + * Reinitialize the database. + */ + void + reinitDb(void); + + + private: + DataProvider* mDb; /**< the data provider */ + static std::string mDbName; /**< the database name */ + static std::string mDbUser; /**< the database user */ + static std::string mDbPassword; /**< the database password */ + static std::string mSqlCreateTable; /**< SQL query to create table */ + static std::string mSqlInsertRow; /**< SQL query to delete table */ + static std::string mSqlFetchRow; /**< SQL query to fetch data */ +}; + + +#endif // _TMWSERV_TEST_DATA_PROVIDER_H_ diff --git a/src/tests/testrecordset.cpp b/src/tests/testrecordset.cpp new file mode 100644 index 00000000..26a9e016 --- /dev/null +++ b/src/tests/testrecordset.cpp @@ -0,0 +1,285 @@ +/* + * 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$ + */ + + +#include <sstream> + +#include "testrecordset.h" + + +// register the fixture into the 'registry' +CPPUNIT_TEST_SUITE_REGISTRATION(RecordSetTest); + + +using namespace tmwserv::dal; + + +/** + * Set up fixtures. + */ +void +RecordSetTest::setUp(void) +{ + // populate mNonEmptyRs. + Row headers; + headers.push_back("id"); + headers.push_back("name"); + mNonEmptyRs.setColumnHeaders(headers); + + Row r1; + r1.push_back("1"); + r1.push_back("john"); + mNonEmptyRs.add(r1); + + Row r2; + r2.push_back("2"); + r2.push_back("mike"); + mNonEmptyRs.add(r2); +} + + +/** + * Tear down fixtures. + */ +void +RecordSetTest::tearDown(void) +{ + // NOOP +} + + +/** + * Test RecordSet::rows() on an empty RecordSet. + */ +void +RecordSetTest::testRows1(void) +{ + CPPUNIT_ASSERT_EQUAL((unsigned int) 0, mEmptyRs.rows()); +} + + +/** + * Test RecordSet::rows() on a non-empty RecordSet. + */ +void +RecordSetTest::testRows2(void) +{ + CPPUNIT_ASSERT_EQUAL((unsigned int) 2, mNonEmptyRs.rows()); +} + + +/** + * Test RecordSet::cols() on an empty RecordSet. + */ +void +RecordSetTest::testCols1(void) +{ + CPPUNIT_ASSERT_EQUAL((unsigned int) 0, mEmptyRs.cols()); +} + + +/** + * Test RecordSet::cols() on a non-empty RecordSet. + */ +void +RecordSetTest::testCols2(void) +{ + CPPUNIT_ASSERT_EQUAL((unsigned int) 2, mNonEmptyRs.cols()); +} + + +/** + * Call RecordSet::isEmpty() from an empty RecordSet. + */ +void +RecordSetTest::testIsEmpty1(void) +{ + CPPUNIT_ASSERT(mEmptyRs.isEmpty()); +} + + +/** + * Call RecordSet::isEmpty() from a non-empty RecordSet. + */ +void +RecordSetTest::testIsEmpty2(void) +{ + CPPUNIT_ASSERT(!mNonEmptyRs.isEmpty()); +} + + +/** + * Call RecordSet::operator() from an empty RecordSet. + */ +void +RecordSetTest::testOperator1(void) +{ + // this should throw std::invalid_argument. + mEmptyRs(0, 0); +} + + +/** + * Call RecordSet::operator() from a non-empty RecordSet with + * a row index and a column index as parameters. + */ +void +RecordSetTest::testOperator2(void) +{ + std::string value("mike"); + + CPPUNIT_ASSERT_EQUAL(value, mNonEmptyRs(1, 1)); +} + + +/** + * Call RecordSet::operator() from a non-empty RecordSet with + * a row index and a column index that are out of range as + * parameters. + */ +void +RecordSetTest::testOperator3(void) +{ + // this should throw std::out_of_range. + mNonEmptyRs(2, 2); +} + + +/** + * Call RecordSet::operator() from a non-empty RecordSet with + * a row index and a field name as parameters. + */ +void +RecordSetTest::testOperator4(void) +{ + std::string value("1"); + + CPPUNIT_ASSERT_EQUAL(value, mNonEmptyRs(0, "id")); +} + + +/** + * Call RecordSet::operator() from a non-empty RecordSet with + * a row index that is out of range and a field name as parameters. + */ +void +RecordSetTest::testOperator5(void) +{ + // this should throw std::out_of_range. + mNonEmptyRs(3, "id"); +} + + +/** + * Call RecordSet::operator() from a non-empty RecordSet with + * a row index and a field name that does not exist as parameters. + */ +void +RecordSetTest::testOperator6(void) +{ + // this should throw std::invalid_argument. + mNonEmptyRs(1, "noname"); +} + + +/** + * Test writing an empty RecordSet to an output stream. + */ +void +RecordSetTest::testOutputStream1(void) +{ + std::string emptyStr; + + std::ostringstream os; + os << mEmptyRs; + + CPPUNIT_ASSERT_EQUAL(emptyStr, os.str()); +} + + +/** + * Test writing a non-empty RecordSet to an output stream. + */ +void +RecordSetTest::testOutputStream2(void) +{ + std::ostringstream os1; + os1 << "|id|name|" << std::endl << std::endl + << "|1|john|" << std::endl + << "|2|mike|" << std::endl; + + std::ostringstream os2; + os2 << mNonEmptyRs; + + CPPUNIT_ASSERT_EQUAL(os1.str(), os2.str()); +} + + +/** + * Test RecordSet::add() to add a new now. + */ +void +RecordSetTest::testAdd1(void) +{ + std::string id("3"); + std::string name("elena"); + + Row r; + r.push_back(id); + r.push_back(name); + mNonEmptyRs.add(r); + + CPPUNIT_ASSERT_EQUAL((unsigned int) 3, mNonEmptyRs.rows()); + CPPUNIT_ASSERT_EQUAL((unsigned int) 2, mNonEmptyRs.cols()); + CPPUNIT_ASSERT_EQUAL(id, mNonEmptyRs(2, 0)); + CPPUNIT_ASSERT_EQUAL(name, mNonEmptyRs(2, 1)); +} + + +/** + * Test RecordSet::add() to add a new now with a different number + * of fields. + */ +void +RecordSetTest::testAdd2(void) +{ + Row r; + r.push_back("4"); + + // this should throw std::invalid_argument. + mNonEmptyRs.add(r); +} + + +/** + * Test RecordSet::add() to add a new now to a RecordSet that does + * not have column headers. + */ +void +RecordSetTest::testAdd3(void) +{ + Row r; + r.push_back("5"); + + // this should throw tmw::dal::RsColumnHeadersNotSet. + mEmptyRs.add(r); +} diff --git a/src/tests/testrecordset.h b/src/tests/testrecordset.h new file mode 100644 index 00000000..66dc7117 --- /dev/null +++ b/src/tests/testrecordset.h @@ -0,0 +1,215 @@ +/* + * 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_TEST_RECORDSET_H_ +#define _TMWSERV_TEST_RECORDSET_H_ + + +#include <cppunit/extensions/HelperMacros.h> + +#include <stdexcept> + +#include "../dal/dalexcept.h" +#include "../dal/recordset.h" + + +using namespace tmwserv::dal; + + +/** + * Unit test for the RecordSet class. + */ +class RecordSetTest: public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(RecordSetTest); + + // add tests to the test suite. + CPPUNIT_TEST(testRows1); + CPPUNIT_TEST(testRows2); + CPPUNIT_TEST(testCols1); + CPPUNIT_TEST(testCols2); + CPPUNIT_TEST(testIsEmpty1); + CPPUNIT_TEST(testIsEmpty2); + CPPUNIT_TEST_EXCEPTION(testOperator1, std::invalid_argument); + CPPUNIT_TEST(testOperator2); + CPPUNIT_TEST_EXCEPTION(testOperator3, std::out_of_range); + CPPUNIT_TEST(testOperator4); + CPPUNIT_TEST_EXCEPTION(testOperator5, std::out_of_range); + CPPUNIT_TEST_EXCEPTION(testOperator6, std::invalid_argument); + CPPUNIT_TEST(testOutputStream1); + CPPUNIT_TEST(testOutputStream2); + CPPUNIT_TEST(testAdd1); + CPPUNIT_TEST_EXCEPTION(testAdd2, std::invalid_argument); + CPPUNIT_TEST_EXCEPTION(testAdd3, RsColumnHeadersNotSet); + + CPPUNIT_TEST_SUITE_END(); + + + public: + /** + * Set up fixtures. + */ + void + setUp(void); + + + /** + * Tear down fixtures. + */ + void + tearDown(void); + + + /** + * Call RecordSet::rows() from an empty RecordSet. + */ + void + testRows1(void); + + + /** + * Call RecordSet::rows() from a non-empty RecordSet. + */ + void + testRows2(void); + + + /** + * Call RecordSet::cols() from an empty RecordSet. + */ + void + testCols1(void); + + + /** + * Call RecordSet::cols() from a non-empty RecordSet. + */ + void + testCols2(void); + + + /** + * Call RecordSet::isEmpty() from an empty RecordSet. + */ + void + testIsEmpty1(void); + + + /** + * Call RecordSet::isEmpty() from a non-empty RecordSet. + */ + void + testIsEmpty2(void); + + + /** + * Call RecordSet::operator() from an empty RecordSet. + */ + void + testOperator1(void); + + + /** + * Call RecordSet::operator() from a non-empty RecordSet with + * a row index and a column index as parameters. + */ + void + testOperator2(void); + + /** + * Call RecordSet::operator() from a non-empty RecordSet with + * a row index and a column index that are out of range as + * parameters. + */ + void + testOperator3(void); + + + /** + * Call RecordSet::operator() from a non-empty RecordSet with + * a row index and a field name as parameters. + */ + void + testOperator4(void); + + + /** + * Call RecordSet::operator() from a non-empty RecordSet with + * a row index that is out of range and a field name as parameters. + */ + void + testOperator5(void); + + + /** + * Call RecordSet::operator() from a non-empty RecordSet with + * a row index and a field name that does not exist as parameters. + */ + void + testOperator6(void); + + + /** + * Test writing an empty RecordSet to an output stream. + */ + void + testOutputStream1(void); + + + /** + * Test writing a non-empty RecordSet to an output stream. + */ + void + testOutputStream2(void); + + + /** + * Call RecordSet::add() to add a new now. + */ + void + testAdd1(void); + + + /** + * Call RecordSet::add() to add a new now with a different number + * of fields. + */ + void + testAdd2(void); + + + /** + * Call RecordSet::add() to add a new now to a RecordSet that does + * not have column headers. + */ + void + testAdd3(void); + + + private: + RecordSet mEmptyRs; /**< empty recordset */ + RecordSet mNonEmptyRs; /**< recordset with some data */ +}; + + +#endif // _TMWSERV_TEST_RECORDSET_H_ diff --git a/src/tests/testsmain.cpp b/src/tests/testsmain.cpp new file mode 100644 index 00000000..70cdc185 --- /dev/null +++ b/src/tests/testsmain.cpp @@ -0,0 +1,65 @@ +/* + * 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$ + */ + + +#include <cppunit/extensions/TestFactoryRegistry.h> +#include <cppunit/ui/text/TextTestRunner.h> + +#include <physfs.h> + + +/** + * Notes: + * - if the unit test application is linked to libsqlite3, there will + * be a memory leak (8 bytes) while no leaks are detected when linked + * to libmysqlclient. the leak was detected using Valgrind, an + * excellent memory debugger. + * + * TODO: check memory leak when linked to libpq (PostgreSQL). + */ + + +int main(int argc, char* argv[]) +{ + // initialize the PhysicsFS library. + PHYSFS_init(argv[0]); + PHYSFS_addToSearchPath(".", 1); + PHYSFS_setWriteDir("."); + + using namespace CppUnit; + + // get the top level suite from the registry. + Test* suite = TestFactoryRegistry::getRegistry().makeTest(); + + // add the test to the list of test to run. + TextTestRunner runner; + runner.addTest(suite); + + // run the tests. + bool wasSuccessful = runner.run(); + + // denitialize the PhysicsFS library. + PHYSFS_deinit(); + + // return error code 1 if the one of test failed. + return wasSuccessful ? 0 : 1; +} diff --git a/src/tests/teststorage.cpp b/src/tests/teststorage.cpp new file mode 100644 index 00000000..9757fdf3 --- /dev/null +++ b/src/tests/teststorage.cpp @@ -0,0 +1,310 @@ +/* + * 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$ + */ + + +#include <sstream> + +#include <physfs.h> + +#include "../utils/cipher.h" + +#include "../dalstoragesql.h" +#include "../storage.h" +#include "teststorage.h" + + +// register the fixture into the 'registry' +CPPUNIT_TEST_SUITE_REGISTRATION(StorageTest); + + +// initialization of static attributes. +std::string StorageTest::mStorageName("tmwteststorage"); +std::string StorageTest::mStorageUser("guest"); +std::string StorageTest::mStorageUserPassword("guest"); + + +using namespace tmwserv; + + +/** + * Set up fixtures. + */ +void +StorageTest::setUp(void) +{ + // reinitialize the storage before each test. + initStorage(); + + // create a storage. + Storage& myStorage = Storage::instance(mStorageName); + myStorage.setUser(mStorageUser); + myStorage.setPassword(mStorageUserPassword); + + // open the storage. + myStorage.open(); +} + + +/** + * Tear down fixtures. + */ +void +StorageTest::tearDown(void) +{ + // close the storage. + Storage& myStorage = Storage::instance(mStorageName); + myStorage.close(); + + // delete the storage. + Storage::destroy(); + + // clean the storage after each test. + cleanStorage(); +} + + +/** + * Fetch an existing account from the database. + */ +void +StorageTest::testGetAccount1(void) +{ + Storage& myStorage = Storage::instance(mStorageName); + + CPPUNIT_ASSERT(myStorage.isOpen()); + + Account* account = myStorage.getAccount("kindjal"); + + using namespace tmwserv::utils; + + std::string name("kindjal"); + std::string password(Cipher::instance().md5("kindjal")); + std::string email("kindjal@domain"); + + CPPUNIT_ASSERT(account != 0); + CPPUNIT_ASSERT_EQUAL(account->getName(), name); + CPPUNIT_ASSERT_EQUAL(account->getPassword(), password); + CPPUNIT_ASSERT_EQUAL(account->getEmail(), email); +} + + +/** + * Fetch an unexisting account from the database. + */ +void +StorageTest::testGetAccount2(void) +{ + Storage& myStorage = Storage::instance(mStorageName); + + if (!myStorage.isOpen()) { + CPPUNIT_FAIL("the storage is not opened."); + } + + Account* account = myStorage.getAccount("xxx"); + + CPPUNIT_ASSERT(account == 0); +} + + +/** + * Initialize the storage. + */ +void +StorageTest::initStorage(void) +{ +#if defined (MYSQL_SUPPORT) || defined (POSTGRE_SUPPORT) || \ + defined (SQLITE_SUPPORT) + + // we are using a database to persist the data from the storage. + + using namespace tmwserv::dal; + + // insert initial data using the data provider directly. + // we must avoid using the APIs from Storage here as it's the purpose + // of these tests. + std::auto_ptr<DataProvider> db(DataProviderFactory::createDataProvider()); + + try { +#ifdef SQLITE_SUPPORT + std::string dbFile(mStorageName); + dbFile += ".db"; + + // ensure that the file does not exist before the tests begin. + if (PHYSFS_exists(dbFile.c_str())) { + if (PHYSFS_delete(dbFile.c_str()) == 0) { + CPPUNIT_FAIL(PHYSFS_getLastError()); + } + } + + db->connect(dbFile, mStorageUser, mStorageUserPassword); +#else + db->connect(mStorageName, mStorageUser, mStorageUserPassword); +#endif + + // drop the tables. + dropTable(db, MAPS_TBL_NAME); + dropTable(db, ACCOUNTS_TBL_NAME); + dropTable(db, CHARACTERS_TBL_NAME); + dropTable(db, ITEMS_TBL_NAME); + dropTable(db, WORLD_ITEMS_TBL_NAME); + dropTable(db, INVENTORIES_TBL_NAME); + + // recreate the tables. + db->execSql(SQL_MAPS_TABLE); + db->execSql(SQL_ACCOUNTS_TABLE); + db->execSql(SQL_CHARACTERS_TABLE); + db->execSql(SQL_ITEMS_TABLE); + db->execSql(SQL_WORLD_ITEMS_TABLE); + db->execSql(SQL_INVENTORIES_TABLE); + + // populate the tables. + insertAccount(db, "kindjal"); + + 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"); + } +#else + // if we are in this block it means that we are not using a database + // to persist the data from the storage. + // at the moment, Storage assume that the data are persisted in a database + // so let's raise a preprocessing error. +#error "no database backend defined" +#endif +} + + +/** + * Clean the storage. + */ +void +StorageTest::cleanStorage(void) +{ +#if defined (MYSQL_SUPPORT) || defined (POSTGRE_SUPPORT) || \ + defined (SQLITE_SUPPORT) + + // we are using a database to persist the data from the storage. + + using namespace tmwserv::dal; + + std::auto_ptr<DataProvider> db(DataProviderFactory::createDataProvider()); + + try { +#ifdef SQLITE_SUPPORT + std::string dbFile(mStorageName); + dbFile += ".db"; + + // ensure that the file does not exist before the tests begin. + if (PHYSFS_exists(dbFile.c_str())) { + if (PHYSFS_delete(dbFile.c_str()) == 0) { + CPPUNIT_FAIL(PHYSFS_getLastError()); + } + } +#else + db->connect(mStorageName, mStorageUser, mStorageUserPassword); + + // drop the tables. + dropTable(db, MAPS_TBL_NAME); + dropTable(db, ACCOUNTS_TBL_NAME); + dropTable(db, CHARACTERS_TBL_NAME); + dropTable(db, ITEMS_TBL_NAME); + dropTable(db, WORLD_ITEMS_TBL_NAME); + dropTable(db, INVENTORIES_TBL_NAME); + + db->disconnect(); +#endif + } + 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"); + } +#else + // if we are in this block it means that we are not using a database + // to persist the data from the storage. + // at the moment, Storage assume that the data are persisted in a database + // so let's raise a preprocessing error. +#error "no database backend defined" +#endif +} + + +/** + * Drop a table. + */ +void +StorageTest::dropTable(std::auto_ptr<DataProvider>& db, + const std::string& name) +{ + try { + std::string sql("drop table "); + sql += name; + sql += ";"; + db->execSql(sql); + } + catch (const DbSqlQueryExecFailure& e) { + // ignore, the table may not exist. + } +} + + +/** + * Insert a new account. + */ +void +StorageTest::insertAccount(std::auto_ptr<DataProvider>& db, + const std::string& name) +{ + std::ostringstream sql; + + // the password will be identical to the name. + + sql << "insert into " << ACCOUNTS_TBL_NAME + << "(username, password, email, level, banned) values " + << "('" << name << "', '" << name << "', '" + << name << "@domain', 1, 0);"; + + db->execSql(sql.str()); +} diff --git a/src/tests/teststorage.h b/src/tests/teststorage.h new file mode 100644 index 00000000..f8230735 --- /dev/null +++ b/src/tests/teststorage.h @@ -0,0 +1,132 @@ +/* + * 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_TEST_STORAGE_H_ +#define _TMWSERV_TEST_STORAGE_H_ + + +#include <cppunit/extensions/HelperMacros.h> + +#include "../dal/dataproviderfactory.h" + + +/** + * Requirements: + * - if using MySQL or PostgreSQL as backends, then make sure that a user + * named 'guest' with the password 'guest' has enough privileges to + * create tables and populate them in a database named 'tmwteststorage' + * prior to running the teststorage unit tests. + */ + + +using namespace tmwserv::dal; + + +/** + * Unit test for the Storage class. + */ +class StorageTest: public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(StorageTest); + + // add tests to the test suite. + CPPUNIT_TEST(testGetAccount1); + CPPUNIT_TEST(testGetAccount2); + + CPPUNIT_TEST_SUITE_END(); + + + public: + /** + * Set up fixtures. + */ + void + setUp(void); + + + /** + * Tear down fixtures. + */ + void + tearDown(void); + + + /** + * Fetch an existing account from the database. + */ + void + testGetAccount1(void); + + + /** + * Fetch an unexisting account from the database. + */ + void + testGetAccount2(void); + + + private: + /** + * Initialize the storage. + */ + void + initStorage(void); + + + /** + * Clean the storage. + */ + void + cleanStorage(void); + + + /** + * Drop a table. + * + * @param db the database. + * @param name the table name. + */ + void + dropTable(std::auto_ptr<DataProvider>& db, + const std::string& name); + + + /** + * Insert a new account. + * + * @param db the database. + * @param name the user name. + */ + void + insertAccount(std::auto_ptr<DataProvider>&, + const std::string& name); + + + private: + static std::string mStorageName; + static std::string mStorageUser; + static std::string mStorageUserPassword; +}; + + +#endif // _TMWSERV_TEST_STORAGE_H_ |