/*
	Проверка создания новой БД.
*/

#include <iostream>
#include <stdexcept>

#include <auto_ptr_3/h/obj_ptr.hpp>

#include <cpp_util_2/h/lexcast.hpp>

#include <oess_1/defs/h/ex.hpp>

#include <oess_1/io/h/mem_buf.hpp>
#include <oess_1/io/h/bstring_buf.hpp>

#include <oess_1/db/cln/h/db.hpp>
#include <oess_1/db/cln/h/local_db.hpp>

const std::string physic_name = "test/oess_db/create/test.normal";

void
test_normal_create()
	{
		const oess_1::db::storage::config_t config;

		oess_1::db::cln::local_db_t local_db( physic_name, config,
				oess_1::db::cln::local_db_t::auto_create );
		oess_1::db::cln::db_t & storage = *( local_db.query_db() ); 

		oess_1::db::cln::transaction_t trx( storage );

		// В созданном хранилище не должно быть потоков.
		unsigned int slice_count = storage.slice_names().size();
		if( slice_count )
			throw std::runtime_error( "test_normal_create FAILED!: "
					"expected slice_count: 0, real slice_count: " +
					cpp_util_2::slexcast( slice_count ) );	

		storage.slice_create( "bbb" );
		if( !storage.slice_is_exists( "bbb" ) )
			throw std::runtime_error( "test_normal_create FAILED!: "
					"stream 'bbb' NOT exists!" );	

		storage.slice_create( "aaa" );
		if( !storage.slice_is_exists( "aaa" ) )
			throw std::runtime_error( "test_normal_create FAILED!: "
					"stream 'aaa' NOT exists!" );	

		trx.commit();
	}

void
test_trx_rollback(
	oess_1::db::cln::db_t & storage )
	{
		{
			oess_1::db::cln::transaction_t trx( storage );
         
			storage.slice_create( "ccc" );
			storage.slice_create( "ddd" );
         
			// Повторное создание слайса ошибкой не считается.
			storage.slice_create( "aaa" );
			if( !storage.slice_is_exists( "aaa" ) )
				throw std::runtime_error( "test_trx_rollback FAILED!: "
						"stream 'aaa' NOT exists!" );	
         
			if( 4 != storage.slice_names().size() )
				throw std::runtime_error( "test_trx_rollback FAILED!: "
						"stream count is not 4" );

			storage.slice_destroy( "bbb" );
			if( 3 != storage.slice_names().size() )
				throw std::runtime_error( "test_trx_rollback FAILED!: "
						"stream count is not 3 (slice 'bbb' removed)" );

			bool is_test_passed = true;
			try
				{
					storage.slice_destroy( "bbb" );
					// Мы здесь не должны быть!
					is_test_passed = false;
				}
			catch( const oess_1::ex_t & x )
				{}
			if( !is_test_passed )
				throw std::runtime_error( "test_trx_rollback FAILED!: "
						"slice 'bbb' successfully destroyed again" );

			storage.slice_create( "bbb" );
			if( 4 != storage.slice_names().size() )
				throw std::runtime_error( "test_trx_rollback FAILED!: "
						"stream count is not 4 (slice 'bbb' recreated)" );
		}

		if( 2 != storage.slice_names().size() )
			throw std::runtime_error( "test_trx_rollback FAILED!: "
					"stream count is not 2" );
		if( storage.slice_is_exists( "ccc" ) )
			throw std::runtime_error( "test_trx_rollback FAILED!: "
					"stream 'ccc' exists!" );	
		if( storage.slice_is_exists( "ddd" ) )
			throw std::runtime_error( "test_trx_rollback FAILED!: "
					"stream 'ddd' exists!" );	
	}

void
test_normal_open()
	{
		const oess_1::db::storage::config_t config;

		oess_1::db::cln::local_db_t local_db( physic_name, config,
				oess_1::db::cln::local_db_t::no_overwrite );
		oess_1::db::cln::db_t & storage = *( local_db.query_db() ); 

		unsigned int slice_count = storage.slice_names().size();
		if( slice_count != 2 )
			throw std::runtime_error( "test_normal_open FAILED!: "
					"expected slice_count: 2, real slice_count: " +
					cpp_util_2::slexcast( slice_count ) );	
		if( !storage.slice_is_exists( "aaa" ) )
			throw std::runtime_error( "test_normal_open FAILED!: "
					"stream 'aaa' not exists!" );	
		if( !storage.slice_is_exists( "bbb" ) )
			throw std::runtime_error( "test_normal_open FAILED!: "
					"stream 'bbb' not exists!" );	

		test_trx_rollback( storage );
	}

int
main( int, char ** )
	{
		try
			{
				test_normal_create();
				test_normal_open();

				return 0;
			}
		catch( const std::exception & x )
			{
				std::cerr << x.what() << std::endl;
			}
		catch( ... )
			{
				std::cerr << "Unknown exception!" << std::endl;
			}

		return 2;
	}
