Files
tbamud/tests/test_utils.c

483 lines
13 KiB
C
Raw 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.
/**
* @file test_utils.c
* Unit tests for pure / near-pure functions in src/utils.c
*/
#include "unity.h"
#include "conf.h"
#include "sysdep.h"
#include "structs.h"
#include "utils.h"
/* Redirect mud log output so basic_mud_vlog() doesn't print the
* "SYSERR: Using log() before stream was initialized!" warning. */
extern FILE *logfile;
void setUp(void) { logfile = stderr; }
void tearDown(void) { logfile = NULL; }
/* =========================================================
* prune_crlf
* ========================================================= */
void test_prune_crlf_strips_crlf(void)
{
char s[] = "hello\r\n";
prune_crlf(s);
TEST_ASSERT_EQUAL_STRING("hello", s);
}
void test_prune_crlf_strips_lf_only(void)
{
char s[] = "hello\n";
prune_crlf(s);
TEST_ASSERT_EQUAL_STRING("hello", s);
}
void test_prune_crlf_no_op_on_clean(void)
{
char s[] = "hello";
prune_crlf(s);
TEST_ASSERT_EQUAL_STRING("hello", s);
}
void test_prune_crlf_multiple_trailing(void)
{
char s[] = "hi\r\n\r\n";
prune_crlf(s);
TEST_ASSERT_EQUAL_STRING("hi", s);
}
/* =========================================================
* str_cmp (may be an alias for strcasecmp on this platform)
* ========================================================= */
void test_str_cmp_equal_strings(void)
{
TEST_ASSERT_EQUAL_INT(0, str_cmp("hello", "hello"));
}
void test_str_cmp_case_insensitive(void)
{
TEST_ASSERT_EQUAL_INT(0, str_cmp("Hello", "hello"));
TEST_ASSERT_EQUAL_INT(0, str_cmp("HELLO", "hello"));
}
void test_str_cmp_ordering_less(void)
{
TEST_ASSERT_LESS_THAN(0, str_cmp("a", "b"));
}
void test_str_cmp_ordering_greater(void)
{
TEST_ASSERT_GREATER_THAN(0, str_cmp("b", "a"));
}
void test_str_cmp_empty_equal(void)
{
TEST_ASSERT_EQUAL_INT(0, str_cmp("", ""));
}
/* =========================================================
* strn_cmp (may be an alias for strncasecmp on this platform)
* ========================================================= */
void test_strn_cmp_equal_prefix(void)
{
TEST_ASSERT_EQUAL_INT(0, strn_cmp("hello", "hello world", 5));
}
void test_strn_cmp_differ_past_n(void)
{
/* First 5 chars same, so strn_cmp("hello!", "hellox", 5) == 0 */
TEST_ASSERT_EQUAL_INT(0, strn_cmp("hello!", "hellox", 5));
}
void test_strn_cmp_differ_within_n(void)
{
TEST_ASSERT_NOT_EQUAL(0, strn_cmp("abc", "xyz", 3));
}
/* =========================================================
* sprintbit
* ========================================================= */
void test_sprintbit_no_bits_set(void)
{
static const char *names[] = { "FLAG_A", "FLAG_B", "\n" };
char result[256];
sprintbit(0, names, result, sizeof(result));
TEST_ASSERT_EQUAL_STRING("NOBITS ", result);
}
void test_sprintbit_single_bit(void)
{
static const char *names[] = { "FLAG_A", "FLAG_B", "\n" };
char result[256];
sprintbit(1, names, result, sizeof(result));
TEST_ASSERT_EQUAL_STRING("FLAG_A ", result);
}
void test_sprintbit_multiple_bits(void)
{
static const char *names[] = { "FLAG_A", "FLAG_B", "\n" };
char result[256];
sprintbit(3, names, result, sizeof(result));
TEST_ASSERT_EQUAL_STRING("FLAG_A FLAG_B ", result);
}
void test_sprintbit_undefined_bit(void)
{
/* Bit 2 is beyond the named array should produce "UNDEFINED" */
static const char *names[] = { "FLAG_A", "FLAG_B", "\n" };
char result[256];
sprintbit(4, names, result, sizeof(result));
TEST_ASSERT_EQUAL_STRING("UNDEFINED ", result);
}
/* =========================================================
* sprinttype
* ========================================================= */
void test_sprinttype_valid_index_zero(void)
{
static const char *names[] = { "ZERO", "ONE", "\n" };
char result[64];
sprinttype(0, names, result, sizeof(result));
TEST_ASSERT_EQUAL_STRING("ZERO", result);
}
void test_sprinttype_valid_index_one(void)
{
static const char *names[] = { "ZERO", "ONE", "\n" };
char result[64];
sprinttype(1, names, result, sizeof(result));
TEST_ASSERT_EQUAL_STRING("ONE", result);
}
void test_sprinttype_out_of_range(void)
{
static const char *names[] = { "ZERO", "ONE", "\n" };
char result[64];
sprinttype(5, names, result, sizeof(result));
TEST_ASSERT_EQUAL_STRING("UNDEFINED", result);
}
/* =========================================================
* levenshtein_distance
* ========================================================= */
void test_levenshtein_identical_strings(void)
{
TEST_ASSERT_EQUAL_INT(0, levenshtein_distance("hello", "hello"));
}
void test_levenshtein_empty_and_nonempty(void)
{
TEST_ASSERT_EQUAL_INT(5, levenshtein_distance("", "hello"));
TEST_ASSERT_EQUAL_INT(5, levenshtein_distance("hello", ""));
}
void test_levenshtein_single_insertion(void)
{
TEST_ASSERT_EQUAL_INT(1, levenshtein_distance("abc", "abcd"));
}
void test_levenshtein_single_deletion(void)
{
TEST_ASSERT_EQUAL_INT(1, levenshtein_distance("abcd", "abc"));
}
void test_levenshtein_single_substitution(void)
{
TEST_ASSERT_EQUAL_INT(1, levenshtein_distance("abc", "axc"));
}
void test_levenshtein_both_empty(void)
{
TEST_ASSERT_EQUAL_INT(0, levenshtein_distance("", ""));
}
/* =========================================================
* count_color_chars
* ========================================================= */
void test_count_color_chars_no_codes(void)
{
TEST_ASSERT_EQUAL_INT(0, count_color_chars("hello"));
}
void test_count_color_chars_empty(void)
{
TEST_ASSERT_EQUAL_INT(0, count_color_chars(""));
}
void test_count_color_chars_single_color_code(void)
{
/* "\tR" is a two-char color escape; both are skipped (counted as overhead) */
TEST_ASSERT_EQUAL_INT(2, count_color_chars("\tR"));
}
void test_count_color_chars_double_tab(void)
{
/* "\t\t" is an escaped literal tab; costs 1 overhead char */
TEST_ASSERT_EQUAL_INT(1, count_color_chars("\t\t"));
}
void test_count_color_chars_mixed(void)
{
/* "\tRhello" → 2 overhead + 0 for "hello" */
TEST_ASSERT_EQUAL_INT(2, count_color_chars("\tRhello"));
}
/* =========================================================
* count_non_protocol_chars
* ========================================================= */
void test_count_non_protocol_chars_plain(void)
{
TEST_ASSERT_EQUAL_INT(5, count_non_protocol_chars("hello"));
}
void test_count_non_protocol_chars_empty(void)
{
TEST_ASSERT_EQUAL_INT(0, count_non_protocol_chars(""));
}
void test_count_non_protocol_chars_newlines_skipped(void)
{
TEST_ASSERT_EQUAL_INT(5, count_non_protocol_chars("\r\nhello"));
}
void test_count_non_protocol_chars_bracket_tag(void)
{
/* "@[bold]hi" "@[bold]" is a protocol tag; only "hi" counted */
TEST_ASSERT_EQUAL_INT(2, count_non_protocol_chars("@[bold]hi"));
}
/* =========================================================
* atoidx
* ========================================================= */
void test_atoidx_valid_number(void)
{
TEST_ASSERT_EQUAL_INT(42, (int)atoidx("42"));
}
void test_atoidx_zero(void)
{
TEST_ASSERT_EQUAL_INT(0, (int)atoidx("0"));
}
void test_atoidx_negative_returns_nowhere(void)
{
TEST_ASSERT_EQUAL_INT((int)NOWHERE, (int)atoidx("-1"));
}
void test_atoidx_overflow_returns_nowhere(void)
{
/* IDXTYPE_MAX is 65535 on this build; a larger value overflows */
TEST_ASSERT_EQUAL_INT((int)NOWHERE, (int)atoidx("99999999"));
}
/* =========================================================
* right_trim_whitespace
* ========================================================= */
void test_right_trim_whitespace_trailing_spaces(void)
{
char *r = right_trim_whitespace("hello ");
TEST_ASSERT_EQUAL_STRING("hello", r);
free(r);
}
void test_right_trim_whitespace_no_trailing(void)
{
char *r = right_trim_whitespace("hello");
TEST_ASSERT_EQUAL_STRING("hello", r);
free(r);
}
void test_right_trim_whitespace_all_whitespace(void)
{
char *r = right_trim_whitespace(" ");
TEST_ASSERT_EQUAL_STRING("", r);
free(r);
}
void test_right_trim_whitespace_empty(void)
{
char *r = right_trim_whitespace("");
TEST_ASSERT_EQUAL_STRING("", r);
free(r);
}
/* =========================================================
* remove_from_string
* ========================================================= */
void test_remove_from_string_word_present(void)
{
char s[] = "hello world";
remove_from_string(s, "world");
/* "world" and the trailing NUL shift left; "hello " remains */
TEST_ASSERT_EQUAL_STRING("hello ", s);
}
void test_remove_from_string_word_absent(void)
{
char s[] = "hello world";
remove_from_string(s, "nope");
TEST_ASSERT_EQUAL_STRING("hello world", s);
}
void test_remove_from_string_word_at_start(void)
{
char s[] = "hello world";
remove_from_string(s, "hello");
/* "hello" removed; " world" remains */
TEST_ASSERT_EQUAL_STRING(" world", s);
}
/* =========================================================
* real_time_passed
* ========================================================= */
void test_real_time_passed_hours(void)
{
time_t base = 1000000;
struct time_info_data *t = real_time_passed(base + 3 * SECS_PER_REAL_HOUR, base);
TEST_ASSERT_EQUAL_INT(3, t->hours);
TEST_ASSERT_EQUAL_INT(0, t->day);
}
void test_real_time_passed_days(void)
{
time_t base = 1000000;
struct time_info_data *t = real_time_passed(base + 2 * SECS_PER_REAL_DAY + SECS_PER_REAL_HOUR, base);
TEST_ASSERT_EQUAL_INT(1, t->hours);
TEST_ASSERT_EQUAL_INT(2, t->day);
}
/* =========================================================
* mud_time_passed
* ========================================================= */
void test_mud_time_passed_hours(void)
{
time_t base = 1000000;
struct time_info_data *t = mud_time_passed(base + 2 * SECS_PER_MUD_HOUR, base);
TEST_ASSERT_EQUAL_INT(2, t->hours);
TEST_ASSERT_EQUAL_INT(0, t->day);
TEST_ASSERT_EQUAL_INT(0, t->month);
TEST_ASSERT_EQUAL_INT(0, t->year);
}
void test_mud_time_passed_days(void)
{
time_t base = 1000000;
struct time_info_data *t = mud_time_passed(base + SECS_PER_MUD_DAY, base);
TEST_ASSERT_EQUAL_INT(0, t->hours);
TEST_ASSERT_EQUAL_INT(1, t->day);
TEST_ASSERT_EQUAL_INT(0, t->month);
TEST_ASSERT_EQUAL_INT(0, t->year);
}
void test_mud_time_passed_months(void)
{
time_t base = 1000000;
struct time_info_data *t = mud_time_passed(base + SECS_PER_MUD_MONTH, base);
TEST_ASSERT_EQUAL_INT(0, t->hours);
TEST_ASSERT_EQUAL_INT(0, t->day);
TEST_ASSERT_EQUAL_INT(1, t->month);
TEST_ASSERT_EQUAL_INT(0, t->year);
}
/* =========================================================
* main
* ========================================================= */
int main(void)
{
UNITY_BEGIN();
/* prune_crlf */
RUN_TEST(test_prune_crlf_strips_crlf);
RUN_TEST(test_prune_crlf_strips_lf_only);
RUN_TEST(test_prune_crlf_no_op_on_clean);
RUN_TEST(test_prune_crlf_multiple_trailing);
/* str_cmp */
RUN_TEST(test_str_cmp_equal_strings);
RUN_TEST(test_str_cmp_case_insensitive);
RUN_TEST(test_str_cmp_ordering_less);
RUN_TEST(test_str_cmp_ordering_greater);
RUN_TEST(test_str_cmp_empty_equal);
/* strn_cmp */
RUN_TEST(test_strn_cmp_equal_prefix);
RUN_TEST(test_strn_cmp_differ_past_n);
RUN_TEST(test_strn_cmp_differ_within_n);
/* sprintbit */
RUN_TEST(test_sprintbit_no_bits_set);
RUN_TEST(test_sprintbit_single_bit);
RUN_TEST(test_sprintbit_multiple_bits);
RUN_TEST(test_sprintbit_undefined_bit);
/* sprinttype */
RUN_TEST(test_sprinttype_valid_index_zero);
RUN_TEST(test_sprinttype_valid_index_one);
RUN_TEST(test_sprinttype_out_of_range);
/* levenshtein_distance */
RUN_TEST(test_levenshtein_identical_strings);
RUN_TEST(test_levenshtein_empty_and_nonempty);
RUN_TEST(test_levenshtein_single_insertion);
RUN_TEST(test_levenshtein_single_deletion);
RUN_TEST(test_levenshtein_single_substitution);
RUN_TEST(test_levenshtein_both_empty);
/* count_color_chars */
RUN_TEST(test_count_color_chars_no_codes);
RUN_TEST(test_count_color_chars_empty);
RUN_TEST(test_count_color_chars_single_color_code);
RUN_TEST(test_count_color_chars_double_tab);
RUN_TEST(test_count_color_chars_mixed);
/* count_non_protocol_chars */
RUN_TEST(test_count_non_protocol_chars_plain);
RUN_TEST(test_count_non_protocol_chars_empty);
RUN_TEST(test_count_non_protocol_chars_newlines_skipped);
RUN_TEST(test_count_non_protocol_chars_bracket_tag);
/* atoidx */
RUN_TEST(test_atoidx_valid_number);
RUN_TEST(test_atoidx_zero);
RUN_TEST(test_atoidx_negative_returns_nowhere);
RUN_TEST(test_atoidx_overflow_returns_nowhere);
/* right_trim_whitespace */
RUN_TEST(test_right_trim_whitespace_trailing_spaces);
RUN_TEST(test_right_trim_whitespace_no_trailing);
RUN_TEST(test_right_trim_whitespace_all_whitespace);
RUN_TEST(test_right_trim_whitespace_empty);
/* remove_from_string */
RUN_TEST(test_remove_from_string_word_present);
RUN_TEST(test_remove_from_string_word_absent);
RUN_TEST(test_remove_from_string_word_at_start);
/* real_time_passed */
RUN_TEST(test_real_time_passed_hours);
RUN_TEST(test_real_time_passed_days);
/* mud_time_passed */
RUN_TEST(test_mud_time_passed_hours);
RUN_TEST(test_mud_time_passed_days);
RUN_TEST(test_mud_time_passed_months);
return UNITY_END();
}