#include #include #include #include #include "../include/dataAcquisition.h" #define TEST_NUMBER 18 #define NUMBER_OF_SENSORS 5 #define SLIDING_WINDOW_SIZE 10 #define AVERAGE_UNCERTAINTY 0.01 #define STD_UNCERTAINTY 0.01 #define M_PI 3.14159265358979323846 #define NORMAL_DISTRIBUTION_MEAN 10.0 #define NORMAL_DISTRIBUTION_STDDEV 2.0 /** * @brief Test function to verify the initialization of sensor readings. * * This function tests the `initializeReadings` function by initializing the * readings with a specified number of sensors and sliding window size. It then * asserts that the number of sensors and the sliding window size are correctly * set. * * @note This test assumes that the constants `NUMBER_OF_SENSORS` and * `SLIDING_WINDOW_SIZE` are defined elsewhere in the code. */ void test_initializeReadings_uniform() { initializeReadings(NUMBER_OF_SENSORS, 100); assert(getSensorsNumber() == NUMBER_OF_SENSORS); assert(getSlidingWindowSize() == SLIDING_WINDOW_SIZE); } /** * @brief Test function to add uniform readings to all sensors and verify if the last sensor's buffer is full. * * This function iterates through a range of values from 1 to SLIDING_WINDOW_SIZE and adds each value to all sensors. * After adding the readings, it asserts that the buffer for the last sensor (NUMBER_OF_SENSORS - 1) is full. * * @note Assumes that the addReading function adds a reading to all sensors and that the isFull function checks if a sensor's buffer is full. */ void test_addReading_uniform() { for (int value = 1; value <= SLIDING_WINDOW_SIZE; value++) { for (int sensor = 0; sensor < NUMBER_OF_SENSORS; sensor++) { addReading(value); } } assert(isFull(NUMBER_OF_SENSORS - 1) == true); // Assuming the last sensor acquired the data } /** * @brief Test function to verify the average calculation on a sensor with uniform data. * * This function tests the `getAverageOnSensor` function by calculating the average * value on the last sensor (NUMBER_OF_SENSORS - 1) and comparing it to the expected * average value. The expected average is calculated as (SLIDING_WINDOW_SIZE + 1) / 2.0. * The test asserts that the difference between the calculated average and the expected * average is within the defined AVERAGE_UNCERTAINTY. */ void test_averageOnSensor_uniform() { //printf("Average on sensor %d: %f\n", NUMBER_OF_SENSORS - 1, getAverageOnSensor(NUMBER_OF_SENSORS - 1)); float average = getAverageOnSensor(NUMBER_OF_SENSORS - 1); float expected_average = (SLIDING_WINDOW_SIZE + 1) / 2.0; assert(fabs(average - expected_average) < AVERAGE_UNCERTAINTY); } /** * @brief Test the standard deviation calculation on the last sensor with uniform data. * * This function tests the standard deviation calculation for the last sensor * in the array of sensors. It compares the calculated standard deviation with * an expected value to ensure the accuracy of the standard deviation function. * * The test uses the following steps: * 1. Calculate the standard deviation for the last sensor. * 2. Define the expected standard deviation value. * 3. Assert that the difference between the calculated and expected values is * within an acceptable uncertainty range (STD_UNCERTAINTY). * * @note The expected standard deviation value is hardcoded as 2.872281323269. */ void test_standardDeviationOnSensor_uniform() { //printf("Standard deviation on sensor %d: %f\n", NUMBER_OF_SENSORS - 1, getStandardDeviationOnSensor(NUMBER_OF_SENSORS - 1)); float standard_deviation = getStandardDeviationOnSensor(NUMBER_OF_SENSORS - 1); float expected_standard_deviation = 2.872281323269; assert(fabs(standard_deviation - expected_standard_deviation) < STD_UNCERTAINTY); } /** * @brief Test function to verify the average calculation on all sensors when the values are uniform. * * This function calculates the average value from all sensors using the `getAverageOnAllSensors` function * and compares it to the expected average value, which is defined by `SLIDING_WINDOW_SIZE`. * The test asserts that the difference between the calculated average and the expected average * is within the acceptable uncertainty range defined by `AVERAGE_UNCERTAINTY`. */ void test_averageOnAllSensors_uniform() { //printf("Average on all sensors: %f\n", getAverageOnAllSensors()); float average = getAverageOnAllSensors(); float expected_average = SLIDING_WINDOW_SIZE; assert(fabs(average - expected_average) < AVERAGE_UNCERTAINTY); } /** * @brief Test the standard deviation calculation on all sensors with uniform data. * * This function tests the `getStandardDeviationOnAllSensors` function by comparing * the calculated standard deviation with the expected value of 0. The test assumes * that all sensors have uniform data, resulting in a standard deviation of 0. * * The test passes if the absolute difference between the calculated standard deviation * and the expected standard deviation is less than the defined uncertainty (`STD_UNCERTAINTY`). * * @note The `printf` statement is commented out and can be used for debugging purposes * to print the calculated standard deviation. */ void test_standardDeviationOnAllSensors_uniform() { //printf("Standard deviation on all sensors: %f\n", getStandardDeviationOnAllSensors()); float standard_deviation = getStandardDeviationOnAllSensors(); float expected_standard_deviation = 0; assert(fabs(standard_deviation - expected_standard_deviation) < STD_UNCERTAINTY); } /** * @brief Test the overall average calculation with uniform sensor data. * * This function tests the `getOverallAverage` function by comparing the * calculated average with the expected average value when all sensors * have uniform data. The expected overall average is calculated as * (SLIDING_WINDOW_SIZE + 1) / 2.0. The test asserts that the difference * between the calculated average and the expected average is within * the defined uncertainty (AVERAGE_UNCERTAINTY). */ void test_overallAverage_uniform() { //printf("Overall average on all sensors: %f\n", getOverallAverage()); float average = getOverallAverage(); float expected_overall_average = (SLIDING_WINDOW_SIZE + 1) / 2.0; assert(fabs(average - expected_overall_average) < AVERAGE_UNCERTAINTY); } /** * @brief Test the overall standard deviation for uniform distribution. * * This function tests the standard deviation calculation for the last sensor * in a uniform distribution scenario. It compares the calculated standard * deviation with the expected value and asserts that the difference is within * an acceptable uncertainty range. * * @note The expected standard deviation value is hardcoded as 2.872281323269. * The acceptable uncertainty range is defined by the macro STD_UNCERTAINTY. */ void test_overallStandardDeviation_uniform() { //printf("Overall standard deviation: %f\n", getOverallStandardDeviation()); float standard_deviation = getStandardDeviationOnSensor(NUMBER_OF_SENSORS - 1); float expected_standard_deviation = 2.872281323269; assert(fabs(standard_deviation - expected_standard_deviation) < STD_UNCERTAINTY); } /** * @brief Test function for anomaly detection with uniform data. * * This function tests the anomaly detection mechanism by: * 1. Calculating the overall average and standard deviation of the data. * 2. Detecting anomalies based on the calculated average and standard deviation. * 3. Asserting that the initial outlier count is zero. * 4. Adding an outlier to the data. * 5. Recalculating the overall average and standard deviation. * 6. Detecting anomalies again with the updated data. * 7. Asserting that the outlier count is one after adding the outlier. * * The function uses the following helper functions: * - getOverallAverage(): Returns the overall average of the data. * - getOverallStandardDeviation(): Returns the overall standard deviation of the data. * - anomalyDetect(float average, float standard_deviation): Detects anomalies based on the provided average and standard deviation. * - getOutlierCount(): Returns the current count of outliers detected. * - addReading(float value): Adds a new reading to the data set. * * The assertions use a tolerance of 0.01 to account for floating-point precision errors. */ void test_anomalyDetect_uniform() { float average = getOverallAverage(); float standard_deviation = getOverallStandardDeviation(); anomalyDetect(average, standard_deviation); //printf("Outlier count: %i\n", getOutlierCount()); assert(fabs(getOutlierCount() - 0) < 0.01); // Adding an outlier addReading(20); average = getOverallAverage(); standard_deviation = getOverallStandardDeviation(); anomalyDetect(average, standard_deviation); //printf("Outlier count: %i\n", getOutlierCount()); assert(fabs(getOutlierCount() - 1) < 0.01); } /** * @brief Unit test for the freeReadings function. * * This function tests the freeReadings function to ensure it correctly * frees the allocated memory and returns true upon successful execution. * * @note This test uses the assert function to verify the expected behavior. */ void test_freeReadings() { assert(freeReadings() == true); } // TODO: Test all the functions with a normal distribution // TODO: Evaluate the normal distribution with the anomaly detection /** * @brief Test the initialization of sensor readings with normal parameters. * * This function tests the `initializeReadings` function by initializing the readings * with a specified number of sensors and sliding window size. It then asserts that * the number of sensors and the sliding window size are correctly set. * * @note This test assumes that the constants `NUMBER_OF_SENSORS` and `SLIDING_WINDOW_SIZE` * are defined elsewhere in the code. */ void test_initializeReadings_normal() { initializeReadings(NUMBER_OF_SENSORS, 100); assert(getSensorsNumber() == NUMBER_OF_SENSORS); assert(getSlidingWindowSize() == SLIDING_WINDOW_SIZE); } /** * @brief Test function to add readings to the data acquisition system. * * This function simulates adding readings to the data acquisition system * for all sensors over a sliding window. It generates random values * following a normal distribution with a specified mean and standard * deviation, and adds these values as readings for each sensor. * * The function then asserts that the data acquisition system is full * for the last sensor, indicating that readings have been successfully * added for all sensors. * * @note This test assumes that the last sensor (NUMBER_OF_SENSORS - 1) * has acquired the data. */ void test_addReading_normal() { for (int i = 0; i < SLIDING_WINDOW_SIZE; i++) { for (int sensor = 0; sensor < NUMBER_OF_SENSORS; sensor++) { float u1 = (float)rand() / RAND_MAX; float u2 = (float)rand() / RAND_MAX; float z0 = sqrt(-2.0 * log(u1)) * cos(2.0 * M_PI * u2); float value = NORMAL_DISTRIBUTION_MEAN + z0 * NORMAL_DISTRIBUTION_STDDEV; addReading(value); } } assert(isFull(NUMBER_OF_SENSORS - 1) == true); // Assuming the last sensor acquired the data } /** * @brief Test the average value on a sensor under normal conditions. * * This function calculates the average value on the last sensor (NUMBER_OF_SENSORS - 1) * and asserts that the difference between the calculated average and the expected mean * (NORMAL_DISTRIBUTION_MEAN) is within an acceptable range defined by AVERAGE_UNCERTAINTY * 50. * * The test ensures that the average value on the sensor is within the expected range, * indicating that the sensor data acquisition is functioning correctly under normal conditions. */ void test_averageOnSensor_normal() { //printf("Average on sensor %d: %f\n", NUMBER_OF_SENSORS - 1, getAverageOnSensor(NUMBER_OF_SENSORS - 1)); float average = getAverageOnSensor(NUMBER_OF_SENSORS - 1); assert(fabs(average - NORMAL_DISTRIBUTION_MEAN) < AVERAGE_UNCERTAINTY * 50); } /** * @brief Tests the standard deviation calculation on the last sensor. * * This function calculates the standard deviation for the last sensor * and asserts that the calculated value is within an acceptable range * of the expected standard deviation for a normal distribution. * * The acceptable range is defined as the expected standard deviation * (NORMAL_DISTRIBUTION_STDDEV) plus or minus a tolerance (STD_UNCERTAINTY * 100). * * @note This test assumes that the sensor data follows a normal distribution. */ void test_standardDeviationOnSensor_normal() { //printf("Standard deviation on sensor %d: %f\n", NUMBER_OF_SENSORS - 1, getStandardDeviationOnSensor(NUMBER_OF_SENSORS - 1)); float standard_deviation = getStandardDeviationOnSensor(NUMBER_OF_SENSORS - 1); assert(fabs(standard_deviation - NORMAL_DISTRIBUTION_STDDEV) < STD_UNCERTAINTY * 100); } /** * @brief Test the average value calculation on all sensors under normal conditions. * * This function tests the `getAverageOnAllSensors` function to ensure that the * average value calculated from all sensors is within an acceptable range of * the expected normal distribution mean. The acceptable range is defined by * `AVERAGE_UNCERTAINTY` multiplied by 100. * * The test asserts that the absolute difference between the calculated average * and the expected normal distribution mean (`NORMAL_DISTRIBUTION_MEAN`) is * less than the specified uncertainty range. */ void test_averageOnAllSensors_normal() { //printf("Average on all sensors: %f\n", getAverageOnAllSensors()); float average = getAverageOnAllSensors(); assert(fabs(average - NORMAL_DISTRIBUTION_MEAN) < AVERAGE_UNCERTAINTY * 100); } /** * @brief Test the standard deviation calculation on all sensors under normal conditions. * * This function tests the `getStandardDeviationOnAllSensors` function to ensure that the * calculated standard deviation is within an acceptable range of the expected normal * distribution standard deviation. The test asserts that the absolute difference between * the calculated standard deviation and the expected normal distribution standard deviation * is less than a specified uncertainty threshold. * * @note The expected normal distribution standard deviation is defined by the macro * `NORMAL_DISTRIBUTION_STDDEV`, and the acceptable uncertainty is defined by the macro * `STD_UNCERTAINTY`. */ void test_standardDeviationOnAllSensors_normal() { //printf("Standard deviation on all sensors: %f\n", getStandardDeviationOnAllSensors()); float standard_deviation = getStandardDeviationOnAllSensors(); assert(fabs(standard_deviation - NORMAL_DISTRIBUTION_STDDEV) < STD_UNCERTAINTY * 100); } /** * @brief Test the overall average calculation under normal conditions. * * This function tests the `getOverallAverage` function to ensure that the * calculated average of all sensors is within an acceptable range of the * expected normal distribution mean. The test asserts that the difference * between the calculated average and the expected mean is less than a * specified uncertainty threshold. * * @note The test uses the `fabs` function to compute the absolute difference * between the calculated average and the expected mean. */ void test_overallAverage_normal() { //printf("Overall average on all sensors: %f\n", getOverallAverage()); float average = getOverallAverage(); assert(fabs(average - NORMAL_DISTRIBUTION_MEAN) < AVERAGE_UNCERTAINTY * 100); } /** * @brief Test the overall standard deviation for normal distribution. * * This function tests the standard deviation calculation for the last sensor * in the array of sensors. It compares the calculated standard deviation * with the expected standard deviation for a normal distribution. * * The test passes if the absolute difference between the calculated standard * deviation and the expected standard deviation is less than the product of * the standard uncertainty and 100. * * @note The function `getStandardDeviationOnSensor` is used to get the * standard deviation for a specific sensor. * * @see getStandardDeviationOnSensor */ void test_overallStandardDeviation_normal() { //printf("Overall standard deviation: %f\n", getOverallStandardDeviation()); float standard_deviation = getStandardDeviationOnSensor(NUMBER_OF_SENSORS - 1); assert(fabs(standard_deviation - NORMAL_DISTRIBUTION_STDDEV) < STD_UNCERTAINTY * 100); } /** * @brief Tests the anomaly detection function under normal conditions. * * This function performs the following steps: * 1. Calculates the overall average and standard deviation of the data. * 2. Calls the anomaly detection function with the calculated average and standard deviation. * 3. Asserts that the number of detected outliers is within the expected range (assuming 5% of the data is outliers). * 4. Adds an outlier to the data. * 5. Recalculates the overall average and standard deviation. * 6. Calls the anomaly detection function again with the new average and standard deviation. * 7. Asserts that the number of detected outliers has increased by one. * * The test assumes that the number of sensors and the sliding window size are defined by the constants * NUMBER_OF_SENSORS and SLIDING_WINDOW_SIZE, respectively. It also assumes that the normal distribution * mean is defined by the constant NORMAL_DISTRIBUTION_MEAN. */ void test_anomalyDetect_normal() { float average = getOverallAverage(); float standard_deviation = getOverallStandardDeviation(); anomalyDetect(average, standard_deviation); //printf("Outlier count: %i\n", getOutlierCount()); assert(fabs(NUMBER_OF_SENSORS * SLIDING_WINDOW_SIZE * 0.05 >= getOutlierCount())); // Assuming 5% of the data is outliers // Adding an outlier addReading(NORMAL_DISTRIBUTION_MEAN * 100); average = getOverallAverage(); standard_deviation = getOverallStandardDeviation(); anomalyDetect(average, standard_deviation); //printf("Outlier count: %i\n", getOutlierCount()); assert(fabs(NUMBER_OF_SENSORS * SLIDING_WINDOW_SIZE * 0.05 + 1 >= getOutlierCount())); // Assuming 5% of the data is outliers and adding one more } void test_getMetrics() { // initialize a matrix of readings float **readings = (float **)malloc(NUMBER_OF_SENSORS * sizeof(float *)); for (int i = 0; i < NUMBER_OF_SENSORS; i++) { readings[i] = (float *)malloc(SLIDING_WINDOW_SIZE * sizeof(float)); for (int j = 0; j < SLIDING_WINDOW_SIZE; j++) { readings[i][j] = j + 1; } } // get metrics Metrics metrics = getMetrics(readings, NUMBER_OF_SENSORS, SLIDING_WINDOW_SIZE); printf("Metrics:\n"); printf("Mean: %f\n", metrics.mean); printf("Standard Deviation: %f\n", metrics.standardDeviation); printf("Possible Faulty Sensor: %d\n", metrics.possibleFaultySensor); } int main() { int tests_run = 0; int tests_passed = 0; printf("=== Test Suite ===\n"); #define RUN_TEST(test) do { \ printf("Progress: %.2f%%, Running %s...", (tests_run / (float)TEST_NUMBER) * 100, #test); \ test(); \ tests_run++; \ tests_passed++; \ printf("OK\n"); \ } while(0) srand(42); RUN_TEST(test_initializeReadings_uniform); RUN_TEST(test_addReading_uniform); RUN_TEST(test_averageOnSensor_uniform); RUN_TEST(test_standardDeviationOnSensor_uniform); RUN_TEST(test_averageOnAllSensors_uniform); RUN_TEST(test_standardDeviationOnAllSensors_uniform); RUN_TEST(test_overallAverage_uniform); RUN_TEST(test_overallStandardDeviation_uniform); RUN_TEST(test_anomalyDetect_uniform); RUN_TEST(test_addReading_normal); RUN_TEST(test_averageOnSensor_normal); RUN_TEST(test_standardDeviationOnSensor_normal); RUN_TEST(test_averageOnAllSensors_normal); RUN_TEST(test_standardDeviationOnAllSensors_normal); RUN_TEST(test_overallAverage_normal); RUN_TEST(test_overallStandardDeviation_normal); RUN_TEST(test_anomalyDetect_normal); RUN_TEST(test_freeReadings); RUN_TEST(test_getMetrics); printf("\n=== Results ===\n"); printf("Tests run: %d\n", tests_run); printf("Tests passed: %d\n", tests_passed); printf("Test coverage: %.2f%%\n", (tests_passed / (float)tests_run) * 100); return 0; }