diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2022-12-07 13:17:14 +0100 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2022-12-07 13:17:14 +0100 |
commit | 4875a3dd9b183dcd2256e2abfc4ccf7484c233b4 (patch) | |
tree | 0abbea881ded030851014ffdd60fbf71fead8f65 /src/tests | |
parent | daf17154bf13139d9375f48525d19d6aaba08155 (diff) |
New upstream version 4.0.2upstream/4.0.2
Diffstat (limited to 'src/tests')
24 files changed, 6821 insertions, 0 deletions
diff --git a/src/tests/tstfuncs.cpp b/src/tests/tstfuncs.cpp new file mode 100755 index 0000000..c499d3f --- /dev/null +++ b/src/tests/tstfuncs.cpp @@ -0,0 +1,581 @@ +/* tstfuncs.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014,2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +time_t timer; + +xbDouble ChronTime(); +void InitTime(); + +xbBool dblEquals( xbDouble a, xbDouble b, xbDouble epsilon ); +xbInt16 TestMethod( xbInt16 PrintOption, const char * title, const xbString &result, const char * expectedResult, size_t expectedLen ); +xbInt16 TestMethod( xbInt16 PrintOption, const char * title, char result, char expectedResult ); +xbInt16 TestMethod( xbInt16 PrintOption, const char * title, xbInt32 result, xbInt32 expectedResult ); +//xbInt16 TestMethod( xbInt16 PrintOption, const char * title, xbUInt32 result, xbUInt32 expectedResult ); +xbInt16 TestMethod( xbInt16 PrintOption, const char * title, xbUInt64 result, xbUInt64 expectedResult ); +xbInt16 TestMethod( xbInt16 PrintOption, const char * title, xbFloat result, xbFloat expectedResult ); +xbInt16 TestMethod( xbInt16 PrintOption, const char * title, xbDouble result, xbDouble expectedResult ); +xbInt16 TestMethod( xbInt16 PrintOption, const char * title, xbDouble result, xbDouble expectedResult, xbDouble dEpsilon ); + + +xbInt16 FileCompare( xbXBase &x, xbInt16 iPo, const xbString &sFile1, const xbString &sFile2, const xbString &sSkipBytes ); + + +#ifdef XB_LOCKING_SUPORT +xbInt16 SetCmd( xbXBase &x, const xbString &sFileName, const xbString &sCmd, const char cSrc, xbInt16 iPo ); +xbInt16 GetCmd( xbXBase &x, const xbString &sFileName, xbString &sCmd, const char cSrc, xbInt16 iPo ); +#endif + +#if defined( XB_DBF4_SUPPORT ) && defined( XB_MEMO_SUPPORT ) + +xbInt16 TestDbt4Method( xbInt16 PrintOption, const char * title, xbMemo * m, xbUInt32 ulHdrNext, xbUInt32 ulBlockCnt, xbString sNodeChain ); +xbInt16 TestDbt4Method( xbInt16 PrintOption, const char * title, xbMemo * m, xbUInt32 ulHdrNext, xbUInt32 ulBlockCnt, xbString sNodeChain ){ + + xbUInt32 ulLastDataBlock = 0L; + xbUInt32 ulHdrNextBlock = 0L; + xbInt16 iRc = 0; + + iRc = m->GetHdrNextBlock( ulHdrNextBlock ); + if( iRc != XB_NO_ERROR ){ + std::cout << std::endl << "[FAIL 1] " << title << std::endl; + std::cout << "Error [" << iRc << "] in GetHdrNextBlock" << std::endl; + return -1; + } + + iRc = m->CalcLastDataBlock( ulLastDataBlock ); + if( iRc != XB_NO_ERROR ){ + std::cout << std::endl << "[FAIL 2] " << title << std::endl; + std::cout << "Error [" << iRc << "] in CalcLastDataBlock" << std::endl; + return -1; + } + + if( ulHdrNext > 0 ){ + if( ulHdrNextBlock != ulHdrNext ){ + std::cout << std::endl << "[FAIL 3] " << title << std::endl; + std::cout << "Expected Header Next Block = [" << ulHdrNext << "] Actual = [" << ulHdrNextBlock << "]" << std::endl; + return -1; + } + if( PrintOption == 2 ){ + xbString sMsg; + sMsg.Sprintf( "[PASS][%3.4f] %s Expected matches actual Len=[%ld] Data=[%lds]\n", + ChronTime(), title, ulHdrNextBlock, ulHdrNext ); + std::cout << sMsg.Str(); + // std::cout << "[PASS][" << ChronTime() << "] " << title << " Expected matches actual HdrBlock=[" << ulHdrNextBlock << "] Data=[" << ulHdrNext << "]" << std::endl; + } else if( PrintOption == 1 ) + std::cout << "[PASS] " << title << std::endl; + } + + if( ulBlockCnt > 0 ){ + if( ulLastDataBlock != ulBlockCnt ){ + std::cout << std::endl << "[FAIL 4] " << title << std::endl; + std::cout << "Expected Block Count = [" << ulBlockCnt << "] Actual = [" << ulLastDataBlock << "]" << std::endl; + return -1; + } + if( PrintOption == 2 ){ + xbString sMsg; + sMsg.Sprintf( "[PASS][%3.4f] %s Expected matches actual Len=[%ld] Data=[%lds]\n", + ChronTime(), title, ulLastDataBlock, ulBlockCnt ); + std::cout << sMsg.Str(); + // std::cout << "[PASS][" << ChronTime() << "] " << title << " Expected matches actual LastBlock=[" << ulLastDataBlock << "] Data=[" << ulBlockCnt << "]" << std::endl; + } else if( PrintOption == 1 ) + std::cout << "[PASS] " << title << std::endl; + } + + #ifdef XB_DEBUG_SUPPORT + xbMemoDbt4 *m4 = (xbMemoDbt4 *) m; + if( sNodeChain != "-1" ){ + xbUInt32 ulNode = ulHdrNextBlock; + xbUInt32 ulNextBlock; + xbUInt32 ulFreeBlockCnt; + xbString sActualNodeChain; + + while( ulNode < ulLastDataBlock ){ + iRc = m4->ReadFreeBlockHeader( ulNode, ulNextBlock, ulFreeBlockCnt ); + if( iRc != XB_NO_ERROR ){ + std::cout << std::endl << "[FAIL 5] " << title << std::endl; + std::cout << "Error [" << iRc << "] in CalcLastDataBlock" << std::endl; + return -1; + } + if( sActualNodeChain != "" ) + sActualNodeChain += ","; + sActualNodeChain.Sprintf( "%s%ld,%ld,%ld", sActualNodeChain.Str(), ulNode, ulFreeBlockCnt, ulNextBlock ); + ulNode = ulNextBlock; + } + if( sNodeChain != sActualNodeChain ){ + std::cout << std::endl << "[FAIL 6] " << title << std::endl; + std::cout << "Expected Block Chain = [" << sNodeChain.Str() << "] Actual = [" << sActualNodeChain.Str() << "]" << std::endl; + return -1; + } + if( PrintOption == 2 ){ + xbString sMsg; + sMsg.Sprintf( "[PASS][%3.4f] %s Expected matches actual Len=[%d] Data=[%s]\n", ChronTime(), title, sNodeChain.Str() ); + std::cout << sMsg.Str(); + //std::cout << "[PASS][" << ChronTime() << "] " << title << " Expected matches actual BlockChain=[" << sNodeChain.Str() << "]" << std::endl; + } else if( PrintOption == 1 ) + std::cout << "[PASS] " << title << std::endl; + } + #endif // XB_DEBUG_SUPPORT" + + return 0; +} +#endif + + + +xbInt16 TestMethod( xbInt16 PrintOption, const char * title, const xbString &sResult, const char * expectedResult, size_t expectedLen ){ + xbInt16 rc = 0; + + if( sResult == expectedResult && sResult.Len() == expectedLen ){ + if( PrintOption == 2 ){ + xbString sMsg; + sMsg.Sprintf( "[PASS][%3.4f] %s Expected matches actual Len=[%d] Data=[%s]\n", ChronTime(), title, expectedLen, expectedResult ); + std::cout << sMsg.Str(); + } else if( PrintOption == 1 ) { + std::cout << "[PASS] " << title << std::endl; + } + } else { + std::cout << std::endl << "[FAIL 1] " << title << std::endl; + std::cout << " Expected Len = [" << expectedLen << "] Expected Data = [" << expectedResult << "]" << std::endl; + std::cout << " Actual Len = [" << sResult.Len() << "] Actual Data = [" << sResult.Str() << "]" << std::endl; + + if( sResult.Len() == expectedLen ) + printf( "lengths match\n" ); + else + printf( "lengths dont match\n" ); + + if( sResult == expectedResult ) + printf( "result matches\n" ); + else + printf( "result does not match\n" ); + + rc = -1; + } + return rc; +} + +xbInt16 TestMethod( xbInt16 PrintOption, const char * title, char result, char expectedResult ){ + xbInt16 rc = 0; + if( result == expectedResult ){ + if( PrintOption == 2 ){ + xbString sMsg; + sMsg.Sprintf( "[PASS][%3.4f] %s Expected matches actual Data=[%c]\n", ChronTime(), title, expectedResult ); + std::cout << sMsg.Str(); + // std::cout << "[PASS][" << ChronTime() << "] " << title << " Expected matches actual Data=[" << expectedResult << "]" << std::endl; + } else if( PrintOption == 1 ) + std::cout << "[PASS] " << title << std::endl; + rc = 0; + } else { + std::cout << std::endl << "[FAIL 2] " << title << std::endl; + std::cout << " Expected Data = [" << expectedResult << "]" << std::endl; + std::cout << " Actual Data = [" << result << "]" << std::endl; + rc = -1; + } + return rc; +} + +xbInt16 TestMethod( xbInt16 PrintOption, const char * title, xbInt32 result, xbInt32 expectedResult ){ + xbInt16 rc = 0; + if( result == expectedResult ){ + if( PrintOption == 2 ){ + xbString sMsg; + sMsg.Sprintf( "[PASS][%3.4f] %s Expected matches actual Data=[%d]\n", ChronTime(), title, expectedResult ); + std::cout << sMsg.Str(); + // std::cout << "[PASS][" << ChronTime() << "] " << title << " Expected matches actual Data=[" << expectedResult << "]" << std::endl; + } else if( PrintOption == 1 ) + std::cout << "[PASS] " << title << std::endl; + rc = 0; + } else { + std::cout << std::endl << "[FAIL 3] " << title << std::endl; + std::cout << " Expected Data = [" << expectedResult << "]" << std::endl; + std::cout << " Actual Data = [" << result << "]" << std::endl; + rc = -1; + } + return rc; +} + + +/* +xbInt16 TestMethod( xbInt16 PrintOption, const char * title, xbUInt32 result, xbUInt32 expectedResult ){ + xbInt16 rc = 0; + if( result == expectedResult ){ + if( PrintOption == 2 ) + std::cout << "[PASS][" << ChronTime() << "] " << title << " Expected matches actual Data=[" << expectedResult << "]" << std::endl; + else if( PrintOption == 1 ) + std::cout << "[PASS] " << title << std::endl; + rc = 0; + } else { + std::cout << std::endl << "[FAIL 3] " << title << std::endl; + std::cout << " Expected Data = [" << expectedResult << "]" << std::endl; + std::cout << " Actual Data = [" << result << "]" << std::endl; + rc = -1; + } + return rc; +} +*/ + +xbInt16 TestMethod( xbInt16 PrintOption, const char * title, xbUInt64 result, xbUInt64 expectedResult ){ + xbInt16 rc = 0; + if( result == expectedResult ){ + if( PrintOption == 2 ){ + xbString sMsg; + sMsg.Sprintf( "[PASS][%f] %3.4s Expected matches actual Data=[%ld]\n", ChronTime(), title, expectedResult ); + std::cout << sMsg.Str(); + // std::cout << "[PASS][" << ChronTime() << "] " << title << " Expected matches actual Data=[" << expectedResult << "]" << std::endl; + } else if( PrintOption == 1 ) + std::cout << "[PASS] " << title << std::endl; + rc = 0; + } else { + std::cout << std::endl << "[FAIL 4] " << title << std::endl; + std::cout << " Expected Data = [" << expectedResult << "]" << std::endl; + std::cout << " Actual Data = [" << result << "]" << std::endl; + rc = -1; + } + return rc; +} + +xbInt16 TestMethod( xbInt16 PrintOption, const char * title, xbFloat result, xbFloat expectedResult ){ + xbInt16 rc = 0; + if( result == expectedResult ){ + if( PrintOption == 2 ){ + xbString sMsg; + sMsg.Sprintf( "[PASS][%f] %3.4s Expected matches actual Data=[%f]\n", ChronTime(), title, expectedResult ); + std::cout << sMsg.Str(); + // std::cout << "[PASS][" << ChronTime() << "] " << title << " Expected matches actual Data=[" << expectedResult << "]" << std::endl; + } else if( PrintOption == 1 ) + std::cout << "[PASS] " << title << std::endl; + rc = 0; + } else { + std::cout << std::endl << "[FAIL 5] " << title << std::endl; + std::cout << " Expected Data = [" << expectedResult << "]" << std::endl; + std::cout << " Actual Data = [" << result << "]" << std::endl; + rc = -1; + } + return rc; +} + +xbInt16 TestMethod( xbInt16 PrintOption, const char * title, xbDouble result, xbDouble expectedResult ){ + xbInt16 rc = 0; + if( result == expectedResult ){ + // if( dblEquals( result, expectedResult ) == 0 ){ + if( PrintOption == 2 ){ + xbString sMsg; + sMsg.Sprintf( "[PASS][%3.4f] %s Expected matches actual Data=[%f]\n", ChronTime(), title, expectedResult ); + std::cout << sMsg.Str(); + //std::cout << "[PASS][" << ChronTime() << "] " << title << " Expected matches actual Data=[" << expectedResult << "]" << std::endl; + } else if( PrintOption == 1 ) + std::cout << "[PASS] " << title << std::endl; + rc = 0; + } else { + std::cout << std::endl << "[FAIL 6] " << title << std::endl; + std::cout << " Expected Data = [" << expectedResult << "]" << std::endl; + std::cout << " Actual Data = [" << result << "]" << std::endl; + rc = -1; + } + return rc; +} + + +// next three routines used to do a compare on double values +xbDouble dblMax( xbDouble a, xbDouble b ){ + if( a > b ) + return a; + else + return b; +} +xbDouble dblMin( xbDouble a, xbDouble b ){ + if( a < b ) + return a; + else + return b; +} +xbBool dblEquals( xbDouble a, xbDouble b, xbDouble epsilon = 0.0001 ){ + + // std::cout << "a=[" << a << "] b=[ " << b << "] dblmax [" << dblAbsMax( a, b ) << "] min [" << dblAbsMin( a, b ) << "]\n"; + if( a < 0 && b >= 0 ) + return xbFalse; + else if( a >= 0 && b < 0 ) + return xbFalse; + if( (dblMax( a ,b ) - dblMin( a, b )) < epsilon ) + return xbTrue; + else + { +// std::cout << "no match a=[" << a << "] b=[" << b << "] dblmax [" << dblAbsMax( a, b ) << "] min [" << dblAbsMin( a, b ) << "]\n"; + return xbFalse; + } +} + +xbInt16 TestMethod( xbInt16 PrintOption, const char * title, xbDouble result, xbDouble expectedResult, xbDouble dEpsilon ){ + xbInt16 rc; + if( dblEquals( result, expectedResult, dEpsilon ) == xbTrue ){ + if( PrintOption == 2 ){ + xbString sMsg; + sMsg.Sprintf( "[PASS][%3.4f] %s Expected matches actual Data=[%f]\n", ChronTime(), title, expectedResult ); + std::cout << sMsg.Str(); + //std::cout << "[PASS][" << ChronTime() << "] " << title << " Expected matches actual Data=[" << expectedResult << "]" << std::endl; + } else if( PrintOption == 1 ) + std::cout << "[PASS] " << title << std::endl; + rc = 0; + } else { + std::cout << std::endl << "[FAIL 6] " << title << std::endl; + std::cout << " Expected Data = [" << expectedResult << "]" << std::endl; + std::cout << " Actual Data = [" << result << "]" << std::endl; + rc = -1; + } + return rc; +} + + +#ifdef XB_LOCKING_SUPPORT + +xbInt16 GetCmd( xbXBase &x, const xbString &sFileName, xbString &sCmd, const char cSrc, xbInt16 iPo ){ + xbInt16 iTryCnt = 0; + xbInt16 iMaxTries = 10; + char cInBuf[256]; + FILE *f; + xbBool bDone = xbFalse; + xbString sMsg; + + while( !bDone && iTryCnt < iMaxTries ){ + + #ifdef HAVE__FSOPEN_F + // 0x40 is SH_DENYNO or _SH_DENYNO + if(( f = _fsopen( sFileName.Str(), "r", 0x40 )) == NULL){ + sMsg.Sprintf( "GetCmd _fsopen() error opening [%s]", sFileName.Str() ); + x.WriteLogMessage( sMsg ); + std::cout << sMsg.Str() << "\n"; + x.xbSleep( 250 ); + iTryCnt++; + } + + #else + + if(( f = fopen( sFileName.Str(), "r" )) == NULL ){ + sMsg.Sprintf( "GetCmd fopen() error opening [%s]", sFileName.Str() ); + x.WriteLogMessage( sMsg ); + std::cout << sMsg.Str() << "\n"; + x.xbSleep( 250 ); + iTryCnt++; + } + #endif + + else { + memset( cInBuf, 0x00, 256 ); + fgets( cInBuf, 256, f ); + fclose( f ); + sCmd = cInBuf; + if( sCmd != "" ) + bDone = xbTrue; + else{ + x.xbSleep( 250 ); + } + } + } + + #ifdef XB_LOGGING_SUPPORT + if( iPo > 0 ){ + sMsg.Sprintf( "[%c] GetCmd [%s]", cSrc, sCmd.Str()); + x.WriteLogMessage( sMsg ); + x.FlushLog(); + } + #endif + + if( iTryCnt >= iMaxTries ) + return -1; + else + return 0; +} + +xbInt16 SetCmd( xbXBase &x, const xbString &sFileName, const xbString &sCmd, const char cSrc, xbInt16 iPo ){ + + xbInt16 iTryCnt = 0; + FILE *f; + xbBool bDone = xbFalse; + + #ifdef XB_LOGGING_SUPPORT + if( iPo > 0 ){ + xbString sMsg; + sMsg.Sprintf( "[%c] SetCmd [%s] FileName [%s]", cSrc, sCmd.Str(), sFileName.Str()); + x.WriteLogMessage( sMsg ); + x.FlushLog(); + } + #endif + + while( !bDone && iTryCnt < 10 ){ + + #ifdef HAVE__FSOPEN_F + // 0x40 is SH_DENYNO or _SH_DENYNO + if(( f = _fsopen( sFileName.Str(), "r", 0x40 )) == NULL){ + x.xbSleep( 250 ); + iTryCnt++; + } + + #else + if(( f = fopen( sFileName.Str(), "w" )) == NULL ){ + x.xbSleep( 250 ); + iTryCnt++; + } + #endif + + else { + fputs( sCmd.Str(), f ); + fflush( f ); + fclose( f ); + bDone = xbTrue; + } + } + if( iTryCnt == 10 ) + return -1; + else{ + x.xbSleep( 250 ); + return 0; + } +} + + + +#endif +void InitTime(){ + time( &timer ); +} + + +xbDouble ChronTime(){ + time_t tWork = timer; + time( &timer ); + return difftime( timer, tWork ); + +} + + + +xbInt16 FileCompare( xbXBase &x, xbInt16 iPo, const xbString &sFile1, const xbString &sFile2, const xbString &sSkipBytes ){ + +/* + iPo print option + sFile1 - File 1 + sFile2 - File 2 + sSkipBytes - comma separated list of bytes to skip the compare on +*/ + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + xbInt16 iErrorCnt = 0; + xbFile f1( &x ); + xbFile f2( &x ); + xbString sMsg; + char c1; + char c2; + + if( iPo > 0 ){ + std::cout << "FileCompare\n"; + std::cout << "Skip bytes = " << sSkipBytes.Str() << std::endl; + std::cout << sFile1.Str() << std::endl; + std::cout << sFile2.Str() << std::endl; + } + + xbLinkListOrd<xbInt32> llO; + llO.SetDupKeys( 0 ); + if( sSkipBytes.Len() > 0 ){ + xbString sNode; + xbUInt32 iCommaCnt = sSkipBytes.CountChar( ',' ); + for( xbUInt32 i = 0; i < (iCommaCnt+1); i++ ){ + sNode.ExtractElement( sSkipBytes, ',', i+1, 0 ); + //std::cout << "Adding key = " << atol( sNode.Str()) << std::endl; + llO.InsertKey( atol( sNode.Str())); + } + } + + xbInt32 iPos = 0; + try{ + + if(( iRc = f1.xbFopen( "r", sFile1, XB_SINGLE_USER )) != XB_NO_ERROR ){ + iErrorStop = 10; + iErrorCnt++; + throw iRc; + } + + if(( iRc = f2.xbFopen( "r", sFile2, XB_SINGLE_USER )) != XB_NO_ERROR ){ + iErrorStop = 20; + iErrorCnt++; + throw iRc; + } + + xbUInt64 uiFs1; + xbUInt64 uiFs2; + + if(( iRc = f1.GetFileSize( uiFs1 )) != XB_NO_ERROR ){ + iErrorStop = 30; + iErrorCnt++; + throw iRc; + } + + if(( iRc = f2.GetFileSize( uiFs2 )) != XB_NO_ERROR ){ + iErrorStop = 40; + iErrorCnt++; + throw iRc; + } + + // std::cout << "file size " << uiFs1 << " " << uiFs2 << "\n"; + + f1.xbRewind(); + f2.xbRewind(); + + while( !f1.xbFeof() && !f2.xbFeof()){ + f1.xbFgetc( c1 ); + f2.xbFgetc( c2 ); + if( c1 != c2 ){ + if( !llO.KeyExists( iPos )){ + iErrorCnt++; + if( iPo > 0 ){ + sMsg.Sprintf( "Diff %ld %x %x\n", iPos, c1, c2 ); + std::cout << sMsg.Str(); + } + } + } + iPos++; + } + } + + catch( xbInt16 ){ + if( iPo > 0 ){ + std::cout << "File Compare Error Count = " << iErrorCnt << std::endl; + + switch( iErrorStop ){ + case 10: + std::cout << "Error opening file = " << sFile1.Str() << std::endl; + break; + case 20: + std::cout << "Error opening file = " << sFile2.Str() << std::endl; + break; + case 30: + std::cout << "GetFileSize() error " << sFile1.Str() << std::endl; + break; + case 40: + std::cout << "GetFileSize() error " << sFile2.Str() << std::endl; + break; + default: + break; + } + } + } + + if( f1.FileIsOpen() ) + f1.xbFclose(); + if( f1.FileIsOpen() ) + f1.xbFclose(); + + return iRc; +} + + diff --git a/src/tests/xb_test_bcd.cpp b/src/tests/xb_test_bcd.cpp new file mode 100755 index 0000000..1eab20f --- /dev/null +++ b/src/tests/xb_test_bcd.cpp @@ -0,0 +1,128 @@ +/* xb_test_bcd.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014,2017,2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the xb bcd functions +// usage: xb_test_expnode QUITE|NORMAL|VERBOSE + +#include "xbase.h" +using namespace xb; + +#include "tstfuncs.cpp" + +/**************************************************************************/ + +int main( int argCnt, char **av ) +{ + + #ifdef XB_INDEX_SUPPORT + + xbInt16 iRc = 0; + xbInt16 iPo = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + iPo = 0; + else if( av[1][0] == 'V' ) + iPo = 2; + } + + + xbXBase x; + + #ifdef XB_LOGGING_SUPPORT + x.EnableMsgLogging(); + if( iPo ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + x.SetDataDirectory( PROJECT_DATA_DIR ); + x.EnableMsgLogging(); + + + if( iPo > 0 ){ + std::cout << "XBase bcd testing program.." << std::endl; + std::cout << "This program tests the bcd logic." << std::endl; + } + + iRc += TestMethod( iPo, "sizeof( xbBcdStruct )", (xbInt32) sizeof( xbBcdStruct ), (xbInt32) 12 ); + + xbString s1( -12345.60 ); + xbBcd bcd1( s1 ); + xbDouble d1; + bcd1.ToDouble( d1 ); + xbString s2( d1 ); + bcd1.ToString( s2 ); + + iRc += TestMethod( iPo, "String Constructor1", d1, -12345.6 ); + iRc += TestMethod( iPo, "String Constructor2", s2.Str(), "-12345.6", 8 ); + + d1 = 0034.04; + xbBcd bcd2( d1 ); + bcd2.ToString( s2 ); + iRc += TestMethod( iPo, "xbDouble Constructor1", s2.Str(), "34.04", 5 ); + + // test the sign comparison logic + xbInt16 iComp = bcd1.Compare( bcd2 ); + iRc += TestMethod( iPo, "Sign Compare 1", iComp, -1 ); + iComp = bcd2.Compare( bcd1 ); + iRc += TestMethod( iPo, "Sign Compare 2", iComp, 1 ); + + // bcd length compare scenarios + bcd1.Set( 123 ); + iRc += TestMethod( iPo, "Length Compare 1", bcd1.Compare( 12 ), 1 ); + iRc += TestMethod( iPo, "Length Compare 2", bcd1.Compare( 1234 ), -1 ); + bcd1.Set( -456 ); + iRc += TestMethod( iPo, "Length Compare 3", bcd1.Compare( -12 ), -1 ); + iRc += TestMethod( iPo, "Length Compare 4", bcd1.Compare( -1234 ), 1 ); + + // same length, value compares + bcd1.Set( 11 ); + iRc += TestMethod( iPo, "Value Compare 1", bcd1.Compare( 10 ), 1 ); + + bcd1.Set( 111 ); + iRc += TestMethod( iPo, "Value Compare 2", bcd1.Compare( 110 ), 1 ); + + + bcd1.Set( 111.111 ); + iRc += TestMethod( iPo, "Value Compare 3", bcd1.Compare( 111.112 ), -1 ); + + bcd1.Set( -100 ); + iRc += TestMethod( iPo, "Value Compare 4", bcd1.Compare( -111 ), 1 ); + iRc += TestMethod( iPo, "Value Compare 5", bcd1.Compare( -99 ), -1 ); + + bcd1.Set( (xbDouble) 0 ); + iRc += TestMethod( iPo, "Value Compare 6", bcd1.Compare( (xbDouble) 0 ), 0 ); + + if( iPo > 0 || iRc < 0 ) + fprintf( stdout, "Total Errors = %d\n", iRc * -1 ); + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], iRc * -1 ); + x.WriteLogMessage( sMsg ); + #endif + + return iRc; + #else + return XB_NO_ERROR; + #endif // XB_INDEX_SUPPORT + +} diff --git a/src/tests/xb_test_date.cpp b/src/tests/xb_test_date.cpp new file mode 100755 index 0000000..1d9b523 --- /dev/null +++ b/src/tests/xb_test_date.cpp @@ -0,0 +1,189 @@ +/* xb_test_date.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014,2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the date class xbDate + +// usage: xb_test_date QUITE|NORMAL|VERBOSE + + +#include "xbase.h" + +using namespace xb; + +#include "tstfuncs.cpp" + + +int main( int argCnt, char **av ) +{ + int iRc = 0; + xbInt16 po = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + po = 0; + else if( av[1][0] == 'V' ) + po = 2; + } + +#ifdef XB_LOGGING_SUPPORT + xbXBase x; + x.EnableMsgLogging(); + if( po ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); +#endif + InitTime(); + + xbDate d1; +#ifdef XB_DEBUG_SUPPORT + if( po > 0 ) + d1.DumpDateTables(); +#endif + + xbDate d2( "19890209" ); + xbString s3 = "20120709"; + xbDate d3( s3 ); + xbString s4; + xbString sFmt = ""; + xbString sOutDate; + xbString s; + + iRc += TestMethod( po, "FormatDate( '', sOutDate ) (sys default format)", d3.FormatDate( sFmt, sOutDate ), 0 ); + iRc += TestMethod( po, "FormatDate( '', sOutDate ) (sys default format)", sOutDate, "07/09/12", 8 ); + iRc += TestMethod( po, "CenturyOf()" , d3.CenturyOf(), 20 ); + iRc += TestMethod( po, "YearOf()", d3.YearOf(), 2012 ); + iRc += TestMethod( po, "MonthOf()", d3.MonthOf(), 7 ); + + iRc += TestMethod( po, "DayOf( XB_FMT_DAY )", d3.DayOf( XB_FMT_WEEK ), 2 ); + iRc += TestMethod( po, "DayOf( XB_FMT_MONTH )", d3.DayOf( XB_FMT_MONTH ), 9 ); + iRc += TestMethod( po, "DayOf( XB_FMT_YEAR )", d3.DayOf( XB_FMT_YEAR ), 191 ); + + iRc += TestMethod( po, "DateIsValid( '12345678' )", d3.DateIsValid( "12345678" ), 0 ); + iRc += TestMethod( po, "d3.DateIsValid( '20120708' )", d3.DateIsValid( "20120708" ), 1 ); + iRc += TestMethod( po, "d3.IsLeapYear()", d3.IsLeapYear(), 1 ); + iRc += TestMethod( po, "d2.IsLeapYear()", d2.IsLeapYear(), 0 ); + + d1.Set( "20010102" ); + iRc += TestMethod( po, "d1.Set('20010102')", d1.Str(), "20010102", 8 ); + iRc += TestMethod( po, "d1.CalcRollingCenturyForYear(10)", d1.CalcRollingCenturyForYear( 10 ), 20 ); + + iRc += TestMethod( po, "d1.JulianDays()", d1.JulianDays(), 2451912 ); + + + iRc += TestMethod( po, "d1.Set( '20140709' )", d1.Set( "20140709" ) , 0 ); + d1.CharDayOf( s ); + iRc += TestMethod( po, "d1.CharDayOf(s)", s, "Wednesday", 9 ); + + d1.CharMonthOf( s ); + iRc += TestMethod( po, "d1.CharMonthOf()", s, "July", 4 ); + + iRc += TestMethod( po, "d1.JulToDate8( 2451913 )", d1.JulToDate8( 2451912 ), 0 ); + iRc += TestMethod( po, "d1.JulToDate8( 2451913 )", d1.Str(), "20010102", 8 ); + iRc += TestMethod( po, "d1.LastDayOfMonth()", d1.LastDayOfMonth(), 0 ); + iRc += TestMethod( po, "d1.LastDayOfMonth()", d1.Str(), "20010131", 8 ); + + iRc += TestMethod( po, "d1.CTOD( '12/01/02' )", d1.CTOD( "12/01/02" ), 0 ); + iRc += TestMethod( po, "d1.CTOD( '12/01/02' )", d1.Str(), "20021201", 8 ); + + xbString s1, s2; + s1 = "MM-DD-YY"; + d1 = "20130402"; + iRc+= TestMethod( po, "d1.FormatDate( s1, sOutDate )", d1.FormatDate( s1, sOutDate ), 0 ); + iRc+= TestMethod( po, "d1.FormatDate( s1, sOutDate )", sOutDate, "04-02-13", 8 ); + + d1 = "20120203"; + iRc += TestMethod( po, "d1=20120203", d1.Str(), "20120203", 8 ); + + s1 = "20130405"; + d1 = s1; + iRc += TestMethod( po, "d1=s1", d1.Str(), "20130405", 8 ); + + d2 = d1; + iRc += TestMethod( po, "d2=d1", d2.Str(), "20130405", 8 ); + + d2+=5; + iRc += TestMethod( po, "d2+=5", d2.Str(), "20130410", 8 ); + + d2-=7; + iRc += TestMethod( po, "d2-=5", d2.Str(), "20130403", 8 ); + + d2++; + iRc += TestMethod( po, "d2++", d2.Str(), "20130404", 8 ); + + d2--; + iRc+= TestMethod( po, "d2--", d2.Str(), "20130403", 8 ); + iRc+= TestMethod( po, "d2-d1", d1-d2, 2 ); + iRc+= TestMethod( po, "d1+2", d1+2, "20130407", 8 ); + iRc+= TestMethod( po, "d1-5", d1-5, "20130402", 8 ); + +// d1.Dump( "d1" ); +// d2.Dump( "d2" ); + + iRc+= TestMethod( po, "d1==d2", d1==d2, 0 ); + d2 = d1; + iRc+= TestMethod( po, "d1==d2", d1==d2, 1 ); + iRc+= TestMethod( po, "d1>=d2", d1>=d2, 1 ); + iRc+= TestMethod( po, "d1<=d2", d1<=d2, 1 ); + iRc+= TestMethod( po, "d1!=d2", d1!=d2, 0 ); + d2++; + iRc+= TestMethod( po, "d1!=d2", d1!=d2, 1 ); + + iRc+= TestMethod( po, "d1>d2", d1>d2, 0 ); + iRc+= TestMethod( po, "d1>=d2", d1>=d2, 0 ); + iRc+= TestMethod( po, "d1<d2", d1<d2, 1 ); + iRc+= TestMethod( po, "d1<=d2", d1<=d2, 1 ); + + d2-=2; + iRc+= TestMethod( po, "d1>d2", d1>d2, 1 ); + iRc+= TestMethod( po, "d1>=d2", d1>=d2, 1 ); + iRc+= TestMethod( po, "d1<d2", d1<d2, 0 ); + iRc+= TestMethod( po, "d1<=d2", d1<=d2, 0 ); + iRc+= TestMethod( po, "d1-d2", d1-d2, 1 ); + +/* + xbDate d4( "20171015" ); + std::cout << "day of [" << d4.Str() << "][" << d4.DayOf( XB_FMT_WEEK ) << "]\n"; + d4++; + std::cout << "day of [" << d4.Str() << "][" << d4.DayOf( XB_FMT_WEEK ) << "]\n"; + d4++; + std::cout << "day of [" << d4.Str() << "][" << d4.DayOf( XB_FMT_WEEK ) << "]\n"; + d4++; + std::cout << "day of [" << d4.Str() << "][" << d4.DayOf( XB_FMT_WEEK ) << "]\n"; + d4++; + std::cout << "day of [" << d4.Str() << "][" << d4.DayOf( XB_FMT_WEEK ) << "]\n"; + d4++; + std::cout << "day of [" << d4.Str() << "][" << d4.DayOf( XB_FMT_WEEK ) << "]\n"; + d4++; + std::cout << "day of [" << d4.Str() << "][" << d4.DayOf( XB_FMT_WEEK ) << "]\n"; + d4++; + std::cout << "day of [" << d4.Str() << "][" << d4.DayOf( XB_FMT_WEEK ) << "]\n"; +*/ + + if( po > 0 || iRc < 0 ) + fprintf( stdout, "Total Errors = %d\n", iRc * -1 ); + +#ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], iRc * -1 ); + x.WriteLogMessage( sMsg ); +#endif + + return iRc; +} diff --git a/src/tests/xb_test_dbf_v3_memos.cpp b/src/tests/xb_test_dbf_v3_memos.cpp new file mode 100755 index 0000000..e364741 --- /dev/null +++ b/src/tests/xb_test_dbf_v3_memos.cpp @@ -0,0 +1,233 @@ +/* xb_test_xbdbf_v3_memos.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014,2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the version III memo field logic + +// usage: xb_test_dbf_v3_memos QUITE|NORMAL|VERBOSE + + +#include "xbase.h" + +using namespace xb; + +#include "tstfuncs.cpp" + + +int main( int argCnt, char **av ) +{ + int rc = 0; + int rc2 = 0; + int po = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + po = 0; + else if( av[1][0] == 'V' ) + po = 2; + } + + + xbSchema MyV3Record[] = + { + { "RECID", XB_NUMERIC_FLD, 8, 0 }, + { "MEMOFLD1", XB_MEMO_FLD, 10, 0 }, + { "MEMOFLD2", XB_MEMO_FLD, 10, 0 }, + { "",0,0,0 } + }; + + + xbXBase x; + +#ifdef XB_LOGGING_SUPPORT + + x.EnableMsgLogging(); + if( po ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); + +#endif + + x.SetDataDirectory( PROJECT_DATA_DIR ); + x.EnableMsgLogging(); + x.DisableDefaultAutoLock(); + InitTime(); + + if( po > 0 ) + std::cout << "Default Data Directory is [" << x.GetDataDirectory().Str() << "]" << std::endl; + + xbDbf3 V3Dbf( &x ); /* version 3 dbf file */ + + rc2 = V3Dbf.CreateTable( "TestV3_memos.DBF", "TestV3", MyV3Record, XB_OVERLAY, XB_MULTI_USER ); + rc += TestMethod( po, "CreateTable()", (xbInt32) rc2, XB_NO_ERROR ); + + + if( rc2 ) + x.DisplayError( rc2 ); + else{ + + xbInt16 fldRecId = V3Dbf.GetFieldNo( "RECID" ); + xbInt16 fldMemo1 = V3Dbf.GetFieldNo( "MEMOFLD1" ); + xbInt16 fldMemo2 = V3Dbf.GetFieldNo( "MEMOFLD2" ); + xbString sData; + + // Record 1 + rc += TestMethod( po, "BlankRecord()", V3Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V3Dbf.PutField( fldRecId, "1" ), XB_NO_ERROR ); + sData = "Memo data"; + rc += TestMethod( po, "UpdateMemoField()", V3Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + + sData = "Some other memo data"; + rc += TestMethod( po, "UpdateMemoField()", V3Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V3Dbf.AppendRecord(), XB_NO_ERROR ); + + // Record 2 + rc += TestMethod( po, "BlankRecord()", V3Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V3Dbf.PutField( fldRecId, "2" ), XB_NO_ERROR ); + sData = "Memo data Rec 2 ..["; + sData.PadRight( 'Z', 1036 ); + sData += ']'; + rc += TestMethod( po, "UpdateMemoField()", V3Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + sData = "Some other memo data Rec 2 ... ["; + sData.PadRight( 'W', 1555 ); + sData += ']'; + rc += TestMethod( po, "UpdateMemoField()", V3Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V3Dbf.AppendRecord(), XB_NO_ERROR ); + + // Check memo header file + xbUInt32 ulNextBlock; + xbMemo *Memo = V3Dbf.GetMemoPtr(); + rc += TestMethod( po, "GetHdrNextBlock()", Memo->GetHdrNextBlock( ulNextBlock ), XB_NO_ERROR ); + rc += TestMethod( po, "GetHdrNextBlock()", (xbInt32) ulNextBlock, 10 ); + + + // Zap a table with memo fields + rc += TestMethod( po, "Zap(0)", V3Dbf.Zap(), XB_NO_ERROR ); + xbUInt32 ulRecCnt = 0; + rc += TestMethod( po, "GetRecCount()", V3Dbf.GetRecordCnt( ulRecCnt ), XB_NO_ERROR ); + rc += TestMethod( po, "GetRecCount() b", (xbInt32) ulRecCnt, 0 ); + Memo = V3Dbf.GetMemoPtr(); + rc += TestMethod( po, "GetHdrNextBlock()", Memo->GetHdrNextBlock( ulNextBlock ), XB_NO_ERROR ); + rc += TestMethod( po, "GetHdrNextBlock()", (xbInt32) ulNextBlock, 1 ); + + + + // Add records back into the table + // Record 1 + rc += TestMethod( po, "BlankRecord()", V3Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V3Dbf.PutField( fldRecId, "1" ), XB_NO_ERROR ); + sData = "Memo data rec 1 memo 1"; + rc += TestMethod( po, "UpdateMemoField()", V3Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + + sData = "Memo data rec 1 memo 2"; + rc += TestMethod( po, "UpdateMemoField()", V3Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V3Dbf.AppendRecord(), XB_NO_ERROR ); + + // Record 2 + rc += TestMethod( po, "BlankRecord()", V3Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V3Dbf.PutField( fldRecId, "2" ), XB_NO_ERROR ); + sData = "Memo data Rec 2 memo 1..["; + sData.PadRight( 'Z', 1036 ); + sData += ']'; + rc += TestMethod( po, "UpdateMemoField()", V3Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + sData = "Some other memo data Rec 2 memo 2 ... ["; + sData.PadRight( 'W', 1555 ); + sData += ']'; + rc += TestMethod( po, "UpdateMemoField()", V3Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V3Dbf.AppendRecord(), XB_NO_ERROR ); + + // Record 3 + rc += TestMethod( po, "BlankRecord()", V3Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V3Dbf.PutField( fldRecId, "3" ), XB_NO_ERROR ); + sData = "Memo data Rec 3 memo 1"; + rc += TestMethod( po, "UpdateMemoField()", V3Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + + sData = "Memo data Rec 3 memo 2"; + rc += TestMethod( po, "UpdateMemoField()", V3Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V3Dbf.AppendRecord(), XB_NO_ERROR ); + + + // Record 4 + rc += TestMethod( po, "BlankRecord()", V3Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V3Dbf.PutField( fldRecId, "4" ), XB_NO_ERROR ); + sData = "Memo data Rec 4 memo 1"; + rc += TestMethod( po, "UpdateMemoField()", V3Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + sData = "Memo data Rec 4 memo 2"; + rc += TestMethod( po, "UpdateMemoField()", V3Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V3Dbf.AppendRecord(), XB_NO_ERROR ); + + + // Record 5 + rc += TestMethod( po, "BlankRecord()", V3Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V3Dbf.PutField( fldRecId, "5" ), XB_NO_ERROR ); + sData = "Memo data Rec 5 memo 1"; + rc += TestMethod( po, "UpdateMemoField()", V3Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + sData = "Memo data Rec 5 memo 2"; + rc += TestMethod( po, "UpdateMemoField()", V3Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V3Dbf.AppendRecord(), XB_NO_ERROR ); + + + // Record 6 + rc += TestMethod( po, "BlankRecord()", V3Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V3Dbf.PutField( fldRecId, "6" ), XB_NO_ERROR ); + sData = "Memo data Rec 6 memo 1"; + rc += TestMethod( po, "UpdateMemoField()", V3Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + sData = "Memo data Rec 6 memo 2"; + rc += TestMethod( po, "UpdateMemoField()", V3Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V3Dbf.AppendRecord(), XB_NO_ERROR ); + + + // Record 7 + rc += TestMethod( po, "BlankRecord()", V3Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V3Dbf.PutField( fldRecId, "7" ), XB_NO_ERROR ); + sData = "Memo data Rec 7 memo 1"; + rc += TestMethod( po, "UpdateMemoField()", V3Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + sData = "Memo data Rec 7 memo 2"; + rc += TestMethod( po, "UpdateMemoField()", V3Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V3Dbf.AppendRecord(), XB_NO_ERROR ); + + + // Flag 1, 3, 5 and 7 for deletion + rc += TestMethod( po, "GetRecord()", V3Dbf.GetRecord( 1 ), XB_NO_ERROR ); + rc += TestMethod( po, "DeleteRecord()", V3Dbf.DeleteRecord(), XB_NO_ERROR ); + + rc += TestMethod( po, "GetRecord()", V3Dbf.GetRecord( 3 ), XB_NO_ERROR ); + rc += TestMethod( po, "DeleteRecord()", V3Dbf.DeleteRecord(), XB_NO_ERROR ); + + rc += TestMethod( po, "GetRecord()", V3Dbf.GetRecord( 5 ), XB_NO_ERROR ); + rc += TestMethod( po, "DeleteRecord()", V3Dbf.DeleteRecord(), XB_NO_ERROR ); + + rc += TestMethod( po, "GetRecord()", V3Dbf.GetRecord( 7 ), XB_NO_ERROR ); + rc += TestMethod( po, "DeleteRecord()", V3Dbf.DeleteRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "Pack()", V3Dbf.Pack(), XB_NO_ERROR ); + rc += TestMethod( po, "Close()", V3Dbf.Close(), XB_NO_ERROR ); + } + + if( po > 0 || rc < 0 ) + fprintf( stdout, "Total Errors = %d\n", rc * -1 ); + +#ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], rc * -1 ); + x.WriteLogMessage( sMsg ); +#endif + + return rc; +} diff --git a/src/tests/xb_test_dbf_v3_nomemos.cpp b/src/tests/xb_test_dbf_v3_nomemos.cpp new file mode 100755 index 0000000..aab118f --- /dev/null +++ b/src/tests/xb_test_dbf_v3_nomemos.cpp @@ -0,0 +1,323 @@ +/* xb_test_xbdbf_v3_nomemos.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014,2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the class xbXdbf + +// usage: xb_test_dbf_v3_nomemos QUITE|NORMAL|VERBOSE + + +#include "xbase.h" + +using namespace xb; + +#include "tstfuncs.cpp" + + +int main( int argCnt, char **av ) +{ + int iRc = 0; + int iRc2 = 0; + int po = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + po = 0; + else if( av[1][0] == 'V' ) + po = 2; + } + + + xbSchema MyV3Record[] = + { + { "FIRSTNAME", XB_CHAR_FLD, 15, 0 }, + { "LASTNAME", XB_CHAR_FLD, 20, 0 }, + { "MIDDLEINIT", XB_CHAR_FLD, 1, 0 }, + { "BIRTHDATE", XB_DATE_FLD, 8, 0 }, + { "STARTDATE", XB_DATE_FLD, 8, 0 }, + { "AMOUNT", XB_NUMERIC_FLD, 9, 2 }, + { "TESTNUM", XB_NUMERIC_FLD, 12, 4 }, + { "SWITCH", XB_LOGICAL_FLD, 1, 0 }, + { "ZIPCODE", XB_NUMERIC_FLD, 5, 0 }, + { "",0,0,0 } + }; + + + xbXBase x; + +#ifdef XB_LOGGING_SUPPORT + x.EnableMsgLogging(); + if( po ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); +#endif + + x.SetDataDirectory( PROJECT_DATA_DIR ); + x.EnableMsgLogging(); + x.DisableDefaultAutoLock(); + InitTime(); + + if( po > 0 ) + std::cout << "Default Data Directory is [" << x.GetDataDirectory().Str() << "]" << std::endl; + + + xbDbf3 V3Dbf( &x ); /* version 3 dbf file */ + + iRc2 = V3Dbf.CreateTable( "TestV3.DBF", "TestV3", MyV3Record, XB_OVERLAY, XB_MULTI_USER ); + + iRc += TestMethod( po, "CreateTable()", (xbInt32) iRc2, XB_NO_ERROR ); + if( iRc2 ) + x.DisplayError( iRc2 ); + + if( po == 2 ){ + std::cout << "There should be one entry in the table list" << std::endl; + x.DisplayTableList(); + } + + xbDbf3 V3Dbf2( &x ); + // next occurrence should error as a dup + x.WriteLogMessage( "Second create attempt" ); + iRc2 = V3Dbf2.CreateTable( "TestV3.DBF", "TestV3", MyV3Record, XB_DONTOVERLAY, XB_MULTI_USER ); + iRc += TestMethod( po, "CreateTable()", iRc2, XB_FILE_EXISTS ); + if( iRc2 != XB_FILE_EXISTS ){ + x.DisplayError( iRc2 ); + } + + if( po == 2 ){ + std::cout << "There should be one entry in the table list" << std::endl; + x.DisplayTableList(); + } + + iRc += TestMethod( po, "BlankRecord()", V3Dbf.BlankRecord(), XB_NO_ERROR ); + iRc += TestMethod( po, "GetFieldNo()", V3Dbf.GetFieldNo("LASTNAME"), 1 ); + iRc += TestMethod( po, "GetFieldNo()", V3Dbf.GetFieldNo("MIDDLEINIT"), 2 ); + + xbInt16 fldLastName = V3Dbf.GetFieldNo( "LASTNAME" ); + + iRc += TestMethod( po, "PutField()", V3Dbf.PutField( fldLastName, "NELSON" ), XB_NO_ERROR ); + iRc += TestMethod( po, "PutField()", V3Dbf.PutField( "FIRSTNAME", "WILLIE" ), XB_NO_ERROR ); + + iRc += TestMethod( po, "PutField()", V3Dbf.PutField( "AMOUNT", "12.34" ), XB_NO_ERROR ); + xbDate d( "19991201" ); + iRc += TestMethod( po, "PutDateField()", V3Dbf.PutDateField( "STARTDATE", d ), XB_NO_ERROR ); + iRc += TestMethod( po, "PutField()", V3Dbf.PutField( "STARTDATE", "19991301" ), XB_INVALID_DATA ); + iRc += TestMethod( po, "PutField()", V3Dbf.PutField( "STARTDATE", "19991201" ), XB_NO_ERROR ); + + + iRc += TestMethod( po, "PutLongField()", V3Dbf.PutLongField( "ZIPCODE", 12345 ), XB_NO_ERROR ); + iRc += TestMethod( po, "PutLogicalField()", V3Dbf.PutLogicalField( "SWITCH", "Y" ), XB_NO_ERROR ); + iRc += TestMethod( po, "PutFloatField()", V3Dbf.PutFloatField( "TESTNUM", (xbFloat) 1234.5678 ), XB_NO_ERROR ); + iRc += TestMethod( po, "AppendRecord()", V3Dbf.AppendRecord(), XB_NO_ERROR ); + + xbString sf; + iRc += TestMethod( po, "GetField1()", V3Dbf.GetField( fldLastName, sf, 0 ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetField2()", sf, "NELSON ", 20 ); + iRc += TestMethod( po, "GetField3()", V3Dbf.GetField( fldLastName, sf ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetField4()", sf, "NELSON ", 20 ); + iRc += TestMethod( po, "GetField5()", V3Dbf.GetField( "LASTNAME", sf ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetField6()", sf, "NELSON ", 20 ); + xbInt16 iNoOfDecimals; + iRc += TestMethod( po, "GetFieldDecimal()", V3Dbf.GetFieldDecimal( "AMOUNT", iNoOfDecimals ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetFieldDecimal()", iNoOfDecimals, 2 ); + + char FieldType; + iRc += TestMethod( po, "GetFieldType()", V3Dbf.GetFieldType( "STARTDATE", FieldType ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetFieldType()", FieldType , 'D' ); + + xbInt16 iFieldLen; + iRc += TestMethod( po, "GetFieldLen()", V3Dbf.GetFieldLen( "STARTDATE", iFieldLen ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetFieldLen()", iFieldLen, 8 ); + + xbInt16 fldAMT = V3Dbf.GetFieldNo( "AMOUNT" ); + iRc += TestMethod( po, "GetRawField1()", V3Dbf.GetField( fldAMT, sf ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetRawField2()", sf, " 12.34", 9 ); + + xbInt32 lZip; + iRc += TestMethod( po, "GetLongField()", V3Dbf.GetLongField( "ZIPCODE", lZip ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetLongField()", lZip, 12345 ); + + xbString sSwitch; + iRc += TestMethod( po, "GetLogicalField()", V3Dbf.GetLogicalField( "SWITCH", sSwitch ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetLogicalField()", sSwitch, "Y", 1 ); + + xbFloat fNum; + iRc += TestMethod( po, "GetFloatField()", V3Dbf.GetFloatField( "TESTNUM", fNum ), 0 ); + iRc += TestMethod( po, "GetFloatField()", fNum, (xbFloat) 1234.5678 ); + + iRc += TestMethod( po, "GetDateField()", V3Dbf.GetDateField( "STARTDATE", d ), 0 ); + iRc += TestMethod( po, "GetDateField()", d.Str(), "19991201", 8 ); + + // init a second record for more testing + iRc += TestMethod( po, "BlankRecord()", V3Dbf.BlankRecord(), XB_NO_ERROR ); + iRc += TestMethod( po, "PutLogicalField()", V3Dbf.PutLogicalField( "SWITCH", xbTrue ), XB_NO_ERROR ); + iRc += TestMethod( po, "AppendRecord()", V3Dbf.AppendRecord(), XB_NO_ERROR ); + xbBool bSwitch; + iRc += TestMethod( po, "GetLogicalField()", V3Dbf.GetLogicalField( "SWITCH", bSwitch ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetLogicalField()", bSwitch, xbTrue ); + + // init a third record for more testing + iRc += TestMethod( po, "BlankRecord()", V3Dbf.BlankRecord(), XB_NO_ERROR ); + iRc += TestMethod( po, "PutLogicalField()", V3Dbf.PutLogicalField( "SWITCH", xbFalse ), XB_NO_ERROR ); + iRc += TestMethod( po, "AppendRecord()", V3Dbf.AppendRecord(), XB_NO_ERROR ); + + + iRc += TestMethod( po, "GetLogicalField()", V3Dbf.GetLogicalField( "SWITCH", bSwitch ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetLogicalField()", bSwitch, xbFalse ); + + iRc += TestMethod( po, "PutField()", V3Dbf.PutField( "TESTNUM", "12345678" ), XB_INVALID_DATA ); + iRc += TestMethod( po, "PutField()", V3Dbf.PutField( "TESTNUM", "1234567" ), XB_NO_ERROR ); + iRc += TestMethod( po, "PutField()", V3Dbf.PutField( "TESTNUM", "1234567.12345" ), XB_INVALID_DATA ); + iRc += TestMethod( po, "PutField()", V3Dbf.PutField( "TESTNUM", ".12345" ), XB_INVALID_DATA ); + iRc += TestMethod( po, "PutField()", V3Dbf.PutField( "TESTNUM", ".1234" ), XB_NO_ERROR ); + iRc += TestMethod( po, "PutField()", V3Dbf.PutField( "TESTNUM", "12345678.1234" ), XB_INVALID_DATA ); + iRc += TestMethod( po, "PutField()", V3Dbf.PutField( "TESTNUM", "1234567.1234" ), XB_NO_ERROR ); + iRc += TestMethod( po, "AppendRecord()", V3Dbf.AppendRecord(), XB_NO_ERROR ); + + iRc += TestMethod( po, "GetFieldCnt()", V3Dbf.GetFieldCnt(), 9 ); + iRc += TestMethod( po, "GetTblAlias()", V3Dbf.GetTblAlias(), "TestV3", 6 ); + iRc += TestMethod( po, "GetDbfStatus()", V3Dbf.GetDbfStatus(), XB_OPEN ); + iRc += TestMethod( po, "GetCurRecNo()", (xbInt32) V3Dbf.GetCurRecNo(), 4 ); + iRc += TestMethod( po, "GetFirstRecord()", V3Dbf.GetFirstRecord(), XB_NO_ERROR ); + iRc += TestMethod( po, "GetCurRecNo()", (xbInt32) V3Dbf.GetCurRecNo(), 1 ); + iRc += TestMethod( po, "GetNextRecord()", V3Dbf.GetNextRecord(), XB_NO_ERROR ); + iRc += TestMethod( po, "GetCurRecNo()", (xbInt32) V3Dbf.GetCurRecNo(), 2 ); + iRc += TestMethod( po, "GetLastRecord()", V3Dbf.GetLastRecord(), XB_NO_ERROR ); + iRc += TestMethod( po, "GetCurRecNo()", (xbInt32) V3Dbf.GetCurRecNo(), 4 ); + iRc += TestMethod( po, "GetPrevRecord()", V3Dbf.GetPrevRecord(), XB_NO_ERROR ); + iRc += TestMethod( po, "GetCurRecNo()", (xbInt32) V3Dbf.GetCurRecNo(), 3 ); + iRc += TestMethod( po, "GetRecordLen()", V3Dbf.GetRecordLen(), 80 ); + + iRc += TestMethod( po, "GetFirstRecord( XB_ALL_RECS )", V3Dbf.GetFirstRecord( XB_ALL_RECS ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetCurRecNo()", (xbInt32) V3Dbf.GetCurRecNo(), 1 ); + iRc += TestMethod( po, "GetNextRecord( XB_ALL_RECS )", V3Dbf.GetNextRecord( XB_ALL_RECS ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetCurRecNo()", (xbInt32) V3Dbf.GetCurRecNo(), 2 ); + iRc += TestMethod( po, "GetLastRecord( XB_ALL_RECS )", V3Dbf.GetLastRecord( XB_ALL_RECS ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetCurRecNo()", (xbInt32) V3Dbf.GetCurRecNo(), 4 ); + iRc += TestMethod( po, "GetPrevRecord( XB_ALL_RECS )", V3Dbf.GetPrevRecord( XB_ALL_RECS ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetCurRecNo()", (xbInt32) V3Dbf.GetCurRecNo(), 3 ); + + iRc += TestMethod( po, "GetFirstRecord( XB_DELETED_RECS )", V3Dbf.GetFirstRecord( XB_DELETED_RECS ), XB_EOF ); + iRc += TestMethod( po, "GetLastRecord( XB_DELETED_RECS )", V3Dbf.GetLastRecord( XB_DELETED_RECS ), XB_EOF ); + + iRc += TestMethod( po, "GetFirstRecord( XB_ALL_RECS )", V3Dbf.GetFirstRecord( XB_ALL_RECS ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetNextRecord( XB_DELETED_RECS )", V3Dbf.GetNextRecord( XB_DELETED_RECS ), XB_EOF ); + + iRc += TestMethod( po, "GetLastRecord( XB_ALL_RECS )", V3Dbf.GetLastRecord( XB_ALL_RECS ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetPrevRecord( XB_DELETED_RECS )", V3Dbf.GetPrevRecord( XB_DELETED_RECS ), XB_BOF ); + + iRc += TestMethod( po, "DeleteAllRecords()", V3Dbf.DeleteAllRecords(), XB_NO_ERROR ); + + + iRc += TestMethod( po, "GetFirstRecord()", V3Dbf.GetFirstRecord(), XB_EOF ); + iRc += TestMethod( po, "GetLastRecord()", V3Dbf.GetLastRecord(), XB_EOF ); + + iRc += TestMethod( po, "GetFirstRecord( XB_ALL_RECS )", V3Dbf.GetFirstRecord( XB_ALL_RECS ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetCurRecNo()", (xbInt32) V3Dbf.GetCurRecNo(), 1 ); + + iRc += TestMethod( po, "GetNextRecord( XB_ALL_RECS )", V3Dbf.GetNextRecord( XB_ALL_RECS ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetCurRecNo()", (xbInt32) V3Dbf.GetCurRecNo(), 2 ); + + iRc += TestMethod( po, "GetNextRecord()", V3Dbf.GetNextRecord(), XB_EOF ); + + iRc += TestMethod( po, "GetLastRecord( XB_ALL_RECS )", V3Dbf.GetLastRecord( XB_ALL_RECS ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetCurRecNo()", (xbInt32) V3Dbf.GetCurRecNo(), 4 ); + + iRc += TestMethod( po, "GetPrevRecord( XB_ALL_RECS )", V3Dbf.GetPrevRecord( XB_ALL_RECS ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetCurRecNo()", (xbInt32) V3Dbf.GetCurRecNo(), 3 ); + + iRc += TestMethod( po, "UndeleteAllRecords()", V3Dbf.UndeleteAllRecords(), XB_NO_ERROR ); + + char * p = V3Dbf.GetRecordBuf(); + iRc += TestMethod( po, "GetRecordBuf()", p[0], ' ' ); + + if( po == 2 ){ + V3Dbf.DumpHeader( 3 ); + V3Dbf.DumpRecord( 4 ); + } + + + + iRc += TestMethod( po, "PutField()", V3Dbf.PutField( "LASTNAME", "CLINTON" ), XB_NO_ERROR ); + iRc += TestMethod( po, "PutRecord()", V3Dbf.PutRecord(), XB_NO_ERROR ); + iRc += TestMethod( po, "DeleteRecord()", V3Dbf.DeleteRecord(), XB_NO_ERROR ); + iRc += TestMethod( po, "UndeleteRecord()", V3Dbf.UndeleteRecord(), XB_NO_ERROR ); + xbUInt32 ulRecCnt = 0; + iRc += TestMethod( po, "GetRecordCnt()", V3Dbf.GetRecordCnt( ulRecCnt ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetRecordCnt()b",(xbInt32) ulRecCnt, 4 ); + iRc += TestMethod( po, "DeleteAllRecords()", V3Dbf.DeleteAllRecords(), XB_NO_ERROR ); + iRc += TestMethod( po, "UndeleteAllRecords()", V3Dbf.UndeleteAllRecords(), XB_NO_ERROR ); + iRc += TestMethod( po, "GetRecord()", V3Dbf.GetRecord( 4 ), XB_NO_ERROR ); + iRc += TestMethod( po, "DeleteRecord()", V3Dbf.DeleteRecord(), XB_NO_ERROR ); + iRc += TestMethod( po, "Commit()", V3Dbf.Commit(), XB_NO_ERROR ); + iRc += TestMethod( po, "GetDbfStatus()", V3Dbf.GetDbfStatus(), XB_OPEN ); + + if( po == 2 ){ + V3Dbf.DumpRecord( 4 ); + } + + xbDbf3 CopyDbf( &x ); + iRc += TestMethod( po, "CopyDbfStructure()", V3Dbf.CopyDbfStructure( &CopyDbf, "CopyStructureV3NoMemos", "CopyAliasV3NoMemos", XB_OVERLAY, XB_MULTI_USER ), XB_NO_ERROR ); + iRc += TestMethod( po, "CopyDbf.Close()", CopyDbf.Close(), XB_NO_ERROR ); + + if( po == 2 ){ + std::cout << "There should be one entry in the table list" << std::endl; + x.DisplayTableList(); + } + + iRc += TestMethod( po, "GetDbfStatus()", CopyDbf.GetDbfStatus(), XB_CLOSED ); + iRc += TestMethod( po, "Open()", CopyDbf.xbDbf::Open( "CopyStructureV3NoMemos.DBF", "CopyAliasV3NoMemos" ), XB_NO_ERROR ); + + if( po == 2 ){ + std::cout << "There should be two entries in the table list" << std::endl; + x.DisplayTableList(); + } + + iRc += TestMethod( po, "CopyDbf.Close()", CopyDbf.Close(), XB_NO_ERROR ); + + #ifdef XB_DEBUG_SUPPORT + #ifdef XB_LOCKING_SUPPORT + V3Dbf.DumpTableLockStatus(); + #endif + #endif + + iRc += TestMethod( po, "PackTable( 0, 0 )", V3Dbf.Pack(), XB_NO_ERROR ); + iRc += TestMethod( po, "GetDbfStatus()", V3Dbf.GetDbfStatus(), XB_OPEN ); + + iRc += TestMethod( po, "Zap()", V3Dbf.Zap(), XB_NO_ERROR ); + if( po == 2 ) + x.DisplayTableList(); + + iRc += TestMethod( po, "Close()", V3Dbf.Close(), XB_NO_ERROR ); + if( po == 2 ) + x.DisplayTableList(); + + if( po > 0 || iRc < 0 ) + fprintf( stdout, "Total Errors = %d\n", iRc * -1 ); + + + V3Dbf.Abort(); // don't crash the program if uncommited updates + +#ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], iRc * -1 ); + x.WriteLogMessage( sMsg ); +#endif + + return iRc; +} diff --git a/src/tests/xb_test_dbf_v4_memos.cpp b/src/tests/xb_test_dbf_v4_memos.cpp new file mode 100755 index 0000000..e92b5b2 --- /dev/null +++ b/src/tests/xb_test_dbf_v4_memos.cpp @@ -0,0 +1,335 @@ +/* xb_test_xbdbf_v4_memos.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014,2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the version III memo field logic +// usage: xb_test_dbf_v4_memos QUITE|NORMAL|VERBOSE + +#include "xbase.h" +using namespace xb; +#include "tstfuncs.cpp" + +int main( int argCnt, char **av ) +{ + int rc = 0; + int rc2 = 0; + int po = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + po = 0; + else if( av[1][0] == 'V' ) + po = 2; + } + + xbSchema MyV4Record[] = + { + { "RECID", XB_NUMERIC_FLD, 8, 0 }, + { "MEMOFLD1", XB_MEMO_FLD, 10, 0 }, + { "MEMOFLD2", XB_MEMO_FLD, 10, 0 }, + { "MEMOFLD3", XB_MEMO_FLD, 10, 0 }, + { "",0,0,0 } + }; + + xbXBase x; + +#ifdef XB_LOGGING_SUPPORT + + x.EnableMsgLogging(); + if( po ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); + +#endif + + x.SetDataDirectory( PROJECT_DATA_DIR ); + x.EnableMsgLogging(); + x.DisableDefaultAutoLock(); + InitTime(); + + + if( po > 0 ) + std::cout << "Default Data Directory is [" << x.GetDataDirectory().Str() << "]" << std::endl; + + xbDbf4 V4Dbf( &x ); + rc += TestMethod( po, "SetCreateMemoBlockSize", V4Dbf.SetCreateMemoBlockSize( 1024 ), XB_NO_ERROR ); + rc2 = V4Dbf.CreateTable( "TestV4_memos.DBF", "TestV4", MyV4Record, XB_OVERLAY, XB_MULTI_USER ); + + xbUInt64 ullDbfOrigFileSize = 0; + xbUInt64 ullDbtOrigFileSize = 0; + rc = V4Dbf.GetFileSize( ullDbfOrigFileSize ); + rc = V4Dbf.GetMemoPtr()->GetFileSize( ullDbtOrigFileSize ); + + rc += TestMethod( po, "CreateTable()", (xbInt32) rc2, XB_NO_ERROR ); + if( rc2 ) + x.DisplayError( rc2 ); + else{ + + xbInt16 fldRecId = V4Dbf.GetFieldNo( "RECID" ); + xbInt16 fldMemo1 = V4Dbf.GetFieldNo( "MEMOFLD1" ); + xbInt16 fldMemo2 = V4Dbf.GetFieldNo( "MEMOFLD2" ); + xbInt16 fldMemo3 = V4Dbf.GetFieldNo( "MEMOFLD3" ); + xbString sData; + + + + + // Record 1 + rc += TestMethod( po, "BlankRecord()", V4Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( fldRecId, "1" ), XB_NO_ERROR ); + sData = "Memo data"; + + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + rc += TestDbt4Method( po, "Add one block", V4Dbf.GetMemoPtr(), 2, 2, "" ); + + sData = "Some other memo data"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + rc += TestDbt4Method( po, "Add one block", V4Dbf.GetMemoPtr(), 3, 3, "" ); + rc += TestMethod( po, "AppendRecord()", V4Dbf.AppendRecord(), XB_NO_ERROR ); + + + + + // Record 2 + rc += TestMethod( po, "BlankRecord()", V4Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( fldRecId, "2" ), XB_NO_ERROR ); + sData = "Memo data Rec 2 ..["; + sData.PadRight( 'Z', 1036 ); + sData += ']'; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + sData = "Some other memo data Rec 2 ... ["; + sData.PadRight( 'W', 1555 ); + sData += ']'; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + rc += TestDbt4Method( po, "Add 7 blocks", V4Dbf.GetMemoPtr(), 7, 7, "" ); + + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, "" ), XB_NO_ERROR ); + rc += TestDbt4Method( po, "Delete 2 blocks", V4Dbf.GetMemoPtr(), 3, 7, "3,2,7" ); + rc += TestMethod( po, "AppendRecord()", V4Dbf.AppendRecord(), XB_NO_ERROR ); + + // Record 3 + rc += TestMethod( po, "BlankRecord()", V4Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( fldRecId, "3" ), XB_NO_ERROR ); + sData = "Memo data r3f1"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + rc += TestDbt4Method( po, "Add one block", V4Dbf.GetMemoPtr(), 4, 7, "4,1,7" ); + sData = "Memo data r3f2"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + rc += TestDbt4Method( po, "Add one block", V4Dbf.GetMemoPtr(), 7, 7, "" ); + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, "" ), XB_NO_ERROR ); + rc += TestDbt4Method( po, "Delete one block", V4Dbf.GetMemoPtr(), 3, 7, "3,1,7" ); + rc += TestMethod( po, "AppendRecord()", V4Dbf.AppendRecord(), XB_NO_ERROR ); + + // Record 4 + rc += TestMethod( po, "BlankRecord()", V4Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( fldRecId, "4" ), XB_NO_ERROR ); + sData = "Memo data Rec 4 fld1 ..["; + sData.PadRight( 'Q', 1036 ); + sData += ']'; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + rc += TestDbt4Method( po, "Update Memo Field", V4Dbf.GetMemoPtr(), 3, 9, "3,1,9" ); + rc += TestMethod( po, "AppendRecord()", V4Dbf.AppendRecord(), XB_NO_ERROR ); + + // go back a record and delete a memo field and test if all blocks filled in + rc += TestMethod( po, "GetPrevRecord()", V4Dbf.GetPrevRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo2, "" ), XB_NO_ERROR ); + rc += TestMethod( po, "Commit()", V4Dbf.Commit(), XB_NO_ERROR ); + rc += TestDbt4Method( po, "Delete one block", V4Dbf.GetMemoPtr(), 3, 9, "3,2,9" ); + + // Record 5 + rc += TestMethod( po, "BlankRecord()", V4Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( fldRecId, "5" ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V4Dbf.AppendRecord(), XB_NO_ERROR ); + + // Zap a table with memo fields + rc += TestMethod( po, "Zap()", V4Dbf.Zap(), XB_NO_ERROR ); + xbUInt32 ulRecCnt = 0; + rc += TestMethod( po, "GetRecCount()", V4Dbf.GetRecordCnt( ulRecCnt ), XB_NO_ERROR ); + rc += TestMethod( po, "GetRecCount()b", (xbInt32) ulRecCnt, 0 ); + + // Add records back into the table, and verify the block chains created as designed + // Record 1 + rc += TestMethod( po, "BlankRecord()", V4Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( fldRecId, "1" ), XB_NO_ERROR ); + sData = "Memo data rec 1 memo 1"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V4Dbf.AppendRecord(), XB_NO_ERROR ); + rc += TestDbt4Method( po, "Update Memo Field", V4Dbf.GetMemoPtr(), 2, 2, "" ); + + // Revise the memo field + sData = "Updated memo data rec1 memo 1"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "Commit()", V4Dbf.Commit(), XB_NO_ERROR ); + rc += TestDbt4Method( po, "UpdateMemoField", V4Dbf.GetMemoPtr(), 2, 2, "" ); + + sData = "Memo data rec 1 memo 2"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "Commit()", V4Dbf.Commit(), XB_NO_ERROR ); + rc += TestDbt4Method( po, "UpdateMemoField", V4Dbf.GetMemoPtr(), 3, 3, "" ); + + // Record 2 + rc += TestMethod( po, "BlankRecord()", V4Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( fldRecId, "2" ), XB_NO_ERROR ); + sData = "Memo data rec 2 memo 1"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + sData = "Memo data rec 2 memo 2"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V4Dbf.AppendRecord(), XB_NO_ERROR ); + rc += TestDbt4Method( po, "Add one block", V4Dbf.GetMemoPtr(), 5, 5, "" ); + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, "" ), XB_NO_ERROR ); + rc += TestMethod( po, "Commit()", V4Dbf.Commit(), XB_NO_ERROR ); + rc += TestDbt4Method( po, "UpdateMemoField", V4Dbf.GetMemoPtr(), 3, 5, "3,1,5" ); + + sData = "Test the abort code"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "Abort()", V4Dbf.Abort(), XB_NO_ERROR ); + rc += TestDbt4Method( po, "UpdateMemoField", V4Dbf.GetMemoPtr(), 3, 5, "3,1,5" ); + + sData = "Test mulitple updates before commit"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + sData = "Test mulitple updates before commit2"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + rc += TestDbt4Method( po, "UpdateMemoField", V4Dbf.GetMemoPtr(), 5, 5, "" ); + sData = "Test mulitple updates before commit3"; + + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "Commit()", V4Dbf.Commit(), XB_NO_ERROR ); + rc += TestDbt4Method( po, "UpdateMemoField", V4Dbf.GetMemoPtr(), 5, 5, "" ); + +// V4Dbf.GetMemoPtr()->DumpMemoInternals(); + + rc += TestMethod( po, "Zap(0)", V4Dbf.Zap(), XB_NO_ERROR ); + + xbUInt64 ullDbfPostZapFileSize = 0; + xbUInt64 ullDbtPostZapFileSize = 0; + rc += V4Dbf.GetFileSize( ullDbfPostZapFileSize ); + rc += V4Dbf.GetMemoPtr()->GetFileSize( ullDbtPostZapFileSize ); + + rc += TestMethod( po, "Zap()", ullDbfPostZapFileSize, ullDbfOrigFileSize ); + rc += TestMethod( po, "Memo->Zap()", ullDbtPostZapFileSize, ullDbtOrigFileSize ); + rc += TestDbt4Method( po, "Zap() block check", V4Dbf.GetMemoPtr(), 1, 1, "" ); + + rc += TestMethod( po, "GetRecCount()", V4Dbf.GetRecordCnt( ulRecCnt ), XB_NO_ERROR ); + rc += TestMethod( po, "GetRecCount()", (xbInt32) ulRecCnt, 0 ); + + rc += TestMethod( po, "BlankRecord()", V4Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( fldRecId, "1" ), XB_NO_ERROR ); + sData = "Memo data rec 1 memo 1"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + sData = "Memo data rec 1 memo 2"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + sData = "Memo data rec 1 memo 3"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo3, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V4Dbf.AppendRecord(), XB_NO_ERROR ); + + sData = "Memo data rec 1 memo 1 A"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + sData = "Memo data rec 1 memo 2 A"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + sData = "Memo data rec 1 memo 3A "; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo3, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "Commit()", V4Dbf.Commit(), XB_NO_ERROR ); + rc += TestDbt4Method( po, "Update Memo Field", V4Dbf.GetMemoPtr(), 4, 4, "" ); + + // Record 2 + rc += TestMethod( po, "BlankRecord()", V4Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( fldRecId, "2" ), XB_NO_ERROR ); + sData = "Memo data rec 2 memo 1"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + sData = "Memo data rec 2 memo 2"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V4Dbf.AppendRecord(), XB_NO_ERROR ); + rc += TestDbt4Method( po, "Add two blocks", V4Dbf.GetMemoPtr(), 6, 6, "" ); + + // Record 3 + rc += TestMethod( po, "BlankRecord()", V4Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( fldRecId, "3" ), XB_NO_ERROR ); + sData = "Memo data rec 3 memo 1"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + sData = "Memo data rec 3 memo 2"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V4Dbf.AppendRecord(), XB_NO_ERROR ); + rc += TestDbt4Method( po, "Add two blocks", V4Dbf.GetMemoPtr(), 8, 8, "" ); + + // Record 4 + rc += TestMethod( po, "BlankRecord()", V4Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( fldRecId, "4" ), XB_NO_ERROR ); + sData = "Memo data rec 4 memo 1"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + sData = "Memo data rec 4 memo 2"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V4Dbf.AppendRecord(), XB_NO_ERROR ); + rc += TestDbt4Method( po, "Add two blocks", V4Dbf.GetMemoPtr(), 10, 10, "" ); + + // Record 5 + rc += TestMethod( po, "BlankRecord()", V4Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( fldRecId, "5" ), XB_NO_ERROR ); + sData = "Memo data rec 5 memo 1"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + sData = "Memo data rec 5 memo 2"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V4Dbf.AppendRecord(), XB_NO_ERROR ); + rc += TestDbt4Method( po, "Add two blocks", V4Dbf.GetMemoPtr(), 12, 12, "" ); + + // Record 6 + rc += TestMethod( po, "BlankRecord()", V4Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( fldRecId, "6" ), XB_NO_ERROR ); + sData = "Memo data rec 6 memo 1"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + sData = "Memo data rec 6 memo 2"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V4Dbf.AppendRecord(), XB_NO_ERROR ); + rc += TestDbt4Method( po, "Add two blocks", V4Dbf.GetMemoPtr(), 14, 14, "" ); + + // Record 7 + rc += TestMethod( po, "BlankRecord()", V4Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( fldRecId, "7" ), XB_NO_ERROR ); + sData = "Memo data rec 6 memo 1"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo1, sData ), XB_NO_ERROR ); + sData = "Memo data rec 6 memo 2"; + rc += TestMethod( po, "UpdateMemoField()", V4Dbf.UpdateMemoField( fldMemo2, sData ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V4Dbf.AppendRecord(), XB_NO_ERROR ); + rc += TestDbt4Method( po, "Add two blocks", V4Dbf.GetMemoPtr(), 16, 16, "" ); + + // delete records 1, 3, 5, 7 + rc += TestMethod( po, "GetRecord()", V4Dbf.GetRecord( 1 ), XB_NO_ERROR ); + rc += TestMethod( po, "DeleteRecord()", V4Dbf.DeleteRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "GetRecord()", V4Dbf.GetRecord( 3 ), XB_NO_ERROR ); + rc += TestMethod( po, "DeleteRecord()", V4Dbf.DeleteRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "GetRecord()", V4Dbf.GetRecord( 5 ), XB_NO_ERROR ); + rc += TestMethod( po, "DeleteRecord()", V4Dbf.DeleteRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "GetRecord()", V4Dbf.GetRecord( 7 ), XB_NO_ERROR ); + rc += TestMethod( po, "DeleteRecord()", V4Dbf.DeleteRecord(), XB_NO_ERROR ); + + + rc += TestMethod( po, "Pack()", V4Dbf.Pack(), XB_NO_ERROR ); + rc += TestMethod( po, "Close()", V4Dbf.Close(), XB_NO_ERROR ); + } + + if( po > 0 || rc < 0 ) + fprintf( stdout, "Total Errors = %d\n", rc * -1 ); + +#ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], rc * -1 ); + x.WriteLogMessage( sMsg ); +#endif + + return rc; +} diff --git a/src/tests/xb_test_dbf_v4_nomemos.cpp b/src/tests/xb_test_dbf_v4_nomemos.cpp new file mode 100755 index 0000000..68ecda0 --- /dev/null +++ b/src/tests/xb_test_dbf_v4_nomemos.cpp @@ -0,0 +1,330 @@ +/* xb_test_xbdbf_v4_nomemos.cpp + +XBase Software Library + +Copyright (c) 1997,2003,2014,2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the class xbXdbf + +// usage: xb_test_dbf_v4_nomemos QUITE|NORMAL|VERBOSE + + +#include "xbase.h" + +using namespace xb; + +#include "tstfuncs.cpp" + + +int main( int argCnt, char **av ) +{ + int rc = 0; + int rc2 = 0; + int po = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + po = 0; + else if( av[1][0] == 'V' ) + po = 2; + } + + xbSchema MyV4Record[] = + { + { "FIRSTNAME", XB_CHAR_FLD, 15, 0 }, + { "LASTNAME", XB_CHAR_FLD, 20, 0 }, + { "MIDDLEINIT", XB_CHAR_FLD, 1, 0 }, + { "BIRTHDATE", XB_DATE_FLD, 8, 0 }, + { "STARTDATE", XB_DATE_FLD, 8, 0 }, + { "AMOUNT", XB_NUMERIC_FLD, 9, 2 }, + { "TESTNUM", XB_NUMERIC_FLD, 12, 4 }, + { "SWITCH", XB_LOGICAL_FLD, 1, 0 }, + { "ZIPCODE", XB_NUMERIC_FLD, 5, 0 }, + { "DBLFLDTST", XB_FLOAT_FLD, 14, 4 }, + { "",0,0,0 } + }; + + xbXBase x; + +#ifdef XB_LOGGING_SUPPORT + x.EnableMsgLogging(); + if( po ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); +#endif + + x.SetDataDirectory( PROJECT_DATA_DIR ); + x.EnableMsgLogging(); + x.DisableDefaultAutoLock(); + InitTime(); + + if( po > 0 ) + std::cout << "Default Data Directory is [" << x.GetDataDirectory().Str() << "]" << std::endl; + + xbDbf4 V4Dbf( &x ); // version 4 dbf file + rc2 = V4Dbf.CreateTable( "TestV4.DBF", "TestV4", MyV4Record, XB_OVERLAY, XB_MULTI_USER ); + rc += TestMethod( po, "CreateTable()", (xbInt32) rc2, XB_NO_ERROR ); + if( rc2 ) + x.DisplayError( rc2 ); + + xbUInt64 ullFileSize; + rc2 = V4Dbf.GetFileSize( ullFileSize ); + + rc = TestMethod( po, "CheckTableSize", ullFileSize, (xbUInt64) 353 ); + + if( po == 2 ){ + std::cout << "There should be one entry in the table list" << std::endl; + x.DisplayTableList(); + } + + xbDbf4 V4Dbf2( &x ); + + // next occurrence should error as a dup + x.WriteLogMessage( "Second create attempt" ); + rc2 = V4Dbf2.CreateTable( "TestV4.DBF", "TestV4", MyV4Record, XB_DONTOVERLAY, XB_MULTI_USER ); + rc += TestMethod( po, "CreateTable()", rc2, XB_FILE_EXISTS ); + if( rc2 != XB_FILE_EXISTS ){ + x.DisplayError( rc2 ); + } + + if( po == 2 ){ + std::cout << "There should be one entry in the table list" << std::endl; + x.DisplayTableList(); + } + + + rc += TestMethod( po, "BlankRecord()", V4Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "GetFieldNo()", V4Dbf.GetFieldNo("LASTNAME"), 1 ); + rc += TestMethod( po, "GetFieldNo()", V4Dbf.GetFieldNo("MIDDLEINIT"), 2 ); + + xbInt16 fldLastName = V4Dbf.GetFieldNo( "LASTNAME" ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( fldLastName, "NELSON" ), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( "FIRSTNAME", "WILLIE" ), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( "AMOUNT", "12.34" ), XB_NO_ERROR ); + xbDate dt( "19500209" ); + rc += TestMethod( po, "PutDateField()", V4Dbf.PutDateField( "BIRTHDATE", dt ), XB_NO_ERROR ); + rc += TestMethod( po, "PutLongField()", V4Dbf.PutLongField( "ZIPCODE", 12345 ), XB_NO_ERROR ); + rc += TestMethod( po, "PutLogicalField()", V4Dbf.PutLogicalField( "SWITCH", "Y" ), XB_NO_ERROR ); + rc += TestMethod( po, "PutFloatField()", V4Dbf.PutFloatField( "TESTNUM", (xbFloat) 1234.5678 ), XB_NO_ERROR ); + rc += TestMethod( po, "PutDoubleField()", V4Dbf.PutDoubleField( "DBLFLDTST", (xbDouble) 9876.5432 ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V4Dbf.AppendRecord(), XB_NO_ERROR ); + + + xbString sf; + rc += TestMethod( po, "GetField()", V4Dbf.GetField( fldLastName, sf, 0 ), XB_NO_ERROR ); + rc += TestMethod( po, "GetField()", sf, "NELSON ", 20 ); + rc += TestMethod( po, "GetField()", V4Dbf.GetField( fldLastName, sf ), XB_NO_ERROR ); + rc += TestMethod( po, "GetField()", sf, "NELSON ", 20 ); + rc += TestMethod( po, "GetField()", V4Dbf.GetField( "LASTNAME", sf ), XB_NO_ERROR ); + rc += TestMethod( po, "GetField()", sf, "NELSON ", 20 ); + xbInt16 iNoOfDecimals; + rc += TestMethod( po, "GetFieldDecimal()", V4Dbf.GetFieldDecimal( "AMOUNT", iNoOfDecimals ), XB_NO_ERROR ); + rc += TestMethod( po, "GetFieldDecimal()", iNoOfDecimals, 2 ); + + xbDouble d; + rc += TestMethod( po, "GetDoubleField()", V4Dbf.GetDoubleField( "DBLFLDTST", d ), XB_NO_ERROR ); + rc += TestMethod( po, "GetDoubleField()-b", d, (xbDouble) 9876.5432 ); + + char FieldType; + rc += TestMethod( po, "GetFieldType()", V4Dbf.GetFieldType( "STARTDATE", FieldType ), XB_NO_ERROR ); + rc += TestMethod( po, "GetFieldType()", FieldType , 'D' ); + + xbInt16 iFieldLen; + rc += TestMethod( po, "GetFieldLen()", V4Dbf.GetFieldLen( "STARTDATE", iFieldLen ), XB_NO_ERROR ); + rc += TestMethod( po, "GetFieldLen()", iFieldLen, 8 ); + + xbInt16 fldAMT = V4Dbf.GetFieldNo( "AMOUNT" ); + rc += TestMethod( po, "GetField()", V4Dbf.GetField( fldAMT, sf ), XB_NO_ERROR ); + rc += TestMethod( po, "GetField()", sf, " 12.34", 9 ); + + xbInt32 lZip; + rc += TestMethod( po, "GetLongField()", V4Dbf.GetLongField( "ZIPCODE", lZip ), XB_NO_ERROR ); + rc += TestMethod( po, "GetLongField()", lZip, 12345 ); + + xbString sSwitch; + rc += TestMethod( po, "GetLogicalField()", V4Dbf.GetLogicalField( "SWITCH", sSwitch ), XB_NO_ERROR ); + rc += TestMethod( po, "GetLogicalField()", sSwitch, "Y", 1 ); + + xbFloat fNum; + rc += TestMethod( po, "GetFloatField()", V4Dbf.GetFloatField( "TESTNUM", fNum ), 0 ); + rc += TestMethod( po, "GetFloatField()", fNum, (xbFloat) 1234.5678 ); + + // init a second record for more testing + rc += TestMethod( po, "BlankRecord()", V4Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutLogicalField()", V4Dbf.PutLogicalField( "SWITCH", xbTrue ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V4Dbf.AppendRecord(), XB_NO_ERROR ); + xbBool bSwitch; + rc += TestMethod( po, "GetLogicalField()", V4Dbf.GetLogicalField( "SWITCH", bSwitch ), 0 ); + rc += TestMethod( po, "GetLogicalField()", bSwitch, xbTrue ); + + // init a third record for more testing + rc += TestMethod( po, "BlankRecord()", V4Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutLogicalField()", V4Dbf.PutLogicalField( "SWITCH", xbFalse ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V4Dbf.AppendRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "GetLogicalField()", V4Dbf.GetLogicalField( "SWITCH", bSwitch ), 0 ); + rc += TestMethod( po, "GetLogicalField()", bSwitch, xbFalse ); + + rc += TestMethod( po, "PutField()", V4Dbf.PutField( "TESTNUM", "12345678" ), XB_INVALID_DATA ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( "TESTNUM", "1234567" ), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( "TESTNUM", "1234567.12345" ), XB_INVALID_DATA ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( "TESTNUM", ".12345" ), XB_INVALID_DATA ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( "TESTNUM", ".1234" ), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( "TESTNUM", "12345678.1234" ), XB_INVALID_DATA ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( "TESTNUM", "1234567.1234" ), XB_NO_ERROR ); + + rc += TestMethod( po, "AppendRecord()", V4Dbf.AppendRecord(), XB_NO_ERROR ); + + rc += TestMethod( po, "GetFieldCnt()", V4Dbf.GetFieldCnt(), 10 ); + rc += TestMethod( po, "GetTblAlias()", V4Dbf.GetTblAlias(), "TestV4", 6 ); + rc += TestMethod( po, "GetDbfStatus()", V4Dbf.GetDbfStatus(), XB_OPEN ); + rc += TestMethod( po, "GetCurRecNo()", (xbInt32) V4Dbf.GetCurRecNo(), 4 ); + rc += TestMethod( po, "GetFirstRecord()", V4Dbf.GetFirstRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "GetCurRecNo()", (xbInt32) V4Dbf.GetCurRecNo(), 1 ); + rc += TestMethod( po, "GetNextRecord()", V4Dbf.GetNextRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "GetCurRecNo()", (xbInt32) V4Dbf.GetCurRecNo(), 2 ); + rc += TestMethod( po, "GetLastRecord()", V4Dbf.GetLastRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "GetCurRecNo()", (xbInt32) V4Dbf.GetCurRecNo(), 4 ); + rc += TestMethod( po, "GetPrevRecord()", V4Dbf.GetPrevRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "GetCurRecNo()", (xbInt32) V4Dbf.GetCurRecNo(), 3 ); + rc += TestMethod( po, "GetRecordLen()", (xbInt32) V4Dbf.GetRecordLen(), 94 ); + + char * p = V4Dbf.GetRecordBuf(); + rc += TestMethod( po, "GetRecordBuf()", p[0], ' ' ); + + if( po == 2 ){ + V4Dbf.DumpHeader( 3 ); + V4Dbf.DumpRecord( 4 ); + } + + rc += TestMethod( po, "PutField()", V4Dbf.PutField( "LASTNAME", "CLINTON" ), XB_NO_ERROR ); + rc += TestMethod( po, "PutRecord()", V4Dbf.PutRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "DeleteRecord()", V4Dbf.DeleteRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "UndeleteRecord()", V4Dbf.UndeleteRecord(), XB_NO_ERROR ); + xbUInt32 ulRecCnt = 0; + rc += TestMethod( po, "GetRecordCnt()", V4Dbf.GetRecordCnt( ulRecCnt ), XB_NO_ERROR ); + rc += TestMethod( po, "GetRecordCnt()", (xbInt32) ulRecCnt, 4 ); + rc += TestMethod( po, "DeleteAllRecords()", V4Dbf.DeleteAllRecords(), XB_NO_ERROR ); + rc += TestMethod( po, "UndeleteAllRecords()", V4Dbf.UndeleteAllRecords(), XB_NO_ERROR ); + rc += TestMethod( po, "GetRecord()", V4Dbf.GetRecord( 2L ), XB_NO_ERROR ); + rc += TestMethod( po, "DeleteRecord()", V4Dbf.DeleteRecord(), XB_NO_ERROR ); + + if( po == 2 ){ + V4Dbf.DumpRecord( 4 ); + } + + xbDbf4 CopyDbf( &x ); + rc += TestMethod( po, "CopyDbfStructure()", V4Dbf.CopyDbfStructure( &CopyDbf, "CopyStructureV4NoMemos", "CopyAliasV4NoMemos", XB_OVERLAY, XB_MULTI_USER ), XB_NO_ERROR ); + rc += TestMethod( po, "CopyDbf.Close()", CopyDbf.Close(), XB_NO_ERROR ); + + if( po == 2 ){ + std::cout << "There should be one entry in the table list" << std::endl; + x.DisplayTableList(); + } + + rc += TestMethod( po, "GetDbfStatus()", CopyDbf.GetDbfStatus(), XB_CLOSED ); + rc += TestMethod( po, "Open()", CopyDbf.xbDbf::Open( "CopyStructureV4NoMemos.DBF", "CopyAliasV4NoMemos" ), XB_NO_ERROR ); + + if( po == 2 ){ + std::cout << "There should be two entries in the table list" << std::endl; + x.DisplayTableList(); + } + + rc += TestMethod( po, "Pack()", V4Dbf.Pack(), XB_NO_ERROR ); + rc += TestMethod( po, "GetDbfStatus()", V4Dbf.GetDbfStatus(), XB_OPEN ); + + rc += TestMethod( po, "Zap()", V4Dbf.Zap(), XB_NO_ERROR ); + if( po == 2 ) + x.DisplayTableList(); + + xbUInt64 ullFileSize2 = 0; + rc2 = V4Dbf.GetFileSize( ullFileSize2 ); + rc = TestMethod( po, "CheckTableSize", ullFileSize2, ullFileSize ); + +// Test of auto commit code here + rc += TestMethod( po, "BlankRecord()", V4Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( fldLastName, "NELSON" ), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( "FIRSTNAME", "WILLIE" ), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( "AMOUNT", "12.34" ), XB_NO_ERROR ); + rc += TestMethod( po, "PutLongField()", V4Dbf.PutLongField( "ZIPCODE", 12345 ), XB_NO_ERROR ); + rc += TestMethod( po, "PutLogicalField()", V4Dbf.PutLogicalField( "SWITCH", "Y" ), XB_NO_ERROR ); + rc += TestMethod( po, "PutFloatField()", V4Dbf.PutFloatField( "TESTNUM", (xbFloat) 1234.5678 ), XB_NO_ERROR ); + rc += TestMethod( po, "PutDoubleField()", V4Dbf.PutDoubleField( "DBLFLDTST", (xbDouble) 9876.5432 ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V4Dbf.AppendRecord(), XB_NO_ERROR ); + + rc += TestMethod( po, "BlankRecord()", V4Dbf.BlankRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( fldLastName, "JOHNSON" ), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( "FIRSTNAME", "JIMMY" ), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( "AMOUNT", "555.33" ), XB_NO_ERROR ); + rc += TestMethod( po, "PutLongField()", V4Dbf.PutLongField( "ZIPCODE", 76523 ), XB_NO_ERROR ); + rc += TestMethod( po, "PutLogicalField()", V4Dbf.PutLogicalField( "SWITCH", "N" ), XB_NO_ERROR ); + rc += TestMethod( po, "PutFloatField()", V4Dbf.PutFloatField( "TESTNUM", (xbFloat) 8765.4321 ), XB_NO_ERROR ); + rc += TestMethod( po, "PutDoubleField()", V4Dbf.PutDoubleField( "DBLFLDTST", (xbDouble) 9876.5432 ), XB_NO_ERROR ); + rc += TestMethod( po, "AppendRecord()", V4Dbf.AppendRecord(), XB_NO_ERROR ); + + rc += TestMethod( po, "PutField()", V4Dbf.PutField( "AMOUNT", "666.22" ), XB_NO_ERROR ); + rc += TestMethod( po, "Abort()", V4Dbf.Abort(), XB_NO_ERROR ); + rc += TestMethod( po, "GetField()", V4Dbf.GetField( "AMOUNT", sf ), XB_NO_ERROR ); + rc += TestMethod( po, "GetField()", sf, " 555.33", 9 ); + + rc += TestMethod( po, "PutField()", V4Dbf.PutField( "AMOUNT", "666.22" ), XB_NO_ERROR ); + rc += TestMethod( po, "Commit()", V4Dbf.Commit(), XB_NO_ERROR ); + rc += TestMethod( po, "GetField()", V4Dbf.GetField( fldAMT, sf ), XB_NO_ERROR ); + rc += TestMethod( po, "GetField()", sf, " 666.22", 9 ); + + rc += TestMethod( po, "GetPrevRecord()", V4Dbf.GetPrevRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "GetNextRecord()", V4Dbf.GetNextRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "GetField()", V4Dbf.GetField( fldAMT, sf ), XB_NO_ERROR ); + rc += TestMethod( po, "GetField()", sf, " 666.22", 9 ); + + rc += TestMethod( po, "AutoCommit()", V4Dbf.SetAutoCommit( 0 ), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( "AMOUNT", "999.33" ), XB_NO_ERROR ); + rc += TestMethod( po, "GetPrevRecord()", V4Dbf.GetPrevRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "GetNextRecord()", V4Dbf.GetNextRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "GetField()", V4Dbf.GetField( fldAMT, sf ), XB_NO_ERROR ); + rc += TestMethod( po, "GetField()", sf, " 666.22", 9 ); + + rc += TestMethod( po, "AutoCommit()", V4Dbf.SetAutoCommit( -1 ), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( "AMOUNT", "999.33" ), XB_NO_ERROR ); + rc += TestMethod( po, "GetCurRecNo()", (xbInt32) V4Dbf.GetCurRecNo(), 2 ); + rc += TestMethod( po, "GetPrevRecord()", V4Dbf.GetPrevRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "GetNextRecord()", V4Dbf.GetNextRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "GetField()", V4Dbf.GetField( fldAMT, sf ), XB_NO_ERROR ); + rc += TestMethod( po, "GetField()", sf, " 999.33", 9 ); + + rc += TestMethod( po, "AutoCommit()", V4Dbf.SetAutoCommit( 1 ), XB_NO_ERROR ); + rc += TestMethod( po, "PutField()", V4Dbf.PutField( "AMOUNT", "432.55" ), XB_NO_ERROR ); + rc += TestMethod( po, "GetCurRecNo()", (xbInt32) V4Dbf.GetCurRecNo(), 2 ); + rc += TestMethod( po, "GetPrevRecord()", V4Dbf.GetPrevRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "GetNextRecord()", V4Dbf.GetNextRecord(), XB_NO_ERROR ); + rc += TestMethod( po, "GetField()", V4Dbf.GetField( fldAMT, sf ), XB_NO_ERROR ); + rc += TestMethod( po, "GetField()", sf, " 432.55", 9 ); + + rc += TestMethod( po, "Close()", V4Dbf.Close(), XB_NO_ERROR ); + if( po == 2 ) + x.DisplayTableList(); + + if( po > 0 || rc < 0 ) + fprintf( stdout, "Total Errors = %d\n", rc * -1 ); + +#ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], rc * -1 ); + x.WriteLogMessage( sMsg ); +#endif + + return rc; +} diff --git a/src/tests/xb_test_expnode.cpp b/src/tests/xb_test_expnode.cpp new file mode 100755 index 0000000..3fb716d --- /dev/null +++ b/src/tests/xb_test_expnode.cpp @@ -0,0 +1,123 @@ +/* xb_test_expnode.cpp + +XBase Software Library + +Copyright (c) 1997,2003,2014,2017,2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the xb expression node functions +// usage: xb_test_expnode QUITE|NORMAL|VERBOSE + +#include "xbase.h" +using namespace xb; + +#include "tstfuncs.cpp" + + +/**************************************************************************/ + +int main( int argCnt, char **av ) +{ + xbInt16 iRc = 0; + xbInt16 po = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + po = 0; + else if( av[1][0] == 'V' ) + po = 2; + } + + xbXBase x; + + #ifdef XB_LOGGING_SUPPORT + x.EnableMsgLogging(); + if( po ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + x.SetDataDirectory( PROJECT_DATA_DIR ); + x.EnableMsgLogging(); + InitTime(); + + if( po > 0 ){ + std::cout << "XBase Expression Node testing program.." << std::endl; + std::cout << "This program tests the XBase expression node logic." << std::endl; + } + + xbString s1 = "TestNode1"; + xbExpNode *n1 = new xbExpNode(); + n1->SetNodeText( s1 ); + n1->SetNodeType( XB_EXP_OPERATOR ); + n1->SetReturnType( XB_EXP_LOGICAL ); + + iRc += TestMethod( po, "GetNodeType()", n1->GetNodeType(), 'O' ); + iRc += TestMethod( po, "GetReturnType()", n1->GetReturnType(), 'L' ); + + xbString s2 = "TestNode2"; + xbExpNode *n2 = new xbExpNode( s2, XB_EXP_FUNCTION, XB_EXP_CHAR ); + + xbString s3 = "TestNode3"; + xbExpNode *n3 = new xbExpNode( s3, XB_EXP_CONSTANT, XB_EXP_NUMERIC ); + + xbString s4 = "TestNode4"; + xbExpNode *n4 = new xbExpNode( s4, XB_EXP_OPERATOR, XB_EXP_DATE ); + + xbString s5 = "TestNode5"; + xbExpNode *n5 = new xbExpNode( s5, XB_EXP_FIELD, XB_EXP_LOGICAL ); + + n1->AddChild( n2 ); + n1->AddChild( n3 ); + n1->AddChild( n4 ); + n1->AddChild( n5 ); + + iRc += TestMethod( po, "GetChildCnt()", (xbInt32) n1->GetChildCnt(), 4 ); + + n1->SetResult( s1 ); + iRc += TestMethod( po, "SetResult() / GetStringResult()", s1, n1->GetStringResult(), 9 ); + + xbBool bVal = xbTrue; + n1->SetResult( bVal ); + iRc += TestMethod( po, "SetResult() / GetBoolResult()", xbTrue, n1->GetBoolResult() ); + + xbDouble d = 123456.789; + n1->SetResult( d ); + iRc += TestMethod( po, "SetResult() / GetNumericResult()", d, n1->GetNumericResult() ); + + #ifdef XB_DEBUG_SUPPORT + if( po > 0 ){ + n1->DumpNode( xbTrue ); + n1->GetChild( 0 )->DumpNode( xbTrue ); + n1->GetChild( 1 )->DumpNode( xbTrue ); + n1->GetChild( 2 )->DumpNode( xbTrue ); + n1->GetChild( 3 )->DumpNode( xbTrue ); + } + #endif + + delete n1; + + if( po > 0 || iRc < 0 ) + fprintf( stdout, "Total Errors = %d\n", iRc * -1 ); + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], iRc * -1 ); + x.WriteLogMessage( sMsg ); + #endif + + return iRc; +} diff --git a/src/tests/xb_test_expression.cpp b/src/tests/xb_test_expression.cpp new file mode 100755 index 0000000..e3b47cc --- /dev/null +++ b/src/tests/xb_test_expression.cpp @@ -0,0 +1,791 @@ +/* xb_test_expression.cpp + +XBase Software Library + +Copyright (c) 1997,2003,2014,2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the class xbExp +// usage: xb_test_expression QUITE|NORMAL|VERBOSE + +#include "xbase.h" +using namespace xb; + +#include "tstfuncs.cpp" + + +/**************************************************************************/ +///@cond DOXYOFF + +class xbExpTest : public xbExp { + + public: + xbExpTest( xbXBase * x ); + xbInt16 GetNextTokenTest( xbExpToken &t ); + xbInt16 OperatorWeightTest( const xbString &sOperator ); + xbExpNode *GetNextNodeTest( xbExpNode * ); +}; + +/**************************************************************************/ +xbExpTest::xbExpTest( xbXBase * x ) : xbExp( x ){ +} +/**************************************************************************/ +xbExpNode *xbExpTest::GetNextNodeTest( xbExpNode *n ){ + return GetNextNode( n ); +} +/**************************************************************************/ +xbInt16 xbExpTest::GetNextTokenTest( xbExpToken &t ){ + return GetNextToken( t ); +} +/**************************************************************************/ +xbInt16 xbExpTest::OperatorWeightTest( const xbString &sOperator ){ + return OperatorWeight( sOperator ); +} +///@endcond DOXYOFF + + +/**************************************************************************/ +xbInt16 DevTester( xbXBase * xb, xbDbf * dbf, const char * sExpIn ){ + + xbExpTest exp( xb ); + xbExpNode *n; + + std::cout << "going to parse expression [" << sExpIn << "]\n"; + xbInt16 iRc = exp.ParseExpression( dbf, sExpIn ); + + std::cout << "back from parse expression\n"; + std::cout << "dump nodes\n"; + n = exp.GetNextNodeTest( NULL ); + if( iRc == XB_NO_ERROR ){ + exp.DumpTree( xbTrue ); + std::cout << "dump nodes\n"; + n = exp.GetNextNodeTest( NULL ); + if( !n ){ + std::cout << "n is null\n"; + } else { + xbInt16 i = 0; + while( n && i < 30 ){ + std::cout << "Node Text = [" << n->GetStringResult().Str() << "]\n"; + n = exp.GetNextNodeTest( n ); + i++; + } + } + std::cout << "end dump nodes\n"; + return 0; + }else{ + std::cout << "Parse Error [" << iRc << "]\n"; + return -1; + } + return 0; +} + +/**************************************************************************/ +xbInt16 TestWeight( xbXBase * xb, xbInt16 iPrintOption, const char * title, const char *sOperator, xbInt16 iExpectedWeight ); +xbInt16 TestWeight( xbXBase * xb, xbInt16 iPrintOption, const char * title, const char *sOperator, xbInt16 iExpectedWeight ){ + + xbInt16 iRc = 0; + xbExpTest expT1( xb ); + + if(( iRc = expT1.OperatorWeightTest( sOperator )) != iExpectedWeight ){ + std::cout << std::endl << "[FAIL O1] " << title << std::endl; + std::cout << " Operator [" << sOperator << "] Weight [" << iRc << "] Expected [" << iExpectedWeight << "]" << std::endl; + return -1; + } + + if( iPrintOption == 2 ) + std::cout << "[PASS] " << title << " Expected matches actual Data=[" << sOperator << "][" << iExpectedWeight << "]" << std::endl; + else if( iPrintOption == 1 ) + std::cout << "[PASS] " << title << std::endl; + + return XB_NO_ERROR; +} +/**************************************************************************/ +xbInt16 TestTokenMethod( xbXBase *xb, xbInt16 iPrintOption, const char * title, const char *sExpression, + const char *sExpectedToken, const char *sExpectedRemainder, char cExpectedNodeType, + char cExpectedReturnType, xbInt16 iErc, xbInt16 iTrc ); + +xbInt16 TestTokenMethod( xbXBase *xb, xbInt16 iPrintOption, const char * title, const char *sExpression, + const char *sExpectedToken, const char *sExpectedRemainder, char cExpectedNodeType, + char cExpectedReturnType, xbInt16 iErc, xbInt16 iTrc ){ + + xbExpTest expT1( xb ); + xbExpToken t; + xbInt16 iRc = XB_NO_ERROR; + t.sExpression = sExpression; + + if(( iRc = expT1.GetNextTokenTest( t )) != iErc ){ + std::cout << std::endl << "[FAIL T1] " << title << std::endl; + std::cout << " Expression [" << sExpression << "]" << std::endl; + std::cout << " GetNextToken iRc = [" << iRc << "]" << std::endl; + return -1; + } + + if( iTrc != t.iSts ){ + std::cout << std::endl << "[FAIL T2] " << title << std::endl; + std::cout << " Expression [" << sExpression << "]" << std::endl; + std::cout << " GetNextToken Token Return Code = [" << iTrc << "]" << std::endl; + return -1; + } + if( iErc == XB_NO_ERROR && iTrc == XB_NO_ERROR && t.sToken != sExpectedToken ){ + std::cout << std::endl << "[FAIL T3] " << title << std::endl; + std::cout << " Expression " << sExpression << std::endl; + std::cout << " Expected Result = [" << sExpectedToken << "] Actual = [" << t.sToken.Str() << "]\n"; + return -1; + } + if( iErc == XB_NO_ERROR && iTrc == XB_NO_ERROR && t.sExpression != sExpectedRemainder ){ + std::cout << std::endl << "[FAIL T4] " << title << std::endl; + std::cout << " Expression " << sExpression << std::endl; + std::cout << " Expected Remainder = [" << sExpectedRemainder << "] Actual = [" << t.sExpression.Str() << "]\n"; + return -1; + } + if( iErc == XB_NO_ERROR && iTrc == XB_NO_ERROR&& t.cNodeType != cExpectedNodeType ){ + std::cout << std::endl << "[FAIL T5] " << title << std::endl; + std::cout << " Expression " << sExpression << std::endl; + std::cout << " Expected Node type = [" << cExpectedNodeType << "] Actual = [" << t.cNodeType << "]\n"; + return -1; + } + if( iErc == XB_NO_ERROR && iTrc == XB_NO_ERROR&& t.cReturnType != cExpectedReturnType ){ + std::cout << std::endl << "[FAIL T6] " << title << std::endl; + std::cout << " Expression " << sExpression << std::endl; + std::cout << " Expected Return type = [" << cExpectedReturnType << "] Actual = [" << t.cReturnType << "]\n"; + return -1; + } + if( iPrintOption == 2 ){ + if( iErc == XB_NO_ERROR ) + std::cout << "[PASS] " << title << " Expected matches actual Data=[" << sExpectedToken << "]" << std::endl; + else + std::cout << "[PASS] " << title << " Expected return code matches actual =[" << iErc << "]" << std::endl; + } else if( iPrintOption == 1 ) + std::cout << "[PASS] " << title << std::endl; + + return 0; +} + +/**************************************************************************/ +xbInt16 TestMethod( xbXBase *xb, xbDbf *d, xbInt16 PrintOption, const char * title, + const xbString &sExpression, const char * sExpectedResult, xbInt16 iExpectedResultLen ); + +xbInt16 TestMethod( xbXBase *xb, xbDbf *d, xbInt16 PrintOption, const char * title, + const xbString &sExpression, const char * sExpectedResult, xbInt16 iExpectedResultLen ){ + + xbInt16 iRc = XB_NO_ERROR; + xbString sResult; + xbExp exp( xb ); + + if(( iRc = exp.ParseExpression( d, sExpression )) != XB_NO_ERROR ){ + std::cout << std::endl << "[FAIL 1] " << title << std::endl; + std::cout << " Return Code = [" << iRc << "]" << std::endl; + return -1; + } + if(( iRc = exp.GetReturnType()) != XB_EXP_CHAR ){ + std::cout << std::endl << "[FAIL 2] " << title << std::endl; + std::cout << " Result type not XB_EXP_CHAR = [" << exp.GetReturnType() << "]" << std::endl; + return -1; + } + if(( iRc = exp.ProcessExpression()) != XB_NO_ERROR ){ + std::cout << std::endl << "[FAIL 3] " << title << std::endl; + std::cout << " Return Code = [" << iRc << "]" << std::endl; + return -1; + } + if(( iRc = exp.GetStringResult( sResult )) != XB_NO_ERROR ){ + std::cout << std::endl << "[FAIL 4] " << title << std::endl; + std::cout << " Return Code = [" << iRc << "]" << std::endl; + return -1; + } + if( sResult != sExpectedResult ){ + std::cout << std::endl << "[FAIL 5] " << title << std::endl; + std::cout << " Expected Result = [" << sExpectedResult << "] Actual Result =[" << sResult.Str() << "]" << std::endl; + exp.DumpTree( 1 ); + return -1; + } + if( exp.GetResultLen() != iExpectedResultLen ){ + std::cout << std::endl << "[FAIL 6] " << title << std::endl; + std::cout << " Expected Result Len = [" << iExpectedResultLen << "] Actual Result =[" << exp.GetResultLen() << "]" << std::endl; + exp.DumpTree( 1 ); + return -1; + } + if( PrintOption == 2 ) + std::cout << "[PASS] " << title << " Expected [" << sExpectedResult << "] matches actual [" << exp.GetResultLen() << "]" << std::endl; + else if( PrintOption == 1 ) + std::cout << "[PASS] " << title << std::endl; + + return 0; +} + +/**************************************************************************/ +xbInt16 TestMethod( xbXBase * xb, xbDbf * d, xbInt16 PrintOption, const char * title, + const xbString &sExpression, xbDouble dExpectedResult ); + +xbInt16 TestMethod( xbXBase * xb, xbDbf * d, xbInt16 PrintOption, const char * title, + const xbString &sExpression, xbDouble dExpectedResult ){ + + xbDouble dResult; + xbInt16 iRc = XB_NO_ERROR; + xbExp exp( xb ); + + if(( iRc = exp.ParseExpression( d, sExpression )) != XB_NO_ERROR ){ + std::cout << std::endl << "[FAIL 1] " << title << std::endl; + std::cout << " Return Code = [" << iRc << "]" << std::endl; + return -1; + } + if(( iRc = exp.GetReturnType()) != XB_EXP_NUMERIC ){ + std::cout << std::endl << "[FAIL 2] " << title << std::endl; + std::cout << " Result type not XB_EXP_NUMERIC = [" << exp.GetReturnType() << "]" << std::endl; + return -1; + } + if(( iRc = exp.ProcessExpression()) != XB_NO_ERROR ){ + std::cout << std::endl << "[FAIL 3] " << title << std::endl; + std::cout << " Return Code = [" << iRc << "]" << std::endl; + return -1; + } + if(( iRc = exp.GetNumericResult( dResult )) != XB_NO_ERROR ){ + std::cout << std::endl << "[FAIL 4] " << title << std::endl; + std::cout << " Return Code = [" << iRc << "]" << std::endl; + return -1; + } + if( !dblEquals( dResult, dExpectedResult, .01 )){ + std::cout << std::endl << "[FAIL 5] " << title << std::endl; + std::cout << " Expected Result = [" << dExpectedResult << "] Actual Result =[" << dResult << "]" << std::endl; + // dump out the tree + exp.DumpTree( 1 ); + return -1; + } + if( PrintOption == 2 ) + std::cout << "[PASS] " << title << " Expected [" << dExpectedResult << "] matches actual [" << exp.GetResultLen() << "]" << std::endl; + else if( PrintOption == 1 ) + std::cout << "[PASS] " << title << std::endl; + return 0; +} +/**************************************************************************/ +xbInt16 TestMethod( xbXBase * xb, xbDbf * d, xbInt16 PrintOption, const char * title, + const xbString &sExpression, xbDate dtExpectedResult ); +xbInt16 TestMethod( xbXBase * xb, xbDbf * d, xbInt16 PrintOption, const char * title, + const xbString &sExpression, xbDate dtExpectedResult ){ + + xbDate dtResult; + xbInt16 iRc = XB_NO_ERROR; + xbExp exp( xb ); + if(( iRc = exp.ParseExpression( d, sExpression )) != XB_NO_ERROR ){ + std::cout << std::endl << "[FAIL 1] " << title << std::endl; + std::cout << " Return Code = [" << iRc << "]" << std::endl; + return -1; + } + if(( iRc = exp.GetReturnType()) != XB_EXP_DATE ){ + std::cout << std::endl << "[FAIL 2] " << title << std::endl; + std::cout << " Result type not XB_EXP_DATE = [" << exp.GetReturnType() << "]" << std::endl; + return -1; + } + if(( iRc = exp.ProcessExpression()) != XB_NO_ERROR ){ + std::cout << std::endl << "[FAIL 3] " << title << std::endl; + std::cout << " Return Code = [" << iRc << "]" << std::endl; + return -1; + } + if(( iRc = exp.GetDateResult( dtResult )) != XB_NO_ERROR ){ + std::cout << std::endl << "[FAIL 4] " << title << std::endl; + std::cout << " Return Code = [" << iRc << "]" << std::endl; + return -1; + } + if( dtResult != dtExpectedResult ){ + std::cout << std::endl << "[FAIL 5] " << title << std::endl; + std::cout << " Expected Result = [" << dtExpectedResult.Str() << "] Actual Result =[" << dtResult.Str() << "]" << std::endl; + // dump out the tree + exp.DumpTree( 1 ); + return -1; + } + if( PrintOption == 2 ) + std::cout << "[PASS] " << title << " Expected [" << dtExpectedResult.Str() << "] matches actual [" << exp.GetResultLen() << "]" << std::endl; + else if( PrintOption == 1 ) + std::cout << "[PASS] " << title << std::endl; + + return 0; +} +/**************************************************************************/ +xbInt16 TestMethod( xbXBase * xb, xbDbf * d, xbInt16 PrintOption, const char * title, + const xbString &sExpression, xbBool bExpectedResult ); +xbInt16 TestMethod( xbXBase * xb, xbDbf * d, xbInt16 PrintOption, const char * title, + const xbString &sExpression, xbBool bExpectedResult ){ + + xbInt16 iRc = XB_NO_ERROR; + + xbBool bResult; + xbExp exp( xb ); + if(( iRc = exp.ParseExpression( d, sExpression )) != XB_NO_ERROR ){ + std::cout << std::endl << "[FAIL 1] " << title << std::endl; + std::cout << " Return Code = [" << iRc << "]" << std::endl; + return -1; + } + if(( iRc = exp.GetReturnType()) != XB_EXP_LOGICAL ){ + std::cout << std::endl << "[FAIL 2] " << title << std::endl; + std::cout << " Result type not XB_EXP_LOGICAL = [" << exp.GetReturnType() << "]" << std::endl; + return -1; + } + if(( iRc = exp.ProcessExpression()) != XB_NO_ERROR ){ + std::cout << std::endl << "[FAIL 3] " << title << std::endl; + std::cout << " Return Code = [" << iRc << "]" << std::endl; + return -1; + } + if(( iRc = exp.GetBoolResult( bResult )) != XB_NO_ERROR ){ + std::cout << std::endl << "[FAIL 4] " << title << std::endl; + std::cout << " Return Code = [" << iRc << "]" << std::endl; + return -1; + } + if( bResult != bExpectedResult ){ + std::cout << std::endl << "[FAIL 5] " << title << std::endl; + std::cout << " Expected Result = [" << bExpectedResult << "] Actual Result =[" << bResult << "]" << std::endl; + // dump out the tree + exp.DumpTree( 1 ); + return -1; + } + if( PrintOption == 2 ) + std::cout << "[PASS] " << title << " Expected [" << bExpectedResult << "] matches actual [" << bResult << "]" << std::endl; + else if( PrintOption == 1 ) + std::cout << "[PASS] " << title << std::endl; + return 0; +} +/**************************************************************************/ +int main( int argCnt, char **av ) +{ + xbInt16 iRc = 0; + xbInt16 rc2 = 0; + xbInt16 po = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + po = 0; + else if( av[1][0] == 'V' ) + po = 2; + } + + xbSchema MyRecord[] = + { + { "CHAR1", XB_CHAR_FLD, 5, 0 }, + { "CHAR2", XB_CHAR_FLD, 7, 0 }, + { "DATE1", XB_DATE_FLD, 8, 0 }, + { "DATE2", XB_DATE_FLD, 8, 0 }, + { "NUM1", XB_NUMERIC_FLD, 9, 2 }, + { "",0,0,0 } + }; + + xbXBase x; + xbDbf * MyFile; + xbDate d; + + #ifdef XB_LOGGING_SUPPORT + x.EnableMsgLogging(); + if( po ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + x.SetDataDirectory( PROJECT_DATA_DIR ); + x.EnableMsgLogging(); + InitTime(); + + if( po > 0 ){ + std::cout << "XBase Expression testing program.." << std::endl; + std::cout << "This program tests the XBase expression logic." << std::endl; + std::cout << "Default Data Directory is [" << x.GetDataDirectory().Str() << "]" << std::endl; + } + +// return 0; + + #ifdef XB_DBF4_SUPPORT + MyFile = new xbDbf4( &x ); /* version 4 dbf file */ + #else + MyFile = new xbDbf3( &x ); /* version 3 dbf file */ + #endif + + + +// return 0; + + rc2 = MyFile->CreateTable( "ExpTest.DBF", "ExpTest", MyRecord, XB_OVERLAY, XB_MULTI_USER ); + +// return 0; + + iRc += TestMethod( po, "CreateTable()", rc2, XB_NO_ERROR ); + iRc += TestMethod( po, "PutField()", MyFile->PutField( "CHAR1", "TEST" ), XB_NO_ERROR ); + iRc += TestMethod( po, "PutField()", MyFile->PutField( "CHAR2", "TEST7B" ), XB_NO_ERROR ); + iRc += TestMethod( po, "PutField()", MyFile->PutFloatField( "NUM1", 5 ), XB_NO_ERROR ); + iRc += TestMethod( po, "PutField()", MyFile->PutField( "DATE1", "19890303" ), XB_NO_ERROR ); + iRc += TestMethod( po, "PutField()", MyFile->PutField ( "DATE2", "20120708" ), XB_NO_ERROR ); + iRc += TestMethod( po, "AppendRecord()", MyFile->AppendRecord(), XB_NO_ERROR ); + + +// return 0; + + + iRc += TestTokenMethod( &x, po, "EOX Test1", "", "", "", '?', XB_EXP_UNKNOWN, XB_NO_ERROR, XB_END_OF_EXPRESSION ); + iRc += TestTokenMethod( &x, po, "EOX Test2 ", " ", "", "", '?', XB_EXP_UNKNOWN, XB_NO_ERROR, XB_END_OF_EXPRESSION ); + iRc += TestTokenMethod( &x, po, "Paren Test1 ", "(SOMETOKEN)+5-100", "SOMETOKEN", "+5-100", XB_EXP_NOTROOT, XB_EXP_UNKNOWN, XB_NO_ERROR , XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Paren Test2 ", "{ANOTHERTOKEN} + 55-100", "ANOTHERTOKEN", " + 55-100", XB_EXP_NOTROOT, XB_EXP_UNKNOWN, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Paren Test3 ", "{{NESTED}TOKEN} + 55-100", "{NESTED}TOKEN", " + 55-100", XB_EXP_NOTROOT, XB_EXP_UNKNOWN, XB_NO_ERROR, XB_NO_ERROR ); + + // next line generates log message + iRc += TestTokenMethod( &x, po, "Paren Test4 ", "{{NESTED}TOKEN + 55-100", "{NESTED}TOKEN", " + 55-100", XB_EXP_NOTROOT, XB_EXP_UNKNOWN, XB_PARSE_ERROR, XB_UNBALANCED_PARENS ); + iRc += TestTokenMethod( &x, po, "Paren Test5 ", " (SOMETOKEN )+5-100", "SOMETOKEN ", "+5-100", XB_EXP_NOTROOT, XB_EXP_UNKNOWN, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Quote Test1 ", "\"SOMETOKEN\"+5-100", "SOMETOKEN", "+5-100", XB_EXP_CONSTANT, XB_EXP_CHAR, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Quote Test2 ", "'SOMETOKEN2'", "SOMETOKEN2", "", XB_EXP_CONSTANT, XB_EXP_CHAR, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Quote Test3 ", " 'SOMETOKEN3 '", "SOMETOKEN3 ", "", XB_EXP_CONSTANT, XB_EXP_CHAR, XB_NO_ERROR, XB_NO_ERROR ); + + + + // next line generates log message + + iRc += TestTokenMethod( &x, po, "Quote Test3 ", " 'SOMETOKEN4 ", "SOMETOKEN3 ", "", XB_EXP_CONSTANT, XB_EXP_CHAR, XB_PARSE_ERROR, XB_UNBALANCED_QUOTES ); + + + iRc += TestTokenMethod( &x, po, "Logical Constant1 ", ".T.", "T", "", XB_EXP_CONSTANT, XB_EXP_LOGICAL, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Logical Constant2 ", ".F.", "F", "", XB_EXP_CONSTANT, XB_EXP_LOGICAL, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Logical Constant3 ", ".TRUE.", "T", "", XB_EXP_CONSTANT, XB_EXP_LOGICAL, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Logical Constant4 ", ".FALSE.", "F", "", XB_EXP_CONSTANT, XB_EXP_LOGICAL, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Logical Constant5 ", ".T. and x", "T", " and x", XB_EXP_CONSTANT, XB_EXP_LOGICAL, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Numeric Constant1 ", "123", "123", "", XB_EXP_CONSTANT, XB_EXP_NUMERIC, XB_NO_ERROR, XB_NO_ERROR ); + + + + iRc += TestTokenMethod( &x, po, "Numeric Constant2 ", "-123", "-123", "", XB_EXP_CONSTANT, XB_EXP_NUMERIC, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Numeric Constant3 ", " - 123", "-123", "", XB_EXP_CONSTANT, XB_EXP_NUMERIC, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Numeric Constant4 ", " - .456", "-.456", "", XB_EXP_CONSTANT, XB_EXP_NUMERIC, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Numeric Constant5 ", " -.002", "-.002", "", XB_EXP_CONSTANT, XB_EXP_NUMERIC, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Numeric Constant6 ", " - .002 + 1", "-.002", " + 1", XB_EXP_CONSTANT, XB_EXP_NUMERIC, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 1", "-", "-", "", XB_EXP_OPERATOR, XB_EXP_UNKNOWN, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 2", "+", "+", "", XB_EXP_OPERATOR, XB_EXP_UNKNOWN, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 3", "*", "*", "", XB_EXP_OPERATOR, XB_EXP_NUMERIC, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 4", "/", "/", "", XB_EXP_OPERATOR, XB_EXP_NUMERIC, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 5", "^", "^", "", XB_EXP_OPERATOR, XB_EXP_NUMERIC, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 6", "%", "%", "", XB_EXP_OPERATOR, XB_EXP_NUMERIC, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 7", "=", "=", "", XB_EXP_OPERATOR, XB_EXP_LOGICAL, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 8", "<", "<", "", XB_EXP_OPERATOR, XB_EXP_LOGICAL, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 9", ">", ">", "", XB_EXP_OPERATOR, XB_EXP_LOGICAL, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 10", "$", "$", "", XB_EXP_OPERATOR, XB_EXP_LOGICAL, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 11", "**", "**", "", XB_EXP_OPERATOR, XB_EXP_NUMERIC, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 12", "++", "++", "", XB_EXP_POST_OPERATOR, XB_EXP_NUMERIC, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 13", "--", "--", "", XB_EXP_POST_OPERATOR, XB_EXP_NUMERIC, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 14", "-- ", "--", " ", XB_EXP_POST_OPERATOR, XB_EXP_NUMERIC, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 15", "--X", "--", "X", XB_EXP_PRE_OPERATOR, XB_EXP_NUMERIC, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 16", "++X", "++", "X", XB_EXP_PRE_OPERATOR, XB_EXP_NUMERIC, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 17", "+=", "+=", "", XB_EXP_OPERATOR, XB_EXP_NUMERIC, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 18", "-=", "-=", "", XB_EXP_OPERATOR, XB_EXP_NUMERIC, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 19", "*=", "*=", "", XB_EXP_OPERATOR, XB_EXP_NUMERIC, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 20", "/=", "/=", "", XB_EXP_OPERATOR, XB_EXP_NUMERIC, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 21", "<>", "<>", "", XB_EXP_OPERATOR, XB_EXP_LOGICAL, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 22", "<=", "<=", "", XB_EXP_OPERATOR, XB_EXP_LOGICAL, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 23", ">=", ">=", "", XB_EXP_OPERATOR, XB_EXP_LOGICAL, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 24", ">= grapes", ">=", " grapes", XB_EXP_OPERATOR, XB_EXP_LOGICAL, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 25", "< apples ", "<", " apples ", XB_EXP_OPERATOR, XB_EXP_LOGICAL, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 26", ".NOT.", ".NOT.", "", XB_EXP_OPERATOR, XB_EXP_LOGICAL, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 27", ".AND.", ".AND.", "", XB_EXP_OPERATOR, XB_EXP_LOGICAL, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Operator 28", ".OR.", ".OR.", "", XB_EXP_OPERATOR, XB_EXP_LOGICAL, XB_NO_ERROR, XB_NO_ERROR ); + + iRc += TestTokenMethod( &x, po, "Function 1", "STOD ( \"08252017\" )", "STOD ( \"08252017\" )", "", XB_EXP_FUNCTION, XB_EXP_DATE, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Function 2", "STR( 8 )", "STR( 8 )", "", XB_EXP_FUNCTION, XB_EXP_CHAR, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Function 3", "STR( (8-3)+3 )", "STR( (8-3)+3 )", "", XB_EXP_FUNCTION, XB_EXP_CHAR, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Function 4", "STR( (8-3)+3 ) + \"A\"", "STR( (8-3)+3 )", " + \"A\"", XB_EXP_FUNCTION, XB_EXP_CHAR, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Function 5", "ISALPHA( \"A\" )", "ISALPHA( \"A\" )", "", XB_EXP_FUNCTION, XB_EXP_LOGICAL, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Function 6", "EXP( 6 )", "EXP( 6 )", "", XB_EXP_FUNCTION, XB_EXP_NUMERIC, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Field 1", "NUM1", "NUM1", "", XB_EXP_FIELD, XB_EXP_UNKNOWN, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Field 2", "NUM1 + X", "NUM1", " + X", XB_EXP_FIELD, XB_EXP_UNKNOWN, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Field 3", "ExpTest->NUM1", "ExpTest->NUM1", "", XB_EXP_FIELD, XB_EXP_UNKNOWN, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Field 4", "ExpTest ->NUM1", "ExpTest ->NUM1", "", XB_EXP_FIELD, XB_EXP_UNKNOWN, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Field 5", "ExpTest -> NUM1", "ExpTest -> NUM1", "", XB_EXP_FIELD, XB_EXP_UNKNOWN, XB_NO_ERROR, XB_NO_ERROR ); + iRc += TestTokenMethod( &x, po, "Field 6", "ExpTest -> NUM1+1", "ExpTest -> NUM1", "+1", XB_EXP_FIELD, XB_EXP_UNKNOWN, XB_NO_ERROR, XB_NO_ERROR ); + + iRc += TestWeight( &x, po, "Weight Test", "", 0 ); + iRc += TestWeight( &x, po, "Weight Test", "toobig", 0 ); + iRc += TestWeight( &x, po, ".OR. Weight Test", ".OR.", 1 ); + iRc += TestWeight( &x, po, ".AND. Weight Test", ".AND.", 2 ); + iRc += TestWeight( &x, po, ".NOT. Weight Test", ".NOT.", 3 ); + iRc += TestWeight( &x, po, "> Weight Test", ">", 4 ); + iRc += TestWeight( &x, po, ">= Weight Test", ">=", 4 ); + iRc += TestWeight( &x, po, "< Weight Test", "<", 4 ); + iRc += TestWeight( &x, po, "<= Weight Test", "<=", 4 ); + iRc += TestWeight( &x, po, "<> Weight Test", "<>", 4 ); + iRc += TestWeight( &x, po, "# Weight Test", "#", 4 ); + iRc += TestWeight( &x, po, "$ Weight Test", "$", 4 ); + iRc += TestWeight( &x, po, "= Weight Test", "=", 4 ); + iRc += TestWeight( &x, po, "-- Prefix decrement Weight Test", "--0", 9 ); + iRc += TestWeight( &x, po, "++ Prefix increment Weight Test", "++0", 9 ); + iRc += TestWeight( &x, po, "** Weight Test", "**", 8 ); + iRc += TestWeight( &x, po, "^ Weight Test", "^", 8 ); + iRc += TestWeight( &x, po, "* Weight Test", "*", 7 ); + iRc += TestWeight( &x, po, "* Weight Test", "/", 7 ); + iRc += TestWeight( &x, po, "* Weight Test", "%", 7 ); + iRc += TestWeight( &x, po, "* Weight Test", "*=", 7 ); + iRc += TestWeight( &x, po, "* Weight Test", "/=", 7 ); + iRc += TestWeight( &x, po, "+ Weight Test", "+", 6 ); + iRc += TestWeight( &x, po, "- Weight Test", "-", 6 ); + iRc += TestWeight( &x, po, "+= Weight Test", "+=", 6 ); + iRc += TestWeight( &x, po, "-= Weight Test", "-=", 6 ); + iRc += TestWeight( &x, po, "-- Postfix decrement Weight Test", "--1", 5 ); + iRc += TestWeight( &x, po, "++ Postfix increment Weight Test", "++1", 5 ); + + iRc += TestMethod( &x, MyFile, po, "CharTest1", "CHAR1", "TEST ", 5 ); + iRc += TestMethod( &x, MyFile, po, "CharTest2", "ExpTest->CHAR1", "TEST ", 5 ); + iRc += TestMethod( &x, MyFile, po, "CharTest3", "ExpTest->CHAR1+CHAR1", "TEST TEST ", 10 ); + iRc += TestMethod( &x, MyFile, po, "CharTest4", "\"PRE_ \"+\" _POST\"", "PRE_ _POST", 11 ); + iRc += TestMethod( &x, MyFile, po, "CharTest5", "\"PRE_ \"-\" _POST\"", "PRE_ _POST ", 11 ); + iRc += TestMethod( &x, MyFile, po, "CharTest6", "\"PRE_\"+ExpTest->CHAR1+\"_POST\"", "PRE_TEST _POST", 14 ); + iRc += TestMethod( &x, MyFile, po, "CharTest7", "STR(123)", " 123", 10 ); + iRc += TestMethod( &x, MyFile, po, "CharTest8", "STR(123)+LTRIM(STR(456))", " 123456", 20 ); + iRc += TestMethod( &x, MyFile, po, "CharTest9", "STR(8)+STR(7)", " 8 7", 20 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest1", "ALLTRIM( \" ABCD \" )", "ABCD", 11 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest2", "CDOW( STOD( \"20171014\" ))", "Saturday", 9 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest3", "CHR( 66 )", "B", 1 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest4", "CMONTH( STOD( \"20171114\" ) )", "November", 9 ); + + // next line causes MAC compiler to cough up a furball + //iRc += TestMethod( &x, MyFile, po, "FuncTest5", "DESCEND( \"ABCDE\" )", "¾½¼»º", 5 ); + + char sDescendResult[6]; // = "¾½¼»º"; + sDescendResult[0] = (char) 0xBE; + sDescendResult[1] = (char) 0xBD; + sDescendResult[2] = (char) 0xBC; + sDescendResult[3] = (char) 0xBB; + sDescendResult[4] = (char) 0xBA; + sDescendResult[5] = (char) 0x00; + iRc += TestMethod( &x, MyFile, po, "FuncTest5", "DESCEND( \"ABCDE\" )", sDescendResult, 5 ); + + iRc += TestMethod( &x, MyFile, po, "FuncTest6", "DTOC( STOD( \"20171114\" ))", "11/14/17", 8 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest7", "DTOS( STOD( \"20171114\" ))", "20171114", 8 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest8", "LEFT( \"ABCDEFGH\", 5 )", "ABCDE", 5 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest9", "LOWER( \"ABCDEFGH\" )", "abcdefgh", 8 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest10", "LTRIM( \" ABC\" )", "ABC", 6 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest11", "REPLICATE( \"ABC\", 3 )", "ABCABCABC", 9 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest12", "RIGHT( \"ABCDEFGH\", 5 )", "DEFGH", 5 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest13", "RTRIM( \"ABCD \" )", "ABCD", 7 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest14", "SPACE( 5 )", " ", 5 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest15", "STR( 8 )", " 8", 10 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest16", "STR( 3, 4 )", " 3", 4 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest17", "STR( 12.7, 5, 2 )", "12.70", 5 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest18", "STR( 43.17, 9, 4, \"0\" )", "0043.1700", 9 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest19", "STRZERO( 56.21, 9, 4 )", "0056.2100", 9 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest20", "SUBSTR( \"SOMESTRING\", 3, 5 )", "MESTR", 5 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest21", "TRIM( \" abc123 \" )", " abc123", 12 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest22", "UPPER( \"abc123RRR\" )", "ABC123RRR", 9 ); + + // numeric logic tests + iRc += TestMethod( &x, MyFile, po, "NumericTest1", "1 + 1", (xbDouble) 2 ); + iRc += TestMethod( &x, MyFile, po, "NumericTest2", "6 - 1", (xbDouble) 5 ); + iRc += TestMethod( &x, MyFile, po, "NumericTest3", "6 * 4", (xbDouble) 24 ); + iRc += TestMethod( &x, MyFile, po, "NumericTest4", "8 / 2", (xbDouble) 4 ); + iRc += TestMethod( &x, MyFile, po, "NumericTest5", "3 ^ 3", (xbDouble) 27 ); + iRc += TestMethod( &x, MyFile, po, "NumericTest6", "4 ** 4", (xbDouble) 256 ); + iRc += TestMethod( &x, MyFile, po, "NumericTest7", "NUM1", (xbDouble) 5 ); + iRc += TestMethod( &x, MyFile, po, "NumericTest8", "NUM1 + 2.3", (xbDouble) 7.3 ); + iRc += TestMethod( &x, MyFile, po, "NumericTest9", "++NUM1", (xbDouble) 6 ); + iRc += TestMethod( &x, MyFile, po, "NumericTest10", "NUM1++", (xbDouble) 5 ); + iRc += TestMethod( &x, MyFile, po, "NumericTest11", "--NUM1", (xbDouble) 4 ); + iRc += TestMethod( &x, MyFile, po, "NumericTest12", "NUM1--", (xbDouble) 5 ); + iRc += TestMethod( &x, MyFile, po, "NumericTest13", "3++", (xbDouble) 3 ); + iRc += TestMethod( &x, MyFile, po, "NumericTest14", "++3", (xbDouble) 4 ); + iRc += TestMethod( &x, MyFile, po, "NumericTest15", "4--", (xbDouble) 4 ); + iRc += TestMethod( &x, MyFile, po, "NumericTest16", "--4", (xbDouble) 3 ); + iRc += TestMethod( &x, MyFile, po, "NumericTest17", "3 += 12", (xbDouble) 15 ); + iRc += TestMethod( &x, MyFile, po, "NumericTest18", "3 -= 12", (xbDouble) -9 ); + iRc += TestMethod( &x, MyFile, po, "NumericTest19", "3 *= 12", (xbDouble) 36 ); + iRc += TestMethod( &x, MyFile, po, "NumericTest20", "12 /= 3", (xbDouble) 4 ); + iRc += TestMethod( &x, MyFile, po, "NumericTest21", "(12+3)*(15-13)", (xbDouble) 30 ); + + // numeric functions + iRc += TestMethod( &x, MyFile, po, "FuncTest23", "ABS( -22 )", (xbDouble) 22 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest24", "ABS( 23 )", (xbDouble) 23 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest25", "ASC( \"A\" )", (xbDouble) 65 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest26", "AT( \",\", \"Booth, Joseph\" )", (xbDouble) 6 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest27", "DAY( STOD( \"20171017\" ))", (xbDouble) 17 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest28", "DESCEND( 1991 )", (xbDouble) -1991 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest29", "DOW( STOD( \"20171017\" ) )", (xbDouble) 3 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest30", "DOW( STOD( \"20171021\" ) )", (xbDouble) 0 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest31", "EXP( 0 )", (xbDouble) 1 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest32", "INT( 123.45 )", (xbDouble) 123 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest33", "LEN( \"ABC123\" )", (xbDouble) 6 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest34", "LOG( 10 )", (xbDouble) 2.3 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest35", "MAX( 10, 20 )", (xbDouble) 20 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest36", "MIN( 10, 20 )", (xbDouble) 10 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest37", "MONTH( STOD( \"20171017\" ))", (xbDouble) 10 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest38", "RECCOUNT()", (xbDouble) 1 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest39", "RECNO()", (xbDouble) 1 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest40", "SQRT( 9 )", (xbDouble) 3 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest41", "VAL( \"89\" )", (xbDouble) 89 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest42", "VAL( \"22.13 and some text\" )", (xbDouble) 22.13 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest43", "YEAR( STOD( \"20171017\" ))", (xbDouble) 2017 ); + + // date logic tests + xbDate dtTest1( "19890303" ); + xbDate dtTest2( "20120708" ); + iRc += TestMethod( &x, MyFile, po, "DateTest1", "ExpTest->DATE1", dtTest1 ); + iRc += TestMethod( &x, MyFile, po, "DateTest2", "DATE1", dtTest1 ); + iRc += TestMethod( &x, MyFile, po, "DateTest3", "ExpTest->DATE2", dtTest2 ); + iRc += TestMethod( &x, MyFile, po, "DateTest4", "DATE2", dtTest2 ); + iRc += TestMethod( &x, MyFile, po, "DateTest5", "DATE2 - DATE1", (xbDouble) 8528 ); + + dtTest1.Set( "20120705" ); + iRc += TestMethod( &x, MyFile, po, "DateTest6", "DATE2 - 3", dtTest1 ); + iRc += TestMethod( &x, MyFile, po, "DateTest7", "DATE2 -= 3", dtTest1 ); + + dtTest1.Set( "20120718" ); + iRc += TestMethod( &x, MyFile, po, "DateTest8", "DATE2 + 10", dtTest1 ); + iRc += TestMethod( &x, MyFile, po, "DateTest9", "DATE2 += 10", dtTest1 ); + + dtTest1.Set( "20120709" ); + iRc += TestMethod( &x, MyFile, po, "DateTest10", "++DATE2", dtTest1 ); + dtTest1.Set( "20120707" ); + iRc += TestMethod( &x, MyFile, po, "DateTest11", "--DATE2", dtTest1 ); + + dtTest1.Set( "20120708" ); + iRc += TestMethod( &x, MyFile, po, "DateTest12", "DATE2++", dtTest1 ); + iRc += TestMethod( &x, MyFile, po, "DateTest13", "DATE2--", dtTest1 ); + + iRc += TestMethod( &x, MyFile, po, "DateTest14", "{07/08/12}", dtTest1 ); + iRc += TestMethod( &x, MyFile, po, "DateTest15", "{07/08/2012}", dtTest1 ); + + iRc += TestMethod( &x, MyFile, po, "DateTest16", "{07/11/12} -3", dtTest1 ); + iRc += TestMethod( &x, MyFile, po, "DateTest17", "{07/06/2012} + 2", dtTest1 ); + + iRc += TestMethod( &x, MyFile, po, "FuncTest44", "CTOD( \"07\\08\\12\" )", dtTest1 ); + + xbDate dtToday; + iRc += TestMethod( &x, MyFile, po, "FuncTest45", "DATE()", dtToday ); + + dtTest2 = "28870625"; + iRc += TestMethod( &x, MyFile, po, "FuncTest46", "DESCEND( DATE2 )", dtTest2 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest47", "STOD( \"20120708\" )", dtTest1 ); + + // boolean logic tests + iRc += TestMethod( &x, MyFile, po, "LogicTest1", "3=5", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest2", "5=5", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest3", "\"abc\"=\"def\"", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest4", "\"abc\"=\"abc\"", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest5", "CTOD( \"07\\08\\12\" ) = CTOD ( \"07\\08\\12\" )", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest6", "CTOD( \"07\\09\\12\" ) = CTOD ( \"07\\08\\12\" )", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest7", "3<>5", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest8", "5<>5", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest9", "3!=5", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest10", "5!=5", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest11", "3 # 5", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest12", "5#5", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest13", "\"3\"<>\"5\"", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest14", "\"5\"<>\"5\"", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest15", "\"3\"!=\"5\"", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest16", "\"5\"!=\"5\"", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest17", "\"3\" # \"5\"", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest18", "\"5\"#\"5\"", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest19", "CTOD( \"07\\08\\12\" ) <> CTOD ( \"07\\08\\12\" )", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest20", "CTOD( \"07\\09\\12\" ) <> CTOD ( \"07\\08\\12\" )", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest21", "CTOD( \"07\\08\\12\" ) != CTOD ( \"07\\08\\12\" )", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest22", "CTOD( \"07\\09\\12\" ) != CTOD ( \"07\\08\\12\" )", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest23", "CTOD( \"07\\08\\12\" ) # CTOD ( \"07\\08\\12\" )", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest24", "CTOD( \"07\\09\\12\" ) # CTOD ( \"07\\08\\12\" )", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest25", "3<5", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest26", "5<5", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest27", "5<4", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest28", "\"a\"<\"b\"", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest29", "\"a\"<\"a\"", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest30", "\"c\"<\"b\"", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest31", "CTOD( \"07\\07\\12\" ) < CTOD ( \"07\\08\\12\" )", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest32", "CTOD( \"07\\08\\12\" ) < CTOD ( \"07\\08\\12\" )", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest33", "CTOD( \"07\\09\\12\" ) < CTOD ( \"07\\08\\12\" )", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest34", "3>5", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest35", "5>5", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest36", "5>4", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest37", "\"a\">\"b\"", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest38", "\"a\">\"a\"", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest39", "\"c\">\"b\"", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest40", "CTOD( \"07\\07\\12\" ) > CTOD ( \"07\\08\\12\" )", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest41", "CTOD( \"07\\08\\12\" ) > CTOD ( \"07\\08\\12\" )", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest42", "CTOD( \"07\\09\\12\" ) > CTOD ( \"07\\08\\12\" )", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest43", "3<=5", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest44", "5<=5", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest45", "5<=4", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest46", "\"a\"<=\"b\"", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest47", "\"a\"<=\"a\"", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest48", "\"c\"<=\"b\"", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest49", "CTOD( \"07\\07\\12\" ) <= CTOD ( \"07\\08\\12\" )", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest50", "CTOD( \"07\\08\\12\" ) <= CTOD ( \"07\\08\\12\" )", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest51", "CTOD( \"07\\09\\12\" ) <= CTOD ( \"07\\08\\12\" )", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest52", "3>=5", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest53", "5>=5", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest54", "5>=4", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest55", "\"a\">=\"b\"", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest56", "\"a\">=\"a\"", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest57", "\"c\">=\"b\"", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest58", "CTOD( \"07\\07\\12\" ) >= CTOD ( \"07\\08\\12\" )", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest59", "CTOD( \"07\\08\\12\" ) >= CTOD ( \"07\\08\\12\" )", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest60", "CTOD( \"07\\09\\12\" ) >= CTOD ( \"07\\08\\12\" )", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest61", "\"abc123\" $ \"abc\"", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest62", "\"abc\" $ \"abc123\"", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest63", "\"abc\" $ \"zzabc123\"", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest64", ".T.", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest65", ".F.", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest66", ".TRUE.", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest67", ".FALSE.", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest68", ".NOT. .F.", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest69", " NOT .F.", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest70", ".NOT. .T.", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest71", " NOT .T.", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest72", ".T. .AND. .T.", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest73", ".T. AND .T.", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest74", ".T. .AND. .NOT. .T.", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest75", ".T. AND NOT .T.", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest76", ".NOT. .T. .AND. .T.", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest77", " NOT .T. AND .T.", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest78", ".NOT. .T. .AND. .NOT. .T.", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest79", " NOT .T. AND NOT .T.", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest80", ".T. .OR. .T.", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest81", ".T. OR .T.", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest82", ".T. .OR. .NOT. .T.", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest83", ".T. OR NOT .T.", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest84", ".NOT. .T. .OR. .T.", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest85", " NOT .T. OR .T.", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "LogicTest86", ".NOT. .T. .OR. .NOT. .T.", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "LogicTest87", " NOT .T. OR NOT .T.", (xbBool) xbFalse ); + + iRc += TestMethod( &x, MyFile, po, "FuncTest48", "ISALPHA( \"12345\" )", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "FuncTest49", "ISALPHA( \"ABCDEF\" )", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "FuncTest50", "ISALPHA( \"A1234\" )", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "FuncTest51", "ISLOWER( \"12345\" )", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "FuncTest52", "ISLOWER( \"ABCDEF\" )", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "FuncTest53", "ISLOWER( \"abc123\" )", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "FuncTest54", "ISLOWER( \"xyz\" )", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "FuncTest55", "ISUPPER( \"12345\" )", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "FuncTest56", "ISUPPER( \"ABCDEF\" )", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "FuncTest57", "ISUPPER( \"abc123\" )", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "FuncTest58", "ISUPPER( \"xyz\" )", (xbBool) xbFalse ); + iRc += TestMethod( &x, MyFile, po, "FuncTest59", "ISUPPER( \"Xyz\" )", (xbBool) xbTrue ); + iRc += TestMethod( &x, MyFile, po, "FuncTest60", "IIF( .T., \"TRUE \", \"FALSE\" )", "TRUE ", 5 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest61", "IIF( .F., \"TRUE \", \"FALSE\" )", "FALSE", 5 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest62", "DEL()", " ", 1 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest63", "DELETED()", (xbBool) xbFalse ); + iRc += TestMethod( po, "DeleteRecord()", MyFile->DeleteRecord(), XB_NO_ERROR ); + iRc += TestMethod( &x, MyFile, po, "FuncTest64", "DEL()", "*", 1 ); + iRc += TestMethod( &x, MyFile, po, "FuncTest65", "DELETED()", (xbBool) xbTrue ); + iRc += TestMethod( po, "UndeleteRecord()", MyFile->UndeleteRecord(), XB_NO_ERROR ); + + + iRc += TestMethod( po, "Close()", MyFile->Close(), XB_NO_ERROR ); + delete MyFile; + + if( po > 0 || iRc < 0 ) + fprintf( stdout, "Total Errors = %d\n", iRc * -1 ); + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], iRc * -1 ); + x.WriteLogMessage( sMsg ); + #endif + + return iRc; +} diff --git a/src/tests/xb_test_file.cpp b/src/tests/xb_test_file.cpp new file mode 100755 index 0000000..ca32693 --- /dev/null +++ b/src/tests/xb_test_file.cpp @@ -0,0 +1,212 @@ +/* xb_test_file.cpp + +Copyright (c) 1997,2003,2014,2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the file functions + +// usage: xb_test_file QUITE|NORMAL|VERBOSE + + +#include "xbase.h" + + +using namespace xb; + + +#include "tstfuncs.cpp" + + +int main( int argCnt, char **av ) +{ + int rc = 0; + int po = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + po = 0; + else if( av[1][0] == 'V' ) + po = 2; + } + +#ifdef XB_LOGGING_SUPPORT + xbXBase x; + x.EnableMsgLogging(); + if( po ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); +#endif + + InitTime(); + xbFile f( &x ); + xbString sWrkStr; + xbString sWrkStr2; + sWrkStr = PROJECT_DATA_DIR; + f.SetDataDirectory( PROJECT_DATA_DIR ); + + #ifdef WIN32 + sWrkStr.SwapChars( '/', '\\' ); + #else + sWrkStr.SwapChars( '\\', '/' ); + #endif + + rc += TestMethod( po, "Set/GetDataDirectory()", f.GetDataDirectory(), sWrkStr, sWrkStr.Len()); + + f.SetFileName( "TestFile.txt" ); + sWrkStr = "TestFile.txt"; + rc += TestMethod( po, "Set/GetFileName()", f.GetFileName(), sWrkStr, sWrkStr.Len()); + + f.GetFileType( sWrkStr ); + rc += TestMethod( po, "GetFileType()", sWrkStr, "TXT", 3 ); + + #ifdef WIN32 + sWrkStr = "\\my\\directory\\"; + #else + sWrkStr = "/my/directory/"; + #endif + + f.SetDirectory( sWrkStr ); + rc += TestMethod( po, "Set/GetDirectory()", f.GetDirectory(), sWrkStr, sWrkStr.Len()); + + sWrkStr += "TestFile.txt"; + rc += TestMethod( po, "GetFqFileName()", f.GetFqFileName(), sWrkStr, 26 ); + +#ifdef WIN32 + sWrkStr = "\\some\\directory\\myfile.dat"; + sWrkStr2 = "\\some\\directory\\"; +#else + sWrkStr = "/some/directory/myfile.dat"; + sWrkStr2 = "/some/directory/"; +#endif + + + f.SetFqFileName( sWrkStr ); + rc += TestMethod( po, "GetDirectory()", f.GetDirectory(), sWrkStr2, 16 ); + rc += TestMethod( po, "GetFileName()", f.GetFileName(), "myfile.dat", 10 ); + + rc += TestMethod( po, "NameSuffixMissing()", f.NameSuffixMissing( "myfile.dbf", 1 ), 0 ); + rc += TestMethod( po, "NameSuffixMissing()", f.NameSuffixMissing( "myfile", 1 ), 1 ); + rc += TestMethod( po, "NameSuffixMissing()", f.NameSuffixMissing( "MYFILE", 1 ), 2 ); + + f.SetDirectory( PROJECT_DATA_DIR ); + f.SetFileName( "xbfile.txt" ); + + rc += TestMethod( po, "xbFopen()", f.xbFopen( "w+b", XB_MULTI_USER ), XB_NO_ERROR ); + + + xbString sTest; + sTest = "Test Data"; + rc += TestMethod( po, "xbWrite()", f.xbFwrite( sTest.Str(), 9, 1 ), XB_NO_ERROR ); + rc += TestMethod( po, "xbFclose()", f.xbFclose(), XB_NO_ERROR ); + + rc += TestMethod( po, "xbFopen()", f.xbFopen( "r+b", XB_MULTI_USER ), XB_NO_ERROR ); + rc += TestMethod( po, "xbFseek()", f.xbFseek( 0, SEEK_SET ), XB_NO_ERROR ); + char buf[10]; + for( int i = 0; i < 10; i++ ) + buf[i] = 0x00; + rc += TestMethod( po, "xbFread()", f.xbFread( buf, 5, 1 ), XB_NO_ERROR ); + rc += TestMethod( po, "xbFread()", buf, "Test ", 5 ); + + rc += TestMethod( po, "xbFclose()", f.xbFclose(), XB_NO_ERROR ); + rc += TestMethod( po, "xbRemove()", f.xbRemove(), XB_NO_ERROR ); + xbInt16 iWork = 100; + char cBuf[9]; + char *p = cBuf; + f.ePutInt16( cBuf, iWork ); + rc += TestMethod( po, "Put/GetShort()", f.eGetInt16( p ), 100 ); + + xbInt32 lWork = 10101; + f.ePutInt32( p, lWork ); + rc += TestMethod( po, "Put/GetLong()", f.eGetInt32( p ), 10101 ); + + lWork = 2147483647; + f.ePutInt32( p, lWork ); + rc += TestMethod( po, "Put/GetLong()", f.eGetInt32( p ), 2147483647 ); + rc += TestMethod( po, "Put/GetLong()", (xbInt32) f.eGetUInt32( p ), 2147483647 ); + + xbDouble d = 123456.789; + f.ePutDouble( p, d ); + rc += TestMethod( po, "Put/GetDouble()", f.eGetDouble( p ), 123456.789 ); + + xbString sFqnS; + xbString sFqnT; + xbFile f2( &x ); + rc += TestMethod( po, "CreateUniqueFileName()", f2.CreateUniqueFileName( PROJECT_DATA_DIR, "dbf", sFqnS ), XB_NO_ERROR ); + + rc += TestMethod( po, "FileExists()", f2.FileExists( sFqnS ), xbFalse ); + rc += TestMethod( po, "xbFopen()", f2.xbFopen( "w+b", sFqnS, XB_SINGLE_USER ), XB_NO_ERROR ); + rc += TestMethod( po, "xbFclose()", f2.xbFclose(), XB_NO_ERROR ); + rc += TestMethod( po, "FileExists()", f2.FileExists( sFqnS ), xbTrue ); + + rc += TestMethod( po, "CreateUniqueFileName()", f2.CreateUniqueFileName( PROJECT_DATA_DIR, "dbf", sFqnT ), XB_NO_ERROR ); + rc += TestMethod( po, "xbRename()", f2.xbRename( sFqnS, sFqnT ), XB_NO_ERROR ); + rc += TestMethod( po, "xbRemove()", f.xbRemove( sFqnT ), XB_NO_ERROR ); + + xbString sFn; + rc += TestMethod( po, "GetFileNamePart()", f2.GetFileNamePart( sFqnS , sFn ), XB_NO_ERROR ); + rc += TestMethod( po, "GetFileExtPart()", f2.GetFileExtPart( sFqnS , sFn ), XB_NO_ERROR ); + rc += TestMethod( po, "GetFileExtPart()", f2.GetFileDirPart( sFqnS , sFn ), XB_NO_ERROR ); + + + rc += TestMethod( po, "SetBlockSize()", f.SetBlockSize( 100 ), XB_INVALID_BLOCK_SIZE ); + rc += TestMethod( po, "SetBlockSize()", f.SetBlockSize( 512 ), XB_NO_ERROR ); + rc += TestMethod( po, "GetBlockSize()", (xbInt32) f.GetBlockSize(), 512 ); + + + char BlockBuf[513]; + memset( BlockBuf, 0x00, 513 ); + rc += TestMethod( po, "xbFopen()", f.xbFopen( "w+b", XB_SINGLE_USER ), XB_NO_ERROR ); + + for( int i = 0; i < 512; i++ ) + BlockBuf[i] = 'A'; + rc += TestMethod( po, "WriteBlock()", f.WriteBlock( 0L, 512, BlockBuf ), XB_NO_ERROR ); + + for( int i = 0; i < 512; i++ ) + BlockBuf[i] = 'B'; + rc += TestMethod( po, "WriteBlock()", f.WriteBlock( 1L, 512, BlockBuf ), XB_NO_ERROR ); + + for( int i = 0; i < 512; i++ ) + BlockBuf[i] = 'C'; + rc += TestMethod( po, "WriteBlock()", f.WriteBlock( 2L, 512, BlockBuf ), XB_NO_ERROR ); + + char BlockBuf2[513]; + memset( BlockBuf2, 0x00, 513 ); + rc += TestMethod( po, "ReadBlock()", f.ReadBlock( 2L, 512, BlockBuf2 ), XB_NO_ERROR ); + + xbString s1 = BlockBuf; + xbString s2 = BlockBuf2; + + rc += TestMethod( po, "ReadBlock()", s1, s2, 512 ); + + rc += TestMethod( po, "xbTruncate()", f.xbTruncate( 1000 ), XB_NO_ERROR ); + + xbUInt64 ullFsize; + rc += TestMethod( po, "GetFileSize()", f.GetFileSize( ullFsize ), XB_NO_ERROR ); + rc += TestMethod( po, "xbGetFileSize()", (xbInt32) ullFsize, 1000 ); + rc += TestMethod( po, "xbFclose()", f.xbFclose(), XB_NO_ERROR ); + + if( po > 0 || rc < 0 ) + fprintf( stdout, "Total Errors = %d\n", rc * -1 ); + +#ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], rc * -1 ); + x.WriteLogMessage( sMsg ); +#endif + + return rc; +} + diff --git a/src/tests/xb_test_filter.cpp b/src/tests/xb_test_filter.cpp new file mode 100755 index 0000000..2aeade3 --- /dev/null +++ b/src/tests/xb_test_filter.cpp @@ -0,0 +1,185 @@ +/* xb_test_filter.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014,2020,2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the class xbIxFilter + +// usage: xb_test_filter QUITE|NORMAL|VERBOSE + + +#include "xbase.h" + +using namespace xb; + +#include "tstfuncs.cpp" + + +int main( int argCnt, char **av ) +{ + int iRc = 0; + int iRc2 = 0; + int iPo = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + iPo = 0; + else if( av[1][0] == 'V' ) + iPo = 2; + } + + + xbSchema MyV4Record[] = + { + { "CFLD", XB_CHAR_FLD, 6, 0 }, + { "NFLD", XB_NUMERIC_FLD, 6, 0 }, + { "ZFLD", XB_CHAR_FLD, 1, 0 }, + { "",0,0,0 } + }; + + + xbXBase x; +#ifdef XB_LOGGING_SUPPORT + x.EnableMsgLogging(); + if( iPo ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); + x.SetLogSize( 1000000 ); +#endif + + x.SetDataDirectory( PROJECT_DATA_DIR ); + x.EnableMsgLogging(); + + char c; + xbString s; + xbInt32 lRecCnt = 0; + iRc = 0; + + if( iPo > 0 ) + std::cout << "Default Data Directory is [" << x.GetDataDirectory().Str() << "]" << std::endl; + + xbDbf *V4Dbf = new xbDbf4( &x ); + + iRc2 = V4Dbf->CreateTable( "TestFilt.DBF", "TestFilter", MyV4Record, XB_OVERLAY, XB_MULTI_USER ); + iRc += TestMethod( iPo, "CreateTable()", (xbInt32) iRc2, XB_NO_ERROR ); + + + #ifdef XB_NDX_SUPPORT + xbIx *ixPtr; + void *ndx; + iRc2 = V4Dbf->CreateTag( "NDX", "TestFilt.NDX", "CFLD", "", 0, 0, XB_OVERLAY, &ixPtr, &ndx ); + iRc += TestMethod( iPo, "CreateTag()", (xbInt32) iRc2, XB_NO_ERROR ); + if( iRc2 ) + x.DisplayError( iRc2 ); + #endif // XB_NDX_SUPPORT + + + if( iRc2 ) + x.DisplayError( iRc2 ); + + for( xbUInt16 i = 0; i < 5 && iRc == XB_NO_ERROR; i++ ){ + // for( xbUInt16 j = 0; j < 26 && iRc == XB_NO_ERROR; j++ ){ + for( xbInt16 j = 25; j >= 0 && iRc == XB_NO_ERROR; j-- ){ + c = j + 65; + s = c; + s.PadRight( c, (xbUInt32) i + 1 ); + V4Dbf->BlankRecord(); + V4Dbf->PutField( "CFLD", s ); + V4Dbf->PutLongField( "NFLD", ++lRecCnt ); + iRc = V4Dbf->AppendRecord(); + } + } + + iRc += TestMethod( iPo, "SetCurTag()", V4Dbf->SetCurTag( "" ), XB_NO_ERROR ); + xbFilter f1( &x, V4Dbf ); + xbString sMyFilterExpression = "LEFT( CFLD, 2 ) = 'YY'"; + iRc += TestMethod( iPo, "Set()", f1.Set( sMyFilterExpression ), XB_NO_ERROR ); + + iRc += TestMethod( iPo, "SetCurTag()", V4Dbf->SetCurTag( "" ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "Set()", f1.Set( sMyFilterExpression ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetFirstRecord()", f1.GetFirstRecord(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurRecNo()", (xbInt32) V4Dbf->GetCurRecNo(), 28 ); + iRc += TestMethod( iPo, "GetNextRecord()", f1.GetNextRecord(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurRecNo()", (xbInt32) V4Dbf->GetCurRecNo(), 54 ); + iRc += TestMethod( iPo, "GetNextRecord()", f1.GetNextRecord(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurRecNo()", (xbInt32) V4Dbf->GetCurRecNo(), 80 ); + iRc += TestMethod( iPo, "GetLast()", f1.GetLastRecord(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurRecNo()", (xbInt32) V4Dbf->GetCurRecNo(), 106 ); + iRc += TestMethod( iPo, "GetPrev()", f1.GetPrevRecord(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurRecNo()", (xbInt32) V4Dbf->GetCurRecNo(), 80 ); + + sMyFilterExpression = "LEFT( CFLD, 2 ) = 'CC'"; + iRc += TestMethod( iPo, "Set()", f1.Set( sMyFilterExpression ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetFirstRecord()", f1.GetFirstRecord(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurRecNo()", (xbInt32) V4Dbf->GetCurRecNo(), 50 ); + iRc += TestMethod( iPo, "GetNextRecord()", f1.GetNextRecord(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurRecNo()", (xbInt32) V4Dbf->GetCurRecNo(), 76 ); + iRc += TestMethod( iPo, "GetNextRecord()", f1.GetNextRecord(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurRecNo()", (xbInt32) V4Dbf->GetCurRecNo(), 102 ); + iRc += TestMethod( iPo, "GetLast()", f1.GetLastRecord(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurRecNo()", (xbInt32) V4Dbf->GetCurRecNo(), 128 ); + iRc += TestMethod( iPo, "GetPrev()", f1.GetPrevRecord(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurRecNo()", (xbInt32) V4Dbf->GetCurRecNo(), 102 ); + + + #ifdef XB_NDX_SUPPORT + f1.SetLimit( 0 ); + + // change things up a bit + iRc += TestMethod( iPo, "GetRecord()", V4Dbf->GetRecord( 32 ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "PutField()", V4Dbf->PutField( "ZFLD", "Z" ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetRecord()", V4Dbf->GetRecord( 52 ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "PutField()", V4Dbf->PutField( "ZFLD", "Z" ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetRecord()", V4Dbf->GetRecord( 76 ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "PutField()", V4Dbf->PutField( "ZFLD", "Z" ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetRecord()", V4Dbf->GetRecord( 103 ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "PutField()", V4Dbf->PutField( "ZFLD", "Z" ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "Commit()", V4Dbf->Commit(), XB_NO_ERROR ); + + iRc += TestMethod( iPo, "SetCurTag()", V4Dbf->SetCurTag( "TestFilt" ), XB_NO_ERROR ); + sMyFilterExpression = "ZFLD = 'Z'"; + iRc += TestMethod( iPo, "Set()", f1.Set( sMyFilterExpression ), XB_NO_ERROR ); + + iRc += TestMethod( iPo, "GetFirstRecord()", f1.GetFirstRecord(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurRecNo()", (xbInt32) V4Dbf->GetCurRecNo(), 52 ); + iRc += TestMethod( iPo, "GetNextRecord()", f1.GetNextRecord(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurRecNo()", (xbInt32) V4Dbf->GetCurRecNo(), 103 ); + iRc += TestMethod( iPo, "GetNextRecord()", f1.GetNextRecord(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurRecNo()", (xbInt32) V4Dbf->GetCurRecNo(), 76 ); + iRc += TestMethod( iPo, "GetLast()", f1.GetLastRecord(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurRecNo()", (xbInt32) V4Dbf->GetCurRecNo(), 32 ); + iRc += TestMethod( iPo, "GetPrev()", f1.GetPrevRecord(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurRecNo()", (xbInt32) V4Dbf->GetCurRecNo(), 76 ); + + #endif // XB_NDX_SUPPORT + + + iRc += TestMethod( iPo, "Close()", V4Dbf->Close(), XB_NO_ERROR ); + delete V4Dbf; + + if( iPo > 0 || iRc < 0 ) + fprintf( stdout, "Total Errors = %d\n", iRc * -1 ); + +#ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], iRc * -1 ); + x.WriteLogMessage( sMsg, 2 ); +#endif + + return iRc; +} diff --git a/src/tests/xb_test_funcs.cpp b/src/tests/xb_test_funcs.cpp new file mode 100755 index 0000000..07e2c17 --- /dev/null +++ b/src/tests/xb_test_funcs.cpp @@ -0,0 +1,288 @@ +/* xb_test_funcs.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014,2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the xb functions +// usage: xb_test_funcs QUITE|NORMAL|VERBOSE + +#include "xbase.h" +using namespace xb; + +#include "tstfuncs.cpp" + + +/**************************************************************************/ + +int main( int argCnt, char **av ) +{ + xbInt16 iRc = 0; + xbInt16 rc2 = 0; + xbInt16 po = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + po = 0; + else if( av[1][0] == 'V' ) + po = 2; + } + + xbSchema MyRecord[] = + { + { "NUM1", XB_NUMERIC_FLD, 9, 2 }, + { "DATE1", XB_DATE_FLD, 8, 0 }, + { "DATE2", XB_DATE_FLD, 8, 0 }, + { "",0,0,0 } + }; + + + xbXBase x; + xbDbf * MyFile; + xbDate d; + + xbString sResult; + xbDate dtResult; + xbDouble dResult; + xbBool bResult; + xbDate dtIn( "19890209" ); + + + #ifdef XB_LOGGING_SUPPORT + x.EnableMsgLogging(); + if( po ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + x.SetDataDirectory( PROJECT_DATA_DIR ); + x.EnableMsgLogging(); + InitTime(); + + if( po > 0 ){ + std::cout << "XBase Expression testing program.." << std::endl; + std::cout << "This program tests the XBase expression logic." << std::endl; + std::cout << "Default Data Directory is [" << x.GetDataDirectory().Str() << "]" << std::endl; + } + + #ifdef XB_DBF4_SUPPORT + MyFile = new xbDbf4( &x ); /* version 4 dbf file */ + #else + MyFile = new xbDbf3( &x ); /* version 3 dbf file */ + #endif + + rc2 = MyFile->CreateTable( "Functest.DBF", "ExpTest", MyRecord, XB_OVERLAY, XB_MULTI_USER ); + iRc += TestMethod( po, "CreateTable()", rc2, XB_NO_ERROR ); + iRc += TestMethod( po, "PutField()", MyFile->PutFloatField( "NUM1", 5 ), XB_NO_ERROR ); + iRc += TestMethod( po, "PutField()", MyFile->PutField( "DATE1", "19890303" ), XB_NO_ERROR ); + iRc += TestMethod( po, "PutField()", MyFile->PutField ( "DATE2", "20120708" ), XB_NO_ERROR ); + + MyFile->SetAutoLock( xbFalse ); + iRc += TestMethod( po, "AppendRecord()", MyFile->AppendRecord(), XB_NO_ERROR ); + + iRc += TestMethod( po, "ABS( -222, dResult )", x.ABS( -222, dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "ABS( -222, dResult )", -222, -222 ); + iRc += TestMethod( po, "ABS( 333, dResult )", x.ABS( 333, dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "ABS( 333, dResult )", 333, 333 ); + + iRc += TestMethod( po, "x.ALLTRIM( \" zzz \", sResult )", x.ALLTRIM( " zzz ", sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.ALLTRIM( \" zzz \", sResult )", sResult, "zzz", 3 ); + + iRc += TestMethod( po, "ASC( \"A\", dResult )", x.ASC( "A", dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "ASC( \"A\" )", dResult, (xbDouble) 65 ); + iRc += TestMethod( po, "ASC( \"B\", dResult )", x.ASC( "B", dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "ASC( \"B\" )", dResult, (xbDouble) 66 ); + iRc += TestMethod( po, "AT( \"ABC\", \"XYZABC\", 4 )", x.AT( "ABC", "XYZABC", dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "AT( \"ABC\", \"XYZABC\", 4 )", dResult, (xbDouble) 4 ); + iRc += TestMethod( po, "CDOW( dtIn, sResult )", x.CDOW( dtIn, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "CDOW( dtIn, sResult )", sResult, "Thursday", 8 ); + iRc += TestMethod( po, "CHR( 101, sResult )", x.CHR( 101, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "CHR( 101, sResult )", sResult, "e", 1 ); + + dtIn = "19870103"; + iRc += TestMethod( po, "CMONTH( dtIn, sResult )", x.CMONTH( dtIn, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "CMONTH( dtIn, sResult )", sResult, "January", 7 ); + iRc += TestMethod( po, "CTOD( \"01\\03\\87\", dtResult )", x.CTOD( "01\\03\\87", dtResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "CTOD( \"01\\03\\87\", dtResult )", dtResult.Str(), "19870103", 8 ); + iRc += TestMethod( po, "DATE( dtResult )", x.DATE( dtResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "DATE( dtResult )", dtResult.Str(), d.Str(), 8 ); + iRc += TestMethod( po, "DAY(\"19870103\", dResult )", x.DAY( "19870103", dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "DAY(\"19870103\", dResult )", dResult, (xbDouble) 3 ); + + iRc += TestMethod( po, "DEL( MyFile, sResult )", x.DEL( MyFile, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "DEL( MyFile, sResult )", sResult, " ", 1 ); + + iRc += TestMethod( po, "DELETED( MyFile, bResult )", x.DELETED( MyFile, bResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "DELETED( MyFile, bResult )", (xbInt32) bResult, xbFalse ); + + iRc += TestMethod( po, "DeleteRecord()", MyFile->DeleteRecord(), XB_NO_ERROR ); + + iRc += TestMethod( po, "DEL( MyFile, sResult )", x.DEL( MyFile, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "DEL( MyFile, sResult )", sResult, "*", 1 ); + iRc += TestMethod( po, "DELETED( MyFile, bResult )", x.DELETED( MyFile, bResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "DELETED( MyFile, bResult )", (xbInt32) bResult, xbTrue ); + + iRc += TestMethod( po, "UndeleteRecord()", MyFile->UndeleteRecord(), XB_NO_ERROR ); + + iRc += TestMethod( po, "DESCEND(\"ABCDE\", sResult )", x.DESCEND( "ABCDE", sResult ), XB_NO_ERROR ); + + char sDescendResult[6]; // = "¾½¼»º"; + sDescendResult[0] = (char) 0xBE; + sDescendResult[1] = (char) 0xBD; + sDescendResult[2] = (char) 0xBC; + sDescendResult[3] = (char) 0xBB; + sDescendResult[4] = (char) 0xBA; + sDescendResult[5] = (char) 0x00; + iRc += TestMethod( po, "DESCEND(\"ABCDE\", sResult )", sResult, sDescendResult, 5 ); + + iRc += TestMethod( po, "DESCEND( 12345, dResult )", x.DESCEND( 12345, dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "DESCEND( 12345, dResult )", dResult, (xbDouble) -12345 ); + dtIn = "19890303"; + iRc += TestMethod( po, "DESCEND( dtIn, dtResult )", x.DESCEND( dtIn, dtResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "DESCEND( dtIn, dtResult )", dtResult.Str(), "29101031", 8 ); + dtIn = "20120708"; + iRc += TestMethod( po, "DESCEND( dtIn, dtResult )", x.DESCEND( dtIn, dtResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "DESCEND( dtIn, dtResult )", dtResult.Str(), "28870625" , 8 ); + + dtIn = "20171014"; + iRc += TestMethod( po, "DOW( dtIn, dResult )", x.DOW( dtIn, dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "DOW(\"20171015\", dResult )", dResult, (xbDouble) 0 ); + dtIn++; + iRc += TestMethod( po, "DOW( dtIn, dResult )", x.DOW( dtIn, dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "DOW(\"20171016\", dResult )", dResult, (xbDouble) 1 ); + dtIn++; + iRc += TestMethod( po, "DOW( dtIn, dResult )", x.DOW( dtIn, dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "DOW(\"20171021\", dResult )", dResult, (xbDouble) 2 ); + + dtIn = "20000101"; + iRc += TestMethod( po, "DTOC( dtIn, sResult )", x.DTOC( dtIn, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "DTOC( dtIn, sResult )", sResult, "01/01/00", 8 ); + iRc += TestMethod( po, "DTOS( dtIn, sResult )", x.DTOS( dtIn, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "DTOS( dtIn, sResult )", sResult, "20000101", 8 ); + iRc += TestMethod( po, "EXP( 1, dResult )", x.EXP( 1, dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "EXP( 1, dResult )", dResult, 2.71828, .001 ); + iRc += TestMethod( po, "x.INT( 621.5, dResult )", x.INT( 621.5, dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.INT( 621.5, dResult )", dResult, (xbDouble) 621 ); + iRc += TestMethod( po, "x.ISALPHA( \"1\", bResult )", x.ISALPHA( "1", bResult ), 0 ); + iRc += TestMethod( po, "x.ISALPHA( \"1\", bResult )", (xbInt32) bResult, xbFalse ); + iRc += TestMethod( po, "x.ISALPHA( \"A\", bResult )", x.ISALPHA( "A", bResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.ISALPHA( \"A\", bResult )", (xbInt32) bResult, xbTrue ); + iRc += TestMethod( po, "x.ISLOWER( \"A\", bResult )", x.ISLOWER( "A", bResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.ISLOWER( \"A\", bResult )", bResult, xbFalse ); + iRc += TestMethod( po, "x.ISLOWER( \"a\", bResult )", x.ISLOWER( "a", bResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.ISLOWER( \"a\", bResult )", bResult, xbTrue ); + iRc += TestMethod( po, "x.ISUPPER( \"A\", bResult )", x.ISUPPER( "A", bResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.ISUPPER( \"A\", bResult )", bResult, xbTrue ); + iRc += TestMethod( po, "x.ISUPPER( \"a\", bResult )", x.ISUPPER( "a", bResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.ISUPPER( \"a\", bResult )", bResult, xbFalse ); + iRc += TestMethod( po, "x.LEFT( \"STRING\", 3, sResult )", x.LEFT( "STRING", 3, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.LEFT( \"STRING\", 3, sResult )", sResult, "STR", 3 ); + iRc += TestMethod( po, "x.LEN( \"AAAAA\", dResult )", x.LEN( "AAAAA", dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.LEN( \"AAAAA\", dResult )", dResult, (xbDouble) 5 ); + iRc += TestMethod( po, "x.LOG( 2, dResult )", x.LOG( 2, dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.LOG( 2, dResult )", dResult, (xbDouble) 0.69314700, .0001 ); + iRc += TestMethod( po, "x.LOWER( \"AAAA\", sResult )", x.LOWER( "AAAA", sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.LOWER( \"AAAA\", sResult )", sResult, "aaaa", 4 ); + iRc += TestMethod( po, "x.LTRIM( \" xxxxxx\" )", x.LTRIM( " xxxxxx", sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.LTRIM( \" xxxxxx\" )", sResult, "xxxxxx", 6 ); + iRc += TestMethod( po, "x.MAX( 10, 27, dResult )", x.MAX( 10, 27, dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.MAX( 10, 27, dResult )", dResult, (xbDouble) 27 ); + iRc += TestMethod( po, "x.MIN( 10, 5, dResult )", x.MIN( 10, 5, dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.MIN( 10, 5, dResult )", dResult, (xbDouble) 5 ); + iRc += TestMethod( po, "x.MONTH( dtIn, dResult )", x.MONTH( dtIn, dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.MONTH( dtIn, dResult )", dResult, (xbDouble) 1 ); + iRc += TestMethod( po, "x.RECCOUNT( MyFile, dResult)", x.RECNO( MyFile, dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.RECCOUNT( MyFile, dResult)", dResult, (xbDouble) 1 ); + iRc += TestMethod( po, "x.RECNO( MyFile, dResult)", x.RECNO( MyFile, dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.RECNO( MyFile, dResult)", dResult, (xbDouble) 1 ); + iRc += TestMethod( po, "x.REPLICATE( \"abc\", 3, sResult )", x.REPLICATE( "abc", 3, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.REPLICATE( \"abc\", 3, sResult )", sResult, "abcabcabc", 9 ); + iRc += TestMethod( po, "x.RIGHT( \"STRING\", 3, sResult )", x.RIGHT( "STRING", 3, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.RIGHT( \"STRING\", 3, sResult )", sResult, "ING", 3 ); + iRc += TestMethod( po, "x.RIGHT( \"STRING\", 3, sResult )", x.RIGHT( "STRING", 5, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.RIGHT( \"STRING\", 3, sResult )", sResult, "TRING", 5 ); + iRc += TestMethod( po, "x.RIGHT( \"STRING\", 3, sResult )", x.RIGHT( "STRING", 6, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.RIGHT( \"STRING\", 3, sResult )", sResult, "STRING", 6 ); + iRc += TestMethod( po, "x.RIGHT( \"STRING\", 3, sResult )", x.RIGHT( "STRING", 7, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.RIGHT( \"STRING\", 3, sResult )", sResult, "STRING", 6 ); + iRc += TestMethod( po, "x.RTRIM( \"zzz \", sResult )", x.RTRIM( "zzz ", sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.RTRIM( \"zzz \", sResult )", sResult, "zzz", 3 ); + iRc += TestMethod( po, "x.TRIM( \"aaa \", sResult )", x.TRIM( "aaa ", sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.TRIM( \"aaa \", sResult )", sResult, "aaa", 3 ); + iRc += TestMethod( po, "x.SPACE( 3, sResult )", x.SPACE( 3, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.SPACE( 3, sResult )", sResult, " ", 3 ); + iRc += TestMethod( po, "x.SQRT( 9, dResult )", x.SQRT( 9, dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.SQRT( 9, dResult )", dResult, (xbDouble) 3 ); + iRc += TestMethod( po, "x.STOD( \"20000101\", dtResult )", x.STOD( "20000101", dtResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.STOD( \"20000101\", dtResult )",dtResult.Str(), "20000101", 8 ); + + xbString sPadChar = " "; + iRc += TestMethod( po, "x.STR( 2001, 4, 0, sPadChar, sResult )", x.STR( 2001, 4, 0, sPadChar, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.STR( 2001, 4, 0, sPadChar, sResult )", sResult, "2001", 4 ); + iRc += TestMethod( po, "x.STR( 2002, 3, 0, sPadChar, sResult )", x.STR( 2002, 3, 0, sPadChar, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.STR( 2002, 3, 0, sPadChar, sResult )", sResult, "***", 3 ); + iRc += TestMethod( po, "x.STR( 203.2, 6, 2, sPadChar, sResult )", x.STR( 203.2, 6, 2, sPadChar, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.STR( 203.2, 6, 2, sPadChar, sResult )", sResult, "203.20", 6 ); + iRc += TestMethod( po, "x.STR( 204.11, 8, 2, sPadChar, sResult )", x.STR( 204.11, 8, 2, sPadChar, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.STR( 204.11, 8, 2, sPadChar, sResult )", sResult, " 204.11", 8 ); + iRc += TestMethod( po, "x.STR( -205.45, 8, 2, sPadChar, sResult )", x.STR( -205.45, 8, 2, sPadChar, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.STR( -205.45, 8, 2, sPadChar, sResult )", sResult, " -205.45", 8 ); + iRc += TestMethod( po, "x.STR( -306.45, 8, 2, sPadChar, sResult )", x.STR( -306.45, 8, 2, sPadChar, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.STR( -306.45, 8, 2, sPadChar, sResult )", sResult, " -306.45", 8 ); + iRc += TestMethod( po, "x.STR( 6.56, 5, 0, sResult )", x.STR( 6.56, 5, 0, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.STR( 6.56, 5, 0, sResult )", sResult, " 7", 5 ); + iRc += TestMethod( po, "x.STR( 7.77, 5, sResult )", x.STR( 7.77, 5, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.STR( 7.77, 5, sResult )", sResult, " 8", 5 ); + iRc += TestMethod( po, "x.STR( 8, sResult )", x.STR( 8, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.STR( 8, sResult )", sResult, " 8", 10 ); + + sPadChar = "0"; + iRc += TestMethod( po, "x.STR( -5.2, 10, 2, sPadChar, sResult )", x.STR( -5.2, 10, 2, sPadChar, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.STR( -5.2, 10, 2, sPadChar, sResult )", sResult, "00000-5.20", 10 ); + iRc += TestMethod( po, "x.STRZERO( 8, 8, 0, sResult )", x.STRZERO( 8, 8, 0, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.STRZERO( 8, 8, 0, sResult )", sResult, "00000008", 8 ); + iRc += TestMethod( po, "x.STRZERO( -8, 8, 0, sResult )", x.STRZERO( -8, 8, 0, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.STRZERO( -8, 8, 0, sResult )", sResult, "-0000008", 8 ); + iRc += TestMethod( po, "x.STRZERO( -205.45, 10, 3 )", x.STRZERO( -205.45, 10, 3, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.STRZERO( -205.45, 10, 3 )", sResult, "-00205.450", 10 ); + iRc += TestMethod( po, "x.STRZERO( -205.45, 3, 1 )", x.STRZERO( -205.45, 3, 1, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.STRZERO( -205.45, 3, 1 )", sResult, "***", 3 ); + iRc += TestMethod( po, "x.SUBSTR( \"TESTSTRING\", 5, 2, sResult )", x.SUBSTR( "TESTSTRING", 5, 2, sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.SUBSTR( \"TESTSTRING\", 5, 2, sResult )", sResult, "ST", 2 ); + iRc += TestMethod( po, "x.UPPER( \"abababa\", sResult )", x.UPPER( "abababa", sResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.UPPER( \"abababa\", sResult )", sResult, "ABABABA", 7 ); + iRc += TestMethod( po, "x.VAL( \"65\", dResult )", x.VAL( "65", dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.VAL( \"65\", dResult )", dResult, (xbDouble) 65 ); + iRc += TestMethod( po, "x.YEAR( dtIn, dResult )", x.YEAR( dtIn, dResult ), XB_NO_ERROR ); + iRc += TestMethod( po, "x.YEAR( dtIn, dResult )", dResult, (xbDouble) 2000 ); + + + iRc += TestMethod( po, "Close()", MyFile->Close(), XB_NO_ERROR ); + + + delete MyFile; + if( po > 0 || iRc < 0 ) + fprintf( stdout, "Total Errors = %d\n", iRc * -1 ); + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], iRc * -1 ); + x.WriteLogMessage( sMsg ); + #endif + + return iRc; +} diff --git a/src/tests/xb_test_linklist.cpp b/src/tests/xb_test_linklist.cpp new file mode 100755 index 0000000..dc253af --- /dev/null +++ b/src/tests/xb_test_linklist.cpp @@ -0,0 +1,340 @@ +/* xb_test_linklist.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014,2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the class xblnklst and xblnknod +// usage: xb_test_linklist QUITE|NORMAL|VERBOSE + + +#include "xbase.h" + +using namespace xb; + +#include "tstfuncs.cpp" + + + +int main( int argCnt, char **av ) +{ + int rc = 0; + + int po = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + po = 0; + else if( av[1][0] == 'V' ) + po = 2; + } + + xbXBase x; +#ifdef XB_LOGGING_SUPPORT + x.EnableMsgLogging(); + if( po ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); +#endif + InitTime(); + + xbLinkList<xbString> ll; + ll.InsertAtFront( "A" ); + ll.InsertAtFront( "B" ); + ll.InsertAtFront( "C" ); + ll.InsertAtFront( "D" ); + ll.InsertAtFront( "E" ); + ll.InsertAtFront( "F" ); + ll.InsertAtFront( "G" ); + ll.InsertAtFront( "H" ); + ll.InsertAtFront( "I" ); + ll.InsertAtFront( "J" ); + ll.InsertAtFront( "K" ); + ll.InsertAtFront( "L" ); + ll.InsertAtFront( "M" ); + ll.InsertAtFront( "N" ); + ll.InsertAtFront( "O" ); + + xbLinkListNode<xbString> * llN = ll.GetHeadNode(); + xbString s; + xbString s2; + xbUInt32 ulCnt = ll.GetNodeCnt(); + for( xbUInt32 i = 0; i < ulCnt; i++ ){ + s2 = llN->GetKey(); + s.Sprintf( "%s%s", s.Str(), s2.Str() ); + llN = llN->GetNextNode(); + } + rc += TestMethod( po, "InsertAtFront()", s, "ONMLKJIHGFEDCBA", 15 ); + + s = ""; + llN = ll.GetHeadNode(); + while( llN ){ + s2 = llN->GetKey(); + s.Sprintf( "%s%s", s.Str(), s2.Str() ); + llN = llN->GetNextNode(); + } + rc += TestMethod( po, "GetNextNode()", s, "ONMLKJIHGFEDCBA", 15 ); + + s = ""; + llN = ll.GetEndNode(); + while( llN ){ + s2 = llN->GetKey(); + s.Sprintf( "%s%s", s.Str(), s2.Str() ); + llN = llN->GetPrevNode(); + } + rc += TestMethod( po, "GetNextNode()", s, "ABCDEFGHIJKLMNO", 15 ); + + + ll.RemoveFromFront( s ); + rc += TestMethod( po, "RemoveFromFront()", s, "O", 1 ); + + llN = ll.GetHeadNode(); + ulCnt = ll.GetNodeCnt(); + rc += TestMethod( po, "RemoveFromFront()", (xbInt32) ulCnt, 14 ); + + s = ""; + for( xbUInt32 i = 0; i < ulCnt; i++ ){ + s2 = llN->GetKey(); + s.Sprintf( "%s%s", s.Str(), s2.Str() ); + llN = llN->GetNextNode(); + } + rc += TestMethod( po, "RemoveFromFront()", s, "NMLKJIHGFEDCBA", 14 ); + + + s = ""; + llN = ll.GetHeadNode(); + while( llN ){ + s2 = llN->GetKey(); + s.Sprintf( "%s%s", s.Str(), s2.Str() ); + llN = llN->GetNextNode(); + } + rc += TestMethod( po, "RemoveFromFront()", s, "NMLKJIHGFEDCBA", 14 ); + + + s = ""; + llN = ll.GetEndNode(); + while( llN ){ + s2 = llN->GetKey(); + s.Sprintf( "%s%s", s.Str(), s2.Str() ); + llN = llN->GetPrevNode(); + } + rc += TestMethod( po, "RemoveFromFront()", s, "ABCDEFGHIJKLMN", 14 ); + + + ll.RemoveFromEnd( s ); + rc = TestMethod( po, "RemoveFromEnd()", s, "A", 1 ); + ulCnt = ll.GetNodeCnt(); + rc += TestMethod( po, "RemoveFromFront()", (xbInt32) ulCnt, 13 ); + + s = ""; + llN = ll.GetHeadNode(); + for( xbUInt32 i = 0; i < ulCnt; i++ ){ + s2 = llN->GetKey(); + s.Sprintf( "%s%s", s.Str(), s2.Str() ); + llN = llN->GetNextNode(); + } + rc += TestMethod( po, "RemoveFromEnd()", s, "NMLKJIHGFEDCB", 13 ); + + s = ""; + llN = ll.GetHeadNode(); + while( llN ){ + s2 = llN->GetKey(); + s.Sprintf( "%s%s", s.Str(), s2.Str() ); + llN = llN->GetNextNode(); + } + rc += TestMethod( po, "RemoveFromEnd()", s, "NMLKJIHGFEDCB", 13 ); + + s = ""; + llN = ll.GetEndNode(); + while( llN ){ + s2 = llN->GetKey(); + s.Sprintf( "%s%s", s.Str(), s2.Str() ); + llN = llN->GetPrevNode(); + } + rc += TestMethod( po, "RemoveFromEnd()", s, "BCDEFGHIJKLMN", 13 ); + + s = "J"; + ll.RemoveByVal( s ); + rc += TestMethod( po, "RemoveByVal()", s, "J", 1 ); + ulCnt = ll.GetNodeCnt(); + rc += TestMethod( po, "RemoveByVal()", (xbInt32) ulCnt, 12 ); + + llN = ll.GetHeadNode(); + s = ""; + for( xbUInt32 i = 0; i < ulCnt; i++ ){ + s2 = llN->GetKey(); + s.Sprintf( "%s%s", s.Str(), s2.Str() ); + llN = llN->GetNextNode(); + } + rc += TestMethod( po, "RemoveByVal()", s, "NMLKIHGFEDCB", 12 ); + + s = ""; + llN = ll.GetHeadNode(); + while( llN ){ + s2 = llN->GetKey(); + s.Sprintf( "%s%s", s.Str(), s2.Str() ); + llN = llN->GetNextNode(); + } + rc += TestMethod( po, "RemoveByVal()", s, "NMLKIHGFEDCB", 12 ); + + s = ""; + llN = ll.GetEndNode(); + while( llN ){ + s2 = llN->GetKey(); + s.Sprintf( "%s%s", s.Str(), s2.Str() ); + llN = llN->GetPrevNode(); + } + rc += TestMethod( po, "RemoveByVal()", s, "BCDEFGHIKLMN", 12 ); + + +// ordered link list + xbLinkListOrd<xbString> llO; + llO.SetDupKeys( 0 ); + rc += TestMethod( po, "InsertKey( J )", llO.InsertKey( "J" ), 0); + rc += TestMethod( po, "InsertKey( J )", llO.InsertKey( "J" ), XB_KEY_NOT_UNIQUE ); + rc += TestMethod( po, "InsertKey( M )", llO.InsertKey( "M" ), 0 ); + rc += TestMethod( po, "InsertKey( C )", llO.InsertKey( "C" ), 0 ); + rc += TestMethod( po, "InsertKey( F )", llO.InsertKey( "F" ), 0 ); + rc += TestMethod( po, "InsertKey( Q )", llO.InsertKey( "Q" ), 0 ); + rc += TestMethod( po, "InsertKey( A )", llO.InsertKey( "A" ), 0 ); + rc += TestMethod( po, "InsertKey( T )", llO.InsertKey( "T" ), 0 ); + + if( po > 1 ){ + std::cout << "dumping node chain from beginning to end\n"; + llN = llO.GetHeadNode(); + while( llN ){ + s2 = llN->GetKey(); + std::cout << "node = " << s2.Str() << "\n"; + llN = llN->GetNextNode(); + } + + std::cout << "dumping node chain from beginning to beginning\n"; + llN = llO.GetHeadNode(); + while( llN ){ + s2 = llN->GetKey(); + std::cout << "node = " << s2.Str() << "\n"; + llN = llN->GetPrevNode(); + } + + std::cout << "dumping node chain from end to end\n"; + llN = llO.GetEndNode(); + while( llN ){ + s2 = llN->GetKey(); + std::cout << "node = " << s2.Str() << "\n"; + llN = llN->GetNextNode(); + } + + std::cout << "dumping node chain from end to beginning\n"; + llN = llO.GetEndNode(); + while( llN ){ + s2 = llN->GetKey(); + std::cout << "node = " << s2.Str() << "\n"; + llN = llN->GetPrevNode(); + } + + + } + + // xbLinkListNode<xbString> * psN; + s2 = "A"; + rc += TestMethod( po, "KeyExists('A')", llO.KeyExists( s2 ), xbTrue ); + rc += TestMethod( po, "RemoveKey('A')", llO.RemoveKey( s2 ), 0 ); + s2 = "J"; + rc += TestMethod( po, "RemoveKey('J')", llO.RemoveKey( s2 ), 0 ); + s2 = "T"; + rc += TestMethod( po, "RemoveKey('T')", llO.RemoveKey( s2 ), 0 ); + rc += TestMethod( po, "RemoveKey('T')", llO.RemoveKey( s2 ), XB_NOT_FOUND ); + rc += TestMethod( po, "KeyExists('T')", llO.KeyExists( s2 ), xbFalse ); + + + + xbLinkListOrd<xbUInt32> lloi; + lloi.SetDupKeys( 0 ); + xbUInt32 i = 3; + + rc += TestMethod( po, "InsertKey( 1 )", lloi.InsertKey( i ), 0 ); + rc += TestMethod( po, "RemoveKey( 1 )", lloi.RemoveKey( i ), 0 ); + rc += TestMethod( po, "RemoveKey( 1 )", lloi.RemoveKey( i ), XB_NOT_FOUND ); + + + if( po > 1 ){ + std::cout << "dumping node chains after delete\n"; + std::cout << "dumping node chain from beginning to end\n"; + llN = llO.GetHeadNode(); + while( llN ){ + s2 = llN->GetKey(); + std::cout << "node = " << s2.Str() << "\n"; + llN = llN->GetNextNode(); + } + + std::cout << "dumping node chain from beginning to beginning\n"; + llN = llO.GetHeadNode(); + while( llN ){ + s2 = llN->GetKey(); + std::cout << "node = " << s2.Str() << "\n"; + llN = llN->GetPrevNode(); + } + + std::cout << "dumping node chain from end to end\n"; + llN = llO.GetEndNode(); + while( llN ){ + s2 = llN->GetKey(); + std::cout << "node = " << s2.Str() << "\n"; + llN = llN->GetNextNode(); + } + + std::cout << "dumping node chain from end to beginning\n"; + llN = llO.GetEndNode(); + while( llN ){ + s2 = llN->GetKey(); + std::cout << "node = " << s2.Str() << "\n"; + llN = llN->GetPrevNode(); + } + } + + + xbLinkListOrd<xbUInt32> ll32; + // xbLinkListNode<xbUInt32> * ll32n; + +// for( xbUInt32 ul = 0; ul < 1; ul++ ) +// ll32.InsertKey( ul, ul ); + + + xbUInt32 ul3 = 0; +// ll32.InsertKey( 1, "1" ); + + ll32.InsertKey( ul3, ul3 ); + + ll.Clear(); + + + +#ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], rc * -1 ); + x.WriteLogMessage( sMsg ); +#endif + + if( po > 0 || rc < 0 ) + fprintf( stdout, "Total Errors = %d\n", rc * -1 ); + + return rc; +} + + + + diff --git a/src/tests/xb_test_lock.cpp b/src/tests/xb_test_lock.cpp new file mode 100755 index 0000000..7e9865b --- /dev/null +++ b/src/tests/xb_test_lock.cpp @@ -0,0 +1,874 @@ +/* xb_test_lock.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014,2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the locking functions of xbase +// usage: xb_test_lock QUITE|NORMAL|VERBOSE + + +#include "xbase.h" + +using namespace xb; + +#include "tstfuncs.cpp" + +/****************************************************************/ +int main( int argCnt, char **av ) +{ + xbInt16 iRc = 0; + xbInt16 iRc2; + xbInt16 po = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + xbInt16 iErrorStop = 0; + xbString sLockFile = "locktest.txt"; + xbString sLockCmd; + xbString sResult; + + xbXBase x; + xbDbf * MyFile; + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + po = 0; + else if( av[1][0] == 'V' ) + po = 2; + } + + xbSchema MyRecord[] = + { + { "LOCKTEST", XB_CHAR_FLD, 5, 0 }, + #ifdef XB_MEMO_SUPPORT + { "MEMOTEST", XB_MEMO_FLD, 10, 0 }, + #endif + { "",0,0,0 } + }; + + + #ifdef XB_LOGGING_SUPPORT + x.EnableMsgLogging(); + if( po > 0 ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + x.SetDataDirectory( PROJECT_DATA_DIR ); + x.EnableMsgLogging(); + InitTime(); + #ifdef XB_DBF4_SUPPORT + MyFile = new xbDbf4( &x ); /* version 4 dbf file */ + #else + MyFile = new xbDbf3( &x ); /* version 3 dbf file */ + #endif + + iRc2 = MyFile->CreateTable( "LockTest.DBF", "LockTest", MyRecord, XB_OVERLAY, XB_MULTI_USER ); + iRc += TestMethod( po, "CreateTable()", iRc2, XB_NO_ERROR ); + iRc += TestMethod( po, "PutField()", MyFile->PutField( "LOCKTEST", "TEST" ), XB_NO_ERROR ); + iRc += TestMethod( po, "AppendRecord()", MyFile->AppendRecord(), XB_NO_ERROR ); + iRc += TestMethod( po, "Close()", MyFile->Close(), XB_NO_ERROR ); + MyFile->Close(); + + //unlink( sLockFile ); + remove( sLockFile ); + + #if defined (HAVE_FORK_F) + pid_t pid; + if(( pid = fork()) < 0 ){ + std::cout << "fork error\n"; + exit(1); + } + + if( pid == 0 ){ + // child task + xbDbf * MyFileChld; + xbInt16 iRcChld = 0; + xbBool bTblOpenChld = xbFalse; + xbInt32 iChildLoop = 0; + xbBool bDone = xbFalse; + xbString sLastLockCmd; + + #ifdef XB_DBF4_SUPPORT + MyFileChld = new xbDbf4( &x ); /* version 4 dbf file */ + #else + MyFileChld = new xbDbf3( &x ); /* version 3 dbf file */ + #endif + + x.xbSleep( 250 ); + + while( !bDone ){ + iRc2 = GetCmd( x, sLockFile, sLockCmd, 'C', po ); + + if( sLockCmd == sLastLockCmd ) + iChildLoop++; + else + sLastLockCmd = sLockCmd; + + #ifdef XB_LOGGING_SUPPORT + if( sLockCmd != "OK" && sLockCmd != "FAIL" ){ + sMsg.Sprintf( "Program [%s] Child task retrieved command=[%s] RC=[%d]", av[0], sLockCmd.Str(), iRc2 ); + x.WriteLogMessage( sMsg ); + } + #endif + + if( iRc2 == 0 ){ + + if( sLockCmd == "OK" || sLockCmd == "FAIL" ) + x.xbSleep( 250 ); + + else if( sLockCmd == "EXIT" ){ + bDone = xbTrue; + + } else if( sLockCmd == "START" && bTblOpenChld ){ + // came back before the parent task could process the result + x.xbSleep( 250 ); + + } else { + + if( sLockCmd == "START" ){ + // begin the process + iRcChld = MyFileChld->Open( "LockTest.DBF" ); + if( iRcChld != XB_NO_ERROR ){ + sResult = "FAIL"; + } else { + sResult = "OK"; + bTblOpenChld = xbTrue; + } + + } else if( sLockCmd == "TL" ){ + // table lock + if(( iRcChld = MyFileChld->LockTable( XB_LOCK )) != XB_NO_ERROR ) + sResult = "FAIL"; + else + sResult = "OK"; + + } else if( sLockCmd == "TU" ){ + // table unlock + if(( iRcChld = MyFileChld->LockTable( XB_UNLOCK )) != XB_NO_ERROR ) + sResult = "FAIL"; + else + sResult = "OK"; + + } else if( sLockCmd == "RL" ){ + // record lock + if(( iRcChld = MyFileChld->LockRecord( XB_LOCK, 1 )) != XB_NO_ERROR ) + sResult = "FAIL"; + else + sResult = "OK"; + + } else if( sLockCmd == "RU" ){ + // record unlock + if(( iRcChld = MyFileChld->LockRecord( XB_UNLOCK, 1 )) != XB_NO_ERROR ) + sResult = "FAIL"; + else + sResult = "OK"; + + } else if( sLockCmd == "ML" ){ + // memo lock + #ifdef XB_MEMO_SUPPORT + if(( iRcChld = MyFileChld->LockMemo( XB_LOCK )) != XB_NO_ERROR ) + sResult = "FAIL"; + else + sResult = "OK"; + #else + sLockCmd = "OK"; + #endif + + } else if( sLockCmd == "MU" ){ + // memo unlock + #ifdef XB_MEMO_SUPPORT + if(( iRcChld = MyFileChld->LockMemo( XB_UNLOCK )) != XB_NO_ERROR ) + sResult = "FAIL"; + else + sResult = "OK"; + #else + sLockCmd = "OK"; + #endif + } + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Child task [%s] Result [%s] RC = [%d]", av[0], sLockCmd.Str(), sResult.Str(), iRcChld ); + x.WriteLogMessage( sMsg ); + #endif + SetCmd( x, sLockFile, sResult, 'C', po ); + if( sResult == "FAIL" ){ + bDone = xbTrue; + MyFileChld->Close(); + delete MyFileChld; + } + } + + } else { + iRc = iRc2; + bDone = xbTrue; + } + //std::cout << "clc [" << iChildLoop++ << "][" << bDone << "][" << sLockCmd.Str() << "]\n"; + x.xbSleep( 250 ); + if( iChildLoop > 15 ) + bDone = xbTrue; + } + MyFileChld->Close(); + delete MyFile; + delete MyFileChld; + + if( po > 0 ) + std::cout << "Exiting child\n"; + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Child task terminating", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + + } else { + + // parent logic + xbInt16 iLoopCtr = 0; + + try{ + + // start + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task issuing START command", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + sLockCmd = "START"; + SetCmd( x, sLockFile, sLockCmd, 'P', po ); + sResult = ""; + + GetCmd( x, sLockFile, sResult, 'P', po ); + while( sResult != "OK" && sResult != "FAIL" && iLoopCtr < 30 ){ + GetCmd( x, sLockFile, sResult, 'P', po ); + x.xbSleep( 250 ); + iLoopCtr++; + } + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task retrieved result [%s]", av[0], sResult.Str() ); + x.WriteLogMessage( sMsg ); + #endif + + if( sResult != "OK" ){ + iErrorStop = 10; + iRc2 = -1; + throw iRc2; + } + + // table lock + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task issuing TL command", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + sLockCmd = "TL"; + SetCmd( x, sLockFile, sLockCmd, 'P', po ); + sResult = ""; + + GetCmd( x, sLockFile, sResult, 'P', po ); + while( sResult != "OK" && sResult != "FAIL" && iLoopCtr < 30 ){ + GetCmd( x, sLockFile, sResult, 'P', po ); + x.xbSleep( 250 ); + iLoopCtr++; + } + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task retrieved result [%s]", av[0], sResult.Str() ); + x.WriteLogMessage( sMsg ); + #endif + + if( sResult != "OK" ){ + iErrorStop = 20; + iRc2 = -1; + throw iRc2; + } + + // attempt to lock table, should fail + if(( iRc2 = MyFile->Open( "LockTest.DBF" )) != XB_NO_ERROR ){ + iErrorStop = 30; + throw iRc2; + } + + if(( iRc2 = MyFile->LockTable( XB_LOCK )) == XB_NO_ERROR ){ + iErrorStop = 40; + throw iRc2; + } + + if( po > 0 ) + std::cout << "[PASS] LockTable Test 1\n"; + + // table unlock + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task issuing TU command", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + sLockCmd = "TU"; + SetCmd( x, sLockFile, sLockCmd, 'P', po ); + sResult = ""; + + GetCmd( x, sLockFile, sResult, 'P', po ); + while( sResult != "OK" && sResult != "FAIL" && iLoopCtr < 30 ){ + GetCmd( x, sLockFile, sResult, 'P', po ); + x.xbSleep( 250 ); + iLoopCtr++; + } + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task retrieved result [%s]", av[0], sResult.Str() ); + x.WriteLogMessage( sMsg ); + #endif + + if( sResult != "OK" ){ + iErrorStop = 50; + iRc2 = -1; + throw iRc2; + } + + if(( iRc2 = MyFile->LockTable( XB_LOCK )) != XB_NO_ERROR ){ + iErrorStop = 60; + throw iRc2; + } + if( po > 0 ) + std::cout << "[PASS] LockTable Test 2\n"; + + if(( iRc2 = MyFile->LockTable( XB_UNLOCK )) != XB_NO_ERROR ){ + iErrorStop = 70; + throw iRc2; + } + + /* record lock */ + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task issuing RL command", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + sLockCmd = "RL"; + SetCmd( x, sLockFile, sLockCmd, 'P', po ); + sResult = ""; + + GetCmd( x, sLockFile, sResult, 'P', po ); + while( sResult != "OK" && sResult != "FAIL" && iLoopCtr < 30 ){ + GetCmd( x, sLockFile, sResult, 'P', po ); + x.xbSleep( 250 ); + iLoopCtr++; + } + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task retrieved result [%s]", av[0], sResult.Str() ); + x.WriteLogMessage( sMsg ); + #endif + + if( sResult != "OK" ){ + iErrorStop = 80; + iRc2 = -1; + throw iRc2; + } + + if(( iRc2 = MyFile->LockRecord( XB_LOCK, 1 )) == XB_NO_ERROR ){ + iErrorStop = 90; + throw iRc2; + } + if( po > 0 ) + std::cout << "[PASS] LockRecord Test 1\n"; + + /* record unlock */ + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task issuing RU command", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + sLockCmd = "RU"; + SetCmd( x, sLockFile, sLockCmd, 'P', po ); + sResult = ""; + + GetCmd( x, sLockFile, sResult, 'P', po ); + while( sResult != "OK" && sResult != "FAIL" && iLoopCtr < 30 ){ + GetCmd( x, sLockFile, sResult, 'P', po ); + x.xbSleep( 250 ); + iLoopCtr++; + } + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task retrieved result [%s]", av[0], sResult.Str() ); + x.WriteLogMessage( sMsg ); + #endif + + if( sResult != "OK" ){ + iErrorStop = 100; + iRc2 = -1; + throw iRc2; + } + + if(( iRc2 = MyFile->LockRecord( XB_LOCK, 1 )) != XB_NO_ERROR ){ + iErrorStop = 110; + throw iRc2; + } + + std::cout << "[PASS] LockRecord Test 2\n"; + if(( iRc2 = MyFile->LockRecord( XB_UNLOCK, 1 )) != XB_NO_ERROR ){ + iErrorStop = 120; + throw iRc2; + } + + + /* memo lock */ + #ifdef XB_MEMO_SUPPORT + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task issuing ML command", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + sLockCmd = "ML"; + SetCmd( x, sLockFile, sLockCmd, 'P', po ); + sResult = ""; + + GetCmd( x, sLockFile, sResult, 'P', po ); + while( sResult != "OK" && sResult != "FAIL" && iLoopCtr < 30 ){ + GetCmd( x, sLockFile, sResult, 'P', po ); + x.xbSleep( 250 ); + iLoopCtr++; + } + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task retrieved result [%s]", av[0], sResult.Str() ); + x.WriteLogMessage( sMsg ); + #endif + + if( sResult != "OK" ){ + iErrorStop = 130; + iRc2 = -1; + throw iRc2; + } + + if(( iRc2 = MyFile->LockMemo( XB_LOCK )) == XB_NO_ERROR ){ + iErrorStop = 140; + throw iRc2; + } + if( po > 0 ) + std::cout << "[PASS] LockMemo Test 1\n"; + + /* memo unlock */ + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task issuing MU command", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + sLockCmd = "MU"; + SetCmd( x, sLockFile, sLockCmd, 'P', po ); + sResult = ""; + + GetCmd( x, sLockFile, sResult, 'P', po ); + while( sResult != "OK" && sResult != "FAIL" && iLoopCtr < 30 ){ + GetCmd( x, sLockFile, sResult, 'P', po ); + x.xbSleep( 250 ); + iLoopCtr++; + } + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task retrieved result [%s]", av[0], sResult.Str() ); + x.WriteLogMessage( sMsg ); + #endif + + if( sResult != "OK" ){ + iErrorStop = 150; + iRc2 = -1; + throw iRc2; + } + + if(( iRc2 = MyFile->LockMemo( XB_LOCK )) != XB_NO_ERROR ){ + iErrorStop = 160; + throw iRc2; + } + + std::cout << "[PASS] LockMemo Test 2\n"; + if(( iRc2 = MyFile->LockMemo( XB_UNLOCK )) != XB_NO_ERROR ){ + iErrorStop = 170; + throw iRc2; + } + #endif + + // exit + sLockCmd = "EXIT"; + SetCmd( x, sLockFile, sLockCmd, 'P', po ); + + } catch (xbInt16 iRc3 ){ + iRc = iRc3; + if( po > 0 ) + std::cout << "Parent lock task exiting on failure [" << sLockCmd.Str() << "][" << iErrorStop << "]\n"; + + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task terminating with errors [%s][%d][%d][%d]...", av[0], sLockCmd.Str(), iErrorStop, iLoopCtr, iRc3 ); + x.WriteLogMessage( sMsg ); + #endif + + } + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task terminating", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + if( po > 0 ) + std::cout << "Exiting parent\n"; + + sLockCmd = "EXIT"; + SetCmd( x, sLockFile, sLockCmd, 'P', po ); + MyFile->Close(); + delete MyFile; + } + #elif defined (HAVE_CREATEPROCESSW_F) + + STARTUPINFO si; + PROCESS_INFORMATION pi; + ZeroMemory( &si, sizeof( si )); + si.cb = sizeof( si ); + ZeroMemory( &pi, sizeof( pi )); + + xbString strCmdLine = "xb_test_lock2"; + if( argCnt > 1 ){ + strCmdLine += " "; + strCmdLine += av[1]; + } + + char sCmdLineBuf[25]; + memset( sCmdLineBuf, 0x00, 25 ); + for( xbUInt32 i = 0; i < strCmdLine.Len(); i++ ) + sCmdLineBuf[i] = strCmdLine[i+1]; + + if( !CreateProcess( NULL, sCmdLineBuf, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi )){ + sMsg.Sprintf( "Program [%s] error in CreateProcess call. Processing aborted" ); + #ifdef XB_LOGGING_SUPPORT + x.WriteLogMessage( sMsg ); + #endif + std::cout << sMsg.Str() << "\n"; + iRc -=1; + } else { + + xbInt16 iLoopCtr = 0; + + try{ + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task issuing START command", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + + sLockCmd = "START"; + SetCmd( x, sLockFile, sLockCmd, 'P', po ); + sResult = ""; + + GetCmd( x, sLockFile, sResult, 'P', po ); + while( sResult != "OK" && sResult != "FAIL" && iLoopCtr < 10 ){ + GetCmd( x, sLockFile, sResult, 'P', po ); + x.xbSleep( 250 ); + iLoopCtr++; + } + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task retrieved result [%s]", av[0], sResult.Str() ); + x.WriteLogMessage( sMsg ); + #endif + + // table lock + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task issuing TL command", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + sLockCmd = "TL"; + SetCmd( x, sLockFile, sLockCmd, 'P', po ); + sResult = ""; + + GetCmd( x, sLockFile, sResult, 'P', po ); + while( sResult != "OK" && sResult != "FAIL" && iLoopCtr < 10 ){ + GetCmd( x, sLockFile, sResult, 'P', po ); + x.xbSleep( 250 ); + iLoopCtr++; + } + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task retrieved result [%s]", av[0], sResult.Str() ); + x.WriteLogMessage( sMsg ); + #endif + + if( sResult != "OK" ){ + iErrorStop = 200; + iRc2 = -1; + throw iRc2; + } + + // attempt to lock table, should fail + if(( iRc2 = MyFile->Open( "LockTest.DBF" )) != XB_NO_ERROR ){ + iErrorStop = 210; + throw iRc2; + } + + if(( iRc2 = MyFile->LockTable( XB_LOCK )) == XB_NO_ERROR ){ + iErrorStop = 220; + throw iRc2; + } + + if( po > 0 ){ + std::cout << "[PASS] LockTable Test 1\n"; + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task LockTable Test 1 Success.", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + } + + // table unlock + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task issuing TU command", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + sLockCmd = "TU"; + SetCmd( x, sLockFile, sLockCmd, 'P', po ); + sResult = ""; + + GetCmd( x, sLockFile, sResult, 'P', po ); + while( sResult != "OK" && sResult != "FAIL" && iLoopCtr < 10 ){ + GetCmd( x, sLockFile, sResult, 'P', po ); + x.xbSleep( 250 ); + iLoopCtr++; + } + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task retrieved result [%s]", av[0], sResult.Str() ); + x.WriteLogMessage( sMsg ); + #endif + + if( sResult != "OK" ){ + iErrorStop = 230; + iRc2 = -1; + throw iRc2; + } + + if(( iRc2 = MyFile->LockTable( XB_LOCK )) != XB_NO_ERROR ){ + iErrorStop = 240; + throw iRc2; + } + if( po > 0 ){ + std::cout << "[PASS] LockTable Test 2\n"; + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task LockTable Test 1 Success.", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + } + + if(( iRc2 = MyFile->LockTable( XB_UNLOCK )) != XB_NO_ERROR ){ + iErrorStop = 250; + throw iRc2; + } + + /* record lock */ + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task issuing RL command", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + sLockCmd = "RL"; + SetCmd( x, sLockFile, sLockCmd, 'P', po ); + sResult = ""; + + GetCmd( x, sLockFile, sResult, 'P', po ); + while( sResult != "OK" && sResult != "FAIL" && iLoopCtr < 10 ){ + GetCmd( x, sLockFile, sResult, 'P', po ); + x.xbSleep( 250 ); + iLoopCtr++; + } + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task retrieved result [%s]", av[0], sResult.Str() ); + x.WriteLogMessage( sMsg ); + #endif + + if( sResult != "OK" ){ + iErrorStop = 260; + iRc2 = -1; + throw iRc2; + } + + if(( iRc2 = MyFile->LockRecord( XB_LOCK, 1 )) == XB_NO_ERROR ){ + iErrorStop = 270; + throw iRc2; + } + if( po > 0 ) + std::cout << "[PASS] LockRecord Test 1\n"; + + /* record unlock */ + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task issuing RU command", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + sLockCmd = "RU"; + SetCmd( x, sLockFile, sLockCmd, 'P', po ); + sResult = ""; + + GetCmd( x, sLockFile, sResult, 'P', po ); + while( sResult != "OK" && sResult != "FAIL" && iLoopCtr < 10 ){ + GetCmd( x, sLockFile, sResult, 'P', po ); + x.xbSleep( 250 ); + iLoopCtr++; + } + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task retrieved result [%s]", av[0], sResult.Str() ); + x.WriteLogMessage( sMsg ); + #endif + + if( sResult != "OK" ){ + iErrorStop = 280; + iRc2 = -1; + throw iRc2; + } + + if(( iRc2 = MyFile->LockRecord( XB_LOCK, 1 )) != XB_NO_ERROR ){ + iErrorStop = 290; + throw iRc2; + } + + std::cout << "[PASS] LockRecord Test 2\n"; + if(( iRc2 = MyFile->LockRecord( XB_UNLOCK, 1 )) != XB_NO_ERROR ){ + iErrorStop = 300; + throw iRc2; + } + + + /* memo lock */ + #ifdef XB_MEMO_SUPPORT + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task issuing ML command", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + sLockCmd = "ML"; + SetCmd( x, sLockFile, sLockCmd, 'P', po ); + sResult = ""; + + GetCmd( x, sLockFile, sResult, 'P', po ); + while( sResult != "OK" && sResult != "FAIL" && iLoopCtr < 10 ){ + GetCmd( x, sLockFile, sResult, 'P', po ); + x.xbSleep( 250 ); + iLoopCtr++; + } + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task retrieved result [%s]", av[0], sResult.Str() ); + x.WriteLogMessage( sMsg ); + #endif + + if( sResult != "OK" ){ + iErrorStop = 310; + iRc2 = -1; + throw iRc2; + } + + if(( iRc2 = MyFile->LockMemo( XB_LOCK )) == XB_NO_ERROR ){ + iErrorStop = 320; + throw iRc2; + } + if( po > 0 ) + std::cout << "[PASS] LockMemo Test 1\n"; + + /* memo unlock */ + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task issuing MU command", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + sLockCmd = "MU"; + SetCmd( x, sLockFile, sLockCmd, 'P', po ); + sResult = ""; + + GetCmd( x, sLockFile, sResult, 'P', po ); + while( sResult != "OK" && sResult != "FAIL" && iLoopCtr < 10 ){ + GetCmd( x, sLockFile, sResult, 'P', po ); + x.xbSleep( 250 ); + iLoopCtr++; + } + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task retrieved result [%s]", av[0], sResult.Str() ); + x.WriteLogMessage( sMsg ); + #endif + + if( sResult != "OK" ){ + iErrorStop = 330; + iRc2 = -1; + throw iRc2; + } + + if(( iRc2 = MyFile->LockMemo( XB_LOCK )) != XB_NO_ERROR ){ + iErrorStop = 340; + throw iRc2; + } + + std::cout << "[PASS] LockMemo Test 2\n"; + if(( iRc2 = MyFile->LockMemo( XB_UNLOCK )) != XB_NO_ERROR ){ + iErrorStop = 350; + throw iRc2; + } + #endif + + // exit + sLockCmd = "EXIT"; + SetCmd( x, sLockFile, sLockCmd, 'P', po ); + + } catch (xbInt16 iRc3 ){ + if( po > 0 ) + std::cout << "Parent lock task exiting on failure [" << sLockCmd.Str() << "][" << iErrorStop << "]\n"; + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Parent task terminating with errors [%s][%d][%d][%d]...", av[0], sLockCmd.Str(), iErrorStop, iLoopCtr, iRc3 ); + x.WriteLogMessage( sMsg ); + #endif + + sLockCmd = "EXIT"; + SetCmd( x, sLockFile, sLockCmd, 'P', po ); + MyFile->Close(); + delete MyFile; + } + } + + #else + iRc--; + sMsg.Sprintf( "Program [%s] not executed. Library does not support 'fork' or 'CreateProcess' function call", av[0] ); + #ifdef XB_LOGGING_SUPPORT + x.WriteLogMessage( sMsg ); + #endif + if( po > 0 ) + std::cout << sMsg.Str() << "\n"; + #endif + + if( po > 0 || iRc < 0 ) + fprintf( stdout, "[%s] Total Errors = %d\n", av[0], iRc * -1 ); + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], iRc * -1 ); + x.WriteLogMessage( sMsg ); + #endif + + return iRc; +} + diff --git a/src/tests/xb_test_lock2.cpp b/src/tests/xb_test_lock2.cpp new file mode 100755 index 0000000..3dd4b57 --- /dev/null +++ b/src/tests/xb_test_lock2.cpp @@ -0,0 +1,208 @@ +/* xb_test_lock2.cpp + +XBase Software Library + +Copyright (c) 1997,2003,2014,2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the locking functions +// This program is the child process that is called if used +// in an environment that supports the CreateProcess library function (ie Windows) + +// usage: xb_test_lock QUITE|NORMAL|VERBOSE + + + +#include "xbase.h" + +using namespace xb; + +#include "tstfuncs.cpp" + +/****************************************************************/ +int main( int argCnt, char **av ) +{ + xbInt16 iRc = 0; + xbInt16 iRc2; + xbInt16 po = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + xbBool bDone = xbFalse; +// xbInt16 iErrorStop = 0; + xbString sLockFile = "locktest.txt"; + xbString sLockCmd; + xbString sResult; + xbInt32 iChildLoop = 0; + + xbXBase x; + xbDbf * MyFile; + + xbBool bTblOpen = xbFalse; + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + po = 0; + else if( av[1][0] == 'V' ) + po = 2; + } + + #ifdef XB_LOGGING_SUPPORT + xbString sLogFileName = x.GetLogFqFileName().Str(); + + sLogFileName.Resize( sLogFileName.Len() - 3 ); + sLogFileName += "_l2.txt"; + x.SetLogFileName( sLogFileName ); + x.EnableMsgLogging(); + if( po > 0 ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + x.SetDataDirectory( PROJECT_DATA_DIR ); + x.EnableMsgLogging(); + InitTime(); + + #ifdef XB_DBF4_SUPPORT + MyFile = new xbDbf4( &x ); /* version 4 dbf file */ + #else + MyFile = new xbDbf3( &x ); /* version 3 dbf file */ + #endif + + x.xbSleep( 250 ); + while( !bDone ){ + iRc2 = GetCmd( x, sLockFile, sLockCmd, 'C', po ); + + #ifdef XB_LOGGING_SUPPORT + if( sLockCmd != "OK" && sLockCmd != "FAIL" ){ + sMsg.Sprintf( "Program [%s] Child task retrieved command=[%s] RC=[%d]", av[0], sLockCmd.Str(), iRc2 ); + x.WriteLogMessage( sMsg ); + } + #endif + + if( iRc2 == 0 ){ + + if( sLockCmd == "OK" || sLockCmd == "FAIL" ) + x.xbSleep( 250 ); + + else if( sLockCmd == "EXIT" ){ + bDone = xbTrue; + + } else if( sLockCmd == "START" && bTblOpen ){ + // came back before the parent task could process the result + x.xbSleep( 250 ); + + } else { + + if( sLockCmd == "START" ){ + + // begin the process + iRc2 = MyFile->Open( "LockTest.DBF" ); + if( iRc2 != XB_NO_ERROR ){ + sResult = "FAIL"; + } else { + sResult = "OK"; + bTblOpen = xbTrue; + } + + } else if( sLockCmd == "TL" ){ + // table lock + if(( iRc2 = MyFile->LockTable( XB_LOCK )) != XB_NO_ERROR ) + sResult = "FAIL"; + else + sResult = "OK"; + + } else if( sLockCmd == "TU" ){ + // table unlock + if(( iRc2 = MyFile->LockTable( XB_UNLOCK )) != XB_NO_ERROR ) + sResult = "FAIL"; + else + sResult = "OK"; + + } else if( sLockCmd == "RL" ){ + // record lock + if(( iRc2 = MyFile->LockRecord( XB_LOCK, 1 )) != XB_NO_ERROR ) + sResult = "FAIL"; + else + sResult = "OK"; + + + } else if( sLockCmd == "RU" ){ + // record unlock + if(( iRc2 = MyFile->LockRecord( XB_UNLOCK, 1 )) != XB_NO_ERROR ) + sResult = "FAIL"; + else + sResult = "OK"; + + } else if( sLockCmd == "ML" ){ + // memo lock + #ifdef XB_MEMO_SUPPORT + if(( iRc2 = MyFile->LockMemo( XB_LOCK )) != XB_NO_ERROR ) + sResult = "FAIL"; + else + sResult = "OK"; + #else + sLockCmd = "OK"; + #endif + + } else if( sLockCmd == "MU" ){ + // memo unlock + #ifdef XB_MEMO_SUPPORT + if(( iRc2 = MyFile->LockMemo( XB_UNLOCK )) != XB_NO_ERROR ) + sResult = "FAIL"; + else + sResult = "OK"; + #else + sLockCmd = "OK"; + #endif + } + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Child task [%s] Result [%s] RC = [%d]", av[0], sLockCmd.Str(), sResult.Str(), iRc2 ); + x.WriteLogMessage( sMsg ); + #endif + SetCmd( x, sLockFile, sResult, 'C', po ); + } + } else { + iRc = iRc2; + bDone = xbTrue; + } + + // std::cout << "clc [" << iChildLoop++ << "][" << bDone << "][" << sLockCmd << "]\n"; + x.xbSleep( 250 ); + if( iChildLoop > 10 ) + bDone = xbTrue; + } + MyFile->Close(); + delete MyFile; + if( po > 0 ) + std::cout << "Exiting child\n"; + + remove( sLockFile ); + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] Child task terminating", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + if( po > 0 || iRc < 0 ) + fprintf( stdout, "Total Errors = %d\n", iRc * -1 ); + + #ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], iRc * -1 ); + x.WriteLogMessage( sMsg ); + #endif + + ExitProcess( iRc ); +} + diff --git a/src/tests/xb_test_log.cpp b/src/tests/xb_test_log.cpp new file mode 100755 index 0000000..613b7dd --- /dev/null +++ b/src/tests/xb_test_log.cpp @@ -0,0 +1,88 @@ +/* xb_test_log.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014,2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the class xbLog + +// usage: xb_test_log QUITE|NORMAL|VERBOSE + + +#include "xbase.h" + +using namespace xb; + +#include "tstfuncs.cpp" + + + +int main( int argCnt, char **av ) +{ + int rc = 0; + +#ifdef XB_LOGGING_SUPPORT + + + int po = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + po = 0; + else if( av[1][0] == 'V' ) + po = 2; + } + + xbXBase x; + x.EnableMsgLogging(); + InitTime(); + if( po ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); + + + xbString sNewLogFileName = "Logfile2.txt"; + sMsg.Sprintf( "Switching to logfile [%s]", sNewLogFileName.Str() ); + x.WriteLogMessage( sMsg ); + + + x.DisableMsgLogging(); + rc += TestMethod( po, "Set/Get Log Status()", x.GetLogStatus(), xbFalse ); + x.SetLogFileName( sNewLogFileName ); + x.EnableMsgLogging(); + + rc += TestMethod( po, "Set/Get Log Status()", x.GetLogStatus(), 1 ); + rc += TestMethod( po,"WriteLogMessage()", x.WriteLogMessage( "Test log message........" ), XB_NO_ERROR ); + + + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], rc * -1 ); + x.WriteLogMessage( sMsg ); + + if( po > 0 || rc < 0 ) + fprintf( stdout, "Total Errors = %d\n", rc * -1 ); + + + #endif /* XB_LOGGING_SUPPORT */ + + + return rc; +} + + + + diff --git a/src/tests/xb_test_mdx.cpp b/src/tests/xb_test_mdx.cpp new file mode 100755 index 0000000..9351e4d --- /dev/null +++ b/src/tests/xb_test_mdx.cpp @@ -0,0 +1,243 @@ +/* xb_test_ndx.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014,2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the class xbIxNdx + +// usage: xb_test_ndx QUITE|NORMAL|VERBOSE + + +#include "xbase.h" + +using namespace xb; + +#include "tstfuncs.cpp" + +int main( int argCnt, char **av ) +{ + int iRc = 0; + int iRc2; + int iPo = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + xbString sMsg; + char c; + xbString s; + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + iPo = 0; + else if( av[1][0] == 'V' ) + iPo = 2; + } + + + xbSchema MyV4Record[] = + { + { "CITY", XB_CHAR_FLD, 100, 0 }, + { "STATE", XB_CHAR_FLD, 2, 0 }, + { "ZIP", XB_NUMERIC_FLD, 9, 0 }, + { "DATE1", XB_DATE_FLD, 8, 0 }, + { "",0,0,0 } + }; + + + xbXBase x; + +#ifdef XB_LOGGING_SUPPORT + x.EnableMsgLogging(); + if( iPo ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); +#endif + + x.SetDataDirectory( PROJECT_DATA_DIR ); + x.EnableMsgLogging(); + x.SetMultiUser( false ); + InitTime(); + + if( iPo > 0 ) + std::cout << "Default Data Directory is [" << x.GetDataDirectory().Str() << "]" << std::endl; + + + xbFile f( &x ); + xbIx *pIx; + void *pTag; + xbDate dt = "19890209"; + xbString sKey; + + xbDbf *V4DbfX1 = new xbDbf4( &x ); + + + iRc2 = V4DbfX1->CreateTable( "TMDXDB01.DBF", "TestMdxX2", MyV4Record, XB_OVERLAY, XB_MULTI_USER ); + iRc += TestMethod( iPo, "CreateTable(1)", iRc2, 0 ); + + /* + CreateTag( const xbString &sIxType, const xbString &sName, const xbString &sKey, const xbString &sFilter, + xbInt16 iDescending, xbInt16 iUnique, xbInt16 iOverLay, xbIx **xbIxOut, void **vpTagOut ); + */ + + iRc2 = V4DbfX1->CreateTag( "MDX", "CITY_TAGA", "CITY", "", 0, 0, XB_OVERLAY, &pIx, &pTag ); + iRc += TestMethod( iPo, "CreateTag(1)", iRc2, 0 ); + + iRc2 = V4DbfX1->CreateTag( "MDX", "ZIP_TAG", "ZIP", "", xbTrue, 0, XB_OVERLAY, &pIx, &pTag ); + iRc += TestMethod( iPo, "CreateTag(2)", iRc2, 0 ); + + iRc2 = V4DbfX1->CreateTag( "MDX", "DATE_TAG", "DATE1", "", 0, xbTrue, XB_OVERLAY, &pIx, &pTag ); + iRc += TestMethod( iPo, "CreateTag(3)", iRc2, 0 ); + + + // std::cout << "Cur Tag Name = " << V4DbfX1->GetCurTagName().Str() << "\n"; + + // xbDouble d = 4000; +// iRc2 = V4DbfX1->Find( d ); +// std::cout << iRc2 << "\n"; + + +// something in th following block of code causing issues + + xbInt32 uZip = 10000; + for( xbUInt16 i = 0; i < 35; i++ ){ + for( xbUInt16 j = 0; j < 14; j++ ){ + + c = j + 65; + s = c; + s.PadRight( c, (xbUInt32) i + 1 ); + //std::cout << "*********** adding s=[" << s.Str() << "] length = " << s.Len() << "\n"; + iRc2 = V4DbfX1->BlankRecord(); + if( iRc2 != XB_NO_ERROR ) + iRc += TestMethod( iPo, "BlankRecord()", iRc2, XB_NO_ERROR ); + + iRc2 = V4DbfX1->PutField( "CITY", s ); + if( iRc2 != XB_NO_ERROR ) + iRc += TestMethod( iPo, "PutField()", iRc2, XB_NO_ERROR ); + + iRc2 = V4DbfX1->PutLongField( "ZIP", uZip++ ); + if( iRc2 != XB_NO_ERROR ) + iRc += TestMethod( iPo, "PutField()", iRc2, XB_NO_ERROR ); + + iRc2 = V4DbfX1->PutDateField( "DATE1", dt ); + dt++; + if( iRc2 != XB_NO_ERROR ) + iRc += TestMethod( iPo, "PutField()", iRc2, XB_NO_ERROR ); + + iRc2 = V4DbfX1->AppendRecord(); + if( iRc2 != XB_NO_ERROR ) + iRc += TestMethod( iPo, "AppendRecord()", iRc2, XB_NO_ERROR ); + + iRc2 = V4DbfX1->Commit(); + if( iRc2 != XB_NO_ERROR ) + iRc += TestMethod( iPo, "Commit()", iRc2, XB_NO_ERROR ); + } + } + + + iRc += TestMethod( iPo, "CheckTagIntegrity()", V4DbfX1->CheckTagIntegrity( 1, 2 ), XB_NO_ERROR ); + + // attempt to add a dup key, should fail with XB_KEY_NOT_UNIQUE + iRc2 = V4DbfX1->BlankRecord(); + if( iRc2 != XB_NO_ERROR ) + iRc += TestMethod( iPo, "BlankRecord()", iRc2, XB_NO_ERROR ); + + iRc2 = V4DbfX1->PutField( "CITY", "Tampa" ); + if( iRc2 != XB_NO_ERROR ) + iRc += TestMethod( iPo, "PutField()", iRc2, XB_NO_ERROR ); + + iRc2 = V4DbfX1->PutLongField( "ZIP", uZip++ ); + if( iRc2 != XB_NO_ERROR ) + iRc += TestMethod( iPo, "PutField()", iRc2, XB_NO_ERROR ); + + dt.Set( "19890209" ); + iRc2 = V4DbfX1->PutDateField( "DATE1", dt ); + dt++; + if( iRc2 != XB_NO_ERROR ) + iRc += TestMethod( iPo, "PutField()", iRc2, XB_NO_ERROR ); + + iRc2 = V4DbfX1->AppendRecord(); + if( iRc2 != XB_KEY_NOT_UNIQUE ) + iRc += TestMethod( iPo, "AppendRecord()", iRc2, XB_NO_ERROR ); + + iRc2 = V4DbfX1->Abort(); + if( iRc2 != XB_NO_ERROR ) + iRc += TestMethod( iPo, "Abort()", iRc2, XB_NO_ERROR ); + + iRc += TestMethod( iPo, "DeleteTag()", V4DbfX1->DeleteTag( "MDX", "CITY_TAGA" ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "CheckTagIntegrity()", V4DbfX1->CheckTagIntegrity( 1, 2 ), XB_NO_ERROR ); + + iRc2 = V4DbfX1->CreateTag( "MDX", "CITY_TAGF", "CITY", ".NOT. DELETED()", 0, 0, XB_OVERLAY, &pIx, &pTag ); + iRc += TestMethod( iPo, "CreateTag(4)", iRc2, 0 ); + + iRc2 = V4DbfX1->SetCurTag( "CITY_TAGF" ); + iRc += TestMethod( iPo, "SetCurTag()", iRc2, XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurTagName()", V4DbfX1->GetCurTagName().Str(), "CITY_TAGF", 9 ); + + iRc += TestMethod( iPo, "CheckTagIntegrity()", V4DbfX1->CheckTagIntegrity( 1, 2 ), XB_INVALID_INDEX ); + + iRc2 = V4DbfX1->Reindex( 0 ); + iRc += TestMethod( iPo, "Reindex( 0 )", iRc2, XB_NO_ERROR ); + iRc += TestMethod( iPo, "CheckTagIntegrity()", V4DbfX1->CheckTagIntegrity( 1, 2 ), XB_NO_ERROR ); + + iRc += TestMethod( iPo, "GetCurTagName()", V4DbfX1->GetCurTagName().Str(), "CITY_TAGF", 9 ); + + iRc2 = V4DbfX1->Reindex( 1 ); + iRc += TestMethod( iPo, "Reindex( 1 )", iRc2, XB_NO_ERROR ); + iRc += TestMethod( iPo, "CheckTagIntegrity()", V4DbfX1->CheckTagIntegrity( 1, 2 ), XB_NO_ERROR ); + + // delete everything, all keys should be removed from the filtered index + iRc += TestMethod( iPo, "DeleteAll(0)", V4DbfX1->DeleteAll( 0 ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "Commit()", V4DbfX1->Commit(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "CheckTagIntegrity()", V4DbfX1->CheckTagIntegrity( 1, 2 ), XB_NO_ERROR ); + + // undelete everything, all keys should be added back into the filtered index + iRc += TestMethod( iPo, "DeleteAll(1)", V4DbfX1->DeleteAll( 1 ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "Commit()", V4DbfX1->Commit(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "CheckTagIntegrity()", V4DbfX1->CheckTagIntegrity( 1, 2 ), XB_NO_ERROR ); + + // std::cout << "Cur Tag Name = " << V4DbfX1->GetCurTagName().Str() << "\n"; + sKey = "abc"; + iRc += TestMethod( iPo, "Find()", V4DbfX1->Find( sKey ), XB_NOT_FOUND ); + sKey = "EEEEE"; + iRc += TestMethod( iPo, "Find()", V4DbfX1->Find( sKey ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurRecNo()", (xbInt32) V4DbfX1->GetCurRecNo(), (xbInt32) 61 ); + + iRc += TestMethod( iPo, "GetNextKey()", V4DbfX1->GetNextKey(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurRecNo()", (xbInt32) V4DbfX1->GetCurRecNo(), (xbInt32) 75 ); + + iRc += TestMethod( iPo, "GetPrevKey()", V4DbfX1->GetPrevKey(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurRecNo()", (xbInt32) V4DbfX1->GetCurRecNo(), (xbInt32) 61 ); + + iRc += TestMethod( iPo, "GetLastKey()", V4DbfX1->GetLastKey(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurRecNo()", (xbInt32) V4DbfX1->GetCurRecNo(), (xbInt32) 490 ); + + iRc += TestMethod( iPo, "GetFirstKey()", V4DbfX1->GetFirstKey(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurRecNo()", (xbInt32) V4DbfX1->GetCurRecNo(), (xbInt32) 1 ); + + + x.CloseAllTables(); + delete V4DbfX1; + + if( iPo > 0 || iRc < 0 ) + fprintf( stdout, "Total Errors = %d\n", iRc * -1 ); + +#ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], iRc * -1 ); + x.WriteLogMessage( sMsg ); +#endif + + return iRc; +} diff --git a/src/tests/xb_test_ndx.cpp b/src/tests/xb_test_ndx.cpp new file mode 100755 index 0000000..31306c0 --- /dev/null +++ b/src/tests/xb_test_ndx.cpp @@ -0,0 +1,330 @@ +/* xb_test_ndx.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014,2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the class xbIxNdx + +// usage: xb_test_ndx QUITE|NORMAL|VERBOSE + + + +// fix me - this program needs to test GetUnique + +#include "xbase.h" + +using namespace xb; + +#include "tstfuncs.cpp" + + +int main( int argCnt, char **av ) +{ + int iRc = 0; + int iRc2 = 0; + int iPo = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + iPo = 0; + else if( av[1][0] == 'V' ) + iPo = 2; + } + + + xbSchema MyV3Record[] = + { + { "CFLD", XB_CHAR_FLD, 30, 0 }, + { "DFLD", XB_DATE_FLD, 8, 0 }, + { "NFLD", XB_NUMERIC_FLD, 12, 0 }, + { "",0,0,0 } + }; + + + xbXBase x; +#ifdef XB_LOGGING_SUPPORT + x.EnableMsgLogging(); + if( iPo ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); + x.SetLogSize( 1000000 ); +#endif + + x.SetDataDirectory( PROJECT_DATA_DIR ); + x.EnableMsgLogging(); +// x.DisableDefaultAutoLock(); + InitTime(); + + char c; + xbString s; + xbInt32 lRecCnt = 0; + iRc = 0; + + + if( iPo > 0 ) + std::cout << "Default Data Directory is [" << x.GetDataDirectory().Str() << "]" << std::endl; + + xbDbf *V3Dbf = new xbDbf3( &x ); + + xbIx *ixPtr; + void *ndx; + + iRc2 = V3Dbf->CreateTable( "TestNdx.DBF", "TestNdx", MyV3Record, XB_OVERLAY, XB_MULTI_USER ); + iRc += TestMethod( iPo, "CreateTable()", (xbInt32) iRc2, XB_NO_ERROR ); + + if( iRc2 ) + x.DisplayError( iRc2 ); + + + iRc2 = V3Dbf->CreateTag( "NDX", "TestNdxC.NDX", "CFLD", "", 0, 0, XB_OVERLAY, &ixPtr, &ndx ); + iRc += TestMethod( iPo, "CreateTag()", (xbInt32) iRc2, XB_NO_ERROR ); + if( iRc2 ) + x.DisplayError( iRc2 ); + + iRc2 = V3Dbf->AssociateIndex( "NDX", "TestNdxC.NDX", 0 ); + iRc += TestMethod( iPo, "Associate()", (xbInt32) iRc2, XB_NO_ERROR ); + + iRc2 = V3Dbf->CreateTag( "NDX", "TestNdxD.NDX", "DFLD", "", 0, 0, XB_OVERLAY, &ixPtr, &ndx ); + iRc += TestMethod( iPo, "CreateTag()", (xbInt32) iRc2, XB_NO_ERROR ); + if( iRc2 ) + x.DisplayError( iRc2 ); + + iRc2 = V3Dbf->AssociateIndex( "NDX", "TestNdxD.NDX", 0 ); + iRc += TestMethod( iPo, "Associate()", (xbInt32) iRc2, XB_NO_ERROR ); + + iRc2 = V3Dbf->CreateTag( "NDX", "TestNdxN.NDX", "NFLD", "", 0, 0, XB_OVERLAY, &ixPtr, &ndx ); + iRc += TestMethod( iPo, "CreateTag()", (xbInt32) iRc2, XB_NO_ERROR ); + if( iRc2 ) + x.DisplayError( iRc2 ); + + iRc2 = V3Dbf->AssociateIndex( "NDX", "TestNdxN.NDX", 0 ); + iRc += TestMethod( iPo, "Associate()", (xbInt32) iRc2, XB_NO_ERROR ); + + + iRc += TestMethod( iPo, "GetCurTagName()", V3Dbf->GetCurTagName().Str(), "TestNdxC", 8 ); + iRc += TestMethod( iPo, "SetCurTag()", V3Dbf->SetCurTag( "TestNdxN" ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurTagName()", V3Dbf->GetCurTagName().Str(), "TestNdxN", 8 ); + xbDouble dbl = 100; + iRc += TestMethod( iPo, "Find( 100 )", V3Dbf->Find( dbl ), XB_NOT_FOUND ); + + iRc += TestMethod( iPo, "SetCurTag()", V3Dbf->SetCurTag( "TestNdxD" ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurTagName()", V3Dbf->GetCurTagName().Str(), "TestNdxD", 8 ); + xbDate dt; + iRc += TestMethod( iPo, "Find( dt )", V3Dbf->Find( dt ), XB_NOT_FOUND ); + + iRc += TestMethod( iPo, "GetFirstKey()", ixPtr->GetFirstKey(), XB_EMPTY ); + iRc += TestMethod( iPo, "GetNextKey()", ixPtr->GetFirstKey(), XB_EMPTY ); + iRc += TestMethod( iPo, "GetLasttKey()", ixPtr->GetLastKey(), XB_EMPTY ); + iRc += TestMethod( iPo, "GetPrevKey()", ixPtr->GetPrevKey(), XB_EMPTY ); + iRc += TestMethod( iPo, "FindKey()", ixPtr->FindKey( NULL, "19611101", 8, 0 ), XB_NOT_FOUND ); + + iRc += TestMethod( iPo, "BlankRecord()", V3Dbf->BlankRecord(), XB_NO_ERROR ); + iRc += TestMethod( iPo, "Putfield()", V3Dbf->PutField( "CFLD", "AAA" ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "Putfield()", V3Dbf->PutField( "DFLD", "19611109" ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "PutfieldDouble()", V3Dbf->PutDoubleField( "NFLD", 50 ), XB_NO_ERROR ); + + iRc += TestMethod( iPo, "AppendRecord()", V3Dbf->AppendRecord(), XB_NO_ERROR ); + + xbDate d( "19890209" ); + + //for( xbUInt16 i = 0; i < 35 && iRc == XB_NO_ERROR; i++ ){ + for( xbUInt16 i = 0; i < 2 && iRc == XB_NO_ERROR; i++ ){ + for( xbUInt16 j = 0; j < 35 && iRc == XB_NO_ERROR; j++ ){ + c = j + 65; + s = c; + s.PadRight( c, (xbUInt32) i + 1 ); + V3Dbf->BlankRecord(); + V3Dbf->PutField( "CFLD", s ); + V3Dbf->PutLongField( "NFLD", ++lRecCnt ); + V3Dbf->PutField( "DFLD", d.Str() ); + d++; + + iRc = V3Dbf->AppendRecord(); + } + } + + iRc += TestMethod( iPo, "SetCurTag()", V3Dbf->SetCurTag( "TestNdxN" ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurTagName()", V3Dbf->GetCurTagName().Str(), "TestNdxN", 8 ); + + dbl = 55.0; + iRc += TestMethod( iPo, "Find( 55.0 )", V3Dbf->Find( dbl ), XB_NO_ERROR ); + + iRc += TestMethod( iPo, "SetCurTag()", V3Dbf->SetCurTag( "TestNdxC" ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurTagName()", V3Dbf->GetCurTagName().Str(), "TestNdxC", 8 ); + + s = "AAA"; + iRc += TestMethod( iPo, "Find( 'AAA' )", V3Dbf->Find( s ), XB_NO_ERROR ); + + s = "AzAA"; + iRc += TestMethod( iPo, "Find( 'AzAA' )", V3Dbf->Find( s ), XB_NOT_FOUND ); + + iRc += TestMethod( iPo, "SetCurTag()", V3Dbf->SetCurTag( "TestNdxD" ), XB_NO_ERROR ); + iRc += TestMethod( iPo, "GetCurTagName()", V3Dbf->GetCurTagName().Str(), "TestNdxD", 8 ); + + std::cout << d.Str() << "\n"; + iRc += TestMethod( iPo, "Find( '19890420' )", V3Dbf->Find( d ), XB_NOT_FOUND ); + + V3Dbf->GetRecord( 26 ); + V3Dbf->PutField( "CFLD", "AAA" ); + V3Dbf->PutRecord( 26 ); + + V3Dbf->GetRecord( 14 ); + V3Dbf->PutField( "CFLD", "AAAA" ); + V3Dbf->PutRecord( 14 ); + + V3Dbf->GetRecord( 11 ); + V3Dbf->PutField( "CFLD", "III" ); + V3Dbf->PutRecord( 11 ); + + V3Dbf->GetRecord( 25 ); + V3Dbf->PutField( "CFLD", "DDD" ); + V3Dbf->PutRecord( 25 ); + + V3Dbf->GetRecord( 12 ); + V3Dbf->PutField( "CFLD", "EEE" ); + V3Dbf->PutRecord( 12 ); + + V3Dbf->GetRecord( 26 ); + V3Dbf->PutField( "CFLD", "CCC" ); + V3Dbf->PutRecord( 26 ); + + V3Dbf->GetRecord( 13 ); + V3Dbf->PutField( "CFLD", "CCCC" ); + V3Dbf->PutRecord( 13 ); + + V3Dbf->GetRecord( 27 ); + V3Dbf->PutField( "CFLD", "AAA" ); + V3Dbf->PutRecord( 27 ); + + V3Dbf->GetRecord( 28 ); + V3Dbf->PutField( "CFLD", "CCC" ); + V3Dbf->PutRecord( 28 ); + + V3Dbf->GetRecord( 24 ); + V3Dbf->PutField( "CFLD", "FFF" ); + V3Dbf->PutRecord( 24 ); + + V3Dbf->GetRecord( 10 ); + V3Dbf->PutField( "CFLD", "HHH" ); + V3Dbf->PutRecord( 10 ); + + + for( xbUInt16 i = 0; i < 35 && iRc == XB_NO_ERROR; i++ ){ + for( xbUInt16 j = 0; j < 14 && iRc == XB_NO_ERROR; j++ ){ + c = j + 65; + s = c; + s.PadRight( c, (xbUInt32) i + 1 ); + V3Dbf->BlankRecord(); + V3Dbf->PutField( "CFLD", s ); + V3Dbf->PutLongField( "NFLD", ++lRecCnt ); + V3Dbf->PutField( "DFLD", d.Str() ); + d++; + iRc = V3Dbf->AppendRecord(); + } + } + + for( xbUInt16 i = 0; i < 2 && iRc == XB_NO_ERROR; i++ ){ + for( xbUInt16 j = 0; j < 14 && iRc == XB_NO_ERROR; j++ ){ + c = j + 65; + s = c; + s.PadRight( c, (xbUInt32) i + 1 ); + + V3Dbf->BlankRecord(); + V3Dbf->PutField( "CFLD", s ); + V3Dbf->PutLongField( "NFLD", ++lRecCnt ); + V3Dbf->PutField( "DFLD", d.Str() ); + d++; + + iRc = V3Dbf->AppendRecord(); + } + } + + V3Dbf->GetRecord( 26 ); + V3Dbf->PutField( "CFLD", "AAA" ); + V3Dbf->PutRecord( 26 ); + + V3Dbf->GetRecord( 14 ); + V3Dbf->PutField( "CFLD", "AAAA" ); + V3Dbf->PutRecord( 14 ); + + V3Dbf->GetRecord( 11 ); + V3Dbf->PutField( "CFLD", "III" ); + V3Dbf->PutRecord( 11 ); + + V3Dbf->GetRecord( 25 ); + V3Dbf->PutField( "CFLD", "DDD" ); + V3Dbf->PutRecord( 25 ); + + V3Dbf->GetRecord( 12 ); + V3Dbf->PutField( "CFLD", "EEE" ); + V3Dbf->PutRecord( 12 ); + + V3Dbf->GetRecord( 26 ); + V3Dbf->PutField( "CFLD", "CCC" ); + V3Dbf->PutRecord( 26 ); + + V3Dbf->GetRecord( 13 ); + V3Dbf->PutField( "CFLD", "CCCC" ); + V3Dbf->PutRecord( 13 ); + + V3Dbf->GetRecord( 27 ); + V3Dbf->PutField( "CFLD", "AAA" ); + V3Dbf->PutRecord( 27 ); + + V3Dbf->GetRecord( 28 ); + V3Dbf->PutField( "CFLD", "CCC" ); + V3Dbf->PutRecord( 28 ); + + V3Dbf->GetRecord( 24 ); + V3Dbf->PutField( "CFLD", "FFF" ); + V3Dbf->PutRecord( 24 ); + + V3Dbf->GetRecord( 10 ); + V3Dbf->PutField( "CFLD", "HHH" ); + V3Dbf->PutRecord( 10 ); + + // just in case there are any issues outstanding + V3Dbf->Abort(); + + xbIxList *ixl = V3Dbf->GetIxList(); + xbIxNdx *ix; + xbString sTagName; + while( ixl ){ + if( *ixl->sFmt == "NDX" ){ + ix = (xbIxNdx *) ixl->ix; + //ix->GetTagName( 0, sTagName ); + sMsg.Sprintf( "CheckTagIntegrity() - [%s]", ix->GetTagName(ix->GetCurTag()).Str()); + iRc += TestMethod( iPo, sMsg, ix->CheckTagIntegrity( ix->GetCurTag(), 2 ), XB_NO_ERROR ); + ixl = ixl->next; + } + } + + iRc += TestMethod( iPo, "Close()", V3Dbf->Close(), XB_NO_ERROR ); + delete V3Dbf; + + if( iPo > 0 || iRc < 0 ) + fprintf( stdout, "Total Errors = %d\n", iRc * -1 ); + +#ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], iRc * -1 ); + x.WriteLogMessage( sMsg, 2 ); +#endif + + return iRc; +} diff --git a/src/tests/xb_test_ndx2.cpp b/src/tests/xb_test_ndx2.cpp new file mode 100755 index 0000000..f406b05 --- /dev/null +++ b/src/tests/xb_test_ndx2.cpp @@ -0,0 +1,145 @@ +/* xb_test_ndx2.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014, 2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + xb64-devel@lists.sourceforge.net + xb64-users@lists.sourceforge.net + +*/ + +// This program tests the class xbIxNdx + +// usage: xb_test_ndx QUITE|NORMAL|VERBOSE + + + +// fix me - this program needs to test GetUnique + +#include "xbase.h" + +using namespace xb; + +#include "tstfuncs.cpp" + + +int main( int argCnt, char **av ) +{ + int iRc = 0; + int iRc2 = 0; + int po = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + po = 0; + else if( av[1][0] == 'V' ) + po = 2; + } + + + xbSchema MyV3Record[] = + { + { "CFLD", XB_CHAR_FLD, 30, 0 }, + { "DFLD", XB_DATE_FLD, 8, 0 }, + { "NFLD", XB_NUMERIC_FLD, 12, 0 }, + { "",0,0,0 } + }; + + + xbXBase x; +#ifdef XB_LOGGING_SUPPORT + x.EnableMsgLogging(); + if( po ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); + x.SetLogSize( 1000000 ); +#endif + + x.SetDataDirectory( PROJECT_DATA_DIR ); + x.EnableMsgLogging(); +// x.DisableDefaultAutoLock(); + + x.SetUniqueKeyOpt( XB_EMULATE_DBASE ); + InitTime(); + xbString s; + iRc = 0; + + if( po > 0 ) + std::cout << "Default Data Directory is [" << x.GetDataDirectory().Str() << "]" << std::endl; + + xbDbf *V3Dbf = new xbDbf3( &x ); + xbIx *ixPtr; + void *ndx; + + iRc2 = V3Dbf->CreateTable( "TestNdx.DBF", "TestNdx", MyV3Record, XB_OVERLAY, XB_MULTI_USER ); + iRc += TestMethod( po, "CreateTable()", (xbInt32) iRc2, XB_NO_ERROR ); + + if( iRc2 ) + x.DisplayError( iRc2 ); + + iRc2 = V3Dbf->CreateTag( "NDX", "TestNdxC.NDX", "CFLD", "", 0, xbTrue, XB_OVERLAY, &ixPtr, &ndx ); + iRc += TestMethod( po, "CreateTag()", (xbInt32) iRc2, XB_NO_ERROR ); + if( iRc2 ) + x.DisplayError( iRc2 ); + + iRc2 = V3Dbf->AssociateIndex( "NDX", "TestNdxC.NDX", 0 ); + iRc += TestMethod( po, "Associate()", (xbInt32) iRc2, XB_NO_ERROR ); + + + iRc += TestMethod( po, "BlankRecord()", V3Dbf->BlankRecord(), XB_NO_ERROR ); + iRc += TestMethod( po, "Putfield()", V3Dbf->PutField( "CFLD", "AAA" ), XB_NO_ERROR ); + iRc += TestMethod( po, "Putfield()", V3Dbf->PutField( "DFLD", "19611109" ), XB_NO_ERROR ); + iRc += TestMethod( po, "PutfieldDouble()", V3Dbf->PutDoubleField( "NFLD", 50 ), XB_NO_ERROR ); + iRc += TestMethod( po, "AppendRecord()", V3Dbf->AppendRecord(), XB_NO_ERROR ); + + + iRc += TestMethod( po, "BlankRecord()", V3Dbf->BlankRecord(), XB_NO_ERROR ); + iRc += TestMethod( po, "Putfield()", V3Dbf->PutField( "CFLD", "BBB" ), XB_NO_ERROR ); + iRc += TestMethod( po, "Putfield()", V3Dbf->PutField( "DFLD", "19611109" ), XB_NO_ERROR ); + iRc += TestMethod( po, "PutfieldDouble()", V3Dbf->PutDoubleField( "NFLD", 50 ), XB_NO_ERROR ); + iRc += TestMethod( po, "AppendRecord()", V3Dbf->AppendRecord(), XB_NO_ERROR ); + + iRc += TestMethod( po, "BlankRecord()", V3Dbf->BlankRecord(), XB_NO_ERROR ); + iRc += TestMethod( po, "Putfield()", V3Dbf->PutField( "CFLD", "BBB" ), XB_NO_ERROR ); + iRc += TestMethod( po, "Putfield()", V3Dbf->PutField( "DFLD", "19611109" ), XB_NO_ERROR ); + iRc += TestMethod( po, "PutfieldDouble()", V3Dbf->PutDoubleField( "NFLD", 50 ), XB_NO_ERROR ); + iRc += TestMethod( po, "AppendRecord()", V3Dbf->AppendRecord(), XB_NO_ERROR ); + + + xbIxList *ixl = V3Dbf->GetIxList(); + xbIxNdx *ix; + xbString sTagName; + while( ixl ){ + if( *ixl->sFmt == "NDX" ){ + ix = (xbIxNdx *) ixl->ix; + //ix->GetTagName( 0, sTagName ); + sMsg.Sprintf( "CheckTagIntegrity() - [%s]", ix->GetTagName(ix->GetCurTag()).Str()); + iRc += TestMethod( po, sMsg, ix->CheckTagIntegrity( ix->GetCurTag(), 2 ), XB_NO_ERROR ); + ixl = ixl->next; + } + } + + iRc += TestMethod( po, "Close()", V3Dbf->Close(), XB_NO_ERROR ); + delete V3Dbf; + + if( po > 0 || iRc < 0 ) + fprintf( stdout, "Total Errors = %d\n", iRc * -1 ); + +#ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], iRc * -1 ); + x.WriteLogMessage( sMsg, 2 ); +#endif + + return iRc; +} diff --git a/src/tests/xb_test_sql.cpp b/src/tests/xb_test_sql.cpp new file mode 100755 index 0000000..630cc89 --- /dev/null +++ b/src/tests/xb_test_sql.cpp @@ -0,0 +1,107 @@ +/* xb_test_sql.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014, 2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + xb64-devel@lists.sourceforge.net + xb64-users@lists.sourceforge.net + +*/ + +// This program tests the SQL functions + +// usage: xb_test_sql QUITE|NORMAL|VERBOSE + + + +#include "xbase.h" + +using namespace xb; + +#include "tstfuncs.cpp" + + +int main( int argCnt, char **av ) +{ + int iRc = 0; + int iRc2 = 0; + int po = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + po = 0; + else if( av[1][0] == 'V' ) + po = 2; + } + + + xbSchema MySqlRecord[] = + { + { "CITY", XB_CHAR_FLD, 30, 0 }, + { "STATE", XB_CHAR_FLD, 2, 0 }, + { "ZIPCODE", XB_NUMERIC_FLD, 9, 0 }, + { "NOTES", XB_MEMO_FLD, 10, 0 }, + { "LASTUPDATE", XB_DATE_FLD, 8, 1 }, + { "ACTIVE", XB_LOGICAL_FLD, 1, 0 }, + { "",0,0,0 } + }; + + + xbXBase x; +#ifdef XB_LOGGING_SUPPORT + x.EnableMsgLogging(); + if( po ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); +#endif + + + + x.SetDataDirectory( PROJECT_DATA_DIR ); + x.EnableMsgLogging(); + InitTime(); + + xbSql sql( &x ); + + if( po > 0 ) + std::cout << "Default Data Directory is [" << x.GetDataDirectory().Str() << "]" << std::endl; + + xbDbf4 SqlDbf( &x ); // version 4 dbf file + iRc2 = SqlDbf.CreateTable( "TestSQL.DBF", "TestSQL", MySqlRecord, XB_OVERLAY, XB_MULTI_USER ); + iRc += TestMethod( po, "CreateTable()", (xbInt32) iRc2, XB_NO_ERROR ); + if( iRc2 ) + x.DisplayError( iRc2 ); + + + xbString sSql = "INSERT INTO TestSQL (CITY, STATE, ZIPCODE, NOTES, LASTUPDATE, ACTIVE ) VALUES ( 'San Diego', 'CA', 92007, 'San Diego is a cool place', '1989-02-09', 'Y')"; + + iRc2 = sql.ExecuteNonQuery( sSql ); + iRc += TestMethod( po, "Insert()", (xbInt32) iRc2, XB_NO_ERROR ); + if( iRc2 ) + x.DisplayError( iRc2 ); + + iRc += TestMethod( po, "Close()", SqlDbf.Close(), XB_NO_ERROR ); + + if( po > 0 || iRc < 0 ) + fprintf( stdout, "Total Errors = %d\n", iRc * -1 ); + + +#ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], iRc * -1 ); + x.WriteLogMessage( sMsg ); +#endif + + return iRc; +} + diff --git a/src/tests/xb_test_string.cpp b/src/tests/xb_test_string.cpp new file mode 100755 index 0000000..f39c101 --- /dev/null +++ b/src/tests/xb_test_string.cpp @@ -0,0 +1,397 @@ +/* xb_test_string.cpp + +XBase63 Software Library + +Copyright (c) 1997,2003,2014, 2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the string class xbString + +// usage: xb_test_string QUIET|NORMAL|VERBOSE + +#define VERBOSE + +#include "xbase.h" + +using namespace xb; + +#include "tstfuncs.cpp" + +int main( int argCnt, char **av = NULL ) + +//int main( int argCnt, char *argv[] ) +{ + int rc = 0; + int po = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + po = 0; + else if( av[1][0] == 'V' ) + po = 2; + } + + xbXBase x; + + #ifdef XB_LOGGING_SUPPORT + x.EnableMsgLogging(); + if( po ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); + #endif + + x.SetDataDirectory( PROJECT_DATA_DIR ); + x.EnableMsgLogging(); + + InitTime(); + + // create a string, assign a value + xbString s1; + s1 = "Test String 1"; + rc += TestMethod( po, "Constructor s1" , s1, "Test String 1", 13 ); + + // create another string, copy the value from s1 into it + xbString s2; + s2 = s1; + rc += TestMethod( po, "Operator '=' " , s2, "Test String 1", 13 ); + + // create another string with a single character + xbString s3( 'X' ); + + //std::cout << "s3 = [" << s3 << "]" << std::endl; + rc += TestMethod( po, "Constructor s3" , s3, "X", 1 ); + + // create another string and assign data to it yet another way + xbString s4( "Class constructor test 4" ); + rc += TestMethod( po, "Constructor s4" , s4, "Class constructor test 4", 24 ); + + // create another string with a size limit + xbString s5( "Class constructor test 4", 7 ); + rc += TestMethod( po, "Constructor s5" , s5, "Class c", 7 ); + + // create another string from a string + xbString s6( s5 ); + rc += TestMethod( po, "Constructor s6" , s6, "Class c", 7 ); + + // create 15 byte string with nothing in it + xbString s7( (xbUInt32) 15 ); + rc += TestMethod( po, "Constructor s7" , s7, "", 0 ); + + xbString s8( "some test data", 6 ); + rc += TestMethod( po, "Constructor s8" , s8, "some t", 6 ); + + xbString s9( "some test data", 30 ); + rc += TestMethod( po, "Constructor s9" , s9, "some test data", 14 ); + + // Extract character from a particular position in the string + rc += TestMethod( po, "Operator [] ", s1[7], 't' ); + rc += TestMethod( po, "Operator [] ", s1.GetCharacter(7), 't' ); + + s1[6] = 'X'; + rc += TestMethod( po, "Operator assignment [] ", s1.GetCharacter(6), 'X' ); + + // set string 7 to a character + s7 = 'Z'; + rc += TestMethod( po, "Operator =", s7.Str(), "Z", 1 ); + + // Concatenation tests - I + s1 = " part 1 "; + s1 += " part 2 "; + s2 = " part 3 "; + s1 += s2; + s1 += 'Z'; + rc += TestMethod( po, "Concatenation test 1", s1, " part 1 part 2 part 3 Z", 25 ); + + // Concatenation tests - II + s1 = "part 1 "; + s1 -= "part 2 "; + s1 -= 'X'; + s1 -= s2; + rc += TestMethod( po, "Concatenation test 2", s1, "part 1part 2X part 3", 20 ); + + // Concatenation tests - III + s1 = "s1data "; + s2 = "s2data "; + s3 = s1 - s2; + rc += TestMethod( po, "Concatenation test 3", s3, "s1datas2data", 12 ); + + // Concatenation tests - IV + s3 = s1 + s2; + rc += TestMethod( po, "Concatenation test 4", s3, "s1data s2data ", 15 ); + + // Concatenation tests - V + s3 = s1 + " (char * data) " + "xyz " + s2 + 'z'; + rc += TestMethod( po, "Concatenation test 1", s3, "s1data (char * data) xyz s2data z", 36 ); + + //Operator tests + s1 = "aaa"; + s2 = "bbb"; + rc += TestMethod( po, "Operator == ", s1 == s2, 0 ); + rc += TestMethod( po, "Operator != ", s1 != s2, 1 ); + rc += TestMethod( po, "Operator < ", s1 < s2, 1 ); + rc += TestMethod( po, "Operator > ", s1 > s2, 0 ); + rc += TestMethod( po, "Operator < ", s1 <= s2, 1 ); + rc += TestMethod( po, "Operator > ", s1 >= s2, 0 ); + + s1 = s2; + rc += TestMethod( po, "Operator == ", s1 == s2, 1 ); + rc += TestMethod( po, "Operator != ", s1 == s2, 1 ); + rc += TestMethod( po, "Operator < ", s1 < s2, 0 ); + rc += TestMethod( po, "Operator > ", s1 > s2, 0 ); + rc += TestMethod( po, "Operator < ", s1 <= s2, 1 ); + rc += TestMethod( po, "Operator > ", s1 >= s2, 1 ); + + s1 = "XYZ"; + rc += TestMethod( po, "Operator * ", (const char *) s1, "XYZ", 3 ); + + s1 = 'Z'; + rc += TestMethod( po, "Operator = ", s1, "Z", 1 ); + + s1 = "ABC,xyz"; + rc += TestMethod( po, "CountChar(c,1) ", (xbInt32) s1.CountChar( ',',1 ), 1 ); + + s1 = "ABC,xy,z"; + rc += TestMethod( po, "CountChar(c,1) ", (xbInt32) s1.CountChar( ',',1 ), 2 ); + + s1 = "ABC,xy,z'asad,as'adss"; + rc += TestMethod( po, "CountChar(c,1) ", (xbInt32) s1.CountChar( ',',1 ), 2 ); + + s1 = "ABADFDSGA"; + rc += TestMethod( po, "CountChar() ", (xbInt32) s1.CountChar( 'A' ), 3 ); + + s1.Ltrunc( 4 ); + rc += TestMethod( po, "Ltrunc(4) ", s1, "FDSGA", 5 ); + + s1.PutAt( 3, 'Z' ); + rc += TestMethod( po, "PutAt(3,'Z') ", s1, "FDZGA", 5 ); + + s1.AddBackSlash( 'Z' ); + rc += TestMethod( po, "AddBackSlash( 'Z' ) ", s1, "FD\\ZGA", 6 ); + + s1 = "ABCDEFG"; + rc += TestMethod( po, "s1.Append( 'Z' )", s1.Append( 'Z' ).Str(), "ABCDEFGZ", 8 ); + rc += TestMethod( po, "s1.Append( '999' )", s1.Append( "999" ), "ABCDEFGZ999", 11 ); + s2 = "!@#"; + rc += TestMethod( po, "s1.Append( '!@#' )", s1.Append( s2 ), "ABCDEFGZ999!@#", 14 ); + + rc += TestMethod( po, "s1.Assign( 'ABCDE', 3, 2 )", s1.Assign( "ABCDE", 3, 2 ), "CD", 2 ); + rc += TestMethod( po, "s1.Assign( 'ABCDE', 2, 7 )", s1.Assign( "ABCDE", 2, 7 ), "BCDE", 4 ); + rc += TestMethod( po, "s1.Assign( 'ABCDE', 1, 4 )", s1.Assign( "ABCDE", 1, 4 ), "ABCD", 4 ); + rc += TestMethod( po, "s1.Assign( 'ABCDE', 5, 5 )", s1.Assign( "ABCDE", 5, 5 ), "E", 1 ); + rc += TestMethod( po, "s1.Assign( 'ABCDE', 15, 5 )", s1.Assign( "ABCDE", 15, 5 ), "", 0 ); + + rc += TestMethod( po, "s1.Assign( 'ABCDE', 1 )", s1.Assign( "ABCDE", 1 ), "ABCDE", 5 ); + rc += TestMethod( po, "s1.Assign( 'ABCDE', 3 )", s1.Assign( "ABCDE", 3 ), "CDE", 3 ); + rc += TestMethod( po, "s1.Assign( 'ABCDE', 10 )", s1.Assign( "ABCDE", 10 ), "", 0 ); + + s2 = "ABCDE"; + rc += TestMethod( po, "s1.Assign( s2, 3, 2 )", s1.Assign( s2, 3, 2 ), "CD", 2 ); + rc += TestMethod( po, "s1.Assign( s2, 2, 7 )", s1.Assign( s2, 2, 7 ), "BCDE", 4 ); + rc += TestMethod( po, "s1.Assign( s2, 1, 4 )", s1.Assign( s2, 1, 4 ), "ABCD", 4 ); + rc += TestMethod( po, "s1.Assign( s2, 5, 5 )", s1.Assign( s2, 5, 5 ), "E", 1 ); + rc += TestMethod( po, "s1.Assign( s2, 15, 5 )", s1.Assign( s2, 15, 5 ), "", 0 ); + + rc += TestMethod( po, "s1.Assign( s2, 1 )", s1.Assign( s2, 1 ), "ABCDE", 5 ); + rc += TestMethod( po, "s1.Assign( s2, 3 )", s1.Assign( s2, 3 ), "CDE", 3 ); + rc += TestMethod( po, "s1.Assign( s2, 10 )", s1.Assign( s2, 10 ), "", 0 ); + + s2 = "1234567890"; + s1 = s2.Copy(); + rc += TestMethod( po, "Copy() ", s1, "1234567890", 10 ); + + s1 = "0x35"; + char hexChar; + s1.CvtHexChar( hexChar ); + rc += TestMethod( po, "CvtHexChar(hexChar) ", hexChar, '5' ); + + s1 = "0x610x620x630x640x65"; + s1.CvtHexString( s2 ); + rc += TestMethod( po, "CvtHexString() ", s2, "abcde", 5 ); + + s1 = "123"; + s2 = "ABC"; + rc += TestMethod( po, "HasAlphaChars()", s1.HasAlphaChars(), 0 ); + rc += TestMethod( po, "HasAlphaChars()", s2.HasAlphaChars(), 1 ); + + s1 = "\\ABC\\XYZ"; + rc += TestMethod( po, "GetPathSeparator()", s1.GetPathSeparator(), '\\' ); + + s1 = "/ABC/XYZ"; + rc += TestMethod( po, "GetPathSeparator()", s1.GetPathSeparator(), '/' ); + + s2 = ""; + rc += TestMethod( po, "IsEmpty()", s2.IsEmpty(), 1 ); + + // trim tests + s1 = " ABC "; + rc += TestMethod( po, "Ltrim()", s1.Ltrim(), "ABC ", 6 ); + s1 = " ABC "; + rc += TestMethod( po, "Rtrim()", s1.Rtrim(), " ABC", 6 ); + s1 = " ABC "; + rc += TestMethod( po, "Trim() ", s1.Trim(), "ABC", 3 ); + + s1 = "ABC "; + rc += TestMethod( po, "Ltrim()", s1.Ltrim(), "ABC ", 6 ); + + s1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + rc += TestMethod( po, "Mid(3,0) ", s1.Mid(3,0), "", 0 ); + + s1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + rc += TestMethod( po, "Mid(4,5) ", s1.Mid(4,5), "DEFGH", 5 ); + + rc += TestMethod( po, "Pos('G') ", (xbInt32) s1.Pos( 'G' ), 4 ); + rc += TestMethod( po, "Pos(\"EFG\") ", (xbInt32) s1.Pos( "EFG" ), 2 ); + + rc += TestMethod( po, "Pos('0') ", (xbInt32) s1.Pos( '0' ), 0 ); + rc += TestMethod( po, "Pos(\"000\") ", (xbInt32) s1.Pos( "000" ), 0 ); + rc += TestMethod( po, "Pos(\"DEF\") ", (xbInt32) s1.Pos( "DEF" ), 1 ); + + s1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + rc += TestMethod( po, "Remove(3,5) ", s1.Remove( 3, 5 ), "ABHIJKLMNOPQRSTUVWXYZ", 21 ); + + s1 = "ABCABCABZ"; + s1.SwapChars( 'A', '9' ); + rc += TestMethod( po, "SwapChars() ", s1, "9BC9BC9BZ", 9 ); + + s1.ToLowerCase(); + rc += TestMethod( po, "ToLowerCase() ", s1, "9bc9bc9bz", 9 ); + + s1.ToUpperCase(); + rc += TestMethod( po, "ToUpperCase() ", s1, "9BC9BC9BZ", 9 ); + + s1.ZapChar( '9' ); + rc += TestMethod( po, "ZapChar('9') ", s1, "BCBCBZ", 6 ); + + s1.ZapLeadingChar( 'B' ); + rc += TestMethod( po, "ZapLeadingChar('B') ", s1, "CBCBZ", 5 ); + + s1.ZapTrailingChar( 'Z' ); + rc += TestMethod( po, "ZapLeadingChar('B') ", s1, "CBCB", 4 ); + + s1.ExtractElement( "aaaa|bbbb|cccc|dddd", '|', 2, 0 ); + rc += TestMethod( po, "ExtractElement() ", s1, "bbbb", 4 ); + + s1.ExtractElement( "aaaa|b'bb|c'ccc|dddd", '|', 3, 1 ); + rc += TestMethod( po, "ExtractElement() ", s1, "dddd", 4 ); + + s1 = "123"; + s1.PadLeft( '0', 9 ); + rc += TestMethod( po, "PadLeft() ", s1, "000000123", 9 ); + + s1 = "abc"; + s1.PadRight( 'Z', 9 ); + rc += TestMethod( po, "PadRight() ", s1, "abcZZZZZZ", 9 ); + + s1.Left( 4 ); + rc += TestMethod( po, "Left(4) ", s1, "abcZ", 4 ); + + s1.Left( 1 ); + rc += TestMethod( po, "Left(1) ", s1, "a", 1 ); + + s1.Left( 0 ); + rc += TestMethod( po, "Left(0) ", s1, "", 0 ); + + + char buf[5]; + buf[0] = 'W'; + buf[1] = 'X'; + buf[2] = 'Y'; + buf[3] = 'Z'; + buf[4] = 0x00; + xbInt32 l = 1234567; + xbFloat f = (xbFloat) 12.35; + s2 = "test string"; + + rc += TestMethod( po, "s1.Sprintf()", s1.Sprintf( "%s %d %s %ld", buf, 12, s2.Str(), l ), "WXYZ 12 test string 1234567", 27 ); + + // %f format varies depending on compiler + s1.Sprintf( "%6.2f", f ); + s1.Ltrim(); + rc += TestMethod( po, "s1.Sprintf()/s.Trim()", s1, "12.35", 5 ); + + s1.SetNum( (long) 123456 ); + rc += TestMethod( po, "SetNum() ", s1, "123456", 6 ); + + s1 = "T"; + rc += TestMethod( po, "ValidLogicalValue", s1.ValidLogicalValue(), 1 ); + + s1 = "xyz"; + rc += TestMethod( po, "ValidLogicalValue", s1.ValidLogicalValue(), 0 ); + + s1 = "-123456.89"; + rc += TestMethod( po, "ValidNumericValue", s1.ValidNumericValue(), 1 ); + + s1 = "ABC-123456.89"; + rc += TestMethod( po, "ValidNumericValue", s1.ValidNumericValue(), 0 ); + + s1 = "abcabcabx"; + rc += TestMethod( po, "GetLastPos", (xbInt16) s1.GetLastPos( 'b' ), 8 ); + s1 = "abcabcabx"; + rc += TestMethod( po, "GetLastPos", (xbInt16) s1.GetLastPos( 'x' ), 9 ); + s1 = "abcabcabx"; + rc += TestMethod( po, "GetLastPos", (xbInt16) s1.GetLastPos( '$' ), 0 ); + rc += TestMethod( po, "GetLastPos", (xbInt16) s1.GetLastPos( "ab" ), 7 ); + + s1 = ")"; + rc += TestMethod( po, "GetLastPos", (xbInt16) s1.GetLastPos( ')' ), 1 ); + s1 = "))))"; + rc += TestMethod( po, "GetLastPos", (xbInt16) s1.GetLastPos( ')' ), 4 ); + + char * p; + p = (char *) malloc( 5 ); + p[0] = '1'; + p[1] = '2'; + p[2] = '3'; + p[3] = '4'; + p[4] = 0x00; + s1.Set( p, 5 ); + free( p ); + rc += TestMethod( po, "Set", s1, "1234", 4 ); + + + xbDouble d = 12345678.876543; + xbString sD( d ); + rc += TestMethod( po, "xbDouble Constructor", sD, "12345678.876543", 15 ); + + xbString sSet; + sSet.Set( sD ); + rc += TestMethod( po, "Set", sD, sD, 15 ); + sSet.Set( s2 ); + rc += TestMethod( po, "Set", sSet, s2, 11 ); + sSet.Set( "" ); + rc += TestMethod( po, "Set", sSet, "", 0 ); + + s1.Sprintf( "string %d", 1 ); + s2.Sprintf( "string %1.1f", 2.0 ); + s3.Sprintf( "%s and %s", s1.Str(), s2.Str()); + rc += TestMethod( po, "Sprintf", s3, "string 1 and string 2.0", 23 ); + + xbInt16 iErrorStop = 10; + xbInt16 iRc = -100; + sMsg.Sprintf( "class::method() Exception Caught. Error Stop = [%d] iRc = [%d] Expression = [%s]", iErrorStop, iRc, s3.Str() ); + + if( po > 0 || rc < 0 ) + fprintf( stdout, "Total Errors = %d\n", rc * -1 ); + +#ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], rc * -1 ); + x.WriteLogMessage( sMsg ); +#endif + + return rc; +} + diff --git a/src/tests/xb_test_tblmgr.cpp b/src/tests/xb_test_tblmgr.cpp new file mode 100755 index 0000000..26ec96a --- /dev/null +++ b/src/tests/xb_test_tblmgr.cpp @@ -0,0 +1,167 @@ +/* xb_test_tblmgr.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014, 2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the class xbXBase +// usage: xb_test_tblmgr QUITE|NORMAL|VERBOSE + + +#include "xbase.h" + +using namespace xb; + +#include "tstfuncs.cpp" + +int main( int argCnt, char **av ) +{ + int rc = 0; + int po = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + po = 0; + else if( av[1][0] == 'V' ) + po = 2; + } + + xbXBase x; + +#ifdef XB_LOGGING_SUPPORT + x.EnableMsgLogging(); + if( po ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); +#endif + InitTime(); + + if( po == 2 ){ + std::cout << "DisplayError Test ==> "; + x.DisplayError( 0 ); + #ifdef WIN32 + std::cout << "WIN32 environment" << std::endl; + #else + std::cout << "Not WIN32 environment" << std::endl; + #endif + } + + xbDbf * d1; + xbDbf * d2; + + #if defined (XB_DBF3_SUPPORT ) + d1 = new xbDbf3( &x ); + #elif defined( XB_DBF4_SUPPORT ) + d1 = new xbDbf4( &x ); + #else + std::cout << "No dbf file support built into library" << std::endl; + return -1; + #endif + + rc += TestMethod( po, "AddTblToTblLst()", x.AddTblToTblList( d1, "TestTableC" ), 0 ); + rc += TestMethod( po, "AddTblToTblLst()", x.AddTblToTblList( d1, "TestTableA" ), 0 ); + rc += TestMethod( po, "AddTblToTblLst()", x.AddTblToTblList( d1, "TestTableB" ), 0 ); + rc += TestMethod( po, "AddTblToTblLst()", x.AddTblToTblList( d1, "TestTableD" ), 0 ); + + + // Next line should generate an exception + rc += TestMethod( po, "AddTblToTblLst()", x.AddTblToTblList( d1, "TestTableC" ), XB_DUP_TABLE_OR_ALIAS ); + + std::cout << "**** Next list should have one each of TestTableA, B, C, D sorted in alpha order ****" << std::endl; + x.DisplayTableList(); + + d2 = (xbDbf *) x.GetDbfPtr( "TestTableA" ); + if( d2 ) + std::cout << "[PASS] GetDbfPtr()" << std::endl; + else{ + std::cout << "[FAIL] GetDbfPtr()" << std::endl; + rc--; + } + + +std::cout << "cp0\n"; + x.SetDataDirectory( "/ABCDEFG/" ); + + #ifdef WIN32 + rc += TestMethod( po, "Set/GetDataDirectory()", x.GetDataDirectory(), "\\ABCDEFG\\", 9 ); + #else + rc += TestMethod( po, "Set/GetDataDirectory()", x.GetDataDirectory(), "/ABCDEFG/", 9 ); + #endif +std::cout << "cp1\n"; + x.SetDataDirectory( "/ABCDEFG" ); + #ifdef WIN32 + rc += TestMethod( po, "Set/GetDataDirectory()", x.GetDataDirectory(), "\\ABCDEFG", 8 ); + #else + rc += TestMethod( po, "Set/GetDataDirectory()", x.GetDataDirectory(), "/ABCDEFG", 8 ); + #endif + + + std::cout << "cp2\n"; + + + x.SetDataDirectory( "\\ABCDEFG\\"); + #ifdef WIN32 + rc += TestMethod( po, "Set/GetDataDirectory()", x.GetDataDirectory(), "\\ABCDEFG\\", 9 ); + #else + rc += TestMethod( po, "Set/GetDataDirectory()", x.GetDataDirectory(), "/ABCDEFG/", 9 ); + #endif + + std::cout << "cp3\n"; + + + x.SetDataDirectory( "\\ABCDEFG" ); + #ifdef WIN32 + rc += TestMethod( po, "Set/GetDataDirectory()", x.GetDataDirectory(), "\\ABCDEFG", 8 ); + #else + rc += TestMethod( po, "Set/GetDataDirectory()", x.GetDataDirectory(), "/ABCDEFG", 8 ); + #endif + + + std::cout << "cp4\n"; + + + x.SetDataDirectory( "ABCDEFG" ); + rc += TestMethod( po, "Set/GetDataDirectory()", x.GetDataDirectory(), "ABCDEFG", 7 ); + + + rc += TestMethod( po, "RemoveTblFromDbList()", x.RemoveTblFromTblList( "TestTableB" ), 0 ); + rc += TestMethod( po, "RemoveTblFromDbList()", x.RemoveTblFromTblList( "TestTableB" ), XB_NOT_FOUND ); + std::cout << "**** Next list should not have TestTableB in it ****" << std::endl; + x.DisplayTableList(); + + + rc += TestMethod( po, "RemoveTblFromDbList()", x.RemoveTblFromTblList( "TestTableA" ), 0 ); + rc += TestMethod( po, "RemoveTblFromDbList()", x.RemoveTblFromTblList( "TestTableC" ), 0 ); + rc += TestMethod( po, "RemoveTblFromDbList()", x.RemoveTblFromTblList( "TestTableD" ), 0 ); + + + delete d1; + + if( po > 0 || rc < 0 ) + fprintf( stdout, "Total Errors = %d\n", rc * -1 ); + + +#ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], rc * -1 ); + x.WriteLogMessage( sMsg ); +#endif + + + return rc; +} + diff --git a/src/tests/xb_test_uda.cpp b/src/tests/xb_test_uda.cpp new file mode 100755 index 0000000..dec41fa --- /dev/null +++ b/src/tests/xb_test_uda.cpp @@ -0,0 +1,98 @@ +/* xb_test_uda.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014, 2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the uda (user data area) functions + +// usage: xb_test_uda QUITE|NORMAL|VERBOSE + + + +#include "xbase.h" + +using namespace xb; + +#include "tstfuncs.cpp" + + +int main( int argCnt, char **av ) +{ + int iRc = 0; + //int iRc2 = 0; + int po = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + po = 0; + else if( av[1][0] == 'V' ) + po = 2; + } + + + + xbXBase x; +#ifdef XB_LOGGING_SUPPORT + x.EnableMsgLogging(); + if( po ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); +#endif + + + x.SetDataDirectory( PROJECT_DATA_DIR ); + x.EnableMsgLogging(); + + xbUda uda; + iRc += TestMethod( po, "GetTokencCnt()", uda.GetTokenCnt(), 0 ); + xbString s1; + xbString s2; + iRc += TestMethod( po, "AddTokenForKey()", uda.AddTokenForKey( "B", "BBBB" ), XB_NO_ERROR ); + s1 = "C"; + iRc += TestMethod( po, "AddTokenForKey()", uda.AddTokenForKey( s1, "CCCC" ), XB_NO_ERROR ); + s2 = "DDDD"; + iRc += TestMethod( po, "AddTokenForKey()", uda.AddTokenForKey( "D", s2 ), XB_NO_ERROR ); + + s1 = "A"; + s2 = "AAAA"; + iRc += TestMethod( po, "AddTokenForKey()", uda.AddTokenForKey( s1, s2 ), XB_NO_ERROR ); + iRc += TestMethod( po, "AddTokenForKey()", uda.AddTokenForKey( "AA", "AAAAA" ), XB_NO_ERROR ); + iRc += TestMethod( po, "AddTokenForKey()", uda.AddTokenForKey( "BB", "BBBBB" ), XB_NO_ERROR ); + iRc += TestMethod( po, "AddTokenForKey()", uda.AddTokenForKey( "CC", "CCCCC" ), XB_NO_ERROR ); + iRc += TestMethod( po, "AddTokenForKey()", uda.AddTokenForKey( "DD", "DDDDD" ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetTokencCnt()", uda.GetTokenCnt(), 8); + + iRc += TestMethod( po, "UpdTokenForKey()", uda.UpdTokenForKey( "BB", "9999" ), XB_NO_ERROR ); + iRc += TestMethod( po, "UpdTokenForKey()", uda.DelTokenForKey( "CC" ), XB_NO_ERROR ); + iRc += TestMethod( po, "GetTokencCnt()", uda.GetTokenCnt(), 7 ); + +#ifdef XB_DEBUG_SUPPORT + uda.DumpUda(); +#endif // XB_DEBUG_SUPPORT + + uda.Clear(); + iRc += TestMethod( po, "GetTokencCnt()", uda.GetTokenCnt(), 0 ); + +#ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], iRc * -1 ); + x.WriteLogMessage( sMsg ); +#endif + + return iRc; +} diff --git a/src/tests/xb_test_xbase.cpp b/src/tests/xb_test_xbase.cpp new file mode 100755 index 0000000..6dad3f7 --- /dev/null +++ b/src/tests/xb_test_xbase.cpp @@ -0,0 +1,106 @@ +/* xb_test_xbase.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014, 2022 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + +*/ + +// This program tests the class xbXBase + +// usage: xb_test_xbase QUITE|NORMAL|VERBOSE + + +#include "xbase.h" + +using namespace xb; + +#include "tstfuncs.cpp" + +int main( int argCnt, char **av ) +{ + int iRc = 0; + int po = 1; /* print option */ + /* 0 - QUIET */ + /* 1 - NORMAL */ + /* 2 - VERBOSE */ + + if( argCnt > 1 ) { + if( av[1][0] == 'Q' ) + po = 0; + else if( av[1][0] == 'V' ) + po = 2; + } + + + xbXBase x; + + +#ifdef XB_LOGGING_SUPPORT + x.EnableMsgLogging(); + if( po ){ + std::cout << "Logfile is [" << x.GetLogFqFileName().Str() << "]" << std::endl; + } + xbString sMsg; + sMsg.Sprintf( "Program [%s] initializing...", av[0] ); + x.WriteLogMessage( sMsg ); +#endif + InitTime(); + + + x.SetDefaultDateFormat( "YY-MM-DD" ); + iRc += TestMethod( po, "SetDefaultDateFormat", x.GetDefaultDateFormat(), "YY-MM-DD", 8 ); + + if( po == 2 ){ + if( x.GetEndianType() == 'L' ) + std::cout << "Little Endian Architecture" << std::endl; + else if( x.GetEndianType() == 'B' ) + std::cout << "Big Endian Architecture" << std::endl; + else + std::cout << "Undefine Endian Architecture" << std::endl; + } + + iRc += TestMethod( po, "GetErrorMessage", x.GetErrorMessage( XB_DBF_FILE_NOT_OPEN ), "DBF File Not Open", 17 ); + + +#ifdef XB_LOGGING_SUPPORT + xbString sLogDir = PROJECT_LOG_DIR; + iRc += TestMethod( po, "GetDefaultLogDirectory()", x.GetDefaultLogDirectory(), sLogDir, sLogDir.Len()); + + xbString sLogName = CMAKE_SYSTEM_NAME; + sLogName += "_"; + sLogName += XB_PLATFORM; + sLogName += ".xbLog.txt"; + iRc += TestMethod( po, "GetDefaultLogFileName()", x.GetDefaultLogFileName(), sLogName, sLogName.Len()); + + x.WriteLogMessage( "test" ); +#endif + + x.xbSleep( 250 ); + + + + if( po == 2 ){ + std::cout << "DisplayError Test ==> "; + x.DisplayError( 0 ); + } + + if( po > 0 || iRc < 0 ) + fprintf( stdout, "Total Errors = %d\n", iRc * -1 ); + + +#ifdef XB_LOGGING_SUPPORT + sMsg.Sprintf( "Program [%s] terminating with [%d] errors...", av[0], iRc * -1 ); + x.WriteLogMessage( sMsg ); +#endif + + return iRc; +} + |