[PATCH 1/1] riched20/tests: Test for ITextDocument::Undo and ITextDocument::Redo.
Jinoh Kang
wine at gitlab.winehq.org
Mon Jun 27 03:23:41 CDT 2022
From: Jinoh Kang <jinoh.kang.kr at gmail.com>
Signed-off-by: Jinoh Kang <jinoh.kang.kr at gmail.com>
---
dlls/riched20/tests/richole.c | 492 ++++++++++++++++++++++++++++++++++
1 file changed, 492 insertions(+)
diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c
index 6a361bc3fa4..6eae75d444b 100644
--- a/dlls/riched20/tests/richole.c
+++ b/dlls/riched20/tests/richole.c
@@ -4955,6 +4955,496 @@ static void test_clipboard(void)
ITextRange_Release(range);
}
+static void subtest_undo(const char *dummy_text)
+{
+ static const char *text_seq[] = {
+ "",
+ "1-alpha",
+ "2-beta",
+ "3-gamma",
+ "4-delta",
+ "5-epsilon",
+ "6-zeta",
+ "7-eta",
+ };
+ static LONG seq[] = { -1, -2, -3, -1, 1, 2, 3, 1, -5, 2, -1, 3, 1, 0 };
+ LONG i = 0, stack_pos = 0;
+ IRichEditOle *reole = NULL;
+ ITextDocument *doc = NULL;
+ ITextSelection *selection;
+ char buffer[1024] = "";
+ HRESULT hr;
+ HWND hwnd;
+ LONG count = 0;
+
+ winetest_push_context("(%Iu)", dummy_text ? strlen(dummy_text) : 0);
+
+ create_interfaces(&hwnd, &reole, &doc, &selection);
+
+ for (i = -2; i <= 2; i++)
+ {
+ if (i != tomFalse && i != tomTrue)
+ {
+ hr = ITextDocument_Undo(doc, i, NULL);
+ todo_wine
+ ok(hr == (i >= 1 ? S_OK : S_FALSE), "(%ld at 0) Undo: %#lx\n", i, hr);
+
+ count = 0xcccccccc;
+ hr = ITextDocument_Undo(doc, i, &count);
+ todo_wine
+ ok(hr == (i >= 1 ? S_OK : S_FALSE), "(%ld at 0) Undo: %#lx\n", i, hr);
+ todo_wine
+ ok(count == (i >= 1 ? i : 0), "(%ld at 0) Expected %ld, got %ld\n", i, i >= 0 ? i : 0, count);
+ }
+
+ hr = ITextDocument_Redo(doc, i, NULL);
+ todo_wine
+ ok(hr == (i == 0 ? S_OK : S_FALSE), "(%ld at 0) Redo: %#lx\n", i, hr);
+
+ count = 0xcccccccc;
+ hr = ITextDocument_Redo(doc, i, &count);
+ todo_wine
+ ok(hr == (i == 0 ? S_OK : S_FALSE), "(%ld at 0) Redo: %#lx\n", i, hr);
+ todo_wine
+ ok(count == 0, "(%ld at 0) got %ld\n", i, count);
+ }
+
+ while (stack_pos < ARRAY_SIZE(text_seq) - 1)
+ {
+ stack_pos++;
+ if (dummy_text)
+ {
+ hr = ITextDocument_Undo(doc, tomSuspend, NULL);
+ todo_wine
+ ok(hr == S_FALSE, "(@%ld) Undo: %#lx\n", stack_pos, hr);
+ if (SUCCEEDED(hr))
+ {
+ SendMessageA(hwnd, EM_SETSEL, (WPARAM)0, (LPARAM)0);
+ SendMessageA(hwnd, EM_REPLACESEL, TRUE, (LPARAM)dummy_text);
+ SendMessageA(hwnd, EM_SETSEL, (WPARAM)0, (LPARAM)strlen(dummy_text));
+ SendMessageA(hwnd, EM_REPLACESEL, TRUE, (LPARAM)"");
+ hr = ITextDocument_Undo(doc, tomResume, NULL);
+ todo_wine
+ ok(hr == S_FALSE, "(@%ld) Undo: %#lx\n", stack_pos, hr);
+ }
+ }
+ SendMessageA(hwnd, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
+ SendMessageA(hwnd, EM_REPLACESEL, TRUE, (LPARAM)text_seq[stack_pos]);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(seq); i++)
+ {
+ LONG expect_count;
+
+ memset(buffer, 0, sizeof(buffer));
+ SendMessageA(hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ todo_wine_if(stack_pos != ARRAY_SIZE(text_seq) - 1)
+ ok(strcmp(buffer, text_seq[stack_pos]) == 0, "Expected %s, got %s\n",
+ wine_dbgstr_a(text_seq[stack_pos]), wine_dbgstr_a(buffer));
+
+ if (!seq[i]) break;
+
+ count = 0xcccccccc;
+ expect_count = labs(stack_pos - min(max(stack_pos + seq[i], 0), (LONG)ARRAY_SIZE(seq) - 1));
+ if (seq[i] < 0)
+ {
+ hr = ITextDocument_Undo(doc, -seq[i], &count);
+ todo_wine
+ ok(hr == S_OK, "(%ld@%ld) Undo: %#lx\n", i, stack_pos, hr);
+ todo_wine
+ ok(count == expect_count, "(%ld@%ld) Expected %ld, got %ld\n", i, stack_pos, expect_count, count);
+ stack_pos -= count;
+ }
+ else
+ {
+ hr = ITextDocument_Redo(doc, seq[i], &count);
+ todo_wine
+ ok(hr == (expect_count ? S_OK : S_FALSE), "(%ld@%ld) Redo: %#lx\n", i, stack_pos, hr);
+ todo_wine
+ ok(count == expect_count, "(%ld@%ld) Expected %ld, got %ld\n", i, stack_pos, expect_count, count);
+ stack_pos += count;
+ }
+
+ if (FAILED(hr) || count <= 0) break;
+ }
+
+ release_interfaces(&hwnd, &reole, &doc, &selection);
+ winetest_pop_context();
+}
+
+static void test_undo(void)
+{
+ subtest_undo(NULL);
+ subtest_undo("dummy 12345");
+}
+
+#define ok_msg_result(h,m,w,l,r) ok_msg_result_(__LINE__,#m,h,m,w,l,r)
+static void ok_msg_result_(int line, const char *desc, HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, LRESULT expect)
+{
+ LRESULT lresult = SendMessageA(hwnd, message, wparam, lparam);
+ ok_(__FILE__,line)(lresult == expect, "%s: Expected %Id, got %Id\n", desc, expect, lresult);
+}
+
+static void test_undo_disable(void)
+{
+ static const char text_initial[] = "initial text";
+ static const char text_foo[] = "foo";
+ static const char text_lorem[] = "lorem ipsum";
+ IRichEditOle *reole = NULL;
+ ITextDocument *doc = NULL;
+ ITextSelection *selection;
+ char buffer[1024] = "";
+ HRESULT hr;
+ HWND hwnd;
+ LONG count = 0;
+ LRESULT def_undo_limit;
+ int subtest_i;
+
+ enum {
+ testGratuitousSuspend = 0x1,
+ testGratuitousResume = 0x2,
+ testResetUndoLimit = 0x4,
+ testEnableUndo = 0x8,
+ testDisableUndo = 0x10,
+ totalTestCount = 0x20,
+ };
+
+ create_interfaces(&hwnd, &reole, &doc, &selection);
+ def_undo_limit = SendMessageA(hwnd, EM_SETUNDOLIMIT, 100, 0);
+ ok(def_undo_limit >= 1, "Message EM_SETUNDOLIMIT returned %#Ix\n", def_undo_limit);
+
+ for (subtest_i = 0; subtest_i < totalTestCount; subtest_i++)
+ {
+ if ((subtest_i & (testEnableUndo | testResetUndoLimit)) == testResetUndoLimit)
+ {
+ continue;
+ }
+
+ winetest_push_context("#%x", subtest_i);
+
+ hr = ITextDocument_Undo(doc, tomTrue, NULL);
+ todo_wine
+ ok(hr == S_FALSE, "Undo: %#lx\n", hr);
+ hr = ITextDocument_Undo(doc, tomResume, NULL);
+ todo_wine
+ ok(hr == S_FALSE, "Undo: %#lx\n", hr);
+ SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"");
+ ok_msg_result(hwnd, EM_CANUNDO, 0, 0, FALSE);
+ ok_msg_result(hwnd, EM_CANREDO, 0, 0, FALSE);
+
+ SendMessageA(hwnd, EM_SETSEL, 0, -1);
+ SendMessageA(hwnd, EM_REPLACESEL, TRUE, (LPARAM)text_initial);
+ ok_msg_result(hwnd, EM_CANUNDO, 0, 0, TRUE);
+ ok_msg_result(hwnd, EM_CANREDO, 0, 0, FALSE);
+
+ count = 0xcccccccc;
+ if (subtest_i & testDisableUndo)
+ {
+ hr = ITextDocument_Undo(doc, tomFalse, &count);
+ todo_wine
+ ok(hr == S_OK, "Undo: %#lx\n", hr);
+ todo_wine
+ ok(count == 0, "Got %ld\n", count);
+ }
+ else
+ {
+ hr = ITextDocument_Undo(doc, tomSuspend, &count);
+ todo_wine
+ ok(hr == S_FALSE, "Undo: %#lx\n", hr);
+ todo_wine
+ ok(count == 0, "Got %ld\n", count);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ todo_wine_if((subtest_i & testDisableUndo) != 0)
+ ok_msg_result(hwnd, EM_CANUNDO, 0, 0, !(subtest_i & testDisableUndo));
+ ok_msg_result(hwnd, EM_CANREDO, 0, 0, FALSE);
+
+ hr = ITextDocument_Undo(doc, 1, &count);
+ todo_wine
+ ok(hr == S_FALSE, "Undo: %#lx\n", hr);
+ todo_wine
+ ok(count == 0, "Got %ld\n", count);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ todo_wine_if((subtest_i & testDisableUndo) != 0)
+ ok_msg_result(hwnd, EM_CANUNDO, 0, 0, !(subtest_i & testDisableUndo));
+ ok_msg_result(hwnd, EM_CANREDO, 0, 0, FALSE);
+ }
+
+ SendMessageA(hwnd, EM_SETSEL, 0, -1);
+ SendMessageA(hwnd, EM_REPLACESEL, TRUE, (LPARAM)text_foo);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = ITextDocument_Undo(doc, 1, &count);
+ todo_wine
+ ok(hr == S_FALSE, "Undo: %#lx\n", hr);
+ todo_wine
+ ok(count == 0, "Got %ld\n", count);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ todo_wine_if((subtest_i & testDisableUndo) != 0)
+ ok_msg_result(hwnd, EM_CANUNDO, 0, 0, !(subtest_i & testDisableUndo));
+ ok_msg_result(hwnd, EM_CANREDO, 0, 0, FALSE);
+ }
+
+ if (SUCCEEDED(hr) && (subtest_i & testGratuitousSuspend))
+ {
+ hr = ITextDocument_Undo(doc, tomSuspend, &count);
+ todo_wine
+ ok(hr == S_FALSE, "Undo: %#lx\n", hr);
+ todo_wine
+ ok(count == 0, "Got %ld\n", count);
+
+ if (SUCCEEDED(hr))
+ {
+ todo_wine_if((subtest_i & testDisableUndo) != 0)
+ ok_msg_result(hwnd, EM_CANUNDO, 0, 0, !(subtest_i & testDisableUndo));
+ ok_msg_result(hwnd, EM_CANREDO, 0, 0, FALSE);
+ }
+ }
+
+ if ((subtest_i & (testEnableUndo | testResetUndoLimit)) == (testEnableUndo | testResetUndoLimit))
+ {
+ LONG_PTR cur_undo_limit = SendMessageA(hwnd, EM_SETUNDOLIMIT, def_undo_limit, 0);
+ ok(cur_undo_limit == def_undo_limit, "Expected undo limit %Id, got %Id\n",
+ def_undo_limit, cur_undo_limit);
+ }
+ else
+ {
+ count = 0xcccccccc;
+ hr = ITextDocument_Undo(doc, (subtest_i & testEnableUndo) ? tomTrue : tomResume, &count);
+ todo_wine
+ ok(hr == S_FALSE, "Undo: %#lx\n", hr);
+ todo_wine
+ ok(count == 0, "Got %ld\n", count);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ todo_wine_if((subtest_i & testDisableUndo) != 0)
+ ok_msg_result(hwnd, EM_CANUNDO, 0, 0, !(subtest_i & testDisableUndo));
+ ok_msg_result(hwnd, EM_CANREDO, 0, 0, FALSE);
+ }
+
+ SendMessageA(hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(strcmp(buffer, text_foo) == 0,
+ "Expected %s, got %s\n", wine_dbgstr_a(text_foo), wine_dbgstr_a(buffer));
+ todo_wine_if((subtest_i & testDisableUndo) != 0)
+ ok_msg_result(hwnd, EM_CANUNDO, 0, 0, !(subtest_i & testDisableUndo));
+ ok_msg_result(hwnd, EM_CANREDO, 0, 0, FALSE);
+
+ count = 0xcccccccc;
+ hr = ITextDocument_Undo(doc, 1, &count);
+ switch (subtest_i & (testEnableUndo | testDisableUndo))
+ {
+ case testEnableUndo | testDisableUndo: /* matching calls: tomFalse => tomTrue */
+ todo_wine
+ ok(hr == S_OK, "Undo: %#lx\n", hr);
+ todo_wine
+ ok(count == 1, "Got %ld\n", count);
+ if (FAILED(hr)) break;
+
+ todo_wine
+ ok_msg_result(hwnd, EM_CANUNDO, 0, 0, FALSE);
+ ok_msg_result(hwnd, EM_CANREDO, 0, 0, FALSE);
+
+ SendMessageA(hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(strcmp(buffer, text_foo) == 0,
+ "Expected %s, got %s\n", wine_dbgstr_a(text_foo), wine_dbgstr_a(buffer));
+
+ count = 0xcccccccc;
+ hr = ITextDocument_Redo(doc, 1, &count);
+ todo_wine
+ ok(hr == S_FALSE, "Redo: %#lx\n", hr);
+ todo_wine
+ ok(count == 0, "Got %ld\n", count);
+ if (FAILED(hr)) break;
+
+ todo_wine
+ ok_msg_result(hwnd, EM_CANUNDO, 0, 0, FALSE);
+ ok_msg_result(hwnd, EM_CANREDO, 0, 0, FALSE);
+ break;
+ case 0: /* matching calls: tomSupend => tomResume */
+ todo_wine
+ ok(hr == S_OK, "Undo: %#lx\n", hr);
+ todo_wine
+ ok(count == 1, "Got %ld\n", count);
+ if (FAILED(hr)) break;
+
+ todo_wine
+ ok_msg_result(hwnd, EM_CANUNDO, 0, 0, FALSE);
+ todo_wine
+ ok_msg_result(hwnd, EM_CANREDO, 0, 0, TRUE);
+
+ SendMessageA(hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ todo_wine
+ ok(strcmp(buffer, "") == 0,
+ "Expected %s, got %s\n", wine_dbgstr_a(""), wine_dbgstr_a(buffer));
+
+ count = 0xcccccccc;
+ hr = ITextDocument_Redo(doc, 1, &count);
+ todo_wine
+ ok(hr == S_OK, "Redo: %#lx\n", hr);
+ todo_wine
+ ok(count == 1, "Got %ld\n", count);
+ if (FAILED(hr)) break;
+
+ if (subtest_i & testDisableUndo)
+ {
+ todo_wine
+ ok_msg_result(hwnd, EM_CANUNDO, 0, 0, FALSE);
+ }
+ ok_msg_result(hwnd, EM_CANREDO, 0, 0, FALSE);
+ break;
+ case testEnableUndo: /* unmatching calls: tomSuspend => tomTrue (not resumed) */
+ todo_wine
+ ok(hr == S_FALSE, "Undo: %#lx\n", hr);
+ todo_wine
+ ok(count == 0, "Got %ld\n", count);
+ if (FAILED(hr)) break;
+
+ ok_msg_result(hwnd, EM_CANUNDO, 0, 0, TRUE);
+ ok_msg_result(hwnd, EM_CANREDO, 0, 0, FALSE);
+ break;
+ case testDisableUndo: /* unmatching calls: tomFalse => tomResume (resumed, no undo entry) */
+ todo_wine
+ ok(hr == S_FALSE, "Undo: %#lx\n", hr);
+ todo_wine
+ ok(count == 0, "Got %ld\n", count);
+ if (FAILED(hr)) break;
+
+ todo_wine
+ ok_msg_result(hwnd, EM_CANUNDO, 0, 0, FALSE);
+ ok_msg_result(hwnd, EM_CANREDO, 0, 0, FALSE);
+ break;
+ default:
+ ok(0, "unreachable code\n");
+ break;
+ }
+
+ SendMessageA(hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(strcmp(buffer, text_foo) == 0,
+ "Expected %s, got %s\n", wine_dbgstr_a(text_foo), wine_dbgstr_a(buffer));
+
+ SendMessageA(hwnd, EM_SETSEL, 0, -1);
+ SendMessageA(hwnd, EM_REPLACESEL, TRUE, (LPARAM)text_lorem);
+
+ ok_msg_result(hwnd, EM_CANUNDO, 0, 0, TRUE);
+ ok_msg_result(hwnd, EM_CANREDO, 0, 0, FALSE);
+
+ count = 0xcccccccc;
+ hr = ITextDocument_Undo(doc, 1, &count);
+ if ((subtest_i & (testEnableUndo | testDisableUndo)) == testEnableUndo)
+ {
+ todo_wine
+ ok(hr == S_FALSE, "Undo: %#lx\n", hr);
+ todo_wine
+ ok(count == 0, "Got %ld\n", count);
+
+ if (SUCCEEDED(hr))
+ {
+ ok_msg_result(hwnd, EM_CANUNDO, 0, 0, TRUE);
+ ok_msg_result(hwnd, EM_CANREDO, 0, 0, FALSE);
+ }
+
+ SendMessageA(hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(strcmp(buffer, text_lorem) == 0,
+ "Expected %s, got %s\n", wine_dbgstr_a(text_lorem), wine_dbgstr_a(buffer));
+ }
+ else
+ {
+ todo_wine
+ ok(hr == S_OK, "Undo: %#lx\n", hr);
+ todo_wine
+ ok(count == 1, "Got %ld\n", count);
+
+ if (SUCCEEDED(hr))
+ {
+ if (subtest_i & testDisableUndo)
+ {
+ todo_wine
+ ok_msg_result(hwnd, EM_CANUNDO, 0, 0, FALSE);
+ }
+ todo_wine
+ ok_msg_result(hwnd, EM_CANREDO, 0, 0, TRUE);
+ }
+
+ SendMessageA(hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ todo_wine
+ ok(strcmp(buffer, text_foo) == 0,
+ "Expected %s, got %s\n", wine_dbgstr_a(text_foo), wine_dbgstr_a(buffer));
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (subtest_i & testDisableUndo)
+ {
+ todo_wine_if((subtest_i & (testEnableUndo | testDisableUndo)) != testEnableUndo)
+ ok_msg_result(hwnd, EM_CANUNDO, 0, 0, (subtest_i & (testEnableUndo | testDisableUndo)) == testEnableUndo);
+ }
+ todo_wine_if((subtest_i & (testEnableUndo | testDisableUndo)) != testEnableUndo)
+ ok_msg_result(hwnd, EM_CANREDO, 0, 0, (subtest_i & (testEnableUndo | testDisableUndo)) != testEnableUndo);
+ }
+
+ if (SUCCEEDED(hr) && (subtest_i & testGratuitousResume))
+ {
+ hr = ITextDocument_Undo(doc, tomResume, &count);
+ todo_wine
+ ok(hr == S_FALSE, "Undo: %#lx\n", hr);
+ todo_wine
+ ok(count == 0, "Got %ld\n", count);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (subtest_i & testDisableUndo)
+ {
+ todo_wine_if((subtest_i & (testEnableUndo | testDisableUndo)) != testEnableUndo)
+ ok_msg_result(hwnd, EM_CANUNDO, 0, 0, (subtest_i & (testEnableUndo | testDisableUndo)) == testEnableUndo);
+ }
+ todo_wine_if((subtest_i & (testEnableUndo | testDisableUndo)) != testEnableUndo)
+ ok_msg_result(hwnd, EM_CANREDO, 0, 0, (subtest_i & (testEnableUndo | testDisableUndo)) != testEnableUndo);
+ }
+
+ count = 0xcccccccc;
+ hr = ITextDocument_Redo(doc, 1, &count);
+ if ((subtest_i & (testEnableUndo | testDisableUndo | testGratuitousResume)) == testEnableUndo)
+ {
+ todo_wine
+ ok(hr == S_FALSE, "Undo: %#lx\n", hr);
+ todo_wine
+ ok(count == 0, "Got %ld\n", count);
+ }
+ else
+ {
+ todo_wine
+ ok(hr == S_OK, "Redo: %#lx\n", hr);
+ todo_wine
+ ok(count == 1, "Got %ld\n", count);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ ok_msg_result(hwnd, EM_CANUNDO, 0, 0, TRUE);
+ ok_msg_result(hwnd, EM_CANREDO, 0, 0, FALSE);
+ }
+
+ SendMessageA(hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(strcmp(buffer, text_lorem) == 0, "Expected %s, got %s\n", wine_dbgstr_a(text_lorem), wine_dbgstr_a(buffer));
+
+ winetest_pop_context();
+ }
+
+ release_interfaces(&hwnd, &reole, &doc, &selection);
+}
+
START_TEST(richole)
{
/* Must explicitly LoadLibrary(). The test has no references to functions in
@@ -4996,4 +5486,6 @@ START_TEST(richole)
test_MoveEnd_story();
test_character_movement();
test_clipboard();
+ test_undo();
+ test_undo_disable();
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/320
More information about the wine-devel
mailing list