diff --git a/build/build_cmgr_xlclang.sh b/build/build_cmgr_xlclang.sh index b78293f3f..8f597573e 100755 --- a/build/build_cmgr_xlclang.sh +++ b/build/build_cmgr_xlclang.sh @@ -166,6 +166,14 @@ xlclang \ rm -rf "${TMP_DIR}" +if [ "${1}" = "--test" ]; then + if [ -f "${COMMON}/bin/configmgr" ]; then + cd "${COMMON}/tests/quickJS/" + ./run_test.sh + cd "${WORKING_DIR}" + echo + fi +fi # This program and the accompanying materials are # made available under the terms of the Eclipse Public License v2.0 which accompanies diff --git a/tests/quickJS/README.md b/tests/quickJS/README.md new file mode 100644 index 000000000..5c7675e2a --- /dev/null +++ b/tests/quickJS/README.md @@ -0,0 +1,15 @@ +# QuickJS tests + +## Simple unit tests + +This framework is as unit testing for individual javascript functions. + +## Adding new test + +Follow the existing structure, always returning the number of errors and tests. + +Keep in mind, test the simple cases like: +* Working cases +* No parameters when exepecting some +* Incorrect data types +* Empty, null, undefined values... diff --git a/tests/quickJS/lib/print.js b/tests/quickJS/lib/print.js new file mode 100644 index 000000000..fcc6cdc87 --- /dev/null +++ b/tests/quickJS/lib/print.js @@ -0,0 +1,63 @@ +/* +// This program and the accompanying materials are made available +// under the terms of the Eclipse Public License v2.0 which +// accompanies this distribution, and is available at +// https://www.eclipse.org/legal/epl-v20.html +// +// SPDX-License-Identifier: EPL-2.0 +// +// Copyright Contributors to the Zowe Project. +*/ + +export const RED = "\u001b[31m"; +export const GREEN = "\u001b[32m"; +export const YELLOW = "\u001b[33m"; +export const PURPLE = "\u001b[35m"; +export const CYAN = "\u001b[36m"; +export const RESET = "\u001b[0m"; + +export function color(color, msg) { + console.log(`${color}${msg}${RESET}`); +} + +export function red(msg) { + color(RED, msg); +} + +export function green(msg) { + color(GREEN, msg); +} + +export function yellow(msg) { + color(YELLOW, msg); +} + +export function purple(msg) { + color(PURPLE, msg); +} + +export function cyan(msg) { + color(CYAN, msg); +} + +export function conditionally(condition, functionTested, parm, result, additionalInfo) { + if (typeof parm == 'object') { + parm = JSON.stringify(parm); + } + if (typeof result == 'object') { + result = JSON.stringify(result); + } + if (!additionalInfo) { + additionalInfo = ''; + } else { + additionalInfo = `[${additionalInfo}]`; + } + console.log(`${condition ? GREEN : RED}` + `${functionTested}("${parm}")=${result} ${additionalInfo}` + RESET); + return + !condition; +} + +export function lines(clr, msg) { + color(clr, `\n${'-'.repeat(msg.length)}`); + color(clr, `${msg}`); + color(clr, `${'-'.repeat(msg.length)}\n`); +} diff --git a/tests/quickJS/lib/test.js b/tests/quickJS/lib/test.js new file mode 100644 index 000000000..eae2e524f --- /dev/null +++ b/tests/quickJS/lib/test.js @@ -0,0 +1,37 @@ +/* +// This program and the accompanying materials are made available +// under the terms of the Eclipse Public License v2.0 which +// accompanies this distribution, and is available at +// https://www.eclipse.org/legal/epl-v20.html +// +// SPDX-License-Identifier: EPL-2.0 +// +// Copyright Contributors to the Zowe Project. +*/ + +import * as print from './print'; + +export const CLASSIC_FAILS = [ '', null, undefined, true, false, -16, 0, 256, 3.141592, 999999999, + ['banana', 'apple', 'kiwi'], + { success: "guaranteed" } +]; + +export function process(testFunction, testSet, compare, msg) { + let errors = 0; + let result; + if (typeof compare == 'object') { + compare = JSON.stringify(compare); + } + for (let t in testSet) { + if (Array.isArray(testSet[t])) { + result = testFunction(...testSet[t]); + } else { + result = testFunction(testSet[t]); + } + if (typeof result == 'object') { + result = JSON.stringify(result); + } + errors += print.conditionally(result == compare, msg, testSet[t], result); + } + return errors; +} diff --git a/tests/quickJS/lib/testSet.js b/tests/quickJS/lib/testSet.js new file mode 100644 index 000000000..471563041 --- /dev/null +++ b/tests/quickJS/lib/testSet.js @@ -0,0 +1,28 @@ +/* +// This program and the accompanying materials are made available +// under the terms of the Eclipse Public License v2.0 which +// accompanies this distribution, and is available at +// https://www.eclipse.org/legal/epl-v20.html +// +// SPDX-License-Identifier: EPL-2.0 +// +// Copyright Contributors to the Zowe Project. +*/ + +import * as testZos from '../testLib/testZos' + +export const TEST_ZOS = [ + testZos.test_changeTag, + testZos.test_changeExtAttr, + testZos.test_changeStreamCCSID, + testZos.test_zstat, + testZos.test_getZosVersion, + testZos.test_getEsm, + testZos.test_dslist, + testZos.test_resolveSymbol, + testZos.test_getStatvfs, +]; + +export const TESTS = [ + ...TEST_ZOS +]; diff --git a/tests/quickJS/quickJS.js b/tests/quickJS/quickJS.js new file mode 100644 index 000000000..0e51d224d --- /dev/null +++ b/tests/quickJS/quickJS.js @@ -0,0 +1,37 @@ +/* +// This program and the accompanying materials are made available +// under the terms of the Eclipse Public License v2.0 which +// accompanies this distribution, and is available at +// https://www.eclipse.org/legal/epl-v20.html +// +// SPDX-License-Identifier: EPL-2.0 +// +// Copyright Contributors to the Zowe Project. +*/ + +import * as std from 'cm_std'; +import * as print from './lib/print'; +import * as testSet from './lib/testSet'; + +let result = {}; +let errors = 0; +let total = 0; + +const loopStart = Date.now(); +for (let testFunction in testSet.TESTS) { + result = testSet.TESTS[testFunction](); + errors += result.errors; + total += result.total; +} +const loopEnd = Date.now(); + +const timeDiff = loopEnd-loopStart; +print.cyan(`\nTime elapsed ${timeDiff} ms.`); + +if (errors) { + print.lines(print.RED, `${errors} error${errors == 1 ? '' : 's'} detected in ${total} tests, review the test output.`); + std.exit(8); +} else { + print.lines(print.GREEN, `${total} tests succesfull.`); + std.exit(0); +} diff --git a/tests/quickJS/run_test.sh b/tests/quickJS/run_test.sh new file mode 100755 index 000000000..14d7d28f6 --- /dev/null +++ b/tests/quickJS/run_test.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +####################################################################### +# This program and the accompanying materials are made available +# under the terms of the Eclipse Public License v2.0 which +# accompanies this distribution, and is available at +# https://www.eclipse.org/legal/epl-v20.html +# +# SPDX-License-Identifier: EPL-2.0 +# +# Copyright Contributors to the Zowe Project. +####################################################################### + +if [ `uname` != "OS/390" ]; then + echo "Error: this test must run on a z/OS system." + exit 1 +fi + +if [ "${1}" = "--help" ]; then + echo "Run the Quick JS tests" + echo " no parm: tries to run configmgr from current 'zowe-common-c/bin'" + echo " path: path to configmgr" + echo " --help: this help" + exit 0 +fi + +configmgr_path="${1}" +if [ -z "${configmgr_path}" ]; then + configmgr_path="../../bin/configmgr" +fi + +if [ -f "${configmgr_path}" ]; then + "${configmgr_path}" -script ./quickJS.js +else + echo "Error: configmgr not found in '${configmgr_path}'" + exit 4 +fi diff --git a/tests/quickJS/testLib/hello.txt b/tests/quickJS/testLib/hello.txt new file mode 100644 index 000000000..5dd01c177 --- /dev/null +++ b/tests/quickJS/testLib/hello.txt @@ -0,0 +1 @@ +Hello, world! \ No newline at end of file diff --git a/tests/quickJS/testLib/testZos.js b/tests/quickJS/testLib/testZos.js new file mode 100644 index 000000000..66d4815da --- /dev/null +++ b/tests/quickJS/testLib/testZos.js @@ -0,0 +1,137 @@ +/* +// This program and the accompanying materials are made available +// under the terms of the Eclipse Public License v2.0 which +// accompanies this distribution, and is available at +// https://www.eclipse.org/legal/epl-v20.html +// +// SPDX-License-Identifier: EPL-2.0 +// +// Copyright Contributors to the Zowe Project. +*/ + +// ======================== +// zowe-common-c/c/qjszos.c +// ======================== + +import * as zos from 'zos'; +import * as print from '../lib/print'; +import * as test from '../lib/test'; + + +export function test_changeTag() { + let errs; + const FAILS = [ ...test.CLASSIC_FAILS, + './file, which does not exit', ['./file, which does not exit', 250000 ], + ] + const FINES = [ + [ './testLib/hello.txt', 0 ], + [ './testLib/hello.txt', 859 ], + [ './testLib/hello.txt', 1047 ], + ]; + + errs = test.process(zos.changeTag, FAILS, -1, 'zos.changeTag'); + errs += test.process(zos.changeTag, FINES, 0, 'zos.changeTag'); + + return { errors: errs, total: FAILS.length + FINES.length } +} + + +export function test_changeExtAttr() { + const FINES = [ + ['./testLib/hello.txt', zos.EXTATTR_PROGCTL, true ], + ['./testLib/hello.txt', zos.EXTATTR_PROGCTL, false ], + ] + let errs = test.process(zos.changeExtAttr, test.CLASSIC_FAILS, -1, 'zos.changeExtAttr'); + errs += test.process(zos.changeExtAttr, FINES, 0, 'zos.changeExtAttr'); + return { errors: errs, total: test.CLASSIC_FAILS.length + FINES.length } +} + + +export function test_changeStreamCCSID() { + const FAILS = [ -2, -1, 999999999, 1024*1024 ]; + const errs = test.process(zos.changeStreamCCSID, FAILS, -1, 'zos.changeStreamCCSID'); + return { errors: errs, total: FAILS.length } +} + + +export function test_zstat() { + const FAILS = [ ...test.CLASSIC_FAILS ]; + const FINES = [ './testLib/hello.txt', './', './run_test.sh' ]; + let errs = 0; + for (let f in FAILS) { + const result = zos.zstat(FAILS[f]); + errs += print.conditionally(result[1] == 129, 'zos.zstat', FAILS[f], result); + } + for (let f in FINES) { + const result = zos.zstat(FINES[f]); + errs += print.conditionally(result[1] == 0, 'zos.zstat', FINES[f], result); + } + return { errors: errs, total: FAILS.length + FINES.length } +} + + +export function test_getZosVersion() { + const result = zos.getZosVersion(); + print.conditionally(true, 'zos.getZosVersion', 'no parameter', result, `${result > 0 ? `in hex 0x${result.toString(16)}` : ``}`); + return { errors: result ? 0 : 1, total : 1 }; +} + + +export function test_getEsm() { + const EXPECTED = [ 'ACF2', 'RACF', 'TSS', 'NONE' ]; + const result = zos.getEsm(); + + if (result == null || !EXPECTED.includes(result)) { + print.conditionally(false, 'zos.getEsms', 'no parameter', result); + return { errors: 1, total: 1 }; + } + print.conditionally(true, 'zos.getEsms', 'no parameter', result); + return { errors: 0, total: 1 }; +} + + +export function test_dslist() { + const FAILS = [ ...test.CLASSIC_FAILS, 'sys1.maclib' ]; + const FINES = [ 'SYS1.PARMLIB', 'SYS1.MACLIB' ]; + + let errs = test.process(zos.dslist, FAILS, null, 'zos.dslist'); + for (let f in FINES) { + const result = zos.dslist(FINES[f]); + errs += print.conditionally(result.datasets[0].dsn == FINES[f], 'zos.dslist', FINES[f], result); + } + return { errors: errs, total: FAILS.length + FINES.length } +} + + +export function test_resolveSymbol() { + const result = zos.resolveSymbol('&YYMMDD'); + const date = new Date(); + const yymmdd = (date.getFullYear() - 2000) * 10000 + (date.getMonth() + 1) * 100 + date.getDate() + ''; + let errs = 0; + + errs += print.conditionally(result == yymmdd, 'zos.resolveSymbol', '&YYMMDD', result, `javascript date -> ${yymmdd}`); + + const ERR_SYMBOLS = [ ...test.CLASSIC_FAILS, 'YYMMDD', ' &', ['a', 'b'], '& UNDEFINED SYMBOL !@#$%^&*()' ]; + errs += test.process(zos.resolveSymbol, ERR_SYMBOLS, '', 'zos.resolveSymbol'); + + return { errors: errs, total : ERR_SYMBOLS.length + 1 };; +} + + +export function test_getStatvfs() { + const PATHS_OK = [ './', '/', '/bin/' ]; + const PATHS_ERR = [ ...test.CLASSIC_FAILS, '/aaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbb/ccccccccccccccccccccccc' ]; + let errs = 0; + + for (let p in PATHS_OK) { + const result = zos.getStatvfs(PATHS_OK[p]); + errs += print.conditionally(result[1] == 0, 'zos.getStatvfs', PATHS_OK[p], result); + } + + for (let p in PATHS_ERR) { + const result = zos.getStatvfs(PATHS_ERR[p]); + errs += print.conditionally(result[1] != 0, 'zos.getStatvfs', PATHS_ERR[p], result[1]); + } + + return { errors: errs, total: PATHS_ERR.length + PATHS_OK.length }; +}