Update test architecture and TestAmbiguity

This commit is contained in:
30hours 2023-12-18 12:34:47 +00:00
parent 25d0b6d1b7
commit d9a26299c7
3 changed files with 104 additions and 44 deletions

View file

@ -8,11 +8,14 @@ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
SET (PROJECT_ROOT "${PROJECT_SOURCE_DIR}") SET (PROJECT_ROOT "${PROJECT_SOURCE_DIR}")
SET (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_ROOT}/bin") SET (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_ROOT}/bin")
SET (PROJECT_TEST_DIR "${PROJECT_SOURCE_DIR}/test")
SET (PROJECT_SOURCE_DIR "${PROJECT_SOURCE_DIR}/src") SET (PROJECT_SOURCE_DIR "${PROJECT_SOURCE_DIR}/src")
SET (PROJECT_BINARY_DIR "${PROJECT_ROOT}/bin") SET (PROJECT_BINARY_DIR "${PROJECT_ROOT}/bin")
SET (PROJECT_BINARY_TEST_DIR "${PROJECT_ROOT}/bin/test")
SET (PROJECT_LIB_DIR "${PROJECT_ROOT}/lib") SET (PROJECT_LIB_DIR "${PROJECT_ROOT}/lib")
MESSAGE ("Source path: ${PROJECT_SOURCE_DIR}") MESSAGE ("Source path: ${PROJECT_SOURCE_DIR}")
MESSAGE ("Binary path: ${PROJECT_BINARY_DIR}") MESSAGE ("Binary path: ${PROJECT_BINARY_DIR}")
MESSAGE ("Binary test path: ${PROJECT_BINARY_TEST_DIR}")
MESSAGE ("Lib path: ${PROJECT_LIB_DIR}") MESSAGE ("Lib path: ${PROJECT_LIB_DIR}")
add_executable(blah2 add_executable(blah2
@ -74,9 +77,11 @@ include_directories("${PROJECT_SOURCE_DIR}/process/spectrum/")
include_directories("${PROJECT_SOURCE_DIR}/data/") include_directories("${PROJECT_SOURCE_DIR}/data/")
include_directories("${PROJECT_SOURCE_DIR}/data/meta/") include_directories("${PROJECT_SOURCE_DIR}/data/meta/")
add_executable(test_ambiguity # unit tests
add_executable(testAmbiguity
${PROJECT_TEST_DIR}/unit/process/ambiguity/TestAmbiguity.cpp
${PROJECT_SOURCE_DIR}/data/IqData.cpp ${PROJECT_SOURCE_DIR}/data/IqData.cpp
${PROJECT_SOURCE_DIR}/data/Map.cpp ${PROJECT_SOURCE_DIR}/data/Map.cpp
${PROJECT_SOURCE_DIR}/process/ambiguity/Ambiguity.cpp ${PROJECT_SOURCE_DIR}/process/ambiguity/Ambiguity.cpp)
${PROJECT_SOURCE_DIR}/process/ambiguity/test_ambiguity.cpp) target_link_libraries(testAmbiguity catch2 fftw3 fftw3_threads)
target_link_libraries(test_ambiguity catch2 fftw3 fftw3_threads) set_target_properties(testAmbiguity PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_TEST_DIR}")

31
test/README.md Normal file
View file

@ -0,0 +1,31 @@
# blah2 Test
**TODO: Tests not implemented yet. Describing desired behaviour for the time being.**
## Framework
The test framework is [catch2](https://github.com/catchorg/Catch2).
## Types
The test files are split across directories defined by the type of test.
- **Unit tests** will test the class in isolation. The directory structure mirrors *src*.
- **Functional tests** will test that expected outputs are achieved from defined inputs. An example would be checking the program turns a specific IQ data set to a specific delay-Doppler map. This test category will rely on golden data.
- **Comparison tests** will compare different methods of performing the same task. An example would be comparing 2 methods of clutter filtering. Metrics to be compared may include time and performance. Note there is no pass/fail criteria for comparison tests - this is purely for information.
## Usage
All tests are compiled when building, however tests be run manually.
- Run a single test case for "TestClass".
```
sudo docker compose run blah2-test TestClass
```
- Run all test cases.
```
sudo docker compose run blah2-test *
```

View file

@ -1,3 +1,10 @@
/// @file TestAmbiguity.cpp
/// @brief Unit test for Ambiguity.cpp
/// @author 30hours
/// @author Dan G
/// @todo Add golden data IqData file for testing.
/// @todo Declaration match to coding style?
#define CATCH_CONFIG_MAIN #define CATCH_CONFIG_MAIN
#include "catch_amalgamated.hpp" #include "catch_amalgamated.hpp"
@ -5,9 +12,13 @@
#include <random> #include <random>
#include <iostream> #include <iostream>
/// @brief Use random_device as RNG.
std::random_device g_rd; std::random_device g_rd;
// Have to use out ref parameter because there's no copy/move ctors /// @brief Generate random IQ data.
/// @param iqData Address of IqData object.
/// @details Have to use out ref parameter because there's no copy/move ctors.
/// @return Void.
void random_iq(IqData& iq_data) { void random_iq(IqData& iq_data) {
std::mt19937 gen(g_rd()); std::mt19937 gen(g_rd());
std::uniform_real_distribution<> dist(-100.0, 100.0); std::uniform_real_distribution<> dist(-100.0, 100.0);
@ -17,6 +28,11 @@ void random_iq(IqData& iq_data) {
} }
} }
/// @brief Read file to IqData buffer.
/// @param buffer1 IqData buffer reference.
/// @param buffer2 IqData buffer surveillance.
/// @param file String of file name.
/// @return Void.
void read_file(IqData& buffer1, IqData& buffer2, const std::string& file) void read_file(IqData& buffer1, IqData& buffer2, const std::string& file)
{ {
short i1, q1, i2, q2; short i1, q1, i2, q2;
@ -40,7 +56,7 @@ void read_file(IqData& buffer1, IqData& buffer2, const std::string& file)
buffer1.push_back({(double)i1, (double)q1}); buffer1.push_back({(double)i1, (double)q1});
buffer2.push_back({(double)i2, (double)q2}); buffer2.push_back({(double)i2, (double)q2});
// Only read for the buffer length - this class is very poorly designed. // only read for the buffer length - this class is very poorly designed
if (buffer1.get_length() == buffer1.get_n()) { if (buffer1.get_length() == buffer1.get_n()) {
break; break;
} }
@ -49,67 +65,72 @@ void read_file(IqData& buffer1, IqData& buffer2, const std::string& file)
fclose(file_replay); fclose(file_replay);
} }
// Make sure the constructor is calculating the parameters correctly. /// @brief Test constructor.
/// @details Check constructor parameters created correctly.
TEST_CASE("Constructor", "[constructor]") TEST_CASE("Constructor", "[constructor]")
{ {
int32_t delay_min{-10}; int32_t delayMin{-10};
int32_t delay_max{300}; int32_t delayMax{300};
int32_t doppler_min{-300}; int32_t dopplerMin{-300};
int32_t doppler_max{300}; int32_t dopplerMax{300};
uint32_t fs{2'000'000}; uint32_t fs{2'000'000};
float cpi_s{0.5}; float tCpi{0.5};
uint32_t n_samples = cpi_s * fs; // narrow on purpose uint32_t nSamples = tCpi * fs; // narrow on purpose
Ambiguity ambiguity(delay_min,delay_max,doppler_min,doppler_max,fs,n_samples); Ambiguity ambiguity(delayMin, delayMax, dopplerMin,
dopplerMax, fs, nSamples);
CHECK_THAT(ambiguity.cpi_length_seconds(), Catch::Matchers::WithinAbs(cpi_s, 0.02)); CHECK_THAT(ambiguity.cpi_length_seconds(), Catch::Matchers::WithinAbs(tCpi, 0.02));
CHECK(ambiguity.doppler_middle() == 0); CHECK(ambiguity.doppler_middle() == 0);
CHECK(ambiguity.corr_samples_per_pulse() == 3322); CHECK(ambiguity.corr_samples_per_pulse() == 3322);
CHECK(ambiguity.delay_bin_count() == delay_max + std::abs(delay_min) + 1); CHECK(ambiguity.delay_bin_count() == delayMax + std::abs(delayMin) + 1);
CHECK(ambiguity.doppler_bin_count() == 301); CHECK(ambiguity.doppler_bin_count() == 301);
CHECK(ambiguity.fft_bin_count() == 6643); CHECK(ambiguity.fft_bin_count() == 6643);
} }
// Make sure the constructor is calculating the parameters correctly with rounded FFT length /// @brief Test constructor with rounded Hamming number FFT length.
TEST_CASE("Constructor_Round", "[constructor]") TEST_CASE("Constructor_Round", "[constructor]")
{ {
int32_t delay_min{-10}; int32_t delayMin{-10};
int32_t delay_max{300}; int32_t delayMax{300};
int32_t doppler_min{-300}; int32_t dopplerMin{-300};
int32_t doppler_max{300}; int32_t dopplerMax{300};
uint32_t fs{2'000'000}; uint32_t fs{2'000'000};
float cpi_s{0.5}; float tCpi{0.5};
uint32_t n_samples = cpi_s * fs; // narrow on purpose uint32_t nSamples = tCpi * fs; // narrow on purpose
Ambiguity ambiguity(delay_min,delay_max,doppler_min,doppler_max,fs,n_samples,true); Ambiguity ambiguity(delayMin, delayMax, dopplerMin,
dopplerMax, fs, nSamples, true);
CHECK_THAT(ambiguity.cpi_length_seconds(), Catch::Matchers::WithinAbs(cpi_s, 0.02)); CHECK_THAT(ambiguity.cpi_length_seconds(), Catch::Matchers::WithinAbs(tCpi, 0.02));
CHECK(ambiguity.doppler_middle() == 0); CHECK(ambiguity.doppler_middle() == 0);
CHECK(ambiguity.corr_samples_per_pulse() == 3322); CHECK(ambiguity.corr_samples_per_pulse() == 3322);
CHECK(ambiguity.delay_bin_count() == delay_max + std::abs(delay_min) + 1); CHECK(ambiguity.delay_bin_count() == delayMax + std::abs(delayMin) + 1);
CHECK(ambiguity.doppler_bin_count() == 301); CHECK(ambiguity.doppler_bin_count() == 301);
CHECK(ambiguity.fft_bin_count() == 6750); CHECK(ambiguity.fft_bin_count() == 6750);
} }
/// @brief Test simple ambiguity processing.
TEST_CASE("Process_Simple", "[process]") TEST_CASE("Process_Simple", "[process]")
{ {
auto round_hamming = GENERATE(true, false); auto round_hamming = GENERATE(true, false);
int32_t delay_min{-10}; int32_t delayMin{-10};
int32_t delay_max{300}; int32_t delayMax{300};
int32_t doppler_min{-300}; int32_t dopplerMin{-300};
int32_t doppler_max{300}; int32_t dopplerMax{300};
uint32_t fs{2'000'000}; uint32_t fs{2'000'000};
float cpi_s{0.5}; float tCpi{0.5};
uint32_t n_samples = cpi_s * fs; // narrow on purpose uint32_t nSamples = tCpi * fs; // narrow on purpose
Ambiguity ambiguity(delay_min,delay_max,doppler_min,doppler_max,fs,n_samples, round_hamming); Ambiguity ambiguity(delayMin, delayMax, dopplerMin,
dopplerMax, fs, nSamples, round_hamming);
IqData x{n_samples}; IqData x{nSamples};
IqData y{n_samples}; IqData y{nSamples};
random_iq(x); random_iq(x);
random_iq(y); random_iq(y);
@ -122,22 +143,24 @@ TEST_CASE("Process_Simple", "[process]")
<< ambiguity.get_latest_performance() << "\n-----------" << std::endl; << ambiguity.get_latest_performance() << "\n-----------" << std::endl;
} }
/// @brief Test processing from a file.
TEST_CASE("Process_File", "[process]") TEST_CASE("Process_File", "[process]")
{ {
auto round_hamming = GENERATE(true, false); auto round_hamming = GENERATE(true, false);
int32_t delay_min{-10}; int32_t delayMin{-10};
int32_t delay_max{300}; int32_t delayMax{300};
int32_t doppler_min{-300}; int32_t dopplerMin{-300};
int32_t doppler_max{300}; int32_t dopplerMax{300};
uint32_t fs{2'000'000}; uint32_t fs{2'000'000};
float cpi_s{0.5}; float tCpi{0.5};
uint32_t n_samples = cpi_s * fs; // narrow on purpose uint32_t nSamples = tCpi * fs; // narrow on purpose
Ambiguity ambiguity(delay_min,delay_max,doppler_min,doppler_max,fs,n_samples, round_hamming); Ambiguity ambiguity(delayMin, delayMax, dopplerMin,
IqData x{n_samples}; dopplerMax, fs, nSamples, round_hamming);
IqData y{n_samples}; IqData x{nSamples};
IqData y{nSamples};
read_file(x, y, "20231214-230611.rspduo"); read_file(x, y, "20231214-230611.rspduo");
REQUIRE(x.get_length() == x.get_n()); REQUIRE(x.get_length() == x.get_n());
@ -151,6 +174,7 @@ TEST_CASE("Process_File", "[process]")
<< ambiguity.get_latest_performance() << "\n-----------" << std::endl; << ambiguity.get_latest_performance() << "\n-----------" << std::endl;
} }
/// @brief Test Hamming number calculation.
TEST_CASE("Next_Hamming", "[hamming]") TEST_CASE("Next_Hamming", "[hamming]")
{ {
CHECK(next_hamming(104) == 108); CHECK(next_hamming(104) == 108);