/* * Copyright (c) 2019 Christian Schoenebeck * * http://www.linuxsampler.org * * This file is part of LinuxSampler and released under the same terms. * See README file for details. */ // This file contains automated test cases against the NKSP real-time // instrument script engine. #include "../../common/global.h" #include "../../common/optional.h" #include "../../common/RTMath.h" #include "../ScriptVM.h" #include "../common.h" #include #include #include #include #include #ifndef TEST_ASSERT # define TEST_ASSERT assert #endif using namespace LinuxSampler; using namespace std; struct RunScriptOpt { String code; bool expectParseError; bool expectRuntimeError; bool expectNoExitResult; bool prohibitExitFunctionArguments; optional expectIntExitResult; optional expectBoolExitResult; optional expectRealExitResult; optional expectStringExitResult; }; static void runScript(const RunScriptOpt& opt) { ScriptVM vm; vm.setAutoSuspendEnabled(false); if (!opt.prohibitExitFunctionArguments) vm.setExitResultEnabled(true); unique_ptr parserCtx( vm.loadScript(opt.code) ); vector errors = parserCtx->errors(); if (opt.expectParseError) { TEST_ASSERT(!errors.empty()); return; } else { for (ParserIssue& err : errors) { err.dump(); } TEST_ASSERT(errors.empty()); } TEST_ASSERT(parserCtx->eventHandler(0)); unique_ptr execCtx( vm.createExecContext(&*parserCtx) ); for (int i = 0; parserCtx->eventHandler(i); ++i) { VMEventHandler* handler = parserCtx->eventHandler(i); VMExecStatus_t result = vm.exec(&*parserCtx, &*execCtx, handler); if (opt.expectRuntimeError) { TEST_ASSERT(result & VM_EXEC_ERROR); } else { TEST_ASSERT(!(result & VM_EXEC_ERROR)); } if (opt.expectNoExitResult) { VMExpr* resExpr = execCtx->exitResult(); TEST_ASSERT(!resExpr); } if (opt.expectIntExitResult) { VMExpr* resExpr = execCtx->exitResult(); TEST_ASSERT(resExpr); TEST_ASSERT(resExpr->exprType() == INT_EXPR); TEST_ASSERT(resExpr->asInt()->evalInt() == *opt.expectIntExitResult); } if (opt.expectRealExitResult) { VMExpr* resExpr = execCtx->exitResult(); TEST_ASSERT(resExpr); TEST_ASSERT(resExpr->exprType() == REAL_EXPR); if (sizeof(vmfloat) == sizeof(float)) { TEST_ASSERT(RTMath::fEqual32(resExpr->asReal()->evalReal(), *opt.expectRealExitResult)); } else { TEST_ASSERT(RTMath::fEqual64(resExpr->asReal()->evalReal(), *opt.expectRealExitResult)); } } if (opt.expectBoolExitResult) { VMExpr* resExpr = execCtx->exitResult(); TEST_ASSERT(resExpr); TEST_ASSERT(resExpr->exprType() == INT_EXPR); TEST_ASSERT(bool(resExpr->asInt()->evalInt()) == *opt.expectBoolExitResult); } if (opt.expectStringExitResult) { VMExpr* resExpr = execCtx->exitResult(); TEST_ASSERT(resExpr); TEST_ASSERT(resExpr->exprType() == STRING_EXPR); TEST_ASSERT(resExpr->asString()->evalStr() == *opt.expectStringExitResult); } } } static void testBuiltInExitFunction() { #if !SILENT_TEST std::cout << "UNIT TEST: built-in exit() function\n"; #endif runScript({ .code = R"NKSP_CODE( on init end on )NKSP_CODE", .expectNoExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit end on )NKSP_CODE", .expectNoExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit() end on )NKSP_CODE", .expectNoExitResult = true }); // integer tests ... runScript({ .code = R"NKSP_CODE( on init exit(42) end on )NKSP_CODE", .expectIntExitResult = 42 }); runScript({ .code = R"NKSP_CODE( on init declare $foo := 1 if ($foo) exit(21) end if end on )NKSP_CODE", .expectIntExitResult = 21 }); runScript({ .code = R"NKSP_CODE( on init declare $foo := 0 if ($foo) exit(21) end if exit(99) end on )NKSP_CODE", .expectIntExitResult = 99 }); // string tests ... runScript({ .code = R"NKSP_CODE( on init exit("fourtytwo!") end on )NKSP_CODE", .expectStringExitResult = "fourtytwo!" }); // in production environment we prohibit the built-in exit() function to // accept any arguments runScript({ .code = R"NKSP_CODE( on init exit(42) end on )NKSP_CODE", .expectParseError = true, // see comment above why .prohibitExitFunctionArguments = true // simulate production environment }); // real number tests ... runScript({ .code = R"NKSP_CODE( on init exit(3.14) end on )NKSP_CODE", .expectRealExitResult = 3.14 }); runScript({ .code = R"NKSP_CODE( on init declare $foo := 1 if ($foo) exit(3.14) end if end on )NKSP_CODE", .expectRealExitResult = 3.14 }); runScript({ .code = R"NKSP_CODE( on init declare $foo := 0 if ($foo) exit(3.14) end if exit(6.9) end on )NKSP_CODE", .expectRealExitResult = 6.9 }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testStringConcatOperator() { #if !SILENT_TEST std::cout << "UNIT TEST: string concatenation (&) operator\n"; #endif runScript({ .code = R"NKSP_CODE( on init declare @s := "foo" & " bar" exit(@s) end on )NKSP_CODE", .expectStringExitResult = "foo bar" }); runScript({ .code = R"NKSP_CODE( on init declare @s := "foo" & " bar" & " " & 123 exit(@s) end on )NKSP_CODE", .expectStringExitResult = "foo bar 123" }); runScript({ .code = R"NKSP_CODE( on init declare $i := 123 declare @s := "foo" & " bar" & " " & $i exit(@s) end on )NKSP_CODE", .expectStringExitResult = "foo bar 123" }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testNegOperator() { #if !SILENT_TEST std::cout << "UNIT TEST: negate (-) operator\n"; #endif // integer tests ... runScript({ .code = R"NKSP_CODE( on init exit(-87) end on )NKSP_CODE", .expectIntExitResult = -87 }); runScript({ .code = R"NKSP_CODE( on init declare $foo := -87 exit(-$foo) end on )NKSP_CODE", .expectIntExitResult = 87 }); // real number tests ... runScript({ .code = R"NKSP_CODE( on init exit(-99.3) end on )NKSP_CODE", .expectRealExitResult = -99.3 }); runScript({ .code = R"NKSP_CODE( on init declare ~foo := -99.3 exit(-~foo) end on )NKSP_CODE", .expectRealExitResult = 99.3 }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testPlusOperator() { #if !SILENT_TEST std::cout << "UNIT TEST: plus (+) operator\n"; #endif // integer tests ... runScript({ .code = R"NKSP_CODE( on init exit(4 + 3) end on )NKSP_CODE", .expectIntExitResult = 7 }); runScript({ .code = R"NKSP_CODE( on init exit(42 + 145) end on )NKSP_CODE", .expectIntExitResult = 187 }); runScript({ .code = R"NKSP_CODE( on init exit(-4 + 2) end on )NKSP_CODE", .expectIntExitResult = -2 }); // real number tests ... runScript({ .code = R"NKSP_CODE( on init exit(4.0 + 3.0) end on )NKSP_CODE", .expectRealExitResult = 7.0 }); runScript({ .code = R"NKSP_CODE( on init exit(42.3 + 145.2) end on )NKSP_CODE", .expectRealExitResult = 187.5 }); runScript({ .code = R"NKSP_CODE( on init exit(-4.0 + 2.2) end on )NKSP_CODE", .expectRealExitResult = -1.8 }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testMinusOperator() { #if !SILENT_TEST std::cout << "UNIT TEST: minus (-) operator\n"; #endif // integer tests ... runScript({ .code = R"NKSP_CODE( on init exit(4 - 3) end on )NKSP_CODE", .expectIntExitResult = 1 }); runScript({ .code = R"NKSP_CODE( on init exit(139 - 74) end on )NKSP_CODE", .expectIntExitResult = 65 }); runScript({ .code = R"NKSP_CODE( on init exit(3 - 9) end on )NKSP_CODE", .expectIntExitResult = -6 }); runScript({ .code = R"NKSP_CODE( on init exit(-3 - 18) end on )NKSP_CODE", .expectIntExitResult = -21 }); // real number tests ... runScript({ .code = R"NKSP_CODE( on init exit(4.0 - 0.2) end on )NKSP_CODE", .expectRealExitResult = 3.8 }); runScript({ .code = R"NKSP_CODE( on init exit(3.1 - 9.65) end on )NKSP_CODE", .expectRealExitResult = -6.55 }); runScript({ .code = R"NKSP_CODE( on init exit(-3.0 - 18.1) end on )NKSP_CODE", .expectRealExitResult = -21.1 }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testModuloOperator() { #if !SILENT_TEST std::cout << "UNIT TEST: modulo (mod) operator\n"; #endif // integer tests ... runScript({ .code = R"NKSP_CODE( on init exit(10 mod 8) end on )NKSP_CODE", .expectIntExitResult = 2 }); runScript({ .code = R"NKSP_CODE( on init declare $a := 10 declare $b := 8 exit($a mod $b) end on )NKSP_CODE", .expectIntExitResult = 2 }); // real number tests ... // (mod operator prohibits real numbers ATM) runScript({ .code = R"NKSP_CODE( on init exit(10.0 mod 8.0) end on )NKSP_CODE", .expectParseError = true // mod operator prohibits real numbers ATM }); runScript({ .code = R"NKSP_CODE( on init exit(10 mod 8.0) end on )NKSP_CODE", .expectParseError = true // mod operator prohibits real numbers ATM }); runScript({ .code = R"NKSP_CODE( on init exit(10.0 mod 8) end on )NKSP_CODE", .expectParseError = true // mod operator prohibits real numbers ATM }); runScript({ .code = R"NKSP_CODE( on init declare ~a := 10.0 declare ~b := 8.0 exit(~a mod ~b) end on )NKSP_CODE", .expectParseError = true // mod operator prohibits real numbers ATM }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testMultiplyOperator() { #if !SILENT_TEST std::cout << "UNIT TEST: multiply (*) operator\n"; #endif // integer tests ... runScript({ .code = R"NKSP_CODE( on init exit(10 * 8) end on )NKSP_CODE", .expectIntExitResult = 80 }); runScript({ .code = R"NKSP_CODE( on init exit(-3 * -4) end on )NKSP_CODE", .expectIntExitResult = 12 }); runScript({ .code = R"NKSP_CODE( on init exit(-52 * 63) end on )NKSP_CODE", .expectIntExitResult = -3276 }); runScript({ .code = R"NKSP_CODE( on init exit(123 * -59) end on )NKSP_CODE", .expectIntExitResult = -7257 }); // real number tests ... runScript({ .code = R"NKSP_CODE( on init exit(10.2 * 8.4) end on )NKSP_CODE", .expectRealExitResult = 85.68 }); runScript({ .code = R"NKSP_CODE( on init exit(10.0 * -3.33) end on )NKSP_CODE", .expectRealExitResult = -33.3 }); runScript({ .code = R"NKSP_CODE( on init exit(-3.33 * 10.0) end on )NKSP_CODE", .expectRealExitResult = -33.3 }); runScript({ .code = R"NKSP_CODE( on init exit(-3.33 * -10.0) end on )NKSP_CODE", .expectRealExitResult = 33.3 }); // mixed type tests ... // (mixed int * real forbidden ATM) runScript({ .code = R"NKSP_CODE( on init exit(2 * 3.0) end on )NKSP_CODE", .expectParseError = true // mixed int * real forbidden ATM }); runScript({ .code = R"NKSP_CODE( on init exit(2.0 * 3) end on )NKSP_CODE", .expectParseError = true // mixed int * real forbidden ATM }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testDivideOperator() { #if !SILENT_TEST std::cout << "UNIT TEST: divide (/) operator\n"; #endif // integer tests ... runScript({ .code = R"NKSP_CODE( on init exit(9 / 3) end on )NKSP_CODE", .expectIntExitResult = 3 }); runScript({ .code = R"NKSP_CODE( on init exit(-27 / 3) end on )NKSP_CODE", .expectIntExitResult = -9 }); runScript({ .code = R"NKSP_CODE( on init exit(35 / -5) end on )NKSP_CODE", .expectIntExitResult = -7 }); runScript({ .code = R"NKSP_CODE( on init exit(39 / -5) end on )NKSP_CODE", .expectIntExitResult = -7 }); // real number tests ... runScript({ .code = R"NKSP_CODE( on init exit(9.0 / 10.0) end on )NKSP_CODE", .expectRealExitResult = 0.9 }); runScript({ .code = R"NKSP_CODE( on init exit(-9.0 / 10.0) end on )NKSP_CODE", .expectRealExitResult = -0.9 }); runScript({ .code = R"NKSP_CODE( on init exit(9.0 / -10.0) end on )NKSP_CODE", .expectRealExitResult = -0.9 }); runScript({ .code = R"NKSP_CODE( on init exit(-9.0 / -10.0) end on )NKSP_CODE", .expectRealExitResult = 0.9 }); // mixed type tests ... // (mixed int / real forbidden ATM) runScript({ .code = R"NKSP_CODE( on init exit(9 / 10.0) end on )NKSP_CODE", .expectParseError = true // mixed int / real forbidden ATM }); runScript({ .code = R"NKSP_CODE( on init exit(9.0 / 10) end on )NKSP_CODE", .expectParseError = true // mixed int / real forbidden ATM }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testSmallerThanOperator() { #if !SILENT_TEST std::cout << "UNIT TEST: smaller than (<) operator\n"; #endif // integer tests ... runScript({ .code = R"NKSP_CODE( on init exit(3 < 4) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(4 < 3) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(-4 < 3) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(3 < -4) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(123 < -45) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(-45 < 123) end on )NKSP_CODE", .expectBoolExitResult = true }); // real number tests ... runScript({ .code = R"NKSP_CODE( on init exit(3.0 < 4.0) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(4.0 < 3.0) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(1.2 < 1.23) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(1.23 < 1.2) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(-4.0 < 3.0) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(3.0 < -4.0) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(123.0 < -45.0) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(-45.0 < 123.0) end on )NKSP_CODE", .expectBoolExitResult = true }); // mixed type tests ... runScript({ .code = R"NKSP_CODE( on init exit(9 < 9.1) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(9.1 < 9) end on )NKSP_CODE", .expectBoolExitResult = false }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testGreaterThanOperator() { #if !SILENT_TEST std::cout << "UNIT TEST: greater than (>) operator\n"; #endif // integer tests ... runScript({ .code = R"NKSP_CODE( on init exit(3 > 4) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(4 > 3) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(-4 > 3) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(3 > -4) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(123 > -45) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(-45 > 123) end on )NKSP_CODE", .expectBoolExitResult = false }); // real number tests ... runScript({ .code = R"NKSP_CODE( on init exit(3.0 > 4.0) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(4.0 > 3.0) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(1.2 > 1.23) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(1.23 > 1.2) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(-4.0 > 3.0) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(3.0 > -4.0) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(123.0 > -45.0) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(-45.0 > 123.0) end on )NKSP_CODE", .expectBoolExitResult = false }); // mixed type tests ... runScript({ .code = R"NKSP_CODE( on init exit(9 > 9.1) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(9.1 > 9) end on )NKSP_CODE", .expectBoolExitResult = true }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testSmallerOrEqualOperator() { #if !SILENT_TEST std::cout << "UNIT TEST: smaller-or-equal (<=) operator\n"; #endif // integer tests ... runScript({ .code = R"NKSP_CODE( on init exit(3 <= 3) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(4 <= 4) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(-23 <= -23) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(23 <= -23) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(3 <= 4) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(4 <= 3) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(-4 <= 3) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(3 <= -4) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(123 <= -45) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(-45 <= 123) end on )NKSP_CODE", .expectBoolExitResult = true }); // real number tests ... runScript({ .code = R"NKSP_CODE( on init exit(3.0 <= 3.0) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(4.33 <= 4.33) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(-23.1 <= -23.1) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(23.3 <= -23.3) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(3.0 <= 4.0) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(4.0 <= 3.0) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(-4.0 <= 3.0) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(3.0 <= -4.0) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(123.0 <= -45.0) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(-45.0 <= 123.0) end on )NKSP_CODE", .expectBoolExitResult = true }); // mixed type tests ... runScript({ .code = R"NKSP_CODE( on init exit(9 <= 9.1) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(9.1 <= 9) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(9 <= 9.0) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(9.0 <= 9) end on )NKSP_CODE", .expectBoolExitResult = true }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testGreaterOrEqualOperator() { #if !SILENT_TEST std::cout << "UNIT TEST: greater-or-equal (>=) operator\n"; #endif // integer tests ... runScript({ .code = R"NKSP_CODE( on init exit(3 >= 3) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(4 >= 4) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(-23 >= -23) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(23 >= -23) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(3 >= 4) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(4 >= 3) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(-4 >= 3) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(3 >= -4) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(123 >= -45) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(-45 >= 123) end on )NKSP_CODE", .expectBoolExitResult = false }); // real number tests ... runScript({ .code = R"NKSP_CODE( on init exit(3.0 >= 3.0) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(3.1 >= 3.1) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(3.1 >= 3.0) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(3.0 >= 3.1) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(-23.33 >= -23.33) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(23.0 >= -23.0) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(3.0 >= 4.0) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(4.0 >= 3.0) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(-4.0 >= 3.0) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(3.0 >= -4.0) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(123.0 >= -45.0) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(-45.0 >= 123.0) end on )NKSP_CODE", .expectBoolExitResult = false }); // mixed type tests ... runScript({ .code = R"NKSP_CODE( on init exit(9 >= 9.1) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(9.1 >= 9) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(9 >= 9.0) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(9.0 >= 9) end on )NKSP_CODE", .expectBoolExitResult = true }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testEqualOperator() { #if !SILENT_TEST std::cout << "UNIT TEST: equal (=) operator\n"; #endif // integer tests ... runScript({ .code = R"NKSP_CODE( on init exit(3 = 3) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(4 = 4) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(3 = 4) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(23 = -23) end on )NKSP_CODE", .expectBoolExitResult = false }); // real number tests ... runScript({ .code = R"NKSP_CODE( on init exit(3.0 = 3.0) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(4.33 = 4.33) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(4.31 = 4.35) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(3.0 = 4.0) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(23.0 = -23.0) end on )NKSP_CODE", .expectBoolExitResult = false }); // mixed type tests ... runScript({ .code = R"NKSP_CODE( on init exit(23 = 23.0) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(23.0 = 23) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(23 = 23.1) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(23.1 = 23) end on )NKSP_CODE", .expectBoolExitResult = false }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testUnequalOperator() { #if !SILENT_TEST std::cout << "UNIT TEST: unequal (#) operator\n"; #endif // integer tests ... runScript({ .code = R"NKSP_CODE( on init exit(3 # 3) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(4 # 4) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(3 # 4) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(23 # -23) end on )NKSP_CODE", .expectBoolExitResult = true }); // real number tests ... runScript({ .code = R"NKSP_CODE( on init exit(3.0 # 3.0) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(3.14 # 3.14) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(3.19 # 3.12) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(23.0 # -23.0) end on )NKSP_CODE", .expectBoolExitResult = true }); // mixed type tests ... runScript({ .code = R"NKSP_CODE( on init exit(3 # 3.0) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(3.0 # 3) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(3.1 # 3) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(3 # 3.1) end on )NKSP_CODE", .expectBoolExitResult = true }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testLogicalAndOperator() { #if !SILENT_TEST std::cout << "UNIT TEST: logical and (and) operator\n"; #endif // integer tests ... runScript({ .code = R"NKSP_CODE( on init exit(1 and 1) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(1 and 2) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(1 and 3) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(1 and 0) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(0 and 1) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(0 and 0) end on )NKSP_CODE", .expectBoolExitResult = false }); // real number tests ... // (not allowed for this operator) runScript({ .code = R"NKSP_CODE( on init exit(1.0 and 1.0) end on )NKSP_CODE", .expectParseError = true // real numbers not allowed for this operator }); // mixed type tests ... // (not allowed for this operator) runScript({ .code = R"NKSP_CODE( on init exit(1.0 and 1) end on )NKSP_CODE", .expectParseError = true // real numbers not allowed for this operator }); runScript({ .code = R"NKSP_CODE( on init exit(1 and 1.0) end on )NKSP_CODE", .expectParseError = true // real numbers not allowed for this operator }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testLogicalOrOperator() { #if !SILENT_TEST std::cout << "UNIT TEST: logical or (or) operator\n"; #endif // integer tests ... runScript({ .code = R"NKSP_CODE( on init exit(1 or 1) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(1 or 2) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(1 or 3) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(1 or 0) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(0 or 1) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit(0 or 0) end on )NKSP_CODE", .expectBoolExitResult = false }); // real number tests ... // (not allowed for this operator) runScript({ .code = R"NKSP_CODE( on init exit(1.0 or 1.0) end on )NKSP_CODE", .expectParseError = true // real numbers not allowed for this operator }); // mixed type tests ... // (not allowed for this operator) runScript({ .code = R"NKSP_CODE( on init exit(1.0 or 1) end on )NKSP_CODE", .expectParseError = true // real numbers not allowed for this operator }); runScript({ .code = R"NKSP_CODE( on init exit(1 or 1.0) end on )NKSP_CODE", .expectParseError = true // real numbers not allowed for this operator }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testLogicalNotOperator() { #if !SILENT_TEST std::cout << "UNIT TEST: logical not (not) operator\n"; #endif // integer tests ... runScript({ .code = R"NKSP_CODE( on init exit(not 1) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(not 2) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit(not 0) end on )NKSP_CODE", .expectBoolExitResult = true }); // real number tests ... // (not allowed for this operator) runScript({ .code = R"NKSP_CODE( on init exit(not 1.0) end on )NKSP_CODE", .expectParseError = true // real numbers not allowed for this operator }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testBitwiseAndOperator() { #if !SILENT_TEST std::cout << "UNIT TEST: bitwise and (.and.) operator\n"; #endif // integer tests ... runScript({ .code = R"NKSP_CODE( on init exit(1 .and. 1) end on )NKSP_CODE", .expectIntExitResult = 1 }); runScript({ .code = R"NKSP_CODE( on init exit(43 .and. 142) end on )NKSP_CODE", .expectIntExitResult = 10 }); // real number tests ... // (not allowed for this operator) runScript({ .code = R"NKSP_CODE( on init exit(1.0 .and. 1.0) end on )NKSP_CODE", .expectParseError = true // real numbers not allowed for this operator }); // mixed type tests ... // (not allowed for this operator) runScript({ .code = R"NKSP_CODE( on init exit(1.0 .and. 1) end on )NKSP_CODE", .expectParseError = true // real numbers not allowed for this operator }); runScript({ .code = R"NKSP_CODE( on init exit(1 .and. 1.0) end on )NKSP_CODE", .expectParseError = true // real numbers not allowed for this operator }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testBitwiseOrOperator() { #if !SILENT_TEST std::cout << "UNIT TEST: bitwise or (.or.) operator\n"; #endif // integer tests ... runScript({ .code = R"NKSP_CODE( on init exit(1 .or. 1) end on )NKSP_CODE", .expectIntExitResult = 1 }); runScript({ .code = R"NKSP_CODE( on init exit(0 .or. 0) end on )NKSP_CODE", .expectIntExitResult = 0 }); runScript({ .code = R"NKSP_CODE( on init exit(43 .or. 142) end on )NKSP_CODE", .expectIntExitResult = 175 }); // real number tests ... // (not allowed for this operator) runScript({ .code = R"NKSP_CODE( on init exit(1.0 .or. 1.0) end on )NKSP_CODE", .expectParseError = true // real numbers not allowed for this operator }); // mixed type tests ... // (not allowed for this operator) runScript({ .code = R"NKSP_CODE( on init exit(1.0 .or. 1) end on )NKSP_CODE", .expectParseError = true // real numbers not allowed for this operator }); runScript({ .code = R"NKSP_CODE( on init exit(1 .or. 1.0) end on )NKSP_CODE", .expectParseError = true // real numbers not allowed for this operator }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testBitwiseNotOperator() { #if !SILENT_TEST std::cout << "UNIT TEST: bitwise not (.not.) operator\n"; #endif // integer tests ... runScript({ .code = R"NKSP_CODE( on init exit(.not. -1) end on )NKSP_CODE", .expectIntExitResult = 0 }); runScript({ .code = R"NKSP_CODE( on init exit(.not. 0) end on )NKSP_CODE", .expectIntExitResult = -1 }); runScript({ .code = R"NKSP_CODE( on init exit(.not. 3) end on )NKSP_CODE", .expectIntExitResult = ssize_t(size_t(-1) << 2) }); // real number tests ... // (not allowed for this operator) runScript({ .code = R"NKSP_CODE( on init exit(.not. 1.0) end on )NKSP_CODE", .expectParseError = true // real numbers not allowed for this operator }); runScript({ .code = R"NKSP_CODE( on init exit(.not. -1.0) end on )NKSP_CODE", .expectParseError = true // real numbers not allowed for this operator }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testPrecedenceOfOperators() { #if !SILENT_TEST std::cout << "UNIT TEST: precedence of operators\n"; #endif // integer tests ... runScript({ .code = R"NKSP_CODE( on init exit(3 + 4 * 2) end on )NKSP_CODE", .expectIntExitResult = 11 }); runScript({ .code = R"NKSP_CODE( on init exit(4 * 2 + 3) end on )NKSP_CODE", .expectIntExitResult = 11 }); runScript({ .code = R"NKSP_CODE( on init exit((3 + 4) * 2) end on )NKSP_CODE", .expectIntExitResult = 14 }); runScript({ .code = R"NKSP_CODE( on init exit(4 * (2 + 3)) end on )NKSP_CODE", .expectIntExitResult = 20 }); // real number tests ... runScript({ .code = R"NKSP_CODE( on init exit(3.2 + 4.0 * 2.0) end on )NKSP_CODE", .expectRealExitResult = 11.2 }); runScript({ .code = R"NKSP_CODE( on init exit(4.0 * 2.0 + 3.2) end on )NKSP_CODE", .expectRealExitResult = 11.2 }); runScript({ .code = R"NKSP_CODE( on init exit((3.2 + 4.0) * 2.0) end on )NKSP_CODE", .expectRealExitResult = 14.4 }); runScript({ .code = R"NKSP_CODE( on init exit(4.0 * (2.0 + 3.2)) end on )NKSP_CODE", .expectRealExitResult = 20.8 }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testBuiltInMinFunction() { #if !SILENT_TEST std::cout << "UNIT TEST: built-in min() function\n"; #endif runScript({ .code = R"NKSP_CODE( on init declare $foo := min end on )NKSP_CODE", .expectParseError = true // because min() function requires 2 arguments }); runScript({ .code = R"NKSP_CODE( on init declare $foo := min() end on )NKSP_CODE", .expectParseError = true // because min() function requires 2 arguments }); runScript({ .code = R"NKSP_CODE( on init declare $foo := min(1) end on )NKSP_CODE", .expectParseError = true // because min() function requires 2 arguments }); runScript({ .code = R"NKSP_CODE( on init declare $foo := min(1,2) exit($foo) end on )NKSP_CODE", .expectIntExitResult = 1 }); runScript({ .code = R"NKSP_CODE( on init declare $foo := min(-30,4) exit($foo) end on )NKSP_CODE", .expectIntExitResult = -30 }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testBuiltInMaxFunction() { #if !SILENT_TEST std::cout << "UNIT TEST: built-in max() function\n"; #endif runScript({ .code = R"NKSP_CODE( on init declare $foo := max end on )NKSP_CODE", .expectParseError = true // because max() function requires 2 arguments }); runScript({ .code = R"NKSP_CODE( on init declare $foo := max() end on )NKSP_CODE", .expectParseError = true // because max() function requires 2 arguments }); runScript({ .code = R"NKSP_CODE( on init declare $foo := max(1) end on )NKSP_CODE", .expectParseError = true // because max() function requires 2 arguments }); runScript({ .code = R"NKSP_CODE( on init declare $foo := max(1,2) exit($foo) end on )NKSP_CODE", .expectIntExitResult = 2 }); runScript({ .code = R"NKSP_CODE( on init declare $foo := max(-30,4) exit($foo) end on )NKSP_CODE", .expectIntExitResult = 4 }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testBuiltInAbsFunction() { #if !SILENT_TEST std::cout << "UNIT TEST: built-in abs() function\n"; #endif runScript({ .code = R"NKSP_CODE( on init declare $foo := abs end on )NKSP_CODE", .expectParseError = true // because abs() function requires 1 argument }); runScript({ .code = R"NKSP_CODE( on init declare $foo := abs() end on )NKSP_CODE", .expectParseError = true // because abs() function requires 1 argument }); runScript({ .code = R"NKSP_CODE( on init declare $foo := abs(23) exit($foo) end on )NKSP_CODE", .expectIntExitResult = 23 }); runScript({ .code = R"NKSP_CODE( on init declare $foo := abs(-23) exit($foo) end on )NKSP_CODE", .expectIntExitResult = 23 }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testBuiltInIncFunction() { #if !SILENT_TEST std::cout << "UNIT TEST: built-in inc() function\n"; #endif runScript({ .code = R"NKSP_CODE( on init declare $foo := 5 inc($foo) exit($foo) end on )NKSP_CODE", .expectIntExitResult = 6 }); runScript({ .code = R"NKSP_CODE( on init declare $foo := 5 inc($foo) inc($foo) inc($foo) exit($foo) end on )NKSP_CODE", .expectIntExitResult = 8 }); runScript({ .code = R"NKSP_CODE( on init declare $foo := 5 inc($foo) exit( inc($foo) ) end on )NKSP_CODE", .expectIntExitResult = 7 }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testBuiltInDecFunction() { #if !SILENT_TEST std::cout << "UNIT TEST: built-in dec() function\n"; #endif runScript({ .code = R"NKSP_CODE( on init declare $foo := 5 dec($foo) exit($foo) end on )NKSP_CODE", .expectIntExitResult = 4 }); runScript({ .code = R"NKSP_CODE( on init declare $foo := 5 dec($foo) dec($foo) dec($foo) exit($foo) end on )NKSP_CODE", .expectIntExitResult = 2 }); runScript({ .code = R"NKSP_CODE( on init declare $foo := 5 dec($foo) exit( dec($foo) ) end on )NKSP_CODE", .expectIntExitResult = 3 }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testBuiltInInRangeFunction() { #if !SILENT_TEST std::cout << "UNIT TEST: built-in in_range() function\n"; #endif runScript({ .code = R"NKSP_CODE( on init exit( in_range(1,4,9) ) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit( in_range(5,4,9) ) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit( in_range(9,4,9) ) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit( in_range(10,4,9) ) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit( in_range(-6,-5,5) ) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init exit( in_range(-5,-5,5) ) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit( in_range(0,-5,5) ) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit( in_range(5,-5,5) ) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init exit( in_range(6,-5,5) ) end on )NKSP_CODE", .expectBoolExitResult = false }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testBuiltInRandomFunction() { #if !SILENT_TEST std::cout << "UNIT TEST: built-in random() function\n"; #endif for (int run = 0; run < 20; ++run) { runScript({ .code = R"NKSP_CODE( on init declare $foo := random(-5,5) exit( in_range($foo,-5,5) ) end on )NKSP_CODE", .expectBoolExitResult = true }); } #if !SILENT_TEST std::cout << std::endl; #endif } static void testBuiltInShiftLeftFunction() { #if !SILENT_TEST std::cout << "UNIT TEST: built-in sh_left() function\n"; #endif runScript({ .code = R"NKSP_CODE( on init exit( sh_left(1,0) ) end on )NKSP_CODE", .expectIntExitResult = 1 }); runScript({ .code = R"NKSP_CODE( on init exit( sh_left(1,1) ) end on )NKSP_CODE", .expectIntExitResult = 2 }); runScript({ .code = R"NKSP_CODE( on init exit( sh_left(1,2) ) end on )NKSP_CODE", .expectIntExitResult = 4 }); runScript({ .code = R"NKSP_CODE( on init exit( sh_left(1,3) ) end on )NKSP_CODE", .expectIntExitResult = 8 }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testBuiltInShiftRightFunction() { #if !SILENT_TEST std::cout << "UNIT TEST: built-in sh_right() function\n"; #endif runScript({ .code = R"NKSP_CODE( on init exit( sh_right(8,0) ) end on )NKSP_CODE", .expectIntExitResult = 8 }); runScript({ .code = R"NKSP_CODE( on init exit( sh_right(8,1) ) end on )NKSP_CODE", .expectIntExitResult = 4 }); runScript({ .code = R"NKSP_CODE( on init exit( sh_right(8,2) ) end on )NKSP_CODE", .expectIntExitResult = 2 }); runScript({ .code = R"NKSP_CODE( on init exit( sh_right(8,3) ) end on )NKSP_CODE", .expectIntExitResult = 1 }); runScript({ .code = R"NKSP_CODE( on init exit( sh_right(8,4) ) end on )NKSP_CODE", .expectIntExitResult = 0 }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testBuiltInIntToRealFunction() { #if !SILENT_TEST std::cout << "UNIT TEST: built-in int_to_real() function\n"; #endif runScript({ .code = R"NKSP_CODE( on init exit( int_to_real(8) ) end on )NKSP_CODE", .expectRealExitResult = 8.0 }); runScript({ .code = R"NKSP_CODE( on init declare $foo := 23 exit( int_to_real($foo) ) end on )NKSP_CODE", .expectRealExitResult = 23.0 }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testBuiltInRealFunction() { #if !SILENT_TEST std::cout << "UNIT TEST: built-in real() function\n"; #endif runScript({ .code = R"NKSP_CODE( on init exit( real(8) ) end on )NKSP_CODE", .expectRealExitResult = 8.0 }); runScript({ .code = R"NKSP_CODE( on init declare $foo := 23 exit( real($foo) ) end on )NKSP_CODE", .expectRealExitResult = 23.0 }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testBuiltInRealToIntFunction() { #if !SILENT_TEST std::cout << "UNIT TEST: built-in real_to_int() function\n"; #endif runScript({ .code = R"NKSP_CODE( on init exit( real_to_int(8.9) ) end on )NKSP_CODE", .expectIntExitResult = 8 }); runScript({ .code = R"NKSP_CODE( on init declare ~foo := 8.9 exit( real_to_int(~foo) ) end on )NKSP_CODE", .expectIntExitResult = 8 }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testBuiltInIntFunction() { #if !SILENT_TEST std::cout << "UNIT TEST: built-in int() function\n"; #endif runScript({ .code = R"NKSP_CODE( on init exit( int(8.9) ) end on )NKSP_CODE", .expectIntExitResult = 8 }); runScript({ .code = R"NKSP_CODE( on init declare ~foo := 8.9 exit( int(~foo) ) end on )NKSP_CODE", .expectIntExitResult = 8 }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testBuiltInArrayEqualFunction() { #if !SILENT_TEST std::cout << "UNIT TEST: built-in array_equal() function\n"; #endif runScript({ .code = R"NKSP_CODE( on init declare %foo[3] := ( 1, 2, 3 ) declare %bar[3] := ( 1, 2, 3 ) exit( array_equal(%foo, %bar) ) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init declare %foo[1] := ( 1 ) declare %bar[1] := ( 1 ) exit( array_equal(%foo, %bar) ) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init declare %foo[3] := ( 1, 2, 3 ) declare %bar[3] := ( 0, 2, 3 ) exit( array_equal(%foo, %bar) ) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init declare %foo[3] := ( 1, 2, 3 ) declare %bar[3] := ( 3, 2, 1 ) exit( array_equal(%foo, %bar) ) end on )NKSP_CODE", .expectBoolExitResult = false }); runScript({ .code = R"NKSP_CODE( on init declare %foo[3] := ( 1, 2, 3 ) declare %bar[2] := ( 1, 2 ) exit( array_equal(%foo, %bar) ) end on )NKSP_CODE", .expectBoolExitResult = false }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testBuiltInSortFunction() { #if !SILENT_TEST std::cout << "UNIT TEST: built-in sort() function\n"; #endif runScript({ .code = R"NKSP_CODE( on init declare %input[3] := ( 19, 3, 6 ) declare %expected[3] := ( 3, 6, 19 ) sort(%input, 0) exit( array_equal(%input, %expected) ) end on )NKSP_CODE", .expectBoolExitResult = true }); runScript({ .code = R"NKSP_CODE( on init declare %input[3] := ( 19, 3, 6 ) declare %expected[3] := ( 19, 6, 3 ) sort(%input, 1) exit( array_equal(%input, %expected) ) end on )NKSP_CODE", .expectBoolExitResult = true }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testBuiltInNumElementsFunction() { #if !SILENT_TEST std::cout << "UNIT TEST: built-in num_elements() function\n"; #endif runScript({ .code = R"NKSP_CODE( on init declare %foo[3] := ( 19, 3, 6 ) exit( num_elements(%foo) ) end on )NKSP_CODE", .expectIntExitResult = 3 }); runScript({ .code = R"NKSP_CODE( on init declare %foo[1] := ( 19 ) exit( num_elements(%foo) ) end on )NKSP_CODE", .expectIntExitResult = 1 }); runScript({ .code = R"NKSP_CODE( on init declare %foo[5] := ( 1, 2, 3, 4, 5 ) exit( num_elements(%foo) ) end on )NKSP_CODE", .expectIntExitResult = 5 }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testBuiltInSearchFunction() { #if !SILENT_TEST std::cout << "UNIT TEST: built-in search() function\n"; #endif runScript({ .code = R"NKSP_CODE( on init declare %foo[3] := ( 19, 3, 6 ) exit( search(%foo, 19) ) end on )NKSP_CODE", .expectIntExitResult = 0 }); runScript({ .code = R"NKSP_CODE( on init declare %foo[3] := ( 19, 3, 6 ) exit( search(%foo, 3) ) end on )NKSP_CODE", .expectIntExitResult = 1 }); runScript({ .code = R"NKSP_CODE( on init declare %foo[3] := ( 19, 3, 6 ) exit( search(%foo, 6) ) end on )NKSP_CODE", .expectIntExitResult = 2 }); runScript({ .code = R"NKSP_CODE( on init declare %foo[3] := ( 19, 3, 6 ) exit( search(%foo, 2) ) end on )NKSP_CODE", .expectIntExitResult = -1 }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testIfStatement() { #if !SILENT_TEST std::cout << "UNIT TEST: if statement\n"; #endif runScript({ .code = R"NKSP_CODE( on init declare $foo := 1 if ($foo) exit(42) end if end on )NKSP_CODE", .expectIntExitResult = 42 }); runScript({ .code = R"NKSP_CODE( on init declare $foo := 0 if ($foo) exit(42) end if exit(3) end on )NKSP_CODE", .expectIntExitResult = 3 }); runScript({ .code = R"NKSP_CODE( on init declare $foo := 1 if ($foo) exit(42) else exit(3) end if end on )NKSP_CODE", .expectIntExitResult = 42 }); runScript({ .code = R"NKSP_CODE( on init declare $foo := 0 if ($foo) exit(42) else exit(3) end if end on )NKSP_CODE", .expectIntExitResult = 3 }); #if !SILENT_TEST std::cout << std::endl; #endif } static void testWhileStatement() { #if !SILENT_TEST std::cout << "UNIT TEST: while statement\n"; #endif runScript({ .code = R"NKSP_CODE( on init declare $foo := 100 declare $i := 50 while ($i) $foo := $foo + 1 $i := $i - 1 end while exit($foo) end on )NKSP_CODE", .expectIntExitResult = 150 }); #if !SILENT_TEST std::cout << std::endl; #endif } #if !NO_MAIN int main() { testBuiltInExitFunction(); testStringConcatOperator(); testNegOperator(); testPlusOperator(); testMinusOperator(); testModuloOperator(); testMultiplyOperator(); testDivideOperator(); testSmallerThanOperator(); testGreaterThanOperator(); testSmallerOrEqualOperator(); testGreaterOrEqualOperator(); testEqualOperator(); testUnequalOperator(); testLogicalAndOperator(); testLogicalOrOperator(); testLogicalNotOperator(); testBitwiseAndOperator(); testBitwiseOrOperator(); testBitwiseNotOperator(); testPrecedenceOfOperators(); testBuiltInMinFunction(); testBuiltInMaxFunction(); testBuiltInAbsFunction(); testBuiltInIncFunction(); testBuiltInDecFunction(); testBuiltInInRangeFunction(); testBuiltInRandomFunction(); testBuiltInShiftLeftFunction(); testBuiltInShiftRightFunction(); testBuiltInIntToRealFunction(); testBuiltInRealFunction(); testBuiltInRealToIntFunction(); testBuiltInIntFunction(); testBuiltInArrayEqualFunction(); testBuiltInSortFunction(); testBuiltInNumElementsFunction(); testBuiltInSearchFunction(); testIfStatement(); testWhileStatement(); std::cout << "\nAll tests passed successfully. :-)\n"; return 0; } #endif // !NO_MAIN