编译器扫描程序/解析器通常使用哪些阴性测试用例



我正在为类中提供的语言编写编译器。与我更好的判断相反,我超越了自己,从未为任何编译器测试编写测试。我的教授想看测试。

语言是C语言。我正在使用Catch2和CTest编写测试。下面是一个阳性扫描仪测试的例子:

TEST_CASE("Scanner keyword tests", "[front-end]") {
antlr4::ANTLRInputStream input("int boolean str var func proc if then else while do select return length extern");
WPLLexer lexer(&input);
CHECK(lexer.nextToken()->getType() == lexer.INT);
CHECK(lexer.nextToken()->getType() == lexer.BOOLEAN);
CHECK(lexer.nextToken()->getType() == lexer.STR);
CHECK(lexer.nextToken()->getType() == lexer.VAR);
CHECK(lexer.nextToken()->getType() == lexer.FUNC);
CHECK(lexer.nextToken()->getType() == lexer.PROC);
CHECK(lexer.nextToken()->getType() == lexer.IF);
CHECK(lexer.nextToken()->getType() == lexer.THEN);
CHECK(lexer.nextToken()->getType() == lexer.ELSE);
CHECK(lexer.nextToken()->getType() == lexer.WHILE);
CHECK(lexer.nextToken()->getType() == lexer.DO);
CHECK(lexer.nextToken()->getType() == lexer.SELECT);
CHECK(lexer.nextToken()->getType() == lexer.RETURN);
CHECK(lexer.nextToken()->getType() == lexer.LENGTH);
CHECK(lexer.nextToken()->getType() == lexer.EXTERN);
}

我想写一些阴性测试用例,但不知道从哪里开始编译器扫描程序和解析器的一些常见的阴性测试用例是什么

没有"通用测试用例";,无论是正面的还是负面的,对于一般的编译器来说。每种语言都是不同的。可以有一个特定语言的测试用例语料库;最好的办法是查找该语言的开源实现的测试目录(如果存在的话(。所以这基本上不是你问题的答案,但我希望它能提供一些有用的信息。

对于词法分析器,你应该尝试充分运用词法语法。许多词汇语法很少或根本没有实际的错误条件;任何输入都可以分解为某种类型的令牌

  • 字符编码错误(输入中的字节无法解码为有效代码点(
  • 未终止的引用文字和注释

您当然应该验证lexer在这种情况下的行为是否正确。您还应该验证您的lexer不会被过长的标记或引用文字中奇怪的转义序列阻塞。lexer经常处理不当的一个问题是输入末尾没有换行符。在错误输入中,文件过早结束可能出现在任何位置(例如,在字符串转义序列的中间(;确保你的测试也包括这些案例。

对于解析器,您肯定希望确保每个语法规则都至少通过一个输入进行测试。已经有人试图定义用于生成具有完全覆盖范围的测试集的算法;在互联网上搜索";语法测试用例生成";将产生大量线索。所有这些工具都有一些缺陷,但这些工具可以提供很大帮助。

语法错误更难测试。你可以使用模糊器——事实上,你可能应该使用模糊器,但随机干扰语法正确的输入可能会产生不同的语法正确输入。它肯定接近于";艺术,而非科学";。

如果你试图产生特定的、更有用的语法错误(这可能不是你作业的一部分(,那么你应该测试每个可能的、可纠正的错误案例。同样,您很可能需要手工构建测试集,同时考虑到您产生错误消息的目标。

如果您有时间,您还应该尝试找到输入,无论是否有效,这些输入都会将您的解析器推入二次或更差的解析时间。(对于生产解析器来说,这个测试是必要的,但它可能不在编译器课程的范围内。(这样的问题可能是由于解析器中不受控制的回溯(例如Antlr(造成的。它们也可能是哈希表实现和其他内部结构中明显无害的低效率的结果,这些低效率可能由恶意输入触发。

最新更新