From bd84a885c708616537dee201ee261320e22a8920 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Janis=20Daniel=20Da=CC=88hne?=
 <janis.daehne2@student.uni-halle.de>
Date: Thu, 6 Jun 2019 22:43:44 +0200
Subject: [PATCH] - fixed frontend issue nr. 130 - added compiler options

---
 api.php                      | 13 ++++++-----
 constants.php                |  3 ++-
 do_blackBoxTest_func.php     | 39 +++++++++++++++++---------------
 do_compareFilesTest_func.php | 39 +++++++++++++++++---------------
 do_compileTest_func.php      | 21 ++++++++++--------
 readme.md                    | 43 +++++++++++++++++++-----------------
 6 files changed, 87 insertions(+), 71 deletions(-)

diff --git a/api.php b/api.php
index 1251a4c..33c3c05 100644
--- a/api.php
+++ b/api.php
@@ -262,13 +262,14 @@ foreach ($testCases as $test) {
     }
 
     $testId = $test[$s_test_id];
-    $testContent = $test[$s_test_content];
+    $testContent = $test[$s_test_content]; //can be null or empty
     $testAssets = $test[$s_test_allAssets];
+    $compilerOptions = $test[$s_test_CompilerOptions]; //can be null or empty
 
 
     if (!isset($test[$s_test_command]) || !isset($test[$s_test_id])
         //its ok if we have test content
-        //but throw if we have no content && test type is NOT compile (compile do not need test content...)
+        //but throw if content is null (empty string is ok)
         || (!isset($test[$s_test_content]) && $test[$s_test_command] !== $s_command_compile)
     ) {
 
@@ -352,7 +353,7 @@ foreach ($testCases as $test) {
 
             try {
                 $_result = do_compile($arg_mainFileNameWithExtension, $fullWorkingDirPath, $min_compileTimeout,
-                    $compileCmd, $sourceFileExtensions, $requestDistinctionString, $showTestRunnerDebugOutput);
+                    $compileCmd, $sourceFileExtensions, $requestDistinctionString, $showTestRunnerDebugOutput, $compilerOptions);
             } catch (Exception $e) {
                 //critical error, abort execution (all other tests are likely to fail)
                 output($status_code_InternalServerError, "error executing regex test: " . $e->getMessage());
@@ -556,7 +557,8 @@ foreach ($testCases as $test) {
                         $compileCmd, $execCmd, $sourceFileExtensions, $needCompilation,
                         $maxLinesToRead, $maxErrLinesToRead, $maxLinesToWrite,
                         $requestDistinctionString,
-                        $showTestRunnerDebugOutput
+                        $showTestRunnerDebugOutput,
+                        $compilerOptions
                     );
                 } catch (Exception $e) {
                     //critical error, abort execution (all other tests are likely to fail)
@@ -573,7 +575,8 @@ foreach ($testCases as $test) {
                         $maxLinesToRead, $maxErrLinesToRead, $maxLinesToWrite,
                         ($arg_command === $s_command_justRunTest),
                         $requestDistinctionString,
-                        $showTestRunnerDebugOutput
+                        $showTestRunnerDebugOutput,
+                        $compilerOptions
                     );
                 } catch (Exception $e) {
                     //critical error, abort execution (all other tests are likely to fail)
diff --git a/constants.php b/constants.php
index 519a5cb..72cba2b 100644
--- a/constants.php
+++ b/constants.php
@@ -3,7 +3,7 @@
 # variables
 
 //use this to know which version we published
-$versionString = '2.2.0';
+$versionString = '2.3.0';
 $rootDirNameToUseString = 'work';
 
 $isDebug = false; //logs debug to STDOUT
@@ -128,6 +128,7 @@ $s_test_compileTimeoutInMs = 'compileTimeoutInMs'; # the compile timeout for the
 $s_test_memoryLimitInKb = 'memoryLimitInKb'; # the memory limit for the test
 $s_test_diskSpaceLimitInKb = 'maxDiskSpaceInKb'; # the max dis space the test can write to
 $s_test_allAssets = 'allAssets'; # the asset files
+$s_test_CompilerOptions = 'compilerOptions'; # the compiler options for the test (only for black, compile and compare files test)
 
 
 $exitCodeOutputPrefix = 'exit:';
diff --git a/do_blackBoxTest_func.php b/do_blackBoxTest_func.php
index ace0ad6..6e04891 100644
--- a/do_blackBoxTest_func.php
+++ b/do_blackBoxTest_func.php
@@ -21,6 +21,7 @@ require_once __DIR__ . '/protocolHeaderPartParser.php';
  * @param $justRun true: just run test, false: normal back box test
  * @param $uniqueSessionId string the unique session id for the test runner to handle sandbox file system management
  * @param $showTestRunnerDebugOutput 1: show internal debug output from the test runner (included in the test response)
+ * @param $compilerOptions string the options for the compiler
  * @return array the result
  * @internal param array $allFiles all files to copy in teh dir to use
  * Format: array[int] => {fileName: string, fileContent: string}
@@ -31,7 +32,8 @@ function do_blackBoxTest($mainFileNameWithExtension, $test, $fullWorkingDirPath,
                          $maxLinesToRead, $maxErrLinesToRead, $maxLinesToWrite,
                          $justRun,
                          $uniqueSessionId,
-                         $showTestRunnerDebugOutput
+                         $showTestRunnerDebugOutput,
+                         $compilerOptions
 
 
 )
@@ -84,23 +86,24 @@ function do_blackBoxTest($mainFileNameWithExtension, $test, $fullWorkingDirPath,
 
 
     $longCmd = $config['runner']
-        . ' ' . $command_to_execute_string                              # arg[0] the test method
-        . ' "' . $fullWorkingDirPath . '"'                              # arg[1] dir path
-        . ' "' . $mainFileNameWithExtension . '"'                       # arg[2] file path
-        . ' "' . $compileCmd . '"'                                      # arg[3] command to execute # currently ignored because we call compile in php...
-
-        . ' "' . $commandToExecute . '"'                                # arg[4] command to execute the test
-        . ' "' . $timeout . '"'                                         # arg[5] the timeout in ms
-        . ' "' . $compileTimeout . '"'                                  # arg[6] the compile timeout in ms
-        . ' "' . $memoryLimit . '"'                                     # arg[7] the memory limit
-        . ' "' . $diskSpaceLimit . '"'                                  # arg[8] the disk limit
-        . ' "' . implode(',', $sourceFileExtensions) . '"'         # arg[9] the source file extensions
-        . ' ' . ($needCompilation ? 'true' : 'false')                   # arg[10] true: compile program new, false: not
-        . ' "' . $maxLinesToRead . '"'                                  # arg[11] max lines to read from the user program (inclusive)
-        . ' "' . $maxErrLinesToRead . '"'                               # arg[12] max lines to read from the user program stderr (inclusive)
-        . ' "' . $maxLinesToWrite . '"'                                 # arg[13]  max lines to write to the user program (inclusive)
-        . ' "' . $uniqueSessionId . '"'                                 # arg[14] a unique session id
-        . ' "' . ($showTestRunnerDebugOutput === TRUE ? 1 : 0) . '"'    # arg[15] showTestRunnerDebugOutput
+        . ' ' . escapeshellarg($command_to_execute_string)                              # arg[0] the test method
+        . ' ' . escapeshellarg($fullWorkingDirPath)                               # arg[1] dir path
+        . ' ' . escapeshellarg($mainFileNameWithExtension)                        # arg[2] file path
+        . ' ' . escapeshellarg($compileCmd)                                       # arg[3] compile command
+
+        . ' ' . escapeshellarg($commandToExecute)                                # arg[4] command to execute the test
+        . ' ' . escapeshellarg($timeout)                                          # arg[5] the timeout in ms
+        . ' ' . escapeshellarg($compileTimeout)                                   # arg[6] the compile timeout in ms
+        . ' ' . escapeshellarg($memoryLimit)                                      # arg[7] the memory limit
+        . ' ' . escapeshellarg($diskSpaceLimit)                                   # arg[8] the disk limit
+        . ' ' . escapeshellarg(implode(',', $sourceFileExtensions))         # arg[9] the source file extensions
+        . ' ' . escapeshellarg($needCompilation ? 'true' : 'false')          # arg[10] true: compile program new, false: not
+        . ' ' . escapeshellarg($maxLinesToRead)                                   # arg[11] max lines to read from the user program (inclusive)
+        . ' ' . escapeshellarg($maxErrLinesToRead)                                # arg[12] max lines to read from the user program stderr (inclusive)
+        . ' ' . escapeshellarg($maxLinesToWrite)                                  # arg[13]  max lines to write to the user program (inclusive)
+        . ' ' . escapeshellarg($uniqueSessionId)                                  # arg[14] a unique session id
+        . ' ' . escapeshellarg(($showTestRunnerDebugOutput === TRUE ? 1 : 0))     # arg[15] showTestRunnerDebugOutput
+        . ' ' . escapeshellarg($compilerOptions)                                  # arg[8] options for the compiler
 
     ;
 
diff --git a/do_compareFilesTest_func.php b/do_compareFilesTest_func.php
index 1e344a7..88e4346 100644
--- a/do_compareFilesTest_func.php
+++ b/do_compareFilesTest_func.php
@@ -20,6 +20,7 @@ require_once __DIR__ . '/protocolHeaderPartParser.php';
  * @param $maxLinesToWrite int the max lines to write the user program (passed to the runner)
  * @param $uniqueSessionId string the unique session id for the test runner to handle sandbox file system management
  * @param $showTestRunnerDebugOutput 1: show internal debug output from the test runner (included in the test response)
+ * @param $compilerOptions string the options for the compiler
  * @return array the result
  * @internal param array $allFiles all files to copy in teh dir to use
  * Format: array[int] => {fileName: string, fileContent: string}
@@ -29,7 +30,8 @@ function do_compareFilesTest($mainFileNameWithExtension, $test, $fullWorkingDirP
                              $compileCmd, $execCmd, $sourceFileExtensions, $needCompilation,
                              $maxLinesToRead, $maxErrLinesToRead, $maxLinesToWrite,
                              $uniqueSessionId,
-                             $showTestRunnerDebugOutput
+                             $showTestRunnerDebugOutput,
+                             $compilerOptions
 
 
 )
@@ -86,23 +88,24 @@ function do_compareFilesTest($mainFileNameWithExtension, $test, $fullWorkingDirP
     }
 
     $longCmd = $config['runner']
-        . ' ' . $command_to_execute_string                           # arg[0] the test method
-        . ' "' . $fullWorkingDirPath . '"'                           # arg[1] dir path
-        . ' "' . $mainFileNameWithExtension . '"'                    # arg[2] file path
-        . ' "' . $compileCmd . '"'                                   # arg[3] command to execute # currently ignored because we call compile in php...
-        . ' "' . $commandToExecute . '"'                             # arg[4] command to execute the test
-        . ' "' . $timeout . '"'                                      # arg[5] the timeout
-        . ' "' . $compileTimeout . '"'                               # arg[6] the timeout
-        . ' "' . $memoryLimit . '"'                                  # arg[7] the memory limit
-        . ' "' . $diskSpaceLimit . '"'                               # arg[8] the disk limit
-        . ' "' . implode(',', $sourceFileExtensions) . '"'     # arg[9] the source file extensions
-        . ' ' . ($needCompilation ? 'true' : 'false')                # arg[10] true: compile program new, false: not
-        . ' "' . $maxLinesToRead . '"'                               # arg[11] max lines to read from the user program (inclusive)
-        . ' "' . $maxErrLinesToRead . '"'                            # arg[12] max lines to read from the user program stderr (inclusive)
-        . ' "' . $maxLinesToWrite . '"'                              # arg[13]  max lines to write to the user program (inclusive)
-        . ' "' . $uniqueSessionId . '"'                              # arg[14] a unique session id
-        . ' "' . ($showTestRunnerDebugOutput === TRUE ? 1 : 0) . '"' # arg[15] showTestRunnerDebugOutput
-        . ' "' . $fileHashInfo . '"'                                 # arg[16] file:hash list
+        . ' ' . escapeshellarg($command_to_execute_string)                       # arg[0] the test method
+        . ' ' . escapeshellarg($fullWorkingDirPath)                              # arg[1] dir path
+        . ' ' . escapeshellarg($mainFileNameWithExtension)                       # arg[2] file path
+        . ' ' . escapeshellarg($compileCmd)                                      # arg[3] command to execute
+        . ' ' . escapeshellarg($commandToExecute)                                # arg[4] command to execute the test
+        . ' ' . escapeshellarg($timeout)                                         # arg[5] the timeout
+        . ' ' . escapeshellarg($compileTimeout)                                  # arg[6] the timeout
+        . ' ' . escapeshellarg($memoryLimit)                                     # arg[7] the memory limit
+        . ' ' . escapeshellarg($diskSpaceLimit)                                  # arg[8] the disk limit
+        . ' ' . escapeshellarg(implode(',', $sourceFileExtensions))         # arg[9] the source file extensions
+        . ' ' . escapeshellarg($needCompilation ? 'true' : 'false')          # arg[10] true: compile program new, false: not
+        . ' ' . escapeshellarg($maxLinesToRead)                                   # arg[11] max lines to read from the user program (inclusive)
+        . ' ' . escapeshellarg($maxErrLinesToRead)                                # arg[12] max lines to read from the user program stderr (inclusive)
+        . ' ' . escapeshellarg($maxLinesToWrite)                                  # arg[13]  max lines to write to the user program (inclusive)
+        . ' ' . escapeshellarg($uniqueSessionId)                                  # arg[14] a unique session id
+        . ' ' . escapeshellarg($showTestRunnerDebugOutput === TRUE ? 1 : 0)  # arg[15] showTestRunnerDebugOutput
+        . ' ' . escapeshellarg($fileHashInfo)                                     # arg[16] file:hash list
+        . ' ' . escapeshellarg($compilerOptions)                                  # arg[8] options for the compiler
 
     ;
 
diff --git a/do_compileTest_func.php b/do_compileTest_func.php
index d22511e..513c160 100644
--- a/do_compileTest_func.php
+++ b/do_compileTest_func.php
@@ -12,6 +12,7 @@ require_once __DIR__ . '/protocolHeaderPartParser.php';
  * @param $sourceFileExtensions array the list with the file extensions from the source files for the p language
  * @param $uniqueSessionId string the unique session id for the test runner to handle sandbox file system management
  * @param $showTestRunnerDebugOutput true: show internal debug output from the test runner (included in the test response)
+ * @param $compilerOptions string the options for the compiler
  * @return array
  * Format: return_var: process exit value, output the output of the process
  * @internal param array $allFiles all files to copy in teh dir to use
@@ -21,7 +22,8 @@ function do_compile($mainFileNameWithExtension, $fullWorkingDirPath,
                     $compileTimeout,
                     $compileCmd, $sourceFileExtensions,
                     $uniqueSessionId,
-                    $showTestRunnerDebugOutput
+                    $showTestRunnerDebugOutput,
+                    $compilerOptions
 )
 {
 
@@ -44,14 +46,15 @@ function do_compile($mainFileNameWithExtension, $fullWorkingDirPath,
     $return_var = -1;
 
     $longCmd = $config['runner']
-        . ' ' . $command_to_execute_string                          # arg[0] the test method
-        . ' "' . $fullWorkingDirPath . '"'                          # arg[1] dir path
-        . ' "' . $mainFileNameWithExtension . '"'                   # arg[2] file path
-        . ' "' . $compileTimeout . '"'                             # arg[3] compile timeout in ms
-        . ' "' . $compileCmd . '"'                                  # arg[4] command to execute
-        . ' "' . implode(',', $sourceFileExtensions) . '"'     # arg[5] the source file extensions
-        . ' "' . $uniqueSessionId . '"'                             # arg[6] a unique session id
-        . ' "' . ($showTestRunnerDebugOutput === TRUE ? 1 : 0) . '"'  # arg[7] showTestRunnerDebugOutput
+        . ' ' . escapeshellarg($command_to_execute_string)                          # arg[0] the test method
+        . ' ' . escapeshellarg($fullWorkingDirPath)                                 # arg[1] dir path
+        . ' ' . escapeshellarg($mainFileNameWithExtension)                          # arg[2] file path
+        . ' ' . escapeshellarg($compileTimeout)                                     # arg[3] compile timeout in ms
+        . ' ' . escapeshellarg($compileCmd)                                         # arg[4] command to execute
+        . ' ' . escapeshellarg(implode(',', $sourceFileExtensions))           # arg[5] the source file extensions
+        . ' ' . escapeshellarg($uniqueSessionId)                                    # arg[6] a unique session id
+        . ' ' . escapeshellarg($showTestRunnerDebugOutput === TRUE ? 1 : 0)    # arg[7] showTestRunnerDebugOutput
+        . ' ' . escapeshellarg($compilerOptions)                                    # arg[8] options for the compiler
     ;
 
 
diff --git a/readme.md b/readme.md
index ba98c8f..dd02818 100644
--- a/readme.md
+++ b/readme.md
@@ -43,7 +43,7 @@ The request is a json object so the request should be from mime type application
 * **mainFileNameWithExtension**: (string) the file with the main class / entry point 
 * **testContents**: (array of objects) an array of tests  
   * **id** (int) is the id of the test to identify the test (and the related result)
-  * **content** (string/multi line string) the test content to use (depends on the used command) 
+  * **content** (string/multi line string) the test content to use (depends on the used command) [MUST NO BE EMPTY (design decision)]
   * **assets** (array) the files (assets) for the test
     * **fileName** (string) the file name for the asset. 
       * **note** that the file name must not contain the following characters: ` ` (whitespace), `:`
@@ -123,7 +123,7 @@ If the tests could be executed or to code to execute the tests is reached then t
                 "runnerVersion": "1.0.0",
                 "testResultCode": 0,
                 "protocol": "can be multiline \n\r string",
-                "testServerVersion": "1.0.0",
+                "testServerVersion": "1.0.0"
             }
         ]
     }
@@ -352,35 +352,33 @@ The commands will probably require the users files (code). This files can be acc
 
 * **#50** - contains the timeout in ms
 * **#51** - contains the memory limit in kb
-* **#52** - contains the disk space limit in kb (the progrma can write to)
+* **#52** - contains the disk space limit in kb (the program can write to)
 
-(So **#1**/**#6** would produce the same result as **#8** when the operating system (os) is unix, escaped: \"#1/#6\" = \"#8\")
+(So **#1**/**#6** would produce the same result as **#8** when the operating system (os) is unix, escaped: "#1/#6" = "#8")
 
 **Notes**
 
 - all files need an extension else they are ignored
 - if the main file has no extension then code 100 is returned and the program is not compiled/executed  
-- any `compile` and `exec` commands will be interpret by the test server (the unix user who executes the test server) so when you 
-  e.g. set `compile` to `\"echo\" \"$PATH\"` then `$PATH` will be resolved by the unix user and the test runner gets `/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games...`
+- any `compile` and `exec` commands will be executed by the test server (the unix user who executes the test server) BUT they are enclosed in `escapeshellarg` so
+  e.g. set `compile` to `"echo" "$PATH"` then `$PATH` will *NOT* be resolved by the unix
 
 #### Example (windows)
 internalName (primary key) | compile | exec | extensions
 --- | --- | --- | ---
-csharp | \\"C:\Program Files (x86)\Mono\bin\mcs.bat\\" \\"#5\\" | \\"C:\Program Files (x86)\Mono\bin\mono\\" \\"#4.exe\\"  | ["cs"]
-java | \\"C:\Program Files (x86)\JetBrains\IntelliJ IDEA 14.1.4\jdk1.8.0_65\bin\javac\\" \\"-encoding\\" \\"UTF8\\" \\"#5\\" | \\"C:\Program Files (x86)\JetBrains\IntelliJ IDEA 14.1.4\jdk1.8.0_65\bin\java\\" \\"-cp\\" \\"#1\\" \\"#2\\" | ["java"]
-python | \\"python\\" \\"-m\\" \\"py_compile\\" \\"#5\\" | \\"python\\" \\"#5\\"  | ["py"]
-php | \\"C:\xampp\php3\php.exe\\" \\"-l\\" \\"#5\\" | \\"C:\xampp\php3\php.exe\\" \\"#5\\" | ["php"]
+csharp | C:\Program Files (x86)\Mono\bin\mcs.bat "#5" | C:\Program Files (x86)\Mono\bin\mono "#4.exe"  | ["cs"]
+java | C:\Program Files (x86)\JetBrains\IntelliJ IDEA 14.1.4\jdk1.8.0_65\bin\javac -encoding UTF8 "#5" | C:\Program Files (x86)\JetBrains\IntelliJ IDEA 14.1.4\jdk1.8.0_65\bin\java -cp "#1" "#2" | ["java"]
+python | python -m py_compile "#5" | python "#5"  | ["py"]
+php | C:\xampp\php3\php.exe -l "#5" | C:\xampp\php3\php.exe "#5" | ["php"]
 
 #### Example (linux)
 internalName (primary key) | compile | exec | extensions
 --- | --- | --- | --- 
-java | \\"javac\\" \\"-encoding\\" \\"UTF8\\"  \\"#5\\" | \\"java\\" \\"-Dfile.encoding=UTF8\\" \\"-cp\\" \\"#1\\" \\"#2\\" | ["java"]
-python | \\"python\\" \\"-m\\" \\"py_compile\\" \\"#5\\" | \\"python\\" \\"#5\\" | ["py"]
+java | javac -encoding UTF8  "#5" | java -Dfile.encoding=UTF8 -cp "#1" "#2" | ["java"]
+python | python -m py_compile "#5" | python "#5" | ["py"]
 
-**Reminder** do not forget to escape evey path and arguments!
 
-
-**The compile and execute commands will be wrapped by "..." (double quotes). In order to escap paths use \\"...path...\\" (for bash shell) (see the command examples)**
+**All arguments passed to the shell are wrapped by php `escapeshellarg`, Paths (and maybe other arguments) could contain spaces, wrap them inside double quotes `"a name"`**
 
 
 # Transaction table
@@ -464,7 +462,7 @@ the following settings can be set through the db ()`useConfigFromDb` and connect
 * **maxParallelTests**: (int) the max amount of parallel running tests, if more tests are requested they are rejected with an busy error (use this with the hard limits in the db to calculate the max ressource usage), **set this to 0 or a negative value to no limit the amount of parallel tests**
 * **maxNumberOfTestsWithOneRequest**: (int) the number of tests that can be run with one request (only the first X tests will be executed ... the other will be ignored), this is used to limit the time a user can occupy the test server
 
-* **runner** : (string) the shell/cmd command to execute in order to start the Runner (paths needs to be properly escaped) (you might need to use absolute paths)  
+* **runner** : (string) the shell/cmd command to execute in order to start the Runner (paths with whitespaces needs to be properly escaped via `"path 1"`) (you might need to use absolute paths)  
   **For Java** you probably want UTF8 encoding... there is a command line argument for that, add  
   -Dfile.encoding=UTF8  
   after the java executable (else the user program would be called with utf8 encoding but the test runner cannot handle UTF8)
@@ -477,7 +475,7 @@ the following settings can be set through the db ()`useConfigFromDb` and connect
 
 * **environmentVars** : (string, \r\n or \n separated, key value pairs are separated by = OR NULL) the environment variables for the test runner. All environment vars are cleared and only these are set (even if this is the empty string). The special delimiters `\n` and `=` must not be used inside keys or values. 
   The test runner is called and these environment variables are set.
-  You can use `"path""` to escape paths or other strings
+  You can use `"path""` to escape paths with whitespaces
   It is recommended that you at least specify the following: `USER, HOME ,PATH`
   * `USER` is the executing user e.g. `yapextester`
   * `HOME` is the home path for the executing user e.g. `/home/yapextester`
@@ -562,7 +560,9 @@ arg[14] = a unique session id (e.g. used with firejail to manage overlay fs name
 arg[15] = "true" to enable debug output (this will leak internal paths!!) or "false" to disable debug output. 
 The debug output will be normal lines starting with " [Test-Runner]"
 
-## Compile Test or Syntaxtest
+arg[16] = (**string**) options for the compiler (whitespace separated like normal program args, whitespaces could be escaped by `-a "-b c"`)
+
+## Compile Test (or Syntax Test)
 method name: **compileTest**
 
 arg[1] = the directory containing all files (the main file)
@@ -573,14 +573,16 @@ arg[3] = the compile timeout in ms
 
 arg[4] = the compile command to execute
 
-arg[5] = contains a list of extensions of the soruce files for the p lang (differentiate beteen source files and assets). This is a "," separated list
+arg[5] = contains a list of extensions of the source files for the p lang (differentiate beteen source files and assets). This is a "," separated list
 e.g. "cpp, h"
 
-arg[6] = a unique session id 
+arg[6] = (string) a unique session id 
 
 arg[7] = "true" to enable debug output (this will leak internal paths!!) or "false" to disable debug output.
 The debug output will be normal lines starting with " [Test-Runner]"
 
+arg[8] = (string) options for the compiler (whitespace separated like normal program args, whitespaces could be escaped by `-a "-b c"`)
+
 ## Regex Test
 method name: **regexTest**
 
@@ -637,6 +639,7 @@ arg[16] = "file1:hash1 file2:hash2" a list of `file:hash` pairs separated with a
 These are the files for the test (the assets) with the pre calculated hash or `null` (if not pre calculated).
 The test runner decides of the hash needs to be calculated or not (only files that should be compared need to be hashed).
 
+arg[17] = (**string**) options for the compiler (whitespace separated like normal program args, whitespaces could be escaped by `-a "-b c"`)
 
 ## For all tests
 
-- 
GitLab