From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/ntdll/tests/rtl.c | 168 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+)
diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c index cbf564fa513..2f7a1d4cdc0 100644 --- a/dlls/ntdll/tests/rtl.c +++ b/dlls/ntdll/tests/rtl.c @@ -89,6 +89,7 @@ __ASM_STDCALL_FUNC( wrap_fastcall_func1, 8,
/* Function ptrs for ntdll calls */ static HMODULE hntdll = 0; +static void (WINAPI *pRtlDeleteNoSplay)(PRTL_SPLAY_LINKS, PRTL_SPLAY_LINKS *); static VOID (WINAPI *pRtlMoveMemory)(LPVOID,LPCVOID,SIZE_T); static VOID (WINAPI *pRtlFillMemory)(LPVOID,SIZE_T,BYTE); static VOID (WINAPI *pRtlFillMemoryUlong)(LPVOID,SIZE_T,ULONG); @@ -148,6 +149,7 @@ static void InitFunctionPtrs(void) hntdll = LoadLibraryA("ntdll.dll"); ok(hntdll != 0, "LoadLibrary failed\n"); if (hntdll) { + pRtlDeleteNoSplay = (void *)GetProcAddress(hntdll, "RtlDeleteNoSplay"); pRtlMoveMemory = (void *)GetProcAddress(hntdll, "RtlMoveMemory"); pRtlFillMemory = (void *)GetProcAddress(hntdll, "RtlFillMemory"); pRtlFillMemoryUlong = (void *)GetProcAddress(hntdll, "RtlFillMemoryUlong"); @@ -4499,6 +4501,171 @@ static void test_RtlSplay(void) } }
+static void test_RtlDeleteNoSplay(void) +{ + /* 3 + * / \ + * 1 5 + * / \ / \ + * 0 2 4 6 + */ + static const struct splay_index splay_indices[] = + { + {3, 1, 5}, + {1, 0, 2}, + {5, 4, 6}, + {0, -1, -1}, + {2, -1, -1}, + {4, -1, -1}, + {6, -1, -1}, + }; + /* 3 + * / \ + * 1 5 + * \ / \ + * 2 4 6 + */ + static const struct splay_index delete0[] = + { + {3, 1, 5}, + {1, -1, 2}, + {5, 4, 6}, + {2, -1, -1}, + {4, -1, -1}, + {6, -1, -1}, + }; + /* 3 + * / \ + * 0 5 + * \ / \ + * 2 4 6 + */ + static const struct splay_index delete1[] = + { + {3, 0, 5}, + {0, -1, 2}, + {5, 4, 6}, + {2, -1, -1}, + {4, -1, -1}, + {6, -1, -1}, + }; + /* 3 + * / \ + * 1 5 + * / / \ + * 0 4 6 + */ + static const struct splay_index delete2[] = + { + {3, 1, 5}, + {1, 0, -1}, + {5, 4, 6}, + {0, -1, -1}, + {4, -1, -1}, + {6, -1, -1}, + }; + /* 2 + * / \ + * 1 5 + * / / \ + * 0 4 6 + */ + static const struct splay_index delete3[] = + { + {2, 1, 5}, + {1, 0, -1}, + {5, 4, 6}, + {0, -1, -1}, + {4, -1, -1}, + {6, -1, -1}, + }; + /* 3 + * / \ + * 1 5 + * / \ \ + * 0 2 6 + */ + static const struct splay_index delete4[] = + { + {3, 1, 5}, + {1, 0, 2}, + {5, -1, 6}, + {0, -1, -1}, + {2, -1, -1}, + {6, -1, -1}, + }; + /* 3 + * / \ + * 1 4 + * / \ \ + * 0 2 6 + */ + static const struct splay_index delete5[] = + { + {3, 1, 4}, + {1, 0, 2}, + {4, -1, 6}, + {0, -1, -1}, + {2, -1, -1}, + {6, -1, -1}, + }; + /* 3 + * / \ + * 1 5 + * / \ / + * 0 2 4 + */ + static const struct splay_index delete6[] = + { + {3, 1, 5}, + {1, 0, 2}, + {5, 4, -1}, + {0, -1, -1}, + {2, -1, -1}, + {4, -1, -1}, + }; + RTL_SPLAY_LINKS links[7], *root; + static const struct + { + const struct splay_index *indices; + unsigned int index_count; + } + expected_indices[] = + { + {delete0, ARRAY_SIZE(delete0)}, + {delete1, ARRAY_SIZE(delete1)}, + {delete2, ARRAY_SIZE(delete2)}, + {delete3, ARRAY_SIZE(delete3)}, + {delete4, ARRAY_SIZE(delete4)}, + {delete5, ARRAY_SIZE(delete5)}, + {delete6, ARRAY_SIZE(delete6)}, + }; + unsigned int i; + + if (!pRtlDeleteNoSplay) + { + win_skip("RtlDeleteNoSplay is unavailable.\n"); + return; + } + + for (i = 0; i < ARRAY_SIZE(expected_indices); i++) + { + winetest_push_context("%d", i); + + init_splay_indices(links, ARRAY_SIZE(links), splay_indices, ARRAY_SIZE(splay_indices)); + root = &links[expected_indices[i].indices[0].parent_index]; + pRtlDeleteNoSplay(&links[i], &root); + expect_splay_indices(links, root, expected_indices[i].indices, expected_indices[i].index_count); + + winetest_pop_context(); + } + + /* Test that root should be NULL when the splay tree is empty */ + RtlInitializeSplayLinks(&links[0]); + pRtlDeleteNoSplay(&links[0], &root); + ok(root == NULL, "Got unexpected root.\n"); +} + START_TEST(rtl) { InitFunctionPtrs(); @@ -4556,4 +4723,5 @@ START_TEST(rtl) test_RtlRealPredecessor(); test_RtlRealSuccessor(); test_RtlSplay(); + test_RtlDeleteNoSplay(); }