数据类型支持

对于测试函数,返回值类型可以是任意的,函数返回值会被忽略。

在C和C++环境下,测试函数支持的参数类型不同:

C环境下,参数类型只能是(char* data, size_t len),测试框架将会把输入的原始缓冲区传给测试函数。测试函数可以任意使用。

C++环境下,支持任意数量的参数。测试框架内置部分参数类型的适配,同时支持用户自己扩展框架,以使其支持任意类型的参数。

  • 内置参数类型

    以下类型可以直接作为测试函数的参数:

    参数类型说明
    char* buf, size_t len原始缓冲区数据输入,长度为len,没有\0结尾。C语言环境下,只支持这个类型,并且前面不能有别的参数。C++环境下,还可以在它前面加任意的别的类型,但这两个参数的位置只能是最后两个。
    bool
    int8_t/uint8_t同时也包括[signed/unsigned] char
    int16_t/uint16_t同时也包括[signed/unsigned] short
    int32_t/uint32_t同时也包括[signed/unsigned] int/long
    int64_t/uint64_t同时也包括[signed/unsigned] long long
    float/double
    char*/std::stringC-style或C++字符串
    std::vectorT是任意支持的类型(包括内置支持和自定义支持)
    std::tuple<T...>T是任意支持类型的列表(包括内置支持和自定义支持)
    std::map<K,V>K,V是任意支持的类型(包括内置支持和自定义支持)

    以上类型,可以按值传参,也可以按引用传参。可以添加const/volatile修饰。使用按引用传参时,引用对象的生命周期会持续到测试函数执行结束。

  • 自定义参数类型

    当以上的内置参数类型不能满足需求时,可以使用自定义类型。使用时,只需要写一个转换函数。

    转换函数的格式类似于测试函数,可以接收任意的参数,返回要转换的类型。再使用**WFUZZ_CUSTOM_CONVERTER(function)**宏注册一下转换函数。然后就可以像使用内置类型一样,使用这些类型了。示例程序如下:

    #include <wfuzz.h>
    #include <stdio.h>
    #include <math.h>
    
    struct Point{ int x; int y; };
    Point point_converter(int x, int y) {
        return { x, y };
    }
    WFUZZ_CUSTOM_CONVERTER(point_converter);
    void test_point(Point p) {
    printf("distance: %f\n", sqrt(1.0*p.x*p.x + 1.0*p.y*p.y));
    }
    WFUZZ_TEST_ENTRYPOINT(test_point);
    

    转换函数可以嵌套使用,例如上面程序中定义了Point类型的转换函数,后续的自定义类型就可以基于Point函数定义:

    struct Circle { Point center; int radius; };
    
    Circle circle_converter(Point center, int radius) {
        return { center, radius };
    }
    WFUZZ_CUSTOM_CONVERTER(circle_converter);
    void test_circle(Circle c) {
        printf(
            "Circle: center: (%d, %d), radius: %d\n", 
            c.center.x,
            c.center.y,
            c.radius
        );
    }
    WFUZZ_TEST_ENTRYPOINT(test_circle);