标签 博客 下的文章

buildc 0.1.4版本发布

年后buildc开始逐渐在产品线的项目里应用了,随之而来的是大家反馈的各种意见和bug。尤其是bug,我都会很认真地应对,也会及时发布相应的版本修复这些bug。buildc 0.1.4版本就是一个bugfix版本,其修复的bug源于今天上午的一次持续集成的失败。

 
上午收到Jenkins发送的一个"build failed"的mail,一个安装包项目CI job执行失败了,于是到Jenkins web页面上检查错误原因。这个Job会在两个slave node上执行集成,一个在x86 linux上,一个在x86 solaris上。这次失败是因为x86 linux上的一个配置问题导致的,页面显示x86 solaris那个节点的集成是成功的。我无意间查看了x86 solaris节点集成过程的命令行输出,发现如下内容:
 
Config Make.rules OK!
Failed to execute cmd [make CMODE=64-bit], errno = [512]
Finished: SUCCESS
 
显然,构建脚本并未真正成功,但Jenkins却认为这次集成是OK的,这是怎么回事呢?难道是Jenkins有问题?为了弄清原因,我登到那个Solaris节点上,进入到Jenkins slave工作目录下的workspace中,在对应的Job目录下,手工执行了集成脚本,执行结束后,通过"echo $?"查看命令的返回值,居然是"0",也就是说执行结果是成功的,这怎么可能?明明代码中输出是"errno= [512]"。
 
为了验证问题,我编写了一个测试程序以验证代码执行是否正确:
 
# testerrno.py
 
#! /usr/bin/env python
 
import commands
import sys
 
def execute(cmd):
        o = commands.getstatusoutput(cmd)
        if o[0] != 0:
            print "Failed to execute cmd [%s], errno = [%d]” % (cmd, o[0])
            sys.exit(o[0])
        return o
 
if __name__ == '__main__':
        execute('ls -l foo')
 
由于当前目录下并未有foo文件,因此预期testerrno.py的执行结果应该是失败的,执行过程如下:
 
$> testerrno.py
Failed to execute cmd [ls -l foo], errno = [512]
$> echo $?
0
 
从结果中可以看到,居然执行结果返回的真的是0。我将上述代码中的sys.exit(o[0])直接改为了sys.exit(512),我要看看究竟是怎么回事,结果执行结果又出乎我的意料:
 
$> testerrno.py
Failed to execute cmd [ls -l foo], errno = [512]
$> echo $?
0
 
居然还是0。突然脑海中冒出一个思路:难道是Shell不支持512这么大的errno?于是将512改为23,再试:
 
$> testerrno.py
Failed to execute cmd [ls -l foo], errno = [512]
$> echo $?
23
 
执行后得到的结果为:23。看来我的思路是正确的,那Shell支持的最大errno值究竟是多少呢?经验告诉我很可能是255。于是乎我又分别将返回值硬编码为255和256并执行之,结果当返回值为255时,echo $?的输出为255;当返回值为256时,echo $?的返回值居然变成了0,看来就是这个问题了。关于为何Python获取到的ls -l foo的执行结果为512(commands.getstatusoutput的返回结果),我没有深究,但如果手工在命令行上执行'ls -l foo',得到的返回值实际上是2,而不是512。另外我的Shell版本为:GNU bash, version 3.00.16。
 
如何修复buildc的这个问题呢?我的方法是让command.execute在执行命令出错时返回同一个指定的错误码,目前为errors.py中shell_cmd_exec_failed值。但command.execute会打印commands.getstatusoutput返回结果中的真实错误码值,两不耽误。
 
于是就有了这buildc 0.1.4版本,该版本在Python 2.4.3和Python 2.6.2下都测试OK。

lcut 0.3.0版本发布

lcut单元测试框架在我的项目中应用已经有一段时间了,项目组的同事对lcut的使用也是越来越熟悉,这不今天一位同事还提出了一个新需求,需求大致是这样的。

 
在实际项目中,经常遇到这类情况:
 
int bar(…) {
    int ret;
 
    ret = foo(…);
    /* assert ret */
    …
 
    ret = foo(…);
    /* assert ret */
    …
 
    ret = foo(…);
    /* assert ret */
    …
}
 
上述代码中被测函数接口bar的实现中多次调用了某函数foo。这样当我们用mock方式测试bar这个函数时,可能需要多次重复设置foo的返回值以及输出函数的值,就像这样:
 
void tc_test_bar_return_ok(lcut_tc_t *tc, void *data) {
    LCUT_RETV_RETURN(foo, 0);
    LCUT_RETV_RETURN(foo, 0);
    LCUT_RETV_RETURN(foo, 0);
 
    LCUT_ARG_RETURN(foo, 1);
    LCUT_ARG_RETURN(foo, 1);
    LCUT_ARG_RETURN(foo, 1);
 
    LCUT_INT_EQUAL(tc, 0, bar(…));
    …
}
 
我的同事希望lcut能提供一个接口:支持一次调用,设置多次mock obj的返回值或输出参数,使用这样的接口后,上述代码就可以简化为:
 
void tc_test_bar_return_ok(lcut_tc_t *tc, void *data) {
    LCUT_RETV_RETURN_COUNT(foo, 0, 3);
    LCUT_ARG_RETURN_COUNT(foo, 1, 3);
 
    LCUT_INT_EQUAL(tc, 0, bar(…));
}
 
这个需求提的非常好,看起来更像是一种语法糖(syntactic sugar),用于简化代码编写。于是乎下午我就为lcut增加了两个有用的宏:LCUT_RETV_RETURN_COUNT和LCUT_ARG_RETURN_COUNT。
 
正如上面所说,这两个宏可在一次调用中多次设置某个mock obj的返回值和输出参数值,两个宏的原型如下:
 
#define LCUT_RETV_RETURN_COUNT(fcname, value, count) do { \
        lcut_mock_obj_return(#fcname, (void*)value, __FUNCTION__, __LINE__, __FILE__, MOCK_RETV, count); \
    } while(0);
 
#define LCUT_ARG_RETURN_COUNT(fcname, value, count) do { \
        lcut_mock_obj_return(#fcname, (void*)value, __FUNCTION__, __LINE__, __FILE__, MOCK_ARG, count); \
    } while(0);
 
只是比之前提供的LCUT_RETV_RETURN和LCUT_ARG_RETURN多了一个宏参数count。count用于指出对mocked obj进行多少次返回值或输出参数的设置。
 
另外当count传入-1时,其语义为无论mocked object被使用多少次,其返回值或输出参数值都是一样的,即使用LCUT_RETV_RETURN_COUNT或LCUT_ARG_RETURN_COUNT时设置的那个值,直到下一次调用这两个宏进行重新设置时,值才会发生变化。例如上面的例子我们也可以改写为:
 
void tc_test_bar_return_ok(lcut_tc_t *tc, void *data) {
    LCUT_RETV_RETURN_COUNT(foo, 0, -1);
    LCUT_ARG_RETURN_COUNT(foo, 1, -1);
 
    LCUT_INT_EQUAL(tc, 0, bar(…));
}
 
这样无论后续再调用多少次bar函数,foo的返回值总是0,输出参数也总是1。
 
增加了这两个宏后,lcut的版本号也小升了一位,最新版本是lcut-0.3.0-rc1,其中还增加了一个针对lcut mock功能的example – mock_test.c。同时Google Code上的lcut guide也做了更新,对新增的宏的用法进行了简要说明。
 
就这样,lcut 0.3.0版本算是发布了,后续还会经过内部的细致测试,如果没有什么问题,就会去掉rc。
如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言进阶课 Go语言精进之路1 Go语言精进之路2 Go语言第一课 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats