2020-04-27 07:50:38 +00:00
|
|
|
// Unit-test API for nasal
|
|
|
|
//
|
|
|
|
// There are two versions of this module, and we load one or the other
|
|
|
|
// depending on if we're running the test_suite (using CppUnit) or
|
|
|
|
// the normal simulator. The logic is that aircraft-developers and
|
|
|
|
// people hacking Nasal likely don't have a way to run the test-suite,
|
|
|
|
// whereas core-developers and Jenksin want a way to run all tests
|
|
|
|
// through the standard CppUnit mechanim. So we have a consistent
|
|
|
|
// Nasal API, but different implement in fgfs_test_suite vs
|
|
|
|
// normal fgfs executable.
|
|
|
|
//
|
|
|
|
// Copyright (C) 2020 James Turner
|
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License as
|
|
|
|
// published by the Free Software Foundation; either version 2 of the
|
|
|
|
// License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful, but
|
|
|
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program; if not, write to the Free Software
|
|
|
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <Main/globals.hxx>
|
|
|
|
#include <Main/util.hxx>
|
|
|
|
|
2020-05-21 21:32:28 +00:00
|
|
|
#include <cppunit/TestAssert.h>
|
|
|
|
|
2020-04-27 07:50:38 +00:00
|
|
|
#include <simgear/nasal/cppbind/from_nasal.hxx>
|
|
|
|
#include <simgear/nasal/cppbind/to_nasal.hxx>
|
|
|
|
#include <simgear/nasal/cppbind/NasalHash.hxx>
|
|
|
|
#include <simgear/nasal/cppbind/Ghost.hxx>
|
|
|
|
|
2020-05-22 16:35:24 +00:00
|
|
|
static CppUnit::SourceLine nasalSourceLine(onst nasal::CallContext& ctx)
|
|
|
|
{
|
|
|
|
const string fileName = ctx.from_nasal<string>(naGetSourceFile(ctx.c_ctx(), 0));
|
|
|
|
const int lineNumber = naGetLine(ctx.c_ctx(), 0);
|
|
|
|
return CppUnit::SourceLine(fileName, lineNumber);
|
|
|
|
}
|
|
|
|
|
2020-05-21 21:32:28 +00:00
|
|
|
static naRef f_assert(const nasal::CallContext& ctx )
|
2020-04-27 07:50:38 +00:00
|
|
|
{
|
2020-05-21 21:32:28 +00:00
|
|
|
bool pass = ctx.requireArg<bool>(0);
|
|
|
|
auto msg = ctx.getArg<string>(1, "assert failed:");
|
2020-05-22 16:35:24 +00:00
|
|
|
|
|
|
|
CppUnit::Asserter::failIf(!pass, "assertion failed:" + msg, nasalSourceLine(ctx));
|
2020-05-21 21:32:28 +00:00
|
|
|
if (!pass) {
|
|
|
|
ctx.runtimeError(msg.c_str());
|
|
|
|
}
|
|
|
|
return naNil();
|
2020-04-27 07:50:38 +00:00
|
|
|
}
|
|
|
|
|
2020-05-21 21:32:28 +00:00
|
|
|
static naRef f_fail(const nasal::CallContext& ctx )
|
2020-04-27 07:50:38 +00:00
|
|
|
{
|
2020-05-21 21:32:28 +00:00
|
|
|
auto msg = ctx.getArg<string>(0);
|
2020-05-22 16:35:24 +00:00
|
|
|
|
2020-05-21 21:32:28 +00:00
|
|
|
CppUnit::Asserter::fail("assertion failed:" + msg,
|
2020-05-22 16:35:24 +00:00
|
|
|
nasalSourceLine(ctx));
|
|
|
|
|
2020-05-21 21:32:28 +00:00
|
|
|
ctx.runtimeError("Test failed: %s", msg.c_str());
|
|
|
|
return naNil();
|
|
|
|
}
|
2020-04-27 07:50:38 +00:00
|
|
|
|
2020-05-21 21:32:28 +00:00
|
|
|
static naRef f_assert_equal(const nasal::CallContext& ctx )
|
|
|
|
{
|
|
|
|
naRef argA = ctx.requireArg<naRef>(0);
|
|
|
|
naRef argB = ctx.requireArg<naRef>(1);
|
|
|
|
auto msg = ctx.getArg<string>(2, "assert_equal failed");
|
2020-04-27 07:50:38 +00:00
|
|
|
|
2020-05-21 21:32:28 +00:00
|
|
|
bool same = naEqual(argA, argB);
|
|
|
|
if (!same) {
|
2020-04-27 07:50:38 +00:00
|
|
|
|
2020-05-21 21:32:28 +00:00
|
|
|
string aStr = ctx.from_nasal<string>(argA);
|
|
|
|
string bStr = ctx.from_nasal<string>(argB);
|
|
|
|
msg += "; expected:" + aStr + ", actual:" + bStr;
|
2020-04-27 07:50:38 +00:00
|
|
|
|
2020-05-22 16:35:24 +00:00
|
|
|
CppUnit::Asserter::fail(msg, nasalSourceLine(ctx));
|
2020-05-21 21:32:28 +00:00
|
|
|
ctx.runtimeError(msg.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
return naNil();
|
2020-04-27 07:50:38 +00:00
|
|
|
}
|
|
|
|
|
2020-05-21 21:32:28 +00:00
|
|
|
static naRef f_assert_doubles_equal(const nasal::CallContext& ctx )
|
2020-04-27 07:50:38 +00:00
|
|
|
{
|
2020-05-21 21:32:28 +00:00
|
|
|
double argA = ctx.requireArg<double>(0);
|
|
|
|
double argB = ctx.requireArg<double>(1);
|
|
|
|
double tolerance = ctx.requireArg<double>(2);
|
|
|
|
|
|
|
|
auto msg = ctx.getArg<string>(3, "assert_doubles_equal failed");
|
|
|
|
|
|
|
|
const bool same = fabs(argA - argB) < tolerance;
|
|
|
|
if (!same) {
|
|
|
|
msg += "; expected:" + std::to_string(argA) + ", actual:" + std::to_string(argB);
|
2020-05-22 16:35:24 +00:00
|
|
|
CppUnit::Asserter::fail(msg, nasalSourceLine(ctx));
|
2020-05-21 21:32:28 +00:00
|
|
|
ctx.runtimeError(msg.c_str());
|
|
|
|
}
|
|
|
|
|
2020-04-27 07:50:38 +00:00
|
|
|
return naNil();
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
2020-05-21 21:32:28 +00:00
|
|
|
naRef initNasalUnitTestCppUnit(naRef nasalGlobals, naContext c)
|
2020-04-27 07:50:38 +00:00
|
|
|
{
|
2020-05-21 21:32:28 +00:00
|
|
|
nasal::Hash globals_module(nasalGlobals, c),
|
|
|
|
unitTest = globals_module.createHash("unitTest");
|
|
|
|
|
|
|
|
unitTest.set("assert", f_assert);
|
|
|
|
unitTest.set("fail", f_fail);
|
|
|
|
unitTest.set("assert_equal", f_assert_equal);
|
|
|
|
unitTest.set("assert_doubles_equal", f_assert_doubles_equal);
|
|
|
|
|
2020-04-27 07:50:38 +00:00
|
|
|
return naNil();
|
|
|
|
}
|