📄 hutils.tpl
字号:
REM hUtils.tpl -- File logging and testing utilities for OPL testing.
REM Copyright (c) 1999-2000 Symbian Ltd. All rights reserved.
REM Portions from T_UTIL by Howard Price, May 1990.
REM v0.26
DECLARE EXTERNAL
INCLUDE "Const.oph"
INCLUDE "System.oxh"
INCLUDE "hUtils.oph"
REM Private functions.
EXTERNAL _hInit:
EXTERNAL _hDoLog%:(aData$)
EXTERNAL _hOpenLog%:
EXTERNAL _hLogErrorFormat$:(aErr%,aErrx$)
EXTERNAL _hLogErrorProcname$:(aErr$)
EXTERNAL _hLogPrepareToUse%:(aFlag%)
EXTERNAL _hLogPrepareToStop:(aFlag%)
EXTERNAL _hException:(a1$,a2$,a3$)
EXTERNAL _hErrorCount%: REM Total number of errors detected.
EXTERNAL _hPreTestCheck%:
EXTERNAL _hPostTestCheck%:
EXTERNAL _hCheckDrawables%:
EXTERNAL _hCheckScreen%:
EXTERNAL _hDescendTree%:(aPath$)
EXTERNAL _hFileLaunch%:(aOpofilename$)
EXTERNAL _hFileIsOpo%:(aPath$)
EXTERNAL _hFilename$:(aOpofilename$)
EXTERNAL _hFilenameExt$:(aPath$)
EXTERNAL _hDirname$:(aPath$)
EXTERNAL _hBasename$:(aPath$)
EXTERNAL _hSetTestFileDesc%:(aPath$)
EXTERNAL _hSetTestProcDesc%:(aPath$)
EXTERNAL _hLogLevelText$:(aLevel%)
EXTERNAL _hThreadId$: REM Thread Id of this program.
REM Private constants
REM Levels and Ids e.g. Test "Crystal\Color\Sprite test99:"
REM indicates kTestFileDesc="Crystal\Color\Sprite",
REM using Sprite.tpl and Test99: is the proc being CALLed.
CONST _KhLogProcSep$=":"
CONST _KhLogDirSep$="\"
PROC hLogUsage:
dINIT "'hUtils' is not designed to run stand-alone"
dTEXT "","Logging and testing procedures are called by applications"
dTEXT "","Use LOADM ""KLogTestUtil$"" to make the procedures available"
DIALOG
ENDP
PROC hLog%:(aLevel%,aData$)
REM Logs Data$ to text log file, provided the logging level
REM is lower than the current threshold. Returns any error value.
EXTERNAL hLogThreshold%
EXTERNAL _hThreadId$
LOCAL err%
LOCAL data$(KMaxStringLen%)
REM Lose it if its too low...
IF aLevel%>hLogThreshold%
RETURN KErrNone%
ENDIF
REM data$=LogConvert$:(aData$)
REM Write out the thread Id, then the logged text, then the CR/LF pair.
data$=_hThreadId$+": "+aData$+CHR$(13)+CHR$(10)
err%=_hDoLog%:(data$)
RETURN err%
ENDP
PROC hLink:(aCallbackProcName$,aThreadId&,aUserFlag%)
REM The main procedure.
REM !!TODO Document these globals.
GLOBAL hLogThreshold% REM Current log priority threshold.
GLOBAL hCallVerbose% REM !!TODO dunno???
GLOBAL _hTestFileDesc$(255) REM Test OPO/APP ???
GLOBAL _hTestProcDesc$(255)
GLOBAL _hTestRoot$(255) REM Root of current suite. e.g. "\MyTests"
GLOBAL _hTestNumber% REM
GLOBAL _hErrorCount% REM Total number of errors detected.
REM Initialisation flag settings.
REM Boolean flags true for the following conditions:
GLOBAL _hDebugMode% REM Test harness code running in debug mode.
GLOBAL _hDryRunOnly% REM No tests to be executed--harness will descend test tree but not run tests.
GLOBAL _hManualControl% REM User offered control before each test runs.
GLOBAL _hStartAtTest% REM Testing begins midway into suite.
GLOBAL _hStopAtFirstError% REM Stop test harness if a test raises an error.
GLOBAL _hLocalErrorHandling% REM A target app using harness will handle errors itself.
GLOBAL _hSpoofTargetName$(255) REM Name of target app.
GLOBAL _hSpoofTargetThread& REM Thread id of target app.
GLOBAL _hThreadId$(5) REM Harness user id in "12345" format.
REM Screen size
GLOBAL _hgWidth%,_hgHeight%
_hgWidth%=gWIDTH :_hgHeight%=gHEIGHT
_hThreadId$=RIGHT$("0000"+GEN$(aThreadId&,5),5)
_hInit:
_hLogPrepareToUse%:(aUserFlag%)
REM No error handling around here, otherwise we lose the
REM benefits of standalone testing under TextEd.
@(aCallbackProcName$): REM Call back to the tester.
_hLogPrepareToStop:(aUserFlag%)
BUSY OFF
ENDP
PROC hThreadIdFromOplDoc&:
REM Return the thread id of current app.
LOCAL prev&
RETURN SyThreadIdFromOpenDoc&:(CMD$(1),prev&)
ENDP
PROC hThreadIdFromOplAppUid&:(aUid&)
REM Thread id of app whose UID is aUid&.
LOCAL prev&
RETURN SyThreadIdFromAppUid&:(aUid&,prev&)
ENDP
PROC hLogChangeThreshold%:(aNewLevel%)
REM Change the threshold level at which log notes are
REM written to the log file. Returns the old level.
REM The smaller the level, the less info logged.
EXTERNAL hLogThreshold%
LOCAL oldLevel%,delta$(255)
oldLevel%=hLogThreshold%
hLogThreshold%=aNewLevel%
REM Report when going more verbose. Heck, report all the time.
delta$=_hLogLevelText$:(oldLevel%)+" to "+_hLogLevelText$:(aNewLevel%)
hLog%:(KhLogAlways%,"Logging threshold level changed from "+delta$+".")
RETURN oldLevel%
ENDP
PROC hLogTimestamp:
REM Time/date stamp for simple timing.
hLog%:(KhLogAlways%,DATIM$)
ENDP
PROC hTestNumber%:
REM Return current test number.
EXTERNAL _hTestNumber%
RETURN _hTestNumber%
ENDP
PROC hTestDesc$:
REM Return test description.
EXTERNAL _hTestFileDesc$,_hTestProcDesc$
REM Running standalone?
IF _hTestFileDesc$=""
RETURN _hTestProcDesc$
ENDIF
RETURN _hTestFileDesc$+" "+_hTestProcDesc$
ENDP
PROC hRunTest%:(aProcname$)
REM Automatic execution of the proc named aProcname.
EXTERNAL hCallVerbose%
EXTERNAL _hDebugMode%
EXTERNAL _hTestDesc$()
EXTERNAL _hTestNumber%
EXTERNAL _hDryRunOnly%,_hStartAtTest%,_hStopAtFirstError%
EXTERNAL _hErrorCount%
EXTERNAL _hLocalErrorHandling%
REM !!TODO manual mode?
REM Copy of current test id.
_hSetTestProcDesc%:(aProcname$+_KhLogProcSep$)
_hTestNumber%=_hTestNumber%+1
REM Are we skipping?
IF _hStartAtTest%
IF _hStartAtTest%>_hTestNumber%
hLog%:(hCallVerbose%, "Skipping test "+GEN$(hTestNumber%:,6)+" '"+hTestDesc$:+"'")
RETURN
ENDIF
ENDIF
hLog%:(hCallVerbose%, "Test "+GEN$(hTestNumber%:,6)+" '"+hTestDesc$:+"'")
REM Bit of feedback...
BUSY "Test "+GEN$(hTestNumber%:,6)+" '"+hTestDesc$:+"'", KBusyBottomRight%
IF NOT _hLocalErrorHandling%
ONERR ErrorHandlerCall::
ENDIF
IF NOT _hDryRunOnly%
IF _hDebugMode%
_hPreTestCheck%:
ENDIF
@(aProcName$):
IF _hDebugMode%
_hPostTestCheck%:
ENDIF
ENDIF
RETURN
ErrorHandlerCall::
ONERR OFF
hLog%:(KhLogAlways%, "!!! ERROR: test "+GEN$(hTestNumber%:,6)+" '"+hTestDesc$:+"'")
hLog%:(KhLogAlways%, _hLogErrorFormat$:(ERR,ERRX$))
_hErrorCount%=_hErrorCount%+1
IF _hStopAtFirstError%
RAISE ERR
ENDIF
ENDP
PROC hCall%:(aProcname$)
REM Call the proc aProcname$ in an interactive program.
REM To be used by log users only.
EXTERNAL hCallVerbose%, _hLocalErrorHandling%
rem hLog%:(hCallVerbose%, "Calling '"+aProcname$+"'")
IF NOT _hLocalErrorHandling%
ONERR ErrorHandlerCall::
ENDIF
@(aProcName$):
RETURN
ErrorHandlerCall::
ONERR OFF
hLog%:(KhLogAlways%, "!!! ERROR: target proc '"+aProcname$+"'")
hLog%:(KhLogAlways%, _hLogErrorFormat$:(ERR,ERRX$))
ENDP
PROC hCleanUp%:(aCleanUpProcname$)
REM Execute the clean-up proc named in aCleanUpProcname$
EXTERNAL hCallVerbose%
EXTERNAL _hTestDesc$()
EXTERNAL _hTestNumber%
EXTERNAL _hDryRunOnly%,_hStartAtTest%
EXTERNAL _hErrorCount%
REM !!TODO manual mode?
REM Copy of current test id.
_hSetTestProcDesc%:(aCleanUpProcname$+_KhLogProcSep$)
rem _hTestNumber%=_hTestNumber%+1
REM Are we skipping?
IF _hStartAtTest%
IF _hStartAtTest%>_hTestNumber%
rem hLog%:(hCallVerbose%, "Skipping test "+GEN$(hTestNumber%:,6)+" '"+hTestDesc$:+"'")
RETURN
ENDIF
ENDIF
hLog%:(hCallVerbose%, "Test "+GEN$(hTestNumber%:,6)+" '"+hTestDesc$:+"' [CleanUp]")
ONERR ErrorHandlerCall::
IF NOT _hDryRunOnly%
@(aCleanUpProcName$):
ENDIF
RETURN
ErrorHandlerCall::
ONERR OFF
hLog%:(KhLogAlways%, "!!! ERROR: in test "+GEN$(hTestNumber%:,6)+" '"+hTestDesc$:+"'")
hLog%:(KhLogAlways%, _hLogErrorFormat$:(ERR,ERRX$))
_hErrorCount%=_hErrorCount%+1
ENDP
PROC hStartTestHarness:(aRoot$)
REM Start executing a test suite whose location is the folder aRoot$
EXTERNAL _hTestRoot$
_hTestRoot$=aRoot$
IF RIGHT$(_hTestRoot$,1)<>"\"
_hTestRoot$=_hTestRoot$+"\"
ENDIF
hLog%:(KhLogAlways%,"Test harness starting at "+_hTestRoot$)
_hDescendTree%:(aRoot$)
ENDP
PROC hDiskName$:
REM Harness disk name e.g. "c:"
LOCAL off%(6),p$(255),disk$(255)
p$=PARSE$(CMD$(1),"",off%())
IF off%(KParseAOffPath%)>1
disk$=LEFT$(p$,off%(KParseAOffPath%)-1)
ELSE
disk$="c:"
ENDIF
RETURN disk$
ENDP
PROC hRunningUnderSystemTestApp%:
REM Bool returning True if running under system test.
EXTERNAL _hTestRoot$
IF LEN(_hTestRoot$)
RETURN KTrue%
ELSE
RETURN KFalse%
ENDIF
ENDP
PROC hInitTestHarness:(aFlag1%,aFlag2%)
REM Change test harness flags.
EXTERNAL _hDebugMode%
EXTERNAL _hDryRunOnly%,_hManualControl%,_hStartAtTest%
EXTERNAL _hStopAtFirstError%, _hLocalErrorHandling%
IF aFlag1% AND KhInitDebugMode%
_hDebugMode%=KTrue%
hLog%:(KhLogAlways%,"Init: KhInitDebugMode% set.")
hLog%:(KhLogAlways%,"Entering debug mode.")
ELSEIF aFlag1% AND KhInitDryRunOnly%
_hDryRunOnly%=KTrue%
hLog%:(KhLogAlways%,"Init: KhInitDryRunOnly% set.")
hLog%:(KhLogAlways%,"Dry run only.")
ELSEIF aFlag1% AND KhInitManualControl%
_hManualControl%=KTrue%
hLog%:(KhLogAlways%,"Init: KhInitManualControl% set.")
hLog%:(KhLogAlways%,"Manual control.")
ELSEIF aFlag1% AND KhInitStartAtTestNumber%
_hStartAtTest%=aFlag2%
hLog%:(KhLogAlways%,"Init: KhInitStartAtTestNumber% set.")
hLog%:(KhLogAlways%,"Starting at test "+GEN$(_hStartAtTest%,5)+".")
ELSEIF aFlag1% AND KhInitStopAtFirstError%
_hStopAtFirstError%=KTrue%
hLog%:(KhLogAlways%,"Init: KhInitStopAtFirstError% set.")
hLog%:(KhLogAlways%,"Stop at first error.")
ELSEIF aFlag1% AND KhInitLocalErrorHandling%
_hLocalErrorHandling%=KTrue%
hLog%:(KhLogAlways%,"Init: KhInitLocalErrorHandling% set.")
hLog%:(KhLogAlways%,"Target app will handle errors itself.")
ENDIF
ENDP
PROC hSpoofRunTargetApp&:(aLib$,aDoc$,aTail$,aCmd&)
REM Launch a target app, which may receive spoofed keys.
REM "OPL","","RZ:\System\Opl\Toolbar.opo",2
REM "Data","Z:\System\Data\Help","",0
EXTERNAL _hSpoofTargetName$
EXTERNAL _hSpoofTargetThread&
LOCAL thread&
LOCAL targetFilename$(255)
REM Identify the app that will receive the key events.
IF LOWER$(aLib$)="opl"
_hSpoofTargetName$=aTail$
targetFilename$=RIGHT$(_hSpoofTargetName$,LEN(_hSpoofTargetName$)-1)
ELSE
_hSpoofTargetName$=aLib$
targetFilename$=aLib$
ENDIF
REM Check the target exists.
IF NOT EXIST (targetFilename$)
hLog%:(KhLogAlways%,"Target not found: "+targetFilename$)
RAISE KErrNotExists%
ENDIF
thread&=SyRunApp&:(aLib$,aDoc$,aTail$,aCmd&)
hLog%:(KhLogAlways%, "Thread "+GEN$(thread&,5)+" is "+_hSpoofTargetName$)
PAUSE KhLaunchDelay%
IF aCmd&=KSyRunAppBackground%
REM !!TODO push it to background????
ENDIF
REM Store target thread.
_hSpoofTargetThread&=thread&
RETURN thread&
ENDP
PROC hSpoofCloseApp%:
REM Close a launched app.
LOCAL previous&
LOCAL thread&
thread&=hSpoofTargetThread&:
hLog%:(KhLogMedium%,"hSpoofCloseApp%: running.")
hLog%:(KhLogMedium%,"EndTask&:("+GEN$(thread&,6)+") called.")
previous&=0
SyKillTask&:(thread&,previous&)
REM !!TODO Try EndTask&: before KillTask&: as it's nicer.
REM !!TODO Handle any errors here, like the thread already being dead.
rem Finally, bring the test harness to the foreground...
hHarnessSetForeground:
ENDP
PROC hSpoofTargetName$:
REM Return the current spoof app name.
EXTERNAL _hSpoofTargetName$
REM Returns the name of the current receiver app.
RETURN _hSpoofTargetName$
ENDP
PROC hSpoofTargetThread&:
EXTERNAL _hSpoofTargetThread&
REM Returns the thread id of the current receiver app.
RETURN _hSpoofTargetThread&
ENDP
PROC hSpoofSetFlagTargetApp%:(aTargetApp$,aDeleteFlag%)
LOCAL lockfile$(255),err%,handle%
LOCAL ret% REM first error detected, if any.
rem lockfile$=_hBasename$:(aTargetApp$)+_hFilenameExt$:(aTargetApp$)+".flag"
lockfile$=aTargetApp$+".flag"
TRAP DELETE lockfile$
IF aDeleteFlag%
err%=ERR
IF err%
hLog%:(KhLogAlways%,"Error: '"+ERR$(err%)+"' when deleting "+lockfile$)
ret%=err%
ENDIF
RETURN ret%
ENDIF
err%=IOOPEN(handle%,lockfile$,KIoOpenModeCreate% OR KIoOpenFormatBinary%)
IF err%
hLog%:(KhLogAlways%,"Error: '"+ERR$(err%)+"' when creating "+lockfile$)
IF NOT ret%
ret%=err%
ENDIF
ENDIF
err%=IOCLOSE(handle%)
IF err%
hLog%:(KhLogAlways%,"Error: '"+ERR$(err%)+"' when closing "+lockfile$)
IF NOT ret%
ret%=err%
ENDIF
ENDIF
RETURN ret%
ENDP
PROC hSpoofGetFlagTargetApp%:(aTargetApp$)
LOCAL lockfile$(255)
lockfile$=aTargetApp$+".flag"
IF EXIST(lockfile$)
RETURN KTrue%
ENDIF
RETURN KFalse%
ENDP
PROC hSendString&:(aBuffer$)
REM Send a string to the current spoof target.
LOCAL ret&,len%,i%
len%=LEN(aBuffer$)
i%=1
WHILE i%<=len%
ret&=hSendKeyRich&:(ASC(MID$(aBuffer$,i%,1)),0,0,0)
i%=i%+1
ENDWH
PAUSE KhSendStringDelay%
RETURN ret&
ENDP
PROC hSendKey&:(aCode&)
LOCAL ret&
ret&=hSendKeyRich&:(aCode&,0,0,0)
PAUSE KhSendKeyDelay%
RETURN ret&
ENDP
PROC hSendKeyRich&:(aCode&,aScancode&,aMod&,aRpt&)
LOCAL prev&
PAUSE KhSendKeyRichDelay%
prev&=0
rem hLog%:(KhLogAlways%,"hSendKeyRich&: sending code="+GEN$(aCode&,5)+ " sc="+GEN$(aScanCode&,3)+" mod="+GEN$(aMod&,3)+ " rpt="+GEN$(aRpt&,3)+" to thread "+GEN$(hSpoofTargetThread&:,6)+".")
RETURN SySendKeyEventToApp&:(hSpoofTargetThread&:, prev&, aCode&, aScanCode&, aMod&, aRpt&)
ENDP
REM Quick shortcuts...
PROC hSpace%:
hSendKey&:(KKeySpace%)
ENDP
PROC hTab%:
hSendKey&:(KKeyTab%)
ENDP
PROC hEsc%:
hSendKey&:(KKeyEsc%)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -