授课语音

编写测试用例

为确保线程安全的队列(Queue)在多线程环境下正确工作,我们可以编写测试用例来验证其功能。以下是对 Queue 进行单元测试的一些基本用例,包括并发入队和出队操作的测试。

假设我们已经实现了线程安全的队列(Queue),下面是编写测试用例的示例,使用 pthread 库进行多线程测试。

1. 头文件包含和测试框架

首先,我们需要包含头文件,并设置测试框架。假设我们使用 CUnit 进行单元测试,您可以根据实际需要选择其他测试框架。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <assert.h>
#include "queue.h"  // 假设队列的实现文件为 queue.h

// 定义常量和全局变量
#define THREAD_COUNT 10    // 测试的线程数量
#define ENQUEUE_COUNT 100  // 每个线程入队的次数

Queue q;  // 队列实例

2. 辅助函数

在测试中,我们需要实现一些辅助函数来启动线程并执行队列的入队和出队操作。

// 线程入队函数
void* enqueueTest(void* arg) {
    for (int i = 0; i < ENQUEUE_COUNT; i++) {
        enqueue(&q, i);  // 执行入队操作
    }
    return NULL;
}

// 线程出队函数
void* dequeueTest(void* arg) {
    int value;
    for (int i = 0; i < ENQUEUE_COUNT; i++) {
        while (!dequeue(&q, &value)) {
            // 如果队列为空,等待
        }
    }
    return NULL;
}

3. 测试用例

3.1 单线程入队和出队

我们首先可以测试单线程下的入队和出队操作,确保基本功能正常。

void test_single_thread_operations() {
    initQueue(&q);

    // 单线程入队操作
    enqueue(&q, 1);
    enqueue(&q, 2);
    enqueue(&q, 3);

    int value;
    assert(dequeue(&q, &value) && value == 1);  // 第一个元素是1
    assert(dequeue(&q, &value) && value == 2);  // 第二个元素是2
    assert(dequeue(&q, &value) && value == 3);  // 第三个元素是3

    // 队列为空
    assert(dequeue(&q, &value) == false);  // 出队失败

    destroyQueue(&q);
}

3.2 多线程并发入队

测试多个线程并发执行入队操作的情况。

void test_multithreaded_enqueue() {
    initQueue(&q);
    
    pthread_t threads[THREAD_COUNT];
    
    // 创建多个线程进行入队
    for (int i = 0; i < THREAD_COUNT; i++) {
        pthread_create(&threads[i], NULL, enqueueTest, NULL);
    }

    // 等待线程完成
    for (int i = 0; i < THREAD_COUNT; i++) {
        pthread_join(threads[i], NULL);
    }

    // 验证队列中的元素数量
    int expected_value = THREAD_COUNT * ENQUEUE_COUNT - 1;
    int value;
    for (int i = 0; i <= expected_value; i++) {
        assert(dequeue(&q, &value) && value == i);
    }

    // 队列为空
    assert(dequeue(&q, &value) == false);  // 出队失败

    destroyQueue(&q);
}

3.3 多线程并发入队和出队

测试多个线程并发执行入队和出队操作,确保线程安全。

void test_multithreaded_enqueue_dequeue() {
    initQueue(&q);
    
    pthread_t enqueue_threads[THREAD_COUNT];
    pthread_t dequeue_threads[THREAD_COUNT];
    
    // 创建多个线程进行入队
    for (int i = 0; i < THREAD_COUNT; i++) {
        pthread_create(&enqueue_threads[i], NULL, enqueueTest, NULL);
    }

    // 创建多个线程进行出队
    for (int i = 0; i < THREAD_COUNT; i++) {
        pthread_create(&dequeue_threads[i], NULL, dequeueTest, NULL);
    }

    // 等待所有入队线程完成
    for (int i = 0; i < THREAD_COUNT; i++) {
        pthread_join(enqueue_threads[i], NULL);
    }

    // 等待所有出队线程完成
    for (int i = 0; i < THREAD_COUNT; i++) {
        pthread_join(dequeue_threads[i], NULL);
    }

    // 队列应为空
    int value;
    assert(dequeue(&q, &value) == false);  // 出队失败

    destroyQueue(&q);
}

4. 主测试函数

最后,在主函数中调用各个测试用例。

int main() {
    // 运行所有测试
    test_single_thread_operations();
    test_multithreaded_enqueue();
    test_multithreaded_enqueue_dequeue();

    printf("All tests passed!\n");
    return 0;
}

5. 编译和运行

编译时需要链接 pthread 库:

gcc -o queue_test queue_test.c -lpthread

运行测试:

./queue_test

6. 总结

  • 单线程测试:首先验证了基本的队列操作功能,确保入队和出队操作在没有并发情况下正常工作。
  • 多线程入队:多个线程并发执行入队操作,验证了多线程访问队列时的同步性。
  • 多线程入队和出队:在并发环境下,同时执行入队和出队操作,确保队列实现能够正确处理并发。

通过这些测试,我们确保了线程安全的队列在多线程环境中的可靠性和正确性。

去1:1私密咨询

系列课程: