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.
prolin32subdirectory in Linux with command
../euroasm.x testman.htm
..\euroasm.exe testman.htm
.../eatests/testman.x
../eatests/subdirectory with command
testman.x "t1234", "t13*"
, testman.x "*"
etc.
The header defines program format, imported libraries, used temporary files.
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]
, 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
[.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 localeuroasm.iniwill 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]
mask.htmand then compares the test results.
t1234.htm.
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
.htm(test source) survives.
EraseTemporaryFiles PROC ; Delete alltest*.*files except fortest.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