/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* main.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: yiyuli +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/12/01 00:00:00 by yiyuli #+# #+# */ /* Updated: 2025/12/01 00:00:00 by yiyuli ### ########.fr */ /* */ /* ************************************************************************** */ #include "ft_printf.h" #include #include #include #define RED "\033[0;31m" #define GREEN "\033[0;32m" #define YELLOW "\033[0;33m" #define RESET "\033[0m" static int g_tests = 0; static int g_passed = 0; void print_header(const char *title) { printf("\n%s========== %s ==========%s\n", YELLOW, title, RESET); } void compare_return(int ft_ret, int std_ret, const char *test_name) { g_tests++; if (ft_ret == std_ret) { g_passed++; printf("%s[PASS]%s %s (ret: %d)\n", GREEN, RESET, test_name, ft_ret); } else { printf("%s[FAIL]%s %s (ft: %d, std: %d)\n", RED, RESET, test_name, ft_ret, std_ret); } } int main(void) { int ft_ret; int std_ret; char *null_str = NULL; void *null_ptr = NULL; printf("\n%s╔══════════════════════════════════════════════════════════╗%s\n", YELLOW, RESET); printf("%s║ ft_printf COMPREHENSIVE TEST SUITE ║%s\n", YELLOW, RESET); printf("%s╚══════════════════════════════════════════════════════════╝%s\n", YELLOW, RESET); /* ==================== CHARACTER TESTS ==================== */ print_header("CHARACTER (%c) TESTS"); printf("ft: "); ft_ret = ft_printf("%c\n", 'a'); printf("std: "); std_ret = printf("%c\n", 'a'); compare_return(ft_ret, std_ret, "simple char 'a'"); printf("ft: "); ft_ret = ft_printf("%c\n", 'Z'); printf("std: "); std_ret = printf("%c\n", 'Z'); compare_return(ft_ret, std_ret, "uppercase char 'Z'"); printf("ft: "); ft_ret = ft_printf("%c\n", '0'); printf("std: "); std_ret = printf("%c\n", '0'); compare_return(ft_ret, std_ret, "digit char '0'"); printf("ft: "); ft_ret = ft_printf("%c\n", ' '); printf("std: "); std_ret = printf("%c\n", ' '); compare_return(ft_ret, std_ret, "space char"); printf("ft: "); ft_ret = ft_printf("%c\n", '\t'); printf("std: "); std_ret = printf("%c\n", '\t'); compare_return(ft_ret, std_ret, "tab char"); printf("ft: "); ft_ret = ft_printf("%c\n", 0); printf("std: "); std_ret = printf("%c\n", 0); compare_return(ft_ret, std_ret, "null char (0)"); printf("ft: "); ft_ret = ft_printf("%c\n", 127); printf("std: "); std_ret = printf("%c\n", 127); compare_return(ft_ret, std_ret, "DEL char (127)"); printf("ft: "); ft_ret = ft_printf("%c\n", -128); printf("std: "); std_ret = printf("%c\n", -128); compare_return(ft_ret, std_ret, "char -128 (overflow)"); printf("ft: "); ft_ret = ft_printf("%c%c%c\n", 'a', 'b', 'c'); printf("std: "); std_ret = printf("%c%c%c\n", 'a', 'b', 'c'); compare_return(ft_ret, std_ret, "multiple chars 'abc'"); /* ==================== STRING TESTS ==================== */ print_header("STRING (%s) TESTS"); printf("ft: "); ft_ret = ft_printf("%s\n", "Hello, World!"); printf("std: "); std_ret = printf("%s\n", "Hello, World!"); compare_return(ft_ret, std_ret, "simple string"); printf("ft: "); ft_ret = ft_printf("%s\n", ""); printf("std: "); std_ret = printf("%s\n", ""); compare_return(ft_ret, std_ret, "empty string"); printf("ft: "); ft_ret = ft_printf("%s\n", null_str); printf("std: "); std_ret = printf("%s\n", null_str); compare_return(ft_ret, std_ret, "NULL string"); printf("ft: "); ft_ret = ft_printf("%s\n", " "); printf("std: "); std_ret = printf("%s\n", " "); compare_return(ft_ret, std_ret, "whitespace only"); printf("ft: "); ft_ret = ft_printf("%s\n", "\t\n\r"); printf("std: "); std_ret = printf("%s\n", "\t\n\r"); compare_return(ft_ret, std_ret, "escape sequences"); printf("ft: "); ft_ret = ft_printf("%s%s%s\n", "Hello", " ", "World"); printf("std: "); std_ret = printf("%s%s%s\n", "Hello", " ", "World"); compare_return(ft_ret, std_ret, "multiple strings"); printf("ft: "); ft_ret = ft_printf("%s\n", "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); printf("std: "); std_ret = printf("%s\n", "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); compare_return(ft_ret, std_ret, "long alphanumeric string"); /* ==================== POINTER TESTS ==================== */ print_header("POINTER (%p) TESTS"); int test_int = 42; char test_char = 'x'; char *test_str = "test"; printf("ft: "); ft_ret = ft_printf("%p\n", &test_int); printf("std: "); std_ret = printf("%p\n", &test_int); compare_return(ft_ret, std_ret, "int pointer"); printf("ft: "); ft_ret = ft_printf("%p\n", &test_char); printf("std: "); std_ret = printf("%p\n", &test_char); compare_return(ft_ret, std_ret, "char pointer"); printf("ft: "); ft_ret = ft_printf("%p\n", test_str); printf("std: "); std_ret = printf("%p\n", test_str); compare_return(ft_ret, std_ret, "string pointer"); printf("ft: "); ft_ret = ft_printf("%p\n", null_ptr); printf("std: "); std_ret = printf("%p\n", null_ptr); compare_return(ft_ret, std_ret, "NULL pointer"); printf("ft: "); ft_ret = ft_printf("%p\n", (void *)1); printf("std: "); std_ret = printf("%p\n", (void *)1); compare_return(ft_ret, std_ret, "pointer value 1"); printf("ft: "); ft_ret = ft_printf("%p\n", (void *)LONG_MAX); printf("std: "); std_ret = printf("%p\n", (void *)LONG_MAX); compare_return(ft_ret, std_ret, "LONG_MAX as pointer"); printf("ft: "); ft_ret = ft_printf("%p\n", (void *)ULONG_MAX); printf("std: "); std_ret = printf("%p\n", (void *)ULONG_MAX); compare_return(ft_ret, std_ret, "ULONG_MAX as pointer"); printf("ft: "); ft_ret = ft_printf("%p%p\n", &test_int, &test_char); printf("std: "); std_ret = printf("%p%p\n", &test_int, &test_char); compare_return(ft_ret, std_ret, "multiple pointers"); /* ==================== DECIMAL/INTEGER TESTS ==================== */ print_header("DECIMAL/INTEGER (%d/%i) TESTS"); printf("ft: "); ft_ret = ft_printf("%d\n", 0); printf("std: "); std_ret = printf("%d\n", 0); compare_return(ft_ret, std_ret, "zero"); printf("ft: "); ft_ret = ft_printf("%d\n", 42); printf("std: "); std_ret = printf("%d\n", 42); compare_return(ft_ret, std_ret, "positive 42"); printf("ft: "); ft_ret = ft_printf("%d\n", -42); printf("std: "); std_ret = printf("%d\n", -42); compare_return(ft_ret, std_ret, "negative -42"); printf("ft: "); ft_ret = ft_printf("%d\n", INT_MAX); printf("std: "); std_ret = printf("%d\n", INT_MAX); compare_return(ft_ret, std_ret, "INT_MAX"); printf("ft: "); ft_ret = ft_printf("%d\n", INT_MIN); printf("std: "); std_ret = printf("%d\n", INT_MIN); compare_return(ft_ret, std_ret, "INT_MIN"); printf("ft: "); ft_ret = ft_printf("%d\n", (int)-2147483648); printf("std: "); std_ret = printf("%d\n", (int)-2147483648); compare_return(ft_ret, std_ret, "-2147483648 literal"); printf("ft: "); ft_ret = ft_printf("%i\n", 0); printf("std: "); std_ret = printf("%i\n", 0); compare_return(ft_ret, std_ret, "%i zero"); printf("ft: "); ft_ret = ft_printf("%i\n", INT_MAX); printf("std: "); std_ret = printf("%i\n", INT_MAX); compare_return(ft_ret, std_ret, "%i INT_MAX"); printf("ft: "); ft_ret = ft_printf("%i\n", INT_MIN); printf("std: "); std_ret = printf("%i\n", INT_MIN); compare_return(ft_ret, std_ret, "%i INT_MIN"); printf("ft: "); ft_ret = ft_printf("%d%d%d\n", 1, 2, 3); printf("std: "); std_ret = printf("%d%d%d\n", 1, 2, 3); compare_return(ft_ret, std_ret, "multiple decimals"); printf("ft: "); ft_ret = ft_printf("%d\n", 1); printf("std: "); std_ret = printf("%d\n", 1); compare_return(ft_ret, std_ret, "single digit 1"); printf("ft: "); ft_ret = ft_printf("%d\n", -1); printf("std: "); std_ret = printf("%d\n", -1); compare_return(ft_ret, std_ret, "single digit -1"); printf("ft: "); ft_ret = ft_printf("%d\n", 10); printf("std: "); std_ret = printf("%d\n", 10); compare_return(ft_ret, std_ret, "10"); printf("ft: "); ft_ret = ft_printf("%d\n", -10); printf("std: "); std_ret = printf("%d\n", -10); compare_return(ft_ret, std_ret, "-10"); /* ==================== UNSIGNED TESTS ==================== */ print_header("UNSIGNED (%u) TESTS"); printf("ft: "); ft_ret = ft_printf("%u\n", 0); printf("std: "); std_ret = printf("%u\n", 0); compare_return(ft_ret, std_ret, "unsigned zero"); printf("ft: "); ft_ret = ft_printf("%u\n", 42); printf("std: "); std_ret = printf("%u\n", 42); compare_return(ft_ret, std_ret, "unsigned 42"); printf("ft: "); ft_ret = ft_printf("%u\n", UINT_MAX); printf("std: "); std_ret = printf("%u\n", UINT_MAX); compare_return(ft_ret, std_ret, "UINT_MAX"); printf("ft: "); ft_ret = ft_printf("%u\n", 4294967295U); printf("std: "); std_ret = printf("%u\n", 4294967295U); compare_return(ft_ret, std_ret, "4294967295U literal"); printf("ft: "); ft_ret = ft_printf("%u\n", (unsigned int)-1); printf("std: "); std_ret = printf("%u\n", (unsigned int)-1); compare_return(ft_ret, std_ret, "(unsigned int)-1"); printf("ft: "); ft_ret = ft_printf("%u\n", (unsigned int)-42); printf("std: "); std_ret = printf("%u\n", (unsigned int)-42); compare_return(ft_ret, std_ret, "(unsigned int)-42"); printf("ft: "); ft_ret = ft_printf("%u%u%u\n", 1, 2, 3); printf("std: "); std_ret = printf("%u%u%u\n", 1, 2, 3); compare_return(ft_ret, std_ret, "multiple unsigned"); /* ==================== LOWERCASE HEX TESTS ==================== */ print_header("LOWERCASE HEX (%x) TESTS"); printf("ft: "); ft_ret = ft_printf("%x\n", 0); printf("std: "); std_ret = printf("%x\n", 0); compare_return(ft_ret, std_ret, "hex zero"); printf("ft: "); ft_ret = ft_printf("%x\n", 10); printf("std: "); std_ret = printf("%x\n", 10); compare_return(ft_ret, std_ret, "hex 10 (a)"); printf("ft: "); ft_ret = ft_printf("%x\n", 15); printf("std: "); std_ret = printf("%x\n", 15); compare_return(ft_ret, std_ret, "hex 15 (f)"); printf("ft: "); ft_ret = ft_printf("%x\n", 16); printf("std: "); std_ret = printf("%x\n", 16); compare_return(ft_ret, std_ret, "hex 16 (10)"); printf("ft: "); ft_ret = ft_printf("%x\n", 255); printf("std: "); std_ret = printf("%x\n", 255); compare_return(ft_ret, std_ret, "hex 255 (ff)"); printf("ft: "); ft_ret = ft_printf("%x\n", 256); printf("std: "); std_ret = printf("%x\n", 256); compare_return(ft_ret, std_ret, "hex 256 (100)"); printf("ft: "); ft_ret = ft_printf("%x\n", UINT_MAX); printf("std: "); std_ret = printf("%x\n", UINT_MAX); compare_return(ft_ret, std_ret, "hex UINT_MAX"); printf("ft: "); ft_ret = ft_printf("%x\n", 0xdeadbeef); printf("std: "); std_ret = printf("%x\n", 0xdeadbeef); compare_return(ft_ret, std_ret, "hex deadbeef"); printf("ft: "); ft_ret = ft_printf("%x\n", (unsigned int)-1); printf("std: "); std_ret = printf("%x\n", (unsigned int)-1); compare_return(ft_ret, std_ret, "hex (unsigned)-1"); printf("ft: "); ft_ret = ft_printf("%x%x%x\n", 10, 11, 12); printf("std: "); std_ret = printf("%x%x%x\n", 10, 11, 12); compare_return(ft_ret, std_ret, "multiple hex"); /* ==================== UPPERCASE HEX TESTS ==================== */ print_header("UPPERCASE HEX (%X) TESTS"); printf("ft: "); ft_ret = ft_printf("%X\n", 0); printf("std: "); std_ret = printf("%X\n", 0); compare_return(ft_ret, std_ret, "HEX zero"); printf("ft: "); ft_ret = ft_printf("%X\n", 10); printf("std: "); std_ret = printf("%X\n", 10); compare_return(ft_ret, std_ret, "HEX 10 (A)"); printf("ft: "); ft_ret = ft_printf("%X\n", 15); printf("std: "); std_ret = printf("%X\n", 15); compare_return(ft_ret, std_ret, "HEX 15 (F)"); printf("ft: "); ft_ret = ft_printf("%X\n", 255); printf("std: "); std_ret = printf("%X\n", 255); compare_return(ft_ret, std_ret, "HEX 255 (FF)"); printf("ft: "); ft_ret = ft_printf("%X\n", UINT_MAX); printf("std: "); std_ret = printf("%X\n", UINT_MAX); compare_return(ft_ret, std_ret, "HEX UINT_MAX"); printf("ft: "); ft_ret = ft_printf("%X\n", 0xDEADBEEF); printf("std: "); std_ret = printf("%X\n", 0xDEADBEEF); compare_return(ft_ret, std_ret, "HEX DEADBEEF"); printf("ft: "); ft_ret = ft_printf("%X%X%X\n", 10, 11, 12); printf("std: "); std_ret = printf("%X%X%X\n", 10, 11, 12); compare_return(ft_ret, std_ret, "multiple HEX"); /* ==================== PERCENT TESTS ==================== */ print_header("PERCENT (%%) TESTS"); printf("ft: "); ft_ret = ft_printf("%%\n"); printf("std: "); std_ret = printf("%%\n"); compare_return(ft_ret, std_ret, "single percent"); printf("ft: "); ft_ret = ft_printf("%%%%\n"); printf("std: "); std_ret = printf("%%%%\n"); compare_return(ft_ret, std_ret, "double percent"); printf("ft: "); ft_ret = ft_printf("100%%\n"); printf("std: "); std_ret = printf("100%%\n"); compare_return(ft_ret, std_ret, "100%"); printf("ft: "); ft_ret = ft_printf("%%100\n"); printf("std: "); std_ret = printf("%%100\n"); compare_return(ft_ret, std_ret, "%100"); printf("ft: "); ft_ret = ft_printf("50%% off\n"); printf("std: "); std_ret = printf("50%% off\n"); compare_return(ft_ret, std_ret, "50% off"); /* ==================== MIXED TESTS ==================== */ print_header("MIXED FORMAT TESTS"); printf("ft: "); ft_ret = ft_printf("%c%s%d\n", 'A', "BC", 123); printf("std: "); std_ret = printf("%c%s%d\n", 'A', "BC", 123); compare_return(ft_ret, std_ret, "char + string + decimal"); printf("ft: "); ft_ret = ft_printf("char: %c, str: %s, num: %d\n", 'X', "test", 42); printf("std: "); std_ret = printf("char: %c, str: %s, num: %d\n", 'X', "test", 42); compare_return(ft_ret, std_ret, "with labels"); printf("ft: "); ft_ret = ft_printf("%d %i %u %x %X\n", -42, 42, 42, 42, 42); printf("std: "); std_ret = printf("%d %i %u %x %X\n", -42, 42, 42, 42, 42); compare_return(ft_ret, std_ret, "all number formats"); printf("ft: "); ft_ret = ft_printf("ptr: %p, str: %s, %%\n", &test_int, "hello"); printf("std: "); std_ret = printf("ptr: %p, str: %s, %%\n", &test_int, "hello"); compare_return(ft_ret, std_ret, "ptr + str + percent"); printf("ft: "); ft_ret = ft_printf("%s%s%s%s%s\n", "a", "b", "c", "d", "e"); printf("std: "); std_ret = printf("%s%s%s%s%s\n", "a", "b", "c", "d", "e"); compare_return(ft_ret, std_ret, "many strings"); printf("ft: "); ft_ret = ft_printf("%d%d%d%d%d%d%d%d%d%d\n", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9); printf("std: "); std_ret = printf("%d%d%d%d%d%d%d%d%d%d\n", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9); compare_return(ft_ret, std_ret, "many decimals"); /* ==================== NO FORMAT SPECIFIER TESTS ==================== */ print_header("NO FORMAT SPECIFIER TESTS"); printf("ft: "); ft_ret = ft_printf("Hello World\n"); printf("std: "); std_ret = printf("Hello World\n"); compare_return(ft_ret, std_ret, "plain string no format"); printf("ft: "); ft_ret = ft_printf("\n"); printf("std: "); std_ret = printf("\n"); compare_return(ft_ret, std_ret, "only newline"); printf("ft: "); ft_ret = ft_printf(""); printf("std: "); std_ret = printf(""); compare_return(ft_ret, std_ret, "empty string"); printf("ft: "); ft_ret = ft_printf(" \t\t \n"); printf("std: "); std_ret = printf(" \t\t \n"); compare_return(ft_ret, std_ret, "whitespace only"); /* ==================== EDGE CASE COMBINATIONS ==================== */ print_header("EDGE CASE COMBINATIONS"); printf("ft: "); ft_ret = ft_printf("%c%c%c%c%c\n", 0, 'a', 0, 'b', 0); printf("std: "); std_ret = printf("%c%c%c%c%c\n", 0, 'a', 0, 'b', 0); compare_return(ft_ret, std_ret, "null chars between chars"); printf("ft: "); ft_ret = ft_printf("%d%s%d\n", INT_MIN, " to ", INT_MAX); printf("std: "); std_ret = printf("%d%s%d\n", INT_MIN, " to ", INT_MAX); compare_return(ft_ret, std_ret, "INT_MIN to INT_MAX"); printf("ft: "); ft_ret = ft_printf("%x%X%x%X\n", 0xabcd, 0xABCD, 0xef, 0xEF); printf("std: "); std_ret = printf("%x%X%x%X\n", 0xabcd, 0xABCD, 0xef, 0xEF); compare_return(ft_ret, std_ret, "mixed case hex"); printf("ft: "); ft_ret = ft_printf("%u%u\n", 0, UINT_MAX); printf("std: "); std_ret = printf("%u%u\n", 0, UINT_MAX); compare_return(ft_ret, std_ret, "0 and UINT_MAX"); printf("ft: "); ft_ret = ft_printf("%%%c%%\n", 'X'); printf("std: "); std_ret = printf("%%%c%%\n", 'X'); compare_return(ft_ret, std_ret, "percent char percent"); printf("ft: "); ft_ret = ft_printf("%s%p%s\n", "addr:", &test_int, ":end"); printf("std: "); std_ret = printf("%s%p%s\n", "addr:", &test_int, ":end"); compare_return(ft_ret, std_ret, "string ptr string"); /* ==================== CONSECUTIVE SPECIFIERS ==================== */ print_header("CONSECUTIVE SPECIFIERS"); printf("ft: "); ft_ret = ft_printf("%d%d\n", 0, 0); printf("std: "); std_ret = printf("%d%d\n", 0, 0); compare_return(ft_ret, std_ret, "two zeros"); printf("ft: "); ft_ret = ft_printf("%s%s\n", "", ""); printf("std: "); std_ret = printf("%s%s\n", "", ""); compare_return(ft_ret, std_ret, "two empty strings"); printf("ft: "); ft_ret = ft_printf("%p%p%p\n", null_ptr, null_ptr, null_ptr); printf("std: "); std_ret = printf("%p%p%p\n", null_ptr, null_ptr, null_ptr); compare_return(ft_ret, std_ret, "three null pointers"); /* ==================== SUMMARY ==================== */ printf("\n%s╔══════════════════════════════════════════════════════════╗%s\n", YELLOW, RESET); printf("%s║ TEST SUMMARY ║%s\n", YELLOW, RESET); printf("%s╚══════════════════════════════════════════════════════════╝%s\n", YELLOW, RESET); printf("\nTotal: %d tests | ", g_tests); if (g_passed == g_tests) printf("%sPassed: %d%s | ", GREEN, g_passed, RESET); else printf("%sPassed: %d%s | ", YELLOW, g_passed, RESET); if (g_tests - g_passed > 0) printf("%sFailed: %d%s\n", RED, g_tests - g_passed, RESET); else printf("%sFailed: %d%s\n", GREEN, g_tests - g_passed, RESET); if (g_passed == g_tests) printf("\n%s✓ All tests passed!%s\n\n", GREEN, RESET); else printf("\n%s✗ Some tests failed!%s\n\n", RED, RESET); return (g_tests - g_passed); }