From: Jinoh Kang jinoh.kang.kr@gmail.com
Signed-off-by: Jinoh Kang jinoh.kang.kr@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@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@0) Undo: %#lx\n", i, hr); + todo_wine + ok(count == (i >= 1 ? i : 0), "(%ld@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@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@0) Redo: %#lx\n", i, hr); + todo_wine + ok(count == 0, "(%ld@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(); }