first commit
This commit is contained in:
173
test_suite/CMakeLists.txt
Normal file
173
test_suite/CMakeLists.txt
Normal file
@@ -0,0 +1,173 @@
|
||||
# CMake module includes.
|
||||
include(SetupFGFSEmbeddedResources)
|
||||
include(SetupFGFSIncludes)
|
||||
include(SetupFGFSLibraries)
|
||||
include(SetupMSVCGrouping)
|
||||
|
||||
# Add each test suite category.
|
||||
foreach(test_category
|
||||
gui_tests
|
||||
simgear_tests
|
||||
system_tests
|
||||
unit_tests
|
||||
fgdata_tests
|
||||
)
|
||||
add_subdirectory(${test_category})
|
||||
endforeach(test_category)
|
||||
|
||||
# Add the testing API.
|
||||
add_subdirectory(FGTestApi)
|
||||
|
||||
# Add all test suite sources and headers.
|
||||
set(TESTSUITE_SOURCES
|
||||
${TESTSUITE_SOURCES}
|
||||
bootstrap.cxx
|
||||
dataStore.cxx
|
||||
fgCompilerOutputter.cxx
|
||||
fgTestListener.cxx
|
||||
fgTestRunner.cxx
|
||||
formatting.cxx
|
||||
logging.cxx
|
||||
testSuite.cxx
|
||||
)
|
||||
set(TESTSUITE_HEADERS
|
||||
${TESTSUITE_HEADERS}
|
||||
dataStore.hxx
|
||||
fgCompilerOutputter.hxx
|
||||
fgTestListener.hxx
|
||||
fgTestRunner.hxx
|
||||
formatting.hxx
|
||||
logging.hxx
|
||||
)
|
||||
|
||||
# The test suite output directory.
|
||||
set(TESTSUITE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
# Get the CppUnit sources and headers to be built into the test suite.
|
||||
if (NOT SYSTEM_CPPUNIT)
|
||||
message(STATUS "CppUnit: Building the FlightGear supplied CppUnit library")
|
||||
|
||||
get_property(CPPUNIT_SOURCES GLOBAL PROPERTY CPPUNIT_SOURCES)
|
||||
get_property(CPPUNIT_HEADERS GLOBAL PROPERTY CPPUNIT_HEADERS)
|
||||
|
||||
|
||||
add_library(CppUnitLib STATIC ${CPPUNIT_SOURCES} ${CPPUNIT_HEADERS})
|
||||
|
||||
target_include_directories(CppUnitLib PUBLIC "${PROJECT_SOURCE_DIR}/3rdparty/cppunit/include")
|
||||
|
||||
set(CPPUNIT_LIBRARIES CppUnitLib)
|
||||
else()
|
||||
message(STATUS "CppUnit: Linking to the system supplied CppUnit library")
|
||||
endif()
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Set up all test suites as CTests.
|
||||
|
||||
# Activation.
|
||||
include(Dart)
|
||||
|
||||
# System test suites.
|
||||
add_test(AeroMeshSystemTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -s AeroMeshTests)
|
||||
#add_test(GPSSystemTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -s GPSTests)
|
||||
#add_test(NavaidsSystemTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -s NavaidsTests)
|
||||
|
||||
# Unit test suites.
|
||||
add_test(AddonManagementUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u AddonManagementTests)
|
||||
add_test(AeroElementUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u AeroElementTests)
|
||||
add_test(AircraftPerformanceUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u AircraftPerformanceTests)
|
||||
add_test(AutosaveMigrationUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u AutosaveMigrationTests)
|
||||
add_test(FlightplanUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u FlightplanTests)
|
||||
add_test(FPNasalUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u FPNasalTests)
|
||||
add_test(GPSUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u GPSTests)
|
||||
add_test(HoldControllerUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u HoldControllerTests)
|
||||
if(ENABLE_HID_INPUT)
|
||||
add_test(HIDInputUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u HIDInputTests)
|
||||
endif()
|
||||
add_test(LaRCSimMatrixUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u LaRCSimMatrixTests)
|
||||
add_test(MktimeUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u MktimeTests)
|
||||
add_test(NasalSysUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u NasalSysTests)
|
||||
add_test(NavaidsUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u NavaidsTests)
|
||||
add_test(NavRadioUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u NavRadioTests)
|
||||
add_test(PosInitUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u PosInitTests)
|
||||
add_test(RNAVProcedureUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u RNAVProcedureTests)
|
||||
add_test(RouteManagerUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u RouteManagerTests)
|
||||
add_test(YASimAtmosphereUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -u YASimAtmosphereTests)
|
||||
|
||||
# GUI test suites.
|
||||
|
||||
# Simgear unit test suites.
|
||||
add_test(CanvasSimgearUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -m CanvasTests)
|
||||
add_test(MathGeodesySimgearUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -m MathGeodesyTests)
|
||||
add_test(SimgearPropsSimgearUnitTests ${TESTSUITE_OUTPUT_DIR}/fgfs_test_suite --ctest -m SimgearPropsTests)
|
||||
|
||||
# FGData test suites.
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Set up the binary.
|
||||
|
||||
# Set up the embedded resources.
|
||||
setup_fgfs_embedded_resources()
|
||||
|
||||
# Sort the sources and headers for MSVC.
|
||||
setup_msvc_grouping()
|
||||
|
||||
# most object files come from fgfsObjects target: this property
|
||||
# contains all the sources which need to be compiled seperately
|
||||
# for the test-suite, becuase they depend on BUILDING_TESTSUTIE define
|
||||
# we setup below via target_compile_definitions
|
||||
|
||||
get_property(TEST_SOURCES GLOBAL PROPERTY FG_TEST_SOURCES)
|
||||
|
||||
# Set up the separate executable for running the test suite.
|
||||
add_executable(fgfs_test_suite
|
||||
${TEST_SOURCES}
|
||||
${TESTSUITE_SOURCES}
|
||||
${TESTSUITE_HEADERS}
|
||||
$<TARGET_OBJECTS:fgfsObjects>
|
||||
)
|
||||
|
||||
add_dependencies(fgfs_test_suite buildId)
|
||||
set_target_properties(fgfs_test_suite
|
||||
PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY "${TESTSUITE_OUTPUT_DIR}"
|
||||
)
|
||||
if(ENABLE_AUTOTESTING)
|
||||
set(TEST_SUITE_COMMAND "fgfs_test_suite")
|
||||
set(TEST_SUITE_COMMENT "Running the full FlightGear test suite")
|
||||
else()
|
||||
set(TEST_SUITE_COMMENT "Building the FlightGear test suite.")
|
||||
endif(ENABLE_AUTOTESTING)
|
||||
|
||||
# Set up the target links.
|
||||
setup_fgfs_libraries(fgfs_test_suite)
|
||||
# Additional search paths for includes.
|
||||
setup_fgfs_includes(fgfs_test_suite)
|
||||
|
||||
# test codce includes its headers as test_suite/foo.h, so we need this
|
||||
target_include_directories(fgfs_test_suite PUBLIC ${PROJECT_SOURCE_DIR})
|
||||
|
||||
target_compile_definitions(fgfs_test_suite PUBLIC BUILDING_TESTSUITE)
|
||||
|
||||
# Additional libraries just for the test suite.
|
||||
target_link_libraries(fgfs_test_suite ${CPPUNIT_LIBRARIES})
|
||||
|
||||
# target to run the tests
|
||||
if (MSVC)
|
||||
file(TO_NATIVE_PATH "${FG_QT_BIN_DIR}" _qt5_bin_dir_native)
|
||||
file(TO_NATIVE_PATH "${FINAL_MSVC_3RDPARTY_DIR}/bin" _msvc_3rdparty_bin_dir)
|
||||
file(TO_NATIVE_PATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}" _install_bin_dir)
|
||||
|
||||
set(CMAKE_MSVCIDE_RUN_PATH "${_install_bin_dir};${_msvc_3rdparty_bin_dir};${_qt5_bin_dir_native}")
|
||||
endif()
|
||||
|
||||
if (FG_QT_ROOT_DIR)
|
||||
# for QtPlatformHeaders
|
||||
target_include_directories(fgfs_test_suite PRIVATE ${FG_QT_ROOT_DIR}/include)
|
||||
endif()
|
||||
|
||||
|
||||
add_custom_target(test_suite
|
||||
${TEST_SUITE_COMMAND}
|
||||
DEPENDS fgfs_test_suite
|
||||
COMMENT ${TEST_SUITE_COMMENT}
|
||||
)
|
||||
24
test_suite/FGTestApi/CMakeLists.txt
Normal file
24
test_suite/FGTestApi/CMakeLists.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
set(TESTSUITE_SOURCES
|
||||
${TESTSUITE_SOURCES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/testGlobals.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/NavDataCache.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/PrivateAccessorFDM.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scene_graph.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TestPilot.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/NasalUnitTesting_TestSuite.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TestDataLogger.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/testApis.cxx
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
|
||||
set(TESTSUITE_HEADERS
|
||||
${TESTSUITE_HEADERS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/testGlobals.hxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/NavDataCache.hxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/PrivateAccessorFDM.hxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scene_graph.hxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TestPilot.hxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TestDataLogger.hxx
|
||||
PARENT_SCOPE
|
||||
)
|
||||
131
test_suite/FGTestApi/NasalUnitTesting_TestSuite.cxx
Normal file
131
test_suite/FGTestApi/NasalUnitTesting_TestSuite.cxx
Normal file
@@ -0,0 +1,131 @@
|
||||
// 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>
|
||||
|
||||
#include <Scripting/NasalSys.hxx>
|
||||
#include <Scripting/NasalSys_private.hxx>
|
||||
|
||||
#include <cppunit/TestAssert.h>
|
||||
|
||||
#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>
|
||||
|
||||
static CppUnit::SourceLine nasalSourceLine(const 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);
|
||||
}
|
||||
|
||||
static naRef f_assert(const nasal::CallContext& ctx )
|
||||
{
|
||||
bool pass = ctx.requireArg<bool>(0);
|
||||
auto msg = ctx.getArg<string>(1, "assert failed:");
|
||||
|
||||
CppUnit::Asserter::failIf(!pass, "assertion failed:" + msg, nasalSourceLine(ctx));
|
||||
return naNil();
|
||||
}
|
||||
|
||||
static naRef f_fail(const nasal::CallContext& ctx )
|
||||
{
|
||||
auto msg = ctx.getArg<string>(0);
|
||||
|
||||
CppUnit::Asserter::fail("assertion failed:" + msg,
|
||||
nasalSourceLine(ctx));
|
||||
return naNil();
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
bool same = nasalStructEqual(ctx.c_ctx(), argA, argB);
|
||||
if (!same) {
|
||||
|
||||
string aStr = ctx.from_nasal<string>(argA);
|
||||
string bStr = ctx.from_nasal<string>(argB);
|
||||
msg += "; expected:" + aStr + ", actual:" + bStr;
|
||||
|
||||
CppUnit::Asserter::fail(msg, nasalSourceLine(ctx));
|
||||
}
|
||||
|
||||
return naNil();
|
||||
}
|
||||
|
||||
static naRef f_equal(const nasal::CallContext& ctx)
|
||||
{
|
||||
naRef argA = ctx.requireArg<naRef>(0);
|
||||
naRef argB = ctx.requireArg<naRef>(1);
|
||||
|
||||
bool same = nasalStructEqual(ctx.c_ctx(), argA, argB);
|
||||
return naNum(same);
|
||||
}
|
||||
|
||||
static naRef f_assert_doubles_equal(const nasal::CallContext& ctx )
|
||||
{
|
||||
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);
|
||||
CppUnit::Asserter::fail(msg, nasalSourceLine(ctx));
|
||||
}
|
||||
|
||||
return naNil();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
naRef initNasalUnitTestCppUnit(naRef nasalGlobals, naContext c)
|
||||
{
|
||||
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("equal", f_equal);
|
||||
unitTest.set("assert_doubles_equal", f_assert_doubles_equal);
|
||||
|
||||
return naNil();
|
||||
}
|
||||
|
||||
void shutdownNasalUnitTestInSim()
|
||||
{
|
||||
// stub
|
||||
}
|
||||
48
test_suite/FGTestApi/NavDataCache.cxx
Normal file
48
test_suite/FGTestApi/NavDataCache.cxx
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "NavDataCache.hxx"
|
||||
|
||||
#include <Navaids/NavDataCache.hxx>
|
||||
|
||||
|
||||
namespace FGTestApi {
|
||||
|
||||
namespace setUp {
|
||||
|
||||
void initNavDataCache()
|
||||
{
|
||||
if (flightgear::NavDataCache::instance())
|
||||
return;
|
||||
|
||||
flightgear::NavDataCache* cache = flightgear::NavDataCache::createInstance();
|
||||
if (cache->isRebuildRequired()) {
|
||||
std::cerr << "Navcache rebuild for testing" << std::flush;
|
||||
|
||||
while (cache->rebuild() != flightgear::NavDataCache::REBUILD_DONE) {
|
||||
SGTimeStamp::sleepForMSec(1000);
|
||||
std::cerr << "." << std::flush;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace setUp.
|
||||
|
||||
} // End of namespace FGTestApi.
|
||||
35
test_suite/FGTestApi/NavDataCache.hxx
Normal file
35
test_suite/FGTestApi/NavDataCache.hxx
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FG_NAV_DATA_CACHE_TEST_HELPERS_HXX
|
||||
#define FG_NAV_DATA_CACHE_TEST_HELPERS_HXX
|
||||
|
||||
namespace FGTestApi {
|
||||
|
||||
namespace setUp {
|
||||
|
||||
|
||||
void initNavDataCache();
|
||||
|
||||
} // End of namespace setUp.
|
||||
|
||||
} // End of namespace FGTestApi.
|
||||
|
||||
#endif // of FG_NAV_DATA_CACHE_TEST_HELPERS_HXX
|
||||
63
test_suite/FGTestApi/PrivateAccessorFDM.cxx
Normal file
63
test_suite/FGTestApi/PrivateAccessorFDM.cxx
Normal file
@@ -0,0 +1,63 @@
|
||||
#include "PrivateAccessorFDM.hxx"
|
||||
|
||||
#include <FDM/AIWake/AIWakeGroup.hxx>
|
||||
#include <FDM/AIWake/AircraftMesh.hxx>
|
||||
#include <FDM/AIWake/WakeMesh.hxx>
|
||||
#include <FDM/YASim/Atmosphere.hpp>
|
||||
|
||||
|
||||
|
||||
// Access variables from src/FDM/AIWake/AIWakeGroup.hxx.
|
||||
WakeMesh*
|
||||
FGTestApi::PrivateAccessor::FDM::Accessor::read_FDM_AIWake_AIWakeGroup_aiWakeData(AIWakeGroup* instance, int i)
|
||||
{
|
||||
return instance->_aiWakeData[i].mesh;
|
||||
}
|
||||
|
||||
|
||||
// Access variables from src/FDM/AIWake/AircraftMesh.hxx.
|
||||
const std::vector<SGVec3d>
|
||||
FGTestApi::PrivateAccessor::FDM::Accessor::read_FDM_AIWake_AircraftMesh_collPt(AircraftMesh* instance) const
|
||||
{
|
||||
return instance->collPt;
|
||||
}
|
||||
|
||||
const std::vector<SGVec3d>
|
||||
FGTestApi::PrivateAccessor::FDM::Accessor::read_FDM_AIWake_AircraftMesh_midPt(AircraftMesh* instance) const
|
||||
{
|
||||
return instance->midPt;
|
||||
}
|
||||
|
||||
|
||||
// Access variables from src/FDM/AIWake/WakeMesh.hxx.
|
||||
const std::vector<AeroElement_ptr>
|
||||
FGTestApi::PrivateAccessor::FDM::Accessor::read_FDM_AIWake_WakeMesh_elements(WakeMesh* instance) const
|
||||
{
|
||||
return instance->elements;
|
||||
}
|
||||
|
||||
int
|
||||
FGTestApi::PrivateAccessor::FDM::Accessor::read_FDM_AIWake_WakeMesh_nelm(WakeMesh* instance) const
|
||||
{
|
||||
return instance->nelm;
|
||||
}
|
||||
|
||||
double **
|
||||
FGTestApi::PrivateAccessor::FDM::Accessor::read_FDM_AIWake_WakeMesh_Gamma(WakeMesh* instance) const
|
||||
{
|
||||
return instance->Gamma;
|
||||
}
|
||||
|
||||
|
||||
// Access variables from src/FDM/YASim/Atmosphere.hxx.
|
||||
float
|
||||
FGTestApi::PrivateAccessor::FDM::Accessor::read_FDM_YASim_Atmosphere_numColumns(std::unique_ptr<yasim::Atmosphere> &instance) const
|
||||
{
|
||||
return instance->numColumns;
|
||||
}
|
||||
|
||||
float
|
||||
FGTestApi::PrivateAccessor::FDM::Accessor::read_FDM_YASim_Atmosphere_data(std::unique_ptr<yasim::Atmosphere> &instance, int i, int j) const
|
||||
{
|
||||
return instance->data[i][j];
|
||||
}
|
||||
53
test_suite/FGTestApi/PrivateAccessorFDM.hxx
Normal file
53
test_suite/FGTestApi/PrivateAccessorFDM.hxx
Normal file
@@ -0,0 +1,53 @@
|
||||
#ifndef _FG_PRIVATE_ACCESSOR_FDM_HXX
|
||||
#define _FG_PRIVATE_ACCESSOR_FDM_HXX
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/structure/SGSharedPtr.hxx>
|
||||
|
||||
// Forward declarations for src/FDM/AIWake.
|
||||
class AIWakeData;
|
||||
class AIWakeGroup;
|
||||
class AircraftMesh;
|
||||
class WakeMesh;
|
||||
class AeroElement;
|
||||
typedef SGSharedPtr<AeroElement> AeroElement_ptr;
|
||||
|
||||
// Forward declaration for: src/FDM/YASim.
|
||||
namespace yasim {
|
||||
class Atmosphere;
|
||||
}
|
||||
|
||||
|
||||
namespace FGTestApi {
|
||||
namespace PrivateAccessor {
|
||||
namespace FDM {
|
||||
|
||||
class Accessor
|
||||
{
|
||||
public:
|
||||
// Access variables from src/FDM/AIWake/AIWakeGroup.hxx.
|
||||
WakeMesh* read_FDM_AIWake_AIWakeGroup_aiWakeData(AIWakeGroup* instance, int i);
|
||||
|
||||
// Access variables from src/FDM/AIWake/AircraftMesh.hxx.
|
||||
const std::vector<SGVec3d> read_FDM_AIWake_AircraftMesh_collPt(AircraftMesh* instance) const;
|
||||
const std::vector<SGVec3d> read_FDM_AIWake_AircraftMesh_midPt(AircraftMesh* instance) const;
|
||||
|
||||
// Access variables from src/FDM/AIWake/WakeMesh.hxx.
|
||||
const std::vector<AeroElement_ptr> read_FDM_AIWake_WakeMesh_elements(WakeMesh* instance) const;
|
||||
int read_FDM_AIWake_WakeMesh_nelm(WakeMesh* instance) const;
|
||||
double **read_FDM_AIWake_WakeMesh_Gamma(WakeMesh* instance) const;
|
||||
|
||||
// Access variables from src/FDM/YASim/Atmosphere.hxx.
|
||||
float read_FDM_YASim_Atmosphere_numColumns(std::unique_ptr<yasim::Atmosphere> &instance) const;
|
||||
float read_FDM_YASim_Atmosphere_data(std::unique_ptr<yasim::Atmosphere> &instance, int i, int j) const;
|
||||
};
|
||||
|
||||
} // End of namespace FDM.
|
||||
} // End of namespace PrivateAccessor.
|
||||
} // End of namespace FGTestApi.
|
||||
|
||||
#endif // _FG_PRIVATE_ACCESSOR_FDM_HXX
|
||||
170
test_suite/FGTestApi/TestDataLogger.cxx
Normal file
170
test_suite/FGTestApi/TestDataLogger.cxx
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright (C) 2020 James Turner
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "TestDataLogger.hxx"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#include <simgear/io/iostreams/sgstream.hxx>
|
||||
|
||||
#include "Main/globals.hxx"
|
||||
|
||||
namespace FGTestApi {
|
||||
|
||||
using DoubleVec = std::vector<double>;
|
||||
|
||||
static std::unique_ptr<DataLogger> static_instance;
|
||||
|
||||
class DataLogger::DataLoggerPrivate
|
||||
{
|
||||
public:
|
||||
sg_ofstream _stream;
|
||||
|
||||
struct SampleInfo {
|
||||
int column;
|
||||
std::string name;
|
||||
// range / units info, later
|
||||
SGPropertyNode_ptr property;
|
||||
};
|
||||
|
||||
double _currentTimeBase;
|
||||
std::vector<SampleInfo> _samples;
|
||||
DoubleVec _openRow;
|
||||
bool _didHeader = false;
|
||||
|
||||
void writeCurrentRow()
|
||||
{
|
||||
if (!_didHeader) {
|
||||
writeHeader();
|
||||
_didHeader = true;
|
||||
}
|
||||
|
||||
// capture property values into the open row data
|
||||
std::for_each(_samples.begin(), _samples.end(), [this](const SampleInfo& info) {
|
||||
if (info.property) {
|
||||
_openRow[info.column] = info.property->getDoubleValue();
|
||||
}
|
||||
});
|
||||
|
||||
// write time base
|
||||
_stream << globals->get_sim_time_sec() << ",";
|
||||
|
||||
for (const auto v : _openRow) {
|
||||
if (std::isnan(v)) {
|
||||
_stream << ","; // skip this data point
|
||||
} else {
|
||||
_stream << v << ",";
|
||||
}
|
||||
}
|
||||
|
||||
_stream << "\n";
|
||||
|
||||
std::fill(_openRow.begin(), _openRow.end(), std::numeric_limits<double>::quiet_NaN());
|
||||
}
|
||||
|
||||
void writeHeader()
|
||||
{
|
||||
_stream << "sim-time, ";
|
||||
std::for_each(_samples.begin(), _samples.end(), [this](const SampleInfo& info) {
|
||||
_stream << info.name << ", ";
|
||||
});
|
||||
|
||||
_stream << "\n";
|
||||
}
|
||||
};
|
||||
|
||||
DataLogger::DataLogger()
|
||||
{
|
||||
d.reset(new DataLoggerPrivate);
|
||||
}
|
||||
|
||||
DataLogger::~DataLogger()
|
||||
{
|
||||
d->_stream.close();
|
||||
}
|
||||
|
||||
bool DataLogger::isActive()
|
||||
{
|
||||
return static_instance != nullptr;
|
||||
}
|
||||
|
||||
DataLogger* DataLogger::instance()
|
||||
{
|
||||
if (!static_instance) {
|
||||
static_instance.reset(new DataLogger);
|
||||
}
|
||||
|
||||
return static_instance.get();
|
||||
}
|
||||
|
||||
void DataLogger::initTest(const std::string& testName)
|
||||
{
|
||||
d->_stream = sg_ofstream(testName + "_trace.csv");
|
||||
}
|
||||
|
||||
void DataLogger::tearDown()
|
||||
{
|
||||
if (static_instance) {
|
||||
static_instance.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void DataLogger::writeRecord()
|
||||
{
|
||||
d->writeCurrentRow();
|
||||
}
|
||||
|
||||
void DataLogger::recordProperty(const std::string& name, SGPropertyNode_ptr prop)
|
||||
{
|
||||
int index = static_cast<int>(d->_samples.size());
|
||||
DataLoggerPrivate::SampleInfo info{index, name, prop};
|
||||
d->_samples.push_back(info);
|
||||
|
||||
if (d->_openRow.size() <= index) {
|
||||
d->_openRow.resize(index + 1, std::numeric_limits<double>::quiet_NaN());
|
||||
}
|
||||
}
|
||||
|
||||
void DataLogger::recordSamplePoint(const std::string& name, double value)
|
||||
{
|
||||
auto it = std::find_if(d->_samples.begin(), d->_samples.end(), [&name](const DataLoggerPrivate::SampleInfo& sample) {
|
||||
return name == sample.name;
|
||||
});
|
||||
|
||||
int index = 0;
|
||||
if (it == d->_samples.end()) {
|
||||
index = static_cast<int>(d->_samples.size());
|
||||
DataLoggerPrivate::SampleInfo info{index, name};
|
||||
d->_samples.push_back(info);
|
||||
} else {
|
||||
index = it->column;
|
||||
}
|
||||
|
||||
// grow _openRow as required
|
||||
if (d->_openRow.size() <= index) {
|
||||
d->_openRow.resize(index + 1, std::numeric_limits<double>::quiet_NaN());
|
||||
}
|
||||
|
||||
d->_openRow[index] = value;
|
||||
}
|
||||
|
||||
} // namespace FGTestApi
|
||||
57
test_suite/FGTestApi/TestDataLogger.hxx
Normal file
57
test_suite/FGTestApi/TestDataLogger.hxx
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2020 James Turner
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <simgear/props/props.hxx>
|
||||
|
||||
namespace FGTestApi {
|
||||
|
||||
class DataLogger
|
||||
{
|
||||
public:
|
||||
~DataLogger();
|
||||
|
||||
static DataLogger* instance();
|
||||
static bool isActive();
|
||||
|
||||
void initTest(const std::string& testName);
|
||||
|
||||
void recordProperty(const std::string& name, SGPropertyNode_ptr prop);
|
||||
|
||||
void setUp();
|
||||
|
||||
void tearDown();
|
||||
|
||||
void recordSamplePoint(const std::string& name, double value);
|
||||
|
||||
void writeRecord();
|
||||
|
||||
private:
|
||||
DataLogger();
|
||||
|
||||
class DataLoggerPrivate;
|
||||
std::unique_ptr<DataLoggerPrivate> d;
|
||||
};
|
||||
|
||||
|
||||
} // namespace FGTestApi
|
||||
282
test_suite/FGTestApi/TestPilot.cxx
Normal file
282
test_suite/FGTestApi/TestPilot.cxx
Normal file
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright (C) 2019 James Turner
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "TestPilot.hxx"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <simgear/math/SGGeodesy.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/math/SGGeod.hxx>
|
||||
|
||||
#include <Aircraft/AircraftPerformance.hxx> // for formulae
|
||||
#include <Main/globals.hxx>
|
||||
|
||||
#include "TestDataLogger.hxx"
|
||||
|
||||
namespace FGTestApi {
|
||||
|
||||
TestPilot::TestPilot(SGPropertyNode_ptr props) :
|
||||
_propRoot(props)
|
||||
{
|
||||
if (!_propRoot) {
|
||||
// use default properties
|
||||
_propRoot = globals->get_props();
|
||||
}
|
||||
|
||||
_latProp = _propRoot->getNode("position/latitude-deg", true);
|
||||
_lonProp = _propRoot->getNode("position/longitude-deg", true);
|
||||
_altitudeProp = _propRoot->getNode("position/altitude-ft", true);
|
||||
_headingProp = _propRoot->getNode("orientation/heading-deg", true);
|
||||
_speedKnotsProp = _propRoot->getNode("velocities/airspeed-kt", true);
|
||||
_speedMachProp = _propRoot->getNode("velocities/mach", true);
|
||||
_groundspeedKnotsProp = _propRoot->getNode("velocities/groundspeed-kt", true);
|
||||
_verticalFPMProp = _propRoot->getNode("velocities/vertical-fpm", true);
|
||||
|
||||
globals->add_subsystem("flight", this, SGSubsystemMgr::FDM);
|
||||
}
|
||||
|
||||
TestPilot::~TestPilot()
|
||||
{
|
||||
}
|
||||
|
||||
void TestPilot::resetAtPosition(const SGGeod& pos)
|
||||
{
|
||||
_turnActive = false;
|
||||
setPosition(pos);
|
||||
}
|
||||
|
||||
void TestPilot::init()
|
||||
{
|
||||
_vspeedFPM = 1200;
|
||||
}
|
||||
|
||||
void TestPilot::update(double dt)
|
||||
{
|
||||
updateValues(dt);
|
||||
}
|
||||
|
||||
void TestPilot::setSpeedKts(double knots)
|
||||
{
|
||||
_speedKnots = knots;
|
||||
}
|
||||
|
||||
void TestPilot::setVerticalFPM(double fpm)
|
||||
{
|
||||
_vspeedFPM = fpm;
|
||||
}
|
||||
|
||||
void TestPilot::setCourseTrue(double deg)
|
||||
{
|
||||
_trueCourseDeg = deg;
|
||||
}
|
||||
|
||||
void TestPilot::turnToCourse(double deg)
|
||||
{
|
||||
_turnActive = true;
|
||||
_targetCourseDeg = deg;
|
||||
}
|
||||
|
||||
void TestPilot::flyHeading(double hdg)
|
||||
{
|
||||
_lateralMode = LateralMode::Heading;
|
||||
_turnActive = true;
|
||||
_targetCourseDeg = hdg;
|
||||
}
|
||||
|
||||
void TestPilot::flyGPSCourse(GPS *gps)
|
||||
{
|
||||
_gps = gps;
|
||||
_gpsNode = globals->get_props()->getNode("instrumentation/gps");
|
||||
_gpsLegCourse = _gpsNode->getNode("wp/leg-true-course-deg", true);
|
||||
_courseErrorNm = _gpsNode->getNode("wp/wp[1]/course-error-nm", true);
|
||||
|
||||
_lateralMode = LateralMode::GPSCourse;
|
||||
_turnActive = false;
|
||||
}
|
||||
|
||||
void TestPilot::flyGPSCourseOffset(GPS *gps, double offsetNm)
|
||||
{
|
||||
_gps = gps;
|
||||
_gpsNode = globals->get_props()->getNode("instrumentation/gps");
|
||||
_gpsLegCourse = _gpsNode->getNode("wp/leg-true-course-deg", true);
|
||||
_courseErrorNm = _gpsNode->getNode("wp/wp[1]/course-error-nm", true);
|
||||
|
||||
_lateralMode = LateralMode::GPSOffset;
|
||||
_courseOffsetNm = offsetNm;
|
||||
_turnActive = false;
|
||||
}
|
||||
|
||||
void TestPilot::flyDirectTo(const SGGeod& target)
|
||||
{
|
||||
_lateralMode = LateralMode::Direct;
|
||||
_targetPos = target;
|
||||
}
|
||||
|
||||
void TestPilot::updateValues(double dt)
|
||||
{
|
||||
auto dl = DataLogger::instance();
|
||||
|
||||
if (_gps && (_lateralMode == LateralMode::GPSCourse)) {
|
||||
_targetCourseDeg = _gpsLegCourse->getDoubleValue();
|
||||
|
||||
// set how aggressively we try to correct our course
|
||||
double courseCorrectionFactor = 64.0;
|
||||
double crossTrack = _courseErrorNm->getDoubleValue();
|
||||
|
||||
dl->recordSamplePoint("TP-error-nm", crossTrack);
|
||||
|
||||
SG_CLAMP_RANGE(crossTrack, -2.0, 2.0); // clamp to 2nm deviation
|
||||
double correction = courseCorrectionFactor * crossTrack;
|
||||
const double maxCorrectionAngle = 45;
|
||||
|
||||
dl->recordSamplePoint("TP-base-correction-deg", correction);
|
||||
|
||||
// within 1nm of the desired course, start to bias
|
||||
// based on heading error. This is to reduce overshooting
|
||||
// while still keeping the responsiveness high
|
||||
if (fabs(crossTrack) < 1.0) {
|
||||
// compensate for heading
|
||||
double headingError = _targetCourseDeg - _trueCourseDeg;
|
||||
SG_NORMALIZE_RANGE(headingError, -180.0, 180.0);
|
||||
if (fabs(headingError) > 90.0) {
|
||||
// we're pointing the wrong way, don't compensate
|
||||
// otherwise we get into knots trying to make the
|
||||
// turn back the right way
|
||||
} else {
|
||||
const double p = 1.0 - fabs(crossTrack);
|
||||
const double headingErrorFactor = 0.6;
|
||||
correction += p * headingError * headingErrorFactor;
|
||||
}
|
||||
}
|
||||
|
||||
dl->recordSamplePoint("TP-correction-deg", correction);
|
||||
|
||||
SG_CLAMP_RANGE(correction, -maxCorrectionAngle, maxCorrectionAngle);
|
||||
_targetCourseDeg += correction;
|
||||
|
||||
dl->recordSamplePoint("TP-target-deg", _targetCourseDeg);
|
||||
|
||||
SG_NORMALIZE_RANGE(_targetCourseDeg, 0.0, 360.0);
|
||||
if (!_turnActive &&(fabs(_trueCourseDeg - _targetCourseDeg) > 0.5)) {
|
||||
_turnActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (_gps && (_lateralMode == LateralMode::GPSOffset)) {
|
||||
_targetCourseDeg = _gpsLegCourse->getDoubleValue();
|
||||
|
||||
double crossTrack = _courseErrorNm->getDoubleValue();
|
||||
double offsetError = crossTrack - _courseOffsetNm;
|
||||
|
||||
const double offsetCorrectionFactor = 25.0;
|
||||
const double correction = offsetError * offsetCorrectionFactor;
|
||||
_targetCourseDeg += correction;
|
||||
|
||||
SG_NORMALIZE_RANGE(_targetCourseDeg, 0.0, 360.0);
|
||||
if (!_turnActive &&(fabs(_trueCourseDeg - _targetCourseDeg) > 0.5)) {
|
||||
_turnActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (_lateralMode == LateralMode::Direct) {
|
||||
_targetCourseDeg = SGGeodesy::courseDeg(globals->get_aircraft_position(), _targetPos);
|
||||
SG_NORMALIZE_RANGE(_targetCourseDeg, 0.0, 360.0);
|
||||
if (!_turnActive && (fabs(_trueCourseDeg - _targetCourseDeg) > 0.5)) {
|
||||
_turnActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (_turnActive) {
|
||||
if (fabs(_targetCourseDeg - _trueCourseDeg) < 0.1) {
|
||||
_trueCourseDeg = _targetCourseDeg;
|
||||
_turnActive = false;
|
||||
} else {
|
||||
// standard 2-minute turn, 180-deg min, thus 3-degrees per second
|
||||
|
||||
double turnDeg = 5.0 * dt;
|
||||
double errorDeg = _targetCourseDeg - _trueCourseDeg;
|
||||
SG_NORMALIZE_RANGE(errorDeg, -180.0, 180.0);
|
||||
|
||||
// clamp turn to error value
|
||||
turnDeg = std::min(turnDeg, fabs(errorDeg));
|
||||
|
||||
// and now ensure we follow the correct sign
|
||||
turnDeg = copysign(turnDeg, errorDeg);
|
||||
|
||||
// simple integral
|
||||
_trueCourseDeg += turnDeg;
|
||||
SG_NORMALIZE_RANGE(_trueCourseDeg, 0.0, 360.0);
|
||||
}
|
||||
}
|
||||
|
||||
SGGeod currentPos = globals->get_aircraft_position();
|
||||
|
||||
const double M = flightgear::AircraftPerformance::machForCAS(currentPos.getElevationFt(), _speedKnots);
|
||||
_speedMachProp->setDoubleValue(M);
|
||||
const double gs = flightgear::AircraftPerformance::groundSpeedForMach(currentPos.getElevationFt(), M);
|
||||
_groundspeedKnotsProp->setDoubleValue(gs);
|
||||
double d = gs * SG_KT_TO_MPS * dt;
|
||||
SGGeod newPos = SGGeodesy::direct(currentPos, _trueCourseDeg, d);
|
||||
|
||||
if (_altActive) {
|
||||
if (fabs(_targetAltitudeFt - currentPos.getElevationFt()) < 1) {
|
||||
_altActive = false;
|
||||
newPos.setElevationFt(_targetAltitudeFt);
|
||||
} else {
|
||||
double errorFt = _targetAltitudeFt - currentPos.getElevationFt();
|
||||
double vspeed = std::min(fabs(errorFt),_vspeedFPM * dt / 60.0);
|
||||
double dv = copysign(vspeed, errorFt);
|
||||
newPos.setElevationFt(currentPos.getElevationFt() + dv);
|
||||
}
|
||||
}
|
||||
|
||||
setPosition(newPos);
|
||||
}
|
||||
|
||||
void TestPilot::setPosition(const SGGeod& pos)
|
||||
{
|
||||
_latProp->setDoubleValue(pos.getLatitudeDeg());
|
||||
_lonProp->setDoubleValue(pos.getLongitudeDeg());
|
||||
_altitudeProp->setDoubleValue(pos.getElevationFt());
|
||||
|
||||
_headingProp->setDoubleValue(_trueCourseDeg);
|
||||
_speedKnotsProp->setDoubleValue(_speedKnots);
|
||||
_verticalFPMProp->setDoubleValue(_vspeedFPM);
|
||||
}
|
||||
|
||||
void TestPilot::setTargetAltitudeFtMSL(double altFt)
|
||||
{
|
||||
_targetAltitudeFt = altFt;
|
||||
_altActive = true;
|
||||
}
|
||||
|
||||
bool TestPilot::isOnHeading(double heading) const
|
||||
{
|
||||
const double hdgDelta = (_trueCourseDeg - heading);
|
||||
return fabs(hdgDelta) < 0.5;
|
||||
}
|
||||
|
||||
double TestPilot::trueCourseDeg() const
|
||||
{
|
||||
return _trueCourseDeg;
|
||||
}
|
||||
|
||||
|
||||
} // of namespace
|
||||
112
test_suite/FGTestApi/TestPilot.hxx
Normal file
112
test_suite/FGTestApi/TestPilot.hxx
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (C) 2019 James Turner
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _FGTEST_API_TEST_PILOT_HXX
|
||||
#define _FGTEST_API_TEST_PILOT_HXX
|
||||
|
||||
#include <simgear/props/propsfwd.hxx>
|
||||
#include <simgear/math/SGMathFwd.hxx>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/math/SGGeod.hxx>
|
||||
|
||||
class GPS;
|
||||
|
||||
namespace FGTestApi {
|
||||
|
||||
/**
|
||||
* @brief simulation of the user (pilot) fying in a particular way
|
||||
* around the world. Standard property tree values are updated
|
||||
* (position / orientation / velocity)
|
||||
*/
|
||||
class TestPilot : public SGSubsystem
|
||||
{
|
||||
public:
|
||||
TestPilot(SGPropertyNode_ptr props = {});
|
||||
~TestPilot();
|
||||
|
||||
void resetAtPosition(const SGGeod& pos);
|
||||
|
||||
void setSpeedKts(double knots);
|
||||
|
||||
void setCourseTrue(double deg);
|
||||
void turnToCourse(double deg);
|
||||
|
||||
void setVerticalFPM(double fpm);
|
||||
void setTargetAltitudeFtMSL(double altFt);
|
||||
|
||||
// void setTurnRateDegSec();
|
||||
|
||||
void init() override;
|
||||
void update(double dT) override;
|
||||
|
||||
void flyHeading(double hdg);
|
||||
void flyDirectTo(const SGGeod& target);
|
||||
void flyGPSCourse(GPS *gps);
|
||||
|
||||
void flyGPSCourseOffset(GPS *gps, double offsetNm);
|
||||
|
||||
bool isOnHeading(double heading) const;
|
||||
|
||||
double trueCourseDeg() const;
|
||||
private:
|
||||
enum class LateralMode
|
||||
{
|
||||
Heading,
|
||||
Direct,
|
||||
GPSCourse,
|
||||
GPSOffset
|
||||
};
|
||||
|
||||
void updateValues(double dt);
|
||||
void setPosition(const SGGeod& pos);
|
||||
|
||||
SGPropertyNode_ptr _propRoot;
|
||||
|
||||
double _trueCourseDeg = 0.0;
|
||||
double _speedKnots = 0.0; // IAS
|
||||
double _vspeedFPM = 0.0;
|
||||
|
||||
bool _turnActive = false;
|
||||
bool _altActive = false;
|
||||
double _targetCourseDeg = 0.0;
|
||||
double _targetAltitudeFt = 0.0;
|
||||
|
||||
LateralMode _lateralMode = LateralMode::Heading;
|
||||
SGGeod _targetPos;
|
||||
GPS* _gps = nullptr;
|
||||
double _courseOffsetNm =0.0;
|
||||
|
||||
SGPropertyNode_ptr _latProp;
|
||||
SGPropertyNode_ptr _lonProp;
|
||||
SGPropertyNode_ptr _altitudeProp;
|
||||
SGPropertyNode_ptr _headingProp;
|
||||
SGPropertyNode_ptr _speedKnotsProp;
|
||||
SGPropertyNode_ptr _verticalFPMProp;
|
||||
SGPropertyNode_ptr _groundspeedKnotsProp;
|
||||
SGPropertyNode_ptr _speedMachProp;
|
||||
|
||||
SGPropertyNode_ptr _gpsNode;
|
||||
SGPropertyNode_ptr _gpsLegCourse;
|
||||
SGPropertyNode_ptr _courseErrorNm;
|
||||
};
|
||||
|
||||
} // of namespace FGTestApi
|
||||
|
||||
#endif // of _FGTEST_API_TEST_PILOT_HXX
|
||||
|
||||
57
test_suite/FGTestApi/scene_graph.cxx
Normal file
57
test_suite/FGTestApi/scene_graph.cxx
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "scene_graph.hxx"
|
||||
|
||||
#include <Main/fg_props.hxx>
|
||||
#include <Main/globals.hxx>
|
||||
#include <Main/locale.hxx>
|
||||
#include <Scenery/scenery.hxx>
|
||||
#include <Viewer/renderer.hxx>
|
||||
#include <Viewer/FGEventHandler.hxx>
|
||||
|
||||
|
||||
namespace FGTestApi {
|
||||
namespace setUp {
|
||||
|
||||
void initScenery()
|
||||
{
|
||||
// Read the global defaults from $FG_ROOT/defaults.xml (needed by the renderer).
|
||||
SGPath defaultsXML = globals->get_fg_root() / "defaults.xml";
|
||||
if (!defaultsXML.exists())
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Cannot read the global defaults from \"" << defaultsXML.utf8Str() << "\".");
|
||||
fgLoadProps("defaults.xml", globals->get_props());
|
||||
|
||||
// otherwise fgSplashProgress will assert
|
||||
globals->get_locale()->selectLanguage({});
|
||||
|
||||
// Set up the renderer.
|
||||
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
|
||||
FGRenderer* render = globals->get_renderer();
|
||||
render->init();
|
||||
render->setView(viewer.get());
|
||||
|
||||
// Start up the scenery subsystem.
|
||||
globals->add_new_subsystem<FGScenery>(SGSubsystemMgr::DISPLAY);
|
||||
globals->get_scenery()->init();
|
||||
globals->get_scenery()->bind();
|
||||
}
|
||||
|
||||
} // End of namespace setUp.
|
||||
} // End of namespace FGTestApi.
|
||||
31
test_suite/FGTestApi/scene_graph.hxx
Normal file
31
test_suite/FGTestApi/scene_graph.hxx
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FG_TEST_SCENE_GRAPH_HXX
|
||||
#define FG_TEST_SCENE_GRAPH_HXX
|
||||
|
||||
namespace FGTestApi {
|
||||
namespace setUp {
|
||||
|
||||
void initScenery();
|
||||
|
||||
} // End of namespace setUp.
|
||||
} // End of namespace FGTestApi.
|
||||
|
||||
#endif // FG_TEST_SCENE_GRAPH_HXX
|
||||
30
test_suite/FGTestApi/testApis.cxx
Normal file
30
test_suite/FGTestApi/testApis.cxx
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
// implement various test-only methods on classes
|
||||
|
||||
#include <Airports/groundnetwork.hxx>
|
||||
#include <Airports/airport.hxx>
|
||||
#include <Airports/xmlloader.hxx>
|
||||
#include <Navaids/procedure.hxx>
|
||||
|
||||
void FGAirport::testSuiteInjectGroundnetXML(const SGPath& path)
|
||||
{
|
||||
_groundNetwork.reset(new FGGroundNetwork(const_cast<FGAirport*>(this)));
|
||||
XMLLoader::loadFromPath(_groundNetwork.get(), path);
|
||||
_groundNetwork->init();
|
||||
}
|
||||
|
||||
void FGAirport::testSuiteInjectProceduresXML(const SGPath& path)
|
||||
{
|
||||
if (mProceduresLoaded) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Procedures already loaded for" << ident());
|
||||
mSIDs.clear();
|
||||
mSTARs.clear();
|
||||
mApproaches.clear();
|
||||
}
|
||||
|
||||
mProceduresLoaded = true;
|
||||
flightgear::RouteBase::loadAirportProcedures(path, const_cast<FGAirport*>(this));
|
||||
}
|
||||
|
||||
476
test_suite/FGTestApi/testGlobals.cxx
Normal file
476
test_suite/FGTestApi/testGlobals.cxx
Normal file
@@ -0,0 +1,476 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "test_suite/dataStore.hxx"
|
||||
#include <ctime>
|
||||
|
||||
#include "TestDataLogger.hxx"
|
||||
#include "testGlobals.hxx"
|
||||
|
||||
#include <simgear/io/iostreams/sgstream.hxx>
|
||||
|
||||
#if defined(HAVE_QT)
|
||||
#include <GUI/QtLauncher.hxx>
|
||||
#endif
|
||||
|
||||
#include <Main/globals.hxx>
|
||||
#include <Main/options.hxx>
|
||||
#include <Main/util.hxx>
|
||||
#include <Main/FGInterpolator.hxx>
|
||||
#include <Main/locale.hxx>
|
||||
|
||||
#include <Time/TimeManager.hxx>
|
||||
|
||||
#include <simgear/structure/event_mgr.hxx>
|
||||
#include <simgear/timing/timestamp.hxx>
|
||||
#include <simgear/timing/sg_time.hxx>
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
#include <simgear/props/props_io.hxx>
|
||||
|
||||
#include <Airports/airport.hxx>
|
||||
#include <Navaids/FlightPlan.hxx>
|
||||
#include <Navaids/waypoint.hxx>
|
||||
#include <Navaids/routePath.hxx>
|
||||
|
||||
#include <Scripting/NasalSys.hxx>
|
||||
|
||||
using namespace flightgear;
|
||||
|
||||
namespace FGTestApi {
|
||||
|
||||
bool global_loggingToKML = false;
|
||||
sg_ofstream global_kmlStream;
|
||||
bool global_lineStringOpen = false;
|
||||
|
||||
namespace setUp {
|
||||
|
||||
void initTestGlobals(const std::string& testName)
|
||||
{
|
||||
assert(globals == nullptr);
|
||||
globals = new FGGlobals;
|
||||
|
||||
DataStore &data = DataStore::get();
|
||||
if (!data.getFGRoot().exists()) {
|
||||
data.findFGRoot("");
|
||||
}
|
||||
globals->set_fg_root(data.getFGRoot());
|
||||
|
||||
// current dir
|
||||
SGPath homePath = SGPath::fromUtf8(FGBUILDDIR) / "test_home";
|
||||
if (!homePath.exists()) {
|
||||
(homePath / "dummyFile").create_dir(0755);
|
||||
}
|
||||
|
||||
globals->set_fg_home(homePath);
|
||||
auto props = globals->get_props();
|
||||
props->setStringValue("sim/fg-home", homePath.utf8Str());
|
||||
|
||||
// Activate headless mode.
|
||||
globals->set_headless(true);
|
||||
|
||||
fgSetDefaults();
|
||||
|
||||
auto t = globals->add_new_subsystem<TimeManager>(SGSubsystemMgr::INIT);
|
||||
t->bind();
|
||||
t->init(); // establish mag-var data
|
||||
|
||||
/**
|
||||
* Both the event manager and subsystem manager are initialised by the
|
||||
* FGGlobals ctor, but only the subsystem manager is destroyed by the dtor.
|
||||
* Here the event manager is added to the subsystem manager so it can be
|
||||
* destroyed via the subsystem manager.
|
||||
*/
|
||||
globals->add_subsystem("events", globals->get_event_mgr(), SGSubsystemMgr::DISPLAY);
|
||||
|
||||
// necessary to avoid asserts: mark FGLocale as initialized
|
||||
globals->get_locale()->selectLanguage({});
|
||||
}
|
||||
|
||||
bool logPositionToKML(const std::string& testName)
|
||||
{
|
||||
// clear any previous state
|
||||
if (global_loggingToKML) {
|
||||
global_kmlStream.close();
|
||||
global_lineStringOpen = false;
|
||||
}
|
||||
|
||||
SGPath p = SGPath::desktop() / (testName + ".kml");
|
||||
global_kmlStream.open(p);
|
||||
if (!global_kmlStream.is_open()) {
|
||||
SG_LOG(SG_GENERAL, SG_WARN, "unable to open:" << p);
|
||||
return false;
|
||||
}
|
||||
|
||||
// pre-amble
|
||||
global_kmlStream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
"<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n"
|
||||
"<Document>\n";
|
||||
// need more precision for doubles when specifying lat/lon, see
|
||||
// https://xkcd.com/2170/ :)
|
||||
global_kmlStream.precision(12);
|
||||
|
||||
global_loggingToKML = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool logLinestringsToKML(const std::string& testName)
|
||||
{
|
||||
// clear any previous state
|
||||
if (global_loggingToKML) {
|
||||
global_kmlStream.close();
|
||||
global_lineStringOpen = false;
|
||||
}
|
||||
|
||||
SGPath p = SGPath::desktop() / (testName + ".kml");
|
||||
global_kmlStream.open(p);
|
||||
if (!global_kmlStream.is_open()) {
|
||||
SG_LOG(SG_GENERAL, SG_WARN, "unable to open:" << p);
|
||||
return false;
|
||||
}
|
||||
|
||||
// pre-amble
|
||||
global_kmlStream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
"<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n"
|
||||
"<Document>\n";
|
||||
// need more precision for doubles when specifying lat/lon, see
|
||||
// https://xkcd.com/2170/ :)
|
||||
global_kmlStream.precision(12);
|
||||
|
||||
global_loggingToKML = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void initStandardNasal(bool withCanvas)
|
||||
{
|
||||
fgInitAllowedPaths();
|
||||
|
||||
auto nasalNode = globals->get_props()->getNode("nasal", true);
|
||||
|
||||
// load loadpriority.xml, for default modules load order
|
||||
|
||||
auto nasalLoadPriority = globals->get_props()->getNode("/sim/nasal-load-priority",true);
|
||||
readProperties(globals->get_fg_root() / "Nasal/loadpriority.xml", nasalLoadPriority);
|
||||
|
||||
// set various props to reduce Nasal errors
|
||||
auto props = globals->get_props();
|
||||
props->setStringValue("sim/flight-model", "null");
|
||||
props->setStringValue("sim/aircraft", "test-suite-aircraft");
|
||||
|
||||
props->setDoubleValue("sim/current-view/config/default-field-of-view-deg", 90.0);
|
||||
// ensure /sim/view/config exists
|
||||
props->setBoolValue("sim/view/config/foo", false);
|
||||
|
||||
props->setBoolValue("sim/rendering/precipitation-gui-enable", false);
|
||||
props->setBoolValue("sim/rendering/precipitation-aircraft-enable", false);
|
||||
|
||||
// disable various larger modules
|
||||
nasalNode->setBoolValue("canvas/enabled", withCanvas);
|
||||
nasalNode->setBoolValue("jetways/enabled", false);
|
||||
nasalNode->setBoolValue("jetways_edit/enabled", false);
|
||||
nasalNode->setBoolValue("local_weather/enabled", false);
|
||||
|
||||
// Nasal needs the interpolator running
|
||||
globals->add_subsystem("prop-interpolator", new FGInterpolator, SGSubsystemMgr::INIT);
|
||||
|
||||
// will be inited, since we already did that
|
||||
globals->add_new_subsystem<FGNasalSys>(SGSubsystemMgr::INIT);
|
||||
}
|
||||
|
||||
void populateFPWithoutNasal(flightgear::FlightPlanRef f,
|
||||
const std::string& depICAO, const std::string& depRunway,
|
||||
const std::string& destICAO, const std::string& destRunway,
|
||||
const std::string& waypoints)
|
||||
{
|
||||
FGAirportRef depApt = FGAirport::getByIdent(depICAO);
|
||||
f->setDeparture(depApt->getRunwayByIdent(depRunway));
|
||||
|
||||
|
||||
FGAirportRef destApt = FGAirport::getByIdent(destICAO);
|
||||
f->setDestination(destApt->getRunwayByIdent(destRunway));
|
||||
|
||||
// since we don't have the Nasal route-manager delegate, insert the
|
||||
// runway waypoints manually
|
||||
|
||||
auto depRwy = new RunwayWaypt(f->departureRunway(), f);
|
||||
depRwy->setFlag(WPT_DEPARTURE);
|
||||
f->insertWayptAtIndex(depRwy, -1);
|
||||
|
||||
for (auto ws : simgear::strutils::split(waypoints)) {
|
||||
WayptRef wpt = f->waypointFromString(ws);
|
||||
if (!wpt) {
|
||||
SG_LOG(SG_NAVAID, SG_ALERT, "No waypoint created for:" << ws);
|
||||
continue;
|
||||
}
|
||||
f->insertWayptAtIndex(wpt, -1);
|
||||
}
|
||||
|
||||
|
||||
auto destRwy = f->destinationRunway();
|
||||
f->insertWayptAtIndex(new BasicWaypt(destRwy->pointOnCenterline(-8 * SG_NM_TO_METER),
|
||||
destRwy->ident() + "-8", f), -1);
|
||||
f->insertWayptAtIndex(new RunwayWaypt(destRwy, f), -1);
|
||||
}
|
||||
|
||||
void populateFPWithNasal(flightgear::FlightPlanRef f,
|
||||
const std::string& depICAO, const std::string& depRunway,
|
||||
const std::string& destICAO, const std::string& destRunway,
|
||||
const std::string& waypoints)
|
||||
{
|
||||
FGAirportRef depApt = FGAirport::getByIdent(depICAO);
|
||||
f->setDeparture(depApt->getRunwayByIdent(depRunway));
|
||||
|
||||
FGAirportRef destApt = FGAirport::getByIdent(destICAO);
|
||||
f->setDestination(destApt->getRunwayByIdent(destRunway));
|
||||
|
||||
// insert after the last departure waypoint
|
||||
int insertIndex = 1;
|
||||
|
||||
for (auto ws : simgear::strutils::split(waypoints)) {
|
||||
WayptRef wpt = f->waypointFromString(ws);
|
||||
f->insertWayptAtIndex(wpt, insertIndex++);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace setUp.
|
||||
|
||||
void beginLineString(const std::string& ident)
|
||||
{
|
||||
global_lineStringOpen = true;
|
||||
global_kmlStream << "<Placemark>\n";
|
||||
if (!ident.empty()) {
|
||||
global_kmlStream << "<name>" << ident << "</name>\n";
|
||||
}
|
||||
global_kmlStream << "<LineString>\n";
|
||||
global_kmlStream << "<tessellate>1</tessellate>\n";
|
||||
global_kmlStream << "<coordinates>\n";
|
||||
}
|
||||
|
||||
void logCoordinate(const SGGeod& pos)
|
||||
{
|
||||
if (!global_lineStringOpen) {
|
||||
beginLineString({});
|
||||
}
|
||||
|
||||
global_kmlStream << pos.getLongitudeDeg() << "," << pos.getLatitudeDeg() << " " << endl;
|
||||
}
|
||||
|
||||
void rawLogCoordinate(const SGGeod& pos)
|
||||
{
|
||||
global_kmlStream << pos.getLongitudeDeg() << "," << pos.getLatitudeDeg() << " " << endl;
|
||||
}
|
||||
|
||||
void endCurrentLineString()
|
||||
{
|
||||
global_lineStringOpen = false;
|
||||
global_kmlStream <<
|
||||
"</coordinates>\n"
|
||||
"</LineString>\n"
|
||||
"</Placemark>\n" << endl;
|
||||
}
|
||||
|
||||
void setPosition(const SGGeod& g)
|
||||
{
|
||||
if (global_loggingToKML) {
|
||||
if (global_lineStringOpen) {
|
||||
endCurrentLineString();
|
||||
}
|
||||
|
||||
logCoordinate(g);
|
||||
}
|
||||
|
||||
globals->get_props()->setDoubleValue("position/latitude-deg", g.getLatitudeDeg());
|
||||
globals->get_props()->setDoubleValue("position/longitude-deg", g.getLongitudeDeg());
|
||||
globals->get_props()->setDoubleValue("position/altitude-ft", g.getElevationFt());
|
||||
}
|
||||
|
||||
const SGGeod getPosition()
|
||||
{
|
||||
return SGGeod::fromDegFt(
|
||||
globals->get_props()->getDoubleValue("position/latitude-deg"),
|
||||
globals->get_props()->getDoubleValue("position/longitude-deg"),
|
||||
globals->get_props()->getDoubleValue("position/altitude-ft"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setPositionAndStabilise(const SGGeod& g)
|
||||
{
|
||||
setPosition(g);
|
||||
for (int i=0; i<60; ++i) {
|
||||
globals->get_subsystem_mgr()->update(0.015);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void runForTime(double t)
|
||||
{
|
||||
const int tickHz = 30;
|
||||
const double tickDuration = 1.0 / tickHz;
|
||||
|
||||
int ticks = static_cast<int>(t * tickHz);
|
||||
assert(ticks > 0);
|
||||
|
||||
const int logInterval = 0.5 * tickHz;
|
||||
int nextLog = 0;
|
||||
|
||||
long startTime = globals->get_time_params()->get_cur_time();
|
||||
|
||||
for (int t = 0; t < ticks; ++t) {
|
||||
globals->inc_sim_time_sec(tickDuration);
|
||||
globals->get_time_params()->update(globals->get_view_position(), startTime, t * tickDuration);
|
||||
globals->get_subsystem_mgr()->update(tickDuration);
|
||||
|
||||
if (nextLog == 0) {
|
||||
if (global_loggingToKML) {
|
||||
logCoordinate(globals->get_aircraft_position());
|
||||
}
|
||||
|
||||
if (DataLogger::isActive()) {
|
||||
DataLogger::instance()->writeRecord();
|
||||
}
|
||||
nextLog = logInterval;
|
||||
} else {
|
||||
nextLog--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool runForTimeWithCheck(double t, RunCheck check)
|
||||
{
|
||||
const int tickHz = 30;
|
||||
const double tickDuration = 1.0 / tickHz;
|
||||
|
||||
int ticks = static_cast<int>(t * tickHz);
|
||||
assert(ticks > 0);
|
||||
const int logInterval = 0.5 * tickHz;
|
||||
int nextLog = 0;
|
||||
|
||||
for (int t = 0; t < ticks; ++t) {
|
||||
globals->inc_sim_time_sec(tickDuration);
|
||||
globals->get_subsystem_mgr()->update(tickDuration);
|
||||
|
||||
if (nextLog == 0) {
|
||||
if (global_loggingToKML) {
|
||||
logCoordinate(globals->get_aircraft_position());
|
||||
}
|
||||
|
||||
if (DataLogger::isActive()) {
|
||||
DataLogger::instance()->writeRecord();
|
||||
}
|
||||
nextLog = logInterval;
|
||||
} else {
|
||||
nextLog--;
|
||||
}
|
||||
|
||||
bool done = check();
|
||||
if (done) {
|
||||
if (global_loggingToKML) {
|
||||
endCurrentLineString();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void adjustSimulationWorldTime(time_t desiredUnixTime)
|
||||
{
|
||||
int timeOffset = desiredUnixTime - time(nullptr);
|
||||
globals->get_props()->setIntValue("/sim/time/cur-time-override", 0);
|
||||
globals->get_props()->setIntValue("/sim/time/warp", timeOffset);
|
||||
|
||||
globals->get_subsystem<TimeManager>()->update(0.0);
|
||||
}
|
||||
|
||||
void writeFlightPlanToKML(flightgear::FlightPlanRef fp)
|
||||
{
|
||||
if (!global_loggingToKML)
|
||||
return;
|
||||
|
||||
RoutePath rpath(fp);
|
||||
|
||||
for (int i=0; i<fp->numLegs(); ++i) {
|
||||
SGGeodVec legPath = rpath.pathForIndex(i);
|
||||
auto wp = fp->legAtIndex(i)->waypoint();
|
||||
|
||||
writeGeodsToKML("FP-leg-" + wp->ident(), legPath);
|
||||
|
||||
SGGeod legWPPosition = wp->position();
|
||||
writePointToKML("WP " + wp->ident(), legWPPosition);
|
||||
}
|
||||
}
|
||||
|
||||
void writeGeodsToKML(const std::string &label, const flightgear::SGGeodVec& geods)
|
||||
{
|
||||
if (global_lineStringOpen) {
|
||||
endCurrentLineString();
|
||||
}
|
||||
|
||||
beginLineString(label);
|
||||
|
||||
for (const auto& g : geods) {
|
||||
logCoordinate(g);
|
||||
}
|
||||
|
||||
endCurrentLineString();
|
||||
}
|
||||
|
||||
void writePointToKML(const std::string& ident, const SGGeod& pos)
|
||||
{
|
||||
global_kmlStream << "<Placemark>\n";
|
||||
global_kmlStream << "<name>" << ident << "</name>\n";
|
||||
global_kmlStream << "<Point>\n";
|
||||
global_kmlStream << "<coordinates>\n";
|
||||
rawLogCoordinate(pos);
|
||||
global_kmlStream << "</coordinates>\n";
|
||||
global_kmlStream << "</Point>\n";
|
||||
global_kmlStream << "</Placemark>\n";
|
||||
}
|
||||
|
||||
bool executeNasal(const std::string& code)
|
||||
{
|
||||
auto nasal = globals->get_subsystem<FGNasalSys>();
|
||||
if (!nasal) {
|
||||
throw sg_exception("Nasal not available");
|
||||
}
|
||||
|
||||
nasal->getAndClearErrorList();
|
||||
std::string output, parseErrors;
|
||||
bool ok = nasal->parseAndRunWithOutput(code, output, parseErrors);
|
||||
if (!parseErrors.empty()) {
|
||||
SG_LOG(SG_NASAL, SG_ALERT, "Errors running Nasal:" << parseErrors);
|
||||
return false;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
namespace tearDown {
|
||||
|
||||
void shutdownTestGlobals()
|
||||
{
|
||||
// The QApplication instance must be destroyed before exit() begins, see
|
||||
// <https://bugreports.qt.io/browse/QTBUG-48709> (otherwise, segfault).
|
||||
#if defined(HAVE_QT)
|
||||
flightgear::shutdownQtApp();
|
||||
#endif
|
||||
|
||||
delete globals;
|
||||
globals = nullptr;
|
||||
|
||||
if (global_kmlStream) {
|
||||
if (global_lineStringOpen) {
|
||||
endCurrentLineString();
|
||||
}
|
||||
// post-amble
|
||||
global_kmlStream << "</Document>\n"
|
||||
"</kml>" << endl;
|
||||
global_kmlStream.close();
|
||||
global_loggingToKML = false;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace tearDown.
|
||||
|
||||
} // End of namespace FGTestApi.
|
||||
75
test_suite/FGTestApi/testGlobals.hxx
Normal file
75
test_suite/FGTestApi/testGlobals.hxx
Normal file
@@ -0,0 +1,75 @@
|
||||
#ifndef FG_TEST_GLOBALS_HELPERS_HXX
|
||||
#define FG_TEST_GLOBALS_HELPERS_HXX
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
#include <simgear/math/SGGeod.hxx>
|
||||
#include <simgear/structure/SGSharedPtr.hxx>
|
||||
|
||||
namespace flightgear
|
||||
{
|
||||
class FlightPlan;
|
||||
typedef SGSharedPtr<FlightPlan> FlightPlanRef;
|
||||
|
||||
typedef std::vector<SGGeod> SGGeodVec;
|
||||
}
|
||||
|
||||
namespace FGTestApi {
|
||||
|
||||
namespace setUp {
|
||||
|
||||
void initTestGlobals(const std::string& testName);
|
||||
|
||||
bool logPositionToKML(const std::string& testName);
|
||||
/**Don't log aircraft positions*/
|
||||
bool logLinestringsToKML(const std::string& testName);
|
||||
|
||||
void initStandardNasal(bool withCanvas = false);
|
||||
|
||||
void populateFPWithoutNasal(flightgear::FlightPlanRef f,
|
||||
const std::string& depICAO, const std::string& depRunway,
|
||||
const std::string& destICAO, const std::string& destRunway,
|
||||
const std::string& waypoints);
|
||||
|
||||
void populateFPWithNasal(flightgear::FlightPlanRef f,
|
||||
const std::string& depICAO, const std::string& depRunway,
|
||||
const std::string& destICAO, const std::string& destRunway,
|
||||
const std::string& waypoints);
|
||||
|
||||
} // End of namespace setUp.
|
||||
|
||||
// helpers during tests
|
||||
|
||||
const SGGeod getPosition();
|
||||
void setPosition(const SGGeod& g);
|
||||
void setPositionAndStabilise(const SGGeod& g);
|
||||
|
||||
void runForTime(double t);
|
||||
|
||||
/**
|
||||
@brief set the simulation date/time clock to 'time'
|
||||
*/
|
||||
void adjustSimulationWorldTime(time_t time);
|
||||
|
||||
using RunCheck = std::function<bool(void)>;
|
||||
|
||||
bool runForTimeWithCheck(double t, RunCheck check);
|
||||
|
||||
void writeFlightPlanToKML(flightgear::FlightPlanRef fp);
|
||||
|
||||
void writeGeodsToKML(const std::string &label, const flightgear::SGGeodVec& geods);
|
||||
void writePointToKML(const std::string& ident, const SGGeod& pos);
|
||||
|
||||
bool executeNasal(const std::string& code);
|
||||
|
||||
namespace tearDown {
|
||||
|
||||
void shutdownTestGlobals();
|
||||
|
||||
} // End of namespace tearDown.
|
||||
|
||||
} // End of namespace FGTestApi.
|
||||
|
||||
#endif // of FG_TEST_GLOBALS_HELPERS_HXX
|
||||
1
test_suite/attic/README
Normal file
1
test_suite/attic/README
Normal file
@@ -0,0 +1 @@
|
||||
This is a collection of ancient testing code.
|
||||
318
test_suite/attic/alcinfo.cxx
Normal file
318
test_suite/attic/alcinfo.cxx
Normal file
@@ -0,0 +1,318 @@
|
||||
/* -*- mode: C; tab-width:8; c-basic-offset:8 -*-
|
||||
* vi:set ts=8:
|
||||
*
|
||||
* alcinfo.x
|
||||
*
|
||||
* alcinfo display info about a ALC extension and OpenAL renderer
|
||||
*
|
||||
* This file is in the Public Domain and comes with no warranty.
|
||||
* Erik Hofman <erik@ehofman.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <OpenAL/al.h>
|
||||
# include <OpenAL/alc.h>
|
||||
#else
|
||||
# include <AL/al.h>
|
||||
# include <AL/alc.h>
|
||||
# include <AL/alext.h>
|
||||
#endif
|
||||
|
||||
#ifndef AL_VERSION_1_1
|
||||
# ifdef __APPLE__
|
||||
# include <OpenAL/altypes.h>
|
||||
# include <OpenAL/alctypes.h>
|
||||
#else
|
||||
# include <AL/altypes.h>
|
||||
# include <AL/alctypes.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
using std::string;
|
||||
|
||||
#ifndef ALC_ALL_DEVICES_SPECIFIER
|
||||
# define ALC_ALL_DEVICES_SPECIFIER 0x1013
|
||||
#endif
|
||||
|
||||
#define MAX_DATA 16
|
||||
static const int indentation = 4;
|
||||
static const int maxmimumWidth = 79;
|
||||
|
||||
void printExtensions (const char *, char, const char *);
|
||||
void displayDevices(const char *, const char *);
|
||||
char *getDeviceName(int, char **);
|
||||
void testForError(void *, const string&);
|
||||
void testForALCError(ALCdevice *);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ALCint data[MAX_DATA];
|
||||
ALCdevice *device = NULL;
|
||||
ALCcontext *context = NULL;
|
||||
ALenum error;
|
||||
char *s;
|
||||
|
||||
if (alcIsExtensionPresent(NULL, "ALC_enumeration_EXT") == AL_TRUE)
|
||||
{
|
||||
if (alcIsExtensionPresent(NULL, "ALC_enumerate_all_EXT") == AL_FALSE)
|
||||
s = (char *)alcGetString(NULL, ALC_DEVICE_SPECIFIER);
|
||||
else
|
||||
s = (char *)alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
|
||||
displayDevices("output", s);
|
||||
|
||||
s = (char *)alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
|
||||
displayDevices("input", s);
|
||||
}
|
||||
|
||||
s = getDeviceName(argc, argv);
|
||||
device = alcOpenDevice(s);
|
||||
testForError(device, "Audio device not available.");
|
||||
|
||||
context = alcCreateContext(device, NULL);
|
||||
testForError(context, "Unable to create a valid context.");
|
||||
|
||||
alcMakeContextCurrent(context);
|
||||
testForALCError(device);
|
||||
|
||||
s = (char *)alcGetString(device, ALC_DEFAULT_DEVICE_SPECIFIER);
|
||||
printf("default output device: %s\n", s);
|
||||
testForALCError(device);
|
||||
|
||||
error = alcIsExtensionPresent(device, "ALC_EXT_capture");
|
||||
if (error)
|
||||
{
|
||||
s = (char *)alcGetString(device, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
|
||||
printf("default input device: %s\n", s);
|
||||
testForALCError(device);
|
||||
}
|
||||
printf("capture support: %s\n", (error) ? "yes" : "no");
|
||||
|
||||
alcGetIntegerv(device, ALC_FREQUENCY, 1, data);
|
||||
printf("mixer frequency: %u hz\n", data[0]);
|
||||
testForALCError(device);
|
||||
|
||||
alcGetIntegerv(device, ALC_REFRESH, 1, data+1);
|
||||
printf("refresh rate : %u hz\n", data[0]/data[1]);
|
||||
testForALCError(device);
|
||||
|
||||
data[0] = 0;
|
||||
alcGetIntegerv(device, ALC_MONO_SOURCES, 1, data);
|
||||
error = alcGetError(device);
|
||||
if (error == AL_NONE) {
|
||||
printf("supported sources; mono: %u, ", data[0]);
|
||||
|
||||
data[0] = 0;
|
||||
alcGetIntegerv(device, ALC_STEREO_SOURCES, 1, data);
|
||||
printf("stereo: %u\n", data[0]);
|
||||
testForALCError(device);
|
||||
}
|
||||
|
||||
printf("ALC version: ");
|
||||
alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, data);
|
||||
printf("%i.", *data);
|
||||
alcGetIntegerv(device, ALC_MINOR_VERSION, 1, data);
|
||||
printf("%i\n", *data);
|
||||
testForALCError(device);
|
||||
|
||||
s = (char *)alcGetString(device, ALC_EXTENSIONS);
|
||||
printExtensions ("ALC extensions", ' ', s);
|
||||
testForALCError(device);
|
||||
|
||||
s = (char *)alGetString(AL_VENDOR);
|
||||
error = alGetError();
|
||||
if ((error = alGetError()) != AL_NO_ERROR)
|
||||
printf("Error #%x: %s\n", error, alGetString(error));
|
||||
else
|
||||
printf("OpenAL vendor string: %s\n", s);
|
||||
|
||||
s = (char *)alGetString(AL_RENDERER);
|
||||
if ((error = alGetError()) != AL_NO_ERROR)
|
||||
printf("Error #%x: %s\n", error, alGetString(error));
|
||||
else
|
||||
printf("OpenAL renderer string: %s\n", s);
|
||||
|
||||
s = (char *)alGetString(AL_VERSION);
|
||||
if ((error = alGetError()) != AL_NO_ERROR)
|
||||
printf("Error #%x: %s\n", error, alGetString(error));
|
||||
else if (!s)
|
||||
printf("Querying AL_VERSION returned NULL pointer!\n");
|
||||
else
|
||||
printf("OpenAL version string: %s\n", s);
|
||||
|
||||
s = (char *)alGetString(AL_EXTENSIONS);
|
||||
printExtensions ("OpenAL extensions", ' ', s);
|
||||
testForALCError(device);
|
||||
|
||||
if (alcMakeContextCurrent(NULL) == 0)
|
||||
printf("alcMakeContextCurrent failed.\n");
|
||||
|
||||
device = alcGetContextsDevice(context);
|
||||
alcDestroyContext(context);
|
||||
testForALCError(device);
|
||||
|
||||
if (alcCloseDevice(device) == 0)
|
||||
printf("alcCloseDevice failed.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
printChar (int c, int *width)
|
||||
{
|
||||
putchar (c);
|
||||
*width = (c == '\n') ? 0 : (*width + 1);
|
||||
}
|
||||
|
||||
void
|
||||
indent (int *width)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < indentation; i++)
|
||||
{
|
||||
printChar (' ', width);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
printExtensions (const char *header, char separator, const char *extensions)
|
||||
{
|
||||
int width = 0, start = 0, end = 0;
|
||||
|
||||
printf ("%s:\n", header);
|
||||
if (extensions == NULL || extensions[0] == '\0')
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
indent (&width);
|
||||
while (1)
|
||||
{
|
||||
if (extensions[end] == separator || extensions[end] == '\0')
|
||||
{
|
||||
if (width + end - start + 2 > maxmimumWidth)
|
||||
{
|
||||
printChar ('\n', &width);
|
||||
indent (&width);
|
||||
}
|
||||
while (start < end)
|
||||
{
|
||||
printChar (extensions[start], &width);
|
||||
start++;
|
||||
}
|
||||
if (extensions[end] == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
start++;
|
||||
end++;
|
||||
if (extensions[end] == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
printChar (',', &width);
|
||||
printChar (' ', &width);
|
||||
}
|
||||
end++;
|
||||
}
|
||||
printChar ('\n', &width);
|
||||
}
|
||||
|
||||
char *
|
||||
getCommandLineOption(int argc, char **argv, const string& option)
|
||||
{
|
||||
int slen = option.size();
|
||||
char *rv = 0;
|
||||
int i;
|
||||
|
||||
for (i=0; i<argc; i++)
|
||||
{
|
||||
if (strncmp(argv[i], option.c_str(), slen) == 0)
|
||||
{
|
||||
i++;
|
||||
if (i<argc) rv = argv[i];
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
char *
|
||||
getDeviceName(int argc, char **argv)
|
||||
{
|
||||
static char devname[255];
|
||||
int len = 255;
|
||||
char *s;
|
||||
|
||||
s = getCommandLineOption(argc, argv, "-d");
|
||||
if (s)
|
||||
{
|
||||
strncpy((char *)&devname, s, len);
|
||||
len -= strlen(s);
|
||||
|
||||
s = getCommandLineOption(argc, argv, "-r");
|
||||
if (s)
|
||||
{
|
||||
strncat((char *)&devname, " on ", len);
|
||||
len -= 4;
|
||||
|
||||
strncat((char *)&devname, s, len);
|
||||
}
|
||||
s = (char *)&devname;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
displayDevices(const char *type, const char *list)
|
||||
{
|
||||
ALCchar *ptr, *nptr;
|
||||
|
||||
ptr = (ALCchar *)list;
|
||||
printf("list of all available %s devices:\n", type);
|
||||
if (!list)
|
||||
{
|
||||
printf("none\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
nptr = ptr;
|
||||
while (*(nptr += strlen(ptr)+1) != 0)
|
||||
{
|
||||
printf(" %s\n", ptr);
|
||||
ptr = nptr;
|
||||
}
|
||||
printf(" %s\n", ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testForError(void *p, const string& s)
|
||||
{
|
||||
if (p == NULL)
|
||||
{
|
||||
printf("\nError: %s\n\n", s.c_str());
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testForALCError(ALCdevice *device)
|
||||
{
|
||||
ALenum error;
|
||||
error = alcGetError(device);
|
||||
if (error != ALC_NO_ERROR)
|
||||
printf("\nALC Error %x occurred: %s\n", error, alcGetString(device, error));
|
||||
}
|
||||
34
test_suite/attic/est-epsilon.cxx
Normal file
34
test_suite/attic/est-epsilon.cxx
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#if defined( __APPLE__)
|
||||
# include <OpenGL/OpenGL.h>
|
||||
#else
|
||||
# include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
GLfloat a, t;
|
||||
|
||||
a = 1.0;
|
||||
|
||||
do {
|
||||
printf("a = %.10f\n", a);
|
||||
a = a / 2.0;
|
||||
t = 1.0 + a;
|
||||
} while ( t > 1.0 );
|
||||
|
||||
a = a + a;
|
||||
|
||||
printf("Estimated GLfloat epsilon = %.10f\n", a);
|
||||
|
||||
return(0);
|
||||
}
|
||||
123
test_suite/attic/gl-info.cxx
Normal file
123
test_suite/attic/gl-info.cxx
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
From: Steve Baker <sbaker@link.com>
|
||||
Sender: root@fatcity.com
|
||||
To: OPENGL-GAMEDEV-L <OPENGL-GAMEDEV-L@fatcity.com>
|
||||
Subject: Re: Win32 OpenGL Resource Page
|
||||
Date: Fri, 24 Apr 1998 07:33:51 -0800
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#if defined( __APPLE__)
|
||||
# include <OpenGL/OpenGL.h>
|
||||
# include <GLUT/glut.h>
|
||||
#else
|
||||
# include <GL/gl.h>
|
||||
# ifdef HAVE_GLUT_H
|
||||
# include <GL/glut.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
void getPrints ( GLenum token, char *string )
|
||||
{
|
||||
printf ( "%s = \"%s\"\n", string, glGetString ( token ) ) ;
|
||||
}
|
||||
|
||||
void getPrint2f ( GLenum token, char *string )
|
||||
{
|
||||
GLfloat f[2] ;
|
||||
glGetFloatv ( token, f ) ;
|
||||
printf ( "%s = %g,%g\n", string, f[0],f[1] ) ;
|
||||
}
|
||||
|
||||
void getPrintf ( GLenum token, char *string )
|
||||
{
|
||||
GLfloat f ;
|
||||
glGetFloatv ( token, &f ) ;
|
||||
printf ( "%s = %g\n", string, f ) ;
|
||||
}
|
||||
|
||||
void getPrint2i ( GLenum token, char *string )
|
||||
{
|
||||
GLint i[2] ;
|
||||
glGetIntegerv ( token, i ) ;
|
||||
printf ( "%s = %d,%d\n", string, i[0],i[1] ) ;
|
||||
}
|
||||
|
||||
void getPrinti ( GLenum token, char *string )
|
||||
{
|
||||
GLint i ;
|
||||
glGetIntegerv ( token, &i ) ;
|
||||
printf ( "%s = %d\n", string, i ) ;
|
||||
}
|
||||
|
||||
int main ( int argc, char **argv )
|
||||
{
|
||||
#ifdef HAVE_GLUT_H
|
||||
glutInit ( &argc, argv ) ;
|
||||
glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ) ;
|
||||
glutCreateWindow ( "You should never see this window!" ) ;
|
||||
|
||||
getPrints ( GL_VENDOR , "GL_VENDOR" ) ;
|
||||
getPrints ( GL_RENDERER , "GL_RENDERER" ) ;
|
||||
getPrints ( GL_VERSION , "GL_VERSION" ) ;
|
||||
getPrints ( GL_EXTENSIONS , "GL_EXTENSIONS" ) ;
|
||||
|
||||
getPrinti ( GL_RED_BITS , "GL_RED_BITS" ) ;
|
||||
getPrinti ( GL_GREEN_BITS , "GL_GREEN_BITS" ) ;
|
||||
getPrinti ( GL_BLUE_BITS , "GL_BLUE_BITS" ) ;
|
||||
getPrinti ( GL_ALPHA_BITS , "GL_ALPHA_BITS" ) ;
|
||||
getPrinti ( GL_DEPTH_BITS , "GL_DEPTH_BITS" ) ;
|
||||
getPrinti ( GL_INDEX_BITS , "GL_INDEX_BITS" ) ;
|
||||
getPrinti ( GL_STENCIL_BITS, "GL_STENCIL_BITS" ) ;
|
||||
|
||||
getPrinti ( GL_ACCUM_RED_BITS , "GL_ACCUM_RED_BITS" ) ;
|
||||
getPrinti ( GL_ACCUM_GREEN_BITS, "GL_ACCUM_GREEN_BITS" ) ;
|
||||
getPrinti ( GL_ACCUM_BLUE_BITS , "GL_ACCUM_BLUE_BITS" ) ;
|
||||
getPrinti ( GL_ACCUM_ALPHA_BITS, "GL_ACCUM_ALPHA_BITS" ) ;
|
||||
|
||||
getPrinti ( GL_AUX_BUFFERS, "GL_AUX_BUFFERS" ) ;
|
||||
|
||||
getPrinti ( GL_MAX_ATTRIB_STACK_DEPTH , "GL_MAX_ATTRIB_STACK_DEPTH" ) ;
|
||||
getPrinti ( GL_MAX_NAME_STACK_DEPTH , "GL_MAX_NAME_STACK_DEPTH" ) ;
|
||||
getPrinti ( GL_MAX_TEXTURE_STACK_DEPTH , "GL_MAX_TEXTURE_STACK_DEPTH" ) ;
|
||||
getPrinti ( GL_MAX_PROJECTION_STACK_DEPTH, "GL_MAX_PROJECTION_STACK_DEPTH" ) ;
|
||||
getPrinti ( GL_MAX_MODELVIEW_STACK_DEPTH , "GL_MAX_MODELVIEW_STACK_DEPTH" ) ;
|
||||
|
||||
getPrinti ( GL_MAX_CLIP_PLANES , "GL_MAX_CLIP_PLANES" ) ;
|
||||
getPrinti ( GL_MAX_EVAL_ORDER , "GL_MAX_EVAL_ORDER" ) ;
|
||||
getPrinti ( GL_MAX_LIGHTS , "GL_MAX_LIGHTS" ) ;
|
||||
getPrinti ( GL_MAX_LIST_NESTING , "GL_MAX_LIST_NESTING" ) ;
|
||||
getPrinti ( GL_MAX_TEXTURE_SIZE , "GL_MAX_TEXTURE_SIZE" ) ;
|
||||
getPrint2i( GL_MAX_VIEWPORT_DIMS , "GL_MAX_VIEWPORT_DIMS" ) ;
|
||||
|
||||
getPrintf ( GL_POINT_SIZE_GRANULARITY, "GL_POINT_SIZE_GRANULARITY" ) ;
|
||||
getPrint2f( GL_POINT_SIZE_RANGE , "GL_POINT_SIZE_RANGE" ) ;
|
||||
|
||||
printf("Default values:\n\n");
|
||||
|
||||
getPrinti( GL_UNPACK_ALIGNMENT , "GL_UNPACK_ALIGNMENT" ) ;
|
||||
getPrinti( GL_UNPACK_ROW_LENGTH , "GL_UNPACK_ROW_LENGTH" ) ;
|
||||
getPrinti( GL_UNPACK_SKIP_PIXELS , "GL_UNPACK_SKIP_PIXELS" ) ;
|
||||
getPrinti( GL_UNPACK_SKIP_ROWS , "GL_UNPACK_SKIP_ROWS" ) ;
|
||||
getPrinti( GL_BLEND_SRC , "GL_BLEND_SRC" ) ;
|
||||
getPrinti( GL_BLEND_DST , "GL_BLEND_DST" ) ;
|
||||
#else
|
||||
|
||||
printf("GL Utility Toolkit (glut) was not found on this system.\n");
|
||||
#endif
|
||||
|
||||
return 0 ;
|
||||
}
|
||||
61
test_suite/attic/layout-test.cxx
Normal file
61
test_suite/attic/layout-test.cxx
Normal file
@@ -0,0 +1,61 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <osg/GL>
|
||||
#include <plib/pw.h>
|
||||
#include <plib/pu.h>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/props/props_io.hxx>
|
||||
|
||||
#include "layout.hxx"
|
||||
|
||||
// Takes a property file on the command line, lays it out, and writes
|
||||
// the resulting tree back to stdout. Requires that the
|
||||
// "Helvetica.txf" font file from the base package be in the current
|
||||
// directory.
|
||||
|
||||
// g++ -Wall -g -o layout layout.cxx layout-props.cxx layout-test.cxx
|
||||
// -I/fg/include -L/fg/lib -I.. -lsgprops -lsgdebug -lsgstructure
|
||||
// -lsgmisc -lsgxml -lplibpw -lplibpu -lplibfnt -lplibul -lGL
|
||||
|
||||
// We can't load a plib fntTexFont without a GL context, so we use the
|
||||
// PW library to initialize things. The callbacks are required, but
|
||||
// just stubs.
|
||||
void exitCB(){ pwCleanup(); exit(0); }
|
||||
void resizeCB(int w, int h){ }
|
||||
void mouseMotionCB(int x, int y){ puMouse(x, y); }
|
||||
void mouseButtonCB(int button, int updn, int x, int y){ puMouse(button, updn, x, y); }
|
||||
void keyboardCB(int key, int updn, int x, int y){ puKeyboard(key, updn, x, y); }
|
||||
|
||||
const char* FONT_FILE = "Helvetica.txf";
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
FILE* tmp;
|
||||
if(!(tmp = fopen(FONT_FILE, "r"))) {
|
||||
fprintf(stderr, "Could not open %s for reading.\n", FONT_FILE);
|
||||
exit(1);
|
||||
}
|
||||
fclose(tmp);
|
||||
|
||||
pwInit(0, 0, 600, 400, 0, const_cast<char*>("Layout Test"), true, 0);
|
||||
pwSetCallbacks(keyboardCB, mouseButtonCB, mouseMotionCB,
|
||||
resizeCB, exitCB);
|
||||
|
||||
fntTexFont helv;
|
||||
helv.load(FONT_FILE);
|
||||
puFont puhelv(&helv);
|
||||
|
||||
LayoutWidget::setDefaultFont(&puhelv, 15);
|
||||
SGPropertyNode props;
|
||||
readProperties(argv[1], &props);
|
||||
LayoutWidget w(&props);
|
||||
int pw=0, ph=0;
|
||||
w.calcPrefSize(&pw, &ph);
|
||||
w.layout(0, 0, pw, ph);
|
||||
writeProperties(std::cout, &props, true);
|
||||
}
|
||||
274
test_suite/attic/test-env-map.cxx
Normal file
274
test_suite/attic/test-env-map.cxx
Normal file
@@ -0,0 +1,274 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#if defined( __APPLE__)
|
||||
# include <OpenGL/OpenGL.h>
|
||||
# include <GLUT/glut.h>
|
||||
#else
|
||||
# include <GL/gl.h>
|
||||
# ifdef HAVE_GLUT_H
|
||||
# include <GL/glut.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define TEXRES_X 256
|
||||
#define TEXRES_Y 256
|
||||
|
||||
#ifdef HAVE_GLUT_H
|
||||
unsigned char env_map[TEXRES_X][TEXRES_Y][4];
|
||||
GLuint texName;
|
||||
int window_x = 640, window_y = 480;
|
||||
float alpha = 0.0, beta = 0.0;
|
||||
|
||||
/*****************************************************************/
|
||||
/*****************************************************************/
|
||||
/*****************************************************************/
|
||||
void setColor(float x, float y, float z, float angular_size, float r, float g, float b, float a)
|
||||
{
|
||||
//normalize
|
||||
float inv_length = 1.0 / sqrt(x*x + y*y + z*z);
|
||||
x *= inv_length; y *= inv_length; z *= inv_length;
|
||||
printf("x = %f, y = %f, z = %f\n", x, y, z);
|
||||
|
||||
float cos_angular_size = cos(angular_size*3.1415/180.0);
|
||||
printf("cos_angular_size = %f\n", cos_angular_size);
|
||||
|
||||
for(float tz_sign = -1.0; tz_sign < 3.0; tz_sign += 2.0)
|
||||
{
|
||||
for(float tx = -1.0; tx <= 1.0; tx += 0.01)
|
||||
{
|
||||
for(float ty = -1.0; ty <= 1.0; ty += 0.01)
|
||||
{
|
||||
if ((1.0 - tx*tx - ty*ty)<0.0)
|
||||
continue;
|
||||
|
||||
float tz = tz_sign * sqrt(1.0 - tx*tx - ty*ty);
|
||||
|
||||
float cos_phi = x*tx + y*ty + z*tz;
|
||||
|
||||
if (cos_angular_size < cos_phi)
|
||||
{
|
||||
float rx = tx; //mirroring on the z=0 plane
|
||||
float ry = ty;
|
||||
float rz = -tz;
|
||||
|
||||
float inv_m = 1.0 / (2.0 * sqrt(rx*rx + ry*ry + (rz + 1)*(rz + 1)));
|
||||
int s = (int)(TEXRES_X * (rx * inv_m + 0.5));
|
||||
int t = (int)(TEXRES_Y * (ry * inv_m + 0.5));
|
||||
|
||||
//seg_fault protection:
|
||||
if (s<0) s=0;
|
||||
if (s>=TEXRES_X) s=TEXRES_X-1;
|
||||
|
||||
if (t<0) t=0;
|
||||
if (t>=TEXRES_Y) t=TEXRES_Y-1;
|
||||
|
||||
env_map[s][t][0] = (unsigned char)(r * 255);
|
||||
env_map[s][t][1] = (unsigned char)(g * 255);
|
||||
env_map[s][t][2] = (unsigned char)(b * 255);
|
||||
env_map[s][t][3] = (unsigned char)(a * 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*****************************************************************/
|
||||
/*****************************************************************/
|
||||
/*****************************************************************/
|
||||
|
||||
void init(void)
|
||||
{
|
||||
glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||
glShadeModel(GL_FLAT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
for(int x=0; x<TEXRES_X; x++)
|
||||
{
|
||||
for(int y=0; y<TEXRES_Y; y++)
|
||||
{
|
||||
env_map[x][y][0] = x; //a few colors
|
||||
env_map[x][y][1] = y;
|
||||
env_map[x][y][2] = 128;
|
||||
env_map[x][y][3] = 128;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************/
|
||||
/*****************************************************************/
|
||||
/*****************************************************************/
|
||||
// x y z ang r g b a
|
||||
setColor(0.0, 0.0, -1.0 , 23.0, 1.0, 1.0, 1.0, 1.0);
|
||||
setColor(0.7071067, 0.0, -0.7071067, 23.0, 1.0, 0.0, 0.0, 1.0);
|
||||
/*****************************************************************/
|
||||
/*****************************************************************/
|
||||
/*****************************************************************/
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glGenTextures(1, &texName);
|
||||
glBindTexture(GL_TEXTURE_2D, texName);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXRES_X, TEXRES_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, env_map);
|
||||
}
|
||||
|
||||
void reshape(int w, int h)
|
||||
{
|
||||
window_x = w; window_y = h;
|
||||
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluPerspective((GLdouble) 60.0, ((GLdouble)w)/((GLdouble)h), (GLdouble) 10.0, (GLdouble) 1000.0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0, 0.0, -20.0);
|
||||
}
|
||||
|
||||
void display()
|
||||
{
|
||||
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
|
||||
|
||||
//show light
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluPerspective((GLdouble) 60.0, (float)window_x/window_y, (GLdouble) 1.0, (GLdouble) 100.0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glTranslatef(0.0, 0.0, -10.0);
|
||||
|
||||
glRotatef(alpha, 1.0, 0.0, 0.0);
|
||||
glRotatef(beta, 0.0, 1.0, 0.0);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
glVertex3f(0.0, 0.0, 0.0);
|
||||
glVertex3f(0.0, 0.0, 1.0);
|
||||
glEnd();
|
||||
|
||||
/*****************************************************************/
|
||||
/*****************************************************************/
|
||||
/*****************************************************************/
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
glBindTexture(GL_TEXTURE_2D, texName);
|
||||
|
||||
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
|
||||
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
|
||||
glEnable(GL_TEXTURE_GEN_S);
|
||||
glEnable(GL_TEXTURE_GEN_T);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glNormal3f(0.0, 0.0, 1.0);
|
||||
glVertex3f(1.0, 1.0, 0.0);
|
||||
glVertex3f(-1.0, 1.0, 0.0);
|
||||
glVertex3f(-1.0, -1.0, 0.0);
|
||||
glVertex3f(1.0, -1.0, 0.0);
|
||||
glEnd();
|
||||
|
||||
/*
|
||||
glPointSize(48.0);
|
||||
glBegin(GL_POINTS);
|
||||
glNormal3f(0.0, 0.0, 1.0);
|
||||
glVertex3f(0.0, 0.0, 0.0);
|
||||
glEnd();
|
||||
*/
|
||||
|
||||
glDisable(GL_TEXTURE_GEN_S);
|
||||
glDisable(GL_TEXTURE_GEN_T);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
/*****************************************************************/
|
||||
/*****************************************************************/
|
||||
/*****************************************************************/
|
||||
|
||||
//show how the map looks like
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
//gluOrtho2D(0.0 -10.0, 1.0 +10.0, -(float)window_x/window_y -10.0,0.0 +10.0);
|
||||
//glOrtho(0.0, 5.0, -5.0, 0.0, -10.0, 10.0);
|
||||
glOrtho(0.0, 5.0*((float)window_x/window_y), -5.0, 0.0, -10.0, 10.0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
glBindTexture(GL_TEXTURE_2D, texName);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0, 0.0); glVertex3f(0.0, 0.0, 0.0);
|
||||
glTexCoord2f(0.0, 1.0); glVertex3f(0.0, -1.0, 0.0);
|
||||
glTexCoord2f(1.0, 1.0); glVertex3f(1.0, -1.0, 0.0);
|
||||
glTexCoord2f(1.0, 0.0); glVertex3f(1.0, 0.0, 0.0);
|
||||
glEnd();
|
||||
glFlush();
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glutPostRedisplay () ;
|
||||
glutSwapBuffers () ;
|
||||
}
|
||||
|
||||
void keyboard (unsigned char key, int x, int y)
|
||||
{
|
||||
switch(key)
|
||||
{
|
||||
case 27:
|
||||
exit(0);
|
||||
|
||||
case '8':
|
||||
alpha += 1.0;
|
||||
if (alpha >= 360.0) alpha -= 360.0;
|
||||
break;
|
||||
|
||||
case '2':
|
||||
alpha -= 1.0;
|
||||
if (alpha < 0.0) alpha += 360.0;
|
||||
break;
|
||||
|
||||
case '4':
|
||||
beta -= 1.0;
|
||||
if (beta <= -90.0) beta = -90.0;
|
||||
break;
|
||||
|
||||
case '6':
|
||||
beta += 1.0;
|
||||
if (beta >= 90.0) beta = 90.0;
|
||||
break;
|
||||
|
||||
case '5':
|
||||
alpha = 0.0; beta = 0.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_GLUT_H */
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
#ifdef HAVE_GLUT_H
|
||||
glutInitWindowSize(window_x, window_y);
|
||||
glutInit(&argc, argv);
|
||||
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
|
||||
glutCreateWindow(argv[0]);
|
||||
init();
|
||||
glutDisplayFunc(display);
|
||||
glutReshapeFunc(reshape);
|
||||
glutKeyboardFunc(keyboard);
|
||||
|
||||
glutMainLoop();
|
||||
#else
|
||||
|
||||
printf("GL Utility Toolkit (glut) was not found on this system.\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
18
test_suite/attic/test-gethostname.cxx
Normal file
18
test_suite/attic/test-gethostname.cxx
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if defined( unix ) || defined( __CYGWIN__ )
|
||||
# include <unistd.h> // for gethostname()
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
#if defined( unix ) || defined( __CYGWIN__ )
|
||||
char name[256];
|
||||
gethostname( name, 256 );
|
||||
printf("hostname = %s\n", name);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
116
test_suite/attic/test-text.cxx
Normal file
116
test_suite/attic/test-text.cxx
Normal file
@@ -0,0 +1,116 @@
|
||||
// do some non-destructive read tests relating text files
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static void readchars( FILE *fd ) {
|
||||
int c;
|
||||
while ( (c = fgetc(fd)) != EOF ) {
|
||||
printf("c = %d", c);
|
||||
if ( c == 10 ) {
|
||||
printf(" LF \\n");
|
||||
}
|
||||
if ( c == 13 ) {
|
||||
printf(" CR \\r");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void readlines( FILE *fd ) {
|
||||
char line[256];
|
||||
while ( fgets(line, 255, fd) != NULL ) {
|
||||
int len = strlen(line);
|
||||
printf("line = %s", line);
|
||||
if ( len >= 2 ) {
|
||||
printf(" char[n - 1] = %d char[n] = %d\n",
|
||||
line[len-2], line[len-1]);
|
||||
} else if ( len >= 1 ) {
|
||||
printf(" char[n] = %d\n",line[len-1]);
|
||||
} else {
|
||||
printf("empty string\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char **argv ) {
|
||||
// check usage
|
||||
if ( argc != 2 ) {
|
||||
printf("usage: %s file\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char file[256];
|
||||
strcpy( file, argv[1] );
|
||||
FILE *fd;
|
||||
|
||||
// open a file in (default) text mode
|
||||
printf("TEXT MODE (DEFAULT) by character\n\n");
|
||||
fd = fopen( file, "r" );
|
||||
if ( fd != NULL ) {
|
||||
readchars( fd );
|
||||
fclose(fd);
|
||||
} else {
|
||||
printf("Cannot open %s\n", file);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// open a file in (explicit) text mode
|
||||
printf("TEXT MODE (EXPLICIT) by character\n\n");
|
||||
fd = fopen( file, "rt" );
|
||||
if ( fd != NULL ) {
|
||||
readchars( fd );
|
||||
fclose(fd);
|
||||
} else {
|
||||
printf("Cannot open %s\n", file);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// open a file in (explicit) binary mode
|
||||
printf("BINARY MODE (EXPLICIT) by character\n\n");
|
||||
fd = fopen( file, "rb" );
|
||||
if ( fd != NULL ) {
|
||||
readchars( fd );
|
||||
fclose(fd);
|
||||
} else {
|
||||
printf("Cannot open %s\n", file);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// open a file in (default) text mode
|
||||
printf("TEXT MODE (DEFAULT) by line\n\n");
|
||||
fd = fopen( file, "r" );
|
||||
if ( fd != NULL ) {
|
||||
readlines( fd );
|
||||
fclose(fd);
|
||||
} else {
|
||||
printf("Cannot open %s\n", file);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// open a file in (explicit) text mode
|
||||
printf("TEXT MODE (EXPLICIT) by line\n\n");
|
||||
fd = fopen( file, "rt" );
|
||||
if ( fd != NULL ) {
|
||||
readlines( fd );
|
||||
fclose(fd);
|
||||
} else {
|
||||
printf("Cannot open %s\n", file);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// open a file in (explicit) binary mode
|
||||
printf("BINARY MODE (EXPLICIT) by line\n\n");
|
||||
fd = fopen( file, "rb" );
|
||||
if ( fd != NULL ) {
|
||||
readlines( fd );
|
||||
fclose(fd);
|
||||
} else {
|
||||
printf("Cannot open %s\n", file);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
26
test_suite/bootstrap.cxx
Normal file
26
test_suite/bootstrap.cxx
Normal file
@@ -0,0 +1,26 @@
|
||||
// bootstrap.cxx -- replacement bootstrap routines for the test suite.
|
||||
//
|
||||
// Written by Edward d'Auvergne, started May 2017.
|
||||
//
|
||||
// Copyright (C) 2017 Edward d'Auvergne
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
#include <iostream>
|
||||
|
||||
int _bootstrap_OSInit;
|
||||
std::string hostname;
|
||||
135
test_suite/dataStore.cxx
Normal file
135
test_suite/dataStore.cxx
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (C) 2018 James Turner
|
||||
* Copyright (C) 2018 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <simgear/misc/strutils.hxx>
|
||||
|
||||
#include <Main/fg_init.hxx>
|
||||
|
||||
|
||||
#include "dataStore.hxx"
|
||||
|
||||
|
||||
// Sanity check.
|
||||
bool looksLikeFGData(const SGPath& path)
|
||||
{
|
||||
return (path / "defaults.xml").exists();
|
||||
}
|
||||
|
||||
|
||||
// Set up the path to FGData.
|
||||
int DataStore::findFGRoot(const std::string& fgRootCmdLineOpt, bool debug)
|
||||
{
|
||||
SGPath fgRoot;
|
||||
|
||||
// Command line supplied path.
|
||||
if (!fgRootCmdLineOpt.empty()) {
|
||||
fgRoot = SGPath::fromUtf8(fgRootCmdLineOpt);
|
||||
if (looksLikeFGData(fgRoot)) {
|
||||
if (debug)
|
||||
std::cerr << "FGdata from the command line: " << fgRoot << std::endl;
|
||||
_fgRootPath = fgRoot;
|
||||
return 0;
|
||||
|
||||
// Fail if an invalid path is supplied.
|
||||
} else {
|
||||
std::cerr << "The supplied path \"" << fgRootCmdLineOpt << "\" is not a valid FGData path." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// The FG_DATA_DIR CMake option.
|
||||
fgRoot = SGPath::fromUtf8(PKGLIBDIR);
|
||||
if (looksLikeFGData(fgRoot)) {
|
||||
if (debug)
|
||||
std::cerr << "FGdata found via $PKGLIBDIR: " << fgRoot << std::endl;
|
||||
_fgRootPath = fgRoot;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The FG_ROOT environmental variable.
|
||||
if (std::getenv("FG_ROOT")) {
|
||||
fgRoot = SGPath::fromEnv("FG_ROOT");
|
||||
if (looksLikeFGData(fgRoot)) {
|
||||
if (debug)
|
||||
std::cerr << "FGdata found via $FG_ROOT: " << fgRoot << std::endl;
|
||||
_fgRootPath = fgRoot;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Try in ../fgdata.
|
||||
fgRoot = SGPath::fromUtf8(FGSRCDIR) / ".." / "fgdata";
|
||||
if (looksLikeFGData(fgRoot)) {
|
||||
if (debug)
|
||||
std::cerr << "FGdata found at \"$FGSRCDIR/../fgdata\": " << fgRoot << std::endl;
|
||||
_fgRootPath = fgRoot;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Try in ../data.
|
||||
fgRoot = SGPath::fromUtf8(FGSRCDIR) / ".." / "data";
|
||||
if (looksLikeFGData(fgRoot)) {
|
||||
if (debug)
|
||||
std::cerr << "FGdata found at \"$FGSRCDIR/../data\": " << std::endl;
|
||||
_fgRootPath = fgRoot;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// No FGData.
|
||||
std::cerr << "FGData not found." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get the path to FGData.
|
||||
SGPath DataStore::getFGRoot()
|
||||
{
|
||||
return _fgRootPath;
|
||||
}
|
||||
|
||||
// Perform a version validation of FGData, returning zero if ok.
|
||||
int DataStore::validateFGRoot()
|
||||
{
|
||||
// The FGData version.
|
||||
SGPath root = getFGRoot();
|
||||
std::string base_version = fgBasePackageVersion(root);
|
||||
if (base_version.empty()) {
|
||||
std::cout << "Base package not found." << std::endl;
|
||||
std::cout << "Required FGData files not found, please check your configuration." << std::endl;
|
||||
std::cout << "Looking for FGData files in '" << root.str() << "'." << std::endl;
|
||||
std::cout.flush();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Comparison of only the major and minor version numbers.
|
||||
const int versionComp = simgear::strutils::compare_versions(FLIGHTGEAR_VERSION, base_version, 2);
|
||||
if (versionComp != 0) {
|
||||
std::cout << "Base package version mismatch." << std::endl;
|
||||
std::cout << "Version check failed, please check your configuration." << std::endl;
|
||||
std::cout << "The FGData version '" << base_version << "' in '" << root.str();
|
||||
std::cout << "does not match the FlightGear version '" << std::string(FLIGHTGEAR_VERSION);
|
||||
std::cout << "'." << std::endl;
|
||||
std::cout.flush();
|
||||
}
|
||||
return versionComp;
|
||||
}
|
||||
54
test_suite/dataStore.hxx
Normal file
54
test_suite/dataStore.hxx
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _FG_TEST_SUITE_DATA_STORE_HXX
|
||||
#define _FG_TEST_SUITE_DATA_STORE_HXX
|
||||
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
|
||||
// The data store singleton.
|
||||
class DataStore
|
||||
{
|
||||
public:
|
||||
// Return the singleton, instantiating it if required.
|
||||
static DataStore& get()
|
||||
{
|
||||
static DataStore instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
// Function deletion to allow the class to be a singleton.
|
||||
DataStore(DataStore const&) = delete;
|
||||
void operator=(DataStore const&) = delete;
|
||||
|
||||
// FGData path functions.
|
||||
int findFGRoot(const std::string& fgRootCmdLineOpt, bool debug = false);
|
||||
SGPath getFGRoot();
|
||||
int validateFGRoot();
|
||||
|
||||
private:
|
||||
DataStore() = default;
|
||||
|
||||
// The path to FGData.
|
||||
SGPath _fgRootPath;
|
||||
};
|
||||
|
||||
|
||||
#endif // _FG_TEST_SUITE_DATA_STORE_HXX
|
||||
167
test_suite/fgCompilerOutputter.cxx
Normal file
167
test_suite/fgCompilerOutputter.cxx
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
|
||||
#include <cppunit/SourceLine.h>
|
||||
#include <cppunit/TestResultCollector.h>
|
||||
|
||||
#include "fgCompilerOutputter.hxx"
|
||||
#include "formatting.hxx"
|
||||
#include "logging.hxx"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
// Create a new class instance.
|
||||
fgCompilerOutputter * fgCompilerOutputter::defaultOutputter(CppUnit::TestResultCollector *result, vector<TestIOCapt> *capt, const clock_t *clock, CppUnit::OStream &stream)
|
||||
{
|
||||
return new fgCompilerOutputter(result, capt, clock, stream);
|
||||
}
|
||||
|
||||
|
||||
// Printout for each failed test.
|
||||
void fgCompilerOutputter::printFailureDetail(CppUnit::TestFailure *failure)
|
||||
{
|
||||
// Declarations.
|
||||
TestIOCapt test_io;
|
||||
vector<TestIOCapt>::iterator test_iter;
|
||||
|
||||
// Initial separator.
|
||||
#ifdef _WIN32
|
||||
fg_stream << endl;
|
||||
#endif
|
||||
fg_stream << string(WIDTH_DIVIDER, '=') << endl;
|
||||
|
||||
// Test info.
|
||||
fg_stream << (failure->isError() ? "ERROR: " : "FAIL: ") << failure->failedTestName() << endl;
|
||||
fg_stream << string(WIDTH_DIVIDER, '-') << endl;
|
||||
fg_stream << (failure->isError() ? "Error" : "Assertion") << ": ";
|
||||
printFailureLocation(failure->sourceLine());
|
||||
printFailureMessage(failure);
|
||||
fg_stream.flush();
|
||||
|
||||
if (debug)
|
||||
return;
|
||||
|
||||
// The captured IO for this test.
|
||||
test_iter = find_if(io_capt->begin(), io_capt->end(), matchTestName(failure->failedTestName()));
|
||||
if (test_iter != io_capt->end())
|
||||
test_io = *test_iter;
|
||||
|
||||
// SG_LOG IO streams.
|
||||
if (!test_io.sg_interleaved.empty())
|
||||
fgCompilerOutputter::printIOStreamMessages("SG_LOG, "+test_io.log_class+" class, "+test_io.log_priority+" priority", test_io.sg_interleaved, true);
|
||||
if (!test_io.sg_bulk_only.empty())
|
||||
fgCompilerOutputter::printIOStreamMessages("SG_LOG, "+test_io.log_class+" class, SG_BULK only priority", test_io.sg_bulk_only);
|
||||
if (!test_io.sg_debug_only.empty())
|
||||
fgCompilerOutputter::printIOStreamMessages("SG_LOG, "+test_io.log_class+" class, SG_DEBUG only priority", test_io.sg_debug_only);
|
||||
if (!test_io.sg_info_only.empty())
|
||||
fgCompilerOutputter::printIOStreamMessages("SG_LOG, "+test_io.log_class+" class, SG_INFO only priority", test_io.sg_info_only);
|
||||
if (!test_io.sg_warn_only.empty())
|
||||
fgCompilerOutputter::printIOStreamMessages("SG_LOG, "+test_io.log_class+" class, SG_WARN only priority", test_io.sg_warn_only);
|
||||
if (!test_io.sg_alert_only.empty())
|
||||
fgCompilerOutputter::printIOStreamMessages("SG_LOG, "+test_io.log_class+" class, SG_ALERT only priority", test_io.sg_alert_only);
|
||||
|
||||
// Default IO streams.
|
||||
fgCompilerOutputter::printIOStreamMessages("STDOUT and STDERR", test_io.stdio);
|
||||
}
|
||||
|
||||
|
||||
// Detailed printout after a failed run of the test suite.
|
||||
void fgCompilerOutputter::printFailureReport()
|
||||
{
|
||||
// Custom printouts for each failed test.
|
||||
printFailuresList();
|
||||
|
||||
// CTest output (nothing).
|
||||
if (ctest_output)
|
||||
return;
|
||||
|
||||
// A summary with timing info.
|
||||
printSuiteStats();
|
||||
|
||||
// Final summary.
|
||||
fg_stream << endl << "[ FAILED ]" << endl << endl;
|
||||
fg_stream.flush();
|
||||
}
|
||||
|
||||
|
||||
void fgCompilerOutputter::printIOStreamMessages(string heading, string messages, bool empty)
|
||||
{
|
||||
// Silence.
|
||||
if (!empty && messages.size() == 0)
|
||||
return;
|
||||
|
||||
// Divider.
|
||||
fg_stream << string(WIDTH_DIVIDER, '-') << endl;
|
||||
|
||||
// Heading.
|
||||
fg_stream << "# " << heading << endl << endl;
|
||||
|
||||
// Nothing to do
|
||||
if (messages.size() == 0)
|
||||
fg_stream << "(empty)" << endl << endl;
|
||||
|
||||
// The IO stream contents.
|
||||
else
|
||||
fg_stream << messages << endl;
|
||||
}
|
||||
|
||||
|
||||
// Printout of the test suite stats.
|
||||
void fgCompilerOutputter::printSuiteStats()
|
||||
{
|
||||
// A divider.
|
||||
#ifdef _WIN32
|
||||
fg_stream << endl;
|
||||
#endif
|
||||
fg_stream << string(WIDTH_DIVIDER, '-') << endl;
|
||||
|
||||
// Timing and test count line.
|
||||
fg_stream << "Ran " << fg_result->runTests() << " tests";
|
||||
streamsize prec = fg_stream.precision();
|
||||
fg_stream << setprecision(3);
|
||||
fg_stream << " in " << ((double)*suite_timer)/CLOCKS_PER_SEC << " seconds." << endl;
|
||||
fg_stream << setprecision(prec);
|
||||
|
||||
// Failure line.
|
||||
if (!fg_result->wasSuccessful()) {
|
||||
fg_stream << endl << "Failures = " << fg_result->testFailures() << endl;
|
||||
fg_stream << "Errors = " << fg_result->testErrors() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Print a summary after a successful run of the test suite.
|
||||
void fgCompilerOutputter::printSuccess()
|
||||
{
|
||||
// CTest output (nothing).
|
||||
if (ctest_output)
|
||||
return;
|
||||
|
||||
// A summary with timing info.
|
||||
printSuiteStats();
|
||||
|
||||
// Final summary.
|
||||
fg_stream << endl << "[ OK ]" << endl << endl;
|
||||
fg_stream.flush();
|
||||
}
|
||||
89
test_suite/fgCompilerOutputter.hxx
Normal file
89
test_suite/fgCompilerOutputter.hxx
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _FG_COMPILER_OUTPUTTER_HXX
|
||||
#define _FG_COMPILER_OUTPUTTER_HXX
|
||||
|
||||
|
||||
#include <cppunit/CompilerOutputter.h>
|
||||
#include <cppunit/TestFailure.h>
|
||||
|
||||
#include "fgTestListener.hxx"
|
||||
|
||||
|
||||
// The custom outputter for the FlightGear test suite.
|
||||
class fgCompilerOutputter : public CppUnit::CompilerOutputter
|
||||
{
|
||||
public:
|
||||
// Constructor.
|
||||
fgCompilerOutputter(CppUnit::TestResultCollector *result,
|
||||
std::vector<TestIOCapt> *capt,
|
||||
const clock_t *clock,
|
||||
CppUnit::OStream &stream,
|
||||
bool ctest = false,
|
||||
bool debug = false,
|
||||
const std::string &locationFormat = CPPUNIT_COMPILER_LOCATION_FORMAT)
|
||||
: CppUnit::CompilerOutputter(result, stream, locationFormat)
|
||||
, io_capt(capt)
|
||||
, fg_result(result)
|
||||
, fg_stream(stream)
|
||||
, suite_timer(clock)
|
||||
, ctest_output(ctest)
|
||||
, debug(debug)
|
||||
{
|
||||
}
|
||||
|
||||
// Create a new class instance.
|
||||
static fgCompilerOutputter *defaultOutputter(CppUnit::TestResultCollector *result, std::vector<TestIOCapt> *capt, const clock_t *clock, CppUnit::OStream &stream);
|
||||
|
||||
// Print a summary after a successful run of the test suite.
|
||||
void printSuccess();
|
||||
|
||||
// Detailed printout after a failed run of the test suite.
|
||||
void printFailureReport();
|
||||
|
||||
// Printout for each failed test.
|
||||
void printFailureDetail(CppUnit::TestFailure *failure);
|
||||
|
||||
// Printout of the test suite stats.
|
||||
void printSuiteStats();
|
||||
|
||||
// The captured IO for each failed test.
|
||||
std::vector<TestIOCapt> *io_capt;
|
||||
|
||||
private:
|
||||
// Store copies of the base class objects.
|
||||
CppUnit::TestResultCollector *fg_result;
|
||||
CppUnit::OStream &fg_stream;
|
||||
|
||||
// The test suite time, in clock ticks.
|
||||
const clock_t *suite_timer;
|
||||
|
||||
// Output control.
|
||||
bool ctest_output;
|
||||
bool debug;
|
||||
|
||||
// Simgear logstream IO printout.
|
||||
void printIOStreamMessages(std::string heading, std::string messages, bool empty);
|
||||
void printIOStreamMessages(std::string heading, std::string messages) {printIOStreamMessages(heading, messages, false);}
|
||||
};
|
||||
|
||||
|
||||
#endif // _FG_COMPILER_OUTPUTTER_HXX
|
||||
138
test_suite/fgTestListener.cxx
Normal file
138
test_suite/fgTestListener.cxx
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <cppunit/Test.h>
|
||||
#include <cppunit/TestFailure.h>
|
||||
#include <cppunit/TestListener.h>
|
||||
|
||||
#include "fgTestListener.hxx"
|
||||
#include "logging.hxx"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
// Handle failures.
|
||||
void fgTestListener::addFailure(const CppUnit::TestFailure &failure)
|
||||
{
|
||||
m_failure = true;
|
||||
if (failure.isError())
|
||||
m_error = true;
|
||||
}
|
||||
|
||||
|
||||
// Override the base class function to restore IO streams.
|
||||
void fgTestListener::endTest(CppUnit::Test *test)
|
||||
{
|
||||
// Test timing.
|
||||
sum_time += clock() - m_time;
|
||||
|
||||
// Restore the IO streams.
|
||||
if (!debug) {
|
||||
cout.rdbuf(orig_cout);
|
||||
cerr.rdbuf(orig_cerr);
|
||||
}
|
||||
|
||||
// Debugging output.
|
||||
if (debug)
|
||||
cerr << string(WIDTH_DIVIDER, '-') << endl;
|
||||
|
||||
// Per-test single character status feedback.
|
||||
if (m_failure)
|
||||
cerr << (m_error ? "E" : "F");
|
||||
else
|
||||
cerr << '.';
|
||||
|
||||
// Timing output.
|
||||
if (timings || ctest_output || debug) {
|
||||
// Test timing.
|
||||
float time = ((float)(clock()-m_time))/CLOCKS_PER_SEC;
|
||||
char buffer[100];
|
||||
if (time > 60.0)
|
||||
snprintf(buffer, sizeof(buffer), "%10.3f %-3s", time/60, "min");
|
||||
else if (time > 1.0)
|
||||
snprintf(buffer, sizeof(buffer), "%10.3f %-3s", time, "s");
|
||||
else
|
||||
snprintf(buffer, sizeof(buffer), "%10.3f %-3s", time*1000, "ms");
|
||||
cerr << buffer;
|
||||
|
||||
// Test name.
|
||||
cerr << " for " << test->getName() << endl;
|
||||
}
|
||||
cerr.flush();
|
||||
|
||||
// Store the captured IO for any failed tests.
|
||||
if (m_failure && !debug) {
|
||||
// Set up the data structure.
|
||||
TestIOCapt test_io;
|
||||
test_io.name = test->getName();
|
||||
|
||||
// Standard IO.
|
||||
test_io.stdio = capt.str();
|
||||
|
||||
// The simgear logstreams.
|
||||
capturedIO &obj = getIOstreams();
|
||||
test_io.log_class = obj.log_class;
|
||||
test_io.log_priority = obj.log_priority;
|
||||
test_io.sg_interleaved = obj.sg_interleaved.str();
|
||||
test_io.sg_bulk_only = obj.sg_bulk_only.str();
|
||||
test_io.sg_debug_only = obj.sg_debug_only.str();
|
||||
test_io.sg_info_only = obj.sg_info_only.str();
|
||||
test_io.sg_warn_only = obj.sg_warn_only.str();
|
||||
test_io.sg_alert_only = obj.sg_alert_only.str();
|
||||
|
||||
// Add the test's IO to the list.
|
||||
io_capt.push_back(test_io);
|
||||
}
|
||||
}
|
||||
|
||||
// Override the base class function to capture IO streams.
|
||||
void fgTestListener::startTest(CppUnit::Test *test)
|
||||
{
|
||||
// IO capture.
|
||||
if (!debug) {
|
||||
// Clear the simgear logstream buffers.
|
||||
capturedIO &obj = getIOstreams();
|
||||
obj.sg_interleaved.str("");
|
||||
obj.sg_bulk_only.str("");
|
||||
obj.sg_debug_only.str("");
|
||||
obj.sg_info_only.str("");
|
||||
obj.sg_warn_only.str("");
|
||||
obj.sg_alert_only.str("");
|
||||
|
||||
// Store the original STDOUT and STDERR for restoring later on.
|
||||
orig_cout = cout.rdbuf();
|
||||
orig_cerr = cerr.rdbuf();
|
||||
|
||||
// Clear the captured stream and then catch stdout and stderr.
|
||||
capt.str(string());
|
||||
cout.rdbuf(capt.rdbuf());
|
||||
cerr.rdbuf(capt.rdbuf());
|
||||
|
||||
// Debugging output.
|
||||
} else {
|
||||
cerr << string(WIDTH_DIVIDER, '=') << endl;
|
||||
cerr << "Starting test: " << test->getName() << endl;
|
||||
cerr << string(WIDTH_DIVIDER, '-') << endl;
|
||||
}
|
||||
// Reset the test status.
|
||||
m_failure = false;
|
||||
m_error = false;
|
||||
m_time = clock();
|
||||
}
|
||||
103
test_suite/fgTestListener.hxx
Normal file
103
test_suite/fgTestListener.hxx
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _FG_TEST_LISTENER_HXX
|
||||
#define _FG_TEST_LISTENER_HXX
|
||||
|
||||
|
||||
#include <time.h>
|
||||
#include <vector>
|
||||
|
||||
#include "formatting.hxx"
|
||||
|
||||
|
||||
// Data structure for holding the captured IO for a failed test.
|
||||
struct TestIOCapt {
|
||||
std::string name;
|
||||
std::string log_class;
|
||||
std::string log_priority;
|
||||
std::string stdio;
|
||||
std::string sg_interleaved;
|
||||
std::string sg_bulk_only;
|
||||
std::string sg_debug_only;
|
||||
std::string sg_info_only;
|
||||
std::string sg_warn_only;
|
||||
std::string sg_alert_only;
|
||||
};
|
||||
|
||||
|
||||
// Match the test by name for std:find using a vector<TestIOCapt>.
|
||||
class matchTestName
|
||||
{
|
||||
std::string _name;
|
||||
|
||||
public:
|
||||
matchTestName(const std::string &name) : _name(name) {}
|
||||
|
||||
bool operator()(const TestIOCapt &item) const {
|
||||
return item.name == _name;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// The custom test runner for the FlightGear test suite.
|
||||
class fgTestListener : public CppUnit::TestListener
|
||||
{
|
||||
protected:
|
||||
// Failure state.
|
||||
bool m_failure, m_error;
|
||||
|
||||
public:
|
||||
// Constructor.
|
||||
fgTestListener(): m_failure(false), m_error(false), sum_time(0) { };
|
||||
|
||||
// Override the base class function to capture IO. streams
|
||||
void startTest(CppUnit::Test *test);
|
||||
|
||||
// Override the base class function to restore IO streams.
|
||||
void endTest(CppUnit::Test *test);
|
||||
|
||||
// Handle failures.
|
||||
void addFailure(const CppUnit::TestFailure &failure);
|
||||
|
||||
// Test suite timing.
|
||||
clock_t sum_time;
|
||||
|
||||
// IO capture for all failed tests.
|
||||
std::vector<TestIOCapt> io_capt;
|
||||
|
||||
// Output settings.
|
||||
bool timings;
|
||||
bool ctest_output;
|
||||
bool debug;
|
||||
|
||||
protected:
|
||||
// The original IO streams.
|
||||
std::streambuf *orig_cerr, *orig_cout;
|
||||
|
||||
// Captured IO streams.
|
||||
std::stringstream capt;
|
||||
|
||||
// Test timings.
|
||||
clock_t m_time;
|
||||
};
|
||||
|
||||
|
||||
#endif // _FG_TEST_LISTENER_HXX
|
||||
73
test_suite/fgTestRunner.cxx
Normal file
73
test_suite/fgTestRunner.cxx
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2018 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <cppunit/TestResult.h>
|
||||
#include <cppunit/TestResultCollector.h>
|
||||
#include <cppunit/TextTestRunner.h>
|
||||
#include <cppunit/extensions/TestFactoryRegistry.h>
|
||||
|
||||
#include "fgCompilerOutputter.hxx"
|
||||
#include "fgTestListener.hxx"
|
||||
#include "formatting.hxx"
|
||||
|
||||
|
||||
// Execute all test suites for the given test category.
|
||||
int testRunner(const std::string& type, const std::string& title, char *subset, bool timings, bool ctest_output, bool debug)
|
||||
{
|
||||
// Declarations.
|
||||
CppUnit::TextTestRunner runner;
|
||||
|
||||
// Print out a title.
|
||||
if (!ctest_output)
|
||||
printTitle(std::cerr, title);
|
||||
|
||||
// Get all tests.
|
||||
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry(type).makeTest());
|
||||
|
||||
// Set up the test listener.
|
||||
fgTestListener *testListener;
|
||||
testListener = new fgTestListener;
|
||||
runner.eventManager().addListener(testListener);
|
||||
testListener->timings = timings;
|
||||
testListener->ctest_output = ctest_output;
|
||||
testListener->debug = debug;
|
||||
|
||||
// Set the test suite output IO stream.
|
||||
runner.setOutputter(new fgCompilerOutputter(&runner.result(), &testListener->io_capt, &testListener->sum_time, std::cerr, ctest_output, debug));
|
||||
|
||||
// Execute the tests.
|
||||
if (subset == NULL)
|
||||
runner.run("", false, true, false);
|
||||
else {
|
||||
std::stringstream testStream(subset);
|
||||
std::string testName;
|
||||
while( testStream.good() ) {
|
||||
getline( testStream, testName, ',' );
|
||||
runner.run(testName, false, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up.
|
||||
delete testListener;
|
||||
|
||||
// Return the status of the tests.
|
||||
CppUnit::TestResultCollector &status = runner.result();
|
||||
return status.testFailuresTotal();
|
||||
}
|
||||
29
test_suite/fgTestRunner.hxx
Normal file
29
test_suite/fgTestRunner.hxx
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2018 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _FG_TEST_RUNNER_HXX
|
||||
#define _FG_TEST_RUNNER_HXX
|
||||
|
||||
|
||||
// Execute all test suites for the given test category.
|
||||
int testRunner(const std::string&, const std::string&, char*, bool, bool, bool);
|
||||
|
||||
|
||||
#endif // _FG_TEST_RUNNER_HXX
|
||||
19
test_suite/fgdata_tests/CMakeLists.txt
Normal file
19
test_suite/fgdata_tests/CMakeLists.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
# Add each simgear test category.
|
||||
foreach( simgear_test_category
|
||||
)
|
||||
|
||||
add_subdirectory(${simgear_test_category})
|
||||
|
||||
endforeach( simgear_test_category )
|
||||
|
||||
|
||||
set(TESTSUITE_SOURCES
|
||||
${TESTSUITE_SOURCES}
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
|
||||
set(TESTSUITE_HEADERS
|
||||
${TESTSUITE_HEADERS}
|
||||
PARENT_SCOPE
|
||||
)
|
||||
82
test_suite/formatting.cxx
Normal file
82
test_suite/formatting.cxx
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "formatting.hxx"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
// Printout of a section label.
|
||||
void printSection(CppUnit::OStream &stream, const string &text)
|
||||
{
|
||||
// Declarations.
|
||||
string::size_type width = text.size();
|
||||
|
||||
// Format the text.
|
||||
stream << endl;
|
||||
stream << text << endl;
|
||||
stream << string(width, '=') << endl << endl;
|
||||
}
|
||||
|
||||
|
||||
// Print a summary line.
|
||||
void printSummaryLine(CppUnit::OStream &stream, const string &name, int passed)
|
||||
{
|
||||
// Declarations.
|
||||
int n;
|
||||
string dots, state;
|
||||
|
||||
// Passed.
|
||||
if (!passed)
|
||||
state = "OK";
|
||||
|
||||
// Skipped.
|
||||
else if (passed == -1)
|
||||
state = "Skipped";
|
||||
|
||||
// Failed.
|
||||
else
|
||||
state = "Failed";
|
||||
|
||||
// Dots.
|
||||
n = WIDTH_DIVIDER - name.size() - state.size() - 6;
|
||||
dots = string(n, '.');
|
||||
|
||||
// Write out the line.
|
||||
stream << name;
|
||||
stream << " " << dots << " ";
|
||||
stream << "[ " << state << " ]" << endl;
|
||||
}
|
||||
|
||||
|
||||
// Printout of a title label.
|
||||
void printTitle(CppUnit::OStream &stream, const string &text)
|
||||
{
|
||||
// Declarations.
|
||||
string::size_type width = text.size() + 4;
|
||||
|
||||
// Format the text.
|
||||
stream << endl << endl;
|
||||
stream << string(width, '=') << endl;
|
||||
stream << "= " << text << " =" << endl;
|
||||
stream << string(width, '=') << endl << endl;
|
||||
}
|
||||
40
test_suite/formatting.hxx
Normal file
40
test_suite/formatting.hxx
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2018 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _FG_TEST_SUITE_FORMATTING_HXX
|
||||
#define _FG_TEST_SUITE_FORMATTING_HXX
|
||||
|
||||
#include <cppunit/portability/Stream.h>
|
||||
|
||||
|
||||
// Divider width.
|
||||
const int WIDTH_DIVIDER = 70;
|
||||
|
||||
// Printout of a section label.
|
||||
void printSection(CppUnit::OStream &stream, const std::string &text);
|
||||
|
||||
// Print a summary line.
|
||||
void printSummaryLine(CppUnit::OStream &stream, const std::string &name, int passed);
|
||||
|
||||
// Printout of a title label.
|
||||
void printTitle(CppUnit::OStream &stream, const std::string &text);
|
||||
|
||||
|
||||
#endif // _FG_TEST_SUITE_FORMATTING_HXX
|
||||
19
test_suite/gui_tests/CMakeLists.txt
Normal file
19
test_suite/gui_tests/CMakeLists.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
# Add each GUI test category.
|
||||
foreach( gui_test_category
|
||||
)
|
||||
|
||||
add_subdirectory(${gui_test_category})
|
||||
|
||||
endforeach( gui_test_category )
|
||||
|
||||
|
||||
set(TESTSUITE_SOURCES
|
||||
${TESTSUITE_SOURCES}
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
|
||||
set(TESTSUITE_HEADERS
|
||||
${TESTSUITE_HEADERS}
|
||||
PARENT_SCOPE
|
||||
)
|
||||
148
test_suite/logging.cxx
Normal file
148
test_suite/logging.cxx
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
#include "logging.hxx"
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/debug/OsgIoCapture.hxx>
|
||||
|
||||
|
||||
// The global stream capture data structure.
|
||||
static capturedIO *_iostreams = NULL;
|
||||
|
||||
|
||||
// capturedIO constructor.
|
||||
capturedIO::capturedIO(sgDebugClass c, sgDebugPriority p)
|
||||
{
|
||||
callback_interleaved = new StreamLogCallback(sg_interleaved, c, p, false);
|
||||
callback_bulk_only = new StreamLogCallback(sg_bulk_only, c, SG_BULK, true);
|
||||
callback_debug_only = new StreamLogCallback(sg_debug_only, c, SG_DEBUG, true);
|
||||
callback_info_only = new StreamLogCallback(sg_info_only, c, SG_INFO, true);
|
||||
callback_warn_only = new StreamLogCallback(sg_warn_only, c, SG_WARN, true);
|
||||
callback_alert_only = new StreamLogCallback(sg_alert_only, c, SG_ALERT, true);
|
||||
|
||||
// Store the class as a string.
|
||||
if (c == SG_ALL)
|
||||
log_class = "SG_ALL";
|
||||
else {
|
||||
std::stringstream stream;
|
||||
stream << "0x" << std::right << std::setfill('0') << std::setw(8) << std::hex << c;
|
||||
log_class = stream.str();
|
||||
}
|
||||
|
||||
// Store the priority as a string.
|
||||
if (p == SG_BULK)
|
||||
log_priority = "SG_BULK";
|
||||
else if (p == SG_DEBUG)
|
||||
log_priority = "SG_DEBUG";
|
||||
else if (p == SG_INFO)
|
||||
log_priority = "SG_INFO";
|
||||
else if (p == SG_WARN)
|
||||
log_priority = "SG_WARN";
|
||||
else if (p == SG_ALERT)
|
||||
log_priority = "SG_ALERT";
|
||||
else if (p == SG_POPUP)
|
||||
log_priority = "SG_POPUP";
|
||||
else if (p == SG_DEV_WARN)
|
||||
log_priority = "SG_DEV_WARN";
|
||||
else if (p == SG_DEV_ALERT)
|
||||
log_priority = "SG_DEV_ALERT";
|
||||
}
|
||||
|
||||
// capturedIO destructor.
|
||||
capturedIO::~capturedIO()
|
||||
{
|
||||
// Destroy the callback objects.
|
||||
delete callback_interleaved;
|
||||
delete callback_bulk_only;
|
||||
delete callback_debug_only;
|
||||
delete callback_info_only;
|
||||
delete callback_warn_only;
|
||||
delete callback_alert_only;
|
||||
}
|
||||
|
||||
|
||||
// Return the global stream capture data structure, creating it if needed.
|
||||
capturedIO & getIOstreams(sgDebugClass c, sgDebugPriority p)
|
||||
{
|
||||
// Initialise the global stream capture data structure, if needed.
|
||||
if (!_iostreams)
|
||||
_iostreams = new capturedIO(c, p);
|
||||
|
||||
// Return a pointer to the global object.
|
||||
return *_iostreams;
|
||||
}
|
||||
|
||||
|
||||
// Set up to capture all the simgear logging priorities as separate streams.
|
||||
void setupLogging(sgDebugClass c, sgDebugPriority p, bool split)
|
||||
{
|
||||
// Get the single logstream instance.
|
||||
logstream &log = sglog();
|
||||
|
||||
// Set up the logstream testing mode.
|
||||
log.setTestingMode(true);
|
||||
|
||||
// OSG IO capture.
|
||||
osg::setNotifyHandler(new NotifyLogger);
|
||||
|
||||
// IO capture.
|
||||
capturedIO &obj = getIOstreams(c, p);
|
||||
if (!split)
|
||||
log.addCallback(obj.callback_interleaved);
|
||||
else {
|
||||
if (p <= SG_BULK)
|
||||
log.addCallback(obj.callback_bulk_only);
|
||||
if (p <= SG_DEBUG)
|
||||
log.addCallback(obj.callback_debug_only);
|
||||
if (p <= SG_INFO)
|
||||
log.addCallback(obj.callback_info_only);
|
||||
if (p <= SG_WARN)
|
||||
log.addCallback(obj.callback_warn_only);
|
||||
if (p <= SG_ALERT)
|
||||
log.addCallback(obj.callback_alert_only);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Deactivate all the simgear logging priority IO captures.
|
||||
void stopLogging()
|
||||
{
|
||||
// Get the single logstream instance.
|
||||
logstream &log = sglog();
|
||||
|
||||
// IO decapture.
|
||||
capturedIO &obj = getIOstreams();
|
||||
log.removeCallback(obj.callback_interleaved);
|
||||
log.removeCallback(obj.callback_bulk_only);
|
||||
log.removeCallback(obj.callback_debug_only);
|
||||
log.removeCallback(obj.callback_info_only);
|
||||
log.removeCallback(obj.callback_warn_only);
|
||||
log.removeCallback(obj.callback_alert_only);
|
||||
|
||||
// Clean up the IO stream object.
|
||||
delete _iostreams;
|
||||
_iostreams = NULL;
|
||||
|
||||
// Stop the simgear logstream.
|
||||
simgear::shutdownLogging();
|
||||
}
|
||||
100
test_suite/logging.hxx
Normal file
100
test_suite/logging.hxx
Normal file
@@ -0,0 +1,100 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _FG_TEST_SUITE_LOGGING_HXX
|
||||
#define _FG_TEST_SUITE_LOGGING_HXX
|
||||
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <simgear/debug/LogCallback.hxx>
|
||||
|
||||
|
||||
// A logstream callback based on the simgear FileLogCallback class.
|
||||
class StreamLogCallback : public simgear::LogCallback
|
||||
{
|
||||
public:
|
||||
StreamLogCallback(std::ostringstream& stream, sgDebugClass c, sgDebugPriority p, bool priorityMatch):
|
||||
simgear::LogCallback(c, p),
|
||||
m_priority(p),
|
||||
m_stream(stream),
|
||||
m_priorityMatch(priorityMatch)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void operator()(sgDebugClass c, sgDebugPriority p, const char* file, int line, const std::string& message)
|
||||
{
|
||||
if (m_priorityMatch && p != m_priority) return;
|
||||
if (!shouldLog(c, p)) return;
|
||||
if (m_priorityMatch)
|
||||
m_stream << simgear::LogCallback::debugClassToString(c) << ":" << file << ":" << line << ": " << message << std::endl;
|
||||
else
|
||||
m_stream << simgear::LogCallback::debugClassToString(c) << ":" << (int) p << ":" << file << ":" << line << ": " << message << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
sgDebugPriority m_priority;
|
||||
std::ostringstream &m_stream;
|
||||
bool m_priorityMatch;
|
||||
};
|
||||
|
||||
|
||||
// All of the captured IO streams.
|
||||
class capturedIO
|
||||
{
|
||||
public:
|
||||
// Constructor and destructor.
|
||||
capturedIO(sgDebugClass, sgDebugPriority);
|
||||
~capturedIO();
|
||||
|
||||
// The IO streams.
|
||||
std::ostringstream sg_interleaved;
|
||||
std::ostringstream sg_bulk_only;
|
||||
std::ostringstream sg_debug_only;
|
||||
std::ostringstream sg_info_only;
|
||||
std::ostringstream sg_warn_only;
|
||||
std::ostringstream sg_alert_only;
|
||||
|
||||
// The callback objects.
|
||||
StreamLogCallback *callback_interleaved;
|
||||
StreamLogCallback *callback_bulk_only;
|
||||
StreamLogCallback *callback_debug_only;
|
||||
StreamLogCallback *callback_info_only;
|
||||
StreamLogCallback *callback_warn_only;
|
||||
StreamLogCallback *callback_alert_only;
|
||||
|
||||
// The logging class and priority text.
|
||||
std::string log_class;
|
||||
std::string log_priority;
|
||||
};
|
||||
|
||||
|
||||
// Return the global stream capture data structure, creating it if needed.
|
||||
capturedIO & getIOstreams(sgDebugClass c=SG_ALL, sgDebugPriority p=SG_BULK);
|
||||
|
||||
// Set up to capture all the simgear logging priorities as separate streams.
|
||||
void setupLogging(sgDebugClass, sgDebugPriority, bool);
|
||||
|
||||
// Deactivate all the simgear logging priority IO captures.
|
||||
void stopLogging();
|
||||
|
||||
|
||||
#endif // _FG_TEST_SUITE_LOGGING_HXX
|
||||
23
test_suite/simgear_tests/CMakeLists.txt
Normal file
23
test_suite/simgear_tests/CMakeLists.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
# Add each simgear test category.
|
||||
foreach( simgear_test_category
|
||||
math
|
||||
props
|
||||
canvas
|
||||
structure
|
||||
)
|
||||
|
||||
add_subdirectory(${simgear_test_category})
|
||||
|
||||
endforeach( simgear_test_category )
|
||||
|
||||
|
||||
set(TESTSUITE_SOURCES
|
||||
${TESTSUITE_SOURCES}
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
|
||||
set(TESTSUITE_HEADERS
|
||||
${TESTSUITE_HEADERS}
|
||||
PARENT_SCOPE
|
||||
)
|
||||
12
test_suite/simgear_tests/canvas/CMakeLists.txt
Normal file
12
test_suite/simgear_tests/canvas/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
set(TESTSUITE_SOURCES
|
||||
${TESTSUITE_SOURCES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/testCanvas.cxx
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
set(TESTSUITE_HEADERS
|
||||
${TESTSUITE_HEADERS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/testCanvas.hxx
|
||||
PARENT_SCOPE
|
||||
)
|
||||
24
test_suite/simgear_tests/canvas/TestSuite.cxx
Normal file
24
test_suite/simgear_tests/canvas/TestSuite.cxx
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "testCanvas.hxx"
|
||||
|
||||
|
||||
// Set up the tests.
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(CanvasTests, "Simgear unit tests");
|
||||
123
test_suite/simgear_tests/canvas/testCanvas.cxx
Normal file
123
test_suite/simgear_tests/canvas/testCanvas.cxx
Normal file
@@ -0,0 +1,123 @@
|
||||
#include "testCanvas.hxx"
|
||||
|
||||
#include <simgear/canvas/Canvas.hxx>
|
||||
#include <simgear/canvas/elements/CanvasImage.hxx>
|
||||
|
||||
#include "test_suite/FGTestApi/testGlobals.hxx"
|
||||
|
||||
#include <Main/globals.hxx>
|
||||
#include <Main/fg_commands.hxx>
|
||||
|
||||
#include <Canvas/canvas_mgr.hxx>
|
||||
#include <Canvas/FGCanvasSystemAdapter.hxx>
|
||||
extern bool global_nasalMinimalInit;
|
||||
|
||||
|
||||
void verifyPixel(osg::Image* img, int x, int y, const uint8_t* pixel)
|
||||
{
|
||||
auto rawPixel = img->data(x, y);
|
||||
CPPUNIT_ASSERT(memcmp(rawPixel, pixel, 4) == 0);
|
||||
}
|
||||
|
||||
void CanvasTests::setUp()
|
||||
{
|
||||
global_nasalMinimalInit = false;
|
||||
FGTestApi::setUp::initTestGlobals("canvas");
|
||||
|
||||
// Canvas needs loadxml command
|
||||
fgInitCommands();
|
||||
|
||||
simgear::canvas::Canvas::setSystemAdapter(
|
||||
simgear::canvas::SystemAdapterPtr(new canvas::FGCanvasSystemAdapter)
|
||||
);
|
||||
|
||||
globals->add_subsystem("Canvas", new CanvasMgr, SGSubsystemMgr::DISPLAY);
|
||||
|
||||
globals->get_subsystem_mgr()->bind();
|
||||
globals->get_subsystem_mgr()->init();
|
||||
|
||||
FGTestApi::setUp::initStandardNasal(true /* withCanvas */);
|
||||
globals->get_subsystem_mgr()->postinit();
|
||||
}
|
||||
|
||||
// Clean up after each test.
|
||||
void CanvasTests::tearDown()
|
||||
{
|
||||
FGTestApi::tearDown::shutdownTestGlobals();
|
||||
}
|
||||
|
||||
void CanvasTests::testCanvasBasic()
|
||||
{
|
||||
bool ok = FGTestApi::executeNasal(R"(
|
||||
var my_canvas = canvas.new({
|
||||
"name": "PFD-Test",
|
||||
"size": [512, 512],
|
||||
"view": [768, 1024],
|
||||
"mipmapping": 1
|
||||
});
|
||||
|
||||
globals.pfd = my_canvas;
|
||||
)");
|
||||
CPPUNIT_ASSERT(ok);
|
||||
|
||||
auto canvasPtr = globals->get_subsystem<CanvasMgr>()->getCanvas("PFD-Test");
|
||||
CPPUNIT_ASSERT(canvasPtr.valid());
|
||||
|
||||
ok = FGTestApi::executeNasal(R"(
|
||||
globals.pfd.createGroup("wibble");
|
||||
)");
|
||||
CPPUNIT_ASSERT(ok);
|
||||
|
||||
auto wibbleGroupPtr = canvasPtr->getGroup("wibble");
|
||||
CPPUNIT_ASSERT(wibbleGroupPtr.valid());
|
||||
}
|
||||
|
||||
void CanvasTests::testImagePixelOps()
|
||||
{
|
||||
bool ok = FGTestApi::executeNasal(R"(
|
||||
var my_canvas = canvas.new({
|
||||
"name": "ImagePixelOpsCanvas",
|
||||
"size": [512, 512],
|
||||
"view": [768, 1024],
|
||||
"mipmapping": 1
|
||||
});
|
||||
|
||||
var g = my_canvas.createGroup("root");
|
||||
var img = g.createChild('image', 'ops-image');
|
||||
|
||||
# deliberate non-power-of-two sizes here
|
||||
img.setSize(150, 170);
|
||||
|
||||
globals.pixelOps = my_canvas;
|
||||
)");
|
||||
CPPUNIT_ASSERT(ok);
|
||||
|
||||
auto canvasPtr = globals->get_subsystem<CanvasMgr>()->getCanvas("ImagePixelOpsCanvas");
|
||||
CPPUNIT_ASSERT(canvasPtr.valid());
|
||||
|
||||
auto imagePtr = canvasPtr->getRootGroup()->getElementById("ops-image");
|
||||
CPPUNIT_ASSERT(imagePtr.valid());
|
||||
|
||||
auto image = dynamic_cast<simgear::canvas::Image*>(imagePtr.get());
|
||||
image->setFill(osg::Vec4(1.0, 0.0, 0.5, 1.0));
|
||||
|
||||
image->fillRect(SGRecti(20, 40, 70, 55), "#7f3f1f");
|
||||
|
||||
ok = FGTestApi::executeNasal(R"(
|
||||
var canvas = globals.pixelOps;
|
||||
var img = canvas.getGroup('root').getElementById('ops-image');
|
||||
|
||||
print('Image is:', img);
|
||||
img.fillRect([5, 8, 180, 37], '#aabbcc');
|
||||
)");
|
||||
CPPUNIT_ASSERT(ok);
|
||||
|
||||
auto osgImage = image->getImage();
|
||||
const uint8_t testColor1[] = {0xff, 0xcc, 0xbb, 0xaa}; // little endian
|
||||
verifyPixel(osgImage.get(), 5, 8, testColor1);
|
||||
verifyPixel(osgImage.get(), 149, 44, testColor1);
|
||||
|
||||
// test pixles should not have been touched by the second fillRect
|
||||
const uint8_t testColor2[] = {0xff, 0x1f, 0x3f, 0x7f}; // little endian
|
||||
verifyPixel(osgImage.get(), 20, 45, testColor2);
|
||||
}
|
||||
49
test_suite/simgear_tests/canvas/testCanvas.hxx
Normal file
49
test_suite/simgear_tests/canvas/testCanvas.hxx
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include <cppunit/TestFixture.h>
|
||||
|
||||
|
||||
// The unit tests.
|
||||
class CanvasTests : public CppUnit::TestFixture
|
||||
{
|
||||
// Set up the test suite.
|
||||
CPPUNIT_TEST_SUITE(CanvasTests);
|
||||
CPPUNIT_TEST(testCanvasBasic);
|
||||
CPPUNIT_TEST(testImagePixelOps);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
// Set up function for each test.
|
||||
void setUp();
|
||||
|
||||
// Clean up after each test.
|
||||
void tearDown();
|
||||
|
||||
// The tests.
|
||||
void testCanvasBasic();
|
||||
void testImagePixelOps();
|
||||
};
|
||||
|
||||
|
||||
12
test_suite/simgear_tests/math/CMakeLists.txt
Normal file
12
test_suite/simgear_tests/math/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
set(TESTSUITE_SOURCES
|
||||
${TESTSUITE_SOURCES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test-up.cxx
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
set(TESTSUITE_HEADERS
|
||||
${TESTSUITE_HEADERS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/testSGGeodesy.hxx
|
||||
PARENT_SCOPE
|
||||
)
|
||||
24
test_suite/simgear_tests/math/TestSuite.cxx
Normal file
24
test_suite/simgear_tests/math/TestSuite.cxx
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "testSGGeodesy.hxx"
|
||||
|
||||
|
||||
// Set up the tests.
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(MathGeodesyTests, "Simgear unit tests");
|
||||
172
test_suite/simgear_tests/math/test-up.cxx
Normal file
172
test_suite/simgear_tests/math/test-up.cxx
Normal file
@@ -0,0 +1,172 @@
|
||||
// do some test relating to the concept of "up"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
|
||||
#include "testSGGeodesy.hxx"
|
||||
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
|
||||
// The test-up unit test.
|
||||
void MathGeodesyTests::testUp()
|
||||
{
|
||||
// for each lat/lon given in goedetic coordinates, calculate
|
||||
// geocentric coordinates, cartesian coordinates, the local "up"
|
||||
// vector (based on original geodetic lat/lon), as well as the "Z"
|
||||
// intercept (for which 0 = center of earth)
|
||||
|
||||
|
||||
double lon = 0;
|
||||
double alt = 0;
|
||||
int i;
|
||||
const int n = 19;
|
||||
double lat[n] = {0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90};
|
||||
|
||||
// Hard coded expected results.
|
||||
double lat_geoc_expected[n] = {
|
||||
0,
|
||||
4.96669608700923,
|
||||
9.93439421027913,
|
||||
14.9040671396528,
|
||||
19.8766298623747,
|
||||
24.8529125604827,
|
||||
29.8336358098291,
|
||||
34.8193887023496,
|
||||
39.8106105519284,
|
||||
44.8075767840180,
|
||||
49.8103895262907,
|
||||
54.8189733092144,
|
||||
59.8330761504926,
|
||||
64.8522761370246,
|
||||
69.8759934364236,
|
||||
74.9035074740039,
|
||||
79.9339788099657,
|
||||
84.9664750566862,
|
||||
90
|
||||
};
|
||||
double cart_expected[n][3] = {
|
||||
{6378137, 0, 0},
|
||||
{6353866.26310279, 555891.26758132, 0},
|
||||
{6281238.76737403, 1107551.86696002, 0},
|
||||
{6160807.25190988, 1650783.32787306, 0},
|
||||
{5993488.27326157, 2181451.33089075, 0},
|
||||
{5780555.22988658, 2695517.17208404, 0},
|
||||
{5523628.67081747, 3189068.5, 0},
|
||||
{5224663.96230526, 3658349.09101875, 0},
|
||||
{4885936.40630155, 4099787.43648327, 0},
|
||||
{4510023.92403682, 4510023.92403682, 0},
|
||||
{4099787.43648328, 4885936.40630155, 0},
|
||||
{3658349.09101875, 5224663.96230526, 0},
|
||||
{3189068.5, 5523628.67081747, 0},
|
||||
{2695517.17208404, 5780555.22988658, 0},
|
||||
{2181451.33089075, 5993488.27326157, 0},
|
||||
{1650783.32787306, 6160807.25190988, 0},
|
||||
{1107551.86696002, 6281238.76737403, 0},
|
||||
{555891.26758132, 6353866.26310279, 0},
|
||||
{3.90548253078665e-10, 6378137, 0}
|
||||
};
|
||||
double up_expected[n][3] = {
|
||||
{6378137, 0, -0},
|
||||
{6354027.82056206, 0, -552183.96002777},
|
||||
{6281872.82960345, 0, -1100248.54773536},
|
||||
{6162189.08803834, 0, -1640100.14019589},
|
||||
{5995836.38389635, 0, -2167696.78782876},
|
||||
{5784014.11472572, 0, -2679074.46295779},
|
||||
{5528256.63929284, 0, -3170373.73538364},
|
||||
{5230426.84020036, 0, -3637866.9093781},
|
||||
{4892707.60007269, 0, -4077985.57220038},
|
||||
{4517590.87884893, 0, -4487348.40886592},
|
||||
{4107864.09120678, 0, -4862789.03770643},
|
||||
{3666593.52237417, 0, -5201383.52320227},
|
||||
{3197104.58692395, 0, -5500477.13393864},
|
||||
{2702958.82600294, 0, -5757709.84149597},
|
||||
{2187927.64927902, 0, -5971040.00711856},
|
||||
{1655962.9523645, 0, -6138765.68235824},
|
||||
{1111164.87081001, 0, -6259542.96102869},
|
||||
{557747.059253584, 0, -6332400.86398617},
|
||||
{3.91862092481447e-10, 0, -6356752.31424518}
|
||||
};
|
||||
double geod_intercept[n] = {
|
||||
0,
|
||||
552169.92020293,
|
||||
1100137.4939038,
|
||||
1639732.35699488,
|
||||
2166847.86675177,
|
||||
2677472.35586416,
|
||||
3167719.66364641,
|
||||
3633858.71206688,
|
||||
4072341.90150465,
|
||||
4479832.11012469,
|
||||
4853228.0913901,
|
||||
5189688.07642079,
|
||||
5486651.40157058,
|
||||
5741857.99662372,
|
||||
5953365.5852939,
|
||||
6119564.46711958,
|
||||
6239189.76825642,
|
||||
6311331.06793104,
|
||||
6335439.32729282
|
||||
};
|
||||
double geoc_intercept[n] = {
|
||||
0,
|
||||
552169.92020293,
|
||||
1100137.4939038,
|
||||
1639732.35699488,
|
||||
2166847.86675177,
|
||||
2677472.35586416,
|
||||
3167719.66364641,
|
||||
3633858.71206688,
|
||||
4072341.90150465,
|
||||
4479832.11012469,
|
||||
4853228.0913901,
|
||||
5189688.07642079,
|
||||
5486651.40157058,
|
||||
5741857.99662372,
|
||||
5953365.5852939,
|
||||
6119564.46711958,
|
||||
6239189.76825642,
|
||||
6311331.06793104,
|
||||
6378137 // Sole difference with geod, due to truncation artifacts.
|
||||
};
|
||||
|
||||
for (i=0; i < n; i++) {
|
||||
cout << "lon = " << lon << " geod lat = " << lat[i];
|
||||
|
||||
double sl_radius, lat_geoc;
|
||||
sgGeodToGeoc( lat[i] * SGD_DEGREES_TO_RADIANS, alt, &sl_radius, &lat_geoc );
|
||||
cout << " geoc lat = " << lat_geoc * SGD_RADIANS_TO_DEGREES << endl;
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(lat_geoc_expected[i], lat_geoc*SGD_RADIANS_TO_DEGREES, 1e-10);
|
||||
|
||||
double pc[3];
|
||||
sgGeodToCart( lon * SGD_DEGREES_TO_RADIANS, lat[i] * SGD_DEGREES_TO_RADIANS, 0.0, pc );
|
||||
cout << " cartesian = " << SGVec3d(pc[0], pc[1], pc[2]) << endl;
|
||||
for (int j=0; j < 3; j++)
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(cart_expected[i][j], pc[j], 1e-7);
|
||||
|
||||
SGGeod geod_up = SGGeod::fromDeg(lon, -lat[i]);
|
||||
SGVec3d geod_up_vect = SGVec3d::fromGeod(geod_up);
|
||||
cout << " geod up = " << geod_up_vect << endl;
|
||||
for (int j=0; j < 3; j++)
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(up_expected[i][j], geod_up_vect[j], 1e-7);
|
||||
|
||||
SGGeoc geoc_up = SGGeoc::fromGeod(geod_up);
|
||||
SGVec3d geoc_up_vect = SGVec3d::fromGeoc(geoc_up);
|
||||
cout << " geoc up = " << geoc_up_vect << endl;
|
||||
for (int j=0; j < 3; j++)
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(up_expected[i][j], geoc_up_vect[j], 1e-7);
|
||||
|
||||
double slope = geod_up_vect[2] / geod_up_vect[0];
|
||||
double intercept = pc[2] - slope * pc[0];
|
||||
cout << " Z intercept (based on geodetic up) = " << intercept << endl;
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(geod_intercept[i], intercept, 1e-7);
|
||||
|
||||
slope = geoc_up_vect[2] / geoc_up_vect[0];
|
||||
intercept = pc[2] - slope * pc[0];
|
||||
cout << " Z intercept (based on geocentric up) = " << intercept << endl;
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(geoc_intercept[i], intercept, 1e-7);
|
||||
}
|
||||
}
|
||||
50
test_suite/simgear_tests/math/testSGGeodesy.hxx
Normal file
50
test_suite/simgear_tests/math/testSGGeodesy.hxx
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _FG_MATH_GEODESY_SIMGEAR_UNIT_TESTS_HXX
|
||||
#define _FG_MATH_GEODESY_SIMGEAR_UNIT_TESTS_HXX
|
||||
|
||||
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include <cppunit/TestFixture.h>
|
||||
|
||||
|
||||
|
||||
// The unit tests.
|
||||
class MathGeodesyTests : public CppUnit::TestFixture
|
||||
{
|
||||
// Set up the test suite.
|
||||
CPPUNIT_TEST_SUITE(MathGeodesyTests);
|
||||
CPPUNIT_TEST(testUp);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
// Set up function for each test.
|
||||
void setUp() {}
|
||||
|
||||
// Clean up after each test.
|
||||
void tearDown() {}
|
||||
|
||||
// The tests.
|
||||
void testUp();
|
||||
};
|
||||
|
||||
|
||||
#endif // _FG_MATH_GEODESY_SIMGEAR_UNIT_TESTS_HXX
|
||||
12
test_suite/simgear_tests/props/CMakeLists.txt
Normal file
12
test_suite/simgear_tests/props/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
set(TESTSUITE_SOURCES
|
||||
${TESTSUITE_SOURCES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_props.cxx
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
set(TESTSUITE_HEADERS
|
||||
${TESTSUITE_HEADERS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_props.hxx
|
||||
PARENT_SCOPE
|
||||
)
|
||||
24
test_suite/simgear_tests/props/TestSuite.cxx
Normal file
24
test_suite/simgear_tests/props/TestSuite.cxx
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "test_props.hxx"
|
||||
|
||||
|
||||
// Set up the tests.
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(SimgearPropsTests, "Simgear unit tests");
|
||||
81
test_suite/simgear_tests/props/test_props.cxx
Normal file
81
test_suite/simgear_tests/props/test_props.cxx
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "test_props.hxx"
|
||||
|
||||
#include <simgear/props/props_io.hxx>
|
||||
|
||||
// Set up function for each test.
|
||||
void SimgearPropsTests::setUp()
|
||||
{
|
||||
// Create a property tree.
|
||||
tree = new SGPropertyNode;
|
||||
}
|
||||
|
||||
|
||||
// Clean up after each test.
|
||||
void SimgearPropsTests::tearDown()
|
||||
{
|
||||
// Delete the tree (avoiding the memory leak).
|
||||
delete tree;
|
||||
}
|
||||
|
||||
|
||||
// Test property aliasing, to catch possible memory leaks.
|
||||
void SimgearPropsTests::testAliasLeak()
|
||||
{
|
||||
// Declarations.
|
||||
SGPropertyNode *alias;
|
||||
|
||||
// Create a new node.
|
||||
tree->getNode("test-node", true);
|
||||
|
||||
// Aliased node.
|
||||
alias = tree->getNode("test-alias", true);
|
||||
alias->alias("test-node");
|
||||
}
|
||||
|
||||
void SimgearPropsTests::testPropsCopyIf()
|
||||
{
|
||||
// dummy property tree structure
|
||||
tree->setIntValue("a/a/a", 42);
|
||||
tree->setStringValue("a/a/b", "foo");
|
||||
tree->setIntValue("a/a/c[2]", 99);
|
||||
tree->setIntValue("a/a/d", 1);
|
||||
tree->setIntValue("a/b/a[0]", 50);
|
||||
tree->setIntValue("a/b/a[1]", 100);
|
||||
tree->setStringValue("a/b/b", "foo");
|
||||
|
||||
SGPropertyNode_ptr destA(new SGPropertyNode);
|
||||
|
||||
copyPropertiesIf(tree, destA, [](const SGPropertyNode* src) {
|
||||
// always copy non-leaf nodes
|
||||
if (src->nChildren() > 0)
|
||||
return true;
|
||||
|
||||
return (src->getType() == simgear::props::INT) &&
|
||||
src->getIntValue() > 50;
|
||||
});
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(1, destA->getNode("a/a")->nChildren()); // only 99
|
||||
CPPUNIT_ASSERT_EQUAL(99, destA->getIntValue("a/a/c[2]"));
|
||||
CPPUNIT_ASSERT_EQUAL(1, destA->getNode("a/b")->nChildren()); // only 100
|
||||
CPPUNIT_ASSERT_EQUAL(100, destA->getIntValue("a/b/a[1]"));
|
||||
}
|
||||
55
test_suite/simgear_tests/props/test_props.hxx
Normal file
55
test_suite/simgear_tests/props/test_props.hxx
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _FG_SIMGEAR_PROPS_SIMGEAR_UNIT_TESTS_HXX
|
||||
#define _FG_SIMGEAR_PROPS_SIMGEAR_UNIT_TESTS_HXX
|
||||
|
||||
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include <cppunit/TestFixture.h>
|
||||
|
||||
#include <simgear/props/props.hxx>
|
||||
|
||||
|
||||
// The unit tests of the simgear property tree.
|
||||
class SimgearPropsTests : public CppUnit::TestFixture
|
||||
{
|
||||
// Set up the test suite.
|
||||
CPPUNIT_TEST_SUITE(SimgearPropsTests);
|
||||
CPPUNIT_TEST(testAliasLeak);
|
||||
CPPUNIT_TEST(testPropsCopyIf);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
// Set up function for each test.
|
||||
void setUp();
|
||||
|
||||
// Clean up after each test.
|
||||
void tearDown();
|
||||
|
||||
// The tests.
|
||||
void testAliasLeak();
|
||||
void testPropsCopyIf();
|
||||
private:
|
||||
// A property tree.
|
||||
SGPropertyNode *tree;
|
||||
};
|
||||
|
||||
#endif // _FG_SIMGEAR_PROPS_SIMGEAR_UNIT_TESTS_HXX
|
||||
12
test_suite/simgear_tests/structure/CMakeLists.txt
Normal file
12
test_suite/simgear_tests/structure/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
set(TESTSUITE_SOURCES
|
||||
${TESTSUITE_SOURCES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_event.cxx
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
set(TESTSUITE_HEADERS
|
||||
${TESTSUITE_HEADERS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_event.hxx
|
||||
PARENT_SCOPE
|
||||
)
|
||||
24
test_suite/simgear_tests/structure/TestSuite.cxx
Normal file
24
test_suite/simgear_tests/structure/TestSuite.cxx
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "test_event.hxx"
|
||||
|
||||
|
||||
// Set up the tests.
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(SimgearEventTests, "Simgear unit tests");
|
||||
142
test_suite/simgear_tests/structure/test_event.cxx
Normal file
142
test_suite/simgear_tests/structure/test_event.cxx
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include "test_event.hxx"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace {
|
||||
|
||||
SGEventMgr* global_eventManager = nullptr;
|
||||
double global_realTime = 0.0;
|
||||
|
||||
// class which behaves similarly to TimerObj in NasalSys
|
||||
class FakeNasalTimer
|
||||
{
|
||||
public:
|
||||
FakeNasalTimer(string n) : _name(n)
|
||||
{
|
||||
}
|
||||
|
||||
void invoke()
|
||||
{
|
||||
++_invokeCount;
|
||||
|
||||
if (_expectedTime > 0.0) {
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(_expectedTime, global_realTime, 0.1);
|
||||
}
|
||||
|
||||
// rescheudle base don the next time
|
||||
if (!_rescheduleTimes.empty()) {
|
||||
const auto t = _rescheduleTimes.front();
|
||||
_rescheduleTimes.pop_front();
|
||||
|
||||
// TimerObj does this, eugh
|
||||
if (global_eventManager) {
|
||||
global_eventManager->removeTask(_name);
|
||||
start(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void start(double interval)
|
||||
{
|
||||
if (!global_eventManager)
|
||||
return;
|
||||
|
||||
global_eventManager->addTask(_name, [this](){ this->invoke(); },
|
||||
interval, interval /* delay */, false);
|
||||
|
||||
_expectedTime = global_realTime + interval;
|
||||
}
|
||||
|
||||
string _name;
|
||||
deque<double> _rescheduleTimes;
|
||||
int _invokeCount = 0;
|
||||
double _expectedTime = 0.0;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// Set up function for each test.
|
||||
void SimgearEventTests::setUp()
|
||||
{
|
||||
_eventManager = new SGEventMgr;
|
||||
global_eventManager = _eventManager;
|
||||
_eventManager->init();
|
||||
|
||||
_realTimeProp = new SGPropertyNode{};
|
||||
_eventManager->setRealtimeProperty(_realTimeProp);
|
||||
}
|
||||
|
||||
// Clean up after each test.
|
||||
void SimgearEventTests::tearDown()
|
||||
{
|
||||
global_eventManager = nullptr;
|
||||
}
|
||||
|
||||
void SimgearEventTests::runForTestTime(double totalTime, double updateHz, double simTimeScaling)
|
||||
{
|
||||
const double dt = 1.0 / updateHz;
|
||||
const int updateCount = static_cast<int>(totalTime * updateHz);
|
||||
const double simDt = dt * simTimeScaling;
|
||||
_realTimeProp->setDoubleValue(dt);
|
||||
global_realTime = 0.0;
|
||||
|
||||
for (int c = 0; c < updateCount; ++c) {
|
||||
const double newRealTime = global_realTime + dt;
|
||||
global_realTime = newRealTime;
|
||||
_eventManager->update(simDt);
|
||||
}
|
||||
}
|
||||
|
||||
void SimgearEventTests::testTaskRescheduleDuringRun()
|
||||
{
|
||||
auto t1 = std::make_unique<FakeNasalTimer>("timer_aaa");
|
||||
t1->_rescheduleTimes.resize(10);
|
||||
fill(t1->_rescheduleTimes.begin(), t1->_rescheduleTimes.end(), 0.5);
|
||||
t1->_rescheduleTimes.push_back(30.0); // large final value
|
||||
|
||||
global_realTime = 0.0;
|
||||
t1->start(1.0);
|
||||
runForTestTime(8.0, 20);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(11, t1->_invokeCount);
|
||||
}
|
||||
|
||||
void SimgearEventTests::testTaskRescheduleDuringRun2()
|
||||
{
|
||||
auto t1 = std::make_unique<FakeNasalTimer>("timer_bbb");
|
||||
const std::initializer_list<double> times = {
|
||||
0.02, 0.05, 0.02, 0.1, 0.02, 0.125, 0.05, 0.02};
|
||||
t1->_rescheduleTimes = times;
|
||||
t1->_rescheduleTimes.push_back(30.0); // large final value
|
||||
|
||||
global_realTime = 0.0;
|
||||
t1->start(1.0);
|
||||
|
||||
// running at 60Hz, check we don't miss any
|
||||
runForTestTime(8.0, 60);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(9, t1->_invokeCount);
|
||||
}
|
||||
55
test_suite/simgear_tests/structure/test_event.hxx
Normal file
55
test_suite/simgear_tests/structure/test_event.hxx
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cppunit/TestFixture.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/structure/event_mgr.hxx>
|
||||
|
||||
// The unit tests of the simgear property tree.
|
||||
class SimgearEventTests : public CppUnit::TestFixture
|
||||
{
|
||||
// Set up the test suite.
|
||||
CPPUNIT_TEST_SUITE(SimgearEventTests);
|
||||
CPPUNIT_TEST(testTaskRescheduleDuringRun);
|
||||
CPPUNIT_TEST(testTaskRescheduleDuringRun2);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
// Set up function for each test.
|
||||
void setUp();
|
||||
|
||||
// Clean up after each test.
|
||||
void tearDown();
|
||||
|
||||
void runForTestTime(double totalTime, double updateHz, double simTimeScaling = 1.0);
|
||||
|
||||
// The tests.
|
||||
void testTaskRescheduleDuringRun();
|
||||
void testTaskRescheduleDuringRun2();
|
||||
|
||||
private:
|
||||
SGSharedPtr<SGEventMgr> _eventManager;
|
||||
SGPropertyNode_ptr _realTimeProp;
|
||||
SGPropertyNode_ptr _freezeProp;
|
||||
};
|
||||
23
test_suite/system_tests/CMakeLists.txt
Normal file
23
test_suite/system_tests/CMakeLists.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
# Add each system test category.
|
||||
foreach( system_test_category
|
||||
FDM
|
||||
Instrumentation
|
||||
Navaids
|
||||
Main
|
||||
)
|
||||
|
||||
add_subdirectory(${system_test_category})
|
||||
|
||||
endforeach( system_test_category )
|
||||
|
||||
|
||||
set(TESTSUITE_SOURCES
|
||||
${TESTSUITE_SOURCES}
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
|
||||
set(TESTSUITE_HEADERS
|
||||
${TESTSUITE_HEADERS}
|
||||
PARENT_SCOPE
|
||||
)
|
||||
12
test_suite/system_tests/FDM/CMakeLists.txt
Normal file
12
test_suite/system_tests/FDM/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
set(TESTSUITE_SOURCES
|
||||
${TESTSUITE_SOURCES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/testAeroMesh.cxx
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
set(TESTSUITE_HEADERS
|
||||
${TESTSUITE_HEADERS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/testAeroMesh.hxx
|
||||
PARENT_SCOPE
|
||||
)
|
||||
24
test_suite/system_tests/FDM/TestSuite.cxx
Normal file
24
test_suite/system_tests/FDM/TestSuite.cxx
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "testAeroMesh.hxx"
|
||||
|
||||
|
||||
// Set up the unit tests.
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(AeroMeshTests, "System tests");
|
||||
222
test_suite/system_tests/FDM/testAeroMesh.cxx
Normal file
222
test_suite/system_tests/FDM/testAeroMesh.cxx
Normal file
@@ -0,0 +1,222 @@
|
||||
#include "testAeroMesh.hxx"
|
||||
|
||||
#include "test_suite/FGTestApi/testGlobals.hxx"
|
||||
#include "test_suite/FGTestApi/PrivateAccessorFDM.hxx"
|
||||
#include "test_suite/FGTestApi/scene_graph.hxx"
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/misc/test_macros.hxx>
|
||||
#include <simgear/math/SGVec3.hxx>
|
||||
#include <simgear/math/SGGeod.hxx>
|
||||
#include <simgear/math/SGQuat.hxx>
|
||||
#include <simgear/math/SGGeoc.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
|
||||
#include <AIModel/AIAircraft.hxx>
|
||||
#include <AIModel/AIManager.hxx>
|
||||
#include <AIModel/performancedata.hxx>
|
||||
#include <AIModel/performancedb.hxx>
|
||||
#include "FDM/AIWake/AircraftMesh.hxx"
|
||||
#include "FDM/AIWake/AIWakeGroup.hxx"
|
||||
extern "C" {
|
||||
#include "src/FDM/LaRCsim/ls_matrix.h"
|
||||
}
|
||||
|
||||
#include "FDM/JSBSim/math/FGLocation.h"
|
||||
#include "FDM/JSBSim/math/FGQuaternion.h"
|
||||
|
||||
#include <Main/globals.hxx>
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace JSBSim;
|
||||
|
||||
double rho = 2.0E-3;
|
||||
|
||||
|
||||
// Set up function for each test.
|
||||
void AeroMeshTests::setUp()
|
||||
{
|
||||
FGTestApi::setUp::initTestGlobals("aeromesh");
|
||||
FGTestApi::setUp::initScenery();
|
||||
globals->get_props()->getNode("environment/density-slugft3", true)
|
||||
->setDoubleValue(rho);
|
||||
}
|
||||
|
||||
|
||||
// Clean up after each test.
|
||||
void AeroMeshTests::tearDown()
|
||||
{
|
||||
FGTestApi::tearDown::shutdownTestGlobals();
|
||||
}
|
||||
|
||||
|
||||
void AeroMeshTests::testLiftComputation()
|
||||
{
|
||||
double b = 10.0;
|
||||
double c = 2.0;
|
||||
AircraftMesh_ptr mesh = new AircraftMesh(b, c, "test");
|
||||
SGGeod geodPos = SGGeod::fromDeg(0.0, 0.0);
|
||||
SGVec3d pos;
|
||||
double vel = 100.;
|
||||
double weight = 50.;
|
||||
|
||||
SGGeodesy::SGGeodToCart(geodPos, pos);
|
||||
mesh->setPosition(pos, SGQuatd::unit());
|
||||
|
||||
SGPropertyNode* props = globals->get_props()->getNode("ai/models", true);
|
||||
props->setDoubleValue("acceleration-kts-hour", 0.0);
|
||||
props->setDoubleValue("deceleration-kts-hour", 0.0);
|
||||
props->setDoubleValue("climbrate-fpm", 0.0);
|
||||
props->setDoubleValue("decentrate-fpm", 0.0);
|
||||
props->setDoubleValue("rotate-speed-kts", 0.0);
|
||||
props->setDoubleValue("takeoff-speed-kts", 0.0);
|
||||
props->setDoubleValue("climb-speed-kts", 0.0);
|
||||
props->setDoubleValue("cruise-speed-kts", 0.0);
|
||||
props->setDoubleValue("decent-speed-kts", 0.0);
|
||||
props->setDoubleValue("approach-speed-kts", 0.0);
|
||||
props->setDoubleValue("touchdown-speed-kts", 0.0);
|
||||
props->setDoubleValue("taxi-speed-kts", 0.0);
|
||||
props->setDoubleValue("geometry/wing/span-ft", b);
|
||||
props->setDoubleValue("geometry/wing/chord-ft", c);
|
||||
props->setDoubleValue("geometry/weight-lbs", weight);
|
||||
|
||||
globals->add_new_subsystem<PerformanceDB>(SGSubsystemMgr::POST_FDM);
|
||||
globals->get_subsystem<PerformanceDB>()->bind();
|
||||
globals->get_subsystem<PerformanceDB>()->init();
|
||||
|
||||
FGAIManager *aiManager = new FGAIManager;
|
||||
FGAIAircraft *ai = new FGAIAircraft;
|
||||
ai->setGeodPos(geodPos);
|
||||
ai->setSpeed(vel * SG_FPS_TO_KT);
|
||||
ai->setPerformance("", "jet_transport");
|
||||
ai->getPerformance()->initFromProps(props);
|
||||
aiManager->attach(ai);
|
||||
|
||||
AIWakeGroup wg;
|
||||
wg.AddAI(ai);
|
||||
|
||||
SGVec3d force = mesh->GetForce(wg, SGVec3d(vel, 0., 0.), rho);
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(force[1], 0.0, 1e-9);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(force[2], -weight, 1e-9);
|
||||
|
||||
SGVec3d moment = mesh->GetMoment();
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(moment[0], 0.0, 1e-9);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(moment[1], -0.5*weight, 1e-9);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(moment[2], 0.0, 1e-9);
|
||||
|
||||
auto accessor = FGTestApi::PrivateAccessor::FDM::Accessor();
|
||||
|
||||
for (int i=1; i<= accessor.read_FDM_AIWake_WakeMesh_nelm(mesh); ++i)
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(accessor.read_FDM_AIWake_WakeMesh_Gamma(accessor.read_FDM_AIWake_AIWakeGroup_aiWakeData(&wg, 1))[i][1],
|
||||
accessor.read_FDM_AIWake_WakeMesh_Gamma(mesh)[i][1], 1e-9);
|
||||
}
|
||||
|
||||
|
||||
void AeroMeshTests::testFourierLiftingLine()
|
||||
{
|
||||
double b = 10.0;
|
||||
double c = 2.0;
|
||||
double vel = 100.;
|
||||
double weight = 50.;
|
||||
|
||||
auto accessor = FGTestApi::PrivateAccessor::FDM::Accessor();
|
||||
|
||||
WakeMesh_ptr mesh = new WakeMesh(b, c, "testMesh");
|
||||
int N = accessor.read_FDM_AIWake_WakeMesh_nelm(mesh);
|
||||
double **mtx = nr_matrix(1, N, 1, N);
|
||||
double **coef = nr_matrix(1, N, 1, 1);
|
||||
|
||||
mesh->computeAoA(vel, rho, weight);
|
||||
|
||||
for (int m=1; m<=N; ++m) {
|
||||
double vm = M_PI*m/(N+1);
|
||||
double sm = sin(vm);
|
||||
coef[m][1] = c*M_PI/(2*b);
|
||||
for (int n=1; n<=N; ++n)
|
||||
mtx[m][n] = sin(n*vm)*(1.0+coef[m][1]*n/sm);
|
||||
}
|
||||
|
||||
nr_gaussj(mtx, N, coef, 1);
|
||||
|
||||
double S = b*c;
|
||||
double AR = b*b/S;
|
||||
double lift = 0.5*rho*S*vel*vel*coef[1][1]*M_PI*AR;
|
||||
double sinAlpha = weight / lift;
|
||||
lift *= sinAlpha;
|
||||
|
||||
cout << "y, Lift (Fourier), Lift (VLM), Corrected lift (VLM)" << endl;
|
||||
|
||||
for (int i=1; i<=N; ++i) {
|
||||
double y = accessor.read_FDM_AIWake_WakeMesh_elements(mesh)[i-1]->getBoundVortexMidPoint()[1];
|
||||
double theta = acos(2.0*y/b);
|
||||
double gamma = 0.0;
|
||||
for (int n=1; n<=N; ++n)
|
||||
gamma += coef[n][1]*sin(n*theta);
|
||||
|
||||
gamma *= 2.0*b*vel*sinAlpha;
|
||||
|
||||
cout << y << ", " << gamma << ", " << accessor.read_FDM_AIWake_WakeMesh_Gamma(mesh)[i][1] << ", "
|
||||
<< accessor.read_FDM_AIWake_WakeMesh_Gamma(mesh)[i][1] / gamma - 1.0 << endl;
|
||||
}
|
||||
|
||||
nr_free_matrix(mtx, 1, N, 1, N);
|
||||
nr_free_matrix(coef, 1, N, 1, 1);
|
||||
}
|
||||
|
||||
|
||||
void AeroMeshTests::testFrameTransformations()
|
||||
{
|
||||
double b = 10.0;
|
||||
double c = 2.0;
|
||||
double yaw = 80. * SGD_DEGREES_TO_RADIANS;
|
||||
double pitch = 5. * SGD_DEGREES_TO_RADIANS;
|
||||
double roll = -10. * SGD_DEGREES_TO_RADIANS;
|
||||
SGQuatd orient = SGQuatd::fromYawPitchRoll(yaw, pitch, roll);
|
||||
SGGeod geodPos = SGGeod::fromDeg(45.0, 10.0);
|
||||
SGVec3d pos;
|
||||
|
||||
SGGeodesy::SGGeodToCart(geodPos, pos);
|
||||
SGGeoc geoc = SGGeoc::fromCart(pos);
|
||||
|
||||
FGLocation loc(geoc.getLongitudeRad(),
|
||||
geoc.getLatitudeRad(),
|
||||
geoc.getRadiusFt());
|
||||
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(pos[0] * SG_METER_TO_FEET, loc(1), 1e-7);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(pos[1] * SG_METER_TO_FEET, loc(2), 1e-7);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(pos[2] * SG_METER_TO_FEET, loc(3), 1e-7);
|
||||
|
||||
AircraftMesh_ptr mesh = new AircraftMesh(b, c, "test");
|
||||
mesh->setPosition(pos, orient);
|
||||
|
||||
FGQuaternion qJ(roll, pitch, yaw);
|
||||
FGMatrix33 Tb2l = qJ.GetTInv();
|
||||
FGColumnVector3 refPos = loc.GetTec2l() * loc;
|
||||
|
||||
for (int i=0; i < 4; ++i)
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(orient(i), qJ((i+1) % 4 + 1), 1e-9);
|
||||
|
||||
auto accessor = FGTestApi::PrivateAccessor::FDM::Accessor();
|
||||
|
||||
for (int i=0; i < accessor.read_FDM_AIWake_WakeMesh_nelm(mesh); ++i) {
|
||||
SGVec3d pt = accessor.read_FDM_AIWake_WakeMesh_elements(mesh)[i]->getBoundVortexMidPoint();
|
||||
FGColumnVector3 ptJ(pt[0], pt[1], pt[2]);
|
||||
FGColumnVector3 p = loc.GetTl2ec() * (refPos + Tb2l * ptJ);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(accessor.read_FDM_AIWake_AircraftMesh_midPt(mesh)[i][0], p(1), 1e-7);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(accessor.read_FDM_AIWake_AircraftMesh_midPt(mesh)[i][1], p(2), 1e-7);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(accessor.read_FDM_AIWake_AircraftMesh_midPt(mesh)[i][2], p(3), 1e-7);
|
||||
|
||||
pt = accessor.read_FDM_AIWake_WakeMesh_elements(mesh)[i]->getCollocationPoint();
|
||||
ptJ.InitMatrix(pt[0], pt[1], pt[2]);
|
||||
p = loc.GetTl2ec() * (refPos + Tb2l * ptJ);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(accessor.read_FDM_AIWake_AircraftMesh_collPt(mesh)[i][0], p(1), 1e-7);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(accessor.read_FDM_AIWake_AircraftMesh_collPt(mesh)[i][1], p(2), 1e-7);
|
||||
CPPUNIT_ASSERT_DOUBLES_EQUAL(accessor.read_FDM_AIWake_AircraftMesh_collPt(mesh)[i][2], p(3), 1e-7);
|
||||
}
|
||||
}
|
||||
52
test_suite/system_tests/FDM/testAeroMesh.hxx
Normal file
52
test_suite/system_tests/FDM/testAeroMesh.hxx
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _FG_AERO_MESH_SYSTEM_TESTS_HXX
|
||||
#define _FG_AERO_MESH_SYSTEM_TESTS_HXX
|
||||
|
||||
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include <cppunit/TestFixture.h>
|
||||
|
||||
|
||||
// The system tests.
|
||||
class AeroMeshTests : public CppUnit::TestFixture
|
||||
{
|
||||
// Set up the test suite.
|
||||
CPPUNIT_TEST_SUITE(AeroMeshTests);
|
||||
CPPUNIT_TEST(testFourierLiftingLine);
|
||||
CPPUNIT_TEST(testFrameTransformations);
|
||||
CPPUNIT_TEST(testLiftComputation);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
// Set up function for each test.
|
||||
void setUp();
|
||||
|
||||
// Clean up after each test.
|
||||
void tearDown();
|
||||
|
||||
// The tests.
|
||||
void testFourierLiftingLine();
|
||||
void testFrameTransformations();
|
||||
void testLiftComputation();
|
||||
};
|
||||
|
||||
#endif // _FG_AERO_MESH_SYSTEM_TESTS_HXX
|
||||
12
test_suite/system_tests/Instrumentation/CMakeLists.txt
Normal file
12
test_suite/system_tests/Instrumentation/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
set(TESTSUITE_SOURCES
|
||||
${TESTSUITE_SOURCES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
|
||||
#${CMAKE_CURRENT_SOURCE_DIR}/testgps.cxx
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
set(TESTSUITE_HEADERS
|
||||
${TESTSUITE_HEADERS}
|
||||
#${CMAKE_CURRENT_SOURCE_DIR}/testgps.hxx
|
||||
PARENT_SCOPE
|
||||
)
|
||||
24
test_suite/system_tests/Instrumentation/TestSuite.cxx
Normal file
24
test_suite/system_tests/Instrumentation/TestSuite.cxx
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "testgps.hxx"
|
||||
|
||||
|
||||
// Set up the unit tests.
|
||||
//CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(GPSTests, "System tests");
|
||||
351
test_suite/system_tests/Instrumentation/testgps.cxx
Normal file
351
test_suite/system_tests/Instrumentation/testgps.cxx
Normal file
@@ -0,0 +1,351 @@
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/io/iostreams/sgstream.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
|
||||
#include <Main/fg_init.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
|
||||
#include <Instrumentation/gps.hxx>
|
||||
#include <Autopilot/route_mgr.hxx>
|
||||
#include <Environment/environment_mgr.hxx>
|
||||
#include <Navaids/airways.hxx>
|
||||
#include <Navaids/waypoint.hxx>
|
||||
#include <Navaids/procedure.hxx>
|
||||
|
||||
#include "test_suite/helpers/globals.hxx"
|
||||
#include "test_suite/helpers/NavDataCache.hxx"
|
||||
|
||||
#include "testgps.hxx"
|
||||
|
||||
|
||||
using std::string;
|
||||
using namespace flightgear;
|
||||
|
||||
char *homedir = ::getenv( "HOME" );
|
||||
char *hostname = ::getenv( "HOSTNAME" );
|
||||
bool free_hostname = false;
|
||||
|
||||
void testSetPosition(const SGGeod& aPos)
|
||||
{
|
||||
fgSetDouble("/position/longitude-deg", aPos.getLongitudeDeg());
|
||||
fgSetDouble("/position/latitude-deg", aPos.getLatitudeDeg());
|
||||
fgSetDouble("/position/altitude-ft", aPos.getElevationFt());
|
||||
}
|
||||
|
||||
void printScratch(SGPropertyNode* scratch)
|
||||
{
|
||||
if (!scratch->getBoolValue("valid", false)) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Scratch is invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Scratch:" <<
|
||||
scratch->getStringValue("ident") << "/" << scratch->getStringValue("name"));
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "\t" << scratch->getDoubleValue("longitude-deg")
|
||||
<< " " << scratch->getDoubleValue("latitude-deg") << " @ " << scratch->getDoubleValue("altitude-ft"));
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "\t" << scratch->getDoubleValue("true-bearing-deg") <<
|
||||
" (" << scratch->getDoubleValue("mag-bearing-deg") << " magnetic) " << scratch->getDoubleValue("distance-nm"));
|
||||
|
||||
if (scratch->hasChild("result-index")) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "\tresult-index:" << scratch->getIntValue("result-index"));
|
||||
}
|
||||
|
||||
if (scratch->hasChild("route-index")) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "\troute-index:" << scratch->getIntValue("route-index"));
|
||||
}
|
||||
}
|
||||
|
||||
void printRoute(const WayptVec& aRoute)
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "route size=" << aRoute.size());
|
||||
for (unsigned int r=0; r<aRoute.size();++r) {
|
||||
Waypt* w = aRoute[r];
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "\t" << r << ": " << w->ident() << " "
|
||||
<< w->owner()->ident());
|
||||
}
|
||||
}
|
||||
|
||||
void createDummyRoute(FGRouteMgr* rm)
|
||||
{
|
||||
SGPropertyNode* rmInput = fgGetNode("/autopilot/route-manager/input", true);
|
||||
rmInput->setStringValue("UW");
|
||||
rmInput->setStringValue("TLA/347/13");
|
||||
rmInput->setStringValue("TLA");
|
||||
rmInput->setStringValue("HAVEN");
|
||||
rmInput->setStringValue("NEW/305/29");
|
||||
rmInput->setStringValue("NEW");
|
||||
rmInput->setStringValue("OTR");
|
||||
}
|
||||
|
||||
|
||||
void GPSTests::setUp()
|
||||
{
|
||||
fgtest::initTestGlobals("GPS");
|
||||
fgtest::initNavDataCache();
|
||||
}
|
||||
|
||||
|
||||
void GPSTests::tearDown()
|
||||
{
|
||||
fgtest::shutdownTestGlobals();
|
||||
}
|
||||
|
||||
|
||||
void GPSTests::testGPS()
|
||||
{
|
||||
fgSetDouble("/environment/magnetic-variation-deg", 0.0);
|
||||
|
||||
Airway::load();
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "hello world!");
|
||||
|
||||
const FGAirport* egph = fgFindAirportID("EGPH");
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "egph: cart location:" << egph->cart());
|
||||
|
||||
FGAirport::AirportFilter af;
|
||||
FGPositionedList l = FGPositioned::findClosestN(egph->geod(), 20, 2000.0, &af);
|
||||
for (unsigned int i=0; i<l.size(); ++i) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "\t" << l[i]->ident() << "/" << l[i]->name());
|
||||
}
|
||||
|
||||
//l = FGPositioned::findWithinRange(egph->geod(), 500.0, &af);
|
||||
//for (unsigned int i=0; i<l.size(); ++i) {
|
||||
// SG_LOG(SG_GENERAL, SG_ALERT, "\t" << l[i]->ident() << "/" << l[i]->name());
|
||||
//}
|
||||
|
||||
|
||||
FGRouteMgr* rm = new FGRouteMgr;
|
||||
globals->add_subsystem( "route-manager", rm );
|
||||
|
||||
// FGEnvironmentMgr* envMgr = new FGEnvironmentMgr;
|
||||
// globals->add_subsystem("environment", envMgr);
|
||||
// envMgr->init();
|
||||
|
||||
fgSetBool("/sim/realism/simple-gps", true);
|
||||
|
||||
// _realismSimpleGps
|
||||
|
||||
SGPropertyNode* nd = fgGetNode("/instrumentation/gps", true);
|
||||
GPS* gps = new GPS(nd);
|
||||
globals->add_subsystem("gps", gps);
|
||||
|
||||
const FGAirport* egph = fgFindAirportID("EGPH");
|
||||
testSetPosition(egph->geod());
|
||||
|
||||
// startup the route manager
|
||||
rm->init();
|
||||
|
||||
nd->setBoolValue("serviceable", true);
|
||||
fgSetBool("/systems/electrical/outputs/gps", true);
|
||||
|
||||
gps->init();
|
||||
SGPropertyNode* scratch = nd->getChild("scratch", 0, true);
|
||||
SGPropertyNode* wp = nd->getChild("wp", 0, true);
|
||||
SGPropertyNode* wp1 = wp->getChild("wp", 1, true);
|
||||
|
||||
// update a few times
|
||||
gps->update(0.05);
|
||||
gps->update(0.05);
|
||||
gps->update(0.05);
|
||||
|
||||
scratch->setStringValue("query", "TL");
|
||||
scratch->setStringValue("type", "Vor");
|
||||
scratch->setBoolValue("exact", false);
|
||||
nd->setStringValue("command", "search");
|
||||
printScratch(scratch);
|
||||
|
||||
nd->setStringValue("command", "next");
|
||||
printScratch(scratch);
|
||||
|
||||
nd->setStringValue("command", "next");
|
||||
printScratch(scratch);
|
||||
|
||||
// alphanumeric sort, partial matching
|
||||
nd->setDoubleValue("config/min-runway-length-ft", 5000.0);
|
||||
scratch->setBoolValue("exact", false);
|
||||
scratch->setBoolValue("order-by-distance", false);
|
||||
scratch->setStringValue("query", "KS");
|
||||
scratch->setStringValue("type", "apt");
|
||||
|
||||
nd->setStringValue("command", "search");
|
||||
printScratch(scratch);
|
||||
|
||||
nd->setStringValue("command", "next");
|
||||
printScratch(scratch);
|
||||
|
||||
nd->setStringValue("command", "next");
|
||||
printScratch(scratch);
|
||||
|
||||
// alphanumeric sort, explicit matching
|
||||
scratch->setBoolValue("exact", true);
|
||||
scratch->setBoolValue("order-by-distance", true);
|
||||
scratch->setStringValue("type", "vor");
|
||||
scratch->setStringValue("query", "DCS");
|
||||
|
||||
nd->setStringValue("command", "search");
|
||||
printScratch(scratch);
|
||||
|
||||
nd->setStringValue("command", "next");
|
||||
printScratch(scratch);
|
||||
|
||||
// search on totally missing
|
||||
scratch->setBoolValue("exact", true);
|
||||
scratch->setBoolValue("order-by-distance", true);
|
||||
scratch->setStringValue("query", "FOFOFOFOF");
|
||||
nd->setStringValue("command", "search");
|
||||
printScratch(scratch);
|
||||
|
||||
// nearest
|
||||
scratch->setStringValue("type", "apt");
|
||||
scratch->setIntValue("max-results", 10);
|
||||
nd->setStringValue("command", "nearest");
|
||||
printScratch(scratch);
|
||||
|
||||
nd->setStringValue("command", "next");
|
||||
printScratch(scratch);
|
||||
|
||||
nd->setStringValue("command", "next");
|
||||
printScratch(scratch);
|
||||
|
||||
// direct to
|
||||
nd->setStringValue("command", "direct");
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "mode:" << nd->getStringValue("mode") << "\n\t"
|
||||
<< wp1->getStringValue("ID") << " " << wp1->getDoubleValue("longitude-deg")
|
||||
<< " " << wp1->getDoubleValue("latitude-deg"));
|
||||
|
||||
// OBS mode
|
||||
scratch->setStringValue("query", "UW");
|
||||
scratch->setBoolValue("order-by-distance", true);
|
||||
nd->setStringValue("command", "search");
|
||||
printScratch(scratch);
|
||||
|
||||
nd->setStringValue("command", "obs");
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "mode:" << nd->getStringValue("mode") << "\n\t"
|
||||
<< wp1->getStringValue("ID") << " " << wp1->getDoubleValue("longitude-deg")
|
||||
<< " " << wp1->getDoubleValue("latitude-deg"));
|
||||
|
||||
// load route waypoints
|
||||
createDummyRoute(rm);
|
||||
|
||||
scratch->setIntValue("route-index", 5);
|
||||
nd->setStringValue("command", "load-route-wpt");
|
||||
printScratch(scratch);
|
||||
|
||||
nd->setStringValue("command", "next");
|
||||
printScratch(scratch);
|
||||
|
||||
nd->setStringValue("command", "next");
|
||||
printScratch(scratch);
|
||||
|
||||
scratch->setIntValue("route-index", 2);
|
||||
nd->setStringValue("command", "load-route-wpt");
|
||||
nd->setStringValue("command", "direct");
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "mode:" << nd->getStringValue("mode") << "\n\t"
|
||||
<< wp1->getStringValue("ID") << " " << wp1->getDoubleValue("longitude-deg")
|
||||
<< " " << wp1->getDoubleValue("latitude-deg"));
|
||||
|
||||
// route editing
|
||||
SGGeod pos = egph->geod();
|
||||
scratch->setStringValue("ident", "FOOBAR");
|
||||
scratch->setDoubleValue("longitude-deg", pos.getLongitudeDeg());
|
||||
scratch->setDoubleValue("latitude-deg", pos.getLatitudeDeg());
|
||||
nd->setStringValue("command", "define-user-wpt");
|
||||
printScratch(scratch);
|
||||
|
||||
// airways
|
||||
FGPositioned::TypeFilter vorFilt(FGPositioned::VOR);
|
||||
FGPositionedRef tla = FGPositioned::findClosestWithIdent("TLA", pos, &vorFilt);
|
||||
FGPositionedRef big = FGPositioned::findClosestWithIdent("BIG", pos, &vorFilt);
|
||||
FGPositionedRef pol = FGPositioned::findClosestWithIdent("POL", pos, &vorFilt);
|
||||
|
||||
const FGAirport* eddm = fgFindAirportID("EDDM");
|
||||
FGPositionedRef mun = FGPositioned::findClosestWithIdent("MUN",
|
||||
eddm->geod(), &vorFilt);
|
||||
|
||||
const FGAirport* ksfo = fgFindAirportID("KSFO");
|
||||
FGPositionedRef sfo = FGPositioned::findClosestWithIdent("SFO",
|
||||
ksfo->geod(), &vorFilt);
|
||||
|
||||
|
||||
WayptRef awy1 = new NavaidWaypoint(tla, NULL);
|
||||
WayptRef awy2 = new NavaidWaypoint(big, NULL);
|
||||
WayptRef awy3 = new NavaidWaypoint(pol, NULL);
|
||||
WayptRef awy4 = new NavaidWaypoint(mun, NULL);
|
||||
WayptRef awy5 = new NavaidWaypoint(sfo, NULL);
|
||||
|
||||
WayptRef awy6 = new NavaidWaypoint(
|
||||
(FGPositioned*) fgFindAirportID("KJFK"), NULL);
|
||||
|
||||
SGPath p("/Users/jmt/Desktop/airways.kml");
|
||||
sg_ofstream f;
|
||||
f.open(p, fstream::out | fstream::trunc);
|
||||
|
||||
// pre-amble
|
||||
f << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
"<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n"
|
||||
"<Document>\n";
|
||||
|
||||
WayptVec route;
|
||||
Airway::highLevel()->route(awy1, awy3, route);
|
||||
Route::dumpRouteToLineString("egph-egcc", route, f);
|
||||
|
||||
Airway::lowLevel()->route(awy1, awy2, route);
|
||||
Route::dumpRouteToLineString("egph-big", route, f);
|
||||
|
||||
Airway::lowLevel()->route(awy2, awy4, route);
|
||||
Route::dumpRouteToLineString("big-mun", route, f);
|
||||
|
||||
Airway::highLevel()->route(awy4, awy5, route);
|
||||
Route::dumpRouteToLineString("mun-sfo", route, f);
|
||||
|
||||
Airway::lowLevel()->route(awy5, awy6, route);
|
||||
Route::dumpRouteToLineString("sfo-jfk", route, f);
|
||||
|
||||
// post-amble
|
||||
f << "</Document>\n"
|
||||
"</kml>" << endl;
|
||||
f.close();
|
||||
|
||||
// procedures
|
||||
SGPath op("/Users/jmt/Desktop/procedures.kml");
|
||||
f.open(op, fstream::out | fstream::trunc);
|
||||
|
||||
FGAirport* eham = (FGAirport*) fgFindAirportID("EHAM");
|
||||
FGPositioned::TypeFilter fixFilt(FGPositioned::FIX);
|
||||
|
||||
WayptVec approach;
|
||||
FGPositionedRef redfa = FGPositioned::findClosestWithIdent("REDFA",
|
||||
eham->geod(), &fixFilt);
|
||||
bool ok = eham->buildApproach(new NavaidWaypoint(redfa, NULL),
|
||||
eham->getRunwayByIdent("18R"), approach);
|
||||
if (!ok ) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "failed to build approach");
|
||||
}
|
||||
|
||||
|
||||
FGAirport* egll = (FGAirport*) fgFindAirportID("EGLL");
|
||||
WayptVec approach2;
|
||||
ok = egll->buildApproach(new NavaidWaypoint(big, NULL),
|
||||
egll->getRunwayByIdent("27R"), approach2);
|
||||
if (!ok ) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "failed to build approach");
|
||||
}
|
||||
|
||||
// pre-amble
|
||||
f << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
"<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n"
|
||||
"<Document>\n";
|
||||
|
||||
Route::dumpRouteToLineString("REDFA 18R", approach, f);
|
||||
Route::dumpRouteToLineString("EGLL 27R", approach2, f);
|
||||
|
||||
// post-amble
|
||||
f << "</Document>\n"
|
||||
"</kml>" << endl;
|
||||
f.close();
|
||||
}
|
||||
48
test_suite/system_tests/Instrumentation/testgps.hxx
Normal file
48
test_suite/system_tests/Instrumentation/testgps.hxx
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _FG_GPS_SYSTEM_TESTS_HXX
|
||||
#define _FG_GPS_SYSTEM_TESTS_HXX
|
||||
|
||||
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include <cppunit/TestFixture.h>
|
||||
|
||||
|
||||
// The system tests.
|
||||
class GPSTests : public CppUnit::TestFixture
|
||||
{
|
||||
// Set up the test suite.
|
||||
CPPUNIT_TEST_SUITE(GPSTests);
|
||||
CPPUNIT_TEST(testGPS);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
// Set up function for each test.
|
||||
void setUp();
|
||||
|
||||
// Clean up after each test.
|
||||
void tearDown();
|
||||
|
||||
// The tests.
|
||||
void testGPS();
|
||||
};
|
||||
|
||||
#endif // _FG_GPS_SYSTEM_TESTS_HXX
|
||||
12
test_suite/system_tests/Main/CMakeLists.txt
Normal file
12
test_suite/system_tests/Main/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
set(TESTSUITE_SOURCES
|
||||
${TESTSUITE_SOURCES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/testOptions.cxx
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
set(TESTSUITE_HEADERS
|
||||
${TESTSUITE_HEADERS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/testOptions.hxx
|
||||
PARENT_SCOPE
|
||||
)
|
||||
24
test_suite/system_tests/Main/TestSuite.cxx
Normal file
24
test_suite/system_tests/Main/TestSuite.cxx
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "testOptions.hxx"
|
||||
|
||||
|
||||
// Set up the unit tests.
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(OptionsTests, "System tests");
|
||||
171
test_suite/system_tests/Main/testOptions.cxx
Normal file
171
test_suite/system_tests/Main/testOptions.cxx
Normal file
@@ -0,0 +1,171 @@
|
||||
// Written by James Turner, started 2017.
|
||||
//
|
||||
// Copyright (C) 2017 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 "testOptions.hxx"
|
||||
#include "config.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#include "test_suite/FGTestApi/NavDataCache.hxx"
|
||||
#include "test_suite/FGTestApi/scene_graph.hxx"
|
||||
#include "test_suite/FGTestApi/testGlobals.hxx"
|
||||
|
||||
#include <simgear/package/Root.hxx>
|
||||
#include <simgear/props/props_io.hxx>
|
||||
|
||||
#include "Main/fg_props.hxx"
|
||||
#include "Main/globals.hxx"
|
||||
#include "Main/options.hxx"
|
||||
#include <Main/fg_init.hxx>
|
||||
|
||||
using namespace std::string_literals;
|
||||
using namespace flightgear;
|
||||
using namespace simgear::pkg;
|
||||
|
||||
void OptionsTests::setUp()
|
||||
{
|
||||
FGTestApi::setUp::initTestGlobals("options");
|
||||
FGTestApi::setUp::initNavDataCache();
|
||||
Options::reset();
|
||||
fgLoadProps("defaults.xml", globals->get_props());
|
||||
}
|
||||
|
||||
|
||||
void OptionsTests::tearDown()
|
||||
{
|
||||
FGTestApi::tearDown::shutdownTestGlobals();
|
||||
}
|
||||
|
||||
void OptionsTests::testLoadDefaultAircraft()
|
||||
{
|
||||
const auto customFGAircraftPath = SGPath::fromUtf8(FG_TEST_SUITE_DATA) / "customAircraftDir";
|
||||
|
||||
{
|
||||
Options* opts = Options::sharedInstance();
|
||||
opts->setShouldLoadDefaultConfig(false);
|
||||
|
||||
const string fgAircraftArg = "--fg-aircraft=" + customFGAircraftPath.utf8Str();
|
||||
const char* args[] = {"dummypath", fgAircraftArg.c_str()};
|
||||
opts->init(2, (char**)args, SGPath());
|
||||
opts->processOptions();
|
||||
}
|
||||
|
||||
fgInitAircraftPaths(false);
|
||||
fgInitAircraft(false, false);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL("c172p"s, string{fgGetString("/sim/aircraft")});
|
||||
CPPUNIT_ASSERT_EQUAL("c172p"s, string{fgGetString("/sim/aircraft-id")});
|
||||
//CPPUNIT_ASSERT_EQUAL(adPath.utf8Str(), string{fgGetString("/sim/aircraft-dir")});
|
||||
}
|
||||
|
||||
void OptionsTests::testOptionAircraftWithAircraftDir()
|
||||
{
|
||||
const auto adPath = SGPath::fromUtf8(FG_TEST_SUITE_DATA) / "customAircraftDir" / "overrideUfo";
|
||||
|
||||
{
|
||||
Options* opts = Options::sharedInstance();
|
||||
opts->setShouldLoadDefaultConfig(false);
|
||||
|
||||
const string aircraftDirArg = "--aircraft-dir=" + adPath.utf8Str();
|
||||
const char* args[] = {"dummypath", "--aircraft=ufo", aircraftDirArg.c_str()};
|
||||
opts->init(3, (char**)args, SGPath());
|
||||
opts->processOptions();
|
||||
}
|
||||
|
||||
fgInitAircraftPaths(false);
|
||||
fgInitAircraft(false, false);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL("ufo"s, string{fgGetString("/sim/aircraft")});
|
||||
CPPUNIT_ASSERT_EQUAL("ufo"s, string{fgGetString("/sim/aircraft-id")});
|
||||
CPPUNIT_ASSERT_EQUAL(adPath.utf8Str(), string{fgGetString("/sim/aircraft-dir")});
|
||||
}
|
||||
|
||||
void OptionsTests::testOptionAircraftWithFGAircraft()
|
||||
{
|
||||
const auto customFGAircraftPath = SGPath::fromUtf8(FG_TEST_SUITE_DATA) / "customAircraftDir";
|
||||
|
||||
{
|
||||
Options* opts = Options::sharedInstance();
|
||||
opts->setShouldLoadDefaultConfig(false);
|
||||
|
||||
const string fgAircraftArg = "--fg-aircraft=" + customFGAircraftPath.utf8Str();
|
||||
const char* args[] = {"dummypath", "--aircraft=ufo", fgAircraftArg.c_str()};
|
||||
opts->init(3, (char**)args, SGPath());
|
||||
opts->processOptions();
|
||||
}
|
||||
|
||||
fgInitAircraftPaths(false);
|
||||
fgInitAircraft(false, false);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL("ufo"s, string{fgGetString("/sim/aircraft")});
|
||||
CPPUNIT_ASSERT_EQUAL("ufo"s, string{fgGetString("/sim/aircraft-id")});
|
||||
|
||||
const auto correctDir = (customFGAircraftPath / "overrideUfo").utf8Str();
|
||||
CPPUNIT_ASSERT_EQUAL(correctDir, string{fgGetString("/sim/aircraft-dir")});
|
||||
}
|
||||
|
||||
void OptionsTests::testOptionAircraftUnqualified()
|
||||
{
|
||||
const auto packageAircraftDir = SGPath::fromUtf8(FG_TEST_SUITE_DATA) / "dummy_package_root";
|
||||
SGSharedPtr<Root> pkgRoot(new Root(packageAircraftDir, FLIGHTGEAR_VERSION));
|
||||
globals->setPackageRoot(pkgRoot);
|
||||
|
||||
{
|
||||
Options* opts = Options::sharedInstance();
|
||||
opts->setShouldLoadDefaultConfig(false);
|
||||
|
||||
const char* args[] = {"dummypath", "--aircraft=bob"};
|
||||
opts->init(2, (char**)args, SGPath());
|
||||
opts->processOptions();
|
||||
}
|
||||
|
||||
fgInitAircraftPaths(false);
|
||||
fgInitAircraft(false, false);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL("bob"s, string{fgGetString("/sim/aircraft")});
|
||||
CPPUNIT_ASSERT_EQUAL("org.fg.test.catalog1.bob"s, string{fgGetString("/sim/aircraft-id")});
|
||||
|
||||
const auto correctDir = (packageAircraftDir / "org.fg.test.catalog1" / "Aircraft" / "bobCraft").utf8Str();
|
||||
CPPUNIT_ASSERT_EQUAL(correctDir, string{fgGetString("/sim/aircraft-dir")});
|
||||
}
|
||||
|
||||
void OptionsTests::testOptionAircraftFullyQualified()
|
||||
{
|
||||
const auto packageAircraftDir = SGPath::fromUtf8(FG_TEST_SUITE_DATA) / "dummy_package_root";
|
||||
SGSharedPtr<Root> pkgRoot(new Root(packageAircraftDir, FLIGHTGEAR_VERSION));
|
||||
globals->setPackageRoot(pkgRoot);
|
||||
|
||||
{
|
||||
Options* opts = Options::sharedInstance();
|
||||
opts->setShouldLoadDefaultConfig(false);
|
||||
|
||||
const char* args[] = {"dummypath", "--aircraft=org.fg.test.catalog1.bob"};
|
||||
opts->init(2, (char**)args, SGPath());
|
||||
opts->processOptions();
|
||||
}
|
||||
|
||||
fgInitAircraftPaths(false);
|
||||
fgInitAircraft(false, false);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL("bob"s, string{fgGetString("/sim/aircraft")});
|
||||
CPPUNIT_ASSERT_EQUAL("org.fg.test.catalog1.bob"s, string{fgGetString("/sim/aircraft-id")});
|
||||
|
||||
const auto correctDir = (packageAircraftDir / "org.fg.test.catalog1" / "Aircraft" / "bobCraft").utf8Str();
|
||||
CPPUNIT_ASSERT_EQUAL(correctDir, string{fgGetString("/sim/aircraft-dir")});
|
||||
}
|
||||
52
test_suite/system_tests/Main/testOptions.hxx
Normal file
52
test_suite/system_tests/Main/testOptions.hxx
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cppunit/TestFixture.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
|
||||
// The system tests.
|
||||
class OptionsTests : public CppUnit::TestFixture
|
||||
{
|
||||
// Set up the test suite.
|
||||
CPPUNIT_TEST_SUITE(OptionsTests);
|
||||
CPPUNIT_TEST(testLoadDefaultAircraft);
|
||||
CPPUNIT_TEST(testOptionAircraftWithAircraftDir);
|
||||
CPPUNIT_TEST(testOptionAircraftUnqualified);
|
||||
CPPUNIT_TEST(testOptionAircraftFullyQualified);
|
||||
CPPUNIT_TEST(testOptionAircraftWithFGAircraft);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
// Set up function for each test.
|
||||
void setUp();
|
||||
|
||||
// Clean up after each test.
|
||||
void tearDown();
|
||||
|
||||
// The tests.
|
||||
void testOptionAircraftWithAircraftDir();
|
||||
void testOptionAircraftUnqualified();
|
||||
void testOptionAircraftFullyQualified();
|
||||
void testOptionAircraftWithFGAircraft();
|
||||
void testLoadDefaultAircraft();
|
||||
};
|
||||
12
test_suite/system_tests/Navaids/CMakeLists.txt
Normal file
12
test_suite/system_tests/Navaids/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
set(TESTSUITE_SOURCES
|
||||
${TESTSUITE_SOURCES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
|
||||
#${CMAKE_CURRENT_SOURCE_DIR}/testnavs.cxx
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
set(TESTSUITE_HEADERS
|
||||
${TESTSUITE_HEADERS}
|
||||
#${CMAKE_CURRENT_SOURCE_DIR}/testnavs.hxx
|
||||
PARENT_SCOPE
|
||||
)
|
||||
24
test_suite/system_tests/Navaids/TestSuite.cxx
Normal file
24
test_suite/system_tests/Navaids/TestSuite.cxx
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "testnavs.hxx"
|
||||
|
||||
|
||||
// Set up the unit tests.
|
||||
//CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(NavaidsTests, "System tests");
|
||||
107
test_suite/system_tests/Navaids/testnavs.cxx
Normal file
107
test_suite/system_tests/Navaids/testnavs.cxx
Normal file
@@ -0,0 +1,107 @@
|
||||
// Written by James Turner, started 2009.
|
||||
//
|
||||
// Copyright (C) 2009 Curtis L. Olson
|
||||
//
|
||||
// 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 <iostream>
|
||||
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
#include <Navaids/fixlist.hxx>
|
||||
//#include "ilslist.hxx"
|
||||
#include <Navaids/navlist.hxx>
|
||||
//#include "mkrbeacons.hxx"
|
||||
|
||||
#include "test_suite/dataStore.hxx"
|
||||
|
||||
#include "testnavs.hxx"
|
||||
|
||||
|
||||
void NavaidsTests::testNavs()
|
||||
{
|
||||
double heading, dist;
|
||||
|
||||
DataStore &data = DataStore::get();
|
||||
|
||||
FGNavList *current_navlist = new FGNavList;
|
||||
SGPath p_nav = data.getFGRoot() / "/Navaids/default.nav";
|
||||
|
||||
current_navlist->init( p_nav );
|
||||
|
||||
FGNavRecord *n;
|
||||
if ( (n = current_navlist->findByFreq( -93.2 * SG_DEGREES_TO_RADIANS,
|
||||
45.14 * SG_DEGREES_TO_RADIANS,
|
||||
3000, 117.30)) != NULL )
|
||||
{
|
||||
std::cout << "Found a vor station in range" << std::endl;
|
||||
std::cout << " id = " << n->get_ident() << std::endl;
|
||||
} else {
|
||||
std::cout << "not picking up vor. :-(" << std::endl;
|
||||
}
|
||||
|
||||
FGNavRecord *dcs;
|
||||
if ( (dcs = current_navlist->findByIdent( "DCS",
|
||||
-3.3 * SG_DEGREES_TO_RADIANS,
|
||||
55.9 * SG_DEGREES_TO_RADIANS))
|
||||
!= NULL ) {
|
||||
|
||||
std::cout << "Found DCS by ident" << std::endl;
|
||||
if (dcs->get_freq() != 11520)
|
||||
std::cout << "Frequency for DCS VOR is wrong (should be 115.20), it's "
|
||||
<< dcs->get_freq() << std::endl;
|
||||
} else {
|
||||
std::cout << "couldn't locate DCS (Dean-Cross) VOR" << std::endl;
|
||||
}
|
||||
|
||||
// we have to init the marker beacon storage before we parse the ILS file
|
||||
FGMarkerBeacons *current_beacons = new FGMarkerBeacons;
|
||||
current_beacons->init();
|
||||
|
||||
FGILSList *current_ilslist = new FGILSList;
|
||||
SGPath p_ils = data.getFGRoot() / "/Navaids/default.ils";
|
||||
current_ilslist->init( p_ils );
|
||||
FGILS *i = current_ilslist->findByFreq( -93.1 * SG_DEGREES_TO_RADIANS,
|
||||
45.24 * SG_DEGREES_TO_RADIANS,
|
||||
3000, 110.30);
|
||||
if ( i != NULL ) {
|
||||
std::cout << "Found an ils station in range" << std::endl;
|
||||
std::cout << " apt = " << i->get_aptcode() << std::endl;
|
||||
std::cout << " rwy = " << i->get_rwyno() << std::endl;
|
||||
} else {
|
||||
std::cout << "not picking up ils. :-(" << std::endl;
|
||||
}
|
||||
|
||||
FGFixList *current_fixlist = new FGFixList;
|
||||
SGPath p_fix = data.getFGRoot() / "/Navaids/default.fix";
|
||||
current_fixlist->init( p_fix );
|
||||
FGFix fix;
|
||||
|
||||
// attempting to get the position relative to the OTR VOR; heading
|
||||
// should be 108 degrees, distance 74nm (according to my SimCharts
|
||||
// v1.5)
|
||||
if ( current_fixlist->query_and_offset( "DOGGA",
|
||||
-0.103 * SG_DEGREES_TO_RADIANS,
|
||||
53.698 * SG_DEGREES_TO_RADIANS,
|
||||
3000, &fix, &heading, &dist) )
|
||||
{
|
||||
std::cout << "Found a matching fix" << std::endl;
|
||||
std::cout << " id = " << fix.get_ident() << std::endl;
|
||||
std::cout << " heading = " << heading << " dist = " << dist * SG_METER_TO_NM
|
||||
<< std::endl;
|
||||
} else {
|
||||
CPPUNIT_FAIL("did not find fix. :-(");
|
||||
}
|
||||
}
|
||||
48
test_suite/system_tests/Navaids/testnavs.hxx
Normal file
48
test_suite/system_tests/Navaids/testnavs.hxx
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _FG_NAVAIDS_SYSTEM_TESTS_HXX
|
||||
#define _FG_NAVAIDS_SYSTEM_TESTS_HXX
|
||||
|
||||
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include <cppunit/TestFixture.h>
|
||||
|
||||
|
||||
// The system tests.
|
||||
class NavaidsTests : public CppUnit::TestFixture
|
||||
{
|
||||
// Set up the test suite.
|
||||
CPPUNIT_TEST_SUITE(NavaidsTests);
|
||||
CPPUNIT_TEST(testNavs);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
// Set up function for each test.
|
||||
void setUp() {}
|
||||
|
||||
// Clean up after each test.
|
||||
void tearDown() {}
|
||||
|
||||
// The tests.
|
||||
void testNavs();
|
||||
};
|
||||
|
||||
#endif // _FG_NAVAIDS_SYSTEM_TESTS_HXX
|
||||
457
test_suite/testSuite.cxx
Normal file
457
test_suite/testSuite.cxx
Normal file
@@ -0,0 +1,457 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2018 Edward d'Auvergne
|
||||
*
|
||||
* This file is part of the program FlightGear.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
#include "dataStore.hxx"
|
||||
#include "fgTestRunner.hxx"
|
||||
#include "formatting.hxx"
|
||||
#include "logging.hxx"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
// The help message.
|
||||
void helpPrintout(std::ostream &stream) {
|
||||
stream << "Usage: run_test_suite [options]" << std::endl << std::endl;
|
||||
stream << "Options:" << std::endl;
|
||||
stream << " -h, --help show this help message and exit." << std::endl;
|
||||
stream << std::endl;
|
||||
stream << " Test selection options:" << std::endl;
|
||||
stream << " -s, --system-tests execute the system/functional tests." << std::endl;
|
||||
stream << " -u, --unit-tests execute the unit tests." << std::endl;
|
||||
stream << " -g, --gui-tests execute the GUI tests." << std::endl;
|
||||
stream << " -m, --simgear-tests execute the simgear tests." << std::endl;
|
||||
stream << " -f, --fgdata-tests execute the FGData tests." << std::endl;
|
||||
stream << std::endl;
|
||||
stream << " The -s, -u, -g, and -m options accept an optional argument to perform a" << std::endl;
|
||||
stream << " subset of all tests. This argument should either be the name of a test" << std::endl;
|
||||
stream << " suite, the full name of an individual test, or a comma separated list." << std::endl;
|
||||
stream << " E.g. -u DigitalFilterTests\n";
|
||||
stream << std::endl;
|
||||
stream << " Full test names consist of the test suite name, the separator '::' and then" << std::endl;
|
||||
stream << " the individual test name. The test names can revealed with the verbose" << std::endl;
|
||||
stream << " option." << std::endl;
|
||||
stream << std::endl;
|
||||
stream << " Logging options:" << std::endl;
|
||||
stream << " --log-level={bulk,debug,info,warn,alert,popup,dev_warn,dev_alert}" << std::endl;
|
||||
stream << " specify the minimum logging level to output" << std::endl;
|
||||
stream << " --log-class=[none, terrain, astro, flight, input, gl, view, cockpit," << std::endl;
|
||||
stream << " general, math, event, aircraft, autopilot, io, clipper," << std::endl;
|
||||
stream << " network, atc, nasal, instrumentation, systems, ai, environment," << std::endl;
|
||||
stream << " sound, navaid, gui, terrasync, particles, headless, osg," << std::endl;
|
||||
stream << " undefined, all]" << std::endl;
|
||||
stream << " select the logging class(es) to output." << std::endl;
|
||||
stream << " --log-split output the different non-interleaved log streams" << std::endl;
|
||||
stream << " sequentially." << std::endl;
|
||||
stream << std::endl;
|
||||
stream << " Verbosity options:" << std::endl;
|
||||
stream << " -t, --timings verbose output including names and timings for all" << std::endl;
|
||||
stream << " tests." << std::endl;
|
||||
stream << " -c, --ctest simplified output suitable for running via CTest." << std::endl;
|
||||
stream << " -d, --debug disable IO capture for debugging (super verbose output)." << std::endl;
|
||||
stream << " --no-summary disable the final summary printout." << std::endl;
|
||||
stream << std::endl;
|
||||
stream << " FG options:" << std::endl;
|
||||
stream << " --fg-root the path to FGData." << std::endl;
|
||||
stream << std::endl;
|
||||
stream << "Environmental variables:" << std::endl;
|
||||
stream << " FG_TEST_LOG_LEVEL equivalent to the --log-level option." << std::endl;
|
||||
stream << " FG_TEST_LOG_CLASS equivalent to the --log-class option." << std::endl;
|
||||
stream << " FG_TEST_LOG_SPLIT equivalent to the --log-split option." << std::endl;
|
||||
stream << " FG_TEST_TIMINGS equivalent to the -t or --timings option." << std::endl;
|
||||
stream << " FG_TEST_DEBUG equivalent to the -d or --debug option." << std::endl;
|
||||
stream << " FG_ROOT the path to FGData. The order of precedence is" << std::endl;
|
||||
stream << " --fg-root, the FG_DATA_DIR CMake option, FG_ROOT," << std::endl;
|
||||
stream << " '../fgdata/', and '../data/'." << std::endl;
|
||||
stream.flush();
|
||||
}
|
||||
|
||||
|
||||
// Convert the log class comma separated string list into a simgear debug class value.
|
||||
sgDebugClass processLogClass(std::string classList, bool &failure) {
|
||||
// Declarations.
|
||||
std::string logClassItem, val;
|
||||
unsigned int logClass=0;
|
||||
|
||||
// Convert the command line value into a string array.
|
||||
std::replace(classList.begin(), classList.end(), ',', ' ');
|
||||
std::vector<std::string> logClasses;
|
||||
stringstream temp(classList);
|
||||
while (temp >> val)
|
||||
logClasses.push_back(val);
|
||||
|
||||
// Build up the value.
|
||||
for (auto const& logClassItem: logClasses)
|
||||
if (logClassItem == "none")
|
||||
logClass |= SG_NONE;
|
||||
else if (logClassItem == "terrain")
|
||||
logClass |= SG_TERRAIN;
|
||||
else if (logClassItem == "astro")
|
||||
logClass |= SG_ASTRO;
|
||||
else if (logClassItem == "flight")
|
||||
logClass |= SG_FLIGHT;
|
||||
else if (logClassItem == "input")
|
||||
logClass |= SG_INPUT;
|
||||
else if (logClassItem == "gl")
|
||||
logClass |= SG_GL;
|
||||
else if (logClassItem == "view")
|
||||
logClass |= SG_VIEW;
|
||||
else if (logClassItem == "cockpit")
|
||||
logClass |= SG_COCKPIT;
|
||||
else if (logClassItem == "general")
|
||||
logClass |= SG_GENERAL;
|
||||
else if (logClassItem == "math")
|
||||
logClass |= SG_MATH;
|
||||
else if (logClassItem == "event")
|
||||
logClass |= SG_EVENT;
|
||||
else if (logClassItem == "aircraft")
|
||||
logClass |= SG_AIRCRAFT;
|
||||
else if (logClassItem == "autopilot")
|
||||
logClass |= SG_AUTOPILOT;
|
||||
else if (logClassItem == "io")
|
||||
logClass |= SG_IO;
|
||||
else if (logClassItem == "clipper")
|
||||
logClass |= SG_CLIPPER;
|
||||
else if (logClassItem == "network")
|
||||
logClass |= SG_NETWORK;
|
||||
else if (logClassItem == "atc")
|
||||
logClass |= SG_ATC;
|
||||
else if (logClassItem == "nasal")
|
||||
logClass |= SG_NASAL;
|
||||
else if (logClassItem == "instrumentation")
|
||||
logClass |= SG_INSTR;
|
||||
else if (logClassItem == "systems")
|
||||
logClass |= SG_SYSTEMS;
|
||||
else if (logClassItem == "ai")
|
||||
logClass |= SG_AI;
|
||||
else if (logClassItem == "environment")
|
||||
logClass |= SG_ENVIRONMENT;
|
||||
else if (logClassItem == "sound")
|
||||
logClass |= SG_SOUND;
|
||||
else if (logClassItem == "navaid")
|
||||
logClass |= SG_NAVAID;
|
||||
else if (logClassItem == "gui")
|
||||
logClass |= SG_GUI;
|
||||
else if (logClassItem == "terrasync")
|
||||
logClass |= SG_TERRASYNC;
|
||||
else if (logClassItem == "particles")
|
||||
logClass |= SG_PARTICLES;
|
||||
else if (logClassItem == "headless")
|
||||
logClass |= SG_HEADLESS;
|
||||
else if (logClassItem == "osg")
|
||||
logClass |= SG_OSG;
|
||||
else if (logClassItem == "undefined")
|
||||
logClass |= SG_UNDEFD;
|
||||
else if (logClassItem == "all")
|
||||
logClass |= SG_ALL;
|
||||
else {
|
||||
std::cout << "The log class \"" << logClassItem << "\" must be one of:" << std::endl;
|
||||
std::cout << " {none, terrain, astro, flight, input, gl, view, cockpit, general, math," << std::endl;
|
||||
std::cout << " event, aircraft, autopilot, io, clipper, network, atc, nasal," << std::endl;
|
||||
std::cout << " instrumentation, systems, ai, environment, sound, navaid, gui, terrasync," << std::endl;
|
||||
std::cout << " particles, headless, osg, undefined, all}" << std::endl << std::endl;
|
||||
std::cout.flush();
|
||||
failure = true;
|
||||
}
|
||||
|
||||
// Return a simgear debug class.
|
||||
return sgDebugClass(logClass);
|
||||
}
|
||||
|
||||
|
||||
// Convert the log priority string into a simgear debug priority value.
|
||||
sgDebugPriority processLogPriority(std::string logLevel, bool &failure) {
|
||||
// Declarations.
|
||||
sgDebugPriority logPriority=SG_INFO;
|
||||
|
||||
// Conversion.
|
||||
if (logLevel == "bulk")
|
||||
logPriority = SG_BULK;
|
||||
else if (logLevel == "debug")
|
||||
logPriority = SG_DEBUG;
|
||||
else if (logLevel == "info")
|
||||
logPriority = SG_INFO;
|
||||
else if (logLevel == "warn")
|
||||
logPriority = SG_WARN;
|
||||
else if (logLevel == "alert")
|
||||
logPriority = SG_ALERT;
|
||||
else if (logLevel == "popup")
|
||||
logPriority = SG_POPUP;
|
||||
else if (logLevel == "dev_warn")
|
||||
logPriority = SG_DEV_WARN;
|
||||
else if (logLevel == "dev_alert")
|
||||
logPriority = SG_DEV_ALERT;
|
||||
else {
|
||||
std::cout << "The log level setting of \"" << logLevel << "\" must be one of {bulk,debug,info,warn,alert,popup,dev_warn,dev_alert}.\n\n";
|
||||
std::cout.flush();
|
||||
failure = true;
|
||||
}
|
||||
|
||||
// Return the simgear debug priority.
|
||||
return logPriority;
|
||||
}
|
||||
|
||||
|
||||
// Print out a summary of the relax test suite.
|
||||
void summary(CppUnit::OStream &stream, int system_result, int unit_result, int gui_result, int simgear_result, int fgdata_result)
|
||||
{
|
||||
int synopsis = 0;
|
||||
|
||||
// Title.
|
||||
string text = "Summary of the FlightGear test suite";
|
||||
printTitle(stream, text);
|
||||
|
||||
// Subtitle.
|
||||
text = "Synopsis";
|
||||
printSection(stream, text);
|
||||
|
||||
// System/functional test summary.
|
||||
if (system_result != -1) {
|
||||
text = "System/functional tests";
|
||||
printSummaryLine(stream, text, system_result);
|
||||
synopsis += system_result;
|
||||
}
|
||||
|
||||
// Unit test summary.
|
||||
if (unit_result != -1) {
|
||||
text = "Unit tests";
|
||||
printSummaryLine(stream, text, unit_result);
|
||||
synopsis += unit_result;
|
||||
}
|
||||
|
||||
// GUI test summary.
|
||||
if (gui_result != -1) {
|
||||
text = "GUI tests";
|
||||
printSummaryLine(stream, text, gui_result);
|
||||
synopsis += gui_result;
|
||||
}
|
||||
|
||||
// Simgear unit test summary.
|
||||
if (simgear_result != -1) {
|
||||
text = "Simgear unit tests";
|
||||
printSummaryLine(stream, text, simgear_result);
|
||||
synopsis += simgear_result;
|
||||
}
|
||||
|
||||
// FGData test summary.
|
||||
if (fgdata_result != -1) {
|
||||
text = "FGData tests";
|
||||
printSummaryLine(stream, text, fgdata_result);
|
||||
synopsis += fgdata_result;
|
||||
}
|
||||
|
||||
// Synopsis.
|
||||
text ="Synopsis";
|
||||
printSummaryLine(stream, text, synopsis);
|
||||
|
||||
// End.
|
||||
stream << endl << endl;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// Declarations.
|
||||
int status_gui=-1, status_simgear=-1, status_system=-1, status_unit=-1, status_fgdata=-1;
|
||||
bool run_system=false, run_unit=false, run_gui=false, run_simgear=false, run_fgdata=false;
|
||||
bool logSplit=false;
|
||||
bool timings=false, ctest_output=false, debug=false, printSummary=true, help=false;
|
||||
char *subset_system=NULL, *subset_unit=NULL, *subset_gui=NULL, *subset_simgear=NULL, *subset_fgdata=NULL;
|
||||
bool failure=false;
|
||||
char firstchar;
|
||||
std::string arg, delim, fgRoot, logClassVal, logLevel;
|
||||
size_t delimPos;
|
||||
|
||||
// The default logging class and priority to show.
|
||||
sgDebugClass logClass=SG_ALL;
|
||||
sgDebugPriority logPriority=SG_INFO;
|
||||
|
||||
// Process environmental variables before the command line options.
|
||||
if (getenv("FG_TEST_LOG_LEVEL"))
|
||||
logPriority = processLogPriority(getenv("FG_TEST_LOG_LEVEL"), failure);
|
||||
if (getenv("FG_TEST_LOG_CLASS"))
|
||||
logClass = processLogClass(getenv("FG_TEST_LOG_CLASS"), failure);
|
||||
if (getenv("FG_TEST_LOG_SPLIT"))
|
||||
logSplit = true;
|
||||
if (getenv("FG_TEST_TIMINGS"))
|
||||
timings = true;
|
||||
if (getenv("FG_TEST_DEBUG"))
|
||||
debug = true;
|
||||
if (failure)
|
||||
return 1;
|
||||
|
||||
// Argument parsing.
|
||||
for (int i = 1; i < argc; i++) {
|
||||
firstchar = '\0';
|
||||
arg = argv[i];
|
||||
|
||||
if (i < argc-1)
|
||||
firstchar = argv[i+1][0];
|
||||
|
||||
// System test.
|
||||
if (arg == "-s" || arg == "--system-tests") {
|
||||
run_system = true;
|
||||
if (firstchar != '-')
|
||||
subset_system = argv[i+1];
|
||||
|
||||
// Unit test.
|
||||
} else if (arg == "-u" || arg == "--unit-tests") {
|
||||
run_unit = true;
|
||||
if (firstchar != '-')
|
||||
subset_unit = argv[i+1];
|
||||
|
||||
// GUI test.
|
||||
} else if (arg == "-g" || arg == "--gui-tests") {
|
||||
run_gui = true;
|
||||
if (firstchar != '-')
|
||||
subset_gui = argv[i+1];
|
||||
|
||||
// Simgear test.
|
||||
} else if (arg == "-m" || arg == "--simgear-tests") {
|
||||
run_simgear = true;
|
||||
if (firstchar != '-')
|
||||
subset_simgear = argv[i+1];
|
||||
|
||||
// FGData test.
|
||||
} else if (strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "--fgdata-tests") == 0) {
|
||||
run_fgdata = true;
|
||||
if (firstchar != '-')
|
||||
subset_fgdata = argv[i+1];
|
||||
|
||||
// Log class.
|
||||
} else if (arg.find( "--log-class" ) == 0) {
|
||||
// Process the command line.
|
||||
logClass = SG_NONE;
|
||||
delimPos = arg.find('=');
|
||||
logClassVal = arg.substr(delimPos + 1);
|
||||
logClass = processLogClass(logClassVal, failure);
|
||||
if (failure)
|
||||
return 1;
|
||||
|
||||
// Log level.
|
||||
} else if (arg.find( "--log-level" ) == 0) {
|
||||
// Process the command line level.
|
||||
delimPos = arg.find('=');
|
||||
logLevel = arg.substr(delimPos + 1);
|
||||
logPriority = processLogPriority(logLevel, failure);
|
||||
if (failure)
|
||||
return 1;
|
||||
|
||||
// Log splitting.
|
||||
} else if (arg == "--log-split") {
|
||||
logSplit = true;
|
||||
|
||||
// Timing output.
|
||||
} else if (arg == "-t" || arg == "--timings") {
|
||||
timings = true;
|
||||
|
||||
// CTest suitable output.
|
||||
} else if (arg == "-c" || arg == "--ctest") {
|
||||
ctest_output = true;
|
||||
|
||||
// Debug output.
|
||||
} else if (arg == "-d" || arg == "--debug") {
|
||||
debug = true;
|
||||
|
||||
// No summary output.
|
||||
} else if (arg == "--no-summary") {
|
||||
printSummary = false;
|
||||
|
||||
// Help.
|
||||
} else if (arg == "-h" || arg == "--help") {
|
||||
help = true;
|
||||
|
||||
// FGData path.
|
||||
} else if (arg == "--fg-root") {
|
||||
if (firstchar != '-')
|
||||
fgRoot = argv[i+1];
|
||||
}
|
||||
}
|
||||
|
||||
// Help.
|
||||
if (help) {
|
||||
helpPrintout(std::cout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Turn on all tests if no subset was specified.
|
||||
if (!run_system && !run_unit && !run_gui && !run_simgear && !run_fgdata) {
|
||||
run_system = true;
|
||||
run_unit = true;
|
||||
run_gui = true;
|
||||
run_simgear = true;
|
||||
run_fgdata = true;
|
||||
}
|
||||
|
||||
// Set up the data store singleton and FGData path.
|
||||
DataStore& data = DataStore::get();
|
||||
if (data.findFGRoot(fgRoot, debug) != 0) {
|
||||
return 1;
|
||||
}
|
||||
if (data.validateFGRoot() != 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Set up logging.
|
||||
sglog().setDeveloperMode(true);
|
||||
if (debug)
|
||||
sglog().setLogLevels(sgDebugClass(logClass), logPriority);
|
||||
else
|
||||
setupLogging(sgDebugClass(logClass), logPriority, logSplit);
|
||||
|
||||
// Execute each of the test suite categories.
|
||||
if (run_system)
|
||||
status_system = testRunner("System tests", "System / functional tests", subset_system, timings, ctest_output, debug);
|
||||
if (run_unit)
|
||||
status_unit = testRunner("Unit tests", "Unit tests", subset_unit, timings, ctest_output, debug);
|
||||
if (run_gui && 0) // Disabled as there are no GUI tests yet.
|
||||
status_gui = testRunner("GUI tests", "GUI tests", subset_gui, timings, ctest_output, debug);
|
||||
if (run_simgear)
|
||||
status_simgear = testRunner("Simgear unit tests", "Simgear unit tests", subset_simgear, timings, ctest_output, debug);
|
||||
if (run_fgdata)
|
||||
status_fgdata = testRunner("FGData tests", "FGData tests", subset_fgdata, timings, ctest_output, debug);
|
||||
|
||||
// Summary printout.
|
||||
if (printSummary && !ctest_output)
|
||||
summary(cerr, status_system, status_unit, status_gui, status_simgear, status_fgdata);
|
||||
|
||||
// Deactivate the logging.
|
||||
if (!debug)
|
||||
stopLogging();
|
||||
|
||||
// Failure.
|
||||
if (status_system > 0)
|
||||
return 1;
|
||||
if (status_unit > 0)
|
||||
return 1;
|
||||
if (status_gui > 0)
|
||||
return 1;
|
||||
if (status_simgear > 0)
|
||||
return 1;
|
||||
if (status_fgdata > 0)
|
||||
return 1;
|
||||
|
||||
// Success.
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0"?>
|
||||
<PropertyList include="BN-2-main.xml">
|
||||
<texture-path>Textures/Directflight</texture-path>
|
||||
</PropertyList>
|
||||
|
||||
|
||||
6
test_suite/test_data/AI/Aircraft/BN-2/BN-2-Hebridean.xml
Normal file
6
test_suite/test_data/AI/Aircraft/BN-2/BN-2-Hebridean.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0"?>
|
||||
<PropertyList include="BN-2-main.xml">
|
||||
<texture-path>Textures/Hebridean</texture-path>
|
||||
</PropertyList>
|
||||
|
||||
|
||||
6
test_suite/test_data/AI/Aircraft/BN-2/BN-2-Loganair.xml
Normal file
6
test_suite/test_data/AI/Aircraft/BN-2/BN-2-Loganair.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0"?>
|
||||
<PropertyList include="BN-2-main.xml">
|
||||
<texture-path>Textures/Loganair</texture-path>
|
||||
</PropertyList>
|
||||
|
||||
|
||||
87
test_suite/test_data/AI/Aircraft/BN-2/BN-2-main.xml
Normal file
87
test_suite/test_data/AI/Aircraft/BN-2/BN-2-main.xml
Normal file
@@ -0,0 +1,87 @@
|
||||
<?xml version="1.0"?>
|
||||
<PropertyList>
|
||||
<description>Britten-Norman BN-2 Islander</description>
|
||||
<author>Paul RICHTER, Syd Adams, Keith Paterson</author>
|
||||
<path>Models/bn2.ac</path>
|
||||
<animation>
|
||||
<type>select</type>
|
||||
<object-name>prop-blur-left</object-name>
|
||||
<condition>
|
||||
<greater-than>
|
||||
<property>velocities/true-airspeed-kt</property>
|
||||
<value>10</value>
|
||||
</greater-than>
|
||||
</condition>
|
||||
</animation>
|
||||
|
||||
<animation>
|
||||
<type>select</type>
|
||||
<object-name>landinglight.L</object-name>
|
||||
<condition>
|
||||
<less-than>
|
||||
<property>velocities/true-airspeed-kt</property>
|
||||
<value>10</value>
|
||||
</less-than>
|
||||
</condition>
|
||||
</animation>
|
||||
<animation>
|
||||
<type>select</type>
|
||||
<object-name>landinglight.R</object-name>
|
||||
<condition>
|
||||
<less-than>
|
||||
<property>velocities/true-airspeed-kt</property>
|
||||
<value>10</value>
|
||||
</less-than>
|
||||
</condition>
|
||||
</animation>
|
||||
<animation>
|
||||
<type>select</type>
|
||||
<object-name>prop-left</object-name>
|
||||
<condition>
|
||||
<less-than>
|
||||
<property>velocities/true-airspeed-kt</property>
|
||||
<value>10</value>
|
||||
</less-than>
|
||||
</condition>
|
||||
</animation>
|
||||
<animation>
|
||||
<type>select</type>
|
||||
<object-name>prop-disc-left</object-name>
|
||||
<condition>
|
||||
<greater-than>
|
||||
<property>velocities/true-airspeed-kt</property>
|
||||
<value>20</value>
|
||||
</greater-than>
|
||||
</condition>
|
||||
</animation>
|
||||
<animation>
|
||||
<type>select</type>
|
||||
<object-name>prop-blur-right</object-name>
|
||||
<condition>
|
||||
<greater-than>
|
||||
<property>velocities/true-airspeed-kt</property>
|
||||
<value>10</value>
|
||||
</greater-than>
|
||||
</condition>
|
||||
</animation>
|
||||
<animation>
|
||||
<type>select</type>
|
||||
<object-name>prop-disc-right</object-name>
|
||||
<condition>
|
||||
<greater-than>
|
||||
<property>velocities/true-airspeed-kt</property>
|
||||
<value>20</value>
|
||||
</greater-than>
|
||||
</condition>
|
||||
</animation>
|
||||
<animation>
|
||||
<type>select</type>
|
||||
<object-name>prop-right</object-name>
|
||||
<condition>
|
||||
<less-than>
|
||||
<property>velocities/true-airspeed-kt</property>
|
||||
<value>10</value>
|
||||
</less-than>
|
||||
</condition>
|
||||
</animation>
|
||||
</PropertyList>
|
||||
BIN
test_suite/test_data/AI/Aircraft/BN-2/Models/BN-2-livery.png
Normal file
BIN
test_suite/test_data/AI/Aircraft/BN-2/Models/BN-2-livery.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
19722
test_suite/test_data/AI/Aircraft/BN-2/Models/bn2.ac
Normal file
19722
test_suite/test_data/AI/Aircraft/BN-2/Models/bn2.ac
Normal file
File diff suppressed because it is too large
Load Diff
2
test_suite/test_data/AI/Aircraft/BN-2/Models/desktop.ini
Normal file
2
test_suite/test_data/AI/Aircraft/BN-2/Models/desktop.ini
Normal file
@@ -0,0 +1,2 @@
|
||||
[LocalizedFileNames]
|
||||
bn2.ac=@bn2.ac,0
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 86 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
57
test_suite/test_data/AI/Flightplan/left_onground.xml
Executable file
57
test_suite/test_data/AI/Flightplan/left_onground.xml
Executable file
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<PropertyList>
|
||||
<flightplan>
|
||||
<wp>
|
||||
<name>on1</name>
|
||||
<lat>59.534235</lat>
|
||||
<lon>-1.629072</lon>
|
||||
<ktas>10</ktas>
|
||||
<on-ground>1</on-ground>
|
||||
</wp>
|
||||
<wp>
|
||||
<name>on2</name>
|
||||
<lat>59.534315</lat>
|
||||
<lon>-1.629182</lon>
|
||||
<ktas>10</ktas>
|
||||
<on-ground>1</on-ground>
|
||||
</wp>
|
||||
<wp>
|
||||
<name>on5</name>
|
||||
<lat>59.534364</lat>
|
||||
<lon>-1.629345</lon>
|
||||
<ktas>10</ktas>
|
||||
<on-ground>1</on-ground>
|
||||
</wp>
|
||||
<wp>
|
||||
<name>on4</name>
|
||||
<lat>59.534372</lat>
|
||||
<lon>-1.629544</lon>
|
||||
<ktas>10</ktas>
|
||||
<on-ground>1</on-ground>
|
||||
</wp>
|
||||
<wp>
|
||||
<name>on10</name>
|
||||
<lat>59.534363</lat>
|
||||
<lon>-1.629681</lon>
|
||||
<ktas>10</ktas>
|
||||
<on-ground>1</on-ground>
|
||||
</wp>
|
||||
<wp>
|
||||
<name>on3</name>
|
||||
<lat>59.5343438</lat>
|
||||
<lon>-1.6298094</lon>
|
||||
<ktas>10</ktas>
|
||||
<on-ground>1</on-ground>
|
||||
</wp>
|
||||
<wp>
|
||||
<name>on11</name>
|
||||
<lat>59.5341711</lat>
|
||||
<lon>-1.63037</lon>
|
||||
<ktas>10</ktas>
|
||||
<on-ground>1</on-ground>
|
||||
</wp>
|
||||
<wp>
|
||||
<name>END</name>
|
||||
</wp>
|
||||
</flightplan>
|
||||
</PropertyList>
|
||||
57
test_suite/test_data/AI/Flightplan/right_onground.xml
Executable file
57
test_suite/test_data/AI/Flightplan/right_onground.xml
Executable file
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<PropertyList>
|
||||
<flightplan>
|
||||
<wp>
|
||||
<name>on1</name>
|
||||
<lat>59.534235</lat>
|
||||
<lon>-1.629072</lon>
|
||||
<ktas>10</ktas>
|
||||
<on-ground>1</on-ground>
|
||||
</wp>
|
||||
<wp>
|
||||
<name>on2</name>
|
||||
<lat>59.534315</lat>
|
||||
<lon>-1.629182</lon>
|
||||
<ktas>10</ktas>
|
||||
<on-ground>1</on-ground>
|
||||
</wp>
|
||||
<wp>
|
||||
<name>on6</name>
|
||||
<lat>59.5343928</lat>
|
||||
<lon>-1.6292113</lon>
|
||||
<ktas>10</ktas>
|
||||
<on-ground>1</on-ground>
|
||||
</wp>
|
||||
<wp>
|
||||
<name>on7</name>
|
||||
<lat>59.5344594</lat>
|
||||
<lon>-1.6292113</lon>
|
||||
<ktas>10</ktas>
|
||||
<on-ground>1</on-ground>
|
||||
</wp>
|
||||
<wp>
|
||||
<name>on8</name>
|
||||
<lat>59.5345519</lat>
|
||||
<lon>-1.6291362</lon>
|
||||
<ktas>10</ktas>
|
||||
<on-ground>1</on-ground>
|
||||
</wp>
|
||||
<wp>
|
||||
<name>on9</name>
|
||||
<lat>59.5346335</lat>
|
||||
<lon>-1.6288868</lon>
|
||||
<ktas>10</ktas>
|
||||
<on-ground>1</on-ground>
|
||||
</wp>
|
||||
<wp>
|
||||
<name>on12</name>
|
||||
<lat>59.5347749</lat>
|
||||
<lon>-1.6284227</lon>
|
||||
<ktas>10</ktas>
|
||||
<on-ground>1</on-ground>
|
||||
</wp>
|
||||
<wp>
|
||||
<name>END</name>
|
||||
</wp>
|
||||
</flightplan>
|
||||
</PropertyList>
|
||||
62
test_suite/test_data/AI/Traffic/H/HBR.xml
Normal file
62
test_suite/test_data/AI/Traffic/H/HBR.xml
Normal file
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- Updated 29NOV20 to remove EGEL flights as no runway defined in FG -->
|
||||
<trafficlist>
|
||||
<aircraft>
|
||||
<model>Aircraft/BN-2/BN-2-Hebridean.xml</model>
|
||||
<livery>HBR</livery>
|
||||
<airline>HBR</airline>
|
||||
<home-port>EGEO</home-port>
|
||||
<required-aircraft>HBR_BN_2</required-aircraft>
|
||||
<actype>BN2</actype>
|
||||
<offset>0</offset>
|
||||
<radius>8</radius>
|
||||
<flighttype>gate</flighttype>
|
||||
<performance-class>turboprop_transport</performance-class>
|
||||
<registration>G-HEBO</registration>
|
||||
<heavy>false</heavy>
|
||||
</aircraft>
|
||||
<aircraft>
|
||||
<model>Aircraft/BN-2/BN-2-Hebridean.xml</model>
|
||||
<livery>HBR</livery>
|
||||
<airline>HBR</airline>
|
||||
<home-port>EGEO</home-port>
|
||||
<required-aircraft>HBR_BN_2</required-aircraft>
|
||||
<actype>BN2</actype>
|
||||
<offset>0</offset>
|
||||
<radius>8</radius>
|
||||
<flighttype>gate</flighttype>
|
||||
<performance-class>turboprop_transport</performance-class>
|
||||
<registration>G-HEBS</registration>
|
||||
<heavy>false</heavy>
|
||||
</aircraft>
|
||||
<flight>
|
||||
<callsign>Hebridean_1000</callsign>
|
||||
<required-aircraft>HBR_BN_2</required-aircraft>
|
||||
<fltrules>VFR</fltrules>
|
||||
<departure>
|
||||
<port>EGEO</port>
|
||||
<time>2/08:25:00</time>
|
||||
</departure>
|
||||
<cruise-alt>50</cruise-alt>
|
||||
<arrival>
|
||||
<port>EGEY</port>
|
||||
<time>2/08:50:00</time>
|
||||
</arrival>
|
||||
<repeat>WEEK</repeat>
|
||||
</flight>
|
||||
<flight>
|
||||
<callsign>Hebridean_1001</callsign>
|
||||
<required-aircraft>HBR_BN_2</required-aircraft>
|
||||
<fltrules>VFR</fltrules>
|
||||
<departure>
|
||||
<port>EGEO</port>
|
||||
<time>2/14:10:00</time>
|
||||
</departure>
|
||||
<cruise-alt>50</cruise-alt>
|
||||
<arrival>
|
||||
<port>EGEY</port>
|
||||
<time>2/15:20:00</time>
|
||||
</arrival>
|
||||
<repeat>WEEK</repeat>
|
||||
</flight>
|
||||
</trafficlist>
|
||||
75
test_suite/test_data/AI/Traffic/H/TST.xml
Normal file
75
test_suite/test_data/AI/Traffic/H/TST.xml
Normal file
@@ -0,0 +1,75 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- Updated 29NOV20 to remove EGEL flights as no runway defined in FG -->
|
||||
<trafficlist>
|
||||
<aircraft>
|
||||
<model>Aircraft/BN-2/BN-2-Hebridean.xml</model>
|
||||
<livery>TST</livery>
|
||||
<airline>TST</airline>
|
||||
<home-port>YSSY</home-port>
|
||||
<required-aircraft>TST_BN_1</required-aircraft>
|
||||
<actype>BN2</actype>
|
||||
<offset>0</offset>
|
||||
<radius>8</radius>
|
||||
<performance-class>turboprop_transport</performance-class>
|
||||
<registration>G-HEBO</registration>
|
||||
<heavy>false</heavy>
|
||||
</aircraft>
|
||||
<aircraft>
|
||||
<model>Aircraft/BN-2/BN-2-Hebridean.xml</model>
|
||||
<livery>TST</livery>
|
||||
<airline>TST</airline>
|
||||
<home-port>YBBN</home-port>
|
||||
<required-aircraft>TST_BN_2</required-aircraft>
|
||||
<actype>BN2</actype>
|
||||
<offset>0</offset>
|
||||
<radius>8</radius>
|
||||
<performance-class>turboprop_transport</performance-class>
|
||||
<registration>G-HEBY</registration>
|
||||
<heavy>false</heavy>
|
||||
</aircraft>
|
||||
<flight>
|
||||
<callsign>gaParkYSSY1</callsign>
|
||||
<required-aircraft>TST_BN_1</required-aircraft>
|
||||
<fltrules>VFR</fltrules>
|
||||
<departure>
|
||||
<port>YSSY</port>
|
||||
<time>00:40:00</time>
|
||||
</departure>
|
||||
<cruise-alt>50</cruise-alt>
|
||||
<arrival>
|
||||
<port>YBBN</port>
|
||||
<time>00:52:00</time>
|
||||
</arrival>
|
||||
<repeat>03Hr</repeat>
|
||||
</flight>
|
||||
<flight>
|
||||
<callsign>gaParkYSSY2</callsign>
|
||||
<required-aircraft>TST_BN_1</required-aircraft>
|
||||
<fltrules>VFR</fltrules>
|
||||
<departure>
|
||||
<port>YBBN</port>
|
||||
<time>01:20:00</time>
|
||||
</departure>
|
||||
<cruise-alt>50</cruise-alt>
|
||||
<arrival>
|
||||
<port>YSSY</port>
|
||||
<time>01:50:00</time>
|
||||
</arrival>
|
||||
<repeat>03Hr</repeat>
|
||||
</flight>
|
||||
<flight>
|
||||
<callsign>Test_YSSY_1002</callsign>
|
||||
<required-aircraft>TST_BN_2</required-aircraft>
|
||||
<fltrules>VFR</fltrules>
|
||||
<departure>
|
||||
<port>YSSY</port>
|
||||
<time>00:48:00</time>
|
||||
</departure>
|
||||
<cruise-alt>50</cruise-alt>
|
||||
<arrival>
|
||||
<port>YBBN</port>
|
||||
<time>00:49:00</time>
|
||||
</arrival>
|
||||
<repeat>03Hr</repeat>
|
||||
</flight>
|
||||
</trafficlist>
|
||||
76
test_suite/test_data/Aircraft/Test/submodels.xml
Normal file
76
test_suite/test_data/Aircraft/Test/submodels.xml
Normal file
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<PropertyList>
|
||||
<submodel n="0">
|
||||
<name>testLoadXML</name>
|
||||
<model>Models/Geometry/null.ac</model>
|
||||
<trigger>ai/submodels/submodel[0]/trigger</trigger>
|
||||
<speed>100</speed>
|
||||
<speed-prop>ai/submodels/submodel[0]/speed</speed-prop>
|
||||
<count>42</count>
|
||||
<repeat>true</repeat>
|
||||
<delay>0.5</delay>
|
||||
<offsets>
|
||||
<x-m>2</x-m>
|
||||
<y-m>0</y-m>
|
||||
<z-m>0</z-m>
|
||||
<heading-deg>90</heading-deg>
|
||||
<pitch-deg>45</pitch-deg>
|
||||
</offsets>
|
||||
<life>1</life>
|
||||
<buoyancy>10</buoyancy>
|
||||
<wind>true</wind>
|
||||
<weight>3</weight>
|
||||
<contents>ai/submodels/submodel[0]/content</contents>
|
||||
<cd>0.2</cd>
|
||||
<eda>0.1</eda>
|
||||
<aero-stabilized>false</aero-stabilized>
|
||||
<external-force>true</external-force>
|
||||
<force-path>ai/submodels/submodel[0]/force</force-path>
|
||||
<force-stabilized>true</force-stabilized>
|
||||
<no-roll>true</no-roll>
|
||||
<random>true</random>
|
||||
<randomness>
|
||||
<azimuth>5</azimuth>
|
||||
<elevation>5</elevation>
|
||||
<cd>0.1</cd>
|
||||
<life>0.2</life>
|
||||
</randomness>
|
||||
<collision>true</collision>
|
||||
<fuze-range>1</fuze-range>
|
||||
<impact>true</impact>
|
||||
<expiry>true</expiry>
|
||||
<impact-reports>ai/submodels/submodel[0]/report</impact-reports>
|
||||
<slaved>true</slaved>
|
||||
</submodel>
|
||||
|
||||
<submodel n="1">
|
||||
<name>testRelease</name>
|
||||
<model>Models/Geometry/null.ac</model>
|
||||
<trigger>ai/submodels/submodel[1]/trigger</trigger>
|
||||
<count>-1</count>
|
||||
<repeat>false</repeat>
|
||||
<delay>1</delay>
|
||||
<life>10</life>
|
||||
</submodel>
|
||||
|
||||
<submodel n="2">
|
||||
<name>testInitialState</name>
|
||||
<model>Models/Geometry/null.ac</model>
|
||||
<trigger>ai/submodels/submodel[2]/trigger</trigger>
|
||||
<speed>100</speed>
|
||||
<repeat>false</repeat>
|
||||
<delay>-1</delay>
|
||||
<count>-1</count>
|
||||
<aero-stabilised>false</aero-stabilised>
|
||||
<wind>true</wind>
|
||||
<offsets>
|
||||
<x-m>10</x-m>
|
||||
<y-m>6</y-m>
|
||||
<z-m>1</z-m>
|
||||
<heading-deg>30</heading-deg>
|
||||
<pitch-deg>50</pitch-deg>
|
||||
</offsets>
|
||||
<life>10</life>
|
||||
</submodel>
|
||||
</PropertyList>
|
||||
813
test_suite/test_data/EDDF.groundnet.xml
Normal file
813
test_suite/test_data/EDDF.groundnet.xml
Normal file
@@ -0,0 +1,813 @@
|
||||
<?xml version="1.0"?>
|
||||
<groundnet>
|
||||
<version>1</version>
|
||||
<parkingList>
|
||||
<Parking index="0" type="gate" name="V109" lat="N50 2.999935" lon="E8 35.484849" heading="160.6" radius="44" pushBackRoute="92" airlineCodes="" />
|
||||
<Parking index="1" type="gate" name="V115" lat="N50 2.956904" lon="E8 35.314977" heading="160.6" radius="44" pushBackRoute="96" airlineCodes="" />
|
||||
<Parking index="2" type="gate" name="V118" lat="N50 2.888276" lon="E8 35.303240" heading="341.45" radius="44" pushBackRoute="95" airlineCodes="" />
|
||||
<Parking index="3" type="gate" name="V110" lat="N50 2.932207" lon="E8 35.467774" heading="341.45" radius="44" pushBackRoute="91" airlineCodes="" />
|
||||
<Parking index="4" type="gate" name="V100" lat="N50 2.934293" lon="E8 35.797018" heading="341.45" radius="44" pushBackRoute="167" airlineCodes="" />
|
||||
<Parking index="5" type="gate" name="V95" lat="N50 2.967058" lon="E8 35.940585" heading="341.45" radius="44" pushBackRoute="166" airlineCodes="" />
|
||||
<Parking index="6" type="gate" name="V92" lat="N50 2.987622" lon="E8 36.025770" heading="341.45" radius="44" pushBackRoute="165" airlineCodes="" />
|
||||
<Parking index="7" type="gate" name="C16" lat="N50 2.970491" lon="E8 34.976214" heading="-20.5" radius="44" pushBackRoute="97" airlineCodes="" />
|
||||
<Parking index="8" type="gate" name="D4" lat="N50 3.020838" lon="E8 35.186507" heading="342.71" radius="44" pushBackRoute="177" airlineCodes="" />
|
||||
<Parking index="9" type="gate" name="E5" lat="N50 3.064577" lon="E8 35.388765" heading="342.71" radius="44" pushBackRoute="94" airlineCodes="" />
|
||||
<Parking index="10" type="gate" name="E9" lat="N50 3.093001" lon="E8 35.514331" heading="342.71" radius="44" pushBackRoute="93" airlineCodes="" />
|
||||
<Parking index="11" type="gate" name="V268" lat="N50 2.217246" lon="E8 31.436516" heading="339.3" radius="44" pushBackRoute="81" airlineCodes="" />
|
||||
<Parking index="12" type="gate" name="C4" lat="N50 3.002208" lon="E8 34.510773" heading="21.75" radius="44" pushBackRoute="102" airlineCodes="" />
|
||||
<Parking index="13" type="gate" name="B28" lat="N50 2.784223" lon="E8 34.361486" heading="298.11" radius="44" pushBackRoute="105" airlineCodes="" />
|
||||
<Parking index="14" type="gate" name="B48" lat="N50 2.829055" lon="E8 34.522248" heading="28.08" radius="44" pushBackRoute="104" airlineCodes="" />
|
||||
<Parking index="15" type="gate" name="B44" lat="N50 2.901543" lon="E8 34.574913" heading="205.71" radius="44" pushBackRoute="101" airlineCodes="" />
|
||||
<Parking index="16" type="gate" name="C8" lat="N50 2.959101" lon="E8 34.669919" heading="21.75" radius="44" pushBackRoute="100" airlineCodes="" />
|
||||
<Parking index="17" type="gate" name="C14" lat="N50 2.934648" lon="E8 34.840979" heading="340.18" radius="44" pushBackRoute="98" airlineCodes="" />
|
||||
<Parking index="18" type="gate" name="C2" lat="N50 3.000238" lon="E8 34.441947" heading="79.63" radius="44" pushBackRoute="102" airlineCodes="" />
|
||||
<Parking index="19" type="gate" name="B22" lat="N50 2.854101" lon="E8 34.270133" heading="119.89" radius="44" pushBackRoute="109" airlineCodes="" />
|
||||
<Parking index="20" type="gate" name="B23" lat="N50 2.825169" lon="E8 34.377412" heading="-84.06" radius="44" pushBackRoute="105" airlineCodes="" />
|
||||
<Parking index="21" type="gate" name="B10" lat="N50 2.940697" lon="E8 34.286900" heading="159.59" radius="44" pushBackRoute="110" airlineCodes="" />
|
||||
<Parking index="22" type="gate" name="A66" lat="N50 2.792857" lon="E8 33.631193" heading="340.34" radius="44" pushBackRoute="116" airlineCodes="" />
|
||||
<Parking index="23" type="gate" name="A54" lat="N50 2.841211" lon="E8 33.838648" heading="340.34" radius="44" pushBackRoute="117" airlineCodes="" />
|
||||
<Parking index="24" type="gate" name="A16" lat="N50 2.846693" lon="E8 34.029215" heading="113.9" radius="44" pushBackRoute="123" airlineCodes="" />
|
||||
<Parking index="25" type="gate" name="A28" lat="N50 2.695002" lon="E8 33.884392" heading="157.98" radius="44" pushBackRoute="122" airlineCodes="" />
|
||||
<Parking index="26" type="gate" name="F224" lat="N50 2.365898" lon="E8 32.469863" heading="250.54" radius="44" pushBackRoute="83" airlineCodes="" />
|
||||
<Parking index="27" type="gate" name="F211" lat="N50 2.375008" lon="E8 32.623026" heading="70.16" radius="44" pushBackRoute="83" airlineCodes="" />
|
||||
<Parking index="28" type="gate" name="F219" lat="N50 2.498238" lon="E8 32.981234" heading="70.16" radius="44" pushBackRoute="190" airlineCodes="" />
|
||||
<Parking index="29" type="gate" name="V266" lat="N50 2.237159" lon="E8 31.501546" heading="339.44" radius="44" pushBackRoute="82" airlineCodes="" />
|
||||
<Parking index="30" type="gate" name="F235" lat="N50 2.204985" lon="E8 31.785992" heading="339.44" radius="44" pushBackRoute="70" airlineCodes="" />
|
||||
<Parking index="31" type="gate" name="F231" lat="N50 2.280024" lon="E8 32.101077" heading="339.44" radius="44" pushBackRoute="69" airlineCodes="" />
|
||||
<Parking index="32" type="gate" name="V178" lat="N50 2.159443" lon="E8 32.191372" heading="159.54" radius="44" pushBackRoute="194" airlineCodes="" />
|
||||
<Parking index="33" type="gate" name="V174" lat="N50 2.199657" lon="E8 32.361192" heading="159.54" radius="44" pushBackRoute="85" airlineCodes="" />
|
||||
<Parking index="34" type="gate" name="V169" lat="N50 2.300216" lon="E8 32.746177" heading="159.54" radius="44" pushBackRoute="86" airlineCodes="" />
|
||||
<Parking index="35" type="gate" name="V164" lat="N50 2.373806" lon="E8 33.066649" heading="159.54" radius="44" pushBackRoute="190" airlineCodes="" />
|
||||
<Parking index="36" type="gate" name="V159" lat="N50 2.462450" lon="E8 33.442180" heading="159.09" radius="44" pushBackRoute="88" airlineCodes="" />
|
||||
<Parking index="37" type="gate" name="A40" lat="N50 2.646960" lon="E8 33.694767" heading="155.92" radius="44" pushBackRoute="121" airlineCodes="" />
|
||||
<Parking index="38" type="gate" name="A17" lat="N50 2.846756" lon="E8 34.142889" heading="292.36" radius="44" pushBackRoute="108" airlineCodes="" />
|
||||
<Parking index="39" type="gate" name="A1" lat="N50 2.952545" lon="E8 34.235065" heading="99.04" radius="44" pushBackRoute="110" airlineCodes="" />
|
||||
</parkingList>
|
||||
<TaxiNodes>
|
||||
<node index="40" lat="N50 2.768508" lon="E8 35.248439" isOnRunway="0" holdPointType="none" />
|
||||
<node index="41" lat="N50 2.723872" lon="E8 35.194098" isOnRunway="0" holdPointType="none" />
|
||||
<node index="42" lat="N50 2.002157" lon="E8 32.028565" isOnRunway="0" holdPointType="none" />
|
||||
<node index="43" lat="N50 1.598113" lon="E8 32.515177" isOnRunway="0" holdPointType="none" />
|
||||
<node index="44" lat="N50 1.688136" lon="E8 32.918501" isOnRunway="0" holdPointType="none" />
|
||||
<node index="45" lat="N50 1.738117" lon="E8 32.892184" isOnRunway="0" holdPointType="none" />
|
||||
<node index="46" lat="N50 2.366208" lon="E8 35.519847" isOnRunway="0" holdPointType="none" />
|
||||
<node index="47" lat="N50 2.387651" lon="E8 35.577599" isOnRunway="0" holdPointType="none" />
|
||||
<node index="48" lat="N50 2.418646" lon="E8 35.623960" isOnRunway="0" holdPointType="none" />
|
||||
<node index="49" lat="N50 2.456653" lon="E8 35.656871" isOnRunway="0" holdPointType="none" />
|
||||
<node index="50" lat="N50 2.490318" lon="E8 35.675517" isOnRunway="0" holdPointType="none" />
|
||||
<node index="51" lat="N50 2.533802" lon="E8 35.692053" isOnRunway="0" holdPointType="none" />
|
||||
<node index="52" lat="N50 2.626921" lon="E8 35.687006" isOnRunway="0" holdPointType="none" />
|
||||
<node index="53" lat="N50 2.772243" lon="E8 35.679001" isOnRunway="0" holdPointType="none" />
|
||||
<node index="54" lat="N50 2.813156" lon="E8 35.668730" isOnRunway="0" holdPointType="none" />
|
||||
<node index="55" lat="N50 2.872962" lon="E8 35.634612" isOnRunway="0" holdPointType="none" />
|
||||
<node index="56" lat="N50 2.019011" lon="E8 34.065677" isOnRunway="0" holdPointType="none" />
|
||||
<node index="57" lat="N50 1.968782" lon="E8 34.092582" isOnRunway="0" holdPointType="none" />
|
||||
<node index="58" lat="N50 2.284498" lon="E8 35.411532" isOnRunway="0" holdPointType="none" />
|
||||
<node index="59" lat="N50 2.318854" lon="E8 35.558524" isOnRunway="0" holdPointType="none" />
|
||||
<node index="60" lat="N50 2.347394" lon="E8 35.629704" isOnRunway="0" holdPointType="none" />
|
||||
<node index="61" lat="N50 2.382562" lon="E8 35.685301" isOnRunway="0" holdPointType="none" />
|
||||
<node index="62" lat="N50 2.431933" lon="E8 35.729527" isOnRunway="0" holdPointType="none" />
|
||||
<node index="63" lat="N50 2.493341" lon="E8 35.765540" isOnRunway="0" holdPointType="none" />
|
||||
<node index="64" lat="N50 2.531756" lon="E8 35.780072" isOnRunway="0" holdPointType="none" />
|
||||
<node index="65" lat="N50 2.576257" lon="E8 35.783231" isOnRunway="0" holdPointType="none" />
|
||||
<node index="66" lat="N50 2.785100" lon="E8 35.770384" isOnRunway="0" holdPointType="none" />
|
||||
<node index="67" lat="N50 2.816616" lon="E8 35.768067" isOnRunway="0" holdPointType="none" />
|
||||
<node index="68" lat="N50 2.855165" lon="E8 35.749532" isOnRunway="0" holdPointType="none" />
|
||||
<node index="69" lat="N50 2.230702" lon="E8 32.119703" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="70" lat="N50 2.156528" lon="E8 31.809707" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="71" lat="N50 2.111141" lon="E8 31.022815" isOnRunway="0" holdPointType="none" />
|
||||
<node index="72" lat="N50 2.104445" lon="E8 31.053390" isOnRunway="0" holdPointType="none" />
|
||||
<node index="73" lat="N50 2.118431" lon="E8 31.248425" isOnRunway="0" holdPointType="none" />
|
||||
<node index="74" lat="N50 2.134649" lon="E8 31.407790" isOnRunway="0" holdPointType="none" />
|
||||
<node index="75" lat="N50 2.153669" lon="E8 31.493328" isOnRunway="0" holdPointType="none" />
|
||||
<node index="76" lat="N50 2.158680" lon="E8 31.590320" isOnRunway="0" holdPointType="none" />
|
||||
<node index="77" lat="N50 2.184821" lon="E8 31.711053" isOnRunway="0" holdPointType="none" />
|
||||
<node index="78" lat="N50 2.138639" lon="E8 31.736488" isOnRunway="0" holdPointType="none" />
|
||||
<node index="79" lat="N50 2.146045" lon="E8 31.459077" isOnRunway="0" holdPointType="none" />
|
||||
<node index="80" lat="N50 2.187217" lon="E8 31.435337" isOnRunway="0" holdPointType="none" />
|
||||
<node index="81" lat="N50 2.201594" lon="E8 31.451616" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="82" lat="N50 2.218150" lon="E8 31.521140" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="83" lat="N50 2.378574" lon="E8 32.544269" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="84" lat="N50 2.119540" lon="E8 32.211832" isOnRunway="0" holdPointType="none" />
|
||||
<node index="85" lat="N50 2.161474" lon="E8 32.381569" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="86" lat="N50 2.261876" lon="E8 32.767313" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="87" lat="N50 2.334242" lon="E8 33.085543" isOnRunway="0" holdPointType="none" />
|
||||
<node index="88" lat="N50 2.422424" lon="E8 33.464592" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="89" lat="N50 2.962635" lon="E8 35.943877" isOnRunway="0" holdPointType="none" />
|
||||
<node index="90" lat="N50 2.930355" lon="E8 35.801090" isOnRunway="0" holdPointType="none" />
|
||||
<node index="91" lat="N50 2.918671" lon="E8 35.477894" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="92" lat="N50 3.013926" lon="E8 35.475427" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="93" lat="N50 3.084823" lon="E8 35.519220" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="94" lat="N50 3.043830" lon="E8 35.401102" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="95" lat="N50 2.873717" lon="E8 35.315062" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="96" lat="N50 2.973329" lon="E8 35.304268" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="97" lat="N50 2.951846" lon="E8 34.988089" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="98" lat="N50 2.915488" lon="E8 34.855981" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="99" lat="N50 2.897627" lon="E8 34.729840" isOnRunway="0" holdPointType="none" />
|
||||
<node index="100" lat="N50 2.920271" lon="E8 34.656833" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="101" lat="N50 2.939089" lon="E8 34.593759" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="102" lat="N50 2.976405" lon="E8 34.465127" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="103" lat="N50 2.747990" lon="E8 34.502624" isOnRunway="0" holdPointType="none" />
|
||||
<node index="104" lat="N50 2.792754" lon="E8 34.460763" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="105" lat="N50 2.819903" lon="E8 34.431622" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="106" lat="N50 2.645840" lon="E8 34.108153" isOnRunway="0" holdPointType="none" />
|
||||
<node index="107" lat="N50 2.714132" lon="E8 34.107406" isOnRunway="0" holdPointType="none" />
|
||||
<node index="108" lat="N50 2.831943" lon="E8 34.188566" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="109" lat="N50 2.863974" lon="E8 34.212603" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="110" lat="N50 2.923791" lon="E8 34.254066" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="111" lat="N50 2.546371" lon="E8 33.617272" isOnRunway="0" holdPointType="none" />
|
||||
<node index="112" lat="N50 2.562927" lon="E8 33.583692" isOnRunway="0" holdPointType="none" />
|
||||
<node index="113" lat="N50 2.610634" lon="E8 33.552826" isOnRunway="0" holdPointType="none" />
|
||||
<node index="114" lat="N50 2.646578" lon="E8 33.542650" isOnRunway="0" holdPointType="none" />
|
||||
<node index="115" lat="N50 2.729139" lon="E8 33.578944" isOnRunway="0" holdPointType="none" />
|
||||
<node index="116" lat="N50 2.748527" lon="E8 33.646785" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="117" lat="N50 2.801023" lon="E8 33.865967" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="118" lat="N50 2.568248" lon="E8 33.730581" isOnRunway="0" holdPointType="none" />
|
||||
<node index="119" lat="N50 2.580447" lon="E8 33.648159" isOnRunway="0" holdPointType="none" />
|
||||
<node index="120" lat="N50 2.654077" lon="E8 33.611525" isOnRunway="0" holdPointType="none" />
|
||||
<node index="121" lat="N50 2.672812" lon="E8 33.681738" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="122" lat="N50 2.714636" lon="E8 33.853373" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="123" lat="N50 2.814625" lon="E8 33.924607" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="124" lat="N50 2.580757" lon="E8 32.866928" isOnRunway="0" holdPointType="none" />
|
||||
<node index="125" lat="N50 2.607402" lon="E8 32.844502" isOnRunway="0" holdPointType="none" />
|
||||
<node index="126" lat="N50 2.642508" lon="E8 32.791240" isOnRunway="0" holdPointType="none" />
|
||||
<node index="127" lat="N50 2.666092" lon="E8 32.719475" isOnRunway="0" holdPointType="none" />
|
||||
<node index="128" lat="N50 2.671133" lon="E8 32.633694" isOnRunway="0" holdPointType="none" />
|
||||
<node index="129" lat="N50 2.638547" lon="E8 32.136389" isOnRunway="0" holdPointType="none" />
|
||||
<node index="130" lat="N50 2.633326" lon="E8 32.074997" isOnRunway="0" holdPointType="none" />
|
||||
<node index="131" lat="N50 2.573375" lon="E8 31.831956" isOnRunway="0" holdPointType="none" />
|
||||
<node index="132" lat="N50 2.134276" lon="E8 29.995441" isOnRunway="0" holdPointType="none" />
|
||||
<node index="133" lat="N50 2.263648" lon="E8 30.537065" isOnRunway="0" holdPointType="none" />
|
||||
<node index="134" lat="N50 2.129774" lon="E8 29.971337" isOnRunway="0" holdPointType="none" />
|
||||
<node index="135" lat="N50 2.133015" lon="E8 29.925371" isOnRunway="0" holdPointType="none" />
|
||||
<node index="136" lat="N50 2.146517" lon="E8 29.888655" isOnRunway="0" holdPointType="none" />
|
||||
<node index="137" lat="N50 2.696267" lon="E8 32.037025" isOnRunway="0" holdPointType="none" />
|
||||
<node index="138" lat="N50 2.171461" lon="E8 29.867013" isOnRunway="0" holdPointType="none" />
|
||||
<node index="139" lat="N50 2.081473" lon="E8 32.118503" isOnRunway="0" holdPointType="none" />
|
||||
<node index="140" lat="N50 2.047358" lon="E8 31.976352" isOnRunway="0" holdPointType="none" />
|
||||
<node index="141" lat="N50 2.323862" lon="E8 33.132875" isOnRunway="0" holdPointType="none" />
|
||||
<node index="142" lat="N50 2.315552" lon="E8 33.097108" isOnRunway="0" holdPointType="none" />
|
||||
<node index="143" lat="N50 2.298799" lon="E8 33.028902" isOnRunway="0" holdPointType="none" />
|
||||
<node index="144" lat="N50 2.240071" lon="E8 32.781490" isOnRunway="0" holdPointType="none" />
|
||||
<node index="145" lat="N50 2.146617" lon="E8 32.390895" isOnRunway="0" holdPointType="none" />
|
||||
<node index="146" lat="N50 2.105162" lon="E8 32.218547" isOnRunway="0" holdPointType="none" />
|
||||
<node index="147" lat="N50 2.507168" lon="E8 33.900910" isOnRunway="0" holdPointType="none" />
|
||||
<node index="148" lat="N50 2.478498" lon="E8 33.780101" isOnRunway="0" holdPointType="none" />
|
||||
<node index="149" lat="N50 2.452265" lon="E8 33.670862" isOnRunway="0" holdPointType="none" />
|
||||
<node index="150" lat="N50 2.404931" lon="E8 33.472427" isOnRunway="0" holdPointType="none" />
|
||||
<node index="151" lat="N50 2.716334" lon="E8 34.775263" isOnRunway="0" holdPointType="none" />
|
||||
<node index="152" lat="N50 2.664357" lon="E8 34.558436" isOnRunway="0" holdPointType="none" />
|
||||
<node index="153" lat="N50 2.549294" lon="E8 34.077749" isOnRunway="0" holdPointType="none" />
|
||||
<node index="154" lat="N50 2.813551" lon="E8 35.181499" isOnRunway="0" holdPointType="none" />
|
||||
<node index="155" lat="N50 2.730184" lon="E8 34.832643" isOnRunway="0" holdPointType="none" />
|
||||
<node index="156" lat="N50 2.840393" lon="E8 35.279110" isOnRunway="0" holdPointType="none" />
|
||||
<node index="157" lat="N50 2.835443" lon="E8 35.260718" isOnRunway="0" holdPointType="none" />
|
||||
<node index="158" lat="N50 2.832217" lon="E8 35.250756" isOnRunway="0" holdPointType="none" />
|
||||
<node index="159" lat="N50 2.903896" lon="E8 35.546206" isOnRunway="0" holdPointType="none" />
|
||||
<node index="160" lat="N50 2.890550" lon="E8 35.490847" isOnRunway="0" holdPointType="none" />
|
||||
<node index="161" lat="N50 2.851735" lon="E8 35.326780" isOnRunway="0" holdPointType="none" />
|
||||
<node index="162" lat="N50 2.924845" lon="E8 35.644838" isOnRunway="0" holdPointType="none" />
|
||||
<node index="163" lat="N50 2.915776" lon="E8 35.602059" isOnRunway="0" holdPointType="none" />
|
||||
<node index="164" lat="N50 2.895221" lon="E8 35.694028" isOnRunway="0" holdPointType="none" />
|
||||
<node index="165" lat="N50 2.976072" lon="E8 36.037339" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="166" lat="N50 2.955110" lon="E8 35.948503" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="167" lat="N50 2.921839" lon="E8 35.806025" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="168" lat="N50 2.896288" lon="E8 35.698426" isOnRunway="0" holdPointType="none" />
|
||||
<node index="169" lat="N50 2.924681" lon="E8 35.645347" isOnRunway="0" holdPointType="none" />
|
||||
<node index="170" lat="N50 3.027955" lon="E8 35.585198" isOnRunway="0" holdPointType="none" />
|
||||
<node index="171" lat="N50 3.045139" lon="E8 35.565827" isOnRunway="0" holdPointType="none" />
|
||||
<node index="172" lat="N50 3.044321" lon="E8 35.519185" isOnRunway="0" holdPointType="none" />
|
||||
<node index="173" lat="N50 3.044424" lon="E8 35.535257" isOnRunway="0" holdPointType="none" />
|
||||
<node index="174" lat="N50 2.875253" lon="E8 34.810636" isOnRunway="0" holdPointType="none" />
|
||||
<node index="175" lat="N50 2.888696" lon="E8 34.869391" isOnRunway="0" holdPointType="none" />
|
||||
<node index="176" lat="N50 2.922823" lon="E8 35.008451" isOnRunway="0" holdPointType="none" />
|
||||
<node index="177" lat="N50 2.966518" lon="E8 35.190721" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="178" lat="N50 2.990360" lon="E8 35.291932" isOnRunway="0" holdPointType="none" />
|
||||
<node index="179" lat="N50 3.019669" lon="E8 35.414054" isOnRunway="0" holdPointType="none" />
|
||||
<node index="180" lat="N50 3.030958" lon="E8 35.463399" isOnRunway="0" holdPointType="none" />
|
||||
<node index="181" lat="N50 2.819771" lon="E8 34.722454" isOnRunway="0" holdPointType="none" />
|
||||
<node index="182" lat="N50 2.844818" lon="E8 34.762262" isOnRunway="0" holdPointType="none" />
|
||||
<node index="183" lat="N50 2.691620" lon="E8 34.186239" isOnRunway="0" holdPointType="none" />
|
||||
<node index="184" lat="N50 2.763718" lon="E8 34.487916" isOnRunway="0" holdPointType="none" />
|
||||
<node index="185" lat="N50 2.538592" lon="E8 33.545312" isOnRunway="0" holdPointType="none" />
|
||||
<node index="186" lat="N50 2.552705" lon="E8 33.604424" isOnRunway="0" holdPointType="none" />
|
||||
<node index="187" lat="N50 2.573827" lon="E8 33.692887" isOnRunway="0" holdPointType="none" />
|
||||
<node index="188" lat="N50 2.672906" lon="E8 34.107857" isOnRunway="0" holdPointType="none" />
|
||||
<node index="189" lat="N50 2.321243" lon="E8 32.636606" isOnRunway="0" holdPointType="none" />
|
||||
<node index="190" lat="N50 2.401028" lon="E8 32.970175" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="191" lat="N50 2.280818" lon="E8 32.538248" isOnRunway="0" holdPointType="none" />
|
||||
<node index="192" lat="N50 2.300655" lon="E8 32.588034" isOnRunway="0" holdPointType="none" />
|
||||
<node index="193" lat="N50 2.133100" lon="E8 31.931101" isOnRunway="0" holdPointType="none" />
|
||||
<node index="194" lat="N50 2.188574" lon="E8 32.159503" isOnRunway="0" holdPointType="PushBack" />
|
||||
<node index="195" lat="N50 2.090723" lon="E8 31.753430" isOnRunway="0" holdPointType="none" />
|
||||
<node index="196" lat="N50 2.058914" lon="E8 31.636988" isOnRunway="0" holdPointType="none" />
|
||||
<node index="197" lat="N50 2.072246" lon="E8 31.689653" isOnRunway="0" holdPointType="none" />
|
||||
<node index="198" lat="N50 1.959143" lon="E8 31.691518" isOnRunway="0" holdPointType="none" />
|
||||
<node index="199" lat="N50 1.979281" lon="E8 31.691186" isOnRunway="0" holdPointType="none" />
|
||||
<node index="200" lat="N50 1.641881" lon="E8 31.694873" isOnRunway="0" holdPointType="none" />
|
||||
<node index="201" lat="N49 59.998617" lon="E8 31.711146" isOnRunway="0" holdPointType="none" />
|
||||
<node index="202" lat="N50 1.402856" lon="E8 31.697371" isOnRunway="0" holdPointType="none" />
|
||||
<node index="203" lat="N49 59.974172" lon="E8 31.709017" isOnRunway="0" holdPointType="none" />
|
||||
<node index="204" lat="N49 59.943965" lon="E8 31.668430" isOnRunway="0" holdPointType="none" />
|
||||
<node index="205" lat="N49 59.928482" lon="E8 31.646584" isOnRunway="0" holdPointType="none" />
|
||||
<node index="206" lat="N49 59.922001" lon="E8 31.625299" isOnRunway="0" holdPointType="none" />
|
||||
<node index="207" lat="N50 1.966928" lon="E8 31.639534" isOnRunway="0" holdPointType="none" />
|
||||
<node index="208" lat="N50 2.056045" lon="E8 31.623504" isOnRunway="0" holdPointType="none" />
|
||||
<node index="209" lat="N50 2.037712" lon="E8 31.555410" isOnRunway="1" holdPointType="none" />
|
||||
<node index="210" lat="N49 59.925487" lon="E8 31.577437" isOnRunway="1" holdPointType="none" />
|
||||
<node index="211" lat="N50 1.947323" lon="E8 31.556298" isOnRunway="1" holdPointType="none" />
|
||||
<node index="212" lat="N50 2.393382" lon="E8 35.154155" isOnRunway="1" holdPointType="none" />
|
||||
<node index="213" lat="N50 1.657742" lon="E8 32.074192" isOnRunway="1" holdPointType="none" />
|
||||
<node index="214" lat="N50 2.698705" lon="E8 35.184926" isOnRunway="1" holdPointType="none" />
|
||||
<node index="215" lat="N50 1.965053" lon="E8 32.114816" isOnRunway="1" holdPointType="none" />
|
||||
<node index="216" lat="N50 2.745050" lon="E8 31.999783" isOnRunway="1" holdPointType="none" />
|
||||
<node index="217" lat="N50 2.228933" lon="E8 29.842340" isOnRunway="1" holdPointType="none" />
|
||||
<node index="218" lat="N50 2.297290" lon="E8 35.231582" isOnRunway="0" holdPointType="none" />
|
||||
<node index="219" lat="N50 2.383706" lon="E8 35.179090" isOnRunway="0" holdPointType="none" />
|
||||
<node index="220" lat="N50 2.393526" lon="E8 35.154118" isOnRunway="0" holdPointType="none" />
|
||||
<node index="221" lat="N50 1.511581" lon="E8 32.153321" isOnRunway="0" holdPointType="none" />
|
||||
<node index="222" lat="N50 1.657691" lon="E8 32.073653" isOnRunway="0" holdPointType="none" />
|
||||
<node index="223" lat="N50 3.025520" lon="E8 35.475840" isOnRunway="0" holdPointType="none" />
|
||||
<node index="224" lat="N50 2.982489" lon="E8 35.305968" isOnRunway="0" holdPointType="none" />
|
||||
<node index="225" lat="N50 2.862561" lon="E8 35.311869" isOnRunway="0" holdPointType="none" />
|
||||
<node index="226" lat="N50 2.906491" lon="E8 35.476404" isOnRunway="0" holdPointType="none" />
|
||||
<node index="227" lat="N50 2.908578" lon="E8 35.805647" isOnRunway="0" holdPointType="none" />
|
||||
<node index="228" lat="N50 2.941343" lon="E8 35.949214" isOnRunway="0" holdPointType="none" />
|
||||
<node index="229" lat="N50 2.961906" lon="E8 36.034399" isOnRunway="0" holdPointType="none" />
|
||||
<node index="230" lat="N50 2.945084" lon="E8 34.985713" isOnRunway="0" holdPointType="none" />
|
||||
<node index="231" lat="N50 2.994939" lon="E8 35.194569" isOnRunway="0" holdPointType="none" />
|
||||
<node index="232" lat="N50 3.038678" lon="E8 35.396827" isOnRunway="0" holdPointType="none" />
|
||||
<node index="233" lat="N50 3.067102" lon="E8 35.522393" isOnRunway="0" holdPointType="none" />
|
||||
<node index="234" lat="N50 2.191873" lon="E8 31.446103" isOnRunway="0" holdPointType="none" />
|
||||
<node index="235" lat="N50 2.977014" lon="E8 34.500721" isOnRunway="0" holdPointType="none" />
|
||||
<node index="236" lat="N50 2.771443" lon="E8 34.385411" isOnRunway="0" holdPointType="none" />
|
||||
<node index="237" lat="N50 2.805123" lon="E8 34.509480" isOnRunway="0" holdPointType="none" />
|
||||
<node index="238" lat="N50 2.925982" lon="E8 34.586681" isOnRunway="0" holdPointType="none" />
|
||||
<node index="239" lat="N50 2.933907" lon="E8 34.659868" isOnRunway="0" holdPointType="none" />
|
||||
<node index="240" lat="N50 2.909130" lon="E8 34.850176" isOnRunway="0" holdPointType="none" />
|
||||
<node index="241" lat="N50 2.995356" lon="E8 34.415266" isOnRunway="0" holdPointType="none" />
|
||||
<node index="242" lat="N50 2.867618" lon="E8 34.246616" isOnRunway="0" holdPointType="none" />
|
||||
<node index="243" lat="N50 2.822362" lon="E8 34.404391" isOnRunway="0" holdPointType="none" />
|
||||
<node index="244" lat="N50 2.966119" lon="E8 34.277440" isOnRunway="0" holdPointType="none" />
|
||||
<node index="245" lat="N50 2.767314" lon="E8 33.640319" isOnRunway="0" holdPointType="none" />
|
||||
<node index="246" lat="N50 2.815668" lon="E8 33.847773" isOnRunway="0" holdPointType="none" />
|
||||
<node index="247" lat="N50 2.857682" lon="E8 34.004416" isOnRunway="0" holdPointType="none" />
|
||||
<node index="248" lat="N50 2.720148" lon="E8 33.874222" isOnRunway="0" holdPointType="none" />
|
||||
<node index="249" lat="N50 2.374934" lon="E8 32.495439" isOnRunway="0" holdPointType="none" />
|
||||
<node index="250" lat="N50 2.365802" lon="E8 32.597511" isOnRunway="0" holdPointType="none" />
|
||||
<node index="251" lat="N50 2.489032" lon="E8 32.955720" isOnRunway="0" holdPointType="none" />
|
||||
<node index="252" lat="N50 2.211762" lon="E8 31.511072" isOnRunway="0" holdPointType="none" />
|
||||
<node index="253" lat="N50 2.179588" lon="E8 31.795518" isOnRunway="0" holdPointType="none" />
|
||||
<node index="254" lat="N50 2.254627" lon="E8 32.110603" isOnRunway="0" holdPointType="none" />
|
||||
<node index="255" lat="N50 2.184857" lon="E8 32.181891" isOnRunway="0" holdPointType="none" />
|
||||
<node index="256" lat="N50 2.225071" lon="E8 32.351710" isOnRunway="0" holdPointType="none" />
|
||||
<node index="257" lat="N50 2.325630" lon="E8 32.736696" isOnRunway="0" holdPointType="none" />
|
||||
<node index="258" lat="N50 2.399219" lon="E8 33.057168" isOnRunway="0" holdPointType="none" />
|
||||
<node index="259" lat="N50 2.487788" lon="E8 33.432499" isOnRunway="0" holdPointType="none" />
|
||||
<node index="260" lat="N50 2.671725" lon="E8 33.683700" isOnRunway="0" holdPointType="none" />
|
||||
<node index="261" lat="N50 2.836437" lon="E8 34.167974" isOnRunway="0" holdPointType="none" />
|
||||
<node index="262" lat="N50 2.956807" lon="E8 34.208277" isOnRunway="0" holdPointType="none" />
|
||||
</TaxiNodes>
|
||||
<TaxiWaySegments>
|
||||
<arc begin="40" end="158" isPushBackRoute="0" name="L1" />
|
||||
<arc begin="158" end="40" isPushBackRoute="0" name="L1" />
|
||||
<arc begin="41" end="40" isPushBackRoute="0" name="L1" />
|
||||
<arc begin="40" end="41" isPushBackRoute="0" name="L1" />
|
||||
<arc begin="214" end="41" isPushBackRoute="0" name="L1" />
|
||||
<arc begin="41" end="214" isPushBackRoute="0" name="L1" />
|
||||
<arc begin="42" end="140" isPushBackRoute="0" name="L21" />
|
||||
<arc begin="140" end="42" isPushBackRoute="0" name="L21" />
|
||||
<arc begin="215" end="42" isPushBackRoute="0" name="L21" />
|
||||
<arc begin="42" end="215" isPushBackRoute="0" name="L21" />
|
||||
<arc begin="43" end="202" isPushBackRoute="0" name="S" />
|
||||
<arc begin="202" end="43" isPushBackRoute="0" name="S" />
|
||||
<arc begin="44" end="43" isPushBackRoute="0" name="S" />
|
||||
<arc begin="43" end="44" isPushBackRoute="0" name="S" />
|
||||
<arc begin="45" end="44" isPushBackRoute="0" name="S" />
|
||||
<arc begin="44" end="45" isPushBackRoute="0" name="S" />
|
||||
<arc begin="56" end="45" isPushBackRoute="0" name="R" />
|
||||
<arc begin="45" end="56" isPushBackRoute="0" name="R" />
|
||||
<arc begin="46" end="56" isPushBackRoute="0" name="R" />
|
||||
<arc begin="56" end="46" isPushBackRoute="0" name="R" />
|
||||
<arc begin="47" end="46" isPushBackRoute="0" name="R" />
|
||||
<arc begin="46" end="47" isPushBackRoute="0" name="R" />
|
||||
<arc begin="48" end="47" isPushBackRoute="0" name="R" />
|
||||
<arc begin="47" end="48" isPushBackRoute="0" name="R" />
|
||||
<arc begin="49" end="48" isPushBackRoute="0" name="R" />
|
||||
<arc begin="48" end="49" isPushBackRoute="0" name="R" />
|
||||
<arc begin="50" end="49" isPushBackRoute="0" name="R" />
|
||||
<arc begin="49" end="50" isPushBackRoute="0" name="R" />
|
||||
<arc begin="51" end="50" isPushBackRoute="0" name="R" />
|
||||
<arc begin="50" end="51" isPushBackRoute="0" name="R" />
|
||||
<arc begin="52" end="51" isPushBackRoute="0" name="R" />
|
||||
<arc begin="51" end="52" isPushBackRoute="0" name="R" />
|
||||
<arc begin="53" end="52" isPushBackRoute="0" name="R" />
|
||||
<arc begin="52" end="53" isPushBackRoute="0" name="R" />
|
||||
<arc begin="54" end="53" isPushBackRoute="0" name="R" />
|
||||
<arc begin="53" end="54" isPushBackRoute="0" name="R" />
|
||||
<arc begin="55" end="54" isPushBackRoute="0" name="R" />
|
||||
<arc begin="54" end="55" isPushBackRoute="0" name="R" />
|
||||
<arc begin="163" end="55" isPushBackRoute="0" name="R" />
|
||||
<arc begin="55" end="163" isPushBackRoute="0" name="R" />
|
||||
<arc begin="57" end="56" isPushBackRoute="0" name="S" />
|
||||
<arc begin="56" end="57" isPushBackRoute="0" name="S" />
|
||||
<arc begin="58" end="57" isPushBackRoute="0" name="S" />
|
||||
<arc begin="57" end="58" isPushBackRoute="0" name="S" />
|
||||
<arc begin="59" end="58" isPushBackRoute="0" name="S" />
|
||||
<arc begin="58" end="59" isPushBackRoute="0" name="S" />
|
||||
<arc begin="60" end="59" isPushBackRoute="0" name="S" />
|
||||
<arc begin="59" end="60" isPushBackRoute="0" name="S" />
|
||||
<arc begin="61" end="60" isPushBackRoute="0" name="S" />
|
||||
<arc begin="60" end="61" isPushBackRoute="0" name="S" />
|
||||
<arc begin="62" end="61" isPushBackRoute="0" name="S" />
|
||||
<arc begin="61" end="62" isPushBackRoute="0" name="S" />
|
||||
<arc begin="63" end="62" isPushBackRoute="0" name="S" />
|
||||
<arc begin="62" end="63" isPushBackRoute="0" name="S" />
|
||||
<arc begin="64" end="63" isPushBackRoute="0" name="S" />
|
||||
<arc begin="63" end="64" isPushBackRoute="0" name="S" />
|
||||
<arc begin="65" end="64" isPushBackRoute="0" name="S" />
|
||||
<arc begin="64" end="65" isPushBackRoute="0" name="S" />
|
||||
<arc begin="66" end="65" isPushBackRoute="0" name="S" />
|
||||
<arc begin="65" end="66" isPushBackRoute="0" name="S" />
|
||||
<arc begin="67" end="66" isPushBackRoute="0" name="S" />
|
||||
<arc begin="66" end="67" isPushBackRoute="0" name="S" />
|
||||
<arc begin="68" end="67" isPushBackRoute="0" name="S" />
|
||||
<arc begin="67" end="68" isPushBackRoute="0" name="S" />
|
||||
<arc begin="168" end="68" isPushBackRoute="0" name="S" />
|
||||
<arc begin="68" end="168" isPushBackRoute="0" name="S" />
|
||||
<arc begin="69" end="194" isPushBackRoute="0" name="NN" />
|
||||
<arc begin="194" end="69" isPushBackRoute="0" name="NN" />
|
||||
<arc begin="70" end="69" isPushBackRoute="0" name="NN" />
|
||||
<arc begin="69" end="70" isPushBackRoute="0" name="NN" />
|
||||
<arc begin="78" end="70" isPushBackRoute="0" name="NN" />
|
||||
<arc begin="70" end="78" isPushBackRoute="0" name="NN" />
|
||||
<arc begin="71" end="133" isPushBackRoute="0" name="P1" />
|
||||
<arc begin="133" end="71" isPushBackRoute="0" name="P1" />
|
||||
<arc begin="72" end="71" isPushBackRoute="0" name="P1" />
|
||||
<arc begin="71" end="72" isPushBackRoute="0" name="P1" />
|
||||
<arc begin="73" end="72" isPushBackRoute="0" name="P1" />
|
||||
<arc begin="72" end="73" isPushBackRoute="0" name="P1" />
|
||||
<arc begin="74" end="73" isPushBackRoute="0" name="P1" />
|
||||
<arc begin="73" end="74" isPushBackRoute="0" name="P1" />
|
||||
<arc begin="79" end="74" isPushBackRoute="0" name="P1" />
|
||||
<arc begin="74" end="79" isPushBackRoute="0" name="P1" />
|
||||
<arc begin="75" end="79" isPushBackRoute="0" name="P1" />
|
||||
<arc begin="79" end="75" isPushBackRoute="0" name="P1" />
|
||||
<arc begin="76" end="75" isPushBackRoute="0" name="P1" />
|
||||
<arc begin="75" end="76" isPushBackRoute="0" name="P1" />
|
||||
<arc begin="77" end="76" isPushBackRoute="0" name="P1" />
|
||||
<arc begin="76" end="77" isPushBackRoute="0" name="P1" />
|
||||
<arc begin="78" end="77" isPushBackRoute="0" name="P1" />
|
||||
<arc begin="77" end="78" isPushBackRoute="0" name="P1" />
|
||||
<arc begin="80" end="79" isPushBackRoute="0" name="N19" />
|
||||
<arc begin="79" end="80" isPushBackRoute="0" name="N19" />
|
||||
<arc begin="81" end="80" isPushBackRoute="0" name="N19" />
|
||||
<arc begin="80" end="81" isPushBackRoute="0" name="N19" />
|
||||
<arc begin="82" end="81" isPushBackRoute="0" name="N19" />
|
||||
<arc begin="81" end="82" isPushBackRoute="0" name="N19" />
|
||||
<arc begin="83" end="192" isPushBackRoute="0" name="N14" />
|
||||
<arc begin="192" end="83" isPushBackRoute="0" name="N14" />
|
||||
<arc begin="84" end="146" isPushBackRoute="0" name="" />
|
||||
<arc begin="146" end="84" isPushBackRoute="0" name="" />
|
||||
<arc begin="85" end="145" isPushBackRoute="0" name="" />
|
||||
<arc begin="145" end="85" isPushBackRoute="0" name="" />
|
||||
<arc begin="86" end="144" isPushBackRoute="0" name="" />
|
||||
<arc begin="144" end="86" isPushBackRoute="0" name="" />
|
||||
<arc begin="87" end="142" isPushBackRoute="0" name="" />
|
||||
<arc begin="142" end="87" isPushBackRoute="0" name="" />
|
||||
<arc begin="88" end="150" isPushBackRoute="0" name="" />
|
||||
<arc begin="150" end="88" isPushBackRoute="0" name="" />
|
||||
<arc begin="89" end="166" isPushBackRoute="0" name="" />
|
||||
<arc begin="166" end="89" isPushBackRoute="0" name="" />
|
||||
<arc begin="90" end="167" isPushBackRoute="0" name="" />
|
||||
<arc begin="167" end="90" isPushBackRoute="0" name="" />
|
||||
<arc begin="91" end="160" isPushBackRoute="0" name="" />
|
||||
<arc begin="160" end="91" isPushBackRoute="0" name="" />
|
||||
<arc begin="92" end="180" isPushBackRoute="0" name="" />
|
||||
<arc begin="180" end="92" isPushBackRoute="0" name="" />
|
||||
<arc begin="93" end="173" isPushBackRoute="0" name="" />
|
||||
<arc begin="173" end="93" isPushBackRoute="0" name="" />
|
||||
<arc begin="94" end="179" isPushBackRoute="0" name="" />
|
||||
<arc begin="179" end="94" isPushBackRoute="0" name="" />
|
||||
<arc begin="95" end="161" isPushBackRoute="0" name="" />
|
||||
<arc begin="161" end="95" isPushBackRoute="0" name="" />
|
||||
<arc begin="96" end="178" isPushBackRoute="0" name="" />
|
||||
<arc begin="178" end="96" isPushBackRoute="0" name="" />
|
||||
<arc begin="177" end="157" isPushBackRoute="0" name="N1" />
|
||||
<arc begin="157" end="177" isPushBackRoute="0" name="N1" />
|
||||
<arc begin="97" end="176" isPushBackRoute="0" name="" />
|
||||
<arc begin="176" end="97" isPushBackRoute="0" name="" />
|
||||
<arc begin="98" end="175" isPushBackRoute="0" name="" />
|
||||
<arc begin="175" end="98" isPushBackRoute="0" name="" />
|
||||
<arc begin="182" end="155" isPushBackRoute="0" name="N3" />
|
||||
<arc begin="155" end="182" isPushBackRoute="0" name="N3" />
|
||||
<arc begin="99" end="182" isPushBackRoute="0" name="N3" />
|
||||
<arc begin="182" end="99" isPushBackRoute="0" name="N3" />
|
||||
<arc begin="100" end="99" isPushBackRoute="0" name="N3" />
|
||||
<arc begin="99" end="100" isPushBackRoute="0" name="N3" />
|
||||
<arc begin="101" end="100" isPushBackRoute="0" name="N3" />
|
||||
<arc begin="100" end="101" isPushBackRoute="0" name="N3" />
|
||||
<arc begin="102" end="101" isPushBackRoute="0" name="N3" />
|
||||
<arc begin="101" end="102" isPushBackRoute="0" name="N3" />
|
||||
<arc begin="103" end="152" isPushBackRoute="0" name="N4" />
|
||||
<arc begin="152" end="103" isPushBackRoute="0" name="N4" />
|
||||
<arc begin="184" end="103" isPushBackRoute="0" name="N4" />
|
||||
<arc begin="103" end="184" isPushBackRoute="0" name="N4" />
|
||||
<arc begin="104" end="184" isPushBackRoute="0" name="N4" />
|
||||
<arc begin="184" end="104" isPushBackRoute="0" name="N4" />
|
||||
<arc begin="105" end="104" isPushBackRoute="0" name="N4" />
|
||||
<arc begin="104" end="105" isPushBackRoute="0" name="N4" />
|
||||
<arc begin="106" end="153" isPushBackRoute="0" name="N5" />
|
||||
<arc begin="153" end="106" isPushBackRoute="0" name="N5" />
|
||||
<arc begin="188" end="106" isPushBackRoute="0" name="N5" />
|
||||
<arc begin="106" end="188" isPushBackRoute="0" name="N5" />
|
||||
<arc begin="107" end="188" isPushBackRoute="0" name="N5" />
|
||||
<arc begin="188" end="107" isPushBackRoute="0" name="N5" />
|
||||
<arc begin="108" end="107" isPushBackRoute="0" name="N5" />
|
||||
<arc begin="107" end="108" isPushBackRoute="0" name="N5" />
|
||||
<arc begin="109" end="108" isPushBackRoute="0" name="N5" />
|
||||
<arc begin="108" end="109" isPushBackRoute="0" name="N5" />
|
||||
<arc begin="110" end="109" isPushBackRoute="0" name="N5" />
|
||||
<arc begin="109" end="110" isPushBackRoute="0" name="N5" />
|
||||
<arc begin="111" end="149" isPushBackRoute="0" name="N8" />
|
||||
<arc begin="149" end="111" isPushBackRoute="0" name="N8" />
|
||||
<arc begin="186" end="111" isPushBackRoute="0" name="N8" />
|
||||
<arc begin="111" end="186" isPushBackRoute="0" name="N8" />
|
||||
<arc begin="112" end="186" isPushBackRoute="0" name="N8" />
|
||||
<arc begin="186" end="112" isPushBackRoute="0" name="N8" />
|
||||
<arc begin="113" end="112" isPushBackRoute="0" name="N8" />
|
||||
<arc begin="112" end="113" isPushBackRoute="0" name="N8" />
|
||||
<arc begin="114" end="113" isPushBackRoute="0" name="N8" />
|
||||
<arc begin="113" end="114" isPushBackRoute="0" name="N8" />
|
||||
<arc begin="115" end="114" isPushBackRoute="0" name="N8" />
|
||||
<arc begin="114" end="115" isPushBackRoute="0" name="N8" />
|
||||
<arc begin="116" end="115" isPushBackRoute="0" name="N8" />
|
||||
<arc begin="115" end="116" isPushBackRoute="0" name="N8" />
|
||||
<arc begin="117" end="116" isPushBackRoute="0" name="N8" />
|
||||
<arc begin="116" end="117" isPushBackRoute="0" name="N8" />
|
||||
<arc begin="123" end="117" isPushBackRoute="0" name="N8" />
|
||||
<arc begin="117" end="123" isPushBackRoute="0" name="N8" />
|
||||
<arc begin="118" end="148" isPushBackRoute="0" name="N7" />
|
||||
<arc begin="148" end="118" isPushBackRoute="0" name="N7" />
|
||||
<arc begin="187" end="118" isPushBackRoute="0" name="N7" />
|
||||
<arc begin="118" end="187" isPushBackRoute="0" name="N7" />
|
||||
<arc begin="119" end="187" isPushBackRoute="0" name="N7" />
|
||||
<arc begin="187" end="119" isPushBackRoute="0" name="N7" />
|
||||
<arc begin="120" end="119" isPushBackRoute="0" name="N7" />
|
||||
<arc begin="119" end="120" isPushBackRoute="0" name="N7" />
|
||||
<arc begin="121" end="120" isPushBackRoute="0" name="N7" />
|
||||
<arc begin="120" end="121" isPushBackRoute="0" name="N7" />
|
||||
<arc begin="122" end="121" isPushBackRoute="0" name="N7" />
|
||||
<arc begin="121" end="122" isPushBackRoute="0" name="N7" />
|
||||
<arc begin="123" end="122" isPushBackRoute="0" name="N7" />
|
||||
<arc begin="122" end="123" isPushBackRoute="0" name="N7" />
|
||||
<arc begin="137" end="130" isPushBackRoute="0" name="P4" />
|
||||
<arc begin="130" end="137" isPushBackRoute="0" name="P4" />
|
||||
<arc begin="190" end="143" isPushBackRoute="0" name="N11" />
|
||||
<arc begin="143" end="190" isPushBackRoute="0" name="N11" />
|
||||
<arc begin="124" end="190" isPushBackRoute="0" name="N11" />
|
||||
<arc begin="190" end="124" isPushBackRoute="0" name="N11" />
|
||||
<arc begin="125" end="124" isPushBackRoute="0" name="P" />
|
||||
<arc begin="124" end="125" isPushBackRoute="0" name="P" />
|
||||
<arc begin="126" end="125" isPushBackRoute="0" name="P" />
|
||||
<arc begin="125" end="126" isPushBackRoute="0" name="P" />
|
||||
<arc begin="127" end="126" isPushBackRoute="0" name="P" />
|
||||
<arc begin="126" end="127" isPushBackRoute="0" name="P" />
|
||||
<arc begin="128" end="127" isPushBackRoute="0" name="P" />
|
||||
<arc begin="127" end="128" isPushBackRoute="0" name="P" />
|
||||
<arc begin="129" end="128" isPushBackRoute="0" name="P" />
|
||||
<arc begin="128" end="129" isPushBackRoute="0" name="P" />
|
||||
<arc begin="130" end="129" isPushBackRoute="0" name="P" />
|
||||
<arc begin="129" end="130" isPushBackRoute="0" name="P" />
|
||||
<arc begin="131" end="130" isPushBackRoute="0" name="P" />
|
||||
<arc begin="130" end="131" isPushBackRoute="0" name="P" />
|
||||
<arc begin="132" end="133" isPushBackRoute="0" name="P" />
|
||||
<arc begin="133" end="132" isPushBackRoute="0" name="P" />
|
||||
<arc begin="133" end="131" isPushBackRoute="0" name="P" />
|
||||
<arc begin="131" end="133" isPushBackRoute="0" name="P" />
|
||||
<arc begin="134" end="132" isPushBackRoute="0" name="P" />
|
||||
<arc begin="132" end="134" isPushBackRoute="0" name="P" />
|
||||
<arc begin="135" end="134" isPushBackRoute="0" name="P" />
|
||||
<arc begin="134" end="135" isPushBackRoute="0" name="P" />
|
||||
<arc begin="136" end="135" isPushBackRoute="0" name="P" />
|
||||
<arc begin="135" end="136" isPushBackRoute="0" name="P" />
|
||||
<arc begin="138" end="136" isPushBackRoute="0" name="P" />
|
||||
<arc begin="136" end="138" isPushBackRoute="0" name="P" />
|
||||
<arc begin="216" end="137" isPushBackRoute="0" name="P" />
|
||||
<arc begin="137" end="216" isPushBackRoute="0" name="P" />
|
||||
<arc begin="217" end="138" isPushBackRoute="0" name="P" />
|
||||
<arc begin="138" end="217" isPushBackRoute="0" name="P" />
|
||||
<arc begin="199" end="207" isPushBackRoute="0" name="L" />
|
||||
<arc begin="207" end="199" isPushBackRoute="0" name="L" />
|
||||
<arc begin="139" end="140" isPushBackRoute="0" name="L" />
|
||||
<arc begin="140" end="139" isPushBackRoute="0" name="L" />
|
||||
<arc begin="140" end="199" isPushBackRoute="0" name="L" />
|
||||
<arc begin="199" end="140" isPushBackRoute="0" name="L" />
|
||||
<arc begin="141" end="142" isPushBackRoute="0" name="L" />
|
||||
<arc begin="142" end="141" isPushBackRoute="0" name="L" />
|
||||
<arc begin="142" end="143" isPushBackRoute="0" name="L" />
|
||||
<arc begin="143" end="142" isPushBackRoute="0" name="L" />
|
||||
<arc begin="143" end="144" isPushBackRoute="0" name="L" />
|
||||
<arc begin="144" end="143" isPushBackRoute="0" name="L" />
|
||||
<arc begin="144" end="145" isPushBackRoute="0" name="L" />
|
||||
<arc begin="145" end="144" isPushBackRoute="0" name="L" />
|
||||
<arc begin="145" end="146" isPushBackRoute="0" name="L" />
|
||||
<arc begin="146" end="145" isPushBackRoute="0" name="L" />
|
||||
<arc begin="146" end="139" isPushBackRoute="0" name="L" />
|
||||
<arc begin="139" end="146" isPushBackRoute="0" name="L" />
|
||||
<arc begin="147" end="148" isPushBackRoute="0" name="L" />
|
||||
<arc begin="148" end="147" isPushBackRoute="0" name="L" />
|
||||
<arc begin="148" end="149" isPushBackRoute="0" name="L" />
|
||||
<arc begin="149" end="148" isPushBackRoute="0" name="L" />
|
||||
<arc begin="149" end="150" isPushBackRoute="0" name="L" />
|
||||
<arc begin="150" end="149" isPushBackRoute="0" name="L" />
|
||||
<arc begin="150" end="141" isPushBackRoute="0" name="L" />
|
||||
<arc begin="141" end="150" isPushBackRoute="0" name="L" />
|
||||
<arc begin="151" end="152" isPushBackRoute="0" name="L" />
|
||||
<arc begin="152" end="151" isPushBackRoute="0" name="L" />
|
||||
<arc begin="152" end="153" isPushBackRoute="0" name="L" />
|
||||
<arc begin="153" end="152" isPushBackRoute="0" name="L" />
|
||||
<arc begin="153" end="147" isPushBackRoute="0" name="L" />
|
||||
<arc begin="147" end="153" isPushBackRoute="0" name="L" />
|
||||
<arc begin="154" end="155" isPushBackRoute="0" name="L" />
|
||||
<arc begin="155" end="154" isPushBackRoute="0" name="L" />
|
||||
<arc begin="155" end="151" isPushBackRoute="0" name="L" />
|
||||
<arc begin="151" end="155" isPushBackRoute="0" name="L" />
|
||||
<arc begin="156" end="157" isPushBackRoute="0" name="L" />
|
||||
<arc begin="157" end="156" isPushBackRoute="0" name="L" />
|
||||
<arc begin="157" end="158" isPushBackRoute="0" name="L" />
|
||||
<arc begin="158" end="157" isPushBackRoute="0" name="L" />
|
||||
<arc begin="158" end="154" isPushBackRoute="0" name="L" />
|
||||
<arc begin="154" end="158" isPushBackRoute="0" name="L" />
|
||||
<arc begin="159" end="160" isPushBackRoute="0" name="L" />
|
||||
<arc begin="160" end="159" isPushBackRoute="0" name="L" />
|
||||
<arc begin="160" end="161" isPushBackRoute="0" name="L" />
|
||||
<arc begin="161" end="160" isPushBackRoute="0" name="L" />
|
||||
<arc begin="161" end="156" isPushBackRoute="0" name="L" />
|
||||
<arc begin="156" end="161" isPushBackRoute="0" name="L" />
|
||||
<arc begin="162" end="163" isPushBackRoute="0" name="L" />
|
||||
<arc begin="163" end="162" isPushBackRoute="0" name="L" />
|
||||
<arc begin="163" end="159" isPushBackRoute="0" name="L" />
|
||||
<arc begin="159" end="163" isPushBackRoute="0" name="L" />
|
||||
<arc begin="169" end="162" isPushBackRoute="0" name="L" />
|
||||
<arc begin="162" end="169" isPushBackRoute="0" name="L" />
|
||||
<arc begin="164" end="169" isPushBackRoute="0" name="L" />
|
||||
<arc begin="169" end="164" isPushBackRoute="0" name="L" />
|
||||
<arc begin="165" end="166" isPushBackRoute="0" name="L" />
|
||||
<arc begin="166" end="165" isPushBackRoute="0" name="L" />
|
||||
<arc begin="166" end="167" isPushBackRoute="0" name="L" />
|
||||
<arc begin="167" end="166" isPushBackRoute="0" name="L" />
|
||||
<arc begin="167" end="168" isPushBackRoute="0" name="L" />
|
||||
<arc begin="168" end="167" isPushBackRoute="0" name="L" />
|
||||
<arc begin="168" end="164" isPushBackRoute="0" name="L" />
|
||||
<arc begin="164" end="168" isPushBackRoute="0" name="L" />
|
||||
<arc begin="170" end="169" isPushBackRoute="0" name="N" />
|
||||
<arc begin="169" end="170" isPushBackRoute="0" name="N" />
|
||||
<arc begin="171" end="170" isPushBackRoute="0" name="N" />
|
||||
<arc begin="170" end="171" isPushBackRoute="0" name="N" />
|
||||
<arc begin="172" end="173" isPushBackRoute="0" name="N" />
|
||||
<arc begin="173" end="172" isPushBackRoute="0" name="N" />
|
||||
<arc begin="173" end="171" isPushBackRoute="0" name="N" />
|
||||
<arc begin="171" end="173" isPushBackRoute="0" name="N" />
|
||||
<arc begin="174" end="175" isPushBackRoute="0" name="N" />
|
||||
<arc begin="175" end="174" isPushBackRoute="0" name="N" />
|
||||
<arc begin="175" end="176" isPushBackRoute="0" name="N" />
|
||||
<arc begin="176" end="175" isPushBackRoute="0" name="N" />
|
||||
<arc begin="176" end="177" isPushBackRoute="0" name="N" />
|
||||
<arc begin="177" end="176" isPushBackRoute="0" name="N" />
|
||||
<arc begin="177" end="178" isPushBackRoute="0" name="N" />
|
||||
<arc begin="178" end="177" isPushBackRoute="0" name="N" />
|
||||
<arc begin="178" end="179" isPushBackRoute="0" name="N" />
|
||||
<arc begin="179" end="178" isPushBackRoute="0" name="N" />
|
||||
<arc begin="179" end="180" isPushBackRoute="0" name="N" />
|
||||
<arc begin="180" end="179" isPushBackRoute="0" name="N" />
|
||||
<arc begin="180" end="172" isPushBackRoute="0" name="N" />
|
||||
<arc begin="172" end="180" isPushBackRoute="0" name="N" />
|
||||
<arc begin="181" end="182" isPushBackRoute="0" name="N" />
|
||||
<arc begin="182" end="181" isPushBackRoute="0" name="N" />
|
||||
<arc begin="182" end="174" isPushBackRoute="0" name="N" />
|
||||
<arc begin="174" end="182" isPushBackRoute="0" name="N" />
|
||||
<arc begin="183" end="184" isPushBackRoute="0" name="N" />
|
||||
<arc begin="184" end="183" isPushBackRoute="0" name="N" />
|
||||
<arc begin="184" end="181" isPushBackRoute="0" name="N" />
|
||||
<arc begin="181" end="184" isPushBackRoute="0" name="N" />
|
||||
<arc begin="185" end="186" isPushBackRoute="0" name="N" />
|
||||
<arc begin="186" end="185" isPushBackRoute="0" name="N" />
|
||||
<arc begin="186" end="187" isPushBackRoute="0" name="N" />
|
||||
<arc begin="187" end="186" isPushBackRoute="0" name="N" />
|
||||
<arc begin="187" end="188" isPushBackRoute="0" name="N" />
|
||||
<arc begin="188" end="187" isPushBackRoute="0" name="N" />
|
||||
<arc begin="188" end="183" isPushBackRoute="0" name="N" />
|
||||
<arc begin="183" end="188" isPushBackRoute="0" name="N" />
|
||||
<arc begin="189" end="190" isPushBackRoute="0" name="N" />
|
||||
<arc begin="190" end="189" isPushBackRoute="0" name="N" />
|
||||
<arc begin="190" end="185" isPushBackRoute="0" name="N" />
|
||||
<arc begin="185" end="190" isPushBackRoute="0" name="N" />
|
||||
<arc begin="191" end="192" isPushBackRoute="0" name="N" />
|
||||
<arc begin="192" end="191" isPushBackRoute="0" name="N" />
|
||||
<arc begin="192" end="189" isPushBackRoute="0" name="N" />
|
||||
<arc begin="189" end="192" isPushBackRoute="0" name="N" />
|
||||
<arc begin="193" end="194" isPushBackRoute="0" name="N" />
|
||||
<arc begin="194" end="193" isPushBackRoute="0" name="N" />
|
||||
<arc begin="194" end="191" isPushBackRoute="0" name="N" />
|
||||
<arc begin="191" end="194" isPushBackRoute="0" name="N" />
|
||||
<arc begin="195" end="193" isPushBackRoute="0" name="N" />
|
||||
<arc begin="193" end="195" isPushBackRoute="0" name="N" />
|
||||
<arc begin="197" end="195" isPushBackRoute="0" name="N" />
|
||||
<arc begin="195" end="197" isPushBackRoute="0" name="N" />
|
||||
<arc begin="196" end="197" isPushBackRoute="0" name="N" />
|
||||
<arc begin="197" end="196" isPushBackRoute="0" name="N" />
|
||||
<arc begin="198" end="199" isPushBackRoute="0" name="Y" />
|
||||
<arc begin="199" end="198" isPushBackRoute="0" name="Y" />
|
||||
<arc begin="199" end="197" isPushBackRoute="0" name="Y" />
|
||||
<arc begin="197" end="199" isPushBackRoute="0" name="Y" />
|
||||
<arc begin="200" end="198" isPushBackRoute="0" name="Y" />
|
||||
<arc begin="198" end="200" isPushBackRoute="0" name="Y" />
|
||||
<arc begin="201" end="202" isPushBackRoute="0" name="Y" />
|
||||
<arc begin="202" end="201" isPushBackRoute="0" name="Y" />
|
||||
<arc begin="202" end="200" isPushBackRoute="0" name="Y" />
|
||||
<arc begin="200" end="202" isPushBackRoute="0" name="Y" />
|
||||
<arc begin="203" end="201" isPushBackRoute="0" name="Y" />
|
||||
<arc begin="201" end="203" isPushBackRoute="0" name="Y" />
|
||||
<arc begin="204" end="203" isPushBackRoute="0" name="Y" />
|
||||
<arc begin="203" end="204" isPushBackRoute="0" name="Y" />
|
||||
<arc begin="205" end="204" isPushBackRoute="0" name="" />
|
||||
<arc begin="204" end="205" isPushBackRoute="0" name="" />
|
||||
<arc begin="206" end="205" isPushBackRoute="0" name="" />
|
||||
<arc begin="205" end="206" isPushBackRoute="0" name="" />
|
||||
<arc begin="210" end="206" isPushBackRoute="0" name="" />
|
||||
<arc begin="206" end="210" isPushBackRoute="0" name="" />
|
||||
<arc begin="211" end="207" isPushBackRoute="0" name="L" />
|
||||
<arc begin="207" end="211" isPushBackRoute="0" name="L" />
|
||||
<arc begin="209" end="208" isPushBackRoute="0" name="N" />
|
||||
<arc begin="208" end="209" isPushBackRoute="0" name="N" />
|
||||
<arc begin="219" end="218" isPushBackRoute="0" name="R3" />
|
||||
<arc begin="218" end="219" isPushBackRoute="0" name="R3" />
|
||||
<arc begin="220" end="219" isPushBackRoute="0" name="R3" />
|
||||
<arc begin="219" end="220" isPushBackRoute="0" name="R3" />
|
||||
<arc begin="222" end="221" isPushBackRoute="0" name="R17" />
|
||||
<arc begin="221" end="222" isPushBackRoute="0" name="R17" />
|
||||
<arc begin="0" end="223" isPushBackRoute="1" name="V109" />
|
||||
<arc begin="223" end="0" isPushBackRoute="1" name="V109" />
|
||||
<arc begin="223" end="92" isPushBackRoute="1" name="V109" />
|
||||
<arc begin="92" end="223" isPushBackRoute="1" name="V109" />
|
||||
<arc begin="1" end="224" isPushBackRoute="1" name="V115" />
|
||||
<arc begin="224" end="1" isPushBackRoute="1" name="V115" />
|
||||
<arc begin="224" end="96" isPushBackRoute="1" name="V115" />
|
||||
<arc begin="96" end="224" isPushBackRoute="1" name="V115" />
|
||||
<arc begin="2" end="225" isPushBackRoute="1" name="V118" />
|
||||
<arc begin="225" end="2" isPushBackRoute="1" name="V118" />
|
||||
<arc begin="225" end="95" isPushBackRoute="1" name="V118" />
|
||||
<arc begin="95" end="225" isPushBackRoute="1" name="V118" />
|
||||
<arc begin="3" end="226" isPushBackRoute="1" name="V110" />
|
||||
<arc begin="226" end="3" isPushBackRoute="1" name="V110" />
|
||||
<arc begin="226" end="91" isPushBackRoute="1" name="V110" />
|
||||
<arc begin="91" end="226" isPushBackRoute="1" name="V110" />
|
||||
<arc begin="4" end="227" isPushBackRoute="1" name="V100" />
|
||||
<arc begin="227" end="4" isPushBackRoute="1" name="V100" />
|
||||
<arc begin="227" end="167" isPushBackRoute="1" name="V100" />
|
||||
<arc begin="167" end="227" isPushBackRoute="1" name="V100" />
|
||||
<arc begin="5" end="228" isPushBackRoute="1" name="V95" />
|
||||
<arc begin="228" end="5" isPushBackRoute="1" name="V95" />
|
||||
<arc begin="228" end="166" isPushBackRoute="1" name="V95" />
|
||||
<arc begin="166" end="228" isPushBackRoute="1" name="V95" />
|
||||
<arc begin="6" end="229" isPushBackRoute="1" name="V92" />
|
||||
<arc begin="229" end="6" isPushBackRoute="1" name="V92" />
|
||||
<arc begin="229" end="165" isPushBackRoute="1" name="V92" />
|
||||
<arc begin="165" end="229" isPushBackRoute="1" name="V92" />
|
||||
<arc begin="7" end="230" isPushBackRoute="1" name="C16" />
|
||||
<arc begin="230" end="7" isPushBackRoute="1" name="C16" />
|
||||
<arc begin="230" end="97" isPushBackRoute="1" name="C16" />
|
||||
<arc begin="97" end="230" isPushBackRoute="1" name="C16" />
|
||||
<arc begin="8" end="231" isPushBackRoute="1" name="D4" />
|
||||
<arc begin="231" end="8" isPushBackRoute="1" name="D4" />
|
||||
<arc begin="231" end="177" isPushBackRoute="1" name="D4" />
|
||||
<arc begin="177" end="231" isPushBackRoute="1" name="D4" />
|
||||
<arc begin="9" end="232" isPushBackRoute="1" name="E5" />
|
||||
<arc begin="232" end="9" isPushBackRoute="1" name="E5" />
|
||||
<arc begin="232" end="94" isPushBackRoute="1" name="E5" />
|
||||
<arc begin="94" end="232" isPushBackRoute="1" name="E5" />
|
||||
<arc begin="10" end="233" isPushBackRoute="1" name="E9" />
|
||||
<arc begin="233" end="10" isPushBackRoute="1" name="E9" />
|
||||
<arc begin="233" end="93" isPushBackRoute="1" name="E9" />
|
||||
<arc begin="93" end="233" isPushBackRoute="1" name="E9" />
|
||||
<arc begin="11" end="234" isPushBackRoute="1" name="V268" />
|
||||
<arc begin="234" end="11" isPushBackRoute="1" name="V268" />
|
||||
<arc begin="234" end="81" isPushBackRoute="1" name="V268" />
|
||||
<arc begin="81" end="234" isPushBackRoute="1" name="V268" />
|
||||
<arc begin="12" end="235" isPushBackRoute="1" name="C4" />
|
||||
<arc begin="235" end="12" isPushBackRoute="1" name="C4" />
|
||||
<arc begin="235" end="102" isPushBackRoute="1" name="C4" />
|
||||
<arc begin="102" end="235" isPushBackRoute="1" name="C4" />
|
||||
<arc begin="13" end="236" isPushBackRoute="1" name="B28" />
|
||||
<arc begin="236" end="13" isPushBackRoute="1" name="B28" />
|
||||
<arc begin="236" end="105" isPushBackRoute="1" name="B28" />
|
||||
<arc begin="105" end="236" isPushBackRoute="1" name="B28" />
|
||||
<arc begin="14" end="237" isPushBackRoute="1" name="B48" />
|
||||
<arc begin="237" end="14" isPushBackRoute="1" name="B48" />
|
||||
<arc begin="237" end="104" isPushBackRoute="1" name="B48" />
|
||||
<arc begin="104" end="237" isPushBackRoute="1" name="B48" />
|
||||
<arc begin="15" end="238" isPushBackRoute="1" name="B44" />
|
||||
<arc begin="238" end="15" isPushBackRoute="1" name="B44" />
|
||||
<arc begin="238" end="101" isPushBackRoute="1" name="B44" />
|
||||
<arc begin="101" end="238" isPushBackRoute="1" name="B44" />
|
||||
<arc begin="16" end="239" isPushBackRoute="1" name="C8" />
|
||||
<arc begin="239" end="16" isPushBackRoute="1" name="C8" />
|
||||
<arc begin="239" end="100" isPushBackRoute="1" name="C8" />
|
||||
<arc begin="100" end="239" isPushBackRoute="1" name="C8" />
|
||||
<arc begin="17" end="240" isPushBackRoute="1" name="C14" />
|
||||
<arc begin="240" end="17" isPushBackRoute="1" name="C14" />
|
||||
<arc begin="240" end="98" isPushBackRoute="1" name="C14" />
|
||||
<arc begin="98" end="240" isPushBackRoute="1" name="C14" />
|
||||
<arc begin="18" end="241" isPushBackRoute="1" name="C2" />
|
||||
<arc begin="241" end="18" isPushBackRoute="1" name="C2" />
|
||||
<arc begin="241" end="102" isPushBackRoute="1" name="C2" />
|
||||
<arc begin="102" end="241" isPushBackRoute="1" name="C2" />
|
||||
<arc begin="19" end="242" isPushBackRoute="1" name="B22" />
|
||||
<arc begin="242" end="19" isPushBackRoute="1" name="B22" />
|
||||
<arc begin="242" end="109" isPushBackRoute="1" name="B22" />
|
||||
<arc begin="109" end="242" isPushBackRoute="1" name="B22" />
|
||||
<arc begin="20" end="243" isPushBackRoute="1" name="B23" />
|
||||
<arc begin="243" end="20" isPushBackRoute="1" name="B23" />
|
||||
<arc begin="243" end="105" isPushBackRoute="1" name="B23" />
|
||||
<arc begin="105" end="243" isPushBackRoute="1" name="B23" />
|
||||
<arc begin="21" end="244" isPushBackRoute="1" name="B10" />
|
||||
<arc begin="244" end="21" isPushBackRoute="1" name="B10" />
|
||||
<arc begin="244" end="110" isPushBackRoute="1" name="B10" />
|
||||
<arc begin="110" end="244" isPushBackRoute="1" name="B10" />
|
||||
<arc begin="22" end="245" isPushBackRoute="1" name="A66" />
|
||||
<arc begin="245" end="22" isPushBackRoute="1" name="A66" />
|
||||
<arc begin="245" end="116" isPushBackRoute="1" name="A66" />
|
||||
<arc begin="116" end="245" isPushBackRoute="1" name="A66" />
|
||||
<arc begin="23" end="246" isPushBackRoute="1" name="A54" />
|
||||
<arc begin="246" end="23" isPushBackRoute="1" name="A54" />
|
||||
<arc begin="246" end="117" isPushBackRoute="1" name="A54" />
|
||||
<arc begin="117" end="246" isPushBackRoute="1" name="A54" />
|
||||
<arc begin="24" end="247" isPushBackRoute="1" name="A16" />
|
||||
<arc begin="247" end="24" isPushBackRoute="1" name="A16" />
|
||||
<arc begin="247" end="123" isPushBackRoute="1" name="A16" />
|
||||
<arc begin="123" end="247" isPushBackRoute="1" name="A16" />
|
||||
<arc begin="25" end="248" isPushBackRoute="1" name="A28" />
|
||||
<arc begin="248" end="25" isPushBackRoute="1" name="A28" />
|
||||
<arc begin="248" end="122" isPushBackRoute="1" name="A28" />
|
||||
<arc begin="122" end="248" isPushBackRoute="1" name="A28" />
|
||||
<arc begin="26" end="249" isPushBackRoute="1" name="F224" />
|
||||
<arc begin="249" end="26" isPushBackRoute="1" name="F224" />
|
||||
<arc begin="249" end="83" isPushBackRoute="1" name="F224" />
|
||||
<arc begin="83" end="249" isPushBackRoute="1" name="F224" />
|
||||
<arc begin="27" end="250" isPushBackRoute="1" name="F211" />
|
||||
<arc begin="250" end="27" isPushBackRoute="1" name="F211" />
|
||||
<arc begin="250" end="83" isPushBackRoute="1" name="F211" />
|
||||
<arc begin="83" end="250" isPushBackRoute="1" name="F211" />
|
||||
<arc begin="28" end="251" isPushBackRoute="1" name="F219" />
|
||||
<arc begin="251" end="28" isPushBackRoute="1" name="F219" />
|
||||
<arc begin="251" end="190" isPushBackRoute="1" name="F219" />
|
||||
<arc begin="190" end="251" isPushBackRoute="1" name="F219" />
|
||||
<arc begin="29" end="252" isPushBackRoute="1" name="V266" />
|
||||
<arc begin="252" end="29" isPushBackRoute="1" name="V266" />
|
||||
<arc begin="252" end="82" isPushBackRoute="1" name="V266" />
|
||||
<arc begin="82" end="252" isPushBackRoute="1" name="V266" />
|
||||
<arc begin="30" end="253" isPushBackRoute="1" name="F235" />
|
||||
<arc begin="253" end="30" isPushBackRoute="1" name="F235" />
|
||||
<arc begin="253" end="70" isPushBackRoute="1" name="F235" />
|
||||
<arc begin="70" end="253" isPushBackRoute="1" name="F235" />
|
||||
<arc begin="31" end="254" isPushBackRoute="1" name="F231" />
|
||||
<arc begin="254" end="31" isPushBackRoute="1" name="F231" />
|
||||
<arc begin="254" end="69" isPushBackRoute="1" name="F231" />
|
||||
<arc begin="69" end="254" isPushBackRoute="1" name="F231" />
|
||||
<arc begin="32" end="255" isPushBackRoute="1" name="V178" />
|
||||
<arc begin="255" end="32" isPushBackRoute="1" name="V178" />
|
||||
<arc begin="255" end="194" isPushBackRoute="1" name="V178" />
|
||||
<arc begin="194" end="255" isPushBackRoute="1" name="V178" />
|
||||
<arc begin="33" end="256" isPushBackRoute="1" name="V174" />
|
||||
<arc begin="256" end="33" isPushBackRoute="1" name="V174" />
|
||||
<arc begin="256" end="85" isPushBackRoute="1" name="V174" />
|
||||
<arc begin="85" end="256" isPushBackRoute="1" name="V174" />
|
||||
<arc begin="34" end="257" isPushBackRoute="1" name="V169" />
|
||||
<arc begin="257" end="34" isPushBackRoute="1" name="V169" />
|
||||
<arc begin="257" end="86" isPushBackRoute="1" name="V169" />
|
||||
<arc begin="86" end="257" isPushBackRoute="1" name="V169" />
|
||||
<arc begin="35" end="258" isPushBackRoute="1" name="V164" />
|
||||
<arc begin="258" end="35" isPushBackRoute="1" name="V164" />
|
||||
<arc begin="258" end="190" isPushBackRoute="1" name="V164" />
|
||||
<arc begin="190" end="258" isPushBackRoute="1" name="V164" />
|
||||
<arc begin="36" end="259" isPushBackRoute="1" name="V159" />
|
||||
<arc begin="259" end="36" isPushBackRoute="1" name="V159" />
|
||||
<arc begin="259" end="88" isPushBackRoute="1" name="V159" />
|
||||
<arc begin="88" end="259" isPushBackRoute="1" name="V159" />
|
||||
<arc begin="37" end="260" isPushBackRoute="1" name="A40" />
|
||||
<arc begin="260" end="37" isPushBackRoute="1" name="A40" />
|
||||
<arc begin="260" end="121" isPushBackRoute="1" name="A40" />
|
||||
<arc begin="121" end="260" isPushBackRoute="1" name="A40" />
|
||||
<arc begin="38" end="261" isPushBackRoute="1" name="A17" />
|
||||
<arc begin="261" end="38" isPushBackRoute="1" name="A17" />
|
||||
<arc begin="261" end="108" isPushBackRoute="1" name="A17" />
|
||||
<arc begin="108" end="261" isPushBackRoute="1" name="A17" />
|
||||
<arc begin="39" end="262" isPushBackRoute="1" name="A1" />
|
||||
<arc begin="262" end="39" isPushBackRoute="1" name="A1" />
|
||||
<arc begin="262" end="110" isPushBackRoute="1" name="A1" />
|
||||
<arc begin="110" end="262" isPushBackRoute="1" name="A1" />
|
||||
</TaxiWaySegments>
|
||||
</groundnet>
|
||||
|
||||
|
||||
98
test_suite/test_data/EDTY.procedures.xml
Normal file
98
test_suite/test_data/EDTY.procedures.xml
Normal file
@@ -0,0 +1,98 @@
|
||||
<Approach Name="ILS28">
|
||||
<App_Waypoint ID="1">
|
||||
<Name>CF28</Name>
|
||||
<Type>Normal</Type>
|
||||
<Latitude>49.085211</Latitude>
|
||||
<Longitude>10.104772</Longitude>
|
||||
<Speed>0</Speed>
|
||||
<Altitude>5000</Altitude>
|
||||
<AltitudeCons>0</AltitudeCons>
|
||||
<AltitudeRestriction>above</AltitudeRestriction>
|
||||
<Flytype>Fly-by</Flytype>
|
||||
<BankLimit>25</BankLimit>
|
||||
<Sp_Turn>Auto</Sp_Turn>
|
||||
</App_Waypoint>
|
||||
<App_Waypoint ID="2">
|
||||
<Name>ESUVA</Name>
|
||||
<Type>Normal</Type>
|
||||
<Latitude>49.087931</Latitude>
|
||||
<Longitude>10.079558</Longitude>
|
||||
<Speed>0</Speed>
|
||||
<Altitude>5000</Altitude>
|
||||
<AltitudeCons>0</AltitudeCons>
|
||||
<AltitudeRestriction>at</AltitudeRestriction>
|
||||
<Flytype>Fly-by</Flytype>
|
||||
<BankLimit>25</BankLimit>
|
||||
<Sp_Turn>Auto</Sp_Turn>
|
||||
</App_Waypoint>
|
||||
<App_Waypoint ID="3">
|
||||
<Name>RW28</Name>
|
||||
<Type>Runway</Type>
|
||||
<Latitude>49.117467</Latitude>
|
||||
<Longitude>9.792336</Longitude>
|
||||
<Speed>0</Speed>
|
||||
<Altitude>1363</Altitude>
|
||||
<AltitudeCons>0</AltitudeCons>
|
||||
<AltitudeRestriction>at</AltitudeRestriction>
|
||||
<Flytype>Fly-by</Flytype>
|
||||
<BankLimit>25</BankLimit>
|
||||
<Sp_Turn>Auto</Sp_Turn>
|
||||
</App_Waypoint>
|
||||
<App_Waypoint ID="4">
|
||||
<Name>TY021</Name>
|
||||
<Type>Normal</Type>
|
||||
<Latitude>49.131786</Latitude>
|
||||
<Longitude>9.650253</Longitude>
|
||||
<Speed>0</Speed>
|
||||
<Altitude>4000</Altitude>
|
||||
<AltitudeCons>0</AltitudeCons>
|
||||
<AltitudeRestriction>above</AltitudeRestriction>
|
||||
<Flytype>Fly-over</Flytype>
|
||||
<BankLimit>25</BankLimit>
|
||||
<Sp_Turn>Auto</Sp_Turn>
|
||||
</App_Waypoint>
|
||||
<App_Waypoint ID="5">
|
||||
<Name>DKB</Name>
|
||||
<Type>Normal</Type>
|
||||
<Latitude>49.142753</Latitude>
|
||||
<Longitude>10.238306</Longitude>
|
||||
<Speed>0</Speed>
|
||||
<Altitude>5000</Altitude>
|
||||
<AltitudeCons>0</AltitudeCons>
|
||||
<AltitudeRestriction>at</AltitudeRestriction>
|
||||
<Flytype>Fly-by</Flytype>
|
||||
<BankLimit>25</BankLimit>
|
||||
<Sp_Turn>Right</Sp_Turn>
|
||||
</App_Waypoint>
|
||||
<App_Transition Name="DKB">
|
||||
<AppTr_Waypoint ID="1">
|
||||
<Name>DKB</Name>
|
||||
<Type>Normal</Type>
|
||||
<Latitude>49.142753</Latitude>
|
||||
<Longitude>10.238306</Longitude>
|
||||
<Speed>0</Speed>
|
||||
<Altitude>0</Altitude>
|
||||
<AltitudeCons>0</AltitudeCons>
|
||||
<AltitudeRestriction>at</AltitudeRestriction>
|
||||
<Flytype>Fly-by</Flytype>
|
||||
<BankLimit>25</BankLimit>
|
||||
<Sp_Turn>Auto</Sp_Turn>
|
||||
</AppTr_Waypoint>
|
||||
<AppTr_Waypoint ID="2">
|
||||
<Name>DKB</Name>
|
||||
<Type>DmeIntc</Type>
|
||||
<Latitude>49.142753</Latitude>
|
||||
<Longitude>10.238306</Longitude>
|
||||
<Speed>0</Speed>
|
||||
<Altitude>5000</Altitude>
|
||||
<AltitudeCons>0</AltitudeCons>
|
||||
<AltitudeRestriction>above</AltitudeRestriction>
|
||||
<Hdg_Crs>0</Hdg_Crs>
|
||||
<Hdg_Crs_value>214</Hdg_Crs_value>
|
||||
<Flytype>Fly-by</Flytype>
|
||||
<BankLimit>25</BankLimit>
|
||||
<DMEtoIntercept>4.0</DMEtoIntercept>
|
||||
<Sp_Turn>Auto</Sp_Turn>
|
||||
</AppTr_Waypoint>
|
||||
</App_Transition>
|
||||
</Approach>
|
||||
1878
test_suite/test_data/EGPH.groundnet.xml
Normal file
1878
test_suite/test_data/EGPH.groundnet.xml
Normal file
File diff suppressed because it is too large
Load Diff
3249
test_suite/test_data/YBBN.groundnet.xml
Normal file
3249
test_suite/test_data/YBBN.groundnet.xml
Normal file
File diff suppressed because it is too large
Load Diff
1101
test_suite/test_data/YSCB.groundnet.xml
Normal file
1101
test_suite/test_data/YSCB.groundnet.xml
Normal file
File diff suppressed because it is too large
Load Diff
3209
test_suite/test_data/YSSY.groundnet.xml
Normal file
3209
test_suite/test_data/YSSY.groundnet.xml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
This is a simulation of a user-provided custom aircraft dir.
|
||||
|
||||
It contains a fake UFO which intentinoally is different to the one in FGData,
|
||||
for checking precedence of paths and options.
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
|
||||
<PropertyList>
|
||||
<sim>
|
||||
<description>Better UFO than FG data</description>
|
||||
</sim>
|
||||
<zot>42</zot>
|
||||
</PropertyList>
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<PropertyList>
|
||||
<id>org.fg.test.catalog1</id>
|
||||
<description>First test catalog</description>
|
||||
<url>http://localhost:2000/catalogTest1/catalog.xml</url>
|
||||
<catalog-version>4</catalog-version>
|
||||
|
||||
<version>*</version>
|
||||
|
||||
|
||||
<package>
|
||||
<id>bob</id>
|
||||
<name>The Bob Craft</name>
|
||||
<revision type="int">8</revision>
|
||||
<file-size-bytes type="int">593</file-size-bytes>
|
||||
|
||||
<md5>a469c4b837f0521db48616cfe65ac1ea</md5>
|
||||
<url>http://localhost:2000/catalogTest1/alpha.zip</url>
|
||||
|
||||
<dir>bobCraft</dir>
|
||||
|
||||
</package>
|
||||
|
||||
</PropertyList>
|
||||
25
test_suite/unit_tests/AI/CMakeLists.txt
Normal file
25
test_suite/unit_tests/AI/CMakeLists.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
set(TESTSUITE_SOURCES
|
||||
${TESTSUITE_SOURCES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_AIFlightPlan.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_AIManager.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_traffic.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_TrafficMgr.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_groundnet.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_submodels.cxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_VectorMath.cxx
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
set(TESTSUITE_HEADERS
|
||||
${TESTSUITE_HEADERS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_AIFlightPlan.hxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_AIManager.hxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_traffic.hxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_TrafficMgr.hxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_groundnet.hxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_submodels.hxx
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_VectorMath.hxx
|
||||
PARENT_SCOPE
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user