riched20: extend EM_FINDTEXT conformance tests and fix 2 problems they expose (take 2)

tkho at ucla.edu tkho at ucla.edu
Tue Feb 14 14:00:35 CST 2006


Hi,

This patch adds numerous tests to the riched20 conformance test for EM_FINDTEXT
and fixes two problems they expose.

2006-02-14 Thomas Kho <tkho at ucla.edu>

	* dlls/riched20/editor.c:
	riched20: Fixed a null-pointer dereference (by Lei Zhang)
	Corrected find behavior for null-results

	* configure.ac, dlls/riched20/Makefile.in,
	  dlls/riched20/tests/Makefile.in, dlls/riched20/tests/editor.c:
	riched20: expanded tests for EM_FINDTEXT and EM_FINDTEXTEX messages

Without the fix to dlls/riched20/editor.c, the following test case to search
for the empty string crashes on Wine:
+  /* Find nothing */
+  {5, 10, "", FR_DOWN, -1, 0},

 editor.c       |   17 +++-
 tests/editor.c |  227 +++++++++++++++++++++++++++++++--------------------------
 2 files changed, 139 insertions(+), 105 deletions(-)

Signed-off-by: Thomas Kho <tkho at ucla.edu>
Index: dlls/riched20/editor.c
===================================================================
RCS file: /home/wine/wine/dlls/riched20/editor.c,v
retrieving revision 1.88
diff -u -r1.88 editor.c
--- dlls/riched20/editor.c	14 Feb 2006 17:08:34 -0000	1.88
+++ dlls/riched20/editor.c	14 Feb 2006 19:29:28 -0000
@@ -789,11 +789,11 @@
     nMax = max(chrg->cpMin, chrg->cpMax);
   }
   
-  if (!nLen)
+  if (!nLen || nMin < 0 || nMax < 0)
   {
     if (chrgText)
-      chrgText->cpMin = chrgText->cpMax = ((flags & FR_DOWN) ? nMin : nMax);
-    return chrgText->cpMin;
+      chrgText->cpMin = chrgText->cpMax = -1;
+    return -1;
   }
  
   if (flags & FR_DOWN) /* Forward search */
@@ -801,7 +801,11 @@
     nStart = nMin;
     item = ME_FindItemAtOffset(editor, diRun, nStart, &nStart);
     if (!item)
+    {
+      if (chrgText)
+        chrgText->cpMin = chrgText->cpMax = -1;
       return -1;
+    }
 
     para = ME_GetParagraph(item);
     while (item
@@ -845,8 +849,11 @@
   {
     nEnd = nMax;
     item = ME_FindItemAtOffset(editor, diRun, nEnd, &nEnd);
-    if (!item)
+    if (!item) {
+      if (chrgText)
+        chrgText->cpMin = chrgText->cpMax = -1;
       return -1;
+    }
     
     para = ME_GetParagraph(item);
     
@@ -888,6 +895,8 @@
     }
   }
   TRACE("not found\n");
+  if (chrgText)
+    chrgText->cpMin = chrgText->cpMax = -1;
   return -1;
 }
 
Index: dlls/riched20/tests/editor.c
===================================================================
RCS file: /home/wine/wine/dlls/riched20/tests/editor.c,v
retrieving revision 1.1
diff -u -r1.1 editor.c
--- dlls/riched20/tests/editor.c	11 Feb 2006 19:40:52 -0000	1.1
+++ dlls/riched20/tests/editor.c	14 Feb 2006 19:29:28 -0000
@@ -24,19 +24,11 @@
 #include <time.h>
 
 static HMODULE hmoduleRichEdit;
-static const char haystack[] = "Think of Wine as a compatibility layer for "
-  "running Windows programs. Wine does not require Microsoft Windows, as it "
-  "is a completely free alternative implementation of the Windows API "
-  "consisting of 100% non-Microsoft code, however Wine can optionally use "
-  "native Windows DLLs if they are available. Wine provides both a "
-  "development toolkit for porting Windows source code to Unix as well as a "
-  "program loader, allowing many unmodified Windows programs to run on "
-  "x86-based Unixes, including Linux, FreeBSD, and Solaris.";
 
 static HWND new_window(LPCTSTR lpClassName, DWORD dwStyle, HWND parent) {
   HWND hwnd;
   hwnd = CreateWindow(lpClassName, NULL, dwStyle|WS_POPUP|WS_HSCROLL|WS_VSCROLL
-                      |WS_VISIBLE, 0, 0, 200, 50, parent, NULL,
+                      |WS_VISIBLE, 0, 0, 200, 60, parent, NULL,
                       hmoduleRichEdit, NULL);
   ok(hwnd != NULL, "class: %s, error: %d\n", lpClassName, (int) GetLastError());
   return hwnd;
@@ -46,113 +38,147 @@
   return new_window(RICHEDIT_CLASS, ES_MULTILINE, parent);
 }
 
-static void check_EM_FINDTEXT(HWND hwnd, int start, int end, char needle[],
-                              int flags, int expected_start) {
+static const char haystack[] = "WINEWine wineWine wine WineWine";
+                             /* ^0        ^10       ^20       ^30 */
+
+struct find_s {
+  int start;
+  int end;
+  char *needle;
+  int flags;
+  int expected_loc;
+  int _todo_wine;
+};
+
+struct find_s find_tests[] = {
+  /* Find in empty text */
+  {0, -1, "foo", FR_DOWN, -1, 0},
+  {0, -1, "foo", 0, -1, 0},
+  {0, -1, "", FR_DOWN, -1, 0},
+  {20, 5, "foo", FR_DOWN, -1, 0},
+  {5, 20, "foo", FR_DOWN, -1, 0}
+};
+
+struct find_s find_tests2[] = {
+  /* No-result find */
+  {0, -1, "foo", FR_DOWN | FR_MATCHCASE, -1, 0},
+  {5, 20, "WINE", FR_DOWN | FR_MATCHCASE, -1, 0},
+
+  /* Subsequent finds */
+  {0, -1, "Wine", FR_DOWN | FR_MATCHCASE, 4, 0},
+  {5, 31, "Wine", FR_DOWN | FR_MATCHCASE, 13, 0},
+  {14, 31, "Wine", FR_DOWN | FR_MATCHCASE, 23, 0},
+  {24, 31, "Wine", FR_DOWN | FR_MATCHCASE, 27, 0},
+
+  /* Find backwards */
+  {19, 20, "Wine", FR_MATCHCASE, 13, 1},
+  {10, 20, "Wine", FR_MATCHCASE, 4, 1},
+  {20, 10, "Wine", FR_MATCHCASE, 13, 0},
+
+  /* Case-insensitive */
+  {1, 31, "wInE", FR_DOWN, 4, 1},
+  {1, 31, "Wine", FR_DOWN, 4, 0},
+
+  /* High-to-low ranges */
+  {20, 5, "Wine", FR_DOWN, -1, 1},
+  {2, 1, "Wine", FR_DOWN, -1, 0},
+  {30, 29, "Wine", FR_DOWN, -1, 0},
+  {20, 5, "Wine", 0, 13, 0},
+
+  /* Find nothing */
+  {5, 10, "", FR_DOWN, -1, 0},
+  {10, 5, "", FR_DOWN, -1, 0},
+  {0, -1, "", FR_DOWN, -1, 0},
+  {10, 5, "", 0, -1, 0},
+
+  /* Whole-word search */
+  {0, -1, "wine", FR_DOWN | FR_WHOLEWORD, 18, 1},
+  {0, -1, "win", FR_DOWN | FR_WHOLEWORD, -1, 1},
+  
+  /* Bad ranges */
+  {-20, 20, "Wine", FR_DOWN, -1, 0},
+  {-20, 20, "Wine", FR_DOWN, -1, 0},
+  {-15, -20, "Wine", FR_DOWN, -1, 0},
+  {1<<12, 1<<13, "Wine", FR_DOWN, -1, 0},
+
+  /* Check the case noted in bug 4479 where matches at end aren't recognized */
+  {23, 31, "Wine", FR_DOWN | FR_MATCHCASE, 23, 0},
+  {27, 31, "Wine", FR_DOWN | FR_MATCHCASE, 27, 0},
+  {27, 32, "Wine", FR_DOWN | FR_MATCHCASE, 27, 0},
+  {13, 31, "WineWine", FR_DOWN | FR_MATCHCASE, 23, 0},
+  {13, 32, "WineWine", FR_DOWN | FR_MATCHCASE, 23, 0},
+
+  /* The backwards case of bug 4479; bounds look right
+   * Fails because backward find is wrong */
+  {19, 20, "WINE", FR_MATCHCASE, 0, 1},
+  {0, 20, "WINE", FR_MATCHCASE, -1, 1}
+};
+
+static void check_EM_FINDTEXT(HWND hwnd, char *name, struct find_s *f, int id) {
   int findloc;
   FINDTEXT ft;
   memset(&ft, 0, sizeof(ft));
-  ft.chrg.cpMin = start;
-  ft.chrg.cpMax = end;
-  ft.lpstrText = needle;
-  findloc = SendMessage(hwnd, EM_FINDTEXT, flags, (LPARAM) &ft);
-  ok(findloc == expected_start,
-     "EM_FINDTEXT '%s' in range (%d,%d), flags %08x, got start at %d\n",
-     needle, start, end, flags, findloc);
+  ft.chrg.cpMin = f->start;
+  ft.chrg.cpMax = f->end;
+  ft.lpstrText = f->needle;
+  findloc = SendMessage(hwnd, EM_FINDTEXT, f->flags, (LPARAM) &ft);
+  ok(findloc == f->expected_loc,
+     "EM_FINDTEXT(%s,%d) '%s' in range(%d,%d), flags %08x, got start at %d\n",
+     name, id, f->needle, f->start, f->end, f->flags, findloc);
 }
 
-static void test_EM_FINDTEXT(void)
-{
-  CHARRANGE cr;
-  GETTEXTLENGTHEX gtl;
-  int size;
-
-  HWND hwndRichEdit = new_richedit(NULL);
-
-  SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) haystack);
-  SendMessage(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM)&cr);
-  ok(cr.cpMin == cr.cpMax, "(%ld,%ld)\n", cr.cpMin, cr.cpMax);
-
-  gtl.flags = GTL_NUMCHARS;
-  gtl.codepage = CP_ACP;
-  size = SendMessage(hwndRichEdit, EM_GETTEXTLENGTHEX, (WPARAM) &gtl, 0);
-  ok(size == sizeof(haystack) - 1, "size=%d, sizeof haystack=%d\n",
-     size, sizeof(haystack)); /* sizeof counts '\0' */
-
-  check_EM_FINDTEXT(hwndRichEdit, 0, size, "Wine", FR_DOWN | FR_MATCHCASE, 9);
-  check_EM_FINDTEXT(hwndRichEdit, 10, size, "Wine", FR_DOWN | FR_MATCHCASE, 69);
-  check_EM_FINDTEXT(hwndRichEdit, 298, size, "Wine", FR_DOWN | FR_MATCHCASE,
-                    -1);
-  check_EM_FINDTEXT(hwndRichEdit, 0, size, "wine", FR_DOWN | FR_MATCHCASE, -1);
-  todo_wine {
-    check_EM_FINDTEXT(hwndRichEdit, 0, size, "wine", FR_DOWN | FR_WHOLEWORD, 9);
-    check_EM_FINDTEXT(hwndRichEdit, 0, size, "win", FR_DOWN | FR_WHOLEWORD, -1);
-  }
-
-  /* Check the case noted in bug 4479 */
-  SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "blahblah");
-  check_EM_FINDTEXT(hwndRichEdit, 0, 8, "blah", FR_DOWN | FR_MATCHCASE, 0);
-  check_EM_FINDTEXT(hwndRichEdit, 4, 8, "blah", FR_DOWN | FR_MATCHCASE, 4);
-  check_EM_FINDTEXT(hwndRichEdit, 4, 9, "blah", FR_DOWN | FR_MATCHCASE, 4);
-  check_EM_FINDTEXT(hwndRichEdit, 0, 8, "blahblah", FR_DOWN | FR_MATCHCASE, 0);
-
-  DestroyWindow(hwndRichEdit);
-}
-
-static void check_EM_FINDTEXTEX(HWND hwnd, int start, int end, char needle[],
-                                int flags, int expected_start,
-                                int expected_end) {
+static void check_EM_FINDTEXTEX(HWND hwnd, char *name, struct find_s *f,
+    int id) {
   int findloc;
   FINDTEXTEX ft;
   memset(&ft, 0, sizeof(ft));
-  ft.chrg.cpMin = start;
-  ft.chrg.cpMax = end;
-  ft.lpstrText = needle;
-  findloc = SendMessage(hwnd, EM_FINDTEXTEX, flags, (LPARAM) &ft);
-  ok(findloc == expected_start,
-     "EM_FINDTEXTEX '%s' in range (%d,%d), flags %08x, got start at %d\n",
-     needle, start, end, flags, findloc);
-  if(findloc != -1) {
-    ok(ft.chrgText.cpMin == expected_start,
-       "EM_FINDTEXTEX '%s' in range (%d,%d), flags %08x, got start at %ld\n",
-       needle, start, end, flags, ft.chrgText.cpMin);
-    ok(ft.chrgText.cpMax == expected_end,
-       "EM_FINDTEXTEX '%s' in range (%d,%d), flags %08x, got end at %ld\n",
-       needle, start, end, flags, ft.chrgText.cpMax);
-  }
+  ft.chrg.cpMin = f->start;
+  ft.chrg.cpMax = f->end;
+  ft.lpstrText = f->needle;
+  findloc = SendMessage(hwnd, EM_FINDTEXTEX, f->flags, (LPARAM) &ft);
+  ok(findloc == f->expected_loc,
+      "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, start at %d\n",
+      name, id, f->needle, f->start, f->end, f->flags, findloc);
+  ok(ft.chrgText.cpMin == f->expected_loc,
+      "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, start at %ld\n",
+      name, id, f->needle, f->start, f->end, f->flags, ft.chrgText.cpMin);
+  ok(ft.chrgText.cpMax == ((f->expected_loc == -1) ? -1
+        : f->expected_loc + strlen(f->needle)),
+      "EM_FINDTEXTEX(%s,%d) '%s' in range(%d,%d), flags %08x, end at %ld\n",
+      name, id, f->needle, f->start, f->end, f->flags, ft.chrgText.cpMax);
 }
 
-static void test_EM_FINDTEXTEX(void)
+static void run_tests_EM_FINDTEXT(HWND hwnd, char *name, struct find_s *find,
+    int num_tests)
 {
-  CHARRANGE cr;
-  GETTEXTLENGTHEX gtl;
-  int size;
+  int i;
+
+  for (i = 0; i < num_tests; i++) {
+    if (find[i]._todo_wine) {
+      todo_wine {
+        check_EM_FINDTEXT(hwnd, name, &find[i], i);
+        check_EM_FINDTEXTEX(hwnd, name, &find[i], i);
+      }
+    } else {
+        check_EM_FINDTEXT(hwnd, name, &find[i], i);
+        check_EM_FINDTEXTEX(hwnd, name, &find[i], i);
+    }
+  }
+}
 
+static void test_EM_FINDTEXT(void)
+{
   HWND hwndRichEdit = new_richedit(NULL);
 
+  /* Empty rich edit control */
+  run_tests_EM_FINDTEXT(hwndRichEdit, "1", find_tests,
+      sizeof(find_tests)/sizeof(struct find_s));
+
   SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) haystack);
-  SendMessage(hwndRichEdit, EM_EXGETSEL, 0, (LPARAM) &cr);
-  ok(cr.cpMin == cr.cpMax, "(%ld,%ld)\n", cr.cpMin, cr.cpMax);
 
-  gtl.flags = GTL_NUMCHARS;
-  gtl.codepage = CP_ACP;
-  size = SendMessage(hwndRichEdit, EM_GETTEXTLENGTHEX, (WPARAM) &gtl, 0);
-  ok(size == sizeof(haystack) - 1, "size=%d, sizeof haystack=%d\n", size,
-     sizeof(haystack)); /* sizeof counts '\0' */
-
-  check_EM_FINDTEXTEX(hwndRichEdit, 0, size, "Wine", FR_DOWN | FR_MATCHCASE,
-                      9, 13);
-  check_EM_FINDTEXTEX(hwndRichEdit, 10, size, "Wine", FR_DOWN | FR_MATCHCASE,
-                      69, 73);
-  check_EM_FINDTEXTEX(hwndRichEdit, 298, size, "Wine", FR_DOWN | FR_MATCHCASE,
-                      -1, -1);
-  check_EM_FINDTEXTEX(hwndRichEdit, 0, size, "wine", FR_DOWN | FR_MATCHCASE,
-                      -1, -1);
-  todo_wine {
-    check_EM_FINDTEXTEX(hwndRichEdit, 0, size, "wine", FR_DOWN | FR_WHOLEWORD,
-                        9, 13);
-    check_EM_FINDTEXTEX(hwndRichEdit, 0, size, "win", FR_DOWN | FR_WHOLEWORD,
-                        -1, -1);
-  }
+  /* Haystack text */
+  run_tests_EM_FINDTEXT(hwndRichEdit, "2", find_tests2,
+      sizeof(find_tests2)/sizeof(struct find_s));
 
   DestroyWindow(hwndRichEdit);
 }
@@ -168,7 +194,6 @@
   ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError());
 
   test_EM_FINDTEXT();
-  test_EM_FINDTEXTEX();
 
   /* Set the environment variable WINETEST_RICHED20 to keep windows
    * responsive and open for 30 seconds. This is useful for debugging.



More information about the wine-patches mailing list