当前位置:  开发笔记 > 编程语言 > 正文

更换功能单元

如何解决《更换功能单元》经验,为你挑选了2个好方法。

我正在为大型Delphi代码库编写单元测试基础结构.我想将SysUtils.FileExists中对纯函数的调用链接到例如"MockSysUtils.FileExists".

编译器不支持创建具有相同接口的SysUtils单元.

我在想的是在运行时挂钩我的mock函数.现在这可能吗?

还有其他建议吗?

问候,

彼得



1> Barry Kelly..:

运行时替换函数很困难,但通常在技术上是可行的.你需要做的"全部"是:

获取有问题的函数的地址

反汇编前5个字节左右(检查RET指令 - 非常小的例程可能会与另一个例程相邻,阻止您更换它)

将其页面保护(with VirtualProtect)更改为可写

使用JMP rel32指令重写前5个字节(即E9 )

正常实现你的版本函数,确保它具有与你正在模拟的函数相同的参数和调用约定

更简单的方法是链接不同版本的SysUtils.pas.这将要求您还重新编译依赖于SysUtils.pas的RTL和VCL中的所有单元,但它可能比上述函数入门方法更容易.

最简单的方法是语言级方法,其中要么根本不直接依赖SysUtils(因此可以在更高级别切换),要么修改uses声明以有条件地引用不同的单元.



2> Rob Kennedy..:

你可以用MadCodeHook做到这一点.使用该HookCode函数,为其指定要替换的函数的地址以及要调用的函数的地址.它将返回一个函数指针,您可以使用它来调用原始函数,然后取消摘取.从本质上讲,它实现了巴里描述的中间三个步骤.

我认为MadCodeHook是免费供个人使用的.如果您正在寻找比这更自由的东西,您可以尝试找到旧版本的Tnt Unicode控件.它使用相同的挂钩技术将Unicode支持注入到某些VCL代码中.你需要一个旧版本,因为最近的版本不再免费.OverwriteProcedureTntSystem.pas中找到该函数,您也可以在其中找到如何使用它的示例.

代码挂钩很好,因为它不需要您重新编译RTL和VCL,并且它不涉及条件编译来控制哪些函数在范围内.您可以从单元测试设置过程中挂钩代码,原始代码永远不会知道区别.它会认为它正在调用原始FileExists函数(因为它是),但是当它到达那里时,它会立即跳转到你的模拟版本.

推荐阅读
手机用户2402852307
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有