之前在词法和语法分析部分都有测试,不过那些测试显得很小打小闹,而且比较麻烦。好在那都是不复杂的东西,测试负担较小。而符号表这东西是语义分析需要用到的基础结构,如果等到最后进行集成测试,出了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;
}
分享到:
相关推荐
在实际开发中,符号表的高效性和准确性直接关系到编译器的性能和可靠性,因此,对其设计与实现应给予足够的重视。 #### 六、参考资料 在设计和实现符号表的过程中,可以参考以下文献和资料: - Aho, Alfred V., ...
在现代软件开发过程中,测试是一项至关重要的工作,特别是对于C语言这类广泛应用的编程语言。由于软件规模的不断扩大,传统的手工测试方法已经无法满足快速、高效测试的需求。因此,自动化测试技术应运而生,其中...
【特殊符号测试用例文档】通常是指用于验证软件或系统是否能正确处理各种特殊字符和符号的测试文档。这类文档的目的是确保软件在遇到非标准输入时仍能正常运行,避免因为特殊字符导致的程序错误或数据混乱。测试用例...
- 设计测试用例,验证符号表管理程序的正确性和效率。 - 分析实验结果,优化程序性能。 - 编写实验报告,总结经验教训。 8. **后续实验准备**:通过这个实验,学生能够为后续的编译原理实验,如语法分析、错误...
这个过程涉及到上下文无关语法(Context-Free Grammar)的理解与实现,以及错误处理和符号表管理。本实验旨在通过C语言编写一个简单的语法分析器,以加深对编译器设计原理的理解。 首先,我们要了解语法分析器的...
6. **测试在软件开发过程中的地位**:测试是验证软件功能和性能的重要环节,贯穿于整个开发过程中。它包括单元测试、集成测试、系统测试和验收测试,确保软件满足用户需求和预期。良好的测试策略能够尽早发现和修复...
软件需求分析、设计及其测试符号标准是软件开发过程中的重要组成部分,它们之间紧密相连,并且相互依赖。只有通过对软件需求分析、设计和测试的详细描述和Symbolic representation,才能确保软件系统的质量和可靠性...
7. **従CSV数据導入到DB**:测试从CSV导入数据到数据库的过程,确保数据完整无误地导入。 8. **帳票出力**:确保报表的正确生成,包括格式、数据和计算的准确性。 通过以上这些测试点,可以确保对日软件的单体测试...
1. APQP(Advanced Product Quality Planning):即高级产品质量计划,这是一种系统化的方法,用于定义产品开发过程中的关键阶段,并确保在产品开发初期就考虑到了质量要求。APQP 强调跨部门团队合作,涉及制造、...
### UML软件开发过程和支持环境研究 #### 一、引言 随着电子计算机技术和现代通讯技术的迅猛发展,全球市场正经历着前所未有的变化。在这样的背景下,软件工程领域也经历了快速的发展,尤其是在过去的三年里取得的...
SQA测试过程是软件开发过程中不可缺少的一环,它关注于软件产品的质量控制和质量改进。 2. **测试框架与工具**: - SQASuite:根据文件内容推测,SQASuite可能是一个软件测试框架或工具集,用于支持客户端/服务器...
3. 硬件与软件资源成本:这涉及开发、测试和部署过程中需要的硬件资源,比如服务器、工作站、网络设备等,以及相应的软件许可或服务订阅费用。 4. 项目风险预留:任何项目都存在不确定性,因此,在预算中设立一个...
在软件开发过程中,图标起着至关重要的作用,它们是沟通技术与非技术团队之间的重要桥梁。图标能够清晰、直观地表达复杂的信息,提高工作效率,减少误解。以下是对软件开发过程中常用的一些图标及其含义的详细解释。...
### 基于UML的面向对象软件开发过程 #### UML概述及其重要性 统一建模语言(Unified Modeling Language, UML)是一种用于规范化的软件系统建模标准,广泛应用于面向对象的软件开发过程中。它提供了一套图形化的...
α测试是在软件开发过程中的早期阶段进行的一种内部测试形式,主要由开发团队成员或者内部质量保证团队来进行。其目的是在软件产品发布前,找出尽可能多的缺陷和问题。 #### Analysis(分析) 1. 分析指的是识别...
### 统一软件开发过程(UUP)核心知识点详解 #### 一、引言 随着信息技术的飞速发展,软件系统变得越来越复杂。为了应对这一挑战,“统一软件开发过程”(Unified Software Development Process, UUP)作为一种先进的...
MATLAB提供的标准测试函数涵盖了多个领域,包括数值计算、符号计算、矩阵运算、图像处理、信号处理等。例如,`test_fmincon`可用于测试优化算法,`test_fft`则涉及快速傅里叶变换的正确性。这些函数通常包含单元测试...
同时,基于场景的方法也可以用于生成自动驾驶汽车开发过程中的工作产品,例如需求文档、测试用例和验证报告。 ISO 26262 标准规定了自动驾驶汽车开发过程中的安全指导,包括场景的描述和使用。该标准要求在开发过程...
软件开发中英文对照是指在软件开发过程中使用的常用中文和英文术语的对照表,旨在帮助开发和测试人员更好地理解和使用相关术语。 在软件开发中英文对照中,词汇是软件开发的基本组成部分,涵盖了软件开发的各个方面...
在实际的软件开发过程中,了解代码所使用的语言是至关重要的。例如,当你接手一个遗留项目,或者在开源社区中寻找合适组件时,快速识别出代码的语言可以帮助你选择合适的编辑器、IDE、构建工具以及适用的编程规范。...