[2/2] msvcrt/tests: qsort_s implementation and tests (try 3)

Vincas Miliūnas vincas.miliunas at gmail.com
Wed Nov 3 15:24:11 CDT 2010


qsort_s implementation and tests for bug #24925.

Moved the code from msvcr80 to msvcrt.
Added parameter validation for implementation and tests.

---
 dlls/msvcrt/tests/misc.c |  179 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 179 insertions(+), 0 deletions(-)

diff --git a/dlls/msvcrt/tests/misc.c b/dlls/msvcrt/tests/misc.c
index a4a1bd3..7ef2789 100644
--- a/dlls/msvcrt/tests/misc.c
+++ b/dlls/msvcrt/tests/misc.c
@@ -22,6 +22,44 @@
 #include <errno.h>
 #include "msvcrt.h"
 
+#define DEFINE_EXPECT(func) \
+    static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
+
+#define SET_EXPECT(func) \
+    expect_ ## func = TRUE
+
+#define CHECK_EXPECT2(func) \
+    do { \
+        ok(expect_ ##func, "unexpected call " #func  "\n"); \
+        called_ ## func = TRUE; \
+    }while(0)
+
+#define CHECK_EXPECT(func) \
+    do { \
+        CHECK_EXPECT2(func);     \
+        expect_ ## func = FALSE; \
+    }while(0)
+
+#define CHECK_CALLED(func) \
+    do { \
+        ok(called_ ## func, "expected " #func "\n"); \
+        expect_ ## func = called_ ## func = FALSE; \
+    }while(0)
+
+#define CHECK_NOT_CALLED(func) \
+    do { \
+        ok(!called_ ## func, "unexpected " #func "\n"); \
+        expect_ ## func = called_ ## func = FALSE; \
+    }while(0)
+
+#define CLEAR_CALLED(func) \
+    expect_ ## func = called_ ## func = FALSE
+
+DEFINE_EXPECT(invalid_parameter_handler);
+
+typedef int (CDECL *_QSORT_S_COMPARE_FN)(void *, const void *, const void *);
+
+static _invalid_parameter_handler (__cdecl *p_set_invalid_parameter_handler)(_invalid_parameter_handler);
 static int (__cdecl *prand_s)(unsigned int *);
 static int (__cdecl *pmemcpy_s)(void *, MSVCRT_size_t, void*, MSVCRT_size_t);
 static int (__cdecl *pI10_OUTPUT)(long double, int, int, void*);
@@ -30,11 +68,31 @@ static int (__cdecl *p_get_doserrno)(int *);
 static int (__cdecl *p_get_errno)(int *);
 static int (__cdecl *p_set_doserrno)(int);
 static int (__cdecl *p_set_errno)(int);
+static void (__cdecl *p_qsort_s)(void *, size_t, size_t, _QSORT_S_COMPARE_FN, void *);
+
+static int g_qsort_s_context_counter;
+
+static void __cdecl test_invalid_parameter_handler(const wchar_t *expression,
+        const wchar_t *function, const wchar_t *file,
+        unsigned line, uintptr_t arg)
+{
+    CHECK_EXPECT(invalid_parameter_handler);
+    ok(expression == NULL, "expression is not NULL\n");
+    ok(function == NULL, "function is not NULL\n");
+    ok(file == NULL, "file is not NULL\n");
+    ok(line == 0, "line = %u\n", line);
+    ok(arg == 0, "arg = %lx\n", (UINT_PTR)arg);
+}
 
 static void init(void)
 {
     HMODULE hmod = GetModuleHandleA("msvcrt.dll");
 
+    p_set_invalid_parameter_handler = (void *) GetProcAddress(hmod, "_set_invalid_parameter_handler");
+    if(p_set_invalid_parameter_handler)
+        ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL,
+                "Invalid parameter handler was already set\n");
+
     prand_s = (void *)GetProcAddress(hmod, "rand_s");
     pmemcpy_s = (void*)GetProcAddress(hmod, "memcpy_s");
     pI10_OUTPUT = (void*)GetProcAddress(hmod, "$I10_OUTPUT");
@@ -43,6 +101,7 @@ static void init(void)
     p_get_errno = (void *)GetProcAddress(hmod, "_get_errno");
     p_set_doserrno = (void *)GetProcAddress(hmod, "_set_doserrno");
     p_set_errno = (void *)GetProcAddress(hmod, "_set_errno");
+    p_qsort_s = (void *)GetProcAddress(hmod, "qsort_s");
 }
 
 static void test_rand_s(void)
@@ -351,6 +410,125 @@ static void test__set_errno(void)
     ok(errno == 0xdeadbeef, "Expected errno to be 0xdeadbeef, got %d\n", errno);
 }
 
+/* ########## */
+/* Borrowed from dlls/ntdll/tests/string.c */
+
+static __cdecl int intcomparefunc(void *context, const void *a, const void*b)
+{
+    ok (a != b, "must never get the same pointer\n");
+    ++*(int *) context;
+    return (*(int*)a) - (*(int*)b);
+}
+
+static __cdecl int charcomparefunc(void *context, const void *a, const void*b)
+{
+    ok (a != b, "must never get the same pointer\n");
+    ++*(int *) context;
+    return (*(char*)a) - (*(char*)b);
+}
+
+static __cdecl int strcomparefunc(void *context, const void *a, const void*b)
+{
+    ok (a != b, "must never get the same pointer\n");
+    ++*(int *) context;
+    return lstrcmpA(*(char**)a,*(char**)b);
+}
+
+static void test_qsort_s(void)
+{
+    int arr[5] = { 23, 42, 8, 4, 16 };
+    char carr[5] = { 42, 23, 4, 8, 16 };
+    const char *strarr[7] = {
+    "Hello",
+    "Wine",
+    "World",
+    "!",
+    "Hopefully",
+    "Sorted",
+    "."
+    };
+
+    SET_EXPECT(invalid_parameter_handler);
+    p_qsort_s(NULL, 0, 0, NULL, NULL);
+    CHECK_CALLED(invalid_parameter_handler);
+
+    SET_EXPECT(invalid_parameter_handler);
+    p_qsort_s(NULL, 0, 0, intcomparefunc, NULL);
+    CHECK_CALLED(invalid_parameter_handler);
+
+    SET_EXPECT(invalid_parameter_handler);
+    p_qsort_s(NULL, 0, sizeof(int), NULL, NULL);
+    CHECK_CALLED(invalid_parameter_handler);
+
+    SET_EXPECT(invalid_parameter_handler);
+    p_qsort_s(NULL, 1, sizeof(int), intcomparefunc, NULL);
+    CHECK_CALLED(invalid_parameter_handler);
+
+    g_qsort_s_context_counter = 0;
+    p_qsort_s(NULL, 0, sizeof(int), intcomparefunc, NULL);
+    ok(g_qsort_s_context_counter == 0, "callback shouldn't have been called\n");
+
+    g_qsort_s_context_counter = 0;
+    p_qsort_s((void*)arr, 0, sizeof(int), intcomparefunc, &g_qsort_s_context_counter);
+    ok(g_qsort_s_context_counter == 0, "callback shouldn't have been called\n");
+    ok(arr[0] == 23, "badly sorted, nmemb=0, arr[0] is %d\n", arr[0]);
+    ok(arr[1] == 42, "badly sorted, nmemb=0, arr[1] is %d\n", arr[1]);
+    ok(arr[2] == 8,  "badly sorted, nmemb=0, arr[2] is %d\n", arr[2]);
+    ok(arr[3] == 4,  "badly sorted, nmemb=0, arr[3] is %d\n", arr[3]);
+    ok(arr[4] == 16, "badly sorted, nmemb=0, arr[4] is %d\n", arr[4]);
+
+    g_qsort_s_context_counter = 0;
+    p_qsort_s((void*)arr, 1, sizeof(int), intcomparefunc, &g_qsort_s_context_counter);
+    ok(g_qsort_s_context_counter == 0, "callback shouldn't have been called\n");
+    ok(arr[0] == 23, "badly sorted, nmemb=1, arr[0] is %d\n", arr[0]);
+    ok(arr[1] == 42, "badly sorted, nmemb=1, arr[1] is %d\n", arr[1]);
+    ok(arr[2] == 8,  "badly sorted, nmemb=1, arr[2] is %d\n", arr[2]);
+    ok(arr[3] == 4,  "badly sorted, nmemb=1, arr[3] is %d\n", arr[3]);
+    ok(arr[4] == 16, "badly sorted, nmemb=1, arr[4] is %d\n", arr[4]);
+
+    SET_EXPECT(invalid_parameter_handler);
+    g_qsort_s_context_counter = 0;
+    p_qsort_s((void*)arr, 5, 0, intcomparefunc, &g_qsort_s_context_counter);
+    ok(g_qsort_s_context_counter == 0, "callback shouldn't have been called\n");
+    ok(arr[0] == 23, "badly sorted, size=0, arr[0] is %d\n", arr[0]);
+    ok(arr[1] == 42, "badly sorted, size=0, arr[1] is %d\n", arr[1]);
+    ok(arr[2] == 8,  "badly sorted, size=0, arr[2] is %d\n", arr[2]);
+    ok(arr[3] == 4,  "badly sorted, size=0, arr[3] is %d\n", arr[3]);
+    ok(arr[4] == 16, "badly sorted, size=0, arr[4] is %d\n", arr[4]);
+    CHECK_CALLED(invalid_parameter_handler);
+
+    g_qsort_s_context_counter = 0;
+    p_qsort_s((void*)arr, 5, sizeof(int), intcomparefunc, &g_qsort_s_context_counter);
+    ok(g_qsort_s_context_counter > 0, "callback wasn't called\n");
+    ok(arr[0] == 4,  "badly sorted, arr[0] is %d\n", arr[0]);
+    ok(arr[1] == 8,  "badly sorted, arr[1] is %d\n", arr[1]);
+    ok(arr[2] == 16, "badly sorted, arr[2] is %d\n", arr[2]);
+    ok(arr[3] == 23, "badly sorted, arr[3] is %d\n", arr[3]);
+    ok(arr[4] == 42, "badly sorted, arr[4] is %d\n", arr[4]);
+
+    g_qsort_s_context_counter = 0;
+    p_qsort_s((void*)carr, 5, sizeof(char), charcomparefunc, &g_qsort_s_context_counter);
+    ok(g_qsort_s_context_counter > 0, "callback wasn't called\n");
+    ok(carr[0] == 4,  "badly sorted, carr[0] is %d\n", carr[0]);
+    ok(carr[1] == 8,  "badly sorted, carr[1] is %d\n", carr[1]);
+    ok(carr[2] == 16, "badly sorted, carr[2] is %d\n", carr[2]);
+    ok(carr[3] == 23, "badly sorted, carr[3] is %d\n", carr[3]);
+    ok(carr[4] == 42, "badly sorted, carr[4] is %d\n", carr[4]);
+
+    g_qsort_s_context_counter = 0;
+    p_qsort_s((void*)strarr, 7, sizeof(char*), strcomparefunc, &g_qsort_s_context_counter);
+    ok(g_qsort_s_context_counter > 0, "callback wasn't called\n");
+    ok(!strcmp(strarr[0],"!"),  "badly sorted, strarr[0] is %s\n", strarr[0]);
+    ok(!strcmp(strarr[1],"."),  "badly sorted, strarr[1] is %s\n", strarr[1]);
+    ok(!strcmp(strarr[2],"Hello"),  "badly sorted, strarr[2] is %s\n", strarr[2]);
+    ok(!strcmp(strarr[3],"Hopefully"),  "badly sorted, strarr[3] is %s\n", strarr[3]);
+    ok(!strcmp(strarr[4],"Sorted"),  "badly sorted, strarr[4] is %s\n", strarr[4]);
+    ok(!strcmp(strarr[5],"Wine"),  "badly sorted, strarr[5] is %s\n", strarr[5]);
+    ok(!strcmp(strarr[6],"World"),  "badly sorted, strarr[6] is %s\n", strarr[6]);
+}
+
+/* ########## */
+
 START_TEST(misc)
 {
     init();
@@ -363,4 +541,5 @@ START_TEST(misc)
     test__get_errno();
     test__set_doserrno();
     test__set_errno();
+    test_qsort_s();
 }
-- 
1.7.2.3




More information about the wine-patches mailing list