Add files via upload
This commit is contained in:
438
tests.c
Normal file
438
tests.c
Normal file
@@ -0,0 +1,438 @@
|
||||
#include "dynamic_array.h"
|
||||
#include "types.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// Подсчёт тестов
|
||||
|
||||
static int tests_passed = 0;
|
||||
static int tests_failed = 0;
|
||||
|
||||
#define TEST(name) static bool name(void)
|
||||
#define RUN(name) do { \
|
||||
printf(" %-50s", #name); \
|
||||
if (name()) { \
|
||||
tests_passed++; \
|
||||
printf(" [OK]\n"); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ASSERT(cond) do { \
|
||||
if (!(cond)) { \
|
||||
printf(" [FAIL] %s:%d: %s\n", __FILE__, __LINE__, #cond); \
|
||||
tests_failed++; \
|
||||
return false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// --------------- ТЕСТЫ ---------------
|
||||
// Создание и базовые операции
|
||||
|
||||
TEST(test_create_destroy) {
|
||||
DynamicArray *arr = da_create(get_double_type(), 0);
|
||||
ASSERT(arr != NULL);
|
||||
ASSERT(da_size(arr) == 0);
|
||||
da_destroy(arr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(test_push_back_double) {
|
||||
DynamicArray *arr = da_create(get_double_type(), 0);
|
||||
const double vals[] = {1.1, 2.2, 3.3};
|
||||
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
da_push_back(arr, &vals[i]);
|
||||
}
|
||||
ASSERT(da_size(arr) == 3);
|
||||
ASSERT(*(double *)da_get(arr, 0) == 1.1);
|
||||
ASSERT(*(double *)da_get(arr, 1) == 2.2);
|
||||
ASSERT(*(double *)da_get(arr, 2) == 3.3);
|
||||
da_destroy(arr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(test_push_back_complex) {
|
||||
DynamicArray *arr = da_create(get_complex_type(), 0);
|
||||
const Complex vals[] = {
|
||||
{1.1, 1}, {2.2, 2}, {3.3, 3}
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
da_push_back(arr, &vals[i]);
|
||||
}
|
||||
Complex *c_get;
|
||||
ASSERT(da_size(arr) == 3);
|
||||
|
||||
c_get = (Complex *) da_get(arr, 0);
|
||||
ASSERT(c_get->re == 1.1 && c_get->im == 1);
|
||||
c_get = (Complex *) da_get(arr, 1);
|
||||
ASSERT(c_get->re == 2.2 && c_get->im == 2);
|
||||
c_get = (Complex *) da_get(arr, 2);
|
||||
ASSERT(c_get->re == 3.3 && c_get->im == 3);
|
||||
da_destroy(arr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(test_set_get) {
|
||||
DynamicArray *arr = da_create(get_double_type(), 0);
|
||||
const double v1 = 42, v2 = 99;
|
||||
da_push_back(arr, &v1);
|
||||
ASSERT(*(double *)da_get(arr, 0) == 42);
|
||||
da_set(arr, 0, &v2);
|
||||
ASSERT(*(double *)da_get(arr, 0) == 99);
|
||||
da_destroy(arr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(test_insert) {
|
||||
DynamicArray *arr = da_create(get_double_type(), 0);
|
||||
const double a = 1, b = 2, c = 3, ins = 99;
|
||||
da_push_back(arr, &a);
|
||||
da_push_back(arr, &b);
|
||||
da_push_back(arr, &c);
|
||||
da_insert(arr, 1, &ins);
|
||||
ASSERT(da_size(arr) == 4);
|
||||
ASSERT(*(double *)da_get(arr, 0) == 1);
|
||||
ASSERT(*(double *)da_get(arr, 1) == 99);
|
||||
ASSERT(*(double *)da_get(arr, 2) == 2);
|
||||
ASSERT(*(double *)da_get(arr, 3) == 3);
|
||||
da_destroy(arr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(test_remove) {
|
||||
DynamicArray *arr = da_create(get_double_type(), 0);
|
||||
const double vals[] = {10, 20, 30};
|
||||
for (int i = 0; i < 3; i++) da_push_back(arr, &vals[i]);
|
||||
da_remove(arr, 1);
|
||||
ASSERT(da_size(arr) == 2);
|
||||
ASSERT(*(double *)da_get(arr, 0) == 10);
|
||||
ASSERT(*(double *)da_get(arr, 1) == 30);
|
||||
da_destroy(arr);
|
||||
|
||||
return true;
|
||||
}
|
||||
// Граничные случаи
|
||||
|
||||
TEST(test_get_out_of_bounds) {
|
||||
DynamicArray *arr = da_create(get_double_type(), 0);
|
||||
ASSERT(da_get(arr, 0) == NULL);
|
||||
const double v = 1;
|
||||
da_push_back(arr, &v);
|
||||
ASSERT(da_get(arr, 1) == NULL);
|
||||
ASSERT(da_get(arr, 100) == NULL);
|
||||
da_destroy(arr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(test_remove_out_of_bounds) {
|
||||
DynamicArray *arr = da_create(get_double_type(), 0);
|
||||
ASSERT(da_remove(arr, 0) == false);
|
||||
da_destroy(arr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(test_empty_array_operations) {
|
||||
DynamicArray *arr = da_create(get_double_type(), 0);
|
||||
da_sort(arr); // Не должен ломаться
|
||||
ASSERT(da_size(arr) == 0);
|
||||
da_destroy(arr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(test_create_null_type) {
|
||||
DynamicArray *arr = da_create(NULL, 0);
|
||||
ASSERT(arr == NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(test_capacity_growth) {
|
||||
DynamicArray *arr = da_create(get_int_type(), 2);
|
||||
for (int i = 0; i < 100; i++)
|
||||
ASSERT(da_push_back(arr, &i));
|
||||
ASSERT(da_size(arr) >= 100);
|
||||
for (int i = 0; i < 100; i++)
|
||||
ASSERT(*(int *)da_get(arr, i) == i);
|
||||
da_destroy(arr);
|
||||
|
||||
return true;
|
||||
}
|
||||
// Сортировка
|
||||
|
||||
TEST(test_sort_double) {
|
||||
DynamicArray *arr = da_create(get_double_type(), 0);
|
||||
const double vals[] = {3.14, 1.0, 2.71, 0.5};
|
||||
for (int i = 0; i < 4; i++) da_push_back(arr, &vals[i]);
|
||||
da_sort(arr);
|
||||
for (size_t i = 1; i < da_size(arr); i++)
|
||||
ASSERT(*(double *)da_get(arr, i - 1) <= *(double *)da_get(arr, i));
|
||||
da_destroy(arr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(test_sort_complex) {
|
||||
DynamicArray *arr = da_create(get_complex_type(), 0);
|
||||
const Complex vals[] = {
|
||||
{3, 4}, {1, 0}, {0, 2}
|
||||
}; // |5|, |1|, |2|
|
||||
for (int i = 0; i < 3; i++) da_push_back(arr, &vals[i]);
|
||||
da_sort(arr);
|
||||
|
||||
// Порядок по модулю: (1,0), (0,2), (3,4)
|
||||
const Complex *c0 = da_get(arr, 0);
|
||||
const Complex *c1 = da_get(arr, 1);
|
||||
const Complex *c2 = da_get(arr, 2);
|
||||
ASSERT(c0->re == 1.0 && c0->im == 0.0);
|
||||
ASSERT(c1->re == 0.0 && c1->im == 2.0);
|
||||
ASSERT(c2->re == 3.0 && c2->im == 4.0);
|
||||
da_destroy(arr);
|
||||
|
||||
return true;
|
||||
}
|
||||
// map
|
||||
|
||||
static void double_value(void *dest, const void *src) {
|
||||
*(double *)dest = *(const double *)src * 2;
|
||||
}
|
||||
|
||||
TEST(test_map_double) {
|
||||
DynamicArray *arr = da_create(get_double_type(), 0);
|
||||
const double vals[] = {1.0, 2.0, 3.0};
|
||||
for (int i = 0; i < 3; i++) da_push_back(arr, &vals[i]);
|
||||
DynamicArray *mapped = da_map(arr, double_value);
|
||||
ASSERT(mapped != NULL);
|
||||
ASSERT(da_size(mapped) == 3);
|
||||
ASSERT(*(double *)da_get(mapped, 0) == 2.0);
|
||||
ASSERT(*(double *)da_get(mapped, 1) == 4.0);
|
||||
ASSERT(*(double *)da_get(mapped, 2) == 6.0);
|
||||
da_destroy(arr);
|
||||
da_destroy(mapped);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(test_map_empty) {
|
||||
DynamicArray *arr = da_create(get_double_type(), 0);
|
||||
DynamicArray *mapped = da_map(arr, double_value);
|
||||
ASSERT(mapped != NULL);
|
||||
ASSERT(da_size(mapped) == 0);
|
||||
da_destroy(arr);
|
||||
da_destroy(mapped);
|
||||
|
||||
return true;
|
||||
}
|
||||
// where
|
||||
|
||||
static bool is_positive(const void *elem) {
|
||||
return *(const double *)elem > 0;
|
||||
}
|
||||
|
||||
static bool is_real(const void *elem) {
|
||||
const Complex *c_elem = (Complex *)elem;
|
||||
return c_elem->im == 0;
|
||||
}
|
||||
|
||||
TEST(test_where_double) {
|
||||
DynamicArray *arr = da_create(get_double_type(), 0);
|
||||
const double vals[] = {-1.0, 2.5, -3.0, 4.0};
|
||||
for (int i = 0; i < 4; i++)
|
||||
da_push_back(arr, &vals[i]);
|
||||
DynamicArray *filtered = da_where(arr, is_positive);
|
||||
ASSERT(da_size(filtered) == 2);
|
||||
ASSERT(*(double *)da_get(filtered, 0) == 2.5);
|
||||
ASSERT(*(double *)da_get(filtered, 1) == 4.0);
|
||||
da_destroy(arr);
|
||||
da_destroy(filtered);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(test_where_complex) {
|
||||
DynamicArray *arr = da_create(get_complex_type(), 0);
|
||||
const Complex vals[] = {
|
||||
{1.0, 2.0}, {4.0, 0.0}, {-1.0, 1.0}
|
||||
};
|
||||
for (int i = 0; i < 3; i++)
|
||||
da_push_back(arr, &vals[i]);
|
||||
DynamicArray *filtered = da_where(arr, is_real);
|
||||
ASSERT(da_size(filtered) == 1);
|
||||
const Complex *num = da_get(filtered, 0);
|
||||
ASSERT(num->re == 4.0 && num->im == 0.0);
|
||||
da_destroy(arr);
|
||||
da_destroy(filtered);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(test_where_none_match) {
|
||||
DynamicArray *arr = da_create(get_double_type(), 0);
|
||||
const double vals[] = {-1.0, -3.0, -5.0};
|
||||
for (int i = 0; i < 3; i++) da_push_back(arr, &vals[i]);
|
||||
DynamicArray *filtered = da_where(arr, is_positive);
|
||||
ASSERT(da_size(filtered) == 0);
|
||||
da_destroy(arr);
|
||||
da_destroy(filtered);
|
||||
|
||||
return true;
|
||||
}
|
||||
// reduce
|
||||
|
||||
static void sum_reduce_double(void *acc, const void *elem) {
|
||||
*(double *)acc += *(const double *)elem;
|
||||
}
|
||||
|
||||
static void sum_reduce_complex(void *acc, const void *elem) {
|
||||
Complex *c_acc = (Complex *)acc;
|
||||
const Complex *c_elem = (const Complex *)elem;
|
||||
|
||||
c_acc->re += c_elem->re;
|
||||
c_acc->im += c_elem->im;
|
||||
}
|
||||
|
||||
TEST(test_reduce_sum_double) {
|
||||
DynamicArray *arr = da_create(get_double_type(), 0);
|
||||
const double vals[] = {1.0, 2.0, 3.0, 4.0, 5.0};
|
||||
for (int i = 0; i < 5; i++) da_push_back(arr, &vals[i]);
|
||||
|
||||
double initial = 0.0, result = 0.0;
|
||||
da_reduce(arr, sum_reduce_double, &initial, &result);
|
||||
ASSERT(result == 15.0);
|
||||
da_destroy(arr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(test_reduce_sum_complex) {
|
||||
DynamicArray *arr = da_create(get_complex_type(), 0);
|
||||
const Complex vals[] = {
|
||||
{1.0, 0.0}, {2.0, 1.0}, {3.0, 2.0}
|
||||
};
|
||||
for (int i = 0; i < 3; i++) da_push_back(arr, &vals[i]);
|
||||
|
||||
Complex initial = {0.0, 0.0}, result = {0.0, 0.0};
|
||||
da_reduce(arr, sum_reduce_complex, &initial, &result);
|
||||
|
||||
ASSERT(result.re == 6.0 && result.im == 3.0);
|
||||
da_destroy(arr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(test_reduce_empty) {
|
||||
DynamicArray *arr = da_create(get_double_type(), 0);
|
||||
double initial = 42.0, result = 0.0;
|
||||
da_reduce(arr, sum_reduce_double, &initial, &result);
|
||||
ASSERT(result == 42);
|
||||
da_destroy(arr);
|
||||
|
||||
return true;
|
||||
}
|
||||
// Конкатенация
|
||||
|
||||
TEST(test_concat_double) {
|
||||
DynamicArray *a = da_create(get_double_type(), 0);
|
||||
DynamicArray *b = da_create(get_double_type(), 0);
|
||||
const double v1 = 1.0, v2 = 2.0, v3 = 3.0, v4 = 4.0;
|
||||
da_push_back(a, &v1);
|
||||
da_push_back(a, &v2);
|
||||
da_push_back(b, &v3);
|
||||
da_push_back(b, &v4);
|
||||
|
||||
DynamicArray *c = da_concat(a, b);
|
||||
|
||||
ASSERT(c != NULL);
|
||||
ASSERT(da_size(c) == 4);
|
||||
ASSERT(*(double *)da_get(c, 0) == 1.0);
|
||||
ASSERT(*(double *)da_get(c, 1) == 2.0);
|
||||
ASSERT(*(double *)da_get(c, 2) == 3.0);
|
||||
ASSERT(*(double *)da_get(c, 3) == 4.0);
|
||||
|
||||
da_destroy(a);
|
||||
da_destroy(b);
|
||||
da_destroy(c);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(test_concat_type_mismatch) {
|
||||
DynamicArray *a = da_create(get_double_type(), 0);
|
||||
DynamicArray *b = da_create(get_complex_type(), 0);
|
||||
DynamicArray *c = da_concat(a, b);
|
||||
ASSERT(c == NULL); // Несовпадение типов
|
||||
da_destroy(a);
|
||||
da_destroy(b);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST(test_concat_with_empty) {
|
||||
DynamicArray *a = da_create(get_double_type(), 0);
|
||||
DynamicArray *b = da_create(get_double_type(), 0);
|
||||
const double v = 42.0;
|
||||
da_push_back(a, &v);
|
||||
DynamicArray *c = da_concat(a, b);
|
||||
ASSERT(da_size(c) == 1);
|
||||
ASSERT(*(double *)da_get(c, 0) == 42.0);
|
||||
da_destroy(a);
|
||||
da_destroy(b);
|
||||
da_destroy(c);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
printf(" === Модульные тесты ===\n");
|
||||
|
||||
printf("--- Создание и базовые операции ---\n");
|
||||
RUN(test_create_destroy);
|
||||
RUN(test_push_back_double);
|
||||
RUN(test_push_back_complex);
|
||||
RUN(test_set_get);
|
||||
RUN(test_insert);
|
||||
RUN(test_remove);
|
||||
|
||||
printf("--- Граничные случаи ---\n");
|
||||
RUN(test_get_out_of_bounds);
|
||||
RUN(test_remove_out_of_bounds);
|
||||
RUN(test_empty_array_operations);
|
||||
RUN(test_create_null_type);
|
||||
RUN(test_capacity_growth);
|
||||
|
||||
printf("--- Сортировка ---\n");
|
||||
RUN(test_sort_double);
|
||||
RUN(test_sort_complex);
|
||||
|
||||
printf("--- map ---\n");
|
||||
RUN(test_map_double);
|
||||
RUN(test_map_empty);
|
||||
|
||||
printf("--- where ---\n");
|
||||
RUN(test_where_double);
|
||||
RUN(test_where_complex);
|
||||
RUN(test_where_none_match);
|
||||
|
||||
printf("--- reduce ---\n");
|
||||
RUN(test_reduce_sum_double);
|
||||
RUN(test_reduce_sum_complex);
|
||||
RUN(test_reduce_empty);
|
||||
|
||||
printf("--- Конкатенация ---\n");
|
||||
RUN(test_concat_double);
|
||||
RUN(test_concat_type_mismatch);
|
||||
RUN(test_concat_with_empty);
|
||||
|
||||
printf("\n======================\n");
|
||||
printf("Итого: %d пройдено, %d провалено\n", tests_passed, tests_failed);
|
||||
|
||||
return tests_failed > 0 ? 1 : 0;
|
||||
}
|
||||
Reference in New Issue
Block a user