@echo off java -cp ../../zbnfjax/zbnf.jar org.vishia.jztxtcmd.JZtxtcmd %0 :: -t:result/testAll.jz.output.txt REM instead uses <+:create> if "%NOPAUSE%" == "" pause exit /B ==JZcmd== Class FileSystem = org.vishia.util.FileSystem; ##contains some nice static methods. String const scriptStringEmpty; ##Example for a script level Java instance which is able to found in the given classpath of the JRE: Obj scriptObj = new org.vishia.jztxtcmd.JZtxtcmdUserExample(text); String scriptString = "scriptStringFirst"; String const scriptStringConst = "scriptStringConst"; String scriptStringSet2 = "string2"; set TEST="Env-TEST"; ##This routine creates an output file instead the given standard output. sub createOutputFile() { cd &scriptdir; ##The script dir should be the current one, independent of operation system's current dir. ##set current dir to create the output file locally to the script file: mkdir result; ##create if not exist. //debug; //Obj testFile = File:result; ## "result" is the file path. if(File:"result".isDirectory()){ <+out>ok<.+n>; } //debug; <+:create>result/testAll.jzcmd.out.txt<.+>; ##write all <+>output<.+> to it. <+>All output of executing the <&scriptfile> will be written in this file. Refer to the scriptfile which statements are used. search for the parts "==subroutine()==" <.+n> } main(){ call createOutputFile(); //Note: comment it to execute special tests: call testAll(); //copy special tests //call testText(); } sub testAll(){ call TestScriptVarAccess.test(); call testBatch(); call testErrorlevel(); call testOutputTextIndent(); call testDebugErrorMsg(); call testErrorToOutput(); call testThrow(); call TestErrorSub.test(); call TestExceptionInException.method(); call testDataAccess(); call testMethodInvoke(); call testCalctime(); call testVariableDatapath(); call testText(); //call testDebug(); //call TestResult.exec(); //call TestCmdWindows.test(); //call testFile(); //call testStringBuffer(); //call testNumeric(); //call testIf(); //call testJavaNew(); //call testContainer(); //call testEnv(); //call TestChangeDir.exec(); //call TestThread.exec(); //call testIpset(); <+out>done testAll.jz.cmd<.+n> onerror { <+>Test faulty: <&error><.+n> } } class TestScriptVarAccess { sub test() { //debug; <+out>TestScriptVarAccess ... <.+> <+> ==testScriptVarAccess()== A scriptvariable is copied locally, changes are effective only locally. But if jzcmd.scriptVariables().scriptString is set, it is effective in the script: <.+> <+:n>Text in a script variable: scriptString = <&scriptString><.+> scriptString = "new text"; ##this has only an effect inside this subroutine: <+:n>Changed: scriptString = <&scriptString><.+> if(scriptString != "new text"){ <+:n>!!!ERROR TestScriptVarAccess 1 !!! <.+> } call otherMethod(cmp = "scriptStringFirst"); ##to check the scriptvariable jzcmd.scriptVariables().scriptString = "changed on script level"; call otherMethod(cmp = "changed on script level"); ##to check the scriptvariable <+><.+n> <+out>ok<.+n> onerror { <+>Test faulty: <&error><.+n> <+out>ERROR see output file. <.+n> } } sub otherMethod(String cmp) { <+:n>In other method: scriptString = <&scriptString><.+> if(scriptString != cmp){ <+:n>!!!ERROR TestScriptVarAccess <&cmp>!!!<.+n> } } } sub testBatch(){ <+out>testBatch ... <.+> <+> ==testBatch()== This example creates an batchfile in this script and executes it then. It works for MS-Windows. The batch 'myBatch.bat' contains a 'dir' cmd which's output is redirected in a newly created text file 'out.txt'. After execution this JZcmd subroutine evaluates the 'out.txt'. It searches the line containing 'myBatch' and shows it. <.+> currdir = <:><&scriptdir>/..<.>; <+> ::::'''Variantes of currdir''': ::::jzcmd.scriptLevel.currdir = <&jzcmd.scriptLevel.currdir> ::::jzcmd.currdir() = <&jzcmd.currdir()> ::::jzcmdsub.currdir = <&jzcmdsub.currdir> ::::jzcmdsub.currdir() = <&jzcmdsub.currdir()> ::::jzcmdsub.sCurrdir = <&jzcmdsub.sCurrdir> <.+> Openfile bat = "myBatch.bat"; ##opens in current directory <+bat> echo off dir >out.txt call otherbatch.bat <.+close> <+:n>executes myBatch.bat, creates out.txt in the current directory ...<.+> cmd cmd.exe /C myBatch.bat; <+:n>evaluates 'out.txt': <.+> Stringjar sdir = FileSystem.readFile(File:out.txt); ##reads the file. if(sdir.seek("myBatch").line().found()){ String line = sdir.getCurrentPart(); <+><&line><.+n> } <+out>ok<.+n> onerror { <+>Test faulty: <&error><.+n> <+out>ERROR see output file. <.+n> } } sub testErrorlevel() { <+out>testErrorLevel ... <.+> <+> ==testErrorlevel()== <.+> List testErrorlevels; testErrorlevels += "1"; testErrorlevels += "2"; testErrorlevels += "3"; testErrorlevels += "5"; for(level: testErrorlevels){ ##to procude an errorlevel from a cmd invocation create a batch routine: Openfile bat = "error.bat"; <+bat>exit <&level><.+close> cmd cmd.exe /C error.bat; throw on errorlevel 5; <+>testErrorlevel(): <&jzcmdsub.cmdErrorlevel> < 5 <.+n> if errorlevel 2 { <+>testErrorlevel(): <&jzcmdsub.cmdErrorlevel> >= 2 <.+n> } ## onerror cmd { <+>testErrorlevel(): exeception handling <.+n> } } <+out>ok<.+n> onerror { <+>Test faulty: <&error><.+n> <+out>ERROR see output file. <.+n> } } sub testOutputTextIndent() { <+out>testOutputTextIdent ... <.+> <+> ==testOutputTextIndent()== <.+> <+><: > ## without emtpy line First line left aligned Second line left aligned Third line left aligned forth line 2 spaces, <: > continue of forth line, one space fifth line left aligned. <.+> <+out>ok<.+n> onerror { <+>Test faulty: <&error><.+n> <+out>ERROR see output file. <.+n> } } sub testCausesError(){ <+>Variable not exists: <&faultyVariable><.+n> } sub testDebugErrorMsg(){ <+out>testDebugErrorMsg ... <.+> <+> ==testDebugErrorMsg()== <.+> call testCausesError(); <+>This statment is skipped on error<.+n> onerror{ <+out>ok<.+n> <+>onerror block executed for this test: <&error><.+n> } } ##It shows how to handle errors while generating text sub testErrorToOutput(){ <+out>testErrorToOutput ... <.+> <+> :::==testErrorToOutput()== <.+> errortoOutput; ##with this statement an error text will be written into the output text with <?? ... error ??> <+> ::: In this text expression an unknown variable will be accessed. ::: Because 'errorToOutput' was set, the error hint will be produced in this output text: ::: <&unknown> <.+n> errortoOutput off; ##with this statement an exception is thrown on the unknown variable, executes the onerror-block then. <+> ::: In this text expression an unknown variable will be accessed too. ::: But because 'errorToOutput off' was set, the execution is aborted and the 'onerror' block is entered: ::: <&unknown> <.+n> onerror{ <+>Error: <&error> The error with stacktrace: <&jzcmdsub.excStacktraceinfo()> <.+n> } <+out>ok<.+n> ##all onerror handlings are expected! } sub testThrow() { <+out>testThrow ... <.+> <+> :::==testThrow()== :::A throw statement will be execute. <.+> <+>test throw...<.+n> throw "this is the throw text"; <+>further statement skipped!<.+n> onerror{ <+>onerror block: error: <&error> :::Error with stacktrace: <&jzcmdsub.excStacktraceinfo()> <.+> } <+out>ok<.+n> ##all onerror handlings are expected! } class TestErrorSub { sub causeError(){ String xx = nonexistVariable; //causes error, not caught here. } sub test(){ <+out>testErrorSub ... <.+> <+> ==TestErrorSub.test()== <.+> call TestErrorSub.causeError(); <+out>ok<.+n>; onerror { <+>TestErrorSub - onerror reached: <&error> <.+n>; } <+out>ok<.+n> ##all onerror handlings are expected! } } class TestExceptionInException { sub methodinner(){ String xx = nonexistVariable; //causes error, not caught here. onerror{ <+>TestExceptionInException with errorneous: <&unknownVariable><.+n> onerror{ <+>An inner onerror catches the error in an error handling: <&error><.+n> } } String x2 = nonexistVariable; //causes error, not caught here. onerror{ <+>Second error is not catched: <&unknownVariable><.+n> } } sub method() { <+out>testExceptionInException ... <.+> <+> ==TestExceptionInException== <.+> call methodinner(); onerror{ <+>An onerror block in an outer routine should be correct: <&error><.+n> } <+out>ok<.+n> ##all onerror handlings are expected! } } ##checks the access to a String in a Java user class: sub testDataAccess(){ <+out>testDataAccess ... <.+> <+:n>==testDataAccess()==<.+> <+:n>Text in a user Java instance: scriptObj.simpleTestString = <&scriptObj.simpeTestString><.+> scriptObj.simpeTestString = "new text"; ##sets a String in the users class. <+:n>Changed scriptObj.simpeTestString = "new text"; result = <&scriptObj.simpeTestString><.+> if(scriptObj.simpeTestString != "new text"){ <+:n>!!!ERROR testDataAccess !!! <.+> } //create a new variable inside a container in a Java user class. String scriptObj.testVariables.inUserData = "test in users data"; <+><.+n> <+out>ok<.+n> onerror { <+>Access ERROR in script: <&error><.+> <+out>ERROR see output file. <.+n> } } ##searches the correct method by arguments. sub testMethodInvoke(){ <+out>testMethodInvoke ... <.+> <+> ==testMethodInvoke()== <.+> Obj obj = java new org.vishia.zcmd.JZcmdUserExample(text); //obj.methodTest(5,8); //obj.methodTest(5*Math.PI,8+5); ##Converts to an absolute file with currdir obj.methodTest(File: "myFile"); obj.methodTest(File: path/myFile.ext); ## invokes methodTest(char) obj.methodTest("string argument"); //obj.methodTest('a'); ##TODO 'a' as Character does not accept as char argument. //obj.methodTest('b'-1); ##TODO check and fix it. //obj.methodTest(65+32); //obj.methodTest(0x61); obj.methodTest("a"); ## invokes methodTest(String) obj.methodTest(<:>content of <&obj><.>); <+out>ok<.+n> onerror { <+>Access ERROR in script: <&error><.+> <+out>ERROR see output file. <.+n> } } sub testCalctime(){ <+out>testCalcTime ... <.+> <+> ==testCalctime()== <.+> <+>Start...<.+n> Num starttime = System.currentTimeMillis(); Num i = 1; do{ scriptObj.testCalctimeMethodInvocation(i); i = i + 1; } while(i < 1000); Num endtime = System.currentTimeMillis(); Num timediff = endtime - starttime; <+>Time = <&timediff> ms. <.+n> <+out>ok<.+n> onerror { <+>Access ERROR in script: <&error><.+> <+out>ERROR see output file. <.+n> } } sub testVariableDatapath() { <+out>testVariableDatapath ... <.+> <+> ==testVariableDatapath()== <.+> Map map; String map.varA = "valA"; ## example for data tree String map.varB = "valB"; String map.varC = "valC"; String select = "B"; ## any selection input String path = <:>map.var<&select><.>; ##build the path with text expression String result1 = &(path); ##access with variable datapath <+><&result1><.+n> String datafieldname = <:>var<&select><.>; ##build a field name for selection String result2 = &map.&(datafieldname); ##access with variable field name. <+><&result2><.+n> <+out>ok<.+n> onerror { <+>Access ERROR in script: <&error><.+> <+out>ERROR see output file. <.+n> } } sub testText() { <+out>testText ... <.+> <+><: > ==testText()== 1. line without indentation. It starts before indentation point in the script. 2. line without indentation. It starts exactly on indentation point. 3. line has 2 spaces indentation. It starts after the indentation point. ::::4. line without indentation with :::: in script. ::::::::5. line without indentation with more :::::: in script. :: 6. line with 2 spaces indentation because it starts after indentation chars. :::::::: 7. line with 2 spaces indentation. It starts after the indentation chars though there are longer as indentation point in the script. ++++++: 8. line starts with a colon as first char after ++++ indentation. =====9. line without indentation =+10. line starts with a '+' because first char after another indentation char though before indentation point. <.+> String text1 = <:>text1 scriptdir = <:scriptdir> may have a second line, same indentation rules like <+> 3. line with 2 spaces indentation. ====4. line no indentation <.>; String text2 = "constant text"; <+><: > assigment text1 = <&text1> text2 = <&text2>; <.+> <+out>ok<.+n> onerror { <+>Access ERROR in script: <&error><.+> <+out>ERROR see output file. <.+n> } }