/*
 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 * conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
 * to endorse or promote products derived from this software without specific prior written
 * permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "it_pthread_test.h"

static pthread_mutex_t g_pthreadMuxTest1;
static pthread_cond_t g_pthdCondTest1;

static void *PthreadF01(void *t)
{
    int rc;

    rc = pthread_mutex_lock(&g_pthreadMuxTest1);  // 尝试获取互斥锁 g_pthreadMuxTest1
    ICUNIT_GOTO_EQUAL(rc, 0, rc, EXIT);  // 如果获取锁失败，跳转到 EXIT，确保返回值为0，表示成功获取锁

    g_testCount++;  // 增加 g_testCount，表示线程正在执行
    LosTaskDelay(100);  // 延时 100，模拟线程运行期间的某些操作（例如 I/O 操作或计算等）
    ICUNIT_GOTO_EQUAL(g_testCount, 2, g_testCount, EXIT);  // 确保此时 g_testCount 等于 2，表示线程执行过程中计数值的正确性
    g_testCount++;  // 增加 g_testCount，为后续操作做准备

    rc = pthread_cond_wait(&g_pthdCondTest1, &g_pthreadMuxTest1);  // 释放互斥锁，等待条件变量 g_pthdCondTest1 被唤醒
    ICUNIT_GOTO_EQUAL(rc, 0, rc, EXIT);  // 确保等待条件变量的调用没有出错，返回值为0，表示成功等待

    ICUNIT_GOTO_EQUAL(g_testCount, 5, g_testCount, EXIT);  // 确保此时 g_testCount 的值为 5，表示线程同步操作正确
    rc = pthread_mutex_unlock(&g_pthreadMuxTest1);  // 释放互斥锁，允许其他线程操作共享资源
    ICUNIT_GOTO_EQUAL(rc, 0, rc, EXIT);  // 确保释放锁没有出错，返回值为0，表示成功释放锁

EXIT:
    return NULL;  // 线程执行完毕，返回 NULL
}


static void *PthreadF02(void *t)
{
    int i;
    int rc;

    ICUNIT_GOTO_EQUAL(g_testCount, 1, g_testCount, EXIT);  // 确保此时 g_testCount 为 1，表示线程同步的正确性
    g_testCount++;  // 增加 g_testCount，为后续操作做准备
    rc = pthread_mutex_lock(&g_pthreadMuxTest1);  // 获取互斥锁 g_pthreadMuxTest1
    ICUNIT_GOTO_EQUAL(rc, 0, rc, EXIT);  // 确保获取锁没有出错

    ICUNIT_GOTO_EQUAL(g_testCount, 3, g_testCount, EXIT);  // 确保此时 g_testCount 等于 3，表示同步操作执行的正确性
    g_testCount++;  // 增加 g_testCount，表示线程操作继续

    rc = pthread_cond_signal(&g_pthdCondTest1);  // 唤醒等待条件变量 g_pthdCondTest1 的线程
    ICUNIT_GOTO_EQUAL(rc, 0, rc, EXIT);  // 确保条件变量唤醒操作成功，返回值应为0

    ICUNIT_GOTO_EQUAL(g_testCount, 4, g_testCount, EXIT);  // 确保此时 g_testCount 的值为 4，表示线程同步的正确性
    g_testCount++;  // 增加 g_testCount，为后续操作做准备

    rc = pthread_mutex_unlock(&g_pthreadMuxTest1);  // 释放互斥锁，允许其他线程访问共享资源
    ICUNIT_GOTO_EQUAL(rc, 0, rc, EXIT);  // 确保释放锁操作没有出错

    LosTaskDelay(2);  // 延时 2，控制线程执行的时机，确保测试结果稳定

EXIT:
    pthread_exit(NULL);  // 线程执行完毕，退出
}
static unsigned int TestCase(void)
{
    int i;  // 用于循环控制
    long t1 = 1;  // 线程1的参数 t1
    long t2 = 2;  // 线程2的参数 t2
    int rc;  // 用于存储函数调用的返回值，检测调用是否成功
    pthread_t threads[3]; // 定义一个数组，包含3个线程，尽管这里只创建了两个线程（0和1），此数组为初始化时的预留空间
    pthread_attr_t attr;  // 线程属性变量，用于设置线程的属性（但在此代码中未设置具体属性）
    const int loopNum = 2; // 设置线程等待并回收的次数

    g_testCount = 0;  // 初始化全局变量 g_testCount，为0，表示线程同步的初始状态
    pthread_mutex_init(&g_pthreadMuxTest1, NULL);  // 初始化互斥锁 g_pthreadMuxTest1
    pthread_cond_init(&g_pthdCondTest1, NULL);  // 初始化条件变量 g_pthdCondTest1

    rc = pthread_create(&threads[0], NULL, PthreadF01, (void *)t1);  // 创建线程0，执行 PthreadF01，并传递 t1 作为参数
    ICUNIT_ASSERT_EQUAL(rc, 0, rc);  // 确保线程创建成功，返回值应为0

    rc = pthread_create(&threads[1], NULL, PthreadF02, (void *)t2);  // 创建线程1，执行 PthreadF02，并传递 t2 作为参数
    ICUNIT_ASSERT_EQUAL(rc, 0, rc);  // 确保线程创建成功，返回值应为0

    // 主线程等待两个子线程的执行结束
    for (i = 0; i < loopNum; i++) {
        rc = pthread_join(threads[i], NULL);  // 等待线程 i 执行完毕并回收资源
        ICUNIT_ASSERT_EQUAL(rc, 0, rc);  // 确保线程加入操作成功，返回值应为0
    }

    rc = pthread_attr_destroy(&attr);  // 销毁线程属性对象，释放资源
    ICUNIT_ASSERT_EQUAL(rc, 0, rc);  // 确保销毁操作成功

    rc = pthread_mutex_destroy(&g_pthreadMuxTest1);  // 销毁互斥锁，释放资源
    ICUNIT_ASSERT_EQUAL(rc, 0, rc);  // 确保销毁操作成功
    rc = pthread_cond_destroy(&g_pthdCondTest1);  // 销毁条件变量，释放资源
    ICUNIT_ASSERT_EQUAL(rc, 0, rc);  // 确保销毁操作成功

    return 0;  // 返回0，表示测试用例执行完毕
}


void ItTestPthreadCond001(void)
{
    TEST_ADD_CASE("IT_POSIX_PTHREAD_COND_001", TestCase, TEST_POSIX, TEST_PTHREAD, TEST_LEVEL2, TEST_FUNCTION);
}
