RtlAtom tests further improved

György 'Nog' Jeney nog at sdf.lonestar.org
Sat Apr 5 10:14:19 CST 2003


Here's the latest version of my RtlAtom test, these should now succeed on
an nt system.  Thanks to Dmitry for running the initial test.

ChangeLog:
 * dlls/ntdll/tests/Makefile.in
 * dlls/ntdll/tests/atom.c
   Add tests for Rtl Atom fucntions.

nog.

-------------- next part --------------
--- ../cleanwine/dlls/ntdll/tests/Makefile.in	2003-03-23 20:02:50.000000000 +0200
+++ dlls/ntdll/tests/Makefile.in	2003-03-31 15:50:03.000000000 +0200
@@ -6,6 +6,7 @@
 IMPORTS   = ntdll
 
 CTESTS = \
+	atom.c \
 	error.c \
 	generated.c \
 	large_int.c \
--- /dev/null	1970-01-01 02:00:00.000000000 +0200
+++ dlls/ntdll/tests/atom.c	2003-04-05 17:21:58.000000000 +0200
@@ -0,0 +1,413 @@
+/* Unit test suite for Ntdll atom API functions
+ *
+ * Copyright 2003 Gyorgy 'Nog' Jeney
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * NOTES
+ * We use function pointers here as there is no import library for NTDLL on
+ * windows.
+ */
+
+#include <stdio.h>
+#include "windef.h"
+#include "winbase.h"
+#include "winnls.h"
+#include "wine/test.h"
+#include "wine/unicode.h"
+#include "winternl.h"
+
+/* Function pointers for ntdll calls */
+static HMODULE hntdll = 0;
+static NTSTATUS (WINAPI *pRtlCreateAtomTable)(ULONG,PRTL_ATOM_TABLE);
+static NTSTATUS (WINAPI *pRtlDestroyAtomTable)(RTL_ATOM_TABLE);
+static NTSTATUS (WINAPI *pRtlEmptyAtomTable)(RTL_ATOM_TABLE,BOOLEAN);
+static NTSTATUS (WINAPI *pRtlAddAtomToAtomTable)(RTL_ATOM_TABLE,PCWSTR,PRTL_ATOM);
+static NTSTATUS (WINAPI *pRtlDeleteAtomFromAtomTable)(RTL_ATOM_TABLE,RTL_ATOM);
+static NTSTATUS (WINAPI *pRtlLookupAtomInAtomTable)(RTL_ATOM_TABLE,PCWSTR,PRTL_ATOM);
+static NTSTATUS (WINAPI *pRtlPinAtomInAtomTable)(RTL_ATOM_TABLE,RTL_ATOM);
+static NTSTATUS (WINAPI *pRtlQueryAtomInAtomTable)(RTL_ATOM_TABLE,RTL_ATOM,PULONG,PULONG,PWSTR,PULONG);
+
+static WCHAR EmptyAtom[] = {0};
+static WCHAR testAtom1[] = {'H','e','l','l','o',' ','W','o','r','l','d',0};
+static WCHAR testAtom2[] = {'H','e','l','l','o',' ','W','o','r','l','d','2',0};
+static WCHAR testAtom3[] = {'H','e','l','l','o',' ','W','o','r','l','d','3',0};
+
+static WCHAR testAtom1Cap[] = {'H','E','L','L','O',' ','W','O','R','L','D',0};
+static WCHAR testAtom1Low[] = {'h','e','l','l','o',' ','w','o','r','l','d',0};
+
+static WCHAR testAtomInt[] = {'#','1','3','2',0};
+static WCHAR testAtomIntInv[] = {'#','2','3','4','z',0};
+
+static void InitFunctionPtr()
+{
+  hntdll = LoadLibraryA("ntdll.dll");
+  if(hntdll == 0) {
+    printf("Unable to load ntdll.dll\n");
+    return;
+  }
+
+  if(hntdll) {
+    pRtlCreateAtomTable = (void *)GetProcAddress(hntdll, "RtlCreateAtomTable");
+    pRtlDestroyAtomTable = (void *)GetProcAddress(hntdll, "RtlDestroyAtomTable");
+    pRtlEmptyAtomTable = (void *)GetProcAddress(hntdll, "RtlEmptyAtomTable");
+    pRtlAddAtomToAtomTable = (void *)GetProcAddress(hntdll, "RtlAddAtomToAtomTable");
+    pRtlDeleteAtomFromAtomTable = (void *)GetProcAddress(hntdll, "RtlDeleteAtomFromAtomTable");
+    pRtlLookupAtomInAtomTable = (void *)GetProcAddress(hntdll, "RtlLookupAtomInAtomTable");
+    pRtlPinAtomInAtomTable = (void *)GetProcAddress(hntdll, "RtlPinAtomInAtomTable");
+    pRtlQueryAtomInAtomTable = (void *)GetProcAddress(hntdll, "RtlQueryAtomInAtomTable");
+  }
+}
+
+static DWORD RtlAtomTestThread(LPVOID Table)
+{
+  RTL_ATOM_TABLE AtomTable = *(PRTL_ATOM_TABLE)Table;
+  RTL_ATOM Atom;
+  NTSTATUS res;
+  ULONG RefCount = 0, PinCount = 0, Len = 0;
+  WCHAR Name[64];
+
+  res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &Atom);
+  ok(!res, "Unable to find atom from another thread, retval: %lx\n", res);
+/*  printf("testAtom1 according to RtlLookupAtomInAtomTable is %x\n", Atom);*/
+
+  res = pRtlLookupAtomInAtomTable(AtomTable, testAtom2, &Atom);
+  ok(!res, "Unable to lookup pinned atom in table, retval: %lx\n", res);
+/*  printf("testAtom2 supposedly is %x\n", Atom);*/
+
+  res = pRtlQueryAtomInAtomTable(AtomTable, Atom, &RefCount, &PinCount, Name,
+                                 &Len);
+  ok(res == STATUS_BUFFER_TOO_SMALL, "We got wrong retval: %lx\n", res);
+
+  Len = 64;
+  res = pRtlQueryAtomInAtomTable(AtomTable, Atom, &RefCount, &PinCount, Name,
+                                 &Len);
+  ok(!res, "Failed with longenough buffer, retval: %lx\n", res);
+  ok(RefCount == 1, "Refcount was not 1 but %lx\n", RefCount);
+  ok(PinCount == 1, "Pincount was not 1 but %lx\n", PinCount);
+  ok(!strcmpW(Name, testAtom2), "We found wrong atom!!\n");
+  /* Len seems to become invalid ... */
+  /*printf("Len is %lx\n", Len);*/
+
+  Len = 64;
+  res = pRtlQueryAtomInAtomTable(AtomTable, Atom, NULL, NULL, Name, &Len);
+  ok(!res, "RtlQueryAtomInAtomTable with optional args invalid failed, retval: %lx\n", res);
+  ok(!strcmpW(Name, testAtom2), "Found Wrong atom!\n");
+  /* Len seems to become invalid ... */
+  /*printf("Len is %lx\n", Len);*/
+
+  res = pRtlPinAtomInAtomTable(AtomTable, Atom);
+  ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
+
+  return 0;
+}
+
+static void test_NtAtom()
+{
+  RTL_ATOM_TABLE AtomTable = NULL;
+  NTSTATUS res;
+  RTL_ATOM Atom1, Atom2, Atom3, testEAtom, testAtom;
+  HANDLE testThread;
+  ULONG RefCount = 0, PinCount = 0, Len = 0;
+  WCHAR Name[64];
+
+  winetest_start_todo("wine");
+
+  /* If we pass a non-null string to create atom table, then it thinks that we
+   * have passed it an already allocated atom table */
+  res = pRtlCreateAtomTable(0, &AtomTable);
+  ok(!res, "RtlCreateAtomTable should succeed with an atom table size of 0\n");
+
+  if(!res) {
+    res = pRtlDestroyAtomTable(AtomTable);
+    ok(!res, "We could create the atom table, but we couldn't destroy it! retval: %lx\n", res);
+  }
+
+  AtomTable = NULL;
+  res = pRtlCreateAtomTable(37, &AtomTable);
+  ok(!res, "We're unable to create an atom table with a valid table size retval: %lx\n", res);
+  if(!res) {
+    res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom1);
+    ok(!res, "We were unable to add a simple atom to the atom table, retval: %lx\n", res);
+
+    res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1Cap, &testAtom);
+    ok(!res, "We were unable to find capital version of the atom, retval: %lx\n", res);
+    ok(Atom1 == testAtom, "Found wrong atom in table when querying capital atom\n");
+
+    res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1Low, &testAtom);
+    ok(!res, "Unable to find lowercase version of the atom, retval: %lx\n", res);
+    ok(testAtom == Atom1, "Found wrong atom when querying lowercase atom\n");
+
+    res = pRtlAddAtomToAtomTable(AtomTable, EmptyAtom, &testEAtom);
+    ok(res == STATUS_OBJECT_NAME_INVALID, "Got wrong retval, retval: %lx\n", res);
+
+    res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
+    ok(!res, "Failed to find totally legitimate atom, retval: %lx\n", res);
+    ok(testAtom == Atom1, "Found wrong atom!\n");
+
+    res = pRtlAddAtomToAtomTable(AtomTable, testAtom2, &Atom2);
+    ok(!res, "Unable to add other legitimate atom to table, retval: %lx\n", res);
+
+    res = pRtlPinAtomInAtomTable(AtomTable, Atom2);
+    ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
+
+    testThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RtlAtomTestThread, &AtomTable, 0, NULL);
+    WaitForSingleObject(testThread, INFINITE);
+
+    Len = 64;
+    res = pRtlQueryAtomInAtomTable(AtomTable, Atom2, &RefCount, &PinCount, Name, &Len);
+    ok(!res, "Unable to query atom in atom table, retval: %lx\n", res);
+    ok(RefCount == 1, "RefCount is not 1 but %lx\n", RefCount);
+    ok(PinCount == 1, "PinCount is not 1 but %lx\n", PinCount);
+    ok(!strcmpW(Name, testAtom2), "We found wrong atom\n");
+    /* Len seems to become invalid */
+    /*printf("Len is %lx\n", Len);*/
+
+    res = pRtlEmptyAtomTable(AtomTable, FALSE);
+    ok(!res, "Unable to empty atom table, retval %lx\n", res);
+
+    res = pRtlQueryAtomInAtomTable(AtomTable, Atom2, &RefCount, &PinCount, Name,
+&Len);
+    ok(!res, "It seems RtlEmptyAtomTable deleted our pinned atom eaven though we asked it not to, retval: %lx\n", res);
+    ok(RefCount == 1, "RefCount is not 1 but %lx\n", RefCount);
+    ok(PinCount == 1, "PinCount is not 1 but %lx\n", PinCount);
+    ok(!strcmpW(Name, testAtom2), "We found wrong atom\n");
+    /* Len seems to become invalid */
+    /*printf("Len is %lx\n", Len);*/
+
+    res = pRtlLookupAtomInAtomTable(AtomTable, testAtom2, &testAtom);
+    ok(!res, "We can't find our pinned atom!! retval: %lx\n", res);
+    ok(testAtom == Atom2, "We found wrong atom!!!\n");
+
+    res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
+    ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "We found the atom in our table eaven though we asked RtlEmptyAtomTable to remove it, retval: %lx\n", res);
+
+    res = pRtlAddAtomToAtomTable(AtomTable, testAtom3, &Atom3);
+    ok(!res, "Unable to add atom to table, retval: %lx\n", res);
+
+    res = pRtlEmptyAtomTable(AtomTable, TRUE);
+    ok(!res, "Unable to empty atom table, retval: %lx\n", res);
+
+    res = pRtlLookupAtomInAtomTable(AtomTable, testAtom2, &testAtom);
+    ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "The pinned atom should be removed, retval: %lx\n", res);
+
+    res = pRtlLookupAtomInAtomTable(AtomTable, testAtom3, &testAtom);
+    ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "Non pinned atom should also be removed, retval: %lx\n", res);
+
+    res = pRtlDestroyAtomTable(AtomTable);
+    ok(!res, "Can't destroy atom table, retval: %lx\n", res);
+  }
+
+  AtomTable = NULL;
+  res = pRtlCreateAtomTable(37, &AtomTable);
+  ok(!res, "Unable to create atom table, retval: %lx\n", res);
+
+  if(!res) {
+    res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
+    ok(res == STATUS_OBJECT_NAME_NOT_FOUND, "Didn't get expected retval with querying an empty atom table, retval: %lx\n", res);
+
+    res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom1);
+    ok(!res, "Unable to add atom to atom table, retval %lx\n", res);
+
+    res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
+    ok(!res, "Can't find previously added atom in table, retval: %lx\n", res);
+    ok(testAtom == Atom1, "Found wrong atom! retval: %lx\n", res);
+
+    res = pRtlDeleteAtomFromAtomTable(AtomTable, Atom1);
+    ok(!res, "Unable to delete atom from table, retval: %lx\n", res);
+
+    res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
+    ok(res == STATUS_OBJECT_NAME_INVALID, "Able to find previously deleted atom in table, retval: %lx\n", res);
+
+    res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom1);
+    ok(!res, "Unable to add atom to atom table, retval: %lx\n", res);
+
+    res = pRtlPinAtomInAtomTable(AtomTable, Atom1);
+    ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
+
+    res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
+    ok(!res, "Unable to find atom in atom table, retval: %lx\n", res);
+    ok(testAtom == Atom1, "Wrong atom found\n");
+
+    res = pRtlDeleteAtomFromAtomTable(AtomTable, Atom1);
+    ok(res == STATUS_WAS_LOCKED, "Unable to delete atom from table, retval: %lx\n", res);
+
+    res = pRtlLookupAtomInAtomTable(AtomTable, testAtom1, &testAtom);
+    ok(res, "Able to find deleted atom in table\n");
+
+    res = pRtlDestroyAtomTable(AtomTable);
+    ok(!res, "Unable to destroy atom table\n");
+  }
+  winetest_end_todo("wine");
+}
+
+/* These tests *COULD* cause crashes!!!! */
+/*
+static void test_NtCrashAtom()
+{
+  NTSTATUS res;
+
+  winetest_start_todo("wine");
+
+  res = pRtlDestroyAtomTable(NULL);
+  printf("RtlDestroyAtomTable called with invalid atom table1 reted: %lx\n", res);
+
+  winetest_end_todo("wine");
+}
+*/
+
+/* Test Adding integer atoms to atom table */
+static void test_NtIntAtom()
+{
+  NTSTATUS res;
+  RTL_ATOM_TABLE AtomTable;
+  RTL_ATOM testAtom;
+  ULONG RefCount = 0, PinCount = 0;
+  int i;
+
+  winetest_start_todo("wine");
+
+  AtomTable = NULL;
+  res = pRtlCreateAtomTable(37, &AtomTable);
+  ok(!res, "Unable to create atom table, %lx\n", res);
+
+  if(!res) {
+    /* According to the kernel32 functions, integer atoms are only allowd from
+     * 0x0001 to 0xbfff and not 0xc000 to 0xffff, which is correct */
+    res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)0, &testAtom);
+    ok(res == STATUS_INVALID_PARAMETER, "Didn't get expected result from adding 0 int atom, retval: %lx\n", res);
+    for(i = 1; i <= 0xbfff; i++) {
+      res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)i, &testAtom);
+      ok(!res, "Unable to add valid integer atom %i, retval: %lx\n", i, res);
+    }
+
+    for(i = 1; i <= 0xbfff; i++) {
+      res = pRtlLookupAtomInAtomTable(AtomTable, (PWSTR)i, &testAtom);
+      ok(!res, "Unable to find int atom %i, retval: %lx\n", i, res);
+      if(!res) {
+        res = pRtlPinAtomInAtomTable(AtomTable, testAtom);
+        ok(!res, "Unable to pin int atom %i, retval: %lx\n", i, res);
+      }
+    }
+
+    for(i = 0xc000; i <= 0xffff; i++) {
+      res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)i, &testAtom);
+      ok(res, "Able to illeageal integer atom %i, retval: %lx\n", i, res);
+    }
+
+    res = pRtlDestroyAtomTable(AtomTable);
+    ok(!res, "Unable to destroy atom table, retval: %lx\n", res);
+  }
+
+  AtomTable = NULL;
+  res = pRtlCreateAtomTable(37, &AtomTable);
+  ok(!res, "Unable to create atom table, %lx\n", res);
+  if(!res) {
+    res = pRtlLookupAtomInAtomTable(AtomTable, (PWSTR)123, &testAtom);
+    ok(!res, "Unable to query atom in atom table, retval: %lx\n", res);
+
+    res = pRtlAddAtomToAtomTable(AtomTable, testAtomInt, &testAtom);
+    ok(!res, "Unable to add int atom to table, retval: %lx\n", res);
+
+    res = pRtlAddAtomToAtomTable(AtomTable, testAtomIntInv, &testAtom);
+    ok(!res, "Unable to add int atom to table, retval: %lx\n", res);
+
+    res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)123, &testAtom);
+    ok(!res, "Unable to add int atom to table, retval: %lx\n", res);
+
+    res = pRtlAddAtomToAtomTable(AtomTable, (PWSTR)123, &testAtom);
+    ok(!res, "Unable to re-add int atom to table, retval: %lx\n", res);
+
+    res = pRtlQueryAtomInAtomTable(AtomTable, testAtom, &PinCount, &RefCount, NULL, NULL);
+    ok(!res, "Unable to query atom in atom table, retval: %lx\n", res);
+    ok(PinCount == 1, "Expected pincount 1 but got %lx\n", PinCount);
+    ok(RefCount == 1, "Expected refcount 1 but got %lx\n", RefCount);
+
+    res = pRtlPinAtomInAtomTable(AtomTable, testAtom);
+    ok(!res, "Unable to pin int atom, retval: %lx\n", res);
+
+    res = pRtlPinAtomInAtomTable(AtomTable, testAtom);
+    ok(!res, "Unable to pin int atom, retval: %lx\n", res);
+
+    res = pRtlQueryAtomInAtomTable(AtomTable, testAtom, &PinCount, &RefCount, NULL, NULL);
+    ok(!res, "Unable to query atom in atom table, retval: %lx\n", res);
+    ok(PinCount == 1, "Expected pincount 1 but got %lx\n", PinCount);
+    ok(RefCount == 1, "Expected refcount 1 but got %lx\n", RefCount);
+
+    res = pRtlDestroyAtomTable(AtomTable);
+    ok(!res, "Unable to destroy atom table, retval: %lx\n", res);
+  }
+  winetest_end_todo("wine");
+}
+
+/* Tests to see how the pincount and refcount actually works */
+static void test_NtRefPinAtom()
+{
+  RTL_ATOM_TABLE AtomTable;
+  RTL_ATOM Atom;
+  ULONG PinCount = 0, RefCount = 0;
+  NTSTATUS res;
+
+  winetest_end_todo("wine");
+
+  AtomTable = NULL;
+  res = pRtlCreateAtomTable(37, &AtomTable);
+  ok(!res, "Unable to create atom table, %lx\n", res);
+
+  if(!res) {
+    res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom);
+    ok(!res, "Unable to add our atom to the atom table, retval: %lx\n", res);
+
+    res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom);
+    ok(!res, "Unable to add our atom to the atom table, retval: %lx\n", res);
+
+    res = pRtlAddAtomToAtomTable(AtomTable, testAtom1, &Atom);
+    ok(!res, "Unable to add our atom to the atom table, retval: %lx\n", res);
+
+    res = pRtlQueryAtomInAtomTable(AtomTable, Atom, &PinCount, &RefCount, NULL, NULL);
+    ok(!res, "Unable to query atom in atom table, retval: %lx\n", res);
+    ok(PinCount == 1, "Expected pincount 1 but got %lx\n", PinCount);
+    ok(RefCount == 1, "Expected refcount 3 but got %lx\n", RefCount); 
+
+    res = pRtlPinAtomInAtomTable(AtomTable, Atom);
+    ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
+
+    res = pRtlPinAtomInAtomTable(AtomTable, Atom);
+    ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
+
+    res = pRtlPinAtomInAtomTable(AtomTable, Atom);
+    ok(!res, "Unable to pin atom in atom table, retval: %lx\n", res);
+
+    res = pRtlQueryAtomInAtomTable(AtomTable, Atom, &PinCount, &RefCount, NULL, NULL);
+    ok(!res, "Unable to query atom in atom table, retval: %lx\n", res);
+    ok(PinCount == 1, "Expected pincount 3 but got %lx\n", PinCount);
+    ok(RefCount == 1, "Expected refcount 3 but got %lx\n", RefCount);
+
+    res = pRtlDestroyAtomTable(AtomTable);
+    ok(!res, "Unable to destroy atom table, retval: %lx\n", res);
+  }
+  winetest_end_todo("wine");
+}
+
+START_TEST(atom)
+{
+  InitFunctionPtr();
+  if(pRtlCreateAtomTable) {
+    test_NtAtom();
+    test_NtIntAtom();
+    test_NtRefPinAtom();
+/*    test_NtCrashAtom(); */
+  }
+}



More information about the wine-patches mailing list