diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 65d3118..2cd5fc1 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -57,7 +57,7 @@ jobs: - name: Test shell: bash - run: ./build/rtneural_tests all + run: ctest --test-dir build --parallel - name: Collect Coverage Data shell: bash diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f297b71..7f931d6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -87,4 +87,4 @@ jobs: - name: Test shell: bash - run: ./build/rtneural_tests all + run: ctest -C Release --test-dir build --parallel diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e41521..13043b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,8 @@ include(cmake/ChooseBackend.cmake) option(BUILD_TESTS "Build RTNeural accuracy tests" OFF) if(BUILD_TESTS) message(STATUS "RTNeural -- Configuring tests...") + include(CTest) + enable_testing() add_subdirectory(tests) endif() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9e3eef2..4462ea4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2,15 +2,24 @@ include_directories(../RTNeural) add_executable(rtneural_tests tests.cpp) target_link_libraries(rtneural_tests LINK_PUBLIC RTNeural) +target_compile_definitions(rtneural_tests PRIVATE RTNEURAL_ROOT_DIR="${CMAKE_SOURCE_DIR}/") -add_custom_command(TARGET rtneural_tests - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E echo "copying $ to ${PROJECT_BINARY_DIR}/rtneural_tests" - COMMAND ${CMAKE_COMMAND} -E copy $ ${PROJECT_BINARY_DIR}/rtneural_tests) +add_test(NAME "RTNeural_Approx_Test" COMMAND $ approx) +add_test(NAME "RTNeural_Bad_Model_Test" COMMAND $ bad_model) +add_test(NAME "RTNeural_Model_Test" COMMAND $ model) +add_test(NAME "RTNeural_Sample_Rate_RNN_Test" COMMAND $ sample_rate_rnn) +add_test(NAME "RTNeural_Torch_Test" COMMAND $ torch) +add_test(NAME "RTNeural_Util_Test" COMMAND $ util) +add_test(NAME "RTNeural_Conv1D_Test" COMMAND $ conv1d) +add_test(NAME "RTNeural_Conv2D_Test" COMMAND $ conv2d) +add_test(NAME "RTNeural_Dense_Test" COMMAND $ dense) +add_test(NAME "RTNeural_GRU_Test" COMMAND $ gru) +add_test(NAME "RTNeural_GRU_1D_Test" COMMAND $ gru_1d) +add_test(NAME "RTNeural_LSTM_Test" COMMAND $ lstm) +add_test(NAME "RTNeural_LSTM_1D_Test" COMMAND $ lstm_1d) option(RTNEURAL_CODE_COVERAGE "Build RTNeural tests with code coverage flags" OFF) if(RTNEURAL_CODE_COVERAGE) include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/EnableCoverageFlags.cmake) enable_coverage_flags(rtneural_tests) endif() - diff --git a/tests/bad_model_test.hpp b/tests/bad_model_test.hpp index 1862e6a..4aca406 100644 --- a/tests/bad_model_test.hpp +++ b/tests/bad_model_test.hpp @@ -14,7 +14,8 @@ int badModelTest() RTNeural::LSTMLayerT, RTNeural::DenseT> lstm_16; - std::ifstream jsonStream1("models/bad_lstm.json", std::ifstream::binary); + const auto file_path = std::string { RTNEURAL_ROOT_DIR } + "models/bad_lstm.json"; + std::ifstream jsonStream1(file_path, std::ifstream::binary); try { diff --git a/tests/conv2d_model.h b/tests/conv2d_model.h index 8796744..c7c67cc 100644 --- a/tests/conv2d_model.h +++ b/tests/conv2d_model.h @@ -66,9 +66,9 @@ int conv2d_test() #else std::cout << "TESTING CONV2D MODEL..." << std::endl; - const std::string model_file = "models/conv2d.json"; - const std::string data_file = "test_data/conv2d_x_python.csv"; - const std::string data_file_y = "test_data/conv2d_y_python.csv"; + const auto model_file = std::string { RTNEURAL_ROOT_DIR } + "models/conv2d.json"; + const auto data_file = std::string { RTNEURAL_ROOT_DIR } + "test_data/conv2d_x_python.csv"; + const auto data_file_y = std::string { RTNEURAL_ROOT_DIR } + "test_data/conv2d_y_python.csv"; constexpr double threshold = 1.0e-6; diff --git a/tests/model_test.hpp b/tests/model_test.hpp index 4fa1f65..d9ab733 100644 --- a/tests/model_test.hpp +++ b/tests/model_test.hpp @@ -23,8 +23,8 @@ int model_test() { std::cout << "TESTING FULL MODEL..." << std::endl; - const std::string model_file = "models/full_model.json"; - const std::string data_file = "test_data/dense_x_python.csv"; + const std::string model_file = std::string { RTNEURAL_ROOT_DIR } + "models/full_model.json"; + const std::string data_file = std::string { RTNEURAL_ROOT_DIR } + "test_data/dense_x_python.csv"; constexpr double threshold = 1.0e-12; std::ifstream pythonX(data_file); diff --git a/tests/sample_rate_rnn_test.hpp b/tests/sample_rate_rnn_test.hpp index 1aac024..1e827df 100644 --- a/tests/sample_rate_rnn_test.hpp +++ b/tests/sample_rate_rnn_test.hpp @@ -22,7 +22,7 @@ int runModelTest(const std::string& modelFile, MultType sampleRateMult) static constexpr auto baseSampleRate = 48000.0; ModelType baseSampleRateModel; - std::ifstream jsonStream1("models/" + modelFile, std::ifstream::binary); + std::ifstream jsonStream1(std::string { RTNEURAL_ROOT_DIR } + "models/" + modelFile, std::ifstream::binary); baseSampleRateModel.parseJson(jsonStream1); baseSampleRateModel.reset(); auto baseSampleRateSignal = getSampleRateVector(baseSampleRate); @@ -30,7 +30,7 @@ int runModelTest(const std::string& modelFile, MultType sampleRateMult) sample = baseSampleRateModel.forward(&sample); ModelType testSampleRateModel; - std::ifstream jsonStream2("models/" + modelFile, std::ifstream::binary); + std::ifstream jsonStream2(std::string { RTNEURAL_ROOT_DIR } + "models/" + modelFile, std::ifstream::binary); testSampleRateModel.parseJson(jsonStream2); testSampleRateModel.reset(); testSampleRateModel.template get().prepare(sampleRateMult); diff --git a/tests/templated_tests.hpp b/tests/templated_tests.hpp index 27ff88e..f9eb190 100644 --- a/tests/templated_tests.hpp +++ b/tests/templated_tests.hpp @@ -9,15 +9,15 @@ int runTestTemplated(const TestConfig& test) { std::cout << "TESTING " << test.name << " TEMPLATED IMPLEMENTATION..." << std::endl; - std::ifstream jsonStream(test.model_file, std::ifstream::binary); + std::ifstream jsonStream(std::string { RTNEURAL_ROOT_DIR } + test.model_file, std::ifstream::binary); ModelType model; model.parseJson(jsonStream, true); model.reset(); - std::ifstream pythonX(test.x_data_file); + std::ifstream pythonX(std::string { RTNEURAL_ROOT_DIR } + test.x_data_file); auto xData = load_csv::loadFile(pythonX); - std::ifstream pythonY(test.y_data_file); + std::ifstream pythonY(std::string { RTNEURAL_ROOT_DIR } + test.y_data_file); const auto yRefData = load_csv::loadFile(pythonY); std::vector yData(xData.size(), (T)0); diff --git a/tests/tests.cpp b/tests/tests.cpp index 83965e3..37a7268 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -36,14 +36,14 @@ int runTest(const TestConfig& test) { std::cout << "TESTING " << test.name << " IMPLEMENTATION..." << std::endl; - std::ifstream jsonStream(test.model_file, std::ifstream::binary); + std::ifstream jsonStream(std::string { RTNEURAL_ROOT_DIR } + test.model_file, std::ifstream::binary); auto model = RTNeural::json_parser::parseJson(jsonStream, true); model->reset(); - std::ifstream pythonX(test.x_data_file); + std::ifstream pythonX(std::string { RTNEURAL_ROOT_DIR } + test.x_data_file); auto xData = load_csv::loadFile(pythonX); - std::ifstream pythonY(test.y_data_file); + std::ifstream pythonY(std::string { RTNEURAL_ROOT_DIR } + test.y_data_file); const auto yRefData = load_csv::loadFile(pythonY); std::vector yData(xData.size(), (T)0); diff --git a/tests/torch_conv1d_test.hpp b/tests/torch_conv1d_test.hpp index d2265db..4b3ac1a 100644 --- a/tests/torch_conv1d_test.hpp +++ b/tests/torch_conv1d_test.hpp @@ -42,7 +42,8 @@ int testTorchConv1DModel() std::cout << "TESTING TORCH/CONV1D MODEL WITH DATA TYPE: FLOAT" << std::endl; else std::cout << "TESTING TORCH/CONV1D MODEL WITH DATA TYPE: DOUBLE" << std::endl; - std::ifstream jsonStream("models/conv1d_torch.json", std::ifstream::binary); + const auto model_file = std::string { RTNEURAL_ROOT_DIR } + "models/conv1d_torch.json"; + std::ifstream jsonStream(model_file, std::ifstream::binary); nlohmann::json modelJson; jsonStream >> modelJson; @@ -50,7 +51,7 @@ int testTorchConv1DModel() RTNeural::torch_helpers::loadConv1D (modelJson, "", model.template get<0>()); model.reset(); - std::ifstream modelInputsFile { "test_data/conv1d_torch_x_python.csv" }; + std::ifstream modelInputsFile { std::string { RTNEURAL_ROOT_DIR } + "test_data/conv1d_torch_x_python.csv" }; const auto inputs = load_csv::loadFile(modelInputsFile); std::vector> outputs {}; outputs.resize(inputs.size(), {}); @@ -61,7 +62,7 @@ int testTorchConv1DModel() std::copy(model.getOutputs(), model.getOutputs() + 12, outputs[i].begin()); } - std::ifstream modelOutputsFile { "test_data/conv1d_torch_y_python.csv" }; + std::ifstream modelOutputsFile { std::string { RTNEURAL_ROOT_DIR } + "test_data/conv1d_torch_y_python.csv" }; const auto expected_y = loadFile2D (modelOutputsFile); size_t nErrs = 0; diff --git a/tests/torch_gru_test.hpp b/tests/torch_gru_test.hpp index 2372360..c0c7537 100644 --- a/tests/torch_gru_test.hpp +++ b/tests/torch_gru_test.hpp @@ -1,7 +1,7 @@ #pragma once -#include "load_csv.hpp" #include "RTNeural/RTNeural.h" +#include "load_csv.hpp" namespace torch_gru_test { @@ -16,23 +16,24 @@ int testTorchGRUModel() jsonStream >> modelJson; auto& gru = model.template get<0>(); - RTNeural::torch_helpers::loadGRU (modelJson, "gru.", gru); + RTNeural::torch_helpers::loadGRU(modelJson, "gru.", gru); auto& dense = model.template get<1>(); - RTNeural::torch_helpers::loadDense (modelJson, "dense.", dense); + RTNeural::torch_helpers::loadDense(modelJson, "dense.", dense); }; - if (std::is_same::value) + if(std::is_same::value) std::cout << "TESTING TORCH/GRU MODEL WITH DATA TYPE: FLOAT" << std::endl; else std::cout << "TESTING TORCH/GRU MODEL WITH DATA TYPE: DOUBLE" << std::endl; - std::ifstream jsonStream("models/gru_torch.json", std::ifstream::binary); + const auto model_file = std::string { RTNEURAL_ROOT_DIR } + "models/gru_torch.json"; + std::ifstream jsonStream(model_file, std::ifstream::binary); ModelType model; loadModel(jsonStream, model); model.reset(); - std::ifstream modelInputsFile { "test_data/gru_torch_x_python.csv" }; + std::ifstream modelInputsFile { std::string { RTNEURAL_ROOT_DIR } + "test_data/gru_torch_x_python.csv" }; const auto inputs = load_csv::loadFile(modelInputsFile); std::vector outputs {}; outputs.resize(inputs.size(), {}); @@ -42,7 +43,7 @@ int testTorchGRUModel() outputs[i] = model.forward(&inputs[i]); } - std::ifstream modelOutputsFile { "test_data/gru_torch_y_python.csv" }; + std::ifstream modelOutputsFile { std::string { RTNEURAL_ROOT_DIR } + "test_data/gru_torch_y_python.csv" }; const auto expected_y = load_csv::loadFile(modelOutputsFile); size_t nErrs = 0; @@ -50,7 +51,7 @@ int testTorchGRUModel() for(size_t n = 0; n < inputs.size(); ++n) { auto err = std::abs(outputs[n] - expected_y[n]); - if(err > (T) 1.0e-6) + if(err > (T)1.0e-6) { max_error = std::max(err, max_error); nErrs++; diff --git a/tests/torch_lstm_test.hpp b/tests/torch_lstm_test.hpp index 89067ba..af260be 100644 --- a/tests/torch_lstm_test.hpp +++ b/tests/torch_lstm_test.hpp @@ -1,7 +1,7 @@ #pragma once -#include "load_csv.hpp" #include "RTNeural/RTNeural.h" +#include "load_csv.hpp" namespace torch_lstm_test { @@ -16,23 +16,24 @@ int testTorchLSTMModel() jsonStream >> modelJson; auto& lstm = model.template get<0>(); - RTNeural::torch_helpers::loadLSTM (modelJson, "lstm.", lstm); + RTNeural::torch_helpers::loadLSTM(modelJson, "lstm.", lstm); auto& dense = model.template get<1>(); - RTNeural::torch_helpers::loadDense (modelJson, "dense.", dense); + RTNeural::torch_helpers::loadDense(modelJson, "dense.", dense); }; - if (std::is_same::value) + if(std::is_same::value) std::cout << "TESTING TORCH/LSTM MODEL WITH DATA TYPE: FLOAT" << std::endl; else std::cout << "TESTING TORCH/LSTM MODEL WITH DATA TYPE: DOUBLE" << std::endl; - std::ifstream jsonStream("models/lstm_torch.json", std::ifstream::binary); + const auto model_file = std::string { RTNEURAL_ROOT_DIR } + "models/lstm_torch.json"; + std::ifstream jsonStream(model_file, std::ifstream::binary); ModelType model; loadModel(jsonStream, model); model.reset(); - std::ifstream modelInputsFile { "test_data/lstm_torch_x_python.csv" }; + std::ifstream modelInputsFile { std::string { RTNEURAL_ROOT_DIR } + "test_data/lstm_torch_x_python.csv" }; const auto inputs = load_csv::loadFile(modelInputsFile); std::vector outputs {}; outputs.resize(inputs.size(), {}); @@ -42,7 +43,7 @@ int testTorchLSTMModel() outputs[i] = model.forward(&inputs[i]); } - std::ifstream modelOutputsFile { "test_data/lstm_torch_y_python.csv" }; + std::ifstream modelOutputsFile { std::string { RTNEURAL_ROOT_DIR } + "test_data/lstm_torch_y_python.csv" }; const auto expected_y = load_csv::loadFile(modelOutputsFile); size_t nErrs = 0; @@ -50,7 +51,7 @@ int testTorchLSTMModel() for(size_t n = 0; n < inputs.size(); ++n) { auto err = std::abs(outputs[n] - expected_y[n]); - if(err > (T) 1.0e-6) + if(err > (T)1.0e-6) { max_error = std::max(err, max_error); nErrs++;