Files
harbour-core/contrib/hbtest/core.prg
Viktor Szakats 9f16c2bf8e 2017-08-13 18:27 UTC Viktor Szakats (vszakats users.noreply.github.com)
* *
    * update copyright headers with new FSF postal address
    * COPYING.txt -> LICENSE.txt (rest of repo to be synced)
2017-08-13 18:38:59 +00:00

266 lines
7.8 KiB
Plaintext

/*
* Regression tests for the runtime library
*
* Copyright 1999-2013 Viktor Szakats (vszakats.net/harbour)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file LICENSE.txt. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA (or visit https://www.gnu.org/licenses/).
*
* As a special exception, the Harbour Project gives permission for
* additional uses of the text contained in its release of Harbour.
*
* The exception is that, if you link the Harbour libraries with other
* files to produce an executable, this does not by itself cause the
* resulting executable to be covered by the GNU General Public License.
* Your use of that executable is in no way restricted on account of
* linking the Harbour library code into it.
*
* This exception does not however invalidate any other reasons why
* the executable file might be covered by the GNU General Public License.
*
* This exception applies only to the code released by the Harbour
* Project under the name Harbour. If you copy code from other
* Harbour Project or Free Software Foundation releases into a copy of
* Harbour, as the General Public License permits, the exception does
* not apply to the code that you add in this way. To avoid misleading
* anyone as to the status of such modified files, you must delete
* this exception notice from them.
*
* If you write modifications of your own for Harbour, it is your choice
* whether to permit this exception to apply to your modifications.
* If you do not wish that, delete this exception notice.
*
*/
#include "error.ch"
#define TEST_RESULT_COL1_WIDTH 1
#define TEST_RESULT_COL2_WIDTH 11
#define TEST_RESULT_COL3_WIDTH 44
#define TEST_RESULT_COL4_WIDTH 85
THREAD STATIC t_hParams := { => }
PROCEDURE hbtest_Setup( cName, xValue )
IF HB_ISSTRING( cName ) .AND. ! Empty( cName )
IF PCount() > 1
t_hParams[ cName ] := xValue
ELSEIF cName $ t_hParams
hb_HDel( t_hParams, cName )
ENDIF
ENDIF
RETURN
PROCEDURE hbtest_Call( cBlock, bBlock, xResultExpected )
LOCAL xResult
LOCAL oError
LOCAL lPPError
LOCAL lRTE
LOCAL lFailed
LOCAL bOut
LOCAL cLangOld
IF HB_ISSTRING( cBlock )
lPPError := .F.
ELSE
cBlock := "[Preprocessor error]"
lPPError := .T.
ENDIF
cLangOld := hb_langSelect( "en" ) /* to always have RTEs in one language */
BEGIN SEQUENCE WITH ErrorBlock( {| oError | Break( oError ) } )
xResult := Eval( bBlock )
lRTE := .F.
RECOVER USING oError
xResult := ErrorMessage( oError )
lRTE := .T.
END SEQUENCE
hb_langSelect( cLangOld )
IF lRTE
lFailed := !( XToStr( xResult, .F. ) == XToStr( xResultExpected, .F. ) )
ELSE
IF !( ValType( xResult ) == ValType( xResultExpected ) )
IF HB_ISSTRING( xResultExpected ) .AND. ValType( xResult ) $ "ABOHPS"
lFailed := !( XToStr( xResult, .F. ) == xResultExpected )
ELSE
lFailed := .T.
ENDIF
ELSE
lFailed := !( xResult == xResultExpected )
ENDIF
ENDIF
IF lFailed .OR. lPPError .OR. hb_HGetDef( t_hParams, "showall", .T. )
bOut := hb_HGetDef( t_hParams, "output", {| cMsg | OutStd( cMsg ) } )
IF lFailed
Eval( bOut, ;
PadR( iif( lFailed, "!", " " ), TEST_RESULT_COL1_WIDTH ) + " " + ;
PadR( ProcName( 1 ) + "(" + hb_ntos( ProcLine( 1 ) ) + ")", TEST_RESULT_COL2_WIDTH ) + " " + ;
RTrim( cBlock ) + ;
hb_eol() + ;
Space( 5 ) + " Result: " + XToStr( xResult, .F. ) + ;
hb_eol() + ;
Space( 5 ) + "Expected: " + XToStr( xResultExpected, .F. ) + ;
hb_eol() )
ELSE
Eval( bOut, ;
PadR( iif( lFailed, "!", " " ), TEST_RESULT_COL1_WIDTH ) + " " + ;
PadR( ProcName( 1 ) + "(" + hb_ntos( ProcLine( 1 ) ) + ")", TEST_RESULT_COL2_WIDTH ) + " " + ;
PadR( cBlock, TEST_RESULT_COL3_WIDTH ) + " -> " + ;
PadR( XToStr( xResult, .F. ), TEST_RESULT_COL4_WIDTH ) + " | " + ;
XToStr( xResultExpected, .F. ) + ;
hb_eol() )
ENDIF
ENDIF
RETURN
STATIC FUNCTION ErrorMessage( oError )
LOCAL cMessage := ""
LOCAL tmp
IF HB_ISNUMERIC( oError:severity )
SWITCH oError:severity
CASE ES_WHOCARES ; cMessage += "M " ; EXIT
CASE ES_WARNING ; cMessage += "W " ; EXIT
CASE ES_ERROR ; cMessage += "E " ; EXIT
CASE ES_CATASTROPHIC ; cMessage += "C " ; EXIT
ENDSWITCH
ENDIF
IF HB_ISNUMERIC( oError:genCode )
cMessage += hb_ntos( oError:genCode ) + " "
ENDIF
IF HB_ISSTRING( oError:subsystem )
cMessage += oError:subsystem + " "
ENDIF
IF HB_ISNUMERIC( oError:subCode )
cMessage += hb_ntos( oError:subCode ) + " "
ENDIF
IF HB_ISSTRING( oError:description )
cMessage += oError:description + " "
ENDIF
IF ! Empty( oError:operation )
cMessage += "(" + oError:operation + ") "
ENDIF
IF ! Empty( oError:filename )
cMessage += "<" + oError:filename + "> "
ENDIF
IF HB_ISNUMERIC( oError:osCode )
cMessage += "OS:" + hb_ntos( oError:osCode ) + " "
ENDIF
IF HB_ISNUMERIC( oError:tries )
cMessage += "#:" + hb_ntos( oError:tries ) + " "
ENDIF
IF HB_ISARRAY( oError:Args )
cMessage += "A:" + hb_ntos( Len( oError:Args ) ) + ":"
FOR tmp := 1 TO Len( oError:Args )
cMessage += ValType( oError:Args[ tmp ] ) + ":" + XToStr( oError:Args[ tmp ], .T. )
IF tmp < Len( oError:Args )
cMessage += ";"
ENDIF
NEXT
cMessage += " "
ENDIF
IF oError:canDefault .OR. ;
oError:canRetry .OR. ;
oError:canSubstitute
cMessage += "F:"
IF oError:canDefault
cMessage += "D"
ENDIF
IF oError:canRetry
cMessage += "R"
ENDIF
IF oError:canSubstitute
cMessage += "S"
ENDIF
ENDIF
RETURN cMessage
STATIC FUNCTION XToStr( xValue, lInString )
SWITCH ValType( xValue )
CASE "N" ; RETURN hb_ntos( xValue )
CASE "D" ; RETURN iif( lInString, "0d" + iif( Empty( xValue ), "00000000", DToS( xValue ) ), 'hb_SToD( "' + DToS( xValue ) + '" )' )
CASE "U" ; RETURN "NIL"
CASE "C"
CASE "M"
xValue := __StrToExp( xValue )
RETURN iif( lInString, xValue, '"' + xValue + '"' )
CASE "A"
CASE "H"
CASE "O"
IF ! lInString
RETURN hb_ValToExp( xValue, .T. )
ENDIF
EXIT
ENDSWITCH
RETURN hb_CStr( xValue )
STATIC FUNCTION __StrToExp( cStr )
LOCAL cResult := ""
LOCAL nLen, nPos
LOCAL cByte
nLen := hb_BLen( cStr )
FOR nPos := 1 TO nLen
cByte := hb_BSubStr( cStr, nPos, 1 )
IF ! __ByteIsDisplayable( cByte ) .OR. cByte == '"'
cResult += "\" + __ByteEscape( hb_BCode( cByte ) )
ELSE
cResult += cByte
ENDIF
NEXT
RETURN cResult
STATIC FUNCTION __ByteIsDisplayable( cByte )
RETURN ;
hb_BCode( cByte ) >= 32 .AND. ;
hb_BCode( cByte ) < 128
STATIC FUNCTION __ByteEscape( nByte )
LOCAL cResult
LOCAL nExp
IF nByte == 0
RETURN "0"
ELSE
cResult := ""
FOR nExp := 2 TO 0 STEP -1
cResult += SubStr( "01234567", Int( nByte / ( 8 ^ nExp ) ) + 1, 1 )
nByte %= 8 ^ nExp
NEXT
ENDIF
RETURN cResult