#include "ORD.CH" #define CRLF Chr(13)+Chr(10) #define MAX_TEST_RECS 100 #define INDEX_KEY_CHAR CHAR + Str( NUM ) + DTOS( DATE ) #define INDEX_KEY_NUM NUM #define INDEX_KEY_DATE DATE #define INDEX_KEY_LOG LOG EXTERNAL _ADS EXTERNAL DBFNTX EXTERNAL DBFCDX procedure Main( cRDDType, cAdsMode ) local cRDD, aStruct, xTemp, bMemoText field CHAR, NUM, DATE, LOG bMemoText := { || "This is memo #" + LTrim( Str( RecNo() ) ) + "." + CRLF + ; CRLF + ; "This is a very long string. " + ; "This may seem silly however strings like this are still " + ; "used. Not by good programmers though, but I've seen " + ; "stuff like this used for Copyright messages and other " + ; "long text. What is the point to all of this you'd say. " + ; "Well I am coming to the point right now, the constant " + ; "string is limited to 256 characters and this string is " + ; "a lot bigger. Do you get my drift ? If there is somebody " + ; "who has read this line upto the very end: Esto es un " + ; "sombrero grande rid­culo." + CRLF + "/" + CRLF + "[;-)" + CRLF + "\" } do case case Empty( cRDDType ) NotifyUser( "Usage: TESTRDD RDDTYPE [ADSMODE]" + CRLF + ; CRLF + ; "RDDTYPE = DBFNTX, DBFCDX, ADSCDX, ADSNTX or ADSADT" + CRLF + ; CRLF + ; "ADSMODE = LOCAL or SERVER (only applies to ADSCDX, ADSNTX and ADSADT)" + CRLF + ; "(If specify SERVER, must be run from a drive suported by ADS server)", .t. ) case Left( cRDDType := Upper( AllTrim( cRDDType ) ), 3 ) == "ADS" // Do not include ADS.CH as don't want unintended affects when not using // ADS - If need behavior from ADS.CH, include defines and undefs in // these areas. #define ADS_LOCAL_SERVER 1 #define ADS_REMOTE_SERVER 2 #define ADS_NTX 1 #define ADS_CDX 2 #define ADS_ADT 3 RDDRegister( "ADS", 1 ) RDDSetDefault( "ADS" ) if Empty( cADSMode ) NotifyUser( "Missing ADS mode" ) endif cADSMode := Upper( AllTrim( cADSMode ) ) do case case cADSMode == "LOCAL" ; AdsSetServerType( ADS_LOCAL_SERVER ) case cADSMode == "SERVER" ; AdsSetServerType( ADS_REMOTE_SERVER ) otherwise ; NotifyUser( "Bad ADS mode" ) endcase do case case cRDDType == "ADSNTX" ; AdsSetFileType( ADS_NTX ) ; cRDD := "ADSNTX" case cRDDType == "ADSADT" ; AdsSetFileType( ADS_ADT ) ; cRDD := "ADSADT" case cRDDType == "ADSCDX" ; AdsSetFileType( ADS_CDX ) ; cRDD := "ADSCDX" otherwise ; NotifyUser( "Bad ADS flavor" ) endcase AdsLocking( .t. ) AdsRightsCheck( .t. ) AdsSetDefault( "" ) AdsSetSearchPath( "" ) #undef ADS_LOCAL_SERVER #undef ADS_REMOTE_SERVER #undef ADS_NTX #undef ADS_CDX #undef ADS_ADT case cRDDType == "DBFCDX" .or. ; cRDDType == "DBFNTX" RDDSetDefault( cRDD := cRDDType ) otherwise NotifyUser( "Bad DBF flavor" ) endcase // Delete TEST.* since may be changing RDD flavors (avoid conflicts) AEval( Directory( "TEST.*" ), { | a | FErase( a[1] ) } ) AEval( Directory( "TEST?.*" ), { | a | FErase( a[1] ) } ) if File( "TEST.DBF" ) NotifyUser( "Cannot delete TEST.DBF" ) endif // TEST: DBCreate() DBCreate( "TEST.DBF", ; aStruct := { { "CHAR", "C", 30, 0 }, ; { "NUM", "N", 15, 3 }, ; { "DATE", "D", 8, 0 }, ; { "LOG", "L", 1, 0 }, ; { "MEMO", "M", 10, 0 } } ) if .not. File( "TEST.DBF" ) NotifyUser( "Failed to create TEST.DBF" ) endif // TEST: DBUseArea()/USE use TEST.DBF new shared alias MYTEST if .not. Alias() == "MYTEST" NotifyUser( "Failed to open TEST.DBF" ) endif // TEST: RDDName() if .not. RDDName() == cRDD NotifyUser( "Failed to set RDD to " + cRDD ) endif // TEST: DBStruct() if .not. CompareArray( aStruct, DBStruct() ) NotifyUser( "Resulting table structure is not what we asked for" ) endif // TEST: Header() if .not. Header() == 194 NotifyUser( "Header() returned wrong size (" + LTrim( Str( Header() ) ) + " bytes)" ) endif // Add a mix of data to table do while LastRec() < MAX_TEST_RECS // TEST: DBAppend()/APPEND BLANK append blank // TEST: REPLACE replace CHAR with Chr( 65 + Val( SubStr( LTrim( Str( RecNo() ) ), 2, 1 ) ) ) + ; " RECORD " + LTrim( Str( RecNo() ) ) // TEST: Direct field assigment MYTEST->NUM := ( if( RecNo() % 2 > 0, -1, 1 ) * RecNo() ) + ( RecNo() / 1000 ) MYTEST->DATE := Date() + Int( FIELD->NUM ) MYTEST->LOG := ( FIELD->NUM < 0 ) MYTEST->MEMO := Eval( bMemoText ) enddo // TEST: LastRec() if .not. LastRec() == MAX_TEST_RECS NotifyUser( "DbAppend and/or LastRec failed" ) endif // TEST: DbGoBotom()/GO BOTTOM go bottom if .not. RecNo() == MAX_TEST_RECS NotifyUser( "DbGoBottom failed" ) endif // TEST: DbGoTop()/GO TOP go top if .not. RecNo() == 1 NotifyUser( "DbGoTop failed" ) endif // Now check each and every record for accuracy do while .not. EOF() // TEST: Field access if .not. Trim( FIELD->CHAR ) == Chr( 65 + Val( SubStr( LTrim( Str( RecNo() ) ), 2, 1 ) ) ) + ; " RECORD " + LTrim( Str( RecNo() ) ) .or. ; .not. FIELD->NUM == ( if( RecNo() % 2 > 0, -1, 1 ) * RecNo() ) + ( RecNo() / 1000 ) .or. ; .not. FIELD->DATE == Date() + Int( FIELD->NUM ) .or. ; .not. FIELD->LOG == ( FIELD->NUM < 0 ) .or. ; .not. FIELD->MEMO == Eval( bMemoText ) NotifyUser( "Data in table is incorrect" ) endif skip enddo // TEST: Index creation index on INDEX_KEY_CHAR to TESTC index on INDEX_KEY_NUM to TESTN additive index on INDEX_KEY_DATE to TESTD additive index on INDEX_KEY_LOG to TESTL additive // TEST: IndexOrd() if .not. IndexOrd() == 4 NotifyUser( "Bad IndexOrd()" ) endif // TEST: DBOI_KEYCOUNT set order to 1 if .not. DbOrderInfo( DBOI_KEYCOUNT ) == MAX_TEST_RECS NotifyUser( "Bad DBOI_KEYCOUNT/1" ) endif set order to 2 if .not. DbOrderInfo( DBOI_KEYCOUNT ) == MAX_TEST_RECS NotifyUser( "Bad DBOI_KEYCOUNT/2" ) endif set order to 3 if .not. DbOrderInfo( DBOI_KEYCOUNT ) == MAX_TEST_RECS NotifyUser( "Bad DBOI_KEYCOUNT/3" ) endif set order to 4 if .not. DbOrderInfo( DBOI_KEYCOUNT ) == MAX_TEST_RECS NotifyUser( "Bad DBOI_KEYCOUNT/4" ) endif // TEST: Character index set order to 1 go top if .not. DbOrderInfo( DBOI_KEYVAL ) == INDEX_KEY_CHAR NotifyUser( "Bad DBOI_KEYVAL (CHAR)" ) endif // TEST: Positive index key set order to 2 locate for FIELD->NUM > 0 if .not. DbOrderInfo( DBOI_KEYVAL ) == INDEX_KEY_NUM NotifyUser( "Bad DBOI_KEYVAL (NUM)" ) endif // TEST: Negative index key set order to 2 locate for FIELD->NUM < 0 if .not. DbOrderInfo( DBOI_KEYVAL ) == INDEX_KEY_NUM NotifyUser( "Bad DBOI_KEYVAL (NUM)" ) endif // TEST: Date index set order to 3 go bottom if .not. DbOrderInfo( DBOI_KEYVAL ) == INDEX_KEY_DATE NotifyUser( "Bad DBOI_KEYVAL (DATE)" ) endif // TEST: Logical index set order to 4 go top if .not. DbOrderInfo( DBOI_KEYVAL ) == INDEX_KEY_LOG NotifyUser( "Bad DBOI_KEYVAL (LOG/1)" ) endif go bottom if .not. DbOrderInfo( DBOI_KEYVAL ) == INDEX_KEY_LOG NotifyUser( "Bad DBOI_KEYVAL (LOG/2)" ) endif // TEST: EXACT with a locate set order to 0 set exact on locate for FIELD->CHAR = "J RECORD" if .not. EOF() NotifyUser( "LOCATE with EXACT ON failed" ) endif set exact off locate for FIELD->CHAR = "J RECORD" if EOF() NotifyUser( "LOCATE with EXACT OFF failed" ) endif // TEST: EXACT with an index (also tests COUNT) set exact on set order to 0 count for Trim( FIELD->CHAR ) = "A RECORD 1" to xTemp // Get proper count index on CHAR to TESTE for Trim( FIELD->CHAR ) = "A RECORD 1" additive if .not. DbOrderInfo( DBOI_KEYCOUNT ) == xTemp NotifyUser( "Bad conditional index count with EXACT ON" ) endif set exact off set order to 0 count for Trim( FIELD->CHAR ) = "A RECORD 1" to xTemp // Get proper count index on CHAR to TESTE for Trim( FIELD->CHAR ) = "A RECORD 1" additive if .not. DbOrderInfo( DBOI_KEYCOUNT ) == xTemp NotifyUser( "Bad conditional index count with EXACT OFF" ) endif // // // ********************************************* // P U T M O R E R D D T E S T S H E R E // ********************************************* // // // // TEST: DBCloseArea() MYTEST->( DBCloseArea() ) if Select( "MYTEST" ) > 0 NotifyUser( "Failed to close table" ) endif NotifyUser( "Test PASSED! :-)", .t. ) return procedure ErrorSys() ErrorBlock( { |e| MyError( e ) } ) return static procedure MyError( e ) local cTrace := "", i := 1 /*Start are "real" error*/, cErr cErr := "Runtime error" + CRLF + ; CRLF + ; "Gencode: " + LTrim( Str( e:GenCode ) ) + CRLF + ; "Desc: " + e:Description + + CRLF + ; "Sub-system: " + LTrim( Str( e:SubCode ) ) + CRLF + ; CRLF + ; "Call trace:" + CRLF + ; CRLF do while .not. Empty( ProcName( ++i ) ) cErr += Trim( ProcName( i ) ) + "(" + Ltrim( Str( ProcLine( i ) ) ) + ")" + CRLF enddo NotifyUser( cErr ) // Calls quit return static function CompareArray( a1, a2 ) local i, j if .not. Len( a1 ) == Len( a2 ) return .f. endif for i := 1 to Len( a1 ) for j := 1 to Len( a1[i] ) if .not. a1[i,j] == a2[i,j] return .f. endif next next return .t. static procedure NotifyUser( cErr, lNotError ) ? cErr Quit // If remove this, will display all error without stopping return