在testing应用程序稳定性时,我试图删除/损坏应用程序使用的数据库。 OS是Windows,文件系统是NTFS,testing语言是C ++。
我需要的是将任何东西粘贴到数据库文件或删除它。 但在运行过程中被testing的应用程序locking。 所以,也许有人遇到过这种情况,你可以给我/我们可能的方式来绕过testing代码中的这个锁的例子? 理论或来源 – 我很欣赏任何forms的帮助。
你将不得不关闭你的应用程序对文件的句柄。 请记住,我相信你将不得不在你的应用程序中再次打开你的文件。
我发现了一个不同的但类似的问题,解决您的问题的示例代码: 在Windows上强制关闭文件的路径
您只需要复制所有内容,并替换删除文件的部分来破坏文件。 我希望这有助于:D
一般来说,接管文件锁的所有权不是操作系统提供或应该做的,而不是没有原始锁拥有者的协助。 (1)您不能轻易绕过操作系统的安全保证,当然不能从您的用户级别的测试代码。
有关如何在原始所有者的积极协助下完成此操作的指示信息,请参阅MSDN:Windows→开发人员中心 – 桌面→LockFileEx函数和MSDN:Windows→开发人员中心 – 桌面→DuplicateHandle函数,但这不可能如您所愿想去。
有关SqLite
数据库锁定方法(您的应用程序使用)的说明, 请参见http://www.sqlite.org/lockingv3.html ,特别是“如何破坏数据库文件”一章中的说明
显然,将不正确的数据引入到数据库文件或日志中间的硬件或操作系统错误将导致问题。 同样,如果一个流氓程序打开一个数据库文件或日志,并将错误的数据写入中间,那么数据库就会被破坏。 对这类问题没有什么可以做的,所以没有给予进一步的关注。
如果你真的想模拟事情如何变得非常错误,那么一种方法是(2)用pager module
( http://www.sqlite.org/src/finfo?name=src/pager )构建自定义的仅测试SqLite 。 c )妥协,SqLite有可用的源代码,所以可以定制
(3)最常用的理论认为,对于你的测试场景,你应该使用特殊的测试环境配备Mock对象,伪装你想要测试的行为。 在这样的测试环境中,您的应用程序将以特殊的“测试中”模式进行编译,应用程序在被要求时会自动临时释放SqLite
连接,以便环境可以模拟操作系统或硬件故障,然后继续。
在应用程序中使用模拟对象要容易得多,例如在黑盒环境中伪造错误的文件系统驱动程序。
相关: http : //en.wikipedia.org/wiki/Software_testing#Destructive_testing
#include <Windows.h> #include <stdio.h> #include <string.h> #include <tchar.h> #include <iostream> #include <FileAPI.h> #include <WinBase.h> #include <conio.h> #include <ctype.h> #define START_ALLOC 0x1000 #define STATUS_INFO_LENGTH_MISMATCH 0xC0000004 #define SystemHandleInformation 0x10 typedef long(__stdcall *NtQSI)( ULONG SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength ); typedef struct _SYSTEM_HANDLE_ENTRY { ULONG OwnerPid; BYTE ObjectType; BYTE HandleFlags; USHORT HandleValue; PVOID ObjectPointer; ACCESS_MASK AccessMask; } SYSTEM_HANDLE_ENTRY, *PSYSTEM_HANDLE_ENTRY; int main(int argc, char *argv[]) { HMODULE hNtDll = NULL; NtQSI pNtQSI = NULL; PVOID pMem = NULL; ULONG allocSize = START_ALLOC; ULONG retVal = 0; // -------------------------------- ULONG hCount = 0; PSYSTEM_HANDLE_ENTRY hFirstEntry = NULL; // -------------------------------- ULONG i; hNtDll = LoadLibraryA("NTDLL.dll"); if (!hNtDll) return 1; pNtQSI = (NtQSI)GetProcAddress(hNtDll, "NtQuerySystemInformation"); if (!pNtQSI) { FreeLibrary(hNtDll); return 2; } pMem = malloc(allocSize); while (pNtQSI(SystemHandleInformation, pMem, allocSize, &retVal) == STATUS_INFO_LENGTH_MISMATCH) { pMem = realloc(pMem, allocSize *= 2); } hCount = *(ULONG*)pMem; hFirstEntry = (PSYSTEM_HANDLE_ENTRY)((PBYTE)pMem + 4); int pid = atoi(argv[1]); for (i = 0; i < hCount; ++i) if ((hFirstEntry[i].ObjectType == 30) && (hFirstEntry[i].OwnerPid == pid)) { HANDLE TargetHandleValueTemp = (HANDLE)hFirstEntry[i].HandleValue; HANDLE SourceProcHandleTemp = OpenProcess(PROCESS_DUP_HANDLE, FALSE, hFirstEntry[i].OwnerPid); char confirm ='n'; DuplicateHandle(SourceProcHandleTemp, (HANDLE)hFirstEntry[i].HandleValue, GetCurrentProcess(), &TargetHandleValueTemp, 0, FALSE, DUPLICATE_SAME_ACCESS); TCHAR Path[MAX_PATH]; DWORD dwret = GetFinalPathNameByHandle(TargetHandleValueTemp, Path, MAX_PATH, 0); if (!argv[2]) { _tprintf(TEXT("PID: %d\tFileHandle: %d\tThe final path is: %s\n"), hFirstEntry[i].HandleValue, TargetHandleValueTemp, Path); } else if (_tcsstr(Path, _T(argv[2]))) { _tprintf(TEXT("PID: %d\tFileHandle: %d\tThe final path is: %s\n\t Remove it? (y/n): "), hFirstEntry[i].HandleValue, TargetHandleValueTemp, Path); _flushall(); std::cin.get(confirm); if (confirm == 'y') DuplicateHandle(SourceProcHandleTemp, (HANDLE)hFirstEntry[i].HandleValue, GetCurrentProcess(), &TargetHandleValueTemp, 0, FALSE, DUPLICATE_CLOSE_SOURCE); } CloseHandle(SourceProcHandleTemp); CloseHandle(TargetHandleValueTemp); } free(pMem); FreeLibrary(hNtDll); }