EuroAssembler Index Manual Download Source Macros


Sitemap Links Forum Tests Projects

testman.htm
Data
EraseTemporaryFiles
Header
Main
RunTest

Project Test manager is the source text of a compiled 32-bit Linux executable program testman.x used to run EuroAssembler tests in Linux environment.

This utility is an alternative to the script version of the Test Manager.


Format
ELFX 32-bit FLAT CON
Platform
Linux 32-bit and 64-bit.
Build
Compile in prolin32 subdirectory in Linux with command ../euroasm.x testman.htm
eventually in Windows with command ..\euroasm.exe testman.htm.
Output
The target executable file is built as ../eatests/testman.x
Run
Execute testman.x in ../eatests/ subdirectory with command testman.x "t1234", "t13*", testman.x "*" etc.
        EUROASM Unicode=off
testman PROGRAM Format=ELFX, Width=32, Entry=Start:, OutFile="../eatests/testman.x"
          INCLUDEHEAD1 lins.htm, linsfile.htm, linf32.htm, linapi.htm, \
                       status32.htm, cpuext.htm, cpuext32.htm, string32.htm
          ; Specification of files which might be created during the test.
%TemporaryFilesExtensions %SET .asm, .i.asm, .j.asm, .k.asm, \ explicit sources,
                               .exp.lst, .htm.lst, .asm.lst, \ expected and obtained listing,
                               .exp.msg, .msg,               \ expected and obtained messages,
                               .exp.hex, .hex,               \ expected and obtained hexadecimal dump,
                               .ext                          ; object file expected extension specification.
Data
Statically declared and initialized memory variables are defined in the segment [.data] , uninitialized memory variables in the segment [.bss].
[.data]
Errorlevel: DD 0    ; 0=all tests passed, 2=some test failed, 4=file access error, 8=syntax error.
ArgCnt:     DD 0    ; Number of remaining testman.exe command-line arguments.
ArgNr:      DD 0    ; Ordinal number of testman.exe argument.
PassedCnt:  DD 0    ; Number of passed tests.
FailedCnt:  DD 0    ; Number of failed tests.
StartTime:  DD 0    ; Seconds since 1.1.1970 UTC at the start of program.
MsgHandle   DD 0    ; File handle of captured messages.
FirstFILE:          ; Array of FILE structures for temporary files.
test.htm:   DS FILE ; FILE structures for files created during testing.
mask.htm:   DS FILE
tempfile:   DS FILE
euroasm.ini DS FILE
ext %FOR %TemporaryFilesExtensions
test%ext:   DS FILE
    %ENDFOR ext
LastFILE:
HelpText:
DB 13,10
 DB 'File "testman.x" is the Linux version of program "testman"',13,10
 DB ' which will check the functionality of EuroAssembler with test files.',13,10
 DB 'Testman should be run in EuroAssembler subdirectory "eatests".',13,10
 DB 'It erases option file "euroasm.ini" in order to guarantee a stable configuration.',13,10
 DB 'The checked version of EuroAssembler is "../easource/euroasm.x" in Linux.',13,10
 DB 13,10
 DB 'The program testman will extract temporary files from the test file',13,10
 DB ' and then it will compile and link the extracted source.',13,10
 DB 'Finally it compares the obtained listing, messages and object file',13,10
 DB ' "%%test.htm.lst", "%%test.msg" and "%%test.bin"',13,10
 DB ' with expected templates stored in the files',13,10
 DB ' "%%test.exp.lst", "%%test.exp.msg" and "%%test.exp.hex".',13,10
 DB 'The output binary file is converted to hexa format before comparison.',13,10
 DB 'Test is claimed as "passed" if listing, messages and object all match.',13,10
 DB 'Temporary files are erased only when the test has succesfully passed.',13,10
 DB 13,10
 DB 'Tests may be specified as file mask(s) with wildchars "?" or "*", for instance',13,10
 DB '  ./testman.x t1234.htm t1235.htm "t42??.htm"',13,10
 DB 'File extension ".htm" as well as prefix "t" may be omitted',13,10
 DB ' but the test mask name should be in quotes, for instance',13,10
 DB ' ./testman.x "7???"  or  ./testman.x "*" (launch all tests).',13,10
CrLf DB 13,10,0
test:        DB "t????",0
mask:        DB "t????.htm",0
testWithExt  DB "t????.htm",0
Env          DB 0
Command      DB "../easource/euroasm.x",0 ; The tested version of EuroAssembler.
Parameters   DD Command
             DD testWithExt
             DD =B"TIMESTAMP=0",=B"NOWARN=0980",=B"NOWARN=0010..0170",=B"NOWARN=1160",0
Environment  DD Env,0
Error:       DB "Internal error 0x"
ErrCode:     DB "???????? accessing file ",0
AllPassed:   DB 'All '
AllTests:    DB '???? tests passed',0
PassedTests: DB '???? tests passed,'
FailedTests: DB '???? tests failed',0
Duration:    DB ' in'
Seconds:     DB '???? seconds.',13,10,0
;;
[.bss]       ; Reserved, not initialized memory.
DumpAddr:    D DWORD
DumpLine:    D  64 * BYTE
CmdLine:     D 128 * BYTE
Ext:         D  12 * BYTE  ; Extension of object file, e.g. ".lib".
Status:      D DWORD       ; Status flags in following encoding:
stFailed     = 1           ; Test failed.
stListing    = 2           ; Listing are different.
stMessages   = 4           ; Messages are different.
stObject     = 8           ; Object dumps are different.
stA          = 16          ; Assembler source <!--A--> is present in test file.
stB          = 32          ; Object dump <!--B--> is present in test file.
INVALID_HANDLE_VALUE = -1
Main
This is the program code entry which reads command-line arguments and calls subprocedure RunTest for each resolved test file.
[.text]
Start::NOP
  LinAPI time,0,Fastmode=yes
  MOV [StartTime],EAX
  GetArgCount                                    ; A macro from the library  linapi.htm.
  JNC ArgCountOK:
Help:                                            ; When testman.exe was provided with none or wrong test number.
  StdOutput HelpText
  ORB [Errorlevel],8
  JMP End:
ArgCountOK:
  MOV [ArgCnt],ECX
  JECXZ Help:                                    ; If run without arguments.
  FileAssign euroasm.ini,=B"euroasm.ini"
  FileDelete euroasm.ini                         ; Make sure that local euroasm.ini will not interfere.
NextArg:                                         ; Parse command-line arguments.
  MOV EAX,[ArgNr]
  INC EAX
  MOV [ArgNr],EAX
  GetArg EAX
  JC Help:
  ; ESI,ECX is now one command-line argument, e.g. "t1234" or "t1234.htm" or "-?". Expected "t" and max.4 digits.
  CMP ECX,9
  JA Help:
  CMP ECX,5
  JBE Below5
  MOV ECX,5
Below5:
  LEA EDX,[ESI+ECX]                              ; EDX points to the end of the input string.
  CMPB [ESI],'-'
  JE Help:
  MOV EDI,mask:+1                                ; mask DB "t????.htm",0
  MOVD [EDI],'????'                              ; Reinitialize the name mask with wildcards.
  MOV AL,'t'
  CMP [ESI],AL
  JNE NextChar:
  INC ESI
NextChar:                                        ; Digits or wildcards expected.
  CMP ESI,EDX
  JNB Mask3:                                     ; If no more characters to parse.
  LODSB
  CMP AL,'?'
  JE Mask1:
  CMP AL,'*'
  JE Mask3:
  CMP AL,'0'
  JB Help:
  CMP AL,'9'
  JA Help:                                       ; Skip nondigit and nonwild characters.
  MOV [EDI],AL
Mask1:
  INC EDI
  JMP NextChar:
Mask3:
  FileAssign mask.htm:, mask:
  FileEach mask.htm:, RunTest                    ; Perform RunTest with all wildcard-resolved files.
  DEC [ArgCnt]
  JNZ NextArg:                                   ; If provided with more than one argument.
  LinAPI time, 0
  SUB EAX,[StartTime]                            ; EAX is now the duration af all tests in seconds.
  JC Report1:
  StoD Seconds, Size=4, Align=right
Report1:
  MOV EAX,[PassedCnt]
  StoD PassedTests, Size=4, Align=right
  StoD AllTests, Size=4, Align=right
  MOV EAX,[FailedCnt]
  StoD FailedTests, Size=4, Align=right
  MOV ESI,PassedTests:
  TEST EAX                                       ; Did any test fail?
  JNZ Report2:
  MOV ESI,AllPassed:
Report2:
  ADD EAX,[PassedCnt]
  CMP EAX,1
  JNA End:                                       ; Skip the report if only one test was performed.
  StdOutput ESI,Duration
End:TerminateProgram [Errorlevel]
RunTest
This is a callback procedure which executes one test assigned in the file mask.htm and then compares the test results.
It reports test name and results on the standard output.
Input
ESI= is pointer to a zero-terminated, wildcard-resolved test file name, e.g. t1234.htm.
Called from
FileEach macro invoked at Main.Mask3:.
RunTest PROC
    MOV EDI,FirstFILE
NextFile:
    MOV [EDI+FILE.Handle],INVALID_HANDLE_VALUE
    ADD EDI,SIZE# FILE
    CMP EDI,LastFILE
    JB NextFile:
    LEA EDI,[mask.htm.Name]                      ; ./t1234.htm
    LEA ESI,[EDI+2]                              ; t1234.htm
    CMPW [ESI],'./'
    JNE .ND:
    MOV ECX,SIZE# FILE.Name-2
    REP MOVSB
.ND:MOV ECX,5
    MOV EDI,test:                                ; test: DB "t????",0
    REP MOVSB
    MOV EAX,[test:+1]
    MOV [testWithExt+1],EAX                      ; testWithExt DB "t????.htm",0
    StdOutput test:, =B" ... "
ext %FOR %TemporaryFilesExtensions
      FileAssign test%ext:, test:, =B"%ext"
    %ENDFOR ext
    CALL EraseTemporaryFiles
Erased::
    XOR EAX,EAX
    MOV [Status],EAX
    FileAssign  test.htm, test:, =B".htm"
    FileStreamOpen test.htm
    JC .Error:
.NextLine:
    FileStreamReadLn test.htm                    ; Parse test file and write its divisions to temporary files.
    JC .Error:
    JZ .CloseWrittenFiles:                       ; If no more lines.
    MOV ECX,EAX
    StripSpaces ESI,ECX
    CMPB [ESI],'<'                                                                                        ; >
    JE .Marker?:
    MOV EBX,test.exp.lst
    CMP [EBX+FILE.Handle],INVALID_HANDLE_VALUE   ; Is the file already open?
    JNZ .StoreLstLine:
    FileStreamCreate EBX
    JC .Error:
.StoreLstLine:
    FileStreamWrite EBX,ESI,ECX
    JC .Error:
    FileStreamWrite EBX,CrLf,2
    JC .Error:
    JMP .NextLine:
.Marker?:
    CMPD [ESI],'                       ; Is it the marker beginning with <!-- ?
    JNE .NextLine:
    MOV EAX,[ESI+4]
    MOV EDX,EAX
    SHR EDX,8
    CMP EDX,'-->'                                ; Is it the marker ending with --> ?
    JNE .NextLine:
    ADD ESI,8                                    ; Size of the marker.
    SUB ECX,8
    JB .Error:
    Dispatch AL, 'M','A','I','J','K','E','B'
    JMP .NextLine:                               ; Ignore other markers.
.StoreDivisionLine:
    CMP [EBX+FILE.Handle],INVALID_HANDLE_VALUE   ; It the file already open?
    JNE .StoreLine:
    FileStreamCreate EBX
    JC .Error:
.StoreLine:
    FileStreamWrite EBX,ESI,ECX
    JC .Error:
    FileStreamWrite EBX,CrLf,2
    JC .Error:
    JMP .NextLine:
.M: MOV EBX,test.exp.msg
    JMP .StoreDivisionLine:
.A: SetSt [Status],stA
    MOV EBX,test.asm
    JMP .StoreDivisionLine:
.I: MOV EBX,test.i.asm
    JMP .StoreDivisionLine:
.J: MOV EBX,test.j.asm
    JMP .StoreDivisionLine:
.K: MOV EBX,test.k.asm
    JMP .StoreDivisionLine:
.E: SetSt [Status],stB
    MOV EBX,test.ext
    JMP .StoreDivisionLine:
.B: SetSt [Status],stB
    MOV EBX,test.exp.hex
    CMP ECX,53
    JBE .B5:
    MOV ECX,53                                   ; Trim off the character column of the dump.
.B5:StripSpaces ESI,ECX
    JMP .StoreDivisionLine:
.CloseWrittenFiles:
    FileClose test.htm, test.asm, test.i.asm, test.j.asm, test.k.asm, test.ext, test.exp.lst, test.exp.msg, test.exp.hex
    JNSt [Status],stB,.ExecTest:                 ; If output object file won't be checked in this test.
    FileLoad test.ext                            ; File exists if the  marker specified output extension.
    JNC .ObjExt:
    SetSt [Status],stFailed+stObject
    JMP .ExecTest:
.ObjExt:
    MOV ECX,EAX                                  ; File size.
    StripSpaces ESI,ECX
    MOV AL,'.'
    MOV EDI,Ext:
    CMP [ESI],AL
    JE .StoreExt:
    STOSB
.StoreExt:
    REP MOVSB
    XOR EAX,EAX
    STOSB
    FileDelete test.ext
    FileAssign test.ext, test:, Ext:             ; Reassign with the extension depending on program format.
.ExecTest:                                       ; Execute the test.
    MOV EAX,".htm"
    JNSt [Status],stA,.CmdLine:
    MOV EAX,".asm"
.CmdLine:
    MOV [testWithExt+5],EAX                      ; testWithExt DB "t????.htm",0
    StdOutput CmdLine
    LinAPI open,test.msg.Name, O_RDWR+O_CREAT, 777q
    MOV [MsgHandle],EAX                          ; Usually EAX=4.
    LinAPI fork
    CMP EAX,0
    JNZ .Parent:
    ; We are in the child process after fork.
    LinAPI dup2,[MsgHandle],1    ; This instance is a child (soon euroasm.x), its stdoutput will be replaced with 4.
    LinAPI execve,Command,Parameters,Environment ; Transform itself to "euroasm.x" with the argument "testWithExt".
    ; The child process is over.
.Parent:                                         ; Here we continue in parent process (testman.x).
    LinAPI waitpid,-1,0,0                        ; Wait for the child process to terminate.
    LinAPI close,[MsgHandle]

    ; Listing, messages, hexadump and their templates were generated.
    ; Compare listing.
    MOV EBX,test.htm.lst
    JNSt [Status],stA,.LstLoad
    MOV EBX,test.asm.lst
.LstLoad:
    FileLoad EBX                                 ; Obtained listing.
    JC .LstFail:
    FileLoad test.exp.lst                        ; Expected listing.
    JC .LstFail:
    MOV ESI,[EBX+FILE.BufPtr]
    MOV ECX,[EBX+FILE.BufSize]
    MOV EDI,[test.exp.lst.BufPtr]
    CMP ECX,[test.exp.lst.BufSize]
    JNE .LstFail:
    REPE CMPSB
    JE .CmpMsg:
.LstFail:
    SetSt [Status],stFailed + stListing

.CmpMsg:; Compare messages.
    FileLoad test.msg                            ; Obtained messages.
    JC .MsgFail:
    FileLoad test.exp.msg                        ; Expected messages.
    JC .MsgFail:
    MOV ESI,[test.msg.BufPtr]
    MOV ECX,[test.msg.BufSize]
    MOV EDI,[test.exp.msg.BufPtr]
    CMP ECX,[test.exp.msg.BufSize]
    JNE .MsgFail:
    REPE CMPSB
    JE .MsgOK:
.MsgFail:
    SetSt [Status],stFailed + stMessages
.MsgOK:
    JNSt [Status],stB,.ObjOK:
    ; Compare target object executable file.
    ; Convert output file test.ext to hexadecimal dump test.hex.
    FileStreamCreate test.hex
    JC .ObjFail:
    FileLoad test.ext                            ; Obtained target binary output file.
    JC .ObjFail:
    MOV ESI,[test.ext.BufPtr]
    MOV EDX,[test.ext.BufSize]
    ADD EDX,ESI                                  ; End of the dumped data.
    MOV [DumpAddr],-16
.NextDumpLine:                                   ; Prepare one dump row into DumpLine.
    MOV EDI,DumpLine
    MOV EAX,[DumpAddr]
    ADD EAX,16
    MOV [DumpAddr],EAX
    AND EAX,0x0000FFFF
    StoH EDI,Size=4
    MOV AL,':'
    STOSB
    MOV ECX,16                                   ; Prepare max. 16 hex bytes.
.NextDumpByte:
    CMP ESI,EDX
    JNB .WriteDumpLine:
    XOR EAX,EAX
    MOV AL,' '                                   ; Space separation.
    STOSB
    LODSB
    StoH EDI,Size=2                              ; Dump one byte.
    LOOP .NextDumpByte:
.WriteDumpLine:
    SUB EDI,DumpLine                             ; Written line size.
    FileStreamWrite test.hex:, DumpLine,EDI
    FileStreamWrite test.hex, CrLf,2
    CMP ESI,EDX
    JB .NextDumpLine:
    FileClose test.hex, test.ext
    ; Compare hexadecimal dumps.
    FileLoad test.hex                            ; Obtained dump.
    JC .ObjFail:
    FileLoad test.exp.hex                        ; Expected dump.
    JC .ObjFail:
    MOV ESI,[test.hex.BufPtr]
    MOV ECX,[test.hex.BufSize]
    MOV EDI,[test.exp.hex.BufPtr]
    CMP ECX,[test.exp.hex.BufSize]
    JNE .ObjFail:
    REPE CMPSB
    JE .ObjOK:
.ObjFail:
    SetSt [Status],stFailed + stObject
.ObjOK:
    MOV EBX,test.htm.lst
    JNSt [Status],stA,.CloseExpFiles:
    MOV EBX,test.asm.lst
.CloseExpFiles:
    FileClose EBX, test.exp.lst, test.msg, test.exp.msg
    JNSt [Status],stB,.Evaluate:
    FileClose test.ext, test.hex, test.exp.hex
.Evaluate:
    JSt [Status],stFailed,.Failed:
    StdOutput ="passed.", Eol=yes
    INCD [PassedCnt]
    CALL EraseTemporaryFiles
    JMP .ObjectOK:
.Error:                                         ; EBX=^FILE
    ORB [Errorlevel],4
    MOV EAX,-1
    StoH ErrCode,Size=8
    StdOutput Error:
    LEA ESI,[EBX+FILE.Name]
    StdOutput ESI, Eol=yes
    STC                                          ; Break further FileEach wildcard resolving.
    JMP .EndRun:
.Failed:
    StdOutput ="failed:", Eol=yes
    INCD [FailedCnt]
    ORB [Errorlevel],2
    JNSt [Status],stListing,.ListingOK:
    LEA ESI,[EBX+FILE.Name]
    StdOutput ='Obtained listing "', ESI, ='" differs from expected "', \
              test.exp.lst.Name, ='".', Eol=yes
.ListingOK:
    JNSt [Status],stMessages,.MessagesOK:
    StdOutput ='Obtained message "', test.msg.Name, ='"     differs from expected "', \
              test.exp.msg.Name, ='".', Eol=yes
.MessagesOK:
    JNSt [Status],stObject,.ObjectOK:
    StdOutput ='Obtained  output "',test.hex.Name,='"     differs from expected "', \
              test.exp.hex.Name, ='".', Eol=yes
.ObjectOK:
    CLC                                          ; CF=0 to continue FileEach with the next test.
.EndRun:
    RET
  ENDP RunTest
EraseTemporaryFiles
Files with extensions declared in the Header are deleted.
Only the file with extension .htm (test source) survives.
Called from
RunTest before the test is performed, and after it has passed OK. Temporary files remain when the test failed.
EraseTemporaryFiles PROC                         ; Delete all test*.* files except for test.htm.
   FileAssign tempfile, test:, =B"*"             ; test: DB "t????",0
   FileEach tempfile, EraseTempfile
   RET
EraseTempfile PROC                               ; Callback from FileEach to erase one FILE EBX whose name is at ESI.
       GetLength$ ESI
       CMP ECX,9
       JNE .Erase:
       MOV EAX,[ESI+5]
       OR EAX,0x20202000                         ; Convert the resolved file extension to lower case.
       CMP EAX,".htm"
       JE .Skip:                                 ; Do not delete the test file itself.
.Erase:FileDelete EBX
.Skip: RET                                       ; CF=0 to continue with FileEach.
     ENDPROC EraseTempfile
   ENDPROC EraseTemporaryFiles
 ENDPROGRAM testman

▲Back to the top▲