Files
dynamic-array/tests.c
2026-02-22 16:50:46 +03:00

439 lines
11 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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;
}