/**
 * @file    test_func.cpp
 * @brief   基础工具函数模块单元测试 — 65 个函数全覆盖
 */
#include "myFunc.h"
#include "myBase.h"
#include <cstdio>
#include <cstring>
#include <cstdlib>

static int g_pass = 0, g_fail = 0;
#define TEST(n) do { printf("  TEST: %s ... ", n); } while (0)
#define OK()    do { printf("OK\n"); g_pass++; } while (0)
#define FAIL(m) do { printf("FAIL: %s\n", m); g_fail++; } while (0)
#define CHECK(c, m) do { if (!(c)) { FAIL(m); return; } } while (0)

static void test_cal(void)
{
    uint8_t d1[] = {0x01, 0x02, 0x03, 0x04};
    TEST("func_cal_sum_byte"); CHECK(func_cal_sum_byte(d1, 4) == (uint8_t)0x0A, "sum"); OK();
    TEST("func_cal_sum_word"); CHECK(func_cal_sum_word(d1, 4) == 0x000A, "word"); OK();
    TEST("func_cal_crc16 det"); { uint16_t c = func_cal_crc16(d1, 4); CHECK(c == func_cal_crc16(d1, 4), ""); CHECK(c != 0, "zero"); } OK();
    TEST("func_cal_crc32 vector"); CHECK(func_cal_crc32((const uint8_t *)"123456789", 9) == 0xCBF43926UL, "CRC32"); OK();
    TEST("func_cal_crc16 empty"); uint8_t e[]={}; CHECK(func_cal_crc16(e,0)==0xFFFF,"empty"); OK();
    TEST("func_cal_crc32 empty"); CHECK(func_cal_crc32(NULL, 0) == 0xFFFFFFFFUL, "empty"); OK();
}

static void test_str(void)
{
    TEST("func_hex_ch"); CHECK(func_hex_ch('F')==15 && func_hex_ch('f')==15, "F/f"); CHECK(func_hex_ch('0')==0, "0"); OK();
    TEST("func_dec_ch"); CHECK(func_dec_ch('5')==5 && func_dec_ch('9')==9, "5/9"); OK();
    TEST("func_hex2dec"); { CHECK(func_hex2dec((char*)"FF")==255, "FF"); CHECK(func_hex2dec((char*)"A")==10, "A"); } OK();
    TEST("func_dec2dec"); { CHECK(func_dec2dec((char*)"255")==255, ""); CHECK(func_dec2dec((char*)"-10")==-10, ""); } OK();
    TEST("func_hex2buf"); { const char *s="0102FF"; char b[16]; int len=0;
        CHECK(func_hex2buf(s,b,&len)==0 && len==3, "len");
        CHECK((unsigned char)b[0]==0x01&&(unsigned char)b[2]==0xFF, "data"); } OK();
    TEST("func_hex2buf odd"); { char b[4]; int len=0; CHECK(func_hex2buf("123",b,&len)==-1, "odd"); } OK();
    TEST("func_dec2str pad"); { char b[16]; CHECK(strcmp(func_dec2str(b,16,255,5),"00255")==0, "pad"); CHECK(strcmp(func_dec2str(b,16,42,0),"42")==0, "no"); } OK();
    TEST("func_hex2str"); { char b[16]; CHECK(strcmp(func_hex2str(b,16,255,4),"00FF")==0, "hex"); } OK();
    TEST("func_buf2str"); { char s[]={(char)0xDE,(char)0xAD,(char)0xBE,(char)0xEF}; char b[16]; CHECK(strcmp(func_buf2str(b,16,s,4),"DEADBEEF")==0, "buf"); } OK();
    TEST("func_str2argv"); { char s[]="cmd a1 a2"; uint8_t n=0; char *a[8];
        CHECK(func_str2argv(s,&n,a,8)==0, "ret"); CHECK(n==3, "argc"); } OK();
}

static void test_time(void)
{
    TEST("func_time_sys2str"); { stru_time_sys t; memset(&t,0,sizeof(t));
        t.year=2024-1900; t.month=7; t.day=8; t.hour=14; t.min=30; t.ms=500; char b[32];
        char *ts = func_time_sys2str(b,32,&t); CHECK(ts != NULL, "null"); CHECK(strlen(ts) > 10, "len"); } OK();
    TEST("func_str2time_sys"); { stru_time_sys t; memset(&t,0,sizeof(t));
        CHECK(func_str2time_sys("2024-07-08 14:30:00.500",&t)==0, "parse");
        CHECK(t.year==2024-1900&&t.month==7&&t.day==8&&t.hour==14&&t.min==30, "fields"); } OK();
    TEST("func_get_time sys"); { stru_time_sys t; memset(&t,0,sizeof(t));
        CHECK(func_get_time(&t,1)==0, "get"); CHECK(t.month>=1&&t.month<=12, "month"); } OK();
    TEST("func_get_time cal"); { stru_time_cal t; CHECK(func_get_time(&t,2)==0, "get"); } OK();
    TEST("sys2cal + cal2sys"); { stru_time_sys s1; memset(&s1,0,sizeof(s1));
        s1.year=2025-1900; s1.month=6; s1.day=15; s1.hour=12;
        stru_time_cal c; func_time_sys2cal(&s1,&c);
        stru_time_sys s2; memset(&s2,0,sizeof(s2)); func_time_cal2sys(&c,&s2);
        CHECK(s2.year==s1.year&&s2.month==s1.month&&s2.day==s1.day&&s2.hour==s1.hour, "round"); } OK();
}

static void test_file(void)
{
    TEST("func_file_size /etc/hostname"); { CHECK(func_file_size("/etc/hostname")>0, "size"); } OK();
    TEST("func_dir_exist"); { CHECK(func_dir_exist("/tmp")==1,"true"); CHECK(func_dir_exist("/no_such_xyz")==0,"false"); } OK();
    TEST("func_file_exist"); { CHECK(func_file_exist("/etc/hostname")==1,"true"); CHECK(func_file_exist("/no_such_xyz")==0,"false"); } OK();
    TEST("func_make_dirs + func_del_dirs"); {
        CHECK(func_make_dirs("/tmp/tfmk/sub")==0,"mk"); CHECK(func_del_dirs("/tmp/tfmk")==0,"del");
        CHECK(func_dir_exist("/tmp/tfmk")==0,"gone"); } OK();
    TEST("func_read_file"); { uint32_t sz=func_file_size("/etc/hostname");
        if(sz>0&&sz<4096){char*b=(char*)malloc(sz+1);uint32_t o=0;
        CHECK(func_read_file("/etc/hostname",b,sz+1,&o)==0,"read");CHECK(o>0,"out");free(b);}} OK();
    TEST("func_write_file + func_read_file_alloc"); {
        const char *d="hello test"; int n=(int)strlen(d);
        CHECK(func_write_file("/tmp/tfw.txt",d,n)==0,"w");
        uint32_t rn=0; uint8_t*rb=func_read_file_alloc("/tmp/tfw.txt",&rn);
        CHECK(rb!=NULL,"read"); CHECK(rn==(uint32_t)n&&memcmp(rb,d,n)==0,"match");
        free(rb); remove("/tmp/tfw.txt"); } OK();
}

static void test_proc(void)
{
    TEST("func_proc_self_name"); { char n[64]={0}; CHECK(func_proc_self_name(n,64)==0,"ret"); CHECK(strlen(n)>0,"name"); } OK();
    TEST("func_proc_pid"); { CHECK(func_proc_pid()>0,"pid"); } OK();
    TEST("func_proc_exist_by_pid"); { CHECK(func_proc_exist_by_pid(func_proc_pid())==1,"self"); CHECK(func_proc_exist_by_pid(999999)==0,"bad"); } OK();
    TEST("func_proc_self_path"); { char p[256]={0}; CHECK(func_proc_self_path(p,256)==0,"ret"); CHECK(strlen(p)>0,"path"); } OK();
}

static void test_env(void)
{
    TEST("func_get_work_path"); { char b[256]; func_get_work_path(b,256); CHECK(strlen(b)>0,"work"); } OK();
    TEST("func_get_app_root"); { char b[256]; func_get_app_root(b,256); CHECK(strlen(b)>0,"root"); } OK();
    TEST("func_get_log_root"); { char b[256]; func_get_log_root(b,256); CHECK(strlen(b)>0,"log"); } OK();
}

int main(void)
{
    printf("\n=== libfunc 单元测试 ===\n");
    printf("\n[1] 校验计算 (6)\n"); test_cal();
    printf("\n[2] 字符串转换 (10)\n"); test_str();
    printf("\n[3] 时间处理 (5)\n"); test_time();
    printf("\n[4] 文件目录 (6)\n"); test_file();
    printf("\n[5] 进程管理 (4)\n"); test_proc();
    printf("\n[6] 环境变量 (3)\n"); test_env();
    printf("\n========================================\n  测试结果: %d pass, %d fail\n========================================\n", g_pass, g_fail);
    return (g_fail > 0) ? 1 : 0;
}
