/*
 * OSAL (Operating System Abstraction Layer) 测试用例
 * 功能：验证OSAL API的正确性
 * 依赖：OSAL和RT-Thread Nano
 */

#include "osal.h"
#include <rtthread.h>

/* 测试状态 */
static int test_status = 0;

/* 测试线程参数 */
struct test_thread_param
{
    osal_sem_t sem;
    int count;
};

/* 测试线程入口函数 */
static void test_thread_entry(void* parameter)
{
    struct test_thread_param* param = (struct test_thread_param*)parameter;
    
    osal_kprintf("Test thread started\n");
    
    /* 延时一段时间 */
    osal_thread_mdelay(1000);
    
    /* 增加计数 */
    param->count++;
    
    /* 释放信号量 */
    osal_sem_release(param->sem);
    
    osal_kprintf("Test thread finished\n");
}

/* 测试定时器回调函数 */
static void test_timer_callback(void* parameter)
{
    osal_kprintf("Test timer callback\n");
    test_status = 1;
}

/* 测试内存分配 */
static void test_memory(void)
{
    void* ptr1;
    void* ptr2;
    
    osal_kprintf("Testing memory management...\n");
    
    /* 测试内存分配 */
    ptr1 = osal_malloc(100);
    if (ptr1 != NULL)
    {
        osal_kprintf("osal_malloc passed\n");
        
        /* 测试内存释放 */
        osal_free(ptr1);
        osal_kprintf("osal_free passed\n");
    }
    else
    {
        osal_kprintf("osal_malloc failed\n");
        test_status = -1;
    }
    
    /* 测试对齐内存分配 */
    ptr2 = osal_malloc_align(100, 4);
    if (ptr2 != NULL)
    {
        osal_kprintf("osal_malloc_align passed\n");
        
        /* 测试对齐内存释放 */
        osal_free_align(ptr2);
        osal_kprintf("osal_free_align passed\n");
    }
    else
    {
        osal_kprintf("osal_malloc_align failed\n");
        test_status = -1;
    }
}

/* 测试线程管理 */
static void test_thread(void)
{
    osal_thread_t thread;
    osal_sem_t sem;
    struct test_thread_param param;
    
    osal_kprintf("Testing thread management...\n");
    
    /* 创建信号量 */
    sem = osal_sem_create("test_sem", 0);
    if (sem == NULL)
    {
        osal_kprintf("osal_sem_create failed\n");
        test_status = -1;
        return;
    }
    
    /* 初始化参数 */
    param.sem = sem;
    param.count = 0;
    
    /* 创建线程 */
    thread = osal_thread_create("test_thread", 
                               test_thread_entry, 
                               &param, 
                               512, 
                               10);
    
    if (thread == NULL)
    {
        osal_kprintf("osal_thread_create failed\n");
        osal_sem_delete(sem);
        test_status = -1;
        return;
    }
    
    osal_kprintf("osal_thread_create passed\n");
    
    /* 启动线程 */
    if (osal_thread_start(thread) != OSAL_OK)
    {
        osal_kprintf("osal_thread_start failed\n");
        osal_thread_delete(thread);
        osal_sem_delete(sem);
        test_status = -1;
        return;
    }
    
    osal_kprintf("osal_thread_start passed\n");
    
    /* 等待线程完成 */
    if (osal_sem_take(sem, 5000) != OSAL_OK)
    {
        osal_kprintf("osal_sem_take failed\n");
        osal_thread_delete(thread);
        osal_sem_delete(sem);
        test_status = -1;
        return;
    }
    
    osal_kprintf("Thread count: %d\n", param.count);
    
    /* 删除线程和信号量 */
    osal_thread_delete(thread);
    osal_sem_delete(sem);
    
    osal_kprintf("Thread test passed\n");
}

/* 测试信号量 */
static void test_semaphore(void)
{
    osal_sem_t sem;
    int i;
    
    osal_kprintf("Testing semaphore...\n");
    
    /* 创建信号量 */
    sem = osal_sem_create("test_sem", 3);
    if (sem == NULL)
    {
        osal_kprintf("osal_sem_create failed\n");
        test_status = -1;
        return;
    }
    
    /* 测试获取信号量 */
    for (i = 0; i < 3; i++)
    {
        if (osal_sem_take(sem, 0) != OSAL_OK)
        {
            osal_kprintf("osal_sem_take failed\n");
            osal_sem_delete(sem);
            test_status = -1;
            return;
        }
    }
    
    osal_kprintf("osal_sem_take passed\n");
    
    /* 测试尝试获取信号量（应该失败） */
    if (osal_sem_trytake(sem) == OSAL_OK)
    {
        osal_kprintf("osal_sem_trytake should failed\n");
        test_status = -1;
    }
    else
    {
        osal_kprintf("osal_sem_trytake passed\n");
    }
    
    /* 测试释放信号量 */
    for (i = 0; i < 3; i++)
    {
        if (osal_sem_release(sem) != OSAL_OK)
        {
            osal_kprintf("osal_sem_release failed\n");
            osal_sem_delete(sem);
            test_status = -1;
            return;
        }
    }
    
    osal_kprintf("osal_sem_release passed\n");
    
    /* 删除信号量 */
    osal_sem_delete(sem);
    
    osal_kprintf("Semaphore test passed\n");
}

/* 测试互斥量 */
static void test_mutex(void)
{
    osal_mutex_t mutex;
    
    osal_kprintf("Testing mutex...\n");
    
    /* 创建互斥量 */
    mutex = osal_mutex_create("test_mutex");
    if (mutex == NULL)
    {
        osal_kprintf("osal_mutex_create failed\n");
        test_status = -1;
        return;
    }
    
    /* 测试获取互斥量 */
    if (osal_mutex_take(mutex, 1000) != OSAL_OK)
    {
        osal_kprintf("osal_mutex_take failed\n");
        osal_mutex_delete(mutex);
        test_status = -1;
        return;
    }
    
    osal_kprintf("osal_mutex_take passed\n");
    
    /* 测试尝试获取互斥量（应该失败） */
    if (osal_mutex_trytake(mutex) == OSAL_OK)
    {
        osal_kprintf("osal_mutex_trytake should failed\n");
        test_status = -1;
    }
    else
    {
        osal_kprintf("osal_mutex_trytake passed\n");
    }
    
    /* 测试释放互斥量 */
    if (osal_mutex_release(mutex) != OSAL_OK)
    {
        osal_kprintf("osal_mutex_release failed\n");
        osal_mutex_delete(mutex);
        test_status = -1;
        return;
    }
    
    osal_kprintf("osal_mutex_release passed\n");
    
    /* 删除互斥量 */
    osal_mutex_delete(mutex);
    
    osal_kprintf("Mutex test passed\n");
}

/* 测试事件 */
static void test_event(void)
{
    osal_event_t event;
    osal_uint32_t recved;
    
    osal_kprintf("Testing event...\n");
    
    /* 创建事件 */
    event = osal_event_create("test_event");
    if (event == NULL)
    {
        osal_kprintf("osal_event_create failed\n");
        test_status = -1;
        return;
    }
    
    /* 发送事件 */
    if (osal_event_send(event, 0x0001) != OSAL_OK)
    {
        osal_kprintf("osal_event_send failed\n");
        osal_event_delete(event);
        test_status = -1;
        return;
    }
    
    osal_kprintf("osal_event_send passed\n");
    
    /* 接收事件 */
    if (osal_event_recv(event, 0x0001, OSAL_EVENT_OR | OSAL_EVENT_CLEAR, 1000, &recved) != OSAL_OK)
    {
        osal_kprintf("osal_event_recv failed\n");
        osal_event_delete(event);
        test_status = -1;
        return;
    }
    
    osal_kprintf("Received event: 0x%04X\n", recved);
    osal_kprintf("osal_event_recv passed\n");
    
    /* 删除事件 */
    osal_event_delete(event);
    
    osal_kprintf("Event test passed\n");
}

/* 测试消息队列 */
static void test_message_queue(void)
{
    osal_mq_t mq;
    char send_msg[10] = "Hello";
    char recv_msg[10];
    
    osal_kprintf("Testing message queue...\n");
    
    /* 创建消息队列 */
    mq = osal_mq_create("test_mq", 10, 5);
    if (mq == NULL)
    {
        osal_kprintf("osal_mq_create failed\n");
        test_status = -1;
        return;
    }
    
    /* 发送消息 */
    if (osal_mq_send(mq, send_msg, sizeof(send_msg)) != OSAL_OK)
    {
        osal_kprintf("osal_mq_send failed\n");
        osal_mq_delete(mq);
        test_status = -1;
        return;
    }
    
    osal_kprintf("osal_mq_send passed\n");
    
    /* 接收消息 */
    if (osal_mq_recv(mq, recv_msg, sizeof(recv_msg), 1000) != OSAL_OK)
    {
        osal_kprintf("osal_mq_recv failed\n");
        osal_mq_delete(mq);
        test_status = -1;
        return;
    }
    
    osal_kprintf("Received message: %s\n", recv_msg);
    osal_kprintf("osal_mq_recv passed\n");
    
    /* 删除消息队列 */
    osal_mq_delete(mq);
    
    osal_kprintf("Message queue test passed\n");
}

/* 测试定时器 */
static void test_timer(void)
{
    osal_timer_t timer;
    
    osal_kprintf("Testing timer...\n");
    
    /* 创建定时器 */
    timer = osal_timer_create("test_timer", 
                            test_timer_callback, 
                            NULL, 
                            1000, 
                            OSAL_TIMER_FLAG_ONE_SHOT);
    
    if (timer == NULL)
    {
        osal_kprintf("osal_timer_create failed\n");
        test_status = -1;
        return;
    }
    
    osal_kprintf("osal_timer_create passed\n");
    
    /* 启动定时器 */
    if (osal_timer_start(timer) != OSAL_OK)
    {
        osal_kprintf("osal_timer_start failed\n");
        osal_timer_delete(timer);
        test_status = -1;
        return;
    }
    
    osal_kprintf("osal_timer_start passed\n");
    
    /* 等待定时器回调 */
    osal_thread_mdelay(2000);
    
    /* 检查定时器是否触发 */
    if (test_status != 1)
    {
        osal_kprintf("Timer callback not triggered\n");
        test_status = -1;
    }
    else
    {
        osal_kprintf("Timer callback triggered\n");
    }
    
    /* 停止定时器 */
    osal_timer_stop(timer);
    
    /* 删除定时器 */
    osal_timer_delete(timer);
    
    osal_kprintf("Timer test passed\n");
}

/* 测试系统服务 */
static void test_system(void)
{
    osal_tick_t tick1, tick2;
    
    osal_kprintf("Testing system services...\n");
    
    /* 测试获取系统tick */
    tick1 = osal_tick_get();
    osal_kprintf("Current tick: %d\n", tick1);
    
    /* 测试延时 */
    osal_mdelay(1000);
    
    tick2 = osal_tick_get();
    osal_kprintf("Tick after delay: %d\n", tick2);
    osal_kprintf("Tick difference: %d\n", tick2 - tick1);
    
    /* 测试临界区 */
    osal_enter_critical();
    osal_kprintf("Entered critical section\n");
    
    /* 测试获取中断嵌套级别 */
    osal_kprintf("Interrupt nest level: %d\n", osal_interrupt_get_nest());
    
    osal_exit_critical();
    osal_kprintf("Exited critical section\n");
    
    osal_kprintf("System services test passed\n");
}

/* OSAL测试函数 */
int osal_test(void)
{
    osal_kprintf("\n=== OSAL Test Start ===\n");
    
    /* 初始化测试状态 */
    test_status = 0;
    
    /* 测试内存管理 */
    test_memory();
    
    /* 测试线程管理 */
    test_thread();
    
    /* 测试信号量 */
    test_semaphore();
    
    /* 测试互斥量 */
    test_mutex();
    
    /* 测试事件 */
    test_event();
    
    /* 测试消息队列 */
    test_message_queue();
    
    /* 测试定时器 */
    test_timer();
    
    /* 测试系统服务 */
    test_system();
    
    if (test_status == 0)
    {
        osal_kprintf("=== All OSAL tests passed! ===\n\n");
        return 0;
    }
    else
    {
        osal_kprintf("=== Some OSAL tests failed! ===\n\n");
        return -1;
    }
}

/* 导出测试函数 */
MSH_CMD_EXPORT(osal_test, OSAL test);
