[开发过程]符号表的测试

    之前在词法和语法分析部分都有测试,不过那些测试显得很小打小闹,而且比较麻烦。好在那都是不复杂的东西,测试负担较小。而符号表这东西是语义分析需要用到的基础结构,如果等到最后进行集成测试,出了bug还真不好找。所以这东西有必要单独拿来测试一下。不过C语言的测试驱动开发工具还真是难找,这里就山寨一个先。

    测试数据这里简单给出4组

// 测试数据数目
#define NR_TEST_CASE (4)
// 测试数据的基地址
#define BASE_ADDR (1 << 3)

// 待测试的符号表指针
struct SymbolTable* table;

// 维度信息,等于0时结束
// 比如第一组数据,表示 i [2][3][4][5]
int DIM[NR_TEST_CASE][5] = {
    { 2, 3, 4, 5, 0 },
    { 2, 4, 0 },
    { 0 },
    { 2, 3, 4, 0 }
};

// 其它数据
struct {
    char* ident; // 标识符
    AcceptType type; // 类型
    int nrDim; // 维度数
    int* dims; // 每一维大小
    int size; // 总大小
} data[NR_TEST_CASE] = {
    { "i", INTEGER },
    { "ij", INTEGER },
    { "j", REAL },
    { "k", REAL }
};

     按照单元测试的规范,对于每个函数的测试不应该依赖于其它函数。所以每个测试应该独立地进行数据准备工作。这两个函数进行数据准备和测试结束后的清理

void prepare(void)
{
    int i, j, size;
    table = newSymbolTable(BASE_ADDR);
    for (i = 0; i < NR_TEST_CASE; ++i ) {
        // 填充数据中其它部分:总大小及每一维的大小
        size = INTEGER == data[i].type ? INT_SIZE : REAL_SIZE;
        data[i].dims = DIM[i];
        for (j = 0; 0 != DIM[i][j]; ++j) {
            size *= DIM[i][j];
        }
        data[i].nrDim = j;
        data[i].size = size;
    }
    for (i = 0; i < NR_TEST_CASE; ++i) {
        // 将符号注册进符号表,并顺带判断是否每次都成功
        assert (SymTab_OK ==
                regVar(table, data[i].ident, data[i].type, data[i].nrDim,
                       data[i].dims));
    }
}

void clear(void)
{
    finalizeSymbolTable(table);
    showAlloc;
}

    再就是为每个函数准备的测试,依次是

/*
 * 测试 regVar
 * 测试涵盖可能出现的错误,包括 SymTab_MultiDef 和 SymTab_SizeExceeded
 * 因为正确的变量注册在 prepare 中完成了,所以这里不测试
 */
void testRegister(void);

/*
 * 测试 getVarType
 * 测试涵盖正确的返回及 SymTab_NotDef 错误
 */
void testVarType(void);

/*
 * 测试 getVarAddr
 * 测试涵盖正确的返回及 SymTab_NotDef 错误
 */
void testVarAddr(void);

/*
 * 测试 getVarNrDim
 * 测试涵盖正确的返回及 SymTab_NotDef 错误
 */
void testNrDim(void);

/*
 * 测试 getVarDimSize
 * 测试过程中会根据数组大小计算出其单元偏移
 * 测试涵盖正确的返回及 SymTab_NotDef 和 SymTab_ArrDimOutOfRange 错误
 */
void testDimSize(void);

    它们的具体实现如下

void testRegister(void)
{
    prepare();
    // totalSize: 总的内存使用量,判别在试图重复注册同名变量失败后,符号表内使用内存数是否不变
    int i, totalSize = table->used;
    for (i = 0; i < NR_TEST_CASE; ++i) {
        // 重复注册在 prepare 中已经注册的数据
        assert (SymTab_MultiDef ==
                regVar(table, data[i].ident, data[i].type, data[i].nrDim,
                       data[i].dims));
    }
    assert (totalSize == table->used);
    // 内存超出最大限度,试图注册该变量
    int exceed = MAX_VAR_IN_STACK - BASE_ADDR;
    int exceedDim[1] = { exceed };
    assert (SymTab_SizeExceeded
            == regVar(table, "non-exist", INTEGER, 1, exceedDim));
    clear();
    puts("   -> Register test done.\n");
}

void testVarType(void)
{
    prepare();
    int i;
    AcceptType type; // 变量类型,其地址传入函数以存放返回值
    for (i = 0; i < NR_TEST_CASE; ++i) {
        assert (SymTab_OK == getVarType(table, data[i].ident, &type));
        assert (data[i].type == type);
    }
    assert (SymTab_NotDef == getVarType(table, "non-exist", &type));
    clear();
    puts("   -> Type getter test done.\n");
}

void testVarAddr(void)
{
    prepare();
    // addr: 变量地址,其地址传入函数以存放返回值
    // accumulator: 地址积累量,也就是期望的变量地址
    int i, addr, accumulator = BASE_ADDR;
    for (i = 0; i < NR_TEST_CASE; ++i) {
        assert (SymTab_OK == getVarAddr(table, data[i].ident, &addr));
        assert (addr == accumulator);
        accumulator += data[i].size; // 调整到下一变量的期望地址
    }
    assert (accumulator - BASE_ADDR == table->used);
    assert (SymTab_NotDef == getVarAddr(table, "non-exist", &addr));
    clear();
    puts("   -> Address getter test done.\n");
}

void testNrDim(void)
{
    prepare();
    // nrDim: 维度数目,其地址传入函数以存放返回值
    int i, nrDim;
    for (i = 0; i < NR_TEST_CASE; ++i) {
        assert (SymTab_OK == getVarNrDim(table, data[i].ident, &nrDim));
        assert (data[i].nrDim == nrDim);
    }
    assert (SymTab_NotDef == getVarNrDim(table, "non-exist", &nrDim));
    clear();
    puts("   -> Dimension number getter test done.\n");
}

void testDimSize(void)
{
    prepare();
    // dimSize: 维度大小,其地址传入函数以存放返回值
    // expected: 期望维度大小,计算得出
    int i, j, dimSize, expected;
    for (i = 0; i < NR_TEST_CASE; ++i) {
        // 越界错误
        assert (SymTab_ArrDimOutOfRange
                == getVarDimSize(table, data[i].ident, &dimSize, -1));
        expected = INTEGER == data[i].type ? INT_SIZE : REAL_SIZE;
        for (j = 0; j < data[i].nrDim; ++j) {
            assert(SymTab_OK
                   == getVarDimSize(table, data[i].ident, &dimSize, j));
            assert(expected == dimSize);
            expected *= DIM[i][j];
        }
        assert (expected == data[i].size);
        // 越界错误
        assert (SymTab_ArrDimOutOfRange
                == getVarDimSize(table, data[i].ident, &dimSize, j));
    }
    assert (SymTab_NotDef == getVarDimSize(table, "non-exist", &dimSize, 0));
    clear();
    puts("   -> Dimension size getter test done.\n");
}

    最后是文件中其它的散件及main函数

#include<stdio.h>
#include<assert.h>

#define _DEBUG_MODE
#include"symbol-table.h"

int main(void)
{
    testRegister();
    testVarType();
    testVarAddr();
    testNrDim();
    testDimSize();
    puts(":-) All test done.");
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值