
实现一个简单的Database4(译文)
Part 4 我们的第一个测试(和BUG)
我们已经获得插入数据到数据库并打印所有数据的能力。现在来测试一下目前已有的功能。
我使用rspec来写我的测试,因为我对rspec很熟悉,它的语法也相当易读。
译注:rsepec 是一个基于Ruby的测试框架,语法非常简单,可以很方便的测试各种可执行程序,判断输出
我定义一个短小的help来发送一个帮助命令列表到数据库,然后对输出进行断言。
这个简单的测试是确认我们的输入能够获取返回结果。并确保能通过测试:
现在测试插入更多行数据到数据库是可行的:
再次运行测试:
妙啊,测试通过了!我们的数据库现在能够hold住1400行数据,这是因为我们设置pages最大数量是100页,每页可以存放14行数据。
查看我们目前写的的代码,我意识到我们可能没有正确处理存储文本字段。很容易用下面的例子测试出来(插入边界长度的字符串):
测试失败了:
如果是我们自己人工来测试,当我们打印行数据时,会看到有一些奇怪的字符(例子中,我把很长的字符串进行了缩写):
发生了什么?如果看一下代码中我们定义的Row结构,我们确实为username字段分配了32个字节长度,为email字段分配255个字节长度。但是C语言的strings是以一个null字符来作为结尾的,这个字符我们没有为它分配空间。解决方法就是多分配一个额外的字节(来存放这个null字符):
这样确实解决了上面的问题(重新运行上面插入边界长度字符串的测试):
我们不允许插入的username或者email的长度超过固定的列的长度。这样的超出长度要求的spec测试看起来就像下面这样:
为了能够支持上面这种效果,我们需要升级我们的解析器(parser)。提醒一下,我们现在使用的是scanf()
:
但是scanf()
有一些缺点。如果读取的string大于正在读取它的缓存(buffer),就会引起缓存溢出(buffer overflow)并写入到意想不到的地方。所以我们需要在拷贝string到Row结构前检查每一个string的长度。为了检查string长度,我们需要用空格分割输入。
译注: strtok: 字符串处理函数,char * strtok ( char * str, const char * delimiters ); 分解字符串为一组字符串。str为要分解的字符,delimiters为分隔符字符(如果传入字符串,则传入的字符串中每个字符均为分割符)
我使用strtok()
来做这些。如果你看到过程就会觉得它很容易理解:
每当输入到一个分隔符时(在我们的例子中就是空格),就在输入缓冲(input buffer)上连续调用strtok()
,把它分解成子字符串。它返回一个指向子字符串开始位置的指针。
我们可以在每个文本值上调用strlen()
,看看它是否太长(strlen()
函数,获取字符串的长度)。
我们可以像处理其他错误码一样处理错误:
这样就能通过测试了。
到了这里,我们不妨再多处理一个错误情况(id值插入一个负值):
好了,测试做的差不多了。接下来是非常重要的功能:持久化!我们要实现保存我们的数据库到一个文件,再把它从文件中读取出来。(目前它还在内存当中)
现在它越来越牛了。
下面是和上一部分代码,修改位置的对比:
并且我们添加了一些测试:
本文转载自公众号:GreatSQL社区
