#include "dynamic_array.h" #include "types.h" #include #include // Подсчёт тестов 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; }