Regression Test - kernel atom test

Dmitry Timoshkov dmitry at baikal.ru
Thu Oct 3 08:12:26 CDT 2002


"Steven Edwards" <Steven_Ed4153 at yahoo.com> wrote:

> >The question is: do we have to really worry about this? Is it Microsoft,
> >who have broken atom APIs, and not we? Can anybody run atom tests on some
> >other Windows platform other than Windows2000 SP3 (SP0, SP1, SP2 are fine)
> >and report here the result?
> >  
> >
> My counter parts and I in the ReactOS project have been wondering the 
> the same. We started with the goal of Windows NT 4.0 compatiblity in 
> mind but would like to adopt more 2k-isms like wdm and such so we are 
> changing our target. ATM ReactOS bombs very nicely on the kernel32_tests 
> so having a stable target for regressions that both WINE and ReactOS can 
> share would be a good thing.

Okay, I went ahead and tried to figure out what happens.

As a result, now I have fixed atom conformance test along with fixes
to make Wine behave exactly as Windows 2000.

Conformance test was run under Win98,Me and Windows 2000 and has been
fixed to produce 0 failures under win2000. Behaviour of some functions
is very different between 98/Me and 2000. Win98 and WinMe behave equally.

I'm not sending it to wine-patches because I'm not sure that we need all
that tests for 98/Me and 2000 differences. In any case we will not be able
to emulate behaviour of all Windows platforms.

-- 
Dmitry.
-------------- next part --------------
diff -u cvs/hq/wine/dlls/kernel/tests/atom.c wine/dlls/kernel/tests/atom.c
--- cvs/hq/wine/dlls/kernel/tests/atom.c	Mon Sep  9 13:26:55 2002
+++ wine/dlls/kernel/tests/atom.c	Thu Oct  3 20:38:14 2002
@@ -28,6 +28,8 @@
 static const WCHAR FOOBARW[] = {'F','O','O','B','A','R',0};
 static const WCHAR _foobarW[] = {'_','f','o','o','b','a','r',0};
 
+static BOOL unicode_OS;
+
 static void test_add_atom(void)
 {
     ATOM atom, w_atom;
@@ -47,41 +49,67 @@
      * find the first one, not add a new one */
     SetLastError( 0xdeadbeef );
     w_atom = GlobalAddAtomW( foobarW );
-    ok( w_atom == atom, "Unicode atom does not match ASCII" );
-    ok( GetLastError() == 0xdeadbeef, "GlobalAddAtomW set last error" );
+    if (w_atom && GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+        unicode_OS = TRUE;
+
+    trace("Unicode APIs are %ssupported\n", unicode_OS ? "" : "NOT ");
+
+    if (unicode_OS)
+    {
+        ok( w_atom == atom, "Unicode atom does not match ASCII" );
+        ok( GetLastError() == 0xdeadbeef, "GlobalAddAtomW set last error" );
+    }
 
     /* Verify that it can be found (or not) appropriately via unicode name */
-    ok( GlobalFindAtomW( foobarW ) == atom, "could not find atom foobar" );
-    ok( GlobalFindAtomW( FOOBARW ) == atom, "could not find atom FOOBAR" );
-    ok( !GlobalFindAtomW( _foobarW ), "found _foobar" );
+    if (unicode_OS)
+    {
+        ok( GlobalFindAtomW( foobarW ) == atom, "could not find atom foobar" );
+        ok( GlobalFindAtomW( FOOBARW ) == atom, "could not find atom FOOBAR" );
+        ok( !GlobalFindAtomW( _foobarW ), "found _foobar" );
+    }
 
     /* Test integer atoms
-     * (0x0000 .. 0xbfff) should be valid;
+     * (0x0001 .. 0xbfff) should be valid;
      * (0xc000 .. 0xffff) should be invalid */
-    todo_wine
+
+    SetLastError( 0xdeadbeef );
+    ok( GlobalAddAtomA(0) == 0 && GetLastError() == 0xdeadbeef, "succeeded to add atom 0" );
+    if (unicode_OS)
     {
         SetLastError( 0xdeadbeef );
-        ok( GlobalAddAtomA(0) == 0 && GetLastError() == 0xdeadbeef, "failed to add atom 0" );
-        SetLastError( 0xdeadbeef );
-        ok( GlobalAddAtomW(0) == 0 && GetLastError() == 0xdeadbeef, "failed to add atom 0" );
+        ok( GlobalAddAtomW(0) == 0 && GetLastError() == 0xdeadbeef, "succeeded to add atom 0" );
     }
+
     SetLastError( 0xdeadbeef );
     for (i = 1; i <= 0xbfff; i++)
     {
         SetLastError( 0xdeadbeef );
         ok( GlobalAddAtomA((LPCSTR)i) == i && GetLastError() == 0xdeadbeef,
             "failed to add atom %x", i );
-        ok( GlobalAddAtomW((LPCWSTR)i) == i && GetLastError() == 0xdeadbeef,
-            "failed to add atom %x", i );
+        if (unicode_OS)
+        {
+            SetLastError( 0xdeadbeef );
+            ok( GlobalAddAtomW((LPCWSTR)i) == i && GetLastError() == 0xdeadbeef,
+                "failed to add atom %x", i );
+        }
     }
+
     for (i = 0xc000; i <= 0xffff; i++)
     {
         SetLastError( 0xdeadbeef );
-        ok( !GlobalAddAtomA((LPCSTR)i) && (GetLastError() == ERROR_INVALID_PARAMETER),
-            "succeeded adding %x", i );
-        SetLastError( 0xdeadbeef );
-        ok( !GlobalAddAtomW((LPCWSTR)i) && (GetLastError() == ERROR_INVALID_PARAMETER),
-            "succeeded adding %x", i );
+        if (unicode_OS)
+            ok( !GlobalAddAtomA((LPCSTR)i) && GetLastError() == ERROR_INVALID_PARAMETER,
+                "succeeded adding %x", i );
+        else
+            ok( !GlobalAddAtomA((LPCSTR)i) && GetLastError() == 0xdeadbeef,
+                "succeeded adding %x", i );
+
+        if (unicode_OS)
+        {
+            SetLastError( 0xdeadbeef );
+            ok( !GlobalAddAtomW((LPCWSTR)i) && (GetLastError() == ERROR_INVALID_PARAMETER),
+                "succeeded adding %x", i );
+        }
     }
 }
 
@@ -90,7 +118,7 @@
     char buf[10];
     WCHAR bufW[10];
     int i, len;
-    static const char resultW[] = {'f','o','o','b','a','r',0,'.','.','.'};
+    static const WCHAR resultW[] = {'f','o','o','b','a','r',0,'.','.','.'};
 
     ATOM atom = GlobalAddAtomA( "foobar" );
 
@@ -99,52 +127,118 @@
     len = GlobalGetAtomNameA( atom, buf, 10 );
     ok( len == strlen("foobar"), "bad length %d", len );
     ok( !memcmp( buf, "foobar\0...", 10 ), "bad buffer contents" );
-    ok( !GlobalGetAtomNameA( atom, buf, 3 ), "GlobalGetAtomNameA succeeded on short buffer" );
+
+    memset( buf, '.', sizeof(buf) );
+    SetLastError( 0xdeadbeef );
+    if (unicode_OS)
+    {
+        ok( !GlobalGetAtomNameA( atom, buf, 3 ) && GetLastError() == ERROR_MORE_DATA,
+            "GlobalGetAtomNameA succeeded on short buffer" );
+        ok( !memcmp( buf, "fo\0.......", 10 ), "bad buffer contents: %.10s", buf );
+    }
+    else
+    {
+        len = GlobalGetAtomNameA( atom, buf, 3 );
+        ok( len && GetLastError() == 0xdeadbeef, "GlobalGetAtomNameA failed on short buffer" );
+        ok( len == 2, "bad length %d", len );
+        ok( !memcmp( buf, "fo\0.......", 10 ), "bad buffer contents: %.10s", buf );
+    }
 
     /* Repeat, unicode-style */
-    for (i = 0; i < 10; i++) bufW[i] = '.';
-    len = GlobalGetAtomNameW( atom, bufW, 10 );
-    ok( len == lstrlenW(foobarW), "bad length %d", len );
-    todo_wine
+    if (unicode_OS)
     {
+        static const WCHAR sampleW[10] = {'f','o','o','.','.','.','.','.','.','.'};
+
+        for (i = 0; i < 10; i++) bufW[i] = '.';
+        SetLastError( 0xdeadbeef );
+        len = GlobalGetAtomNameW( atom, bufW, 10 );
+        ok( len && GetLastError() == 0xdeadbeef, "GlobalGetAtomNameW failed" );
+        ok( len == lstrlenW(foobarW), "bad length %d", len );
         ok( !memcmp( bufW, resultW, 10*sizeof(WCHAR) ), "bad buffer contents" );
+
+        for (i = 0; i < 10; i++) bufW[i] = '.';
+        SetLastError( 0xdeadbeef );
+        len = GlobalGetAtomNameW( atom, bufW, 3 );
+        ok( len && GetLastError() == 0xdeadbeef, "GlobalGetAtomNameW failed on short buffer" );
+        ok( len == 3, "bad length %d", len );
+        ok( !memcmp( bufW, sampleW, 10*sizeof(WCHAR) ), "bad buffer contents" );
     }
-    ok( !GlobalGetAtomNameW( atom, bufW, 3 ), "GlobalGetAtomNameW succeeded on short buffer" );
 
     /* Check error code returns */
+    memset(buf, '.', 10);
     SetLastError( 0xdeadbeef );
-    ok( !GlobalGetAtomNameA( atom, buf,  0 ) && GetLastError() == ERROR_MORE_DATA, "succeded" );
-    SetLastError( 0xdeadbeef );
-    ok( !GlobalGetAtomNameA( atom, buf, -1 ) && GetLastError() == ERROR_MORE_DATA, "succeded" );
-    SetLastError( 0xdeadbeef );
-    ok( !GlobalGetAtomNameW( atom, bufW,  0 ) && GetLastError() == ERROR_MORE_DATA, "succeded" );
+    if (unicode_OS)
+    {
+        ok( !GlobalGetAtomNameA( atom, buf,  0 ) && GetLastError() == ERROR_MORE_DATA, "succeded" );
+        ok( !memcmp( buf, "..........", 10 ), "should not touch buffer" );
+    }
+    else
+    {
+        ok( !GlobalGetAtomNameA( atom, buf,  0 ) && GetLastError() == 0xdeadbeef, "succeded" );
+        ok( !memcmp( buf, "..........", 10 ), "should not touch buffer: %.10s", buf );
+    }
+
+    memset(buf, '.', 10);
     SetLastError( 0xdeadbeef );
-    ok( !GlobalGetAtomNameW( atom, bufW, -1 ) && GetLastError() == ERROR_MORE_DATA, "succeded" );
+    if (unicode_OS)
+    {
+        len = GlobalGetAtomNameA( atom, buf, -1 );
+        ok( len && GetLastError() == 0xdeadbeef, "failed" );
+        ok( len == strlen("foobar"), "bad length %d", len );
+        ok( !memcmp( buf, "foobar\0...", 10 ), "bad buffer contents %.10s", buf );
+    }
+    else
+    {
+        len = GlobalGetAtomNameA( atom, buf, -1 );
+        ok( !len && GetLastError() == ERROR_INVALID_PARAMETER, "succeded: len %d, error %ld", len, GetLastError() );
+        ok( !memcmp( buf, "..........", 10 ), "should not touch buffer: %.10s", buf );
+    }
+
+    if (unicode_OS)
+    {
+        static const WCHAR sampleW[10] = {'.','.','.','.','.','.','.','.','.','.'};
+
+        for (i = 0; i < 10; i++) bufW[i] = '.';
+        SetLastError( 0xdeadbeef );
+        ok( !GlobalGetAtomNameW( atom, bufW, 0 ) && GetLastError() == ERROR_MORE_DATA, "succeded" );
+        ok( !memcmp( bufW, sampleW, 10 * sizeof(WCHAR) ), "should not touch buffer" );
+
+        for (i = 0; i < 10; i++) bufW[i] = '.';
+        SetLastError( 0xdeadbeef );
+        ok( !GlobalGetAtomNameW( atom, bufW, -1 ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "succeded" );
+        ok( !memcmp( bufW, sampleW, 10 * sizeof(WCHAR) ), "should not touch buffer" );
+    }
 
     /* Test integer atoms */
     for (i = 0; i <= 0xbfff; i++)
     {
         memset( buf, 'a', 10 );
-        len = GlobalGetAtomNameA( i, buf, 10 );
+        len = GlobalGetAtomNameA( (ATOM)i, buf, 10 );
         if (i)
         {
             char res[20];
-            ok( (len > 1) && (len < 7), "bad length %d", len );
+            ok( (len > 1) && (len < 7), "%04x: bad length %d", i, len );
             sprintf( res, "#%d", i );
             memset( res + strlen(res) + 1, 'a', 10 );
-            ok( !memcmp( res, buf, 10 ), "bad buffer contents %s", buf );
+            ok( !memcmp( res, buf, 10 ), "%04x: bad buffer contents %.10s", i, buf );
         }
-        else todo_wine
+        else
         {
-            char res[20];
-            ok( (len > 1) && (len < 7), "bad length %d", len );
-            sprintf( res, "#%d", i );
-            memset( res + strlen(res) + 1, 'a', 10 );
-            ok( !memcmp( res, buf, 10 ), "bad buffer contents %s", buf );
+            char res[10];
+            ok( !len, "bad length %d", len );
+            memset( res, 'a', 10 );
+            if (unicode_OS)
+                ok( !memcmp( res, buf, 10 ), "%04x: bad buffer contents %.10s", i, buf );
+            else
+            {
+                res[0] = 0;
+                ok( !memcmp( res, buf, 10 ), "%04x: bad buffer contents %.10s", i, buf );
+            }
         }
     }
 }
 
+/* Note: GlobalDeleteAtom behaviour is completely broken under 9x/Me */
 static void test_delete_atom(void)
 {
     ATOM atom;
@@ -152,18 +246,34 @@
 
     /* First make sure it doesn't exist */
     atom = GlobalAddAtomA( "foobar" );
-    while (!GlobalDeleteAtom( atom ));
+
+    i = 100;
+    do
+    {
+        SetLastError(ERROR_SUCCESS);
+        ok( !GlobalDeleteAtom( atom ), "expected to always return 0" );
+        if (!--i)
+        {
+            ok( 0, "infinite loop" );
+            break;
+        }
+    } while (GetLastError() == ERROR_SUCCESS);
 
     /* Now add it a number of times */
     for (i = 0; i < 10; i++) atom = GlobalAddAtomA( "foobar" );
 
     /* Make sure it's here */
     ok( GlobalFindAtomA( "foobar" ), "foobar not found" );
-    ok( GlobalFindAtomW( foobarW ), "foobarW not found" );
+    if (unicode_OS)
+        ok( GlobalFindAtomW( foobarW ), "foobarW not found" );
 
     /* That many deletions should succeed */
     for (i = 0; i < 10; i++)
-        ok( !GlobalDeleteAtom( atom ), "delete atom failed" );
+    {
+        SetLastError(ERROR_SUCCESS);
+        ok( !GlobalDeleteAtom( atom ) && GetLastError() == ERROR_SUCCESS,
+            "delete atom failed" );
+    }
 
     /* It should be gone now */
     ok( !GlobalFindAtomA( "foobar" ), "still found it" );
@@ -171,8 +281,8 @@
 
     /* So this one should fail */
     SetLastError( 0xdeadbeef );
-    ok( GlobalDeleteAtom( atom ) == atom && GetLastError() == ERROR_INVALID_HANDLE,
-        "delete failed" );
+    ok( !GlobalDeleteAtom( atom ) && GetLastError() == ERROR_INVALID_HANDLE,
+        "delete atom succeded" );
 }
 
 static void test_error_handling(void)
@@ -189,20 +299,30 @@
     buffer[255] = 'a';
     buffer[256] = 0;
     SetLastError( 0xdeadbeef );
-    ok( !GlobalAddAtomA(buffer) && GetLastError() == ERROR_INVALID_PARAMETER, "add succeded" );
-    SetLastError( 0xdeadbeef );
-    ok( !GlobalFindAtomA(buffer) && GetLastError() == ERROR_INVALID_PARAMETER, "find succeded" );
+    if (unicode_OS)
+        ok( !GlobalAddAtomA(buffer) && GetLastError() == ERROR_INVALID_PARAMETER, "add succeded" );
+    else
+        ok( !GlobalAddAtomA(buffer) && GetLastError() == 0xdeadbeef, "add succeded" );
+    SetLastError( 0xdeadbeef );
+    if (unicode_OS)
+        ok( !GlobalFindAtomA(buffer) && GetLastError() == ERROR_INVALID_PARAMETER, "find succeded" );
+    else
+        ok( !GlobalFindAtomA(buffer) && GetLastError() == 0xdeadbeef, "find succeded" );
 
-    for (i = 0; i < 255; i++) bufferW[i] = 'b';
-    bufferW[255] = 0;
-    ok( atom = GlobalAddAtomW( bufferW ), "add failed" );
-    ok( !GlobalDeleteAtom( atom ), "delete failed" );
-    bufferW[255] = 'b';
-    bufferW[256] = 0;
-    SetLastError( 0xdeadbeef );
-    ok( !GlobalAddAtomW(bufferW) && GetLastError() == ERROR_INVALID_PARAMETER, "add succeded" );
-    SetLastError( 0xdeadbeef );
-    ok( !GlobalFindAtomW(bufferW) && GetLastError() == ERROR_INVALID_PARAMETER, "find succeded" );
+    if (unicode_OS)
+    {
+        for (i = 0; i < 255; i++) bufferW[i] = 'b';
+        bufferW[255] = 0;
+        ok( atom = GlobalAddAtomW( bufferW ), "add failed" );
+        SetLastError(ERROR_SUCCESS);
+        ok( !GlobalDeleteAtom( atom ) && GetLastError() == ERROR_SUCCESS, "delete failed" );
+        bufferW[255] = 'b';
+        bufferW[256] = 0;
+        SetLastError( 0xdeadbeef );
+        ok( !GlobalAddAtomW(bufferW) && GetLastError() == ERROR_INVALID_PARAMETER, "add succeded" );
+        SetLastError( 0xdeadbeef );
+        ok( !GlobalFindAtomW(bufferW) && GetLastError() == ERROR_INVALID_PARAMETER, "find succeded" );
+    }
 }
 
 START_TEST(atom)
diff -u cvs/hq/wine/memory/atom.c wine/memory/atom.c
--- cvs/hq/wine/memory/atom.c	Sun Sep  1 16:39:24 2002
+++ wine/memory/atom.c	Thu Oct  3 17:33:49 2002
@@ -131,7 +131,7 @@
         }
         if (*atomstr) return FALSE;
     }
-    if (!atom || (atom >= MAXINTATOM))
+    if (atom >= MAXINTATOM)
     {
         SetLastError( ERROR_INVALID_PARAMETER );
         atom = 0;
@@ -158,7 +158,7 @@
         }
         if (*atomstr) return FALSE;
     }
-    if (!atom || (atom >= MAXINTATOM))
+    if (atom >= MAXINTATOM)
     {
         SetLastError( ERROR_INVALID_PARAMETER );
         atom = 0;
@@ -502,18 +502,19 @@
 static ATOM ATOM_DeleteAtom( ATOM atom,  BOOL local)
 {
     TRACE( "(%s) %x\n", local ? "local" : "global", atom );
-    if (atom < MAXINTATOM) atom = 0;
-    else
+    if (atom >= MAXINTATOM)
     {
+        int ret;
         SERVER_START_REQ( delete_atom )
         {
             req->atom = atom;
             req->local = local;
-            if (!wine_server_call_err( req )) atom = 0;
+            if ((ret = wine_server_call_err( req )))
+                SetLastError( RtlNtStatusToDosError(ret) );
         }
         SERVER_END_REQ;
     }
-    return atom;
+    return 0;
 }
 
 
@@ -649,7 +650,7 @@
 {
     INT len;
 
-    if (count <= 0)
+    if (!count)
     {
         SetLastError( ERROR_MORE_DATA );
         return 0;
@@ -677,6 +678,7 @@
             wine_server_set_reply( req, full_name, sizeof(full_name) );
             if (!wine_server_call_err( req ))
             {
+                if (count < 0) count = 0x7fffffff;
                 len = WideCharToMultiByte( CP_ACP, 0, full_name,
                                            wine_server_reply_size(reply) / sizeof(WCHAR),
                                            buffer, count - 1, NULL, NULL );
@@ -737,7 +739,7 @@
 {
     INT len;
 
-    if (count <= 0)
+    if (!count)
     {
         SetLastError( ERROR_MORE_DATA );
         return 0;
@@ -767,18 +769,28 @@
             if (!wine_server_call_err( req ))
             {
                 len = wine_server_reply_size(reply) / sizeof(WCHAR);
-                if (count > len) count = len + 1;
-                memcpy( buffer, full_name, (count-1) * sizeof(WCHAR) );
-                buffer[count-1] = 0;
+                if (count > 0)
+                {
+                    if (count > len)
+                    {
+                        memcpy( buffer, full_name, len * sizeof(WCHAR) );
+                        buffer[len] = 0;
+                    }
+                    else
+                    {
+                        len = count;
+                        memcpy( buffer, full_name, len * sizeof(WCHAR) );
+                    }
+                }
+                else
+                {
+                    len = 0;
+                    SetLastError(ERROR_INSUFFICIENT_BUFFER);
+                }
             }
         }
         SERVER_END_REQ;
         if (!len) return 0;
-    }
-    if (count <= len)
-    {
-        SetLastError( ERROR_MORE_DATA );
-        return 0;
     }
     TRACE( "(%s) %x -> %s\n", local ? "local" : "global", atom, debugstr_w(buffer) );
     return len;


More information about the wine-devel mailing list