From 24ab24777d7cd72b7ff35a9d02cb43e26f006b0d Mon Sep 17 00:00:00 2001
From: Mike Buland <eichlan@xagasoft.com>
Date: Tue, 25 May 2010 17:45:03 +0000
Subject: More myriad testing, fixes, arrangement, etc.  UnitSuite add-ons, it
 has some command line parameters now, I would like to also add an automatic
 paramter that would switch it to a computer-readable output mode for use in a
 larger testing framework.

---
 src/cachestoremyriad.h |  3 ++-
 src/exceptionbase.h    |  2 +-
 src/myriad.cpp         | 51 ++++++++++++++++++++++++++++++++++++++++++++------
 src/myriad.h           | 31 ++++++++++++++++++++----------
 src/optparser.cpp      |  2 +-
 src/optparser.h        |  2 +-
 src/tools/myriad.cpp   |  6 +-----
 src/unitsuite.cpp      | 47 +++++++++++++++++++++++++++++++++++++++++++---
 src/unitsuite.h        |  8 +++++++-
 9 files changed, 123 insertions(+), 29 deletions(-)

(limited to 'src')

diff --git a/src/cachestoremyriad.h b/src/cachestoremyriad.h
index 3ae3ec8..bffa0bb 100644
--- a/src/cachestoremyriad.h
+++ b/src/cachestoremyriad.h
@@ -64,7 +64,8 @@ namespace Bu
 				mStore.initialize( iBlockSize, iPreAllocate );
 				int iStream = mStore.createStream();
 				if( iStream != 1 )
-					throw Bu::ExceptionBase("That's...horrible...id = %d.\n\n", iStream );
+					throw Bu::ExceptionBase("That's...horrible...id = %d.\n\n",
+							iStream );
 				MyriadStream ns = mStore.openStream( 1 );
 				Bu::Archive ar( ns, Bu::Archive::save );
 				ar << hId;
diff --git a/src/exceptionbase.h b/src/exceptionbase.h
index 178fc86..c92962f 100644
--- a/src/exceptionbase.h
+++ b/src/exceptionbase.h
@@ -114,7 +114,7 @@ class name : public parent													\
 };
 
 #define subExceptionDeclBegin( name )										\
-class name : public Bu::ExceptionBase											\
+class name : public Bu::ExceptionBase										\
 {																			\
 	public:																	\
 		name( const char *sFormat, ... ) throw ();							\
diff --git a/src/myriad.cpp b/src/myriad.cpp
index f5bc67b..2f5c14f 100644
--- a/src/myriad.cpp
+++ b/src/myriad.cpp
@@ -24,13 +24,28 @@ namespace Bu
 	}
 }
 
-Bu::Myriad::Myriad( Bu::Stream &sStore ) :
+Bu::Myriad::Myriad( Bu::Stream &sStore, int iBlockSize, int iPreallocate ) :
 	sStore( sStore ),
-	iBlockSize( 0 ),
+	iBlockSize( iBlockSize ),
 	iBlocks( 0 ),
 	iUsed( 0 ),
 	bHeaderChanged( false )
 {
+	try
+	{
+		initialize();
+	}
+	catch( Bu::MyriadException &e )
+	{
+		if( e.getErrorCode() == MyriadException::emptyStream )
+		{
+			initialize( iBlockSize, iPreallocate );
+		}
+		else
+		{
+			throw;
+		}
+	}
 }
 
 Bu::Myriad::~Myriad()
@@ -69,18 +84,19 @@ void Bu::Myriad::initialize()
 
 	unsigned char buf[4];
 	if( sStore.read( buf, 4 ) < 4 )
-		throw MyriadException("Input stream appears to be empty.");
+		throw MyriadException( MyriadException::emptyStream,
+				"Input stream appears to be empty.");
 	if( memcmp( buf, Myriad_MAGIC_CODE, 4 ) )
 	{
-		throw MyriadException(
+		throw MyriadException( MyriadException::invalidFormat,
 			"Stream does not appear to be a valid Myriad format.");
 	}
 	sStore.read( buf, 2 );
 	if( buf[0] != 1 )
-		throw MyriadException(
+		throw MyriadException( MyriadException::badVersion,
 			"We can only handle version 1 for now.");
 	if( buf[1] != 32 )
-		throw MyriadException(
+		throw MyriadException( MyriadException::invalidWordSize,
 			"We can only handle 32-bit words at the moment.");
 	sStore.read( &iBlockSize, 4 );
 	int iStreams;
@@ -342,12 +358,16 @@ int Bu::Myriad::findEmptyBlock()
 //	sio << "Myriad: findEmptyBlock(): No empty blocks, adding new one." << sio.nl;
 
 	bsBlockUsed.setSize( bsBlockUsed.getSize()+1, false );
+	/*
 	sStore.setPos( iBlockSize*iBlocks );
 
 	char *pBlock = new char[iBlockSize];
 	memset( pBlock, 0, iBlockSize );
 	sStore.write( pBlock, iBlockSize );
 	delete[] pBlock;
+	*/
+
+	sStore.setSize( (iBlocks+1)*iBlockSize );
 
 	return iBlocks++;
 }
@@ -400,6 +420,9 @@ Bu::Myriad::Stream *Bu::Myriad::findStream( int iId )
 			return *i;
 	}
 
+	throw MyriadException( MyriadException::noSuchStream,
+		"The requested stream doesn't exist and cannot be opened." );
+
 	return NULL;
 }
 
@@ -480,3 +503,19 @@ void Bu::Myriad::setStreamSize( Stream *pStream, long iSize )
 	}
 }
 
+bool Bu::Myriad::isMyriad( Bu::Stream &sStore )
+{
+	sStore.setPos( 0 );
+
+	unsigned char buf[4];
+	if( sStore.read( buf, 4 ) < 4 )
+		throw MyriadException( MyriadException::emptyStream,
+				"Input stream appears to be empty.");
+	sStore.setPos( 0 );
+	if( memcmp( buf, Myriad_MAGIC_CODE, 4 ) )
+	{
+		return false;
+	}
+	return true;
+}
+
diff --git a/src/myriad.h b/src/myriad.h
index 900037b..b5cd18c 100644
--- a/src/myriad.h
+++ b/src/myriad.h
@@ -19,7 +19,16 @@ namespace Bu
 	class Stream;
 	class MyriadStream;
 
-	subExceptionDecl( MyriadException )
+	subExceptionDeclBegin( MyriadException )
+		enum
+		{
+			emptyStream,
+			invalidFormat,
+			badVersion,
+			invalidWordSize,
+			noSuchStream
+		};
+	subExceptionDeclEnd()
 
 	/**
 	 * Numerically Indexed Data Streams.  This is a working name so I can
@@ -69,17 +78,9 @@ namespace Bu
 	{
 		friend class MyriadStream;
 	public:
-		Myriad( Bu::Stream &sStore );
+		Myriad( Bu::Stream &sStore, int iBlockSize=512, int iPreallocate=8 );
 		virtual ~Myriad();
 
-		/**
-		 * Initialize this object based on the data already in the assosiated
-		 * stream.  This will be called automatically for you if you forget,
-		 * but if you want to pre-initialize for some reason, just call this
-		 * once before you actually start doing anything with your Myriad.
-		 */
-		void initialize();
-
 		/**
 		 * Create a new Myriad system in the assosiated stream.  This should be
 		 * used carefully, it will destroy all data already within the stream.
@@ -114,7 +115,17 @@ namespace Bu
 		 */
 		void sync();
 
+		static bool isMyriad( Bu::Stream &sStore );
+
 	private:
+		/**
+		 * Initialize this object based on the data already in the assosiated
+		 * stream.  This will be called automatically for you if you forget,
+		 * but if you want to pre-initialize for some reason, just call this
+		 * once before you actually start doing anything with your Myriad.
+		 */
+		void initialize();
+
 		enum
 		{
 			blockUnused	=	0xFFFFFFFFUL
diff --git a/src/optparser.cpp b/src/optparser.cpp
index 53efe92..864d8ce 100644
--- a/src/optparser.cpp
+++ b/src/optparser.cpp
@@ -290,7 +290,7 @@ int Bu::OptParser::optHelp( StrArray /*aParams*/ )
 	return 0;
 }
 
-void Bu::OptParser::optionError( const Bu::FString sOption )
+void Bu::OptParser::optionError( const Bu::FString &sOption )
 {
 	sio << "Unregcognized option discovered: " << sOption << sio.nl << sio.nl;
 	exit( 1 );
diff --git a/src/optparser.h b/src/optparser.h
index aacafc3..2936a4b 100644
--- a/src/optparser.h
+++ b/src/optparser.h
@@ -182,7 +182,7 @@ namespace Bu
 		 * been handled by an option, and isn't an option (starts with - or --).
 		 * To change this behaviour call 
 		 */
-		virtual void optionError( const Bu::FString sOption );
+		virtual void optionError( const Bu::FString &sOption );
 
 		void setNonOption( OptionSignal sSignal );
 
diff --git a/src/tools/myriad.cpp b/src/tools/myriad.cpp
index 605aac9..535d7ac 100644
--- a/src/tools/myriad.cpp
+++ b/src/tools/myriad.cpp
@@ -121,7 +121,6 @@ int main( int argc, char *argv[] )
 			{
 				File fIn( opts.sFile, File::Read );
 				Myriad m( fIn );
-				m.initialize();
 			}
 			break;
 
@@ -135,7 +134,6 @@ int main( int argc, char *argv[] )
 			{
 				File fOut( opts.sFile, File::Write|File::Read );
 				Myriad m( fOut );
-				m.initialize();
 				m.createStream( opts.iPreallocate );
 			}
 			break;
@@ -143,14 +141,13 @@ int main( int argc, char *argv[] )
 		case modeStreamDump:
 			if( !opts.sFile.isSet() )
 			{
-				sio << "Please specify a file manipulate." << sio.nl;
+				sio << "Please specify a file to manipulate." << sio.nl;
 				return 0;
 			}
 			else
 			{
 				File fOut( opts.sFile, File::Read );
 				Myriad m( fOut );
-				m.initialize();
 				MyriadStream s = m.openStream( opts.iStream );
 				sio << "Stream " << opts.iStream << ":" << sio.nl;
 				char buf[8];
@@ -198,7 +195,6 @@ int main( int argc, char *argv[] )
 			{
 				File fOut( opts.sFile, File::Write|File::Read );
 				Myriad m( fOut );
-				m.initialize();
 				MyriadStream sOut = m.openStream(
 					m.createStream( opts.iPreallocate )
 					);
diff --git a/src/unitsuite.cpp b/src/unitsuite.cpp
index 711b9b5..7d8cc2a 100644
--- a/src/unitsuite.cpp
+++ b/src/unitsuite.cpp
@@ -8,6 +8,8 @@
 #include "bu/unitsuite.h"
 #include "bu/file.h"
 #include "bu/sio.h"
+#include "bu/optparser.h"
+#include <stdlib.h>
 
 using namespace Bu;
 
@@ -30,8 +32,17 @@ Bu::UnitSuite::~UnitSuite()
 }
 
 // Argument handling is coming soon, I promise.
-int Bu::UnitSuite::run( int /*argc*/, char * /*argv */ [] )
+int Bu::UnitSuite::run( int argc, char *argv[] )
 {
+	bool bCleanup = true;
+	OptParser p;
+	p.addOption( Bu::slot( this, &Bu::UnitSuite::onListCases ), 'l', "list",
+			"List available test cases." );
+	p.addOption( bCleanup, "no-cleanup", "Don't erase temp files.");
+	p.setOverride( "no-cleanup", "false" );
+	p.addHelpOption();
+	p.parse( argc, argv );
+
 	int iEPass = 0;
 	int iEFail = 0;
 	int iUPass = 0;
@@ -133,9 +144,12 @@ int Bu::UnitSuite::run( int /*argc*/, char * /*argv */ [] )
 	if( iUPass == 0 && iUFail == 0 )
 		sio << "\tNothing unexpected." << sio.nl << sio.nl;
 
-	for( StrList::iterator i = lFileCleanup.begin(); i; i++ )
+	if( bCleanup )
 	{
-		unlink( (*i).getStr() );
+		for( StrList::iterator i = lFileCleanup.begin(); i; i++ )
+		{
+			unlink( (*i).getStr() );
+		}
 	}
 
 	return 0;
@@ -171,3 +185,30 @@ void Bu::UnitSuite::setName( const FString &sName )
 	sSuiteName = sName;
 }
 
+int Bu::UnitSuite::onListCases( StrArray aParam )
+{
+	sio << "Test cases:" << sio.nl;
+	for( TestList::iterator i = lTests.begin(); i; i++ )
+	{
+		sio << "\t- " << Fmt( iNameWidth, 10, Fmt::Left ) << (*i).sName << "  "
+			<< (*i).eExpect << sio.nl;
+	}
+	sio << sio.nl;
+	exit( 0 );
+	return 0;
+}
+
+Bu::Formatter &Bu::operator<<( Bu::Formatter &f, const Bu::UnitSuite::Expect &e )
+{
+	switch( e )
+	{
+		case Bu::UnitSuite::expectPass:
+			return f << "expect pass";
+
+		case Bu::UnitSuite::expectFail:
+			return f << "expect fail";
+	}
+
+	return f << "**error**";
+}
+
diff --git a/src/unitsuite.h b/src/unitsuite.h
index 74aac6f..ddd3835 100644
--- a/src/unitsuite.h
+++ b/src/unitsuite.h
@@ -10,8 +10,9 @@
 
 #include <stdint.h>
 #include "bu/list.h"
-#include "fstring.h"
+#include "bu/fstring.h"
 #include "bu/file.h"
+#include "bu/array.h"
 
 namespace Bu
 {
@@ -95,6 +96,9 @@ namespace Bu
 		void add( Test fTest, const Bu::FString &sName, Expect e=expectPass );
 		void setName( const FString &sName );
 
+	private:
+		int onListCases( Bu::Array<Bu::FString> aParam );
+
 	private:
 		typedef struct TestInfo
 		{
@@ -113,6 +117,8 @@ namespace Bu
 		StrList lFileCleanup;
 		int iNameWidth;
 	};
+
+Bu::Formatter &operator<<( Bu::Formatter &f, const Bu::UnitSuite::Expect &e );
 }
 
 #define addTest( fn ) add( static_cast<Bu::UnitSuite::Test>(&fn), #fn )
-- 
cgit v1.2.3