@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>
}
}