Fix padded Wine review strings
This commit is contained in:
1 parent
a8cb350467
commit
f40e471938
7 files changed
+416
-33
No files matched your search
@@ -9,6 +9,17 @@
|
||||
#include "../review_capture.h"
|
||||
#define HAS_CAPTURE 1
|
||||
#endif
|
||||
static LRESULT CALLBACK padded_name_proc(HWND window,UINT message,WPARAM wp,LPARAM lp) {
|
||||
const WCHAR text[]={L'R',L'e',L'a',L'd',L'y',0,0xd800,0};
|
||||
if(message==WM_GETTEXTLENGTH)return 7;
|
||||
if(message==WM_GETTEXT && wp) {
|
||||
const size_t copied=std::min<size_t>(7,wp-1);
|
||||
std::copy_n(text,copied,reinterpret_cast<WCHAR*>(lp));
|
||||
reinterpret_cast<WCHAR*>(lp)[copied]=0;
|
||||
return copied;
|
||||
}
|
||||
return DefWindowProcW(window,message,wp,lp);
|
||||
}
|
||||
|
||||
static bool check(bool value, const char *message) {
|
||||
if (!value) std::fprintf(stderr, "FAIL: %s\n", message);
|
||||
@@ -67,15 +78,18 @@ int main(int argc, char **argv) {
|
||||
ok &= check(text.find("private-review-secret") == std::string::npos && text.find("hidden-review-secret") == std::string::npos,
|
||||
"password and hidden contents excluded");
|
||||
ok &= check(SendMessageW(window, WM_APP + 11, 0, 0), "review preserves focus and selection");
|
||||
for (int mode : {1, 2, 3, 4, 5, 6, 7, 8, 9, 14, 15, 17, 18, 21, 22, 23, 24, 25}) {
|
||||
for (int mode : {1, 2, 3, 4, 5, 6, 7, 8, 9, 14, 15, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33}) {
|
||||
std::fprintf(stderr, "capture test: mode %d\n", mode);
|
||||
SendMessageW(window, WM_APP + 10, mode, 0);
|
||||
auto started=GetTickCount64();
|
||||
auto result = capture();
|
||||
std::fprintf(stderr,"capture test: status=%s elapsed=%llu ms\n",result.status.c_str(),static_cast<unsigned long long>(GetTickCount64()-started));
|
||||
const auto value = joined(result);
|
||||
if (mode == 7) ok &= check(result.status == "limited" && result.nodes.empty(), "source limit rejects partial capture");
|
||||
else if (mode == 9) ok &= check(result.status == "stale" && result.nodes.empty(), "same-length update during capture rejects mixed data");
|
||||
else if (mode == 14 || mode == 15 || mode == 18 || mode == 23) ok &= check(result.status == "stale" && result.nodes.empty(), "protection/list/viewport transition rejects old capture");
|
||||
else if (mode == 21) ok &= check(result.status != "ok" && result.nodes.empty(), "delayed native call respects capture deadline");
|
||||
else if (mode == 27) ok &= check(result.status != "ok" && result.nodes.empty() && GetTickCount64()-started<600,"delayed scalar batch respects capture deadline");
|
||||
else ok &= check(result.status == "ok", "configured capture succeeds");
|
||||
ok &= check(value.find("private-review-secret") == std::string::npos && value.find("hidden-review-secret") == std::string::npos,
|
||||
"all captures exclude protected/hidden text");
|
||||
@@ -102,6 +116,37 @@ int main(int argc, char **argv) {
|
||||
if (mode == 14) ok &= check(SendMessageW(window,WM_APP + 14,0,0), "password transition is excluded before copying text");
|
||||
if (mode == 17) ok &= check(value.find("table & item") != std::string::npos && value.find("ready") != std::string::npos, "visible native ListView cells retain text and ampersands");
|
||||
if (mode == 25) ok &= check(value.find("literal & label") != std::string::npos, "SS_NOPREFIX captions retain literal ampersands");
|
||||
if (mode == 26) {
|
||||
size_t visible_lines=0;
|
||||
for(const auto &node:result.nodes)for(const auto &range:node.ranges)
|
||||
if(range.text=="stable buffered output line")++visible_lines;
|
||||
ok &= check(visible_lines>=15,"frame-pumped multiline output captures within the deadline");
|
||||
}
|
||||
if(mode==27){
|
||||
Sleep(750);SendMessageW(window,WM_APP+10,0,0);
|
||||
auto recovered=capture();
|
||||
ok &= check(recovered.status=="ok" && joined(recovered).find("alpha beta")!=std::string::npos,"late scalar callbacks preserve storage and allow a fresh capture");
|
||||
}
|
||||
if(mode==28)ok &= check(value.find("top clipped visible line")!=std::string::npos,"top-clipped Edit captures its lower visible rows");
|
||||
if(mode==29)ok &= check(value.find("nested output ready")!=std::string::npos && SendMessageW(window,WM_APP+16,0,0),"native containers do not synthesize duplicate accessibility trees");
|
||||
if(mode==30)ok &= check(value.find("active mdi text")!=std::string::npos && value.find("covered mdi text")==std::string::npos,"maximized MDI child excludes covered background text");
|
||||
if(mode==31)ok &= check(value.find("active mdi text")!=std::string::npos && value.find("covered mdi text")!=std::string::npos,"side-by-side MDI children retain both visible documents");
|
||||
if (mode == 31) ok &= check(value.find("Active") != std::string::npos && value.find("Background") != std::string::npos,
|
||||
"side-by-side MDI window titles remain available for review");
|
||||
if (mode == 32) ok &= check(value.find("deep clipped visible line") != std::string::npos,
|
||||
"hundreds of clipped rows do not hide the visible tail");
|
||||
if (mode == 33) {
|
||||
bool safe=true, status_present=false;
|
||||
const auto status_id=store.identity(GetDlgItem(window,114))+"_a";
|
||||
for(const auto &node:result.nodes) {
|
||||
if(node.id==status_id)status_present=true;
|
||||
safe &= node.name.find('\0')==std::string::npos;
|
||||
for(const auto &range:node.ranges)safe &= range.text.find('\0')==std::string::npos;
|
||||
}
|
||||
ok &= check(status_present && safe,"padded MSAA status name produces D-Bus-safe accessibility text");
|
||||
ok &= check(value.find("Ready")!=std::string::npos,
|
||||
"status bar retains its exposed label");
|
||||
}
|
||||
if (mode == 21) {
|
||||
Sleep(750);
|
||||
ok &= check(SendMessageW(window,WM_APP + 15,0,0), "remote buffer lives until the delayed target returns");
|
||||
@@ -128,6 +173,23 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
if (mode != 4) ok &= check(SendMessageW(window, WM_APP + 11, 0, 0), "capture leaves caret and focus unchanged");
|
||||
}
|
||||
// A local provider avoids cross-process WM_GETTEXT marshalling, which
|
||||
// itself truncates at the first NUL. Its BSTR retains malformed padding.
|
||||
WNDCLASSW local{};local.hInstance=GetModuleHandleW(nullptr);
|
||||
local.lpfnWndProc=DefWindowProcW;local.lpszClassName=L"WineReviewLocalRoot";
|
||||
RegisterClassW(&local);
|
||||
HWND local_root=CreateWindowW(local.lpszClassName,L"Padded MSAA name",WS_OVERLAPPEDWINDOW,
|
||||
100,100,400,200,nullptr,nullptr,local.hInstance,nullptr);
|
||||
local.lpfnWndProc=padded_name_proc;local.lpszClassName=L"WineReviewPaddedName";
|
||||
RegisterClassW(&local);
|
||||
HWND padded=CreateWindowW(local.lpszClassName,L"",WS_CHILD|WS_VISIBLE,
|
||||
10,10,200,30,local_root,nullptr,local.hInstance,nullptr);
|
||||
ShowWindow(local_root,SW_SHOW);SetForegroundWindow(local_root);SetFocus(padded);
|
||||
auto padded_focus=store.observe_foreground();
|
||||
auto padded_capture=capture_review_window(store,padded_focus,GetTickCount64()+500);
|
||||
ok &= check(padded_capture.status=="ok" && joined(padded_capture).find("Ready")!=std::string::npos,
|
||||
"malformed UTF-16 padding does not discard the valid MSAA label");
|
||||
DestroyWindow(local_root);
|
||||
CoUninitialize();
|
||||
#endif
|
||||
PostMessageW(window, WM_CLOSE, 0, 0);
|
||||
|
||||
Reference in new issue
Block a user