From: Lauri Kenttä Subject: [PATCH v2] kernel32/tests: Test FindFirstFile etc. with wildcards. Message-Id: <20161203202719.2460-1-lauri.kentta@gmail.com> Date: Sat, 3 Dec 2016 22:27:19 +0200 Inspired by bug 7961. v2: Apparently Windows has much more strict limits for file names on native file systems (compared to VirtualBox shared folders), so this version of the patch leaves out some of the more problematic ones. Tested on Windows 2003 Server with NTFS. Signed-off-by: Lauri Kenttä --- dlls/kernel32/tests/file.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c index f039cf9..fa21a14 100644 --- a/dlls/kernel32/tests/file.c +++ b/dlls/kernel32/tests/file.c @@ -2812,6 +2812,103 @@ cleanup: RemoveDirectoryA("test-dir"); } +static void test_FindFirstFile_wildcards(void) +{ + WIN32_FIND_DATAA find_data; + HANDLE handle; + int i, j, k; + static const char* files[] = { + "..a", "..a..a", "..a..a..a", "..a.a", "..a.a..a", "..a.a.a", + ".a", ".a..a", ".a..a..a", ".a.a", ".a.a..a", ".a.a.a", ".aa", ".aaa", + "a", "a..a", "a..a..a", "a..a.a", "a.a", "a.a..a", "a.a.a", + "a.aa", "aa", "aa.a", "aaa", "aaaa" + }; + static const struct { + int todo; + const char *pattern, *result; + } tests[] = { + {0, "*.*.*", "'.', '..', '..a', '..a..a', '..a..a..a', '..a.a', '..a.a..a', '..a.a.a', '.a', '.a..a', '.a..a..a', '.a.a', '.a.a..a', '.a.a.a', '.aa', '.aaa', 'a', 'a..a', 'a..a..a', 'a..a.a', 'a.a', 'a.a..a', 'a.a.a', 'a.aa', 'aa', 'aa.a', 'aaa', 'aaaa'"}, + {0, "*.*.", "'.', '..', '..a', '..a..a', '..a..a..a', '..a.a', '..a.a..a', '..a.a.a', '.a', '.a..a', '.a..a..a', '.a.a', '.a.a..a', '.a.a.a', '.aa', '.aaa', 'a', 'a..a', 'a..a..a', 'a..a.a', 'a.a', 'a.a..a', 'a.a.a', 'a.aa', 'aa', 'aa.a', 'aaa', 'aaaa'"}, + {0, ".*.*", "'.', '..', '..a', '..a..a', '..a..a..a', '..a.a', '..a.a..a', '..a.a.a', '.a', '.a..a', '.a..a..a', '.a.a', '.a.a..a', '.a.a.a', '.aa', '.aaa'"}, + {0, "*.*", "'.', '..', '..a', '..a..a', '..a..a..a', '..a.a', '..a.a..a', '..a.a.a', '.a', '.a..a', '.a..a..a', '.a.a', '.a.a..a', '.a.a.a', '.aa', '.aaa', 'a', 'a..a', 'a..a..a', 'a..a.a', 'a.a', 'a.a..a', 'a.a.a', 'a.aa', 'aa', 'aa.a', 'aaa', 'aaaa'"}, + {0, ".*", "'.', '..', '..a', '..a..a', '..a..a..a', '..a.a', '..a.a..a', '..a.a.a', '.a', '.a..a', '.a..a..a', '.a.a', '.a.a..a', '.a.a.a', '.aa', '.aaa'"}, + {1, "*.", "'.', '..', 'a', '.a', '..a', 'aa', '.aa', 'aaa', 'aaaa', '.aaa'"}, + {0, "*", "'.', '..', '..a', '..a..a', '..a..a..a', '..a.a', '..a.a..a', '..a.a.a', '.a', '.a..a', '.a..a..a', '.a.a', '.a.a..a', '.a.a.a', '.aa', '.aaa', 'a', 'a..a', 'a..a..a', 'a..a.a', 'a.a', 'a.a..a', 'a.a.a', 'a.aa', 'aa', 'aa.a', 'aaa', 'aaaa'"}, + {1, "*..*", "'.', '..', '..a', '..a..a', '..a..a..a', '..a.a', '..a.a..a', '..a.a.a', '.a..a', '.a..a..a', '.a.a..a', 'a..a', 'a..a..a', 'a..a.a', 'a.a..a'"}, + {1, "*..", "'.', '..', 'a', '.a', '..a', 'aa', '.aa', 'aaa', 'aaaa', '.aaa'"}, + {1, ".*.", "'.', '..', '.a', '.aa', '.aaa'"}, + {0, "..*", "'.', '..', '..a', '..a..a', '..a..a..a', '..a.a', '..a.a..a', '..a.a.a'"}, + {0, "**", "'.', '..', '..a', '..a..a', '..a..a..a', '..a.a', '..a.a..a', '..a.a.a', '.a', '.a..a', '.a..a..a', '.a.a', '.a.a..a', '.a.a.a', '.aa', '.aaa', 'a', 'a..a', 'a..a..a', 'a..a.a', 'a.a', 'a.a..a', 'a.a.a', 'a.aa', 'aa', 'aa.a', 'aaa', 'aaaa'"}, + {0, "**.", "'.', '..', '..a', '..a..a', '..a..a..a', '..a.a', '..a.a..a', '..a.a.a', '.a', '.a..a', '.a..a..a', '.a.a', '.a.a..a', '.a.a.a', '.aa', '.aaa', 'a', 'a..a', 'a..a..a', 'a..a.a', 'a.a', 'a.a..a', 'a.a.a', 'a.aa', 'aa', 'aa.a', 'aaa', 'aaaa'"}, + {0, "*. ", "'.', '..', '..a', '..a..a', '..a..a..a', '..a.a', '..a.a..a', '..a.a.a', '.a', '.a..a', '.a..a..a', '.a.a', '.a.a..a', '.a.a.a', '.aa', '.aaa', 'a', 'a..a', 'a..a..a', 'a..a.a', 'a.a', 'a.a..a', 'a.a.a', 'a.aa', 'aa', 'aa.a', 'aaa', 'aaaa'"}, + {1, "* .", "'.', '..', 'a', '.a', '..a', 'aa', '.aa', 'aaa', 'aaaa', '.aaa'"}, + {0, "* . ", "'.', '..', '..a', '..a..a', '..a..a..a', '..a.a', '..a.a..a', '..a.a.a', '.a', '.a..a', '.a..a..a', '.a.a', '.a.a..a', '.a.a.a', '.aa', '.aaa', 'a', 'a..a', 'a..a..a', 'a..a.a', 'a.a', 'a.a..a', 'a.a.a', 'a.aa', 'aa', 'aa.a', 'aaa', 'aaaa'"}, + {0, "*.. ", "'.', '..', '..a', '..a..a', '..a..a..a', '..a.a', '..a.a..a', '..a.a.a', '.a', '.a..a', '.a..a..a', '.a.a', '.a.a..a', '.a.a.a', '.aa', '.aaa', 'a', 'a..a', 'a..a..a', 'a..a.a', 'a.a', 'a.a..a', 'a.a.a', 'a.aa', 'aa', 'aa.a', 'aaa', 'aaaa'"}, + {1, "*. .", "'.', '..', 'a', '.a', '..a', 'aa', '.aa', 'aaa', 'aaaa', '.aaa'"}, + {1, "* ..", "'.', '..', 'a', '.a', '..a', 'aa', '.aa', 'aaa', 'aaaa', '.aaa'"}, + {1, " *..", "'.aaa'"}, + {0, "..* ", "'.', '..', '..a', '..a..a', '..a..a..a', '..a.a', '..a.a..a', '..a.a.a'"}, + {1, "?", "'.', '..', 'a'"}, + {1, "?.", "'.', '..', 'a'"}, + {1, "?. ", "'.', '..', 'a'"}, + {1, "??.", "'.', '..', 'a', 'aa'"}, + {1, "??. ", "'.', '..', 'a', 'aa'"}, + {1, "???.", "'.', '..', 'a', 'aa', 'aaa'"}, + {1, "?.??.", "'.', '..', '.a', '.aa', 'a', 'a.a', 'a.aa'"} + }; + + CreateDirectoryA("test-dir", NULL); + SetCurrentDirectoryA("test-dir"); + for (i = 0; i < sizeof(files) / sizeof(files[0]); ++i) + _lclose(_lcreat(files[i], 0)); + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) + { + char correct[512] = ""; + char incorrect[512] = ""; + char missed[512]; + strcpy(missed, tests[i].result); + + handle = FindFirstFileA(tests[i].pattern, &find_data); + if (handle) do { + char quoted[16] = "'"; + char* ptr; + strcat(quoted, find_data.cFileName); + strcat(quoted, "'"); + + /* Format results nicely. */ + if (strstr(tests[i].result, quoted)) + strcat(correct, ", "), strcat(correct, quoted); + else + strcat(incorrect, ", "), strcat(incorrect, quoted); + if ((ptr = strstr(missed, quoted))) + { + while ((*ptr++ = ' ') && *ptr && *ptr != ' '); + while (ptr != missed && ptr[-1] != '\'') *--ptr = ' '; + } + } while (FindNextFileA(handle, &find_data)); + FindClose(handle); + + /* Format results nicely. */ + for (j = 0; missed[j] && missed[j] == ' '; ++j); + for (k = 0; (missed[k] = missed[j]) != 0; ++k) + for (++j; missed[j] && missed[j] == ' '; ++j); + + todo_wine_if (tests[i].todo) + ok(missed[0] == 0 && incorrect[0] == 0, + "FindFirstFile with '%s' found correctly %s, found incorrectly %s, and missed %s\n", + tests[i].pattern, + correct[0] ? correct+2 : "none", + incorrect[0] ? incorrect+2 : "none", + missed[0] ? missed : "none"); + } + + for (i = 0; i < sizeof(files) / sizeof(files[0]); ++i) + DeleteFileA(files[i]); + SetCurrentDirectoryA(".."); + RemoveDirectoryA("test-dir"); +} + static int test_Mapfile_createtemp(HANDLE *handle) { SetFileAttributesA(filename,FILE_ATTRIBUTE_NORMAL); @@ -4740,6 +4837,7 @@ START_TEST(file) test_MoveFileW(); test_FindFirstFileA(); test_FindNextFileA(); + test_FindFirstFile_wildcards(); test_FindFirstFileExA(FindExInfoStandard, 0, 0); test_FindFirstFileExA(FindExInfoStandard, 0, FIND_FIRST_EX_CASE_SENSITIVE); test_FindFirstFileExA(FindExInfoStandard, 0, FIND_FIRST_EX_LARGE_FETCH); -- 2.10.2