java -cp ../../zbnfjax/zbnf.jar org.vishia.zcmd.JZcmd testAll.jz.bat -t:testAll.jz.output.txt
exit /B


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.zcmd.JZcmdUserExample(text);

String scriptString = "scriptStringFirst";
String const scriptStringConst = "scriptStringConst";

String scriptStringSet2 = "string2";

set TEST="Env-TEST";

  call TestScriptVarAccess.test();
  call testBatch();              <+out>TEST 2<.+n>
  call testErrorlevel();          <+out>TEST 3<.+n>
  call testOutputTextIndent();   <+out>TEST 4<.+n>
  call testDebugErrorMsg();       <+out>TEST 5<.+n>
  call testErrorToOutput();       <+out>TEST 6<.+n>
  call TestErrorSub.test();        <+out>TEST 7<.+n>
  call TestExceptionInException.method(); <+out>TEST 8<.+n>
  call testDataAccess();
  call testMethodInvoke();         <+out>TEST 9<.+n>
  call testCalctime();           <+out>testCalctime<.+n>
  call testVariableDatapath();   <+out>testVariableDatapath<.+n>
  call testText();               <+out>testText<.+n>
  //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();

class TestScriptVarAccess

  sub test() {
      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
  sub otherMethod(String cmp) { 
    <+:n>In other method: scriptString = <&scriptString><.+>
    if(scriptString != cmp){ <+:n>!!!ERROR TestScriptVarAccess <&cmp>!!!<.+n> }

sub testBatch(){

    This example creates an batchfile 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 in the line containing 'myBatch' in the 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()>
 Openfile bat = "myBatch.bat";  ##opens in current directory
   echo off
   dir >out.txt
   call otherbatch.bat
 <+: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.
   String line = sdir.getCurrentPart();

sub 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>

sub 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.

sub testCausesError(){
  <+>Variable not exists: <&faultyVariable><.+n>

sub testDebugErrorMsg(){
  call testCausesError();
  <+>This statment is skipped on error<.+n>
  onerror{ <+>Any error in 'testDebugErrorMsg': <&error><.+n> }

##It shows how to handle errors while generating text
sub testErrorToOutput(){
  errortoOutput;       ##with this statement an error text will be written into the output text with 
  <+>unknown variable: <&unknown><.+n>
  errortoOutput off;   ##with this statement an exception is thrown on the unknown variable, executes the onerror-block
  <+>unknown variable: <&unknown><.+n>
    <+>there is an error: <&error>
      The error with stacktrace: <&jzcmdsub.excStacktraceinfo()>
  <+>test throw...<.+n>
  throw "text";
  <+>further statement skipped!<.+n>
  onerror{ <+>error throw: <&error><.+n> }  

class TestErrorSub 
  sub causeError(){
    String xx = nonexistVariable;  //causes error, not caught here.
  sub test(){
    call TestErrorSub.causeError();
      <+>TestErrorSub - onerror reached: <&error> <.+n>


class TestExceptionInException

  sub methodinner(){
    String xx = nonexistVariable;  //causes error, not caught here.
      <+>TestExceptionInException with errorneous: <&unknownVariable><.+n>
        <+>An inner onerror catches the error in an error handling: <&error><.+n>

    String x2 = nonexistVariable;  //causes error, not caught here.
      <+>Second error is not catched: <&unknownVariable><.+n>
  sub method()
  { <+>==TestExceptionInException==<.+n>
    call methodinner();
      <+>An onerror block in an outer routine should be correct: <&error><.+n>


##checks the access to a String in a Java user class:
sub 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";   
  onerror {
    <+>Access ERROR in script: <&error><.+>

##searches the correct method by arguments.
sub testMethodInvoke(){
  Obj obj = new org.vishia.zcmd.JZcmdUserExample(text);

  ##Converts to an absolute file with currdir
  obj.methodTest(File: "myFile");  
  obj.methodTest(File: path/myFile.ext);  

  ## invokes methodTest(char)
  obj.methodTest("x", "text");
  ## invokes methodTest(String)
  obj.methodTest(<:>content of <&obj><.>);


sub testCalctime(){

  Class Tester = org.vishia.test.TestCalctime_sin;
  Obj tester = java new org.vishia.test.TestCalctime_sin();
  //Obj y = new org.vishia.test.TestCalctime_sin.Double_ab();
  Num starttime = System.currentTimeMillis();
  Num i = 1;
    i = i + 1;
  } while(i < 1000);
  Num endtime = System.currentTimeMillis();
  Num timediff = endtime - starttime;
  <+>Time = <&timediff> ms. <.+n>

sub 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 

  String datafieldname = <:>var<&select><.>;  ##build a field name for selection
  String result2 = &map.&(datafieldname);     ##access with variable field name.


sub testText()
  String text1 = <:>text1 scriptdir = <:scriptdir><.>;
  String text2 = "constant text";