测试 – 作为交互式C程序测试器
我愿意使用交互式语言来测试遗留项目中的一些C代码.我知道一点点,但我还没有在现实世界的项目中使用它.我现在正在看pForth.
使用交互式Forth解释器来测试C程序中某些函数的行为是否合理?这个C代码有很多结构,指向结构的指针,句柄和C中的其他常见结构. 我想我必须编写一些胶水代码来处理参数传递,并且可能在Forth方面进行一些结构分配.我想要有这方面经验的人的估计.这值得么? 解决方法
如果您想要进行交互式测试并且针对嵌入式平台,那么Forth绝对是一个不错的选择.您总能找到在目标平台上运行的Forth实现.如果需要,写一个甚至都不难.
而不是编写特定于您的直接需求的胶水代码,而是寻找通用的Forth to C接口.我使用gforth’s generic C interface这很容易使用.对于Forth中的结构处理,我使用MPE style implementation,它在与C接口时非常灵活(注意正确对齐,请参阅gforth%align /%allot / nalign). 通用目的结构处理单词的定义大约需要20行Forth代码,对于单个链接列表处理或散列表也是如此. 由于您不能使用gforth(仅限POSIX),请为您实现类似C接口的Forth编写扩展模块.只需确保您的Forth和C接口模块使用与您要测试的C代码相同的malloc()和free(). 通过这样的界面,您可以通过定义存根字(即将Forth字映射到C函数和结构)来完成Forth中的所有操作. 这是一个示例测试会话,我使用gforth的C接口调用libc的gettimeofday. s" structs.fs" included also structs load structure handling code clear-libs s" libc" add-lib load libc.so. Not really needed for this particular library c-library libc stubs for C functions c #include <sys/time.h> c-function gettimeofday gettimeofday a a -- n ( struct timeval *,struct timezone * -- int ) end-c-library struct timeval stub for struct timeval 8 field: ->tv_sec sizeof(time_t) == 8 bytes on my 64bits system 8 field: ->tv_usec end-struct timeval buffer: tv now call it (the 0 is for passing NULL for struct timezone *) tv 0 gettimeofday . Return value on the stack. output : 0 tv ->tv_sec @ . output : 1369841953 请注意,tv – > tv_sec实际上相当于C中的(void *)& tv offsetof(struct timeval,tv_sec),因此它为您提供了结构成员的地址,因此您必须使用@获取值. .这里的另一个问题是:由于我使用64位Forth,其中单元格大小为8字节,存储/获取8字节长是很简单的,但是获取/存储4字节int将需要一些特殊处理.无论如何,Forth让这很简单:只需定义特殊用途int @和int!为此而言. 正如您所看到的,使用一个好的通用C接口,您不需要在C中编写任何粘合代码,只需要C函数和结构的Forth存根,但这非常简单(并且大部分都可以自动完成)从您的C标头生成). 一旦您对交互式测试感到满意,您就可以继续进行自动化测试: >将交互式测试会话中的整个输入/输出复制/粘贴到名为testXYZ.log的文件中 由于从交互式会话日志中删除输出可能有点繁琐,您也可以先编写测试脚本testXYZ.fs然后运行它并捕获输出testXYZ.log,但我更喜欢从交互式会话日志开始. Etvoilà! 作为参考,这是我在上面的例子中使用的结构处理代码: ***************************************************************************** structures handling ***************************************************************************** Simple structure definition words. Structure instances are zero initialized. usage : struct foo int: ->refCount int: ->value end-struct struct bar int: ->id foo struct: ->foo 16 chars: ->name end-struct bar buffer: myBar foo buffer: myFoo 42 myBar ->id ! myFoo myBar ->foo ! myBar ->name count type 1 myBar ->foo @ ->refCount +! accessing members of members could use a helper word : struct ( "name" -- addr 0 ; named structure header ) create here 0,0 does> @ ; <field-size> FIELD <field-name> Given a field size on the stack,compiles a word <field-name> that adds the field size to the number on the stack. : field: ( u1 u2 "name" -- u1+u2 ; u -- u+u2 ) over >r save current struct size : r> ?dup if postpone literal postpone + then postpone ; + add field size to struct size ; immediate : end-struct ( addr u -- ; end of structure definition ) swap ! ; : naligned ( addr1 u -- addr2 ; aligns addr1 to alignment u ) 1- tuck + swap invert and ; Typed field helpers : int: cell naligned cell postpone field: ; immediate : struct: >r cell naligned r> postpone field: ; immediate : chars: >r cell naligned r> postpone field: ; immediate with C style alignment 4 constant C_INT_ALIGN 8 constant C_PTR_ALIGN 4 constant C_INT_SIZE : cint: C_INT_ALIGN naligned C_INT_SIZE postpone field: ; immediate : cstruct: >r C_PTR_ALIGN naligned r> postpone field: ; immediate : cchars: >r C_INT_ALIGN naligned r> postpone field: ; immediate : buffer: ( u -- ; creates a zero-ed buffer of size u ) create here over erase allot ; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |