dbghelp/tests: Add tests for image files lookup.
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
This commit is contained in:
parent
058bfeed1d
commit
2abbee9540
1 changed files with 287 additions and 0 deletions
|
@ -926,6 +926,292 @@ static void test_srvgetindexes_dbg(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void make_path(WCHAR file[MAX_PATH], const WCHAR* topdir, const WCHAR* subdir, const WCHAR* base)
|
||||
{
|
||||
wcscpy(file, topdir);
|
||||
if (subdir)
|
||||
{
|
||||
if (file[wcslen(file) - 1] != '\\') wcscat(file, L"\\");
|
||||
wcscat(file, subdir);
|
||||
}
|
||||
if (base)
|
||||
{
|
||||
if (file[wcslen(file) - 1] != '\\') wcscat(file, L"\\");
|
||||
wcscat(file, base);
|
||||
}
|
||||
}
|
||||
|
||||
struct path_validate
|
||||
{
|
||||
DWORD timestamp;
|
||||
DWORD size_of_image;
|
||||
unsigned cb_count;
|
||||
};
|
||||
|
||||
static BOOL CALLBACK path_cb(PCWSTR filename, void* _usr)
|
||||
{
|
||||
struct path_validate* pv = _usr;
|
||||
SYMSRV_INDEX_INFOW ssii;
|
||||
BOOL ret;
|
||||
|
||||
pv->cb_count++;
|
||||
/* wine returns paths in relative form, but relative to search path...
|
||||
* fail (== continue search) until it's fixed
|
||||
*/
|
||||
todo_wine_if(!filename[0] || filename[1] != ':')
|
||||
ok(filename[0] && filename[1] == ':', "Expecting full path, but got %ls\n", filename);
|
||||
if (!filename[0] || filename[1] != ':') return TRUE;
|
||||
|
||||
memset(&ssii, 0, sizeof(ssii));
|
||||
ssii.sizeofstruct = sizeof(ssii);
|
||||
ret = SymSrvGetFileIndexInfoW(filename, &ssii, 0);
|
||||
ok(ret, "SymSrvGetFileIndexInfo failed: %lu %ls\n", GetLastError(), filename);
|
||||
return !(ret && ssii.timestamp == pv->timestamp && ssii.size == pv->size_of_image);
|
||||
}
|
||||
|
||||
static unsigned char2index(char ch)
|
||||
{
|
||||
unsigned val;
|
||||
if (ch >= '0' && ch <= '9')
|
||||
val = ch - '0';
|
||||
else if (ch >= 'a' && ch <= 'z')
|
||||
val = 10 + ch - 'a';
|
||||
else val = ~0u;
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Despite what MS documentation states, option EXACT_SYMBOLS doesn't always work
|
||||
* (it looks like it's only enabled when symsrv.dll is loaded).
|
||||
* So, we don't test with EXACT_SYMBOLS set, nor with a NULL callback, and defer
|
||||
* to our own custom callback the testing.
|
||||
* (We always end when a full matched is found).
|
||||
*/
|
||||
static void test_find_in_path_pe(void)
|
||||
{
|
||||
HANDLE proc = (HANDLE)(DWORD_PTR)0x666002;
|
||||
WCHAR topdir[MAX_PATH];
|
||||
WCHAR search[MAX_PATH];
|
||||
WCHAR file[MAX_PATH];
|
||||
WCHAR found[MAX_PATH];
|
||||
struct path_validate pv;
|
||||
DWORD len;
|
||||
BOOL ret;
|
||||
int i;
|
||||
union nt_header hdr;
|
||||
|
||||
static const struct file_tests
|
||||
{
|
||||
unsigned bitness; /* 32 or 64 */
|
||||
DWORD timestamp;
|
||||
DWORD size_of_image;
|
||||
const WCHAR* module_path;
|
||||
}
|
||||
file_tests[] =
|
||||
{
|
||||
/* 0 */ { 64, 0x12345678, 0x0030cafe, L"foobar.dll" },
|
||||
/* 1 */ { 64, 0x12345678, 0x0030cafe, L"A\\foobar.dll" },
|
||||
/* 2 */ { 64, 0x12345678, 0x0030cafe, L"B\\foobar.dll" },
|
||||
/* 3 */ { 64, 0x56781234, 0x0010f00d, L"foobar.dll" },
|
||||
/* 4 */ { 64, 0x56781234, 0x0010f00d, L"A\\foobar.dll" },
|
||||
/* 5 */ { 64, 0x56781234, 0x0010f00d, L"B\\foobar.dll" },
|
||||
/* 6 */ { 32, 0x12345678, 0x0030cafe, L"foobar.dll" },
|
||||
/* 7 */ { 32, 0x12345678, 0x0030cafe, L"A\\foobar.dll" },
|
||||
/* 8 */ { 32, 0x12345678, 0x0030cafe, L"B\\foobar.dll" },
|
||||
/* 9 */ { 32, 0x56781234, 0x0010f00d, L"foobar.dll" },
|
||||
/* a */ { 32, 0x56781234, 0x0010f00d, L"A\\foobar.dll" },
|
||||
/* b */ { 32, 0x56781234, 0x0010f00d, L"B\\foobar.dll" },
|
||||
};
|
||||
static const struct image_tests
|
||||
{
|
||||
/* files to generate */
|
||||
const char* files;
|
||||
/* parameters for lookup */
|
||||
DWORD lookup_timestamp;
|
||||
DWORD lookup_size_of_image;
|
||||
const char* search; /* several of ., A, B to link to directories */
|
||||
const WCHAR* module;
|
||||
/* expected results */
|
||||
const WCHAR* found_subdir;
|
||||
DWORD expected_cb_count;
|
||||
}
|
||||
image_tests[] =
|
||||
{
|
||||
/* all files 64 bit */
|
||||
/* the passed timestamp & size are not checked before calling the callback! */
|
||||
/* 0 */ { "0", 0x00000000, 0x00000000, ".", L"foobar.dll", NULL, 1},
|
||||
/* 1 */ { "0", 0x12345678, 0x00000000, ".", L"foobar.dll", NULL, 1},
|
||||
/* 2 */ { "0", 0x00000000, 0x0030cafe, ".", L"foobar.dll", NULL, 1},
|
||||
/* 3 */ { "0", 0x12345678, 0x0030cafe, ".", L"foobar.dll", L"", 1},
|
||||
/* no recursion into subdirectories */
|
||||
/* 4 */ { "1", 0x12345678, 0x0030cafe, ".", L"foobar.dll", NULL, 0},
|
||||
/* directories are searched in order */
|
||||
/* 5 */ { "15", 0x12345678, 0x0030cafe, "AB", L"foobar.dll", L"A\\", 1},
|
||||
/* 6 */ { "15", 0x12345678, 0x0030cafe, "BA", L"foobar.dll", L"A\\", 2},
|
||||
/* 7 */ { "12", 0x12345678, 0x0030cafe, "AB", L"foobar.dll", L"A\\", 1},
|
||||
/* 8 */ { "12", 0x12345678, 0x0030cafe, "BA", L"foobar.dll", L"B\\", 1},
|
||||
|
||||
/* all files 32 bit */
|
||||
/* the passed timestamp & size is not checked ! */
|
||||
/* 9 */ { "6", 0x00000000, 0x00000000, ".", L"foobar.dll", NULL, 1},
|
||||
/* 10 */ { "6", 0x12345678, 0x00000000, ".", L"foobar.dll", NULL, 1},
|
||||
/* 11 */ { "6", 0x00000000, 0x0030cafe, ".", L"foobar.dll", NULL, 1},
|
||||
/* 12 */ { "6", 0x12345678, 0x0030cafe, ".", L"foobar.dll", L"", 1},
|
||||
/* no recursion into subdirectories */
|
||||
/* 13 */ { "7", 0x12345678, 0x0030cafe, ".", L"foobar.dll", NULL, 0},
|
||||
/* directories are searched in order */
|
||||
/* 14 */ { "7b", 0x12345678, 0x0030cafe, "AB", L"foobar.dll", L"A\\", 1},
|
||||
/* 15 */ { "7b", 0x12345678, 0x0030cafe, "BA", L"foobar.dll", L"A\\", 2},
|
||||
/* 16 */ { "78", 0x12345678, 0x0030cafe, "AB", L"foobar.dll", L"A\\", 1},
|
||||
/* 17 */ { "78", 0x12345678, 0x0030cafe, "BA", L"foobar.dll", L"B\\", 1},
|
||||
|
||||
/* machine and bitness is not used */
|
||||
/* 18 */ { "1b", 0x12345678, 0x0030cafe, "AB", L"foobar.dll", L"A\\", 1},
|
||||
/* 19 */ { "1b", 0x12345678, 0x0030cafe, "BA", L"foobar.dll", L"A\\", 2},
|
||||
/* 20 */ { "18", 0x12345678, 0x0030cafe, "AB", L"foobar.dll", L"A\\", 1},
|
||||
/* 21 */ { "18", 0x12345678, 0x0030cafe, "BA", L"foobar.dll", L"B\\", 1},
|
||||
/* 22 */ { "75", 0x12345678, 0x0030cafe, "AB", L"foobar.dll", L"A\\", 1},
|
||||
/* 23 */ { "75", 0x12345678, 0x0030cafe, "BA", L"foobar.dll", L"A\\", 2},
|
||||
/* 24 */ { "72", 0x12345678, 0x0030cafe, "AB", L"foobar.dll", L"A\\", 1},
|
||||
/* 25 */ { "72", 0x12345678, 0x0030cafe, "BA", L"foobar.dll", L"B\\", 1},
|
||||
|
||||
/* specifying a full path to module isn't taken into account */
|
||||
/* 26 */ { "0", 0x12345678, 0x0030cafe, "AB", L"@foobar.dll", NULL, 0},
|
||||
/* 27 */ { "6", 0x12345678, 0x0030cafe, "AB", L"@foobar.dll", NULL, 0},
|
||||
|
||||
};
|
||||
static const WCHAR* list_directories[] = {L"A", L"B", L"dll", L"symbols", L"symbols\\dll", L"acm", L"symbols\\acm"};
|
||||
|
||||
ret = SymInitializeW(proc, NULL, FALSE);
|
||||
ok(ret, "Couldn't init dbghelp\n");
|
||||
|
||||
len = GetTempPathW(ARRAY_SIZE(topdir), topdir);
|
||||
ok(len && len < ARRAY_SIZE(topdir), "Unexpected length\n");
|
||||
wcscat(topdir, L"dh.tmp\\");
|
||||
ret = CreateDirectoryW(topdir, NULL);
|
||||
ok(ret, "Couldn't create directory\n");
|
||||
for (i = 0; i < ARRAY_SIZE(list_directories); i++)
|
||||
{
|
||||
make_path(file, topdir, list_directories[i], NULL);
|
||||
ret = CreateDirectoryW(file, NULL);
|
||||
ok(ret, "Couldn't create directory %u %ls\n", i, list_directories[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(image_tests); ++i)
|
||||
{
|
||||
const char* ptr;
|
||||
winetest_push_context("%u", i);
|
||||
|
||||
for (ptr = image_tests[i].files; *ptr; ptr++)
|
||||
{
|
||||
unsigned val = char2index(*ptr);
|
||||
if (val < ARRAY_SIZE(file_tests))
|
||||
{
|
||||
const struct file_tests* ft = &file_tests[val];
|
||||
struct debug_directory_blob* ds_blob;
|
||||
|
||||
make_path(file, topdir, NULL, ft->module_path);
|
||||
/* all modules created with ds pdb reference so that SymSrvGetFileInfoInfo() succeeds */
|
||||
ds_blob = make_pdb_ds_blob(ft->timestamp, &guid1, 124, "pdbds.pdb");
|
||||
if (ft->bitness == 64)
|
||||
{
|
||||
init_headers64(&hdr.nt_header64, ft->timestamp, ft->size_of_image, 0);
|
||||
create_test_dll(&hdr, sizeof(hdr.nt_header64), &ds_blob, 1, file);
|
||||
}
|
||||
else
|
||||
{
|
||||
init_headers32(&hdr.nt_header32, ft->timestamp, ft->size_of_image, 0);
|
||||
create_test_dll(&hdr, sizeof(hdr.nt_header32), &ds_blob, 1, file);
|
||||
}
|
||||
free(ds_blob);
|
||||
}
|
||||
else ok(0, "Unrecognized file reference %c\n", *ptr);
|
||||
}
|
||||
|
||||
search[0] = L'\0';
|
||||
for (ptr = image_tests[i].search; *ptr; ptr++)
|
||||
{
|
||||
if (*search) wcscat(search, L";");
|
||||
wcscat(search, topdir);
|
||||
if (*ptr == '.')
|
||||
;
|
||||
else if (*ptr == 'A')
|
||||
wcscat(search, L"A");
|
||||
else if (*ptr == 'B')
|
||||
wcscat(search, L"B");
|
||||
else ok(0, "Unrecognized file reference %c\n", *ptr);
|
||||
}
|
||||
|
||||
if (image_tests[i].module[0] == L'@')
|
||||
make_path(file, topdir, NULL, &image_tests[i].module[1]);
|
||||
else
|
||||
wcscpy(file, image_tests[i].module);
|
||||
|
||||
pv.timestamp = image_tests[i].lookup_timestamp;
|
||||
pv.size_of_image = image_tests[i].lookup_size_of_image;
|
||||
pv.cb_count = 0;
|
||||
memset(found, 0, sizeof(found));
|
||||
|
||||
ret = SymFindFileInPathW(proc, search, file,
|
||||
(void*)&image_tests[i].lookup_timestamp,
|
||||
image_tests[i].lookup_size_of_image, 0,
|
||||
SSRVOPT_DWORDPTR, found, path_cb, &pv);
|
||||
|
||||
todo_wine
|
||||
ok(pv.cb_count == image_tests[i].expected_cb_count,
|
||||
"Mismatch in cb count, got %u (expected %lu)\n",
|
||||
pv.cb_count, image_tests[i].expected_cb_count);
|
||||
if (image_tests[i].found_subdir)
|
||||
{
|
||||
size_t l1, l2, l3;
|
||||
|
||||
ok(ret, "Couldn't find file: %ls %lu\n", search, GetLastError());
|
||||
|
||||
l1 = wcslen(topdir);
|
||||
l2 = wcslen(image_tests[i].found_subdir);
|
||||
l3 = wcslen(image_tests[i].module);
|
||||
|
||||
ok(l1 + l2 + l3 == wcslen(found) &&
|
||||
!memcmp(found, topdir, l1 * sizeof(WCHAR)) &&
|
||||
!memcmp(&found[l1], image_tests[i].found_subdir, l2 * sizeof(WCHAR)) &&
|
||||
!memcmp(&found[l1 + l2], image_tests[i].module, l3 * sizeof(WCHAR)),
|
||||
"Mismatch in found file %ls (expecting %ls)\n",
|
||||
found, image_tests[i].found_subdir);
|
||||
}
|
||||
else
|
||||
{
|
||||
todo_wine_if(i == 26 || i == 27)
|
||||
ok(!ret, "File reported found, while failure is expected\n");
|
||||
todo_wine_if(i == 26 || i == 27 || (GetLastError() != ERROR_FILE_NOT_FOUND))
|
||||
ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Unexpected error %lu\n", GetLastError());
|
||||
}
|
||||
for (ptr = image_tests[i].files; *ptr; ptr++)
|
||||
{
|
||||
unsigned val = char2index(*ptr);
|
||||
if (val < ARRAY_SIZE(file_tests))
|
||||
{
|
||||
const struct file_tests* ft = &file_tests[val];
|
||||
make_path(file, topdir, NULL, ft->module_path);
|
||||
ret = DeleteFileW(file);
|
||||
ok(ret, "Couldn't delete file %c %ls\n", *ptr, file);
|
||||
}
|
||||
else ok(0, "Unrecognized file reference %c\n", *ptr);
|
||||
}
|
||||
winetest_pop_context();
|
||||
}
|
||||
|
||||
SymCleanup(proc);
|
||||
|
||||
for (i = ARRAY_SIZE(list_directories) - 1; i >= 0; i--)
|
||||
{
|
||||
make_path(file, topdir, list_directories[i], NULL);
|
||||
ret = RemoveDirectoryW(file);
|
||||
ok(ret, "Couldn't remove directory %u %ls\n", i, list_directories[i]);
|
||||
}
|
||||
|
||||
ret = RemoveDirectoryW(topdir);
|
||||
ok(ret, "Couldn't remove directory\n");
|
||||
}
|
||||
|
||||
START_TEST(path)
|
||||
{
|
||||
/* cleanup env variables that affect dbghelp's behavior */
|
||||
|
@ -935,4 +1221,5 @@ START_TEST(path)
|
|||
test_srvgetindexes_pe();
|
||||
test_srvgetindexes_pdb();
|
||||
test_srvgetindexes_dbg();
|
||||
test_find_in_path_pe();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue