【发布时间】:2011-01-09 09:44:33
【问题描述】:
我正在编写各种调用相对复杂的 Win32 API 函数的东西。这是一个例子:
//Encapsulates calling NtQuerySystemInformation buffer management.
WindowsApi::AutoArray NtDll::NtQuerySystemInformation(
SystemInformationClass toGet ) const
{
AutoArray result;
ULONG allocationSize = 1024;
ULONG previousSize;
NTSTATUS errorCheck;
do
{
previousSize = allocationSize;
result.Allocate(allocationSize);
errorCheck = WinQuerySystemInformation(toGet,
result.GetAs<void>(), allocationSize, &allocationSize);
if (allocationSize <= previousSize)
allocationSize = previousSize * 2;
} while (errorCheck == 0xC0000004L);
if (errorCheck != 0)
{
THROW_MANUAL_WINDOWS_ERROR(WinRtlNtStatusToDosError(errorCheck));
}
return result;
}
//Client of the above.
ProcessSnapshot::ProcessSnapshot()
{
using Dll::NtDll;
NtDll ntdll;
AutoArray systemInfoBuffer = ntdll.NtQuerySystemInformation(
NtDll::SystemProcessInformation);
BYTE * currentPtr = systemInfoBuffer.GetAs<BYTE>();
//Loop through the results, creating Process objects.
SYSTEM_PROCESSES * asSysInfo;
do
{
// Loop book keeping
asSysInfo = reinterpret_cast<SYSTEM_PROCESSES *>(currentPtr);
currentPtr += asSysInfo->NextEntryDelta;
//Create the process for the current iteration and fill it with data.
std::auto_ptr<ProcImpl> currentProc(ProcFactory(
static_cast<unsigned __int32>(asSysInfo->ProcessId), this));
NormalProcess* nptr = dynamic_cast<NormalProcess*>(currentProc.get());
if (nptr)
{
nptr->SetProcessName(asSysInfo->ProcessName);
}
// Populate process threads
for(ULONG idx = 0; idx < asSysInfo->ThreadCount; ++idx)
{
SYSTEM_THREADS& sysThread = asSysInfo->Threads[idx];
Thread thread(
currentProc.get(),
static_cast<unsigned __int32>(sysThread.ClientId.UniqueThread),
sysThread.StartAddress);
currentProc->AddThread(thread);
}
processes.push_back(currentProc);
} while(asSysInfo->NextEntryDelta != 0);
}
我的问题是在模拟 NtDll::NtQuerySystemInformation 方法 - 即返回的数据结构很复杂(嗯,这里实际上相对简单但它可能很复杂),并编写一个构建数据结构的测试,如API 调用所花费的时间可能是编写使用 API 的代码的 5-6 倍。
我想做的是调用 API,并以某种方式记录它,这样我就可以将记录的值返回给被测代码,而无需实际调用 API。返回的结构不能简单地进行 memcpy 处理,因为它们通常包含内部指针(指向同一缓冲区中其他位置的指针)。有问题的库需要检查这些类型的东西,并且能够在重放时将指针值恢复到类似的缓冲区。 (即检查每个指针大小的值是否可以被解释为缓冲区中的指针,将其更改为偏移量,并记住在重放时将其更改回指针 - 这里的误报率是可以接受的)
有什么东西可以做这样的事情吗?
【问题讨论】:
-
@Nicklamor:是的。 (无需删除评论——这是个好问题)
-
@NickL “API”在这种情况下是 Windows API。我会调用我想要的函数作为进行实际单元测试的一部分。
-
@Nick:我正在寻找一般的东西;也就是说,它不会关心调用了什么 API 函数。
-
@Billy:您是否尝试这样做,以便您拥有更容易读取的数据结构(AutoArray),或者因为您不想通过 api 调用更改内部变量/指针值确实如此,还是两者兼而有之? ps-谢谢你的耐心
-
@Nick:两者都不是。出于测试目的,我希望能够替换 API 调用本身。例如,在上面,如果我想编写测试,我不能简单地为客户端方法的输出编写测试,因为每次测试运行返回的进程都会不同。我想保存API返回的缓冲区,以后可以返回缓冲区。
标签: c++ unit-testing