2010-04-22 00:46:48 +02:00
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
# ifndef POOL_TEST_H_
# define POOL_TEST_H_
# include <string>
# include <iostream>
# include <stdlib.h>
# include <getopt.h>
# include <TestFixture.h>
# include <TestAssert.h>
# include <TestSuite.h>
# include <TestCaller.h>
# include <ui/text/TestRunner.h>
# include <cppunit/extensions/HelperMacros.h>
# include <unistd.h>
# include "SqlDB.h"
# include "SqliteDB.h"
# include "MySqlDB.h"
# include "PoolSQL.h"
# include "Nebula.h"
// Use this macro in sub-classes to add all the tests defined here
# define ALL_POOLTEST_CPPUNIT_TESTS() \
CPPUNIT_TEST ( oid_assignment ) ; \
CPPUNIT_TEST ( get_from_cache ) ; \
CPPUNIT_TEST ( get_from_db ) ; \
CPPUNIT_TEST ( wrong_get ) ; \
CPPUNIT_TEST ( drop_and_get ) ; \
using namespace std ;
/* ************************************************************************* */
/* ************************************************************************* */
class PoolTest : public CppUnit : : TestFixture
{
private :
// Global flag to use either Sqlite or MySQL
static bool mysql ;
protected :
PoolSQL * pool ;
SqlDB * db ;
PoolObjectSQL * obj ;
/*
* The name of the database to execute the test on
*/
virtual string database_name ( ) = 0 ;
/*
* Bootstrap the DB with the neccessary tables for the test
*/
virtual void bootstrap ( SqlDB * db ) = 0 ;
/*
* Create the appropiate pool
*/
virtual PoolSQL * create_pool ( SqlDB * db ) = 0 ;
/*
* Allocate the indexth sample pool object
*/
virtual int allocate ( int index ) = 0 ;
/*
* Check if the indexth sample object is equal to this one
*/
virtual void check ( int index , PoolObjectSQL * obj ) = 0 ;
// Allocate the sample objects for the DB dump
// virtual void allocate_dump() = 0;
// Check the DB dump with the correct sample string
// virtual void check_dump(string result) = 0;
public :
void setUp ( )
{
string db_name = " test.db " ;
unlink ( " test.db " ) ;
if ( mysql )
{
db = new MySqlDB ( " localhost " , " oneadmin " , " onepass " , NULL ) ;
ostringstream oss1 ;
oss1 < < " DROP DATABASE IF EXISTS " < < database_name ( ) ;
db - > exec ( oss1 ) ;
ostringstream oss ;
oss < < " CREATE DATABASE " < < database_name ( ) ;
db - > exec ( oss ) ;
ostringstream oss2 ;
oss2 < < " use " < < database_name ( ) ;
db - > exec ( oss2 ) ;
}
else
db = new SqliteDB ( db_name ) ;
bootstrap ( db ) ;
pool = create_pool ( db ) ;
} ;
void tearDown ( )
{
if ( mysql )
{
ostringstream oss ;
oss < < " DROP DATABASE IF EXISTS " < < database_name ( ) ;
db - > exec ( oss ) ;
}
else
remove ( " test.db " ) ;
delete db ;
delete pool ;
} ;
// *****************************************************************************
void oid_assignment ( )
{
int oid ;
oid = allocate ( 0 ) ;
// first element in the pool should have oid=0
CPPUNIT_ASSERT ( oid = = 0 ) ;
oid = allocate ( 1 ) ;
// second element in the pool should have oid=1
CPPUNIT_ASSERT ( oid = = 1 ) ;
}
// Try to allocate two objects, and retrieve them
void get_from_cache ( )
{
int oid_0 , oid_1 ;
// Allocate two objects
oid_0 = allocate ( 0 ) ;
oid_1 = allocate ( 1 ) ;
// ---------------------------------
// Get first object and check its integrity
obj = pool - > get ( oid_0 , false ) ;
check ( 0 , obj ) ;
// Same for the second, but ask it to be locked
obj = pool - > get ( oid_1 , true ) ;
if ( obj ! = 0 )
{
obj - > unlock ( ) ;
}
check ( 1 , obj ) ;
} ;
// Try to allocate two objects, and retrieve them
void get_from_db ( )
{
int oid_0 , oid_1 ;
// Allocate two objects
oid_0 = allocate ( 0 ) ;
oid_1 = allocate ( 1 ) ;
// Clean the cache, forcing the pool to read the objects from the DB
pool - > clean ( ) ;
// ---------------------------------
// Get first object and check its integrity
obj = pool - > get ( oid_0 , false ) ;
check ( 0 , obj ) ;
// Same for the second one, but ask it to be locked
obj = pool - > get ( oid_1 , true ) ;
if ( obj ! = 0 )
{
obj - > unlock ( ) ;
}
check ( 1 , obj ) ;
} ;
void wrong_get ( )
{
// The pool is empty
// Non existing oid
obj = pool - > get ( 13 , true ) ;
CPPUNIT_ASSERT ( obj = = 0 ) ;
// Allocate an object
allocate ( 0 ) ;
// Ask again for a non-existing oid
obj = pool - > get ( 213 , true ) ;
CPPUNIT_ASSERT ( obj = = 0 ) ;
}
void drop_and_get ( )
{
int oid_0 , oid_1 ;
// Allocate two objects
oid_0 = allocate ( 0 ) ;
oid_1 = allocate ( 1 ) ;
// Get the first object
obj = pool - > get ( oid_0 , true ) ;
if ( obj ! = 0 )
{
obj - > unlock ( ) ;
}
CPPUNIT_ASSERT ( obj ! = 0 ) ;
obj - > lock ( ) ;
// Delete it
pool - > drop ( obj ) ;
if ( obj ! = 0 )
{
obj - > unlock ( ) ;
}
// It should be gone now
obj = pool - > get ( oid_0 , false ) ;
CPPUNIT_ASSERT ( obj = = 0 ) ;
// The cache is cleaned, the object should be also gone from the DB
pool - > clean ( ) ;
obj = pool - > get ( oid_0 , true ) ;
CPPUNIT_ASSERT ( obj = = 0 ) ;
// But the other object must be accessible
obj = pool - > get ( oid_1 , false ) ;
check ( 1 , obj ) ;
} ;
// *****************************************************************************
static void show_options ( )
{
cout < < " Options: \n " ;
cout < < " -h --help Show this help \n "
" -s --sqlite Run Sqlite tests \n "
" -m --mysql Run MySQL tests \n "
" -l --log Keep the log file, test.log \n " ;
}
/*
* Not a true main , but a static method that can be called from the
* child classes ' true main .
* Options :
* s : run sqlite tests
* m : run mysql tests
*/
static int main ( int argc , char * * argv , CPPUNIT_NS : : TestSuite * suite )
{
// Option flags
bool sqlite_flag = false ;
bool mysql_flag = false ;
bool log_flag = false ;
// Long options
const struct option long_opt [ ] =
{
{ " sqlite " , 0 , NULL , ' s ' } ,
{ " mysql " , 0 , NULL , ' m ' } ,
{ " log " , 0 , NULL , ' l ' } ,
{ " help " , 0 , NULL , ' h ' }
} ;
int c ;
while ( ( c = getopt_long ( argc , argv , " smlh " , long_opt , NULL ) ) ! = - 1 )
switch ( c )
{
case ' s ' :
sqlite_flag = true ;
break ;
case ' m ' :
mysql_flag = true ;
break ;
case ' l ' :
log_flag = true ;
break ;
case ' h ' :
show_options ( ) ;
return 0 ;
}
// If not specified, both sqlite and mysql tests will be run
if ( ! ( sqlite_flag | | mysql_flag ) )
{
sqlite_flag = mysql_flag = true ;
}
// When a DB query fails, it tries to log the error.
// We need to set the log file, otherwise it will end in a dead-lock
NebulaLog : : init_log_system ( NebulaLog : : FILE , Log : : ERROR , " test.log " ) ;
NebulaLog : : log ( " Test " , Log : : ERROR , " Test started " ) ;
// CppUnit::TextUi::TestRunner runner_sqlite;
// runner_sqlite.addTest( suite );
// CppUnit::TextUi::TestRunner runner_mysql;
// runner_mysql.addTest( suite );
CppUnit : : TextUi : : TestRunner runner ;
runner . addTest ( suite ) ;
if ( sqlite_flag )
{
PoolTest : : mysql = false ;
NebulaLog : : log ( " Test " , Log : : ERROR , " Running Sqlite tests... " ) ;
cout < < " \n Running Sqlite tests... \n " ;
}
if ( mysql_flag )
{
PoolTest : : mysql = true ;
NebulaLog : : log ( " Test " , Log : : ERROR , " Running MySQL tests... " ) ;
cout < < " \n Running MySQL tests... \n " ;
}
runner . run ( ) ;
if ( ! log_flag )
remove ( " test.log " ) ;
2010-04-22 23:27:39 +02:00
NebulaLog : : finalize_log_system ( ) ;
2010-04-22 00:46:48 +02:00
return 0 ;
}
} ;
bool PoolTest : : mysql ;
# endif // POOL_TEST_H_