diff --git a/compiler.jar b/compiler.jar
index bfd15780e..2ea33b521 100644
Binary files a/compiler.jar and b/compiler.jar differ
diff --git a/docs/openaf-flags.md b/docs/openaf-flags.md
index ff15172c6..43313a03b 100644
--- a/docs/openaf-flags.md
+++ b/docs/openaf-flags.md
@@ -38,6 +38,12 @@ Central list of noteworthy runtime flags and environment variables.
| OAF_SIGNATURE_KEY | (unset) | Public key for signature validation |
| OAF_VALIDATION_STRICT | false | Require integrity + signature both |
+## Server Management
+
+| Env | Default | Purpose |
+|-----|---------|---------|
+| OAF_PIDFILE | (unset) | Override PID file path in ow.server.checkIn |
+
## Misc Performance / Behavior
| Flag | Purpose |
diff --git a/docs/openaf.md b/docs/openaf.md
index 2e807a21c..110d732d3 100644
--- a/docs/openaf.md
+++ b/docs/openaf.md
@@ -483,6 +483,7 @@ ow.sec.closeMainSBuckets();
ow.loadServer();
// Process management
+// Note: The PID file path can be overridden by setting the OAF_PIDFILE environment variable
var isRunning = ow.server.checkIn("server.pid",
function(existingPid) {
log("Server already running with PID: " + existingPid);
diff --git a/js/mdtablesort.js b/js/mdtablesort.js
index 770c2963e..32d491d69 100644
--- a/js/mdtablesort.js
+++ b/js/mdtablesort.js
@@ -193,6 +193,68 @@ function parseNumberWithUnits(value) {
return numberPart * multiplier;
}
+// Parse a semantic version string and return normalized components.
+function parseSemVer(value) {
+ if (value === null || value === undefined) return null;
+ const cleaned = String(value).trim();
+ if (!cleaned) return null;
+
+ const match = cleaned.match(
+ /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/
+ );
+ if (!match) return null;
+
+ return {
+ major: parseInt(match[1], 10),
+ minor: parseInt(match[2], 10),
+ patch: parseInt(match[3], 10),
+ prerelease: match[4] ? match[4].split('.') : []
+ };
+}
+
+function isNumericIdentifier(value) {
+ return /^\d+$/.test(value);
+}
+
+// Compare semantic versions according to SemVer precedence rules.
+function compareSemVer(a, b) {
+ if (a.major !== b.major) return a.major < b.major ? -1 : 1;
+ if (a.minor !== b.minor) return a.minor < b.minor ? -1 : 1;
+ if (a.patch !== b.patch) return a.patch < b.patch ? -1 : 1;
+
+ const aHasPre = a.prerelease.length > 0;
+ const bHasPre = b.prerelease.length > 0;
+ if (!aHasPre && !bHasPre) return 0;
+ if (!aHasPre) return 1;
+ if (!bHasPre) return -1;
+
+ const len = Math.max(a.prerelease.length, b.prerelease.length);
+ for (let i = 0; i < len; i++) {
+ const ai = a.prerelease[i];
+ const bi = b.prerelease[i];
+
+ if (ai === undefined) return -1;
+ if (bi === undefined) return 1;
+ if (ai === bi) continue;
+
+ const aiNum = isNumericIdentifier(ai);
+ const biNum = isNumericIdentifier(bi);
+
+ if (aiNum && biNum) {
+ const aNum = parseInt(ai, 10);
+ const bNum = parseInt(bi, 10);
+ if (aNum !== bNum) return aNum < bNum ? -1 : 1;
+ continue;
+ }
+
+ if (aiNum && !biNum) return -1;
+ if (!aiNum && biNum) return 1;
+ return ai < bi ? -1 : 1;
+ }
+
+ return 0;
+}
+
// Add helper function to support "yyyy-MM-dd HH:mm:ss" format.
function parseDate(str) {
// If the string contains a space but no 'T', replace the first space with 'T'
@@ -262,6 +324,16 @@ function sortTable(table) {
let valA = cellA ? cellA.textContent.trim() : '';
let valB = cellB ? cellB.textContent.trim() : '';
+ // Attempt semantic version parsing before generic date/string checks
+ const semverA = parseSemVer(valA);
+ const semverB = parseSemVer(valB);
+ if (semverA && semverB) {
+ const semverCmp = compareSemVer(semverA, semverB);
+ if (semverCmp < 0) return crit.direction === 'asc' ? -1 : 1;
+ if (semverCmp > 0) return crit.direction === 'asc' ? 1 : -1;
+ continue;
+ }
+
// Attempt date parsing first
const timeA = parseDate(valA);
const timeB = parseDate(valB);
diff --git a/js/openaf.js b/js/openaf.js
index 03efb85ae..9089c51dc 100644
--- a/js/openaf.js
+++ b/js/openaf.js
@@ -256,7 +256,8 @@ var __flags = ( typeof __flags != "undefined" && "[object Object]" == Object.pro
merge : true,
jsonParse: true,
listFilesRecursive: true,
- colorify : true
+ colorify : true,
+ restart : true
},
WITHMD: {
htmlFilter: true
@@ -4504,8 +4505,13 @@ const stopOpenAFAndRun = function(aCommandLineArray, addCommand) {
* element will be use sequentially to build the command line to start a new OpenAF instance.
* preCommandLineArray can be used to provide java arguments if defined.
*
+ *
*/
const restartOpenAF = function(aCommandLineArray, preLineArray, noStop) {
+ if (__flags.ALTERNATIVES.restart) {
+ endOpenAFAndStartOpenAF(aCommandLineArray, preLineArray, noStop)
+ return
+ }
var javaBin = java.lang.System.getProperty("java.home") + java.io.File.separator + "bin" + java.io.File.separator + "java";
var currentJar = getOpenAFJar();
@@ -4540,7 +4546,7 @@ const restartOpenAF = function(aCommandLineArray, preLineArray, noStop) {
var builder = new java.lang.ProcessBuilder(command);
builder.inheritIO();
- builder.start();
+ builder.start()
if (!noStop) java.lang.System.exit(0);
}
@@ -4559,6 +4565,81 @@ const forkOpenAF = function(aCommandLineArray, preLineArray) {
});
}
+const __quotePosixArg = aArg => "'" + String(aArg).replace(/'/g, "'\"'\"'") + "'"
+const __quoteCmdArg = aArg => {
+ var s = String(aArg)
+ if (s.length == 0) return "\"\""
+ if (/[\s"&|<>^()%!]/.test(s)) return "\"" + s.replace(/(["^%!])/g, "^$1") + "\""
+ return s
+}
+
+/**
+ *
+ * endOpenAFAndStart(aCommandLineArray, noStop)
+ * Terminates the current OpenAF execution while trying to execute the commands on the aCommandLineArray
+ * in detached mode. On Unix systems it uses nohup (and setsid if available). On Windows it uses cmd start.
+ *
+ */
+const endOpenAFAndStart = function(aCommandLineArray, noStop) {
+ _$(aCommandLineArray).isArray().$_("Please provide a command line array.")
+ noStop = _$(noStop).isBoolean().default(false)
+ if (aCommandLineArray.length <= 0) throw "Please provide a non-empty command line array."
+
+ var osName = String(java.lang.System.getProperty("os.name")).toLowerCase()
+ var isWindows = osName.indexOf("windows") >= 0
+ var commandLine = []
+
+ if (isWindows) {
+ var cmd = "start \"\" /B " + aCommandLineArray.map(__quoteCmdArg).join(" ")
+ commandLine = [ "cmd", "/c", cmd ]
+ } else {
+ var cmd = aCommandLineArray.map(__quotePosixArg).join(" ")
+ var shellCmd = "(command -v setsid >/dev/null 2>&1 && nohup setsid " + cmd + " >/dev/null 2>&1 < /dev/null || nohup " + cmd + " >/dev/null 2>&1 < /dev/null) &"
+ commandLine = [ "/bin/sh", "-c", shellCmd ]
+ }
+
+ var builder = new java.lang.ProcessBuilder(commandLine.map(s => new java.lang.String(s)))
+ builder.start()
+ sleep(100, true)
+ if (!noStop) java.lang.System.exit(0)
+}
+
+/**
+ *
+ * endOpenAFAndStartOpenAF(aCommandLineArray, preCommandLineArray, noStop)
+ * Terminates the current OpenAF execution and tries to start a detached OpenAF process with the current
+ * OpenAF command line plus an extra aCommandLineArray. preCommandLineArray can be used to provide java arguments.
+ *
+ */
+const endOpenAFAndStartOpenAF = function(aCommandLineArray, preLineArray, noStop) {
+ if (isDef(aCommandLineArray)) _$(aCommandLineArray).isArray().$_("Please provide a command line array.");
+ noStop = _$(noStop).isBoolean().default(false);
+
+ var javaBin = java.lang.System.getProperty("java.home") + java.io.File.separator + "bin" + java.io.File.separator + "java";
+ var currentJar = getOpenAFJar();
+ if (!currentJar.endsWith(".jar")) return;
+
+ var command = [];
+ command.push(String(javaBin));
+
+ if (isDef(preLineArray)) {
+ for (var c in preLineArray) command.push(String(preLineArray[c]));
+ } else {
+ var ar = java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments();
+ for (var ari = 0; ari < ar.size(); ari++) command.push(String(ar.get(ari)));
+ }
+
+ command.push("-jar");
+ command.push(String(currentJar));
+
+ for (var i in __args) command.push(String(__args[i]));
+ if (isDef(aCommandLineArray)) {
+ for (var ai in aCommandLineArray) command.push(String(aCommandLineArray[ai]));
+ }
+
+ return endOpenAFAndStart(command, noStop);
+}
+
/**
*
* compare(X, Y) : Boolean
@@ -8513,7 +8594,8 @@ const $jsonrpc = function (aOptions) {
_debug("jsonrpc command set to: " + cmd)
return _r
},
- exec: (aMethod, aParams, aNotification) => {
+ exec: (aMethod, aParams, aNotification, aExecOptions) => {
+ aExecOptions = _$(aExecOptions, "aExecOptions").isMap().default({})
switch (aOptions.type) {
case "dummy":
aOptions.options = _$(aOptions.options, "aOptions.options").isMap().default({})
@@ -8566,12 +8648,14 @@ const $jsonrpc = function (aOptions) {
}
if (aMethod == "initialize" && !aNotification) _r._info = isDef(_res) && isDef(_res.result) ? _res.result : _res
return isDef(_res) && isDef(_res.result) ? _res.result : _res
- case "remote":
- default:
- _$(aOptions.url, "aOptions.url").isString().$_()
- aOptions.options = _$(aOptions.options, "aOptions.options").isMap().default({})
+ case "remote":
+ default:
+ _$(aOptions.url, "aOptions.url").isString().$_()
+ aOptions.options = _$(aOptions.options, "aOptions.options").isMap().default({})
aMethod = _$(aMethod, "aMethod").isString().$_()
aParams = _$(aParams, "aParams").isMap().default({})
+ var _restOptions = clone(aOptions.options)
+ if (isMap(aExecOptions.restOptions)) _restOptions = merge(_restOptions, aExecOptions.restOptions)
var _req = {
jsonrpc: "2.0",
@@ -8585,7 +8669,7 @@ const $jsonrpc = function (aOptions) {
delete _req.id
}
_debug("jsonrpc -> " + stringify(_req, __, ""))
- var res = $rest(aOptions.options).post(aOptions.url, _req)
+ var res = $rest(_restOptions).post(aOptions.url, _req)
// Notifications do not expect a reply
if (!!aNotification) return
_debug("jsonrpc <- " + stringify(res, __, ""))
@@ -8631,7 +8715,7 @@ const $jsonrpc = function (aOptions) {
* \
* The aOptions parameter is a map with the following possible keys:\
* \
- * - type (string): Connection type - "stdio" for local process, "remote" for HTTP server, "dummy" for local testing, or "ojob" for oJob-based server (default: "stdio")\
+ * - type (string): Connection type - "stdio" for local process, "remote"/"http" for HTTP server, "dummy" for local testing, or "ojob" for oJob-based server (default: "stdio")\
* - url (string): Required for remote servers - the MCP server endpoint URL\
* - timeout (number): Timeout in milliseconds for operations (default: 60000)\
* - cmd (string): Required for stdio type - the command to launch the MCP server\
@@ -8668,7 +8752,7 @@ const $jsonrpc = function (aOptions) {
* - sh(aCommand): Set the command and switch to stdio type\
* - initialize(clientInfo): Initialize the MCP connection and exchange capabilities\
* - listTools(): Get list of available tools from the MCP server\
- * - callTool(toolName, toolArguments): Execute a specific tool with given arguments\
+ * - callTool(toolName, toolArguments, toolOptions): Execute a specific tool with given arguments and optional per-call options\
* - listPrompts(): Get list of available prompts from the MCP server\
* - getPrompt(promptName, promptArguments): Get a specific prompt with given arguments\
* - toGptTools(aGptInstance, aToolNames): Add MCP tools to a $gpt instance\
@@ -8696,6 +8780,8 @@ const $jsonrpc = function (aOptions) {
* clientInfo: {name: "MyApp", version: "2.0.0"}\
* });\
* remoteClient.initialize();\
+ * // Optional per-call HTTP options (only used for remote/http MCP clients)\
+ * var result2 = remoteClient.callTool("read_file", {path: "/tmp/example.txt"}, { requestHeaders: { Authorization: "Bearer ..." } });\
* var prompts = remoteClient.listPrompts();\
* \
* // Dummy mode for testing\
@@ -8950,12 +9036,13 @@ const $mcp = function(aOptions) {
}
return _jsonrpc.exec("tools/list", {})
},
- callTool: (toolName, toolArguments) => {
+ callTool: (toolName, toolArguments, toolOptions) => {
if (!_r._initialized) {
throw new Error("MCP client not initialized. Call initialize() first.")
}
toolName = _$(toolName, "toolName").isString().$_()
toolArguments = _$(toolArguments, "toolArguments").isMap().default({})
+ toolOptions = _$(toolOptions, "toolOptions").isMap().default(__)
// Call pre-function if provided
if (aOptions.preFn) {
@@ -8965,7 +9052,7 @@ const $mcp = function(aOptions) {
var _res = _jsonrpc.exec("tools/call", {
name: toolName,
arguments: toolArguments
- })
+ }, __, { restOptions: toolOptions })
// Call post-function if provided
if (aOptions.posFn) {
aOptions.posFn(toolName, toolArguments, _res)
@@ -9758,6 +9845,21 @@ if (isUnDef(alert)) alert = function(msg) {
};
var __timeout = {};
+/**
+ *
+ * setTimeout(aFunction, aPeriod)
+ * Tries to execute aFunction after aPeriod milliseconds. Note: this function will block the
+ * main thread, so use it with caution. If you need to execute aFunction in a different thread and avoid blocking the main thread, please use setInterval with a clearInterval after the first execution.
+ * \
+ * Example:\
+ * \
+ * setTimeout(() => { print("Hello after 2 seconds"); }, 2000);\
+ * \
+ * // or using setInterval to avoid blocking the main thread\
+ * var id = setInterval(() => { print("Hello after 2 seconds"); clearInterval(id); }, 2000);\
+ * \
+ *
+ */
const setTimeout = function(aFunction, aPeriod) {
sleep(aPeriod);
var args = [];
@@ -9765,6 +9867,12 @@ const setTimeout = function(aFunction, aPeriod) {
aFunction.apply(this, args);
}
+/**
+ *
+ * setInterval(aFunction, aPeriod) : String
+ * Tries to execute aFunction every aPeriod milliseconds. Returns an id that can be used to clear the interval with clearInterval. Note: this function uses Threads plugin, so it will execute aFunction in a different thread and it won't block the main thread. Also, do note that the aFunction execution time is not included in the aPeriod, so if aFunction takes 2 seconds to execute and aPeriod is 5 seconds, the next execution will be 5 seconds after aFunction finishes, so it will be 7 seconds after the previous execution start.
+ *
+ */
const setInterval = function(aFunction, aPeriod) {
plugin("Threads");
var t = new Threads();
@@ -9775,7 +9883,7 @@ const setInterval = function(aFunction, aPeriod) {
var parent = this;
var f = function(uuid) {
- aFunction.apply(parent, args);
+ aFunction.apply(parent, args);
}
var uuid = t.addThread(f);
@@ -9784,6 +9892,12 @@ const setInterval = function(aFunction, aPeriod) {
return uuid;
}
+/**
+ *
+ * clearInterval(uuid)
+ * Clears the interval with the provided uuid returned by setInterval.
+ *
+ */
const clearInterval = function(uuid) {
var t = __timeout[uuid];
t.stop();
@@ -11277,6 +11391,27 @@ AF.prototype.fromObj2XML = function (obj, sanitize, aAttrKey, aPrefix, aSuffix)
*/
AF.prototype.encryptText = function() { plugin("Console"); print("Encrypted text: " + af.encrypt((new Console()).readLinePrompt("Enter text: ", "*"))); };
+/**
+ *
+ * AF.endOpenAFAndStart(aCommandLineArray, noStop)
+ * Calls endOpenAFAndStart to start a detached process and then end the current OpenAF execution.
+ * noStop=true can be used to avoid exiting the current OpenAF process.
+ *
+ */
+AF.prototype.endOpenAFAndStart = function(aCommandLineArray, noStop) {
+ return endOpenAFAndStart(aCommandLineArray, noStop)
+}
+
+/**
+ *
+ * AF.endOpenAFAndStartOpenAF(aCommandLineArray, preCommandLineArray, noStop)
+ * Calls endOpenAFAndStartOpenAF to detach and start another OpenAF with current arguments plus extras.
+ *
+ */
+AF.prototype.endOpenAFAndStartOpenAF = function(aCommandLineArray, preLineArray, noStop) {
+ return endOpenAFAndStartOpenAF(aCommandLineArray, preLineArray, noStop)
+}
+
/**
*
* AF.protectSystemExit(shouldProtect, aMessage)
diff --git a/js/owrap.server.js b/js/owrap.server.js
index 8d78980b0..13bd91dc5 100644
--- a/js/owrap.server.js
+++ b/js/owrap.server.js
@@ -14,7 +14,8 @@ OpenWrap.server = function() {
* Optionally you can provide an onShutdown function to execute any code needed upon controlled shutdown
* of the server and provide an onAlreadyRunning function (that will received the corresponding aPidFile).
* If the onAlreadyRunning function returns false the process will exit with -1 (or the anExitCode provided),
- * if true will continue processing.
+ * if true will continue processing. The aPidFile parameter can be overridden by setting the OAF_PIDFILE
+ * environment variable.
* Example:\
* \
* var params = processExpr();\
@@ -41,6 +42,11 @@ OpenWrap.server.prototype.checkIn = function(aPidFile, onAlreadyRunning, onShutd
var ret = false;
if (isUndefined(anExitCode)) anExitCode = -1;
+ // Override aPidFile with OAF_PIDFILE environment variable if set
+ var envPidFile = getEnv("OAF_PIDFILE")
+ if (isDef(envPidFile) && String(envPidFile).trim() != "") {
+ aPidFile = String(envPidFile).trim()
+ }
if (isUndefined(aPidFile)) aPidFile = "server.pid";
ret = pidCheckIn(aPidFile);
if (ret && isDefined(onShutdown)) addOnOpenAFShutdown(onShutdown);
@@ -1860,7 +1866,8 @@ OpenWrap.server.prototype.mcpStdio = function(initData, fnsMeta, fns, lgF) {
}*/
})
- if (isDef(_res)) {
+ // JSON-RPC notifications return null by design; don't emit a stray "null" line on stdio.
+ if (isDef(_res) && !isNull(_res)) {
lgF("snd", _res)
sprint(_res, "")
}
diff --git a/lib/kotlin-stdlib-2.3.10.jar b/lib/kotlin-stdlib-2.3.10.jar
new file mode 100644
index 000000000..ff4808afe
Binary files /dev/null and b/lib/kotlin-stdlib-2.3.10.jar differ
diff --git a/lib/ojdbc17-23.26.0.0.0.jar b/lib/ojdbc17-23.26.1.0.0.jar
similarity index 79%
rename from lib/ojdbc17-23.26.0.0.0.jar
rename to lib/ojdbc17-23.26.1.0.0.jar
index 1e4963a01..5d2c1be1f 100644
Binary files a/lib/ojdbc17-23.26.0.0.0.jar and b/lib/ojdbc17-23.26.1.0.0.jar differ
diff --git a/pom.xml b/pom.xml
index 0350ac7e0..2afcdef60 100644
--- a/pom.xml
+++ b/pom.xml
@@ -53,7 +53,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/ma
org.apache.maven.plugins
maven-compiler-plugin
- 3.14.1
+ 3.15.0
org.codehaus.mojo
@@ -295,7 +295,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/ma
org.postgresql
postgresql
- 42.7.9
+ 42.7.10
org.snmp4j
@@ -335,7 +335,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/ma
org.jetbrains.kotlin
kotlin-stdlib
- 2.3.0
+ 2.3.10
com.squareup.okio
@@ -380,7 +380,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/ma
com.oracle.database.jdbc
ojdbc17
- 23.26.0.0.0
+ 23.26.1.0.0
diff --git a/tests/asserts.svg b/tests/asserts.svg
index 3c29f2c20..a41719ae9 100644
--- a/tests/asserts.svg
+++ b/tests/asserts.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/tests/autoTestAll.Server.js b/tests/autoTestAll.Server.js
index 9aeffac0b..7fa82122a 100644
--- a/tests/autoTestAll.Server.js
+++ b/tests/autoTestAll.Server.js
@@ -395,4 +395,63 @@
$ch("queue::test").destroy();
};
+
+ exports.testCheckIn = function() {
+ ow.loadServer();
+
+ // Test 1: Default behavior without parameter - should use default "server.pid"
+ io.rm("server.pid");
+
+ var result1 = ow.server.checkIn(void 0, function() { return false; });
+ ow.test.assert(result1, true, "Problem with checkIn creating default PID file");
+ ow.test.assert(io.fileExists("server.pid"), true, "Problem with checkIn - default PID file should exist");
+
+ pidCheckOut("server.pid");
+ io.rm("server.pid");
+
+ // Test 2: Specified PID file parameter
+ var testPid = "test_checkin.pid";
+ io.rm(testPid);
+
+ var result2 = ow.server.checkIn(testPid, function() { return false; });
+ ow.test.assert(result2, true, "Problem with checkIn creating specified PID file");
+ ow.test.assert(io.fileExists(testPid), true, "Problem with checkIn - specified PID file should exist");
+ ow.test.assert(io.fileExists("server.pid"), false, "Problem with checkIn - default PID file should not exist when custom specified");
+
+ pidCheckOut(testPid);
+ io.rm(testPid);
+
+ // Test 3: Verify OAF_PIDFILE environment variable behavior
+ // Note: Environment variables cannot be set at runtime in Java (they're inherited from parent process)
+ // This test checks if OAF_PIDFILE is set in the environment and validates override behavior.
+ // If OAF_PIDFILE is not set, these tests will be skipped (which is expected behavior).
+ // To test this functionality in CI, set OAF_PIDFILE before running the test suite.
+ // Example CI configuration:
+ // env:
+ // OAF_PIDFILE: test_env.pid
+ // run: cd tests && ../ojob autoTestAll.yaml
+ var envPidFile = getEnv("OAF_PIDFILE");
+ if (isDefined(envPidFile) && envPidFile != "") {
+ // Test 3a: Environment variable overrides explicit parameter
+ io.rm(envPidFile);
+ var result3 = ow.server.checkIn("test_param.pid", function() { return false; });
+ ow.test.assert(result3, true, "Problem with checkIn when OAF_PIDFILE is set");
+ ow.test.assert(io.fileExists(envPidFile), true, "Problem with checkIn - OAF_PIDFILE file should exist");
+ ow.test.assert(io.fileExists("test_param.pid"), false, "Problem with checkIn - parameter file should not exist when OAF_PIDFILE is set");
+
+ pidCheckOut(envPidFile);
+ io.rm(envPidFile);
+
+ // Test 3b: Environment variable overrides default (undefined parameter)
+ io.rm(envPidFile);
+ io.rm("server.pid");
+ var result4 = ow.server.checkIn(void 0, function() { return false; });
+ ow.test.assert(result4, true, "Problem with checkIn when OAF_PIDFILE is set with undefined parameter");
+ ow.test.assert(io.fileExists(envPidFile), true, "Problem with checkIn - OAF_PIDFILE file should exist when parameter is undefined");
+ ow.test.assert(io.fileExists("server.pid"), false, "Problem with checkIn - default file should not exist when OAF_PIDFILE is set");
+
+ pidCheckOut(envPidFile);
+ io.rm(envPidFile);
+ }
+ };
})();
\ No newline at end of file
diff --git a/tests/autoTestAll.Server.yaml b/tests/autoTestAll.Server.yaml
index 5d35c766f..4b2b19ba3 100644
--- a/tests/autoTestAll.Server.yaml
+++ b/tests/autoTestAll.Server.yaml
@@ -80,6 +80,11 @@ jobs:
to : oJob Test
exec: args.func = args.tests.testQueue;
+ - name: Server::CheckIn
+ from: Server::Init
+ to : oJob Test
+ exec: args.func = args.tests.testCheckIn;
+
todo:
# Server tests
# ------------
@@ -97,4 +102,5 @@ todo:
- Server::Locks
- Server::Auth
- Server::AuthApp
- - Server::Queue
\ No newline at end of file
+ - Server::Queue
+ - Server::CheckIn
\ No newline at end of file
diff --git a/tests/autoTestAll.md b/tests/autoTestAll.md
index ffa71c301..149e18ac9 100644
--- a/tests/autoTestAll.md
+++ b/tests/autoTestAll.md
@@ -2,205 +2,208 @@
## Summary
-* Number of tests performed: 194
-* Number of tests passed: 194
-* Number of tests failed: 0
-* Number of asserts: 615
+* Number of tests performed: 197
+* Number of tests passed: 196
+* Number of tests failed: 1
+* Number of asserts: 621
## Result details
| Suite | Test | Status | Time | Result |
|-------|------|--------|------|--------------|
-|AI | LSTM AND | PASS | 153 ms | n/a |
-|AI | LSTM network save and load | PASS | 179 ms | n/a |
-|AI | Liquid XOR | PASS | 360 ms | n/a |
-|AI | Liquid network save and load | PASS | 342 ms | n/a |
+|AI | LSTM AND | PASS | 160 ms | n/a |
+|AI | LSTM network save and load | PASS | 141 ms | n/a |
+|AI | Liquid XOR | PASS | 357 ms | n/a |
+|AI | Liquid network save and load | PASS | 375 ms | n/a |
|AI | Normalize features array | PASS | 1 ms | n/a |
-|AI | Normalize with schema | PASS | 10 ms | n/a |
-|AI | Perceptron XOR | PASS | 709 ms | n/a |
-|AI | Perceptron XOR Put | PASS | 6 seconds, 829 ms | n/a |
-|AI | Perceptron XOR save and load | PASS | 47 ms | n/a |
-|AI | Perceptron network save and load | PASS | 36 ms | n/a |
-|AI | Test C45 | PASS | 29 ms | n/a |
-|AI | Test ID3 | PASS | 59 ms | n/a |
-|AI | Test KMeans | PASS | 14 ms | n/a |
-|CSV | Generic CSV | PASS | 3 ms | n/a |
-|CSV | Stream CSV | PASS | 23 ms | n/a |
-|CSV | ToFrom CSV | PASS | 12 ms | n/a |
-|Channels | Keep history util | PASS | 4 seconds, 6 ms | n/a |
-|Channels | Remote channel access auditing | PASS | 256 ms | n/a |
-|Channels | Subscribers test | PASS | 731 ms | n/a |
-|Channels | Test Elastic Index | PASS | 1 ms | n/a |
-|Channels | Test MVS Utils | PASS | 74 ms | n/a |
-|Channels | Test channel (all) | PASS | 14 ms | n/a |
+|AI | Normalize with schema | PASS | 7 ms | n/a |
+|AI | Perceptron XOR | PASS | 530 ms | n/a |
+|AI | Perceptron XOR Put | PASS | 6 seconds, 227 ms | n/a |
+|AI | Perceptron XOR save and load | PASS | 26 ms | n/a |
+|AI | Perceptron network save and load | PASS | 38 ms | n/a |
+|AI | Test C45 | PASS | 28 ms | n/a |
+|AI | Test ID3 | PASS | 44 ms | n/a |
+|AI | Test KMeans | PASS | 10 ms | n/a |
+|CSV | Generic CSV | PASS | 2 ms | n/a |
+|CSV | Stream CSV | PASS | 18 ms | n/a |
+|CSV | ToFrom CSV | PASS | 6 ms | n/a |
+|Channels | Keep history util | PASS | 4 seconds, 5 ms | n/a |
+|Channels | Remote channel access auditing | PASS | 189 ms | n/a |
+|Channels | Subscribers test | PASS | 689 ms | n/a |
+|Channels | Test Elastic Index | PASS | ~0 ms | n/a |
+|Channels | Test MVS Utils | PASS | 63 ms | n/a |
+|Channels | Test channel (all) | PASS | 15 ms | n/a |
|Channels | Test channel (big) | PASS | 1 ms | n/a |
-|Channels | Test channel (big) | PASS | 22 ms | n/a |
-|Channels | Test channel (big) | PASS | 235 ms | n/a |
+|Channels | Test channel (big) | PASS | 20 ms | n/a |
+|Channels | Test channel (big) | PASS | 212 ms | n/a |
|Channels | Test channel (big) | PASS | ~0 ms | n/a |
-|Channels | Test channel (big) | PASS | 32 seconds, 7 ms | n/a |
+|Channels | Test channel (big) | PASS | 32 seconds, 5 ms | n/a |
|Channels | Test channel (cache) | PASS | 2 ms | n/a |
|Channels | Test channel (cache) | PASS | 1 ms | n/a |
-|Channels | Test channel (cache) | PASS | 32 seconds, 12 ms | n/a |
-|Channels | Test channel (file) | PASS | 4 ms | n/a |
-|Channels | Test channel (file) | PASS | 19 ms | n/a |
-|Channels | Test channel (file) | PASS | 185 ms | n/a |
+|Channels | Test channel (cache) | PASS | 32 seconds, 5 ms | n/a |
+|Channels | Test channel (file) | PASS | 3 ms | n/a |
+|Channels | Test channel (file) | PASS | 11 ms | n/a |
+|Channels | Test channel (file) | PASS | 167 ms | n/a |
|Channels | Test channel (file) | PASS | ~0 ms | n/a |
-|Channels | Test channel (file) | PASS | 32 seconds, 4 ms | n/a |
-|Channels | Test channel (mvs) | PASS | 1 ms | n/a |
-|Channels | Test channel (mvs) | PASS | 9 ms | n/a |
-|Channels | Test channel (mvs) | PASS | 109 ms | n/a |
-|Channels | Test channel (mvs) | PASS | 1 ms | n/a |
+|Channels | Test channel (file) | PASS | 32 seconds, 9 ms | n/a |
+|Channels | Test channel (mvs) | PASS | 2 ms | n/a |
+|Channels | Test channel (mvs) | PASS | 11 ms | n/a |
+|Channels | Test channel (mvs) | PASS | 86 ms | n/a |
+|Channels | Test channel (mvs) | PASS | ~0 ms | n/a |
|Channels | Test channel (mvs) | PASS | 32 seconds, 4 ms | n/a |
|Channels | Test channel (simple) | PASS | ~0 ms | n/a |
|Channels | Test channel (simple) | PASS | 4 ms | n/a |
-|Channels | Test channel (simple) | PASS | 93 ms | n/a |
+|Channels | Test channel (simple) | PASS | 71 ms | n/a |
|Channels | Test channel (simple) | PASS | ~0 ms | n/a |
-|Channels | Test channel (simple) | PASS | 32 seconds, 5 ms | n/a |
+|Channels | Test channel (simple) | PASS | 32 seconds, 6 ms | n/a |
|DB | DB type conversion to JS | PASS | 7 ms | n/a |
-|DB | Simple DB in memory | PASS | 175 ms | n/a |
+|DB | Simple DB in memory | PASS | 155 ms | n/a |
|Format | Add number separator | PASS | 1 ms | n/a |
-|Format | Conversions | PASS | 6 ms | n/a |
-|Format | Cron | PASS | 3 ms | n/a |
-|Format | Cron How Many Ago | PASS | 29 ms | n/a |
-|Format | Date diff | PASS | 5 ms | n/a |
+|Format | Conversions | PASS | 4 ms | n/a |
+|Format | Cron | PASS | 4 ms | n/a |
+|Format | Cron How Many Ago | PASS | 30 ms | n/a |
+|Format | Date diff | PASS | 6 ms | n/a |
|Format | Date to/from | PASS | 2 ms | n/a |
|Format | Escape strings | PASS | 1 ms | n/a |
-|Format | Escape/Unescape HTML4 | PASS | 11 ms | n/a |
-|Format | Host | PASS | 3 ms | n/a |
+|Format | Escape/Unescape HTML4 | PASS | 8 ms | n/a |
+|Format | Host | PASS | 1 ms | n/a |
|Format | LDAP date to/from | PASS | ~0 ms | n/a |
-|Format | LSH | PASS | 591 ms | n/a |
+|Format | LSH | PASS | 599 ms | n/a |
|Format | Load Format | PASS | ~0 ms | n/a |
|Format | Number abbreviation | PASS | 1 ms | n/a |
|Format | Number rounding | PASS | ~0 ms | n/a |
-|Format | SLON | PASS | 26 ms | n/a |
+|Format | SLON | PASS | 18 ms | n/a |
|Format | String pad | PASS | ~0 ms | n/a |
|Format | Time ago | PASS | 2 ms | n/a |
|Format | TimeAbbreviation | PASS | 4 ms | n/a |
-|Format | Unix date to/from | PASS | 1 ms | n/a |
-|Format | Word wrap | PASS | 6 ms | n/a |
-|HTTP | HTTP changing user agent | PASS | 331 ms | n/a |
-|HTTP | HTTP plugin basic functionality | PASS | 53 ms | n/a |
-|HTTP | HTTP plugin test basic auth | PASS | 623 ms | n/a |
-|HTTP | HTTP plugin web socket client | PASS | 3 seconds, 680 ms | n/a |
-|IO | IO Test Gzip Native to Byte array | PASS | 28 ms | n/a |
+|Format | Unix date to/from | PASS | ~0 ms | n/a |
+|Format | Word wrap | PASS | 5 ms | n/a |
+|HTTP | HTTP changing user agent | PASS | 305 ms | n/a |
+|HTTP | HTTP plugin basic functionality | PASS | 47 ms | n/a |
+|HTTP | HTTP plugin test basic auth | PASS | 429 ms | n/a |
+|HTTP | HTTP plugin web socket client | PASS | 3 seconds, 44 ms | n/a |
+|IO | IO Test Gzip Native to Byte array | PASS | 21 ms | n/a |
|IO | IO Test JSON | PASS | 2 ms | n/a |
-|IO | IO Test Stream JSON | PASS | 34 ms | n/a |
-|IO | IO Test TAR functionality | PASS | 4 seconds, 736 ms | n/a |
+|IO | IO Test Stream JSON | PASS | 30 ms | n/a |
+|IO | IO Test TAR functionality | PASS | 4 seconds, 305 ms | n/a |
|IO | IO Test binary file detection | PASS | 13 ms | n/a |
-|IO | IO Test copy streams | PASS | 220 ms | n/a |
-|IO | IO Test copy/move/delete file | PASS | 6 ms | n/a |
+|IO | IO Test copy streams | PASS | 173 ms | n/a |
+|IO | IO Test copy/move/delete file | PASS | 7 ms | n/a |
|IO | IO Test read/writeFileStream | PASS | 6 ms | n/a |
|IO | IO Test read/writeFileStream NIO | PASS | 6 ms | n/a |
-|IO | IO Test read/writeFileStreamBytes | PASS | 2 ms | n/a |
-|IO | IO Test read/writeFileStreamBytes NIO | PASS | 1 ms | n/a |
-|JMX | JMX test | PASS | 562 ms | n/a |
-|Java | Java ASym Cipher | PASS | 172 ms | n/a |
-|Java | Java Cipher | PASS | 278 ms | n/a |
-|Net | Get Actual Time (default) | PASS | 37 ms | n/a |
-|Net | Get Actual Time (server and timeout) | PASS | 43 ms | n/a |
-|Net | Get Actual Time (with server) | PASS | 20 ms | n/a |
-|Net | Get Actual Time (with timeout) | PASS | 20 ms | n/a |
+|IO | IO Test read/writeFileStreamBytes | PASS | 3 ms | n/a |
+|IO | IO Test read/writeFileStreamBytes NIO | PASS | 2 ms | n/a |
+|JMX | JMX test | PASS | 655 ms | n/a |
+|Java | Java ASym Cipher | PASS | 107 ms | n/a |
+|Java | Java Cipher | PASS | 329 ms | n/a |
+|Net | Get Actual Time (default) | PASS | 27 ms | n/a |
+|Net | Get Actual Time (server and timeout) | PASS | 14 ms | n/a |
+|Net | Get Actual Time (with server) | PASS | 8 ms | n/a |
+|Net | Get Actual Time (with timeout) | PASS | 8 ms | n/a |
|Net | Load Net | PASS | ~0 ms | n/a |
|Obj | Array to object conversion | PASS | 1 ms | n/a |
-|Obj | DB ResultSet to object | PASS | 1 second, 421 ms | n/a |
+|Obj | DB ResultSet to object | PASS | 813 ms | n/a |
|Obj | Filter | PASS | 9 ms | n/a |
-|Obj | Flat map | PASS | 13 ms | n/a |
-|Obj | Flatten | PASS | 211 ms | n/a |
-|Obj | Generate One of | PASS | 42 ms | n/a |
-|Obj | Generate One of Fn | PASS | 15 ms | n/a |
+|Obj | Flat map | PASS | 14 ms | n/a |
+|Obj | Flatten | PASS | 192 ms | n/a |
+|Obj | Generate One of | PASS | 26 ms | n/a |
+|Obj | Generate One of Fn | PASS | 14 ms | n/a |
|Obj | Get Path | PASS | 1 ms | n/a |
-|Obj | Object fuzzy search | PASS | 45 ms | n/a |
+|Obj | Object fuzzy search | PASS | 38 ms | n/a |
|Obj | Object pool | PASS | 6 seconds, 79 ms | n/a |
-|Obj | Object schema validation | PASS | 310 ms | n/a |
-|Obj | Object to array conversion | PASS | 2 ms | n/a |
+|Obj | Object schema validation | PASS | 313 ms | n/a |
+|Obj | Object to array conversion | PASS | 1 ms | n/a |
|Obj | Set Path | PASS | 1 ms | n/a |
-|Obj | Sign object | PASS | 422 ms | n/a |
-|Obj | Thread-safe array | PASS | 2 ms | n/a |
+|Obj | Sign object | PASS | 365 ms | n/a |
+|Obj | Thread-safe array | PASS | 3 ms | n/a |
|Obj | Thread-safe array | PASS | ~0 ms | n/a |
-|Obj | Thread-safe map | PASS | 2 ms | n/a |
-|OpenAF | Await | PASS | 13 ms | n/a |
-|OpenAF | AwaitAll | PASS | 54 ms | n/a |
-|OpenAF | Basic Parallel processing | PASS | 12 ms | n/a |
-|OpenAF | Cache | PASS | 330 ms | n/a |
+|Obj | Thread-safe map | PASS | 3 ms | n/a |
+|OpenAF | Await | FAIL | 30 seconds, 7 ms | Problem with await (1) (got 2 but expected 1) |
+|OpenAF | AwaitAll | PASS | 53 ms | n/a |
+|OpenAF | Basic Parallel processing | PASS | 16 ms | n/a |
+|OpenAF | Cache | PASS | 328 ms | n/a |
|OpenAF | Crypt | PASS | 10 ms | n/a |
|OpenAF | DescType | PASS | 2 ms | n/a |
-|OpenAF | Encrypt/Decrypt | PASS | ~0 ms | n/a |
+|OpenAF | Encrypt/Decrypt | PASS | 1 ms | n/a |
|OpenAF | Get Path | PASS | 1 ms | n/a |
-|OpenAF | Get version | PASS | 2 ms | n/a |
+|OpenAF | Get version | PASS | ~0 ms | n/a |
|OpenAF | IsFunctions | PASS | 1 ms | n/a |
-|OpenAF | Java RegExp | PASS | 9 ms | n/a |
+|OpenAF | Java RegExp | PASS | 5 ms | n/a |
|OpenAF | Logs | PASS | 4 ms | n/a |
|OpenAF | Map Array | PASS | 1 ms | n/a |
-|OpenAF | Map22Array | PASS | 516 ms | n/a |
-|OpenAF | NDJSON | PASS | 4 ms | n/a |
-|OpenAF | PSelect | PASS | 7 ms | n/a |
+|OpenAF | Map22Array | PASS | 458 ms | n/a |
+|OpenAF | NDJSON | PASS | 3 ms | n/a |
+|OpenAF | PSelect | PASS | 9 ms | n/a |
|OpenAF | Prints | PASS | 1 ms | n/a |
-|OpenAF | Queue | PASS | 16 ms | n/a |
-|OpenAF | Range | PASS | 4 ms | n/a |
-|OpenAF | Retry | PASS | 1 ms | n/a |
+|OpenAF | Queue | PASS | 12 ms | n/a |
+|OpenAF | Range | PASS | 3 ms | n/a |
+|OpenAF | Retry | PASS | 2 ms | n/a |
|OpenAF | SPrints | PASS | 1 ms | n/a |
-|OpenAF | Search Key and Values | PASS | 6 ms | n/a |
-|OpenAF | Set Path | PASS | 2 ms | n/a |
+|OpenAF | Search Key and Values | PASS | 4 ms | n/a |
+|OpenAF | Set Path | PASS | 1 ms | n/a |
|OpenAF | Test $do | PASS | 15 ms | n/a |
-|OpenAF | Test $doAll | PASS | 8 ms | n/a |
-|OpenAF | Test $doFirst | PASS | 157 ms | n/a |
-|OpenAF | Test AF Parse | PASS | 1 ms | n/a |
-|OpenAF | Test BCrypt | PASS | 1 second, 542 ms | n/a |
+|OpenAF | Test $doAll | PASS | 7 ms | n/a |
+|OpenAF | Test $doFirst | PASS | 155 ms | n/a |
+|OpenAF | Test AF Parse | PASS | ~0 ms | n/a |
+|OpenAF | Test BCrypt | PASS | 734 ms | n/a |
|OpenAF | Test Encoding | PASS | 1 ms | n/a |
|OpenAF | Test Envs | PASS | 1 ms | n/a |
-|OpenAF | Test FLock | PASS | 5 ms | n/a |
+|OpenAF | Test FLock | PASS | 7 ms | n/a |
|OpenAF | Test Format Conversion to/from base64 | PASS | ~0 ms | n/a |
|OpenAF | Test Format Conversion to/from bytes | PASS | ~0 ms | n/a |
|OpenAF | Test GetSet | PASS | 3 ms | n/a |
|OpenAF | Test Lock | PASS | 1 ms | n/a |
-|OpenAF | Test Merge | PASS | ~0 ms | n/a |
+|OpenAF | Test Merge | PASS | 1 ms | n/a |
|OpenAF | Test Object Compression | PASS | ~0 ms | n/a |
-|OpenAF | Test Path | PASS | 115 ms | n/a |
-|OpenAF | Test Rest | PASS | 296 ms | n/a |
+|OpenAF | Test Path | PASS | 102 ms | n/a |
+|OpenAF | Test Rest | PASS | 195 ms | n/a |
|OpenAF | Test SHA1 | PASS | ~0 ms | n/a |
|OpenAF | Test SHA256 | PASS | ~0 ms | n/a |
|OpenAF | Test SHA512 | PASS | ~0 ms | n/a |
|OpenAF | Test Scope Ids | PASS | 1 ms | n/a |
-|OpenAF | Test Shell | PASS | 3 ms | n/a |
+|OpenAF | Test Shell | PASS | 2 ms | n/a |
|OpenAF | Test Shell with Map | PASS | 2 ms | n/a |
-|OpenAF | Test Stream conversions | PASS | 1 ms | n/a |
+|OpenAF | Test Stream conversions | PASS | ~0 ms | n/a |
|OpenAF | Test Void shortcut | PASS | ~0 ms | n/a |
-|OpenAF | Test clone | PASS | 2 ms | n/a |
-|OpenAF | Test pForEach | PASS | 135 ms | n/a |
+|OpenAF | Test clone | PASS | 1 ms | n/a |
+|OpenAF | Test pForEach | PASS | 152 ms | n/a |
|OpenAF | Thread box | PASS | 306 ms | n/a |
-|OpenAF | Two factor authentication | PASS | 2 ms | n/a |
-|OpenAF | XML2And4Obj | PASS | 211 ms | n/a |
-|OpenAF | YAML | PASS | 5 ms | n/a |
-|Sec | Sec basic functionality | PASS | 15 ms | n/a |
-|Sec | Sec function functionality | PASS | 458 ms | n/a |
-|Sec | Sec object functionality | PASS | 885 ms | n/a |
-|Server | Auth | PASS | 6 seconds, 18 ms | n/a |
-|Server | AuthApp | PASS | 163 ms | n/a |
-|Server | HTTP server | PASS | 110 ms | n/a |
-|Server | HTTP server Java | PASS | 20 ms | n/a |
-|Server | HTTP server NWU2 | PASS | 76 ms | n/a |
-|Server | Locks | PASS | 2 seconds, 22 ms | n/a |
-|Server | Queue | PASS | 4 seconds, 669 ms | n/a |
-|Server | REST server | PASS | 102 ms | n/a |
-|Server | REST server Java | PASS | 177 ms | n/a |
-|Server | REST server NWU2 | PASS | 66 ms | n/a |
-|Server | REST server simple | PASS | 32 ms | n/a |
-|Server | REST server simple Java | PASS | 22 ms | n/a |
-|Server | REST server simple NWU2 | PASS | 28 ms | n/a |
-|Server | Scheduler | PASS | 16 seconds, 24 ms | n/a |
+|OpenAF | Two factor authentication | PASS | 1 ms | n/a |
+|OpenAF | XML2And4Obj | PASS | 195 ms | n/a |
+|OpenAF | YAML | PASS | 6 ms | n/a |
+|Sec | Sec basic functionality | PASS | 14 ms | n/a |
+|Sec | Sec function functionality | PASS | 362 ms | n/a |
+|Sec | Sec object functionality | PASS | 857 ms | n/a |
+|Server | Auth | PASS | 6 seconds, 20 ms | n/a |
+|Server | AuthApp | PASS | 174 ms | n/a |
+|Server | CheckIn | PASS | 3 ms | n/a |
+|Server | HTTP server | PASS | 137 ms | n/a |
+|Server | HTTP server Java | PASS | 18 ms | n/a |
+|Server | HTTP server NWU2 | PASS | 75 ms | n/a |
+|Server | Locks | PASS | 2 seconds, 20 ms | n/a |
+|Server | Queue | PASS | 4 seconds, 796 ms | n/a |
+|Server | REST server | PASS | 108 ms | n/a |
+|Server | REST server Java | PASS | 182 ms | n/a |
+|Server | REST server NWU2 | PASS | 68 ms | n/a |
+|Server | REST server simple | PASS | 35 ms | n/a |
+|Server | REST server simple Java | PASS | 24 ms | n/a |
+|Server | REST server simple NWU2 | PASS | 33 ms | n/a |
+|Server | Scheduler | PASS | 16 seconds, 26 ms | n/a |
|Template | Load Template | PASS | ~0 ms | n/a |
-|Template | Test Markdown to HTML | PASS | 654 ms | n/a |
-|Template | Test conditional helpers | PASS | 224 ms | n/a |
-|Template | Test format helpers | PASS | 63 ms | n/a |
-|Template | Test openaf helpers | PASS | 127 ms | n/a |
-|Template | Test partial helpers | PASS | 38 ms | n/a |
-|Template | Test simple template | PASS | 53 ms | n/a |
-|ZIP | ZIP basic functionality | PASS | 1 second, 462 ms | n/a |
-|ZIP | ZIP streaming functionality | PASS | 1 second, 496 ms | n/a |
-|oDoc | Test access to oDoc | PASS | 1 second, 4 ms | n/a |
-|oJob | oJob | PASS | 1 second, 672 ms | n/a |
-|oJob | oJobArgsMultipleLevels | PASS | 1 second, 980 ms | n/a |
-|oJob | oJobChecks | PASS | 1 second, 671 ms | n/a |
-|oJob | oJobInitArray | PASS | 4 seconds, 100 ms | n/a |
-|oJob | oJobPass | PASS | 1 second, 813 ms | n/a |
-|oJob | oJobShortcutOutput | PASS | 1 second, 888 ms | n/a |
-|oJob | oJobShortcuts | PASS | 1 second, 780 ms | n/a |
+|Template | Test Markdown to HTML | PASS | 621 ms | n/a |
+|Template | Test conditional helpers | PASS | 256 ms | n/a |
+|Template | Test format helpers | PASS | 55 ms | n/a |
+|Template | Test openaf helpers | PASS | 120 ms | n/a |
+|Template | Test partial helpers | PASS | 31 ms | n/a |
+|Template | Test simple template | PASS | 35 ms | n/a |
+|ZIP | ZIP basic functionality | PASS | 1 second, 480 ms | n/a |
+|ZIP | ZIP streaming functionality | PASS | 1 second, 507 ms | n/a |
+|oDoc | Test access to oDoc | PASS | 831 ms | n/a |
+|oJob | oJob | PASS | 1 second, 772 ms | n/a |
+|oJob | oJobArgsMultipleLevels | PASS | 2 seconds, 82 ms | n/a |
+|oJob | oJobChecks | PASS | 1 second, 777 ms | n/a |
+|oJob | oJobEncryptedJSON | PASS | 1 second, 557 ms | n/a |
+|oJob | oJobEncryptedYAML | PASS | 1 second, 726 ms | n/a |
+|oJob | oJobInitArray | PASS | 4 seconds, 236 ms | n/a |
+|oJob | oJobPass | PASS | 1 second, 893 ms | n/a |
+|oJob | oJobShortcutOutput | PASS | 2 seconds, 164 ms | n/a |
+|oJob | oJobShortcuts | PASS | 1 second, 827 ms | n/a |
diff --git a/tests/results.svg b/tests/results.svg
index 5f9987511..2be80c5d7 100644
--- a/tests/results.svg
+++ b/tests/results.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file