Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
March 2022
- 80 participants
- 2903 messages
Re: [PATCH v2] ntoskrnl.exe: Make USD pointers volatile to silent a warning.
by Jinoh Kang
On 3/30/22 04:08, Rémi Bernon wrote:
> Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
> ---
> dlls/ntoskrnl.exe/instr.c | 21 +++++++++++++--------
> 1 file changed, 13 insertions(+), 8 deletions(-)
>
> diff --git a/dlls/ntoskrnl.exe/instr.c b/dlls/ntoskrnl.exe/instr.c
> index 8f1aa4d45a3..0aba2413ab1 100644
> --- a/dlls/ntoskrnl.exe/instr.c
> +++ b/dlls/ntoskrnl.exe/instr.c
> @@ -496,9 +496,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(int);
> #define SIB_INDEX( sib, rex ) (((sib) >> 3) & 7) | (((rex) & REX_X) ? 8 : 0)
> #define SIB_BASE( sib, rex ) (((sib) & 7) | (((rex) & REX_B) ? 8 : 0))
>
> -/* keep in sync with dlls/ntdll/thread.c:thread_init */
> -static const BYTE *wine_user_shared_data = (BYTE *)0x7ffe0000;
> -static const BYTE *user_shared_data = (BYTE *)0xfffff78000000000;
> +/* keep in sync with dlls/ntdll/thread.c:thread_init.
> + *
> + * Both the data and the pointers need to be volatile, as GCC 11
> + * considers that a fixed value pointer is an empty array, and will
> + * emit warnings when dereferencing it otherwise.
> + */
> +static const volatile BYTE *const volatile wine_user_shared_data = (BYTE *)0x7ffe0000;
> +static const volatile BYTE *const volatile user_shared_data = (BYTE *)0xfffff78000000000;
>
> static inline DWORD64 *get_int_reg( CONTEXT *context, int index )
> {
> @@ -516,7 +521,7 @@ static inline int get_op_size( int long_op, int rex )
> }
>
> /* store an operand into a register */
> -static void store_reg_word( CONTEXT *context, BYTE regmodrm, const BYTE *addr, int long_op, int rex,
> +static void store_reg_word( CONTEXT *context, BYTE regmodrm, const volatile BYTE *addr, int long_op, int rex,
> enum instr_op op )
> {
> int index = REGMODRM_REG( regmodrm, rex );
> @@ -527,7 +532,7 @@ static void store_reg_word( CONTEXT *context, BYTE regmodrm, const BYTE *addr, i
> switch (op)
> {
> case INSTR_OP_MOV:
> - memcpy( reg, addr, op_size );
> + memcpy( reg, (BYTE *)addr, op_size );
I think we should not use memcpy() here in the first place.
1. There is no guarantee that memcpy() is atomic. The load might race with USD update from wineserver, causing inconsistent tick counter read.
2. Not using memcpy() avoids the GCC 11 -Warray-bounds warning in the first place.
3. Unaligned pointers wouldn't confuse the optimizer as long as the access is volatile.
I think what we need here is an helper that accurately emulates the memory load. Something along the lines of:
static void load_volatile( void *dest, const volatile void *src, size_t size )
{
switch (size)
{
case sizeof(BYTE): *(BYTE *)dest = *(volatile BYTE *)src;
case sizeof(WORD): *(WORD *)dest = *(volatile WORD *)src;
case sizeof(DWORD): *(DWORD *)dest = *(volatile DWORD *)src;
case sizeof(QWORD): *(QWORD *)dest = *(volatile QWORD *)src;
default: assert(0);
}
}
> break;
> case INSTR_OP_OR:
> for (i = 0; i < op_size; ++i)
> @@ -541,7 +546,7 @@ static void store_reg_word( CONTEXT *context, BYTE regmodrm, const BYTE *addr, i
> }
>
> /* store an operand into a byte register */
> -static void store_reg_byte( CONTEXT *context, BYTE regmodrm, const BYTE *addr, int rex, enum instr_op op )
> +static void store_reg_byte( CONTEXT *context, BYTE regmodrm, const volatile BYTE *addr, int rex, enum instr_op op )
> {
> int index = REGMODRM_REG( regmodrm, rex );
> BYTE *reg = (BYTE *)get_int_reg( context, index );
> @@ -843,7 +848,7 @@ static DWORD emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context )
> ULONGLONG temp = 0;
>
> TRACE("USD offset %#x at %p.\n", (unsigned int)offset, (void *)context->Rip);
> - memcpy( &temp, wine_user_shared_data + offset, data_size );
> + memcpy( &temp, (BYTE *)wine_user_shared_data + offset, data_size );
> store_reg_word( context, instr[2], (BYTE *)&temp, long_op, rex, INSTR_OP_MOV );
> context->Rip += prefixlen + len + 2;
> return ExceptionContinueExecution;
> @@ -902,7 +907,7 @@ static DWORD emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context )
> if (offset <= KSHARED_USER_DATA_PAGE_SIZE - data_size)
> {
> TRACE("USD offset %#x at %p.\n", (unsigned int)offset, (void *)context->Rip);
> - memcpy( &context->Rax, wine_user_shared_data + offset, data_size );
> + memcpy( &context->Rax, (BYTE *)wine_user_shared_data + offset, data_size );
> context->Rip += prefixlen + len + 1;
> return ExceptionContinueExecution;
> }
--
Sincerely,
Jinoh Kang
March 31, 2022
Re: [PATCH v3 6/6] win32u: Move NtUserGetMessage implementation from user32.
by Marvin
Hi,
While running your changed tests, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=111670
Your paranoid android.
=== debian11 (32 bit report) ===
user32:
win.c:11361: Test failed: expected 00BE010C, got 00190164
win.c:11606: Test failed: 1: hwnd 004E0090 is still topmost
win.c:11606: Test failed: 2: hwnd 001900B4 is still topmost
win.c:11606: Test failed: 1: hwnd 004E0090 is still topmost
win.c:11606: Test failed: 2: hwnd 001900B4 is still topmost
win.c:11606: Test failed: 1: hwnd 004E0090 is still topmost
win.c:11606: Test failed: 2: hwnd 001900B4 is still topmost
win.c:11763: Test failed: 007700F8: expected NOT topmost
win.c:11787: Test failed: 007700F8: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 004E0090 is still topmost
win.c:11606: Test failed: 2: hwnd 001900B4 is still topmost
win.c:11606: Test failed: 3: hwnd 00070148 is still topmost
win.c:11606: Test failed: 4: hwnd 007700F8 is still topmost
win.c:11810: Test failed: 004E0090: expected NOT topmost
win.c:11811: Test failed: 007700F8: expected next 00070148, got 00000000
win.c:11811: Test failed: 007700F8: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 004E0090 is still topmost
win.c:11606: Test failed: 2: hwnd 001900B4 is still topmost
win.c:11606: Test failed: 3: hwnd 00070148 is still topmost
win.c:11606: Test failed: 4: hwnd 007700F8 is still topmost
win.c:11834: Test failed: 004E0090: expected NOT topmost
win.c:11835: Test failed: 007700F8: expected next 00070148, got 00000000
win.c:11835: Test failed: 007700F8: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 004E0090 is still topmost
win.c:11606: Test failed: 2: hwnd 001900B4 is still topmost
win.c:11606: Test failed: 3: hwnd 00070148 is still topmost
win.c:11606: Test failed: 4: hwnd 007700F8 is still topmost
win.c:11869: Test failed: 007700F8: expected next 00070148, got 00000000
win.c:11869: Test failed: 007700F8: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 004E0090 is still topmost
win.c:11606: Test failed: 2: hwnd 001900B4 is still topmost
win.c:11606: Test failed: 3: hwnd 00070148 is still topmost
win.c:11606: Test failed: 4: hwnd 007700F8 is still topmost
win.c:11892: Test failed: 007700F8: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 004E0090 is still topmost
win.c:11606: Test failed: 2: hwnd 001900B4 is still topmost
win.c:11606: Test failed: 3: hwnd 00070148 is still topmost
win.c:11606: Test failed: 4: hwnd 007700F8 is still topmost
win.c:11903: Test failed: 007700F8: expected next 00070148, got 00000000
win.c:11903: Test failed: 007700F8: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 004E0090 is still topmost
win.c:11606: Test failed: 2: hwnd 001900B4 is still topmost
win.c:11606: Test failed: 3: hwnd 00070148 is still topmost
win.c:11606: Test failed: 4: hwnd 007700F8 is still topmost
win.c:11606: Test failed: 1: hwnd 004E0090 is still topmost
win.c:11606: Test failed: 2: hwnd 001900B4 is still topmost
win.c:11606: Test failed: 3: hwnd 00070148 is still topmost
win.c:11606: Test failed: 4: hwnd 007700F8 is still topmost
win.c:11606: Test failed: 1: hwnd 004E0090 is still topmost
win.c:11606: Test failed: 2: hwnd 001900B4 is still topmost
win.c:11606: Test failed: 3: hwnd 00070148 is still topmost
win.c:11606: Test failed: 4: hwnd 007700F8 is still topmost
=== debian11 (32 bit Chinese:China report) ===
user32:
input.c:2793: Test failed: 4: unexpected WM_MOUSEMOVE message
input.c:2804: Test failed: 9: Unexpected cursor movement
input.c:2521: Test failed: 10: foreground process expected WM_MOUSEMOVE message
input.c:2521: Test failed: 11: foreground process expected WM_MOUSEMOVE message
input.c:2521: Test failed: 12: foreground process expected WM_MOUSEMOVE message
input.c:1733: Test failed: expected to get 64 mouse move points but got -1
input.c:1744: Test failed: expected to get 64 mouse move points but got -1
msg.c:16552: Test failed: OpenClipboard failed, err=5
msg.c:16552: Test failed: EmptyClipboard failed, err=1418
msg.c:16552: Test failed: CloseClipboard failed, err=1418
=== debian11 (32 bit WoW report) ===
user32:
input.c:2162: Test failed: Unexpected rawinput data: 4
input.c:2163: Test failed: Unexpected rawinput data: -8
input.c:2217: Test failed: Unexpected rawinput data: 2
input.c:1628: Test failed: wrong position 5, expected 61x122 got 62x124
input.c:1628: Test failed: wrong position 7, expected 59x118 got 61x122
input.c:1628: Test failed: wrong position 9, expected 57x114 got 60x120
input.c:1628: Test failed: wrong position 11, expected 55x110 got 59x118
input.c:1628: Test failed: wrong position 13, expected 53x106 got 58x116
input.c:1628: Test failed: wrong position 15, expected 51x102 got 57x114
input.c:1628: Test failed: wrong position 16, expected 50x100 got 58x116
input.c:1628: Test failed: wrong position 17, expected 49x98 got 56x112
input.c:1628: Test failed: wrong position 21, expected 45x90 got 54x108
input.c:1628: Test failed: wrong position 23, expected 43x86 got 53x106
input.c:1628: Test failed: wrong position 25, expected 41x82 got 52x104
input.c:1628: Test failed: wrong position 26, expected 40x80 got 51x102
input.c:1628: Test failed: wrong position 30, expected 36x72 got 51x102
input.c:1628: Test failed: wrong position 31, expected 35x70 got 49x98
input.c:1628: Test failed: wrong position 33, expected 33x66 got 48x96
input.c:1628: Test failed: wrong position 35, expected 31x62 got 47x94
input.c:1628: Test failed: wrong position 36, expected 30x60 got 48x96
input.c:1628: Test failed: wrong position 37, expected 29x58 got 46x92
input.c:1628: Test failed: wrong position 38, expected 28x56 got 47x94
input.c:1628: Test failed: wrong position 39, expected 27x54 got 45x90
input.c:1628: Test failed: wrong position 42, expected 24x48 got 45x90
input.c:1628: Test failed: wrong position 43, expected 23x46 got 43x86
input.c:1628: Test failed: wrong position 44, expected 22x44 got 44x88
input.c:1628: Test failed: wrong position 45, expected 21x42 got 42x84
input.c:1628: Test failed: wrong position 47, expected 19x38 got 41x82
input.c:1628: Test failed: wrong position 48, expected 18x36 got 42x84
input.c:1628: Test failed: wrong position 49, expected 17x34 got 40x80
input.c:1628: Test failed: wrong position 51, expected 15x30 got 39x78
input.c:1628: Test failed: wrong position 53, expected 13x26 got 38x76
input.c:1628: Test failed: wrong position 55, expected 11x22 got 37x74
input.c:1628: Test failed: wrong position 61, expected 5x10 got 34x68
input.c:1628: Test failed: wrong position 62, expected 4x8 got 35x70
win.c:11344: Test failed: expected 01EF0142, got 002700C6
win.c:11361: Test failed: expected 01EF0142, got 002700C6
=== debian11 (64 bit WoW report) ===
user32:
input.c:2164: Test failed: Unexpected rawinput data: -16
input.c:1628: Test failed: wrong position 6, expected 60x120 got 63x126
input.c:1628: Test failed: wrong position 7, expected 59x118 got 61x122
input.c:1628: Test failed: wrong position 9, expected 57x114 got 62x124
input.c:1628: Test failed: wrong position 11, expected 55x110 got 61x122
input.c:1628: Test failed: wrong position 12, expected 54x108 got 58x116
input.c:1628: Test failed: wrong position 15, expected 51x102 got 59x118
input.c:1628: Test failed: wrong position 17, expected 49x98 got 58x116
input.c:1628: Test failed: wrong position 18, expected 48x96 got 55x110
input.c:1628: Test failed: wrong position 19, expected 47x94 got 57x114
input.c:1628: Test failed: wrong position 23, expected 43x86 got 55x110
input.c:1628: Test failed: wrong position 24, expected 42x84 got 52x104
input.c:1628: Test failed: wrong position 25, expected 41x82 got 54x108
input.c:1628: Test failed: wrong position 26, expected 40x80 got 51x102
input.c:1628: Test failed: wrong position 28, expected 38x76 got 50x100
input.c:1628: Test failed: wrong position 31, expected 35x70 got 51x102
input.c:1628: Test failed: wrong position 33, expected 33x66 got 50x100
input.c:1628: Test failed: wrong position 34, expected 32x64 got 47x94
input.c:1628: Test failed: wrong position 35, expected 31x62 got 49x98
input.c:1628: Test failed: wrong position 36, expected 30x60 got 46x92
input.c:1628: Test failed: wrong position 37, expected 29x58 got 48x96
input.c:1628: Test failed: wrong position 39, expected 27x54 got 47x94
input.c:1628: Test failed: wrong position 41, expected 25x50 got 44x88
input.c:1628: Test failed: wrong position 51, expected 15x30 got 39x78
input.c:1628: Test failed: wrong position 55, expected 11x22 got 37x74
input.c:1628: Test failed: wrong position 56, expected 10x20 got 36x72
input.c:1628: Test failed: wrong position 57, expected 9x18 got 38x76
input.c:1628: Test failed: wrong position 58, expected 8x16 got 35x70
input.c:1628: Test failed: wrong position 60, expected 6x12 got 34x68
input.c:1628: Test failed: wrong position 62, expected 4x8 got 33x66
win.c:11361: Test failed: expected 0000000001800144, got 00000000000C0130
March 31, 2022
Re: [PATCH v3 5/6] win32u: Move NtUserPeekMessage implementation from user32.
by Marvin
Hi,
While running your changed tests, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=111669
Your paranoid android.
=== debian11 (32 bit report) ===
user32:
input.c:2164: Test failed: Unexpected rawinput data: -5
input.c:2217: Test failed: Unexpected rawinput data: -3
input.c:1628: Test failed: wrong position 10, expected 56x112 got 58x116
input.c:1628: Test failed: wrong position 13, expected 53x106 got 60x120
input.c:1628: Test failed: wrong position 28, expected 38x76 got 53x106
input.c:1628: Test failed: wrong position 29, expected 37x74 got 52x104
input.c:1628: Test failed: wrong position 34, expected 32x64 got 46x92
input.c:1628: Test failed: wrong position 35, expected 31x62 got 49x98
input.c:1628: Test failed: wrong position 39, expected 27x54 got 44x88
input.c:1628: Test failed: wrong position 41, expected 25x50 got 43x86
input.c:1628: Test failed: wrong position 45, expected 21x42 got 44x88
input.c:1628: Test failed: wrong position 49, expected 17x34 got 42x84
input.c:1628: Test failed: wrong position 50, expected 16x32 got 38x76
input.c:1628: Test failed: wrong position 52, expected 14x28 got 41x82
input.c:1628: Test failed: wrong position 54, expected 12x24 got 40x80
input.c:1628: Test failed: wrong position 57, expected 9x18 got 37x74
input.c:1628: Test failed: wrong position 58, expected 8x16 got 35x70
=== debian11 (32 bit Chinese:China report) ===
user32:
input.c:2217: Test failed: Unexpected rawinput data: -9
input.c:1628: Test failed: wrong position 10, expected 56x112 got 62x124
input.c:1628: Test failed: wrong position 12, expected 54x108 got 61x122
input.c:1628: Test failed: wrong position 15, expected 51x102 got 60x120
input.c:1628: Test failed: wrong position 16, expected 50x100 got 59x118
input.c:1628: Test failed: wrong position 23, expected 43x86 got 52x104
input.c:1628: Test failed: wrong position 28, expected 38x76 got 53x106
input.c:1628: Test failed: wrong position 31, expected 35x70 got 48x96
input.c:1628: Test failed: wrong position 39, expected 27x54 got 44x88
input.c:1628: Test failed: wrong position 54, expected 12x24 got 36x72
input.c:1628: Test failed: wrong position 56, expected 10x20 got 35x70
input.c:1628: Test failed: wrong position 57, expected 9x18 got 34x68
input.c:1628: Test failed: wrong position 59, expected 7x14 got 33x66
input.c:1628: Test failed: wrong position 61, expected 5x10 got 37x74
input.c:1628: Test failed: wrong position 62, expected 4x8 got 31x62
input.c:1628: Test failed: wrong position 63, expected 3x6 got 36x72
win.c:11344: Test failed: expected 00BF0102, got 000A015C
win.c:11353: Test failed: GetActiveWindow() = 00000000
win.c:11353: Test failed: GetFocus() = 00000000
win.c:11606: Test failed: 1: hwnd 0069008E is still topmost
win.c:11606: Test failed: 2: hwnd 001500CE is still topmost
win.c:11606: Test failed: 1: hwnd 0069008E is still topmost
win.c:11606: Test failed: 2: hwnd 001500CE is still topmost
win.c:11606: Test failed: 1: hwnd 0069008E is still topmost
win.c:11606: Test failed: 2: hwnd 001500CE is still topmost
win.c:11763: Test failed: 0074010A: expected NOT topmost
win.c:11787: Test failed: 0074010A: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 0069008E is still topmost
win.c:11606: Test failed: 2: hwnd 001500CE is still topmost
win.c:11606: Test failed: 3: hwnd 00070146 is still topmost
win.c:11606: Test failed: 4: hwnd 0074010A is still topmost
win.c:11810: Test failed: 0069008E: expected NOT topmost
win.c:11811: Test failed: 0074010A: expected next 00070146, got 00000000
win.c:11811: Test failed: 0074010A: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 0069008E is still topmost
win.c:11606: Test failed: 2: hwnd 001500CE is still topmost
win.c:11606: Test failed: 3: hwnd 00070146 is still topmost
win.c:11606: Test failed: 4: hwnd 0074010A is still topmost
win.c:11834: Test failed: 0069008E: expected NOT topmost
win.c:11835: Test failed: 0074010A: expected next 00070146, got 00000000
win.c:11835: Test failed: 0074010A: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 0069008E is still topmost
win.c:11606: Test failed: 2: hwnd 001500CE is still topmost
win.c:11606: Test failed: 3: hwnd 00070146 is still topmost
win.c:11606: Test failed: 4: hwnd 0074010A is still topmost
win.c:11869: Test failed: 0074010A: expected next 00070146, got 00000000
win.c:11869: Test failed: 0074010A: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 0069008E is still topmost
win.c:11606: Test failed: 2: hwnd 001500CE is still topmost
win.c:11606: Test failed: 3: hwnd 00070146 is still topmost
win.c:11606: Test failed: 4: hwnd 0074010A is still topmost
win.c:11892: Test failed: 0074010A: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 0069008E is still topmost
win.c:11606: Test failed: 2: hwnd 001500CE is still topmost
win.c:11606: Test failed: 3: hwnd 00070146 is still topmost
win.c:11606: Test failed: 4: hwnd 0074010A is still topmost
win.c:11903: Test failed: 0074010A: expected next 00070146, got 00000000
win.c:11903: Test failed: 0074010A: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 0069008E is still topmost
win.c:11606: Test failed: 2: hwnd 001500CE is still topmost
win.c:11606: Test failed: 3: hwnd 00070146 is still topmost
win.c:11606: Test failed: 4: hwnd 0074010A is still topmost
win.c:11606: Test failed: 1: hwnd 0069008E is still topmost
win.c:11606: Test failed: 2: hwnd 001500CE is still topmost
win.c:11606: Test failed: 3: hwnd 00070146 is still topmost
win.c:11606: Test failed: 4: hwnd 0074010A is still topmost
win.c:11606: Test failed: 1: hwnd 0069008E is still topmost
win.c:11606: Test failed: 2: hwnd 001500CE is still topmost
win.c:11606: Test failed: 3: hwnd 00070146 is still topmost
win.c:11606: Test failed: 4: hwnd 0074010A is still topmost
=== debian11 (32 bit WoW report) ===
user32:
input.c:2164: Test failed: Unexpected rawinput data: -11
input.c:2160: Test failed: GetRawInputBuffer returned 11
input.c:1628: Test failed: wrong position 5, expected 61x122 got 62x124
input.c:1628: Test failed: wrong position 7, expected 59x118 got 61x122
input.c:1628: Test failed: wrong position 9, expected 57x114 got 60x120
input.c:1628: Test failed: wrong position 11, expected 55x110 got 59x118
input.c:1628: Test failed: wrong position 13, expected 53x106 got 58x116
input.c:1628: Test failed: wrong position 15, expected 51x102 got 57x114
input.c:1628: Test failed: wrong position 16, expected 50x100 got 58x116
input.c:1628: Test failed: wrong position 17, expected 49x98 got 56x112
input.c:1628: Test failed: wrong position 21, expected 45x90 got 54x108
input.c:1628: Test failed: wrong position 23, expected 43x86 got 53x106
input.c:1628: Test failed: wrong position 25, expected 41x82 got 52x104
input.c:1628: Test failed: wrong position 29, expected 37x74 got 50x100
input.c:1628: Test failed: wrong position 30, expected 36x72 got 51x102
input.c:1628: Test failed: wrong position 31, expected 35x70 got 49x98
input.c:1628: Test failed: wrong position 33, expected 33x66 got 48x96
input.c:1628: Test failed: wrong position 35, expected 31x62 got 47x94
input.c:1628: Test failed: wrong position 36, expected 30x60 got 48x96
input.c:1628: Test failed: wrong position 37, expected 29x58 got 46x92
input.c:1628: Test failed: wrong position 38, expected 28x56 got 47x94
input.c:1628: Test failed: wrong position 39, expected 27x54 got 45x90
input.c:1628: Test failed: wrong position 42, expected 24x48 got 45x90
input.c:1628: Test failed: wrong position 43, expected 23x46 got 43x86
input.c:1628: Test failed: wrong position 44, expected 22x44 got 44x88
input.c:1628: Test failed: wrong position 45, expected 21x42 got 42x84
input.c:1628: Test failed: wrong position 47, expected 19x38 got 41x82
input.c:1628: Test failed: wrong position 48, expected 18x36 got 42x84
input.c:1628: Test failed: wrong position 49, expected 17x34 got 40x80
input.c:1628: Test failed: wrong position 51, expected 15x30 got 39x78
input.c:1628: Test failed: wrong position 53, expected 13x26 got 38x76
input.c:1628: Test failed: wrong position 55, expected 11x22 got 37x74
input.c:1628: Test failed: wrong position 57, expected 9x18 got 36x72
input.c:1628: Test failed: wrong position 61, expected 5x10 got 34x68
input.c:1628: Test failed: wrong position 62, expected 4x8 got 35x70
win.c:11361: Test failed: expected 01EF0142, got 001100A2
=== debian11 (64 bit WoW report) ===
user32:
win.c:11361: Test failed: expected 0000000000BF010C, got 0000000000320072
win.c:11606: Test failed: 1: hwnd 0000000000BA009C is still topmost
win.c:11606: Test failed: 2: hwnd 00000000002000CA is still topmost
win.c:11606: Test failed: 1: hwnd 0000000000BA009C is still topmost
win.c:11606: Test failed: 2: hwnd 00000000002000CA is still topmost
win.c:11606: Test failed: 1: hwnd 0000000000BA009C is still topmost
win.c:11606: Test failed: 2: hwnd 00000000002000CA is still topmost
win.c:11763: Test failed: 0000000001D8008E: expected NOT topmost
win.c:11787: Test failed: 0000000001D8008E: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 0000000000BA009C is still topmost
win.c:11606: Test failed: 2: hwnd 00000000002000CA is still topmost
win.c:11606: Test failed: 3: hwnd 0000000000070148 is still topmost
win.c:11606: Test failed: 4: hwnd 0000000001D8008E is still topmost
win.c:11810: Test failed: 0000000000BA009C: expected NOT topmost
win.c:11811: Test failed: 0000000001D8008E: expected next 0000000000070148, got 0000000000000000
win.c:11811: Test failed: 0000000001D8008E: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 0000000000BA009C is still topmost
win.c:11606: Test failed: 2: hwnd 00000000002000CA is still topmost
win.c:11606: Test failed: 3: hwnd 0000000000070148 is still topmost
win.c:11606: Test failed: 4: hwnd 0000000001D8008E is still topmost
win.c:11834: Test failed: 0000000000BA009C: expected NOT topmost
win.c:11835: Test failed: 0000000001D8008E: expected next 0000000000070148, got 0000000000000000
win.c:11835: Test failed: 0000000001D8008E: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 0000000000BA009C is still topmost
win.c:11606: Test failed: 2: hwnd 00000000002000CA is still topmost
win.c:11606: Test failed: 3: hwnd 0000000000070148 is still topmost
win.c:11606: Test failed: 4: hwnd 0000000001D8008E is still topmost
win.c:11869: Test failed: 0000000001D8008E: expected next 0000000000070148, got 0000000000000000
win.c:11869: Test failed: 0000000001D8008E: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 0000000000BA009C is still topmost
win.c:11606: Test failed: 2: hwnd 00000000002000CA is still topmost
win.c:11606: Test failed: 3: hwnd 0000000000070148 is still topmost
win.c:11606: Test failed: 4: hwnd 0000000001D8008E is still topmost
win.c:11892: Test failed: 0000000001D8008E: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 0000000000BA009C is still topmost
win.c:11606: Test failed: 2: hwnd 00000000002000CA is still topmost
win.c:11606: Test failed: 3: hwnd 0000000000070148 is still topmost
win.c:11606: Test failed: 4: hwnd 0000000001D8008E is still topmost
win.c:11903: Test failed: 0000000001D8008E: expected next 0000000000070148, got 0000000000000000
win.c:11903: Test failed: 0000000001D8008E: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 0000000000BA009C is still topmost
win.c:11606: Test failed: 2: hwnd 00000000002000CA is still topmost
win.c:11606: Test failed: 3: hwnd 0000000000070148 is still topmost
win.c:11606: Test failed: 4: hwnd 0000000001D8008E is still topmost
win.c:11606: Test failed: 1: hwnd 0000000000BA009C is still topmost
win.c:11606: Test failed: 2: hwnd 00000000002000CA is still topmost
win.c:11606: Test failed: 3: hwnd 0000000000070148 is still topmost
win.c:11606: Test failed: 4: hwnd 0000000001D8008E is still topmost
win.c:11606: Test failed: 1: hwnd 0000000000BA009C is still topmost
win.c:11606: Test failed: 2: hwnd 00000000002000CA is still topmost
win.c:11606: Test failed: 3: hwnd 0000000000070148 is still topmost
win.c:11606: Test failed: 4: hwnd 0000000001D8008E is still topmost
March 31, 2022
[tools 1/3] testbot/cgi: Add SimpleCollectionPage.
by Francois Gouget
SimpleCollectionPage embeds a single collection block. But unlike
CollectionPage it is only a Page subclass instead of implementing both
the Page and CollectionBlock interfaces. Customizing the collection
block is done by creating a CollectionBlock subclass and passing the
appropriate creator function to the page constructor.
This better separates the page customization aspects (implement a
SimpleCollectionPage subclass) from the collection block ones
(implement a CollectionBlock subclass). Most of the time only the
collection block needs to be customized and SimpleCollectionPage can
be used as is.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
.../lib/ObjectModel/CGI/CollectionBlock.pm | 5 +
.../ObjectModel/CGI/SimpleCollectionPage.pm | 138 ++++++++++++++++++
2 files changed, 143 insertions(+)
create mode 100644 testbot/lib/ObjectModel/CGI/SimpleCollectionPage.pm
diff --git a/testbot/lib/ObjectModel/CGI/CollectionBlock.pm b/testbot/lib/ObjectModel/CGI/CollectionBlock.pm
index 9a52f11bc..200734a6a 100644
--- a/testbot/lib/ObjectModel/CGI/CollectionBlock.pm
+++ b/testbot/lib/ObjectModel/CGI/CollectionBlock.pm
@@ -91,6 +91,11 @@ sub _initialize($$$)
#my ($self, $Collection, $EnclosingPage) = @_;
}
+sub Create($$@)
+{
+ return ObjectModel::CGI::CollectionBlock->new(@_);
+}
+
sub CallGetDetailsPage($)
{
my ($self) = @_;
diff --git a/testbot/lib/ObjectModel/CGI/SimpleCollectionPage.pm b/testbot/lib/ObjectModel/CGI/SimpleCollectionPage.pm
new file mode 100644
index 000000000..76e4d5195
--- /dev/null
+++ b/testbot/lib/ObjectModel/CGI/SimpleCollectionPage.pm
@@ -0,0 +1,138 @@
+# -*- Mode: Perl; perl-indent-level: 2; indent-tabs-mode: nil -*-
+# Base class for list pages
+#
+# Copyright 2009 Ge van Geldorp
+# Copyright 2014, 2017-2018, 2022 Francois Gouget
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+
+use strict;
+
+package ObjectModel::CGI::SimpleCollectionPage;
+
+=head1 NAME
+
+ObjectModel::CGI::SimpleCollectionPage - Base class for list pages
+
+A page containing a single collection block.
+
+The SimpleCollectionPage instances have the following properties:
+=over
+=item Collection
+The collection containing the items to be shown in the CollectionBlock widget.
+
+=item CollectionBlock
+The widget showing the items in the specified collection.
+
+=item ActionPerformed
+Set to true if an action was specified and succeeded.
+=back
+
+=cut
+
+use ObjectModel::CGI::Page;
+our @ISA = qw(ObjectModel::CGI::Page);
+
+# Use require to avoid overriding Page::new()
+require ObjectModel::CGI::CollectionBlock;
+
+
+=pod
+=over 12
+
+=item C<_initialize()>
+
+Sets up the new page object.
+
+Parameters:
+=over
+
+=item Request
+=item RequiredRole
+See Page::new().
+
+=item Collection
+This is the collection of items that should be shown in the CollectionBlock
+widget.
+
+=item BlockCreator
+If undefined the page will create an instance of the CollectionBlock class.
+Otherwise it will use this function to create the CollectionBlock widget, thus
+enabling use of a CollectionBlock subclass.
+
+=back
+
+=back
+=cut
+
+sub _initialize($$$$;$)
+{
+ my ($self, $Request, $RequiredRole, $Collection, $BlockCreator) = @_;
+
+ $self->{Collection} = $Collection;
+ $BlockCreator ||= \&ObjectModel::CGI::CollectionBlock::Create;
+ $self->{CollectionBlock} = &$BlockCreator($Collection, $self);
+ $self->SUPER::_initialize($Request, $RequiredRole);
+}
+
+
+#
+# HTML page generation
+#
+
+sub GetTitle($)
+{
+ my ($self) = @_;
+
+ my $Title = ucfirst($self->{Collection}->GetCollectionName());
+ $Title =~ s/([a-z])([A-Z])/$1 $2/g;
+ return $Title;
+}
+
+sub GenerateTitle($)
+{
+ my ($self) = @_;
+
+ my $Title = $self->GetTitle();
+ if ($Title)
+ {
+ print "<h1 id='PageTitle'>", $self->escapeHTML($Title), "</h1>\n";
+ }
+}
+
+sub GenerateBody($)
+{
+ my ($self) = @_;
+
+ print "<div class='CollectionPageBody'>\n";
+ $self->GenerateTitle();
+ print "<div class='Content'>\n";
+ $self->{CollectionBlock}->GenerateList();
+ print "</div>\n";
+ print "</div>\n";
+}
+
+sub GeneratePage($)
+{
+ my ($self) = @_;
+
+ if ($self->GetParam("Action"))
+ {
+ $self->{ActionPerformed} = $self->{CollectionBlock}->OnAction($self->GetParam("Action"));
+ }
+ $self->SUPER::GeneratePage();
+}
+
+1;
--
2.30.2
March 31, 2022
[tools 3/3] testbot/web: Use SimpleCollectionPage for the patches page.
by Francois Gouget
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/web/PatchesList.pl | 63 ++++++++++++++++++--------------------
1 file changed, 29 insertions(+), 34 deletions(-)
diff --git a/testbot/web/PatchesList.pl b/testbot/web/PatchesList.pl
index 04ca0208c..e756a76ff 100644
--- a/testbot/web/PatchesList.pl
+++ b/testbot/web/PatchesList.pl
@@ -2,6 +2,7 @@
# Patch list page
#
# Copyright 2010 Ge van Geldorp
+# Copyright 2012-2018, 2022 Francois Gouget
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -19,34 +20,25 @@
use strict;
-package PatchesListPage;
+package PatchesBlock;
-use ObjectModel::CGI::CollectionPage;
-our @ISA = qw(ObjectModel::CGI::CollectionPage);
+use ObjectModel::CGI::CollectionBlock;
+our @ISA = qw(ObjectModel::CGI::CollectionBlock);
use URI::Escape;
use WineTestBot::Patches;
-sub _initialize($$$)
+sub Create($$)
{
- my ($self, $Request, $RequiredRole) = @_;
+ my ($Collection, $EnclosingPage) = @_;
- $self->SUPER::_initialize($Request, $RequiredRole, CreatePatches());
- $self->SetRefreshInterval(60);
+ return PatchesBlock->new($Collection, $EnclosingPage);
}
-sub SortKeys($$$)
+sub DisplayProperty($$)
{
- my ($self, $CollectionBlock, $Keys) = @_;
-
- my @SortedKeys = sort { $b <=> $a } @$Keys;
- return \@SortedKeys;
-}
-
-sub DisplayProperty($$$)
-{
- my ($self, $CollectionBlock, $PropertyDescriptor) = @_;
+ my ($self, $PropertyDescriptor) = @_;
my $PropertyName = $PropertyDescriptor->GetName();
@@ -54,21 +46,9 @@ sub DisplayProperty($$$)
$PropertyName eq "FromName" || $PropertyName eq "Subject";
}
-sub GetItemActions($$)
-{
- #my ($self, $CollectionBlock) = @_;
- return [];
-}
-
-sub GetActions($$)
-{
- #my ($self, $CollectionBlock) = @_;
- return [];
-}
-
sub GenerateDataCell($$$$$)
{
- my ($self, $CollectionBlock, $Item, $PropertyDescriptor, $DetailsPage) = @_;
+ my ($self, $Item, $PropertyDescriptor, $DetailsPage) = @_;
my $PropertyName = $PropertyDescriptor->GetName();
if ($PropertyName eq "Disposition" and $Item->Disposition =~ /job ([0-9]+)$/)
@@ -80,14 +60,29 @@ sub GenerateDataCell($$$$$)
}
else
{
- $self->SUPER::GenerateDataCell($CollectionBlock, $Item, $PropertyDescriptor, $DetailsPage);
+ $self->SUPER::GenerateDataCell($Item, $PropertyDescriptor, $DetailsPage);
}
}
+sub GetItemActions($)
+{
+ #my ($self) = @_;
+ return [];
+}
+
+sub GetActions($)
+{
+ #my ($self) = @_;
+ return [];
+}
+
package main;
-my $Request = shift;
+use ObjectModel::CGI::SimpleCollectionPage;
+use WineTestBot::Patches;
-my $PatchesListPage = PatchesListPage->new($Request, "");
-$PatchesListPage->GeneratePage();
+my $Request = shift;
+my $Page = ObjectModel::CGI::SimpleCollectionPage->new($Request, "", CreatePatches(), \&PatchesBlock::Create);
+$Page->SetRefreshInterval(60);
+$Page->GeneratePage();
--
2.30.2
March 31, 2022
[tools 2/3] testbot/web: Use SimpleCollectionPage for the job details page.
by Francois Gouget
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/web/JobDetails.pl | 378 +++++++++++++++++++++-----------------
1 file changed, 205 insertions(+), 173 deletions(-)
diff --git a/testbot/web/JobDetails.pl b/testbot/web/JobDetails.pl
index 5b8b7013a..c4d6b1a1b 100644
--- a/testbot/web/JobDetails.pl
+++ b/testbot/web/JobDetails.pl
@@ -2,7 +2,7 @@
# Job details page
#
# Copyright 2009 Ge van Geldorp
-# Copyright 2012-2014,2017-2020 Francois Gouget
+# Copyright 2012-2014,2017-2022 Francois Gouget
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -20,73 +20,35 @@
use strict;
-package JobDetailsPage;
+package StepsTasksBlock;
-use ObjectModel::CGI::CollectionPage;
-our @ISA = qw(ObjectModel::CGI::CollectionPage);
+use ObjectModel::CGI::CollectionBlock;
+our @ISA = qw(ObjectModel::CGI::CollectionBlock);
-use File::Basename;
-use POSIX qw(strftime);
use URI::Escape;
+use POSIX qw(strftime);
-use WineTestBot::Config;
-use WineTestBot::Jobs;
-use WineTestBot::Log; # For Elapsed()
-use WineTestBot::LogUtils;
-use WineTestBot::Missions;
-use WineTestBot::StepsTasks;
use WineTestBot::Utils;
+use WineTestBot::Missions;
use WineTestBot::Engine::Notify;
-sub _initialize($$$)
+sub Create($$)
{
- my ($self, $Request, $RequiredRole) = @_;
- $self->{start} = Time();
+ my ($Collection, $EnclosingPage) = @_;
- my $JobId = $self->GetParam("Key");
- if (! defined($JobId))
- {
- $JobId = $self->GetParam("JobId");
- }
- $self->{Job} = CreateJobs()->GetItem($JobId);
- if (!defined $self->{Job})
- {
- exit($self->Redirect("/"));
- }
- $self->{JobId} = $JobId;
-
- $self->SUPER::_initialize($Request, $RequiredRole, CreateStepsTasks(undef, $self->{Job}));
- if ($self->{Job}->Status =~ /^(?:queued|running)$/)
- {
- $self->SetRefreshInterval(30);
- }
-}
-
-sub GetPageTitle($)
-{
- my ($self) = @_;
-
- my $PageTitle = $self->{Job}->Remarks;
- $PageTitle =~ s/^[[]\Q$PatchesMailingList\E[]] //;
- $PageTitle = "Job " . $self->{JobId} if ($PageTitle eq "");
- $PageTitle .= " - ${ProjectName} Test Bot";
- return $PageTitle;
+ return StepsTasksBlock->new($Collection, $EnclosingPage);
}
-sub GetTitle($)
-{
- my ($self) = @_;
-
- return "Job " . $self->{JobId} . " - " . $self->{Job}->Remarks;
-}
+#
+# Individual item property support
+#
-sub DisplayProperty($$$)
+sub DisplayProperty($$)
{
- my ($self, $CollectionBlock, $PropertyDescriptor) = @_;
+ my ($self, $PropertyDescriptor) = @_;
my $PropertyName = $PropertyDescriptor->GetName();
-
return $PropertyName eq "StepNo" || $PropertyName eq "TaskNo" ||
$PropertyName eq "Status" || $PropertyName eq "VM" ||
$PropertyName eq "Timeout" || $PropertyName eq "FileName" ||
@@ -94,9 +56,22 @@ sub DisplayProperty($$$)
$PropertyName eq "Ended" || $PropertyName eq "TestFailures";
}
-sub GenerateHeaderCell($$$)
+sub SortKeys($$)
{
- my ($self, $CollectionBlock, $PropertyDescriptor) = @_;
+ my ($self, $Keys) = @_;
+
+ my @SortedKeys = sort { $a <=> $b } @$Keys;
+ return \@SortedKeys;
+}
+
+
+#
+# Item cell generation
+#
+
+sub GenerateHeaderCell($$)
+{
+ my ($self, $PropertyDescriptor) = @_;
my $PropertyName = $PropertyDescriptor->GetName();
if ($PropertyName eq "CmdLineArg")
@@ -109,13 +84,104 @@ sub GenerateHeaderCell($$$)
}
else
{
- return $self->SUPER::GenerateHeaderCell($CollectionBlock, $PropertyDescriptor);
+ return $self->SUPER::GenerateHeaderCell($PropertyDescriptor);
+ }
+}
+
+sub GenerateDataCell($$$$)
+{
+ my ($self, $StepTask, $PropertyDescriptor, $DetailsPage) = @_;
+
+ my $PropertyName = $PropertyDescriptor->GetName();
+ if ($PropertyName eq "VM")
+ {
+ print "<td><a href='#k", $self->escapeHTML($StepTask->GetKey()), "'>";
+ print $self->escapeHTML($self->GetDisplayValue($StepTask, $PropertyDescriptor));
+ print "</a></td>\n";
+ }
+ elsif ($PropertyName eq "FileName")
+ {
+ my $FileName = $StepTask->GetFullFileName();
+ if ($FileName and -r $FileName)
+ {
+ my $JobId = $self->{EnclosingPage}->GetJob()->Id;
+ my $URI = "/GetFile.pl?JobKey=" . uri_escape($JobId) .
+ "&StepKey=" . uri_escape($StepTask->StepNo);
+ print "<td><a href='" . $self->escapeHTML($URI) . "'>";
+ print $self->escapeHTML($self->GetDisplayValue($StepTask, $PropertyDescriptor));
+ print "</a></td>\n";
+ }
+ else
+ {
+ $self->SUPER::GenerateDataCell($StepTask, $PropertyDescriptor, $DetailsPage);
+ }
+ }
+ elsif ($PropertyName eq "CmdLineArg")
+ {
+ my $Args = $self->escapeHTML($StepTask->CmdLineArg);
+ if ($Args eq "" or $StepTask->VM->Type eq "wine")
+ {
+ $Args .= "<br>" if ($Args ne "");
+ my ($ErrMessage, $Missions) = ParseMissionStatement($StepTask->Missions);
+ if (defined $ErrMessage)
+ {
+ $Args .= "<span class='Mission'>$ErrMessage</span>";
+ }
+ else
+ {
+ $Args .= "<span class='Mission'>". $self->escapeHTML(GetTaskMissionDescription($Missions->[0], $StepTask->Type)) ."</span>";
+ }
+ }
+ print "<td>$Args</td>\n";
+ }
+ elsif ($PropertyName eq "Ended")
+ {
+ if (defined $StepTask->Ended)
+ {
+ my $Duration = $StepTask->Ended - $StepTask->Started;
+ my $TagId = "E". $StepTask->Id;
+ print "<td><a id='$TagId' class='title' title='",
+ strftime("%Y-%m-%d %H:%M:%S", localtime($StepTask->Ended)),
+ "'>", DurationToString($Duration), "</a>\n";
+ print "<script type='text/javascript'><!--\n";
+ print " ShowDateTime(", $StepTask->Ended, ",'$TagId');\n";
+ print "--></script>\n";
+ print "</td>\n";
+ }
+ else
+ {
+ print "<td> </td>\n";
+ }
+ }
+ else
+ {
+ $self->SUPER::GenerateDataCell($StepTask, $PropertyDescriptor, $DetailsPage);
}
}
-sub GetItemActions($$)
+
+#
+# Per-item actions handling
+#
+
+sub GetItemActions($)
{
- #my ($self, $CollectionBlock) = @_;
+ #my ($self) = @_;
+ return [];
+}
+
+
+#
+# Actions handling
+#
+
+sub GetActions($)
+{
+ my ($self) = @_;
+
+ # These are mutually exclusive
+ return ["Cancel job"] if (!defined $self->CanCancel());
+ return ["Restart job"] if (!defined $self->CanRestart());
return [];
}
@@ -123,20 +189,21 @@ sub CanCancel($)
{
my ($self) = @_;
- my $Status = $self->{Job}->Status;
+ my $Job = $self->{EnclosingPage}->GetJob();
+ my $Status = $Job->Status;
if ($Status ne "queued" && $Status ne "running")
{
- return "Job already $Status";
+ return "Job already $Status";
}
- my $Session = $self->GetCurrentSession();
+ my $Session = $self->{EnclosingPage}->GetCurrentSession();
if (! defined($Session))
{
return "You are not authorized to cancel this job";
}
my $CurrentUser = $Session->User;
if (! $CurrentUser->HasRole("admin") &&
- $self->{Job}->User->GetKey() ne $CurrentUser->GetKey())
+ $Job->User->GetKey() ne $CurrentUser->GetKey())
{
return "You are not authorized to cancel this job";
}
@@ -148,20 +215,21 @@ sub CanRestart($)
{
my ($self) = @_;
- my $Status = $self->{Job}->Status;
+ my $Job = $self->{EnclosingPage}->GetJob();
+ my $Status = $Job->Status;
if ($Status ne "boterror" && $Status ne "canceled")
{
return "Not a failed / canceled Job";
}
- my $Session = $self->GetCurrentSession();
+ my $Session = $self->{EnclosingPage}->GetCurrentSession();
if (! defined($Session))
{
return "You are not authorized to restart this job";
}
my $CurrentUser = $Session->User;
if (! $CurrentUser->HasRole("admin") &&
- $self->{Job}->User->GetKey() ne $CurrentUser->GetKey()) # FIXME: Admin only?
+ $Job->User->GetKey() ne $CurrentUser->GetKey()) # FIXME: Admin only?
{
return "You are not authorized to restart this job";
}
@@ -169,35 +237,26 @@ sub CanRestart($)
return undef;
}
-sub GetActions($$)
-{
- my ($self, $CollectionBlock) = @_;
-
- # These are mutually exclusive
- return ["Cancel job"] if (!defined $self->CanCancel());
- return ["Restart job"] if (!defined $self->CanRestart());
- return [];
-}
-
sub OnCancel($)
{
my ($self) = @_;
my $ErrMessage = $self->CanCancel();
- if (defined($ErrMessage))
+ if (defined $ErrMessage)
{
- $self->{ErrMessage} = $ErrMessage;
+ $self->{EnclosingPage}->SetError(undef, $ErrMessage);
return !1;
}
- $ErrMessage = JobCancel($self->{JobId});
- if (defined($ErrMessage))
+ my $JobId = $self->{EnclosingPage}->GetJob()->Id;
+ $ErrMessage = JobCancel($JobId);
+ if (defined $ErrMessage)
{
- $self->{ErrMessage} = $ErrMessage;
+ $self->{EnclosingPage}->SetError(undef, $ErrMessage);
return !1;
}
- exit($self->Redirect("/JobDetails.pl?Key=" . $self->{JobId}));
+ exit($self->{EnclosingPage}->Redirect("/JobDetails.pl?Key=$JobId"));
}
sub OnRestart($)
@@ -205,44 +264,89 @@ sub OnRestart($)
my ($self) = @_;
my $ErrMessage = $self->CanRestart();
- if (defined($ErrMessage))
+ if (defined $ErrMessage)
{
- $self->{ErrMessage} = $ErrMessage;
+ $self->{EnclosingPage}->SetError(undef, $ErrMessage);
return !1;
}
- $ErrMessage = JobRestart($self->{JobId});
- if (defined($ErrMessage))
+ my $JobId = $self->{EnclosingPage}->GetJob()->Id;
+ $ErrMessage = JobRestart($JobId);
+ if (defined $ErrMessage)
{
- $self->{ErrMessage} = $ErrMessage;
+ $self->{EnclosingPage}->SetError(undef, $ErrMessage);
return !1;
}
- exit($self->Redirect("/JobDetails.pl?Key=" . $self->{JobId}));
+ exit($self->{EnclosingPage}->Redirect("/JobDetails.pl?Key=$JobId"));
}
-sub OnAction($$$)
+sub OnAction($$)
{
- my ($self, $CollectionBlock, $Action) = @_;
+ my ($self, $Action) = @_;
- if ($Action eq "Cancel job")
- {
- return $self->OnCancel();
- }
- elsif ($Action eq "Restart job")
+ return $Action eq "Cancel job" ? $self->OnCancel() :
+ $Action eq "Restart job" ? $self->OnRestart() :
+ $self->SUPER::OnAction($Action);
+}
+
+
+package JobDetailsPage;
+
+use ObjectModel::CGI::SimpleCollectionPage;
+our @ISA = qw(ObjectModel::CGI::SimpleCollectionPage);
+
+use URI::Escape;
+
+use WineTestBot::Config;
+use WineTestBot::Jobs;
+use WineTestBot::Log; # For Elapsed()
+use WineTestBot::LogUtils;
+use WineTestBot::StepsTasks;
+
+
+sub _initialize($$$)
+{
+ my ($self, $Request, $RequiredRole) = @_;
+ $self->{start} = Time();
+
+ $self->{JobId} = $self->GetParam("Key");
+ $self->{JobId} = $self->GetParam("JobId") if (!defined $self->{JobId});
+
+ $self->{Job} = CreateJobs()->GetItem($self->{JobId});
+ exit($self->Redirect("/")) if (!defined $self->{Job});
+
+ my $Collection = CreateStepsTasks(undef, $self->{Job});
+ $self->SUPER::_initialize($Request, $RequiredRole, $Collection, \&StepsTasksBlock::Create);
+ if ($self->{Job}->Status =~ /^(?:queued|running)$/)
{
- return $self->OnRestart();
+ $self->SetRefreshInterval(30);
}
+}
+
+sub GetJob($)
+{
+ my ($self) = @_;
- return $self->SUPER::OnAction($CollectionBlock, $Action);
+ return $self->{Job};
}
-sub SortKeys($$$)
+sub GetPageTitle($)
{
- my ($self, $CollectionBlock, $Keys) = @_;
+ my ($self) = @_;
- my @SortedKeys = sort { $a <=> $b } @$Keys;
- return \@SortedKeys;
+ my $PageTitle = $self->{Job}->Remarks;
+ $PageTitle =~ s/^[[]\Q$PatchesMailingList\E[]] //;
+ $PageTitle = "Job " . $self->{JobId} if ($PageTitle eq "");
+ $PageTitle .= " - ${ProjectName} Test Bot";
+ return $PageTitle;
+}
+
+sub GetTitle($)
+{
+ my ($self) = @_;
+
+ return "Job $self->{JobId} - ". $self->{Job}->Remarks;
}
sub InitMoreInfo($)
@@ -250,7 +354,7 @@ sub InitMoreInfo($)
my ($self) = @_;
my $More = $self->{More} = {};
- my $Keys = $self->SortKeys(undef, $self->{Collection}->GetKeys());
+ my $Keys = $self->{CollectionBlock}->SortKeys($self->{Collection}->GetKeys());
foreach my $Key (@$Keys)
{
my $StepTask = $self->{Collection}->GetItem($Key);
@@ -458,7 +562,7 @@ function HideLog(event, url)
EOF
print "<div class='Content'>\n";
- my $Keys = $self->SortKeys(undef, $self->{Collection}->GetKeys());
+ my $Keys = $self->{CollectionBlock}->SortKeys($self->{Collection}->GetKeys());
my $KeyIndex = 0;
foreach my $Key (@$Keys)
{
@@ -627,78 +731,6 @@ EOF
print "</div>\n";
}
-sub GenerateDataCell($$$$$)
-{
- my ($self, $CollectionBlock, $StepTask, $PropertyDescriptor, $DetailsPage) = @_;
-
- my $PropertyName = $PropertyDescriptor->GetName();
- if ($PropertyName eq "VM")
- {
- print "<td><a href='#k", $self->escapeHTML($StepTask->GetKey()), "'>";
- print $self->escapeHTML($self->GetDisplayValue($CollectionBlock, $StepTask,
- $PropertyDescriptor));
- print "</a></td>\n";
- }
- elsif ($PropertyName eq "FileName")
- {
- my $FileName = $StepTask->GetFullFileName();
- if ($FileName and -r $FileName)
- {
- my $URI = "/GetFile.pl?JobKey=" . uri_escape($self->{JobId}) .
- "&StepKey=" . uri_escape($StepTask->StepNo);
- print "<td><a href='" . $self->escapeHTML($URI) . "'>";
- print $self->escapeHTML($self->GetDisplayValue($CollectionBlock, $StepTask,
- $PropertyDescriptor));
- print "</a></td>\n";
- }
- else
- {
- $self->SUPER::GenerateDataCell($CollectionBlock, $StepTask, $PropertyDescriptor, $DetailsPage);
- }
- }
- elsif ($PropertyName eq "CmdLineArg")
- {
- my $Args = $self->escapeHTML($StepTask->CmdLineArg);
- if ($Args eq "" or $StepTask->VM->Type eq "wine")
- {
- $Args .= "<br>" if ($Args ne "");
- my ($ErrMessage, $Missions) = ParseMissionStatement($StepTask->Missions);
- if (defined $ErrMessage)
- {
- $Args .= "<span class='Mission'>$ErrMessage</span>";
- }
- else
- {
- $Args .= "<span class='Mission'>". $self->escapeHTML(GetTaskMissionDescription($Missions->[0], $StepTask->Type)) ."</span>";
- }
- }
- print "<td>$Args</td>\n";
- }
- elsif ($PropertyName eq "Ended")
- {
- if (defined $StepTask->Ended)
- {
- my $Duration = $StepTask->Ended - $StepTask->Started;
- my $TagId = "E". $StepTask->Id;
- print "<td><a id='$TagId' class='title' title='",
- strftime("%Y-%m-%d %H:%M:%S", localtime($StepTask->Ended)),
- "'>", DurationToString($Duration), "</a>\n";
- print "<script type='text/javascript'><!--\n";
- print " ShowDateTime(", $StepTask->Ended, ",'$TagId');\n";
- print "--></script>\n";
- print "</td>\n";
- }
- else
- {
- print "<td> </td>\n";
- }
- }
- else
- {
- $self->SUPER::GenerateDataCell($CollectionBlock, $StepTask, $PropertyDescriptor, $DetailsPage);
- }
-}
-
sub GenerateFooter($)
{
my ($self) = @_;
--
2.30.2
March 31, 2022
[tools] testbot: Fix the spelling of a couple of Perl POD entries.
by Francois Gouget
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/lib/ObjectModel/CGI/CollectionBlock.pm | 2 +-
testbot/lib/ObjectModel/CGI/Page.pm | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/testbot/lib/ObjectModel/CGI/CollectionBlock.pm b/testbot/lib/ObjectModel/CGI/CollectionBlock.pm
index 58ece69f3..9a52f11bc 100644
--- a/testbot/lib/ObjectModel/CGI/CollectionBlock.pm
+++ b/testbot/lib/ObjectModel/CGI/CollectionBlock.pm
@@ -37,7 +37,7 @@ Also, because this is only one part of a web page, some methods, such as those
dealing with errors, are delegated to the EnclosingPage object which must
implement the ObjectModel::CGI::Page interface.
-Other methods are designed so they can be overriden by the enclosing page as
+Other methods are designed so they can be overridden by the enclosing page as
a way to allow it to modify how the collection block looks or behaves. These
methods can be identified by their CallXxx() trampoline. The override
mechanism works as follows:
diff --git a/testbot/lib/ObjectModel/CGI/Page.pm b/testbot/lib/ObjectModel/CGI/Page.pm
index a79155950..0879557ad 100644
--- a/testbot/lib/ObjectModel/CGI/Page.pm
+++ b/testbot/lib/ObjectModel/CGI/Page.pm
@@ -360,7 +360,7 @@ sub GetPageTitle($)
=head1 C<GetTitle()>
This returns the title for the current web page or email section.
-Note that this may not be valid HTML and thus my need escaping.
+Note that this may not be valid HTML and thus may need escaping.
=back
=cut
--
2.30.2
March 31, 2022
Re: [PATCH v3 4/6] win32u: Move process_sent_messages implementation from user32.
by Marvin
Hi,
While running your changed tests, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=111668
Your paranoid android.
=== debian11 (32 bit report) ===
user32:
win.c:11606: Test failed: 1: hwnd 00BE00AE is still topmost
win.c:11606: Test failed: 2: hwnd 00B700C0 is still topmost
win.c:11606: Test failed: 1: hwnd 00BE00AE is still topmost
win.c:11606: Test failed: 2: hwnd 00B700C0 is still topmost
win.c:11606: Test failed: 1: hwnd 00BE00AE is still topmost
win.c:11606: Test failed: 2: hwnd 00B700C0 is still topmost
win.c:11763: Test failed: 007800F8: expected NOT topmost
win.c:11787: Test failed: 007800F8: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 00BE00AE is still topmost
win.c:11606: Test failed: 2: hwnd 00B700C0 is still topmost
win.c:11606: Test failed: 3: hwnd 00070148 is still topmost
win.c:11606: Test failed: 4: hwnd 007800F8 is still topmost
win.c:11810: Test failed: 00BE00AE: expected NOT topmost
win.c:11811: Test failed: 007800F8: expected next 00070148, got 00000000
win.c:11811: Test failed: 007800F8: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 00BE00AE is still topmost
win.c:11606: Test failed: 2: hwnd 00B700C0 is still topmost
win.c:11606: Test failed: 3: hwnd 00070148 is still topmost
win.c:11606: Test failed: 4: hwnd 007800F8 is still topmost
win.c:11834: Test failed: 00BE00AE: expected NOT topmost
win.c:11835: Test failed: 007800F8: expected next 00070148, got 00000000
win.c:11835: Test failed: 007800F8: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 00BE00AE is still topmost
win.c:11606: Test failed: 2: hwnd 00B700C0 is still topmost
win.c:11606: Test failed: 3: hwnd 00070148 is still topmost
win.c:11606: Test failed: 4: hwnd 007800F8 is still topmost
win.c:11869: Test failed: 007800F8: expected next 00070148, got 00000000
win.c:11869: Test failed: 007800F8: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 00BE00AE is still topmost
win.c:11606: Test failed: 2: hwnd 00B700C0 is still topmost
win.c:11606: Test failed: 3: hwnd 00070148 is still topmost
win.c:11606: Test failed: 4: hwnd 007800F8 is still topmost
win.c:11892: Test failed: 007800F8: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 00BE00AE is still topmost
win.c:11606: Test failed: 2: hwnd 00B700C0 is still topmost
win.c:11606: Test failed: 3: hwnd 00070148 is still topmost
win.c:11606: Test failed: 4: hwnd 007800F8 is still topmost
win.c:11903: Test failed: 007800F8: expected next 00070148, got 00000000
win.c:11903: Test failed: 007800F8: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 00BE00AE is still topmost
win.c:11606: Test failed: 2: hwnd 00B700C0 is still topmost
win.c:11606: Test failed: 3: hwnd 00070148 is still topmost
win.c:11606: Test failed: 4: hwnd 007800F8 is still topmost
win.c:11606: Test failed: 1: hwnd 00BE00AE is still topmost
win.c:11606: Test failed: 2: hwnd 00B700C0 is still topmost
win.c:11606: Test failed: 3: hwnd 00070148 is still topmost
win.c:11606: Test failed: 4: hwnd 007800F8 is still topmost
win.c:11606: Test failed: 1: hwnd 00BE00AE is still topmost
win.c:11606: Test failed: 2: hwnd 00B700C0 is still topmost
win.c:11606: Test failed: 3: hwnd 00070148 is still topmost
win.c:11606: Test failed: 4: hwnd 007800F8 is still topmost
=== debian11 (32 bit Chinese:China report) ===
user32:
input.c:2793: Test failed: 4: unexpected WM_MOUSEMOVE message
input.c:2521: Test failed: 9: foreground process expected WM_MOUSEMOVE message
input.c:2804: Test failed: 9: Unexpected cursor movement
input.c:2521: Test failed: 10: foreground process expected WM_MOUSEMOVE message
input.c:2521: Test failed: 11: foreground process expected WM_MOUSEMOVE message
input.c:2521: Test failed: 12: foreground process expected WM_MOUSEMOVE message
input.c:1733: Test failed: expected to get 64 mouse move points but got -1
input.c:1744: Test failed: expected to get 64 mouse move points but got -1
win.c:11344: Test failed: expected 00D200B0, got 003C0138
win.c:11361: Test failed: expected 00D200B0, got 003C0138
=== debian11 (32 bit WoW report) ===
user32:
input.c:2160: Test failed: GetRawInputBuffer returned 6
input.c:2182: Test failed: Unexpected rawinput data: -8
input.c:2160: Test failed: GetRawInputBuffer returned 7
input.c:2160: Test failed: GetRawInputBuffer returned 1
input.c:2222: Test failed: GetRawInputData succeeded
input.c:2223: Test failed: GetRawInputData returned deadbeef
input.c:2160: Test failed: GetRawInputBuffer returned 1
input.c:2164: Test failed: Unexpected rawinput data: 0
input.c:1628: Test failed: wrong position 5, expected 61x122 got 62x124
input.c:1628: Test failed: wrong position 7, expected 59x118 got 61x122
input.c:1628: Test failed: wrong position 9, expected 57x114 got 60x120
input.c:1628: Test failed: wrong position 11, expected 55x110 got 59x118
input.c:1628: Test failed: wrong position 13, expected 53x106 got 58x116
input.c:1628: Test failed: wrong position 15, expected 51x102 got 57x114
input.c:1628: Test failed: wrong position 16, expected 50x100 got 58x116
input.c:1628: Test failed: wrong position 17, expected 49x98 got 56x112
input.c:1628: Test failed: wrong position 21, expected 45x90 got 54x108
input.c:1628: Test failed: wrong position 23, expected 43x86 got 53x106
input.c:1628: Test failed: wrong position 25, expected 41x82 got 52x104
input.c:1628: Test failed: wrong position 30, expected 36x72 got 51x102
input.c:1628: Test failed: wrong position 31, expected 35x70 got 49x98
input.c:1628: Test failed: wrong position 33, expected 33x66 got 48x96
input.c:1628: Test failed: wrong position 35, expected 31x62 got 47x94
input.c:1628: Test failed: wrong position 36, expected 30x60 got 48x96
input.c:1628: Test failed: wrong position 37, expected 29x58 got 46x92
input.c:1628: Test failed: wrong position 38, expected 28x56 got 47x94
input.c:1628: Test failed: wrong position 39, expected 27x54 got 45x90
input.c:1628: Test failed: wrong position 42, expected 24x48 got 45x90
input.c:1628: Test failed: wrong position 43, expected 23x46 got 43x86
input.c:1628: Test failed: wrong position 44, expected 22x44 got 44x88
input.c:1628: Test failed: wrong position 45, expected 21x42 got 42x84
input.c:1628: Test failed: wrong position 47, expected 19x38 got 41x82
input.c:1628: Test failed: wrong position 48, expected 18x36 got 42x84
input.c:1628: Test failed: wrong position 49, expected 17x34 got 40x80
input.c:1628: Test failed: wrong position 51, expected 15x30 got 39x78
input.c:1628: Test failed: wrong position 53, expected 13x26 got 38x76
input.c:1628: Test failed: wrong position 55, expected 11x22 got 37x74
input.c:1628: Test failed: wrong position 57, expected 9x18 got 36x72
=== debian11 (64 bit WoW report) ===
user32:
win.c:11361: Test failed: expected 0000000000BF010C, got 000000000011015E
win.c:11606: Test failed: 1: hwnd 0000000000280082 is still topmost
win.c:11606: Test failed: 2: hwnd 00000000003100CE is still topmost
win.c:11606: Test failed: 1: hwnd 0000000000280082 is still topmost
win.c:11606: Test failed: 2: hwnd 00000000003100CE is still topmost
win.c:11606: Test failed: 1: hwnd 0000000000280082 is still topmost
win.c:11606: Test failed: 2: hwnd 00000000003100CE is still topmost
win.c:11763: Test failed: 00000000007400F8: expected NOT topmost
win.c:11787: Test failed: 00000000007400F8: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 0000000000280082 is still topmost
win.c:11606: Test failed: 2: hwnd 00000000003100CE is still topmost
win.c:11606: Test failed: 3: hwnd 0000000000070148 is still topmost
win.c:11606: Test failed: 4: hwnd 00000000007400F8 is still topmost
win.c:11810: Test failed: 0000000000280082: expected NOT topmost
win.c:11811: Test failed: 00000000007400F8: expected next 0000000000070148, got 0000000000000000
win.c:11811: Test failed: 00000000007400F8: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 0000000000280082 is still topmost
win.c:11606: Test failed: 2: hwnd 00000000003100CE is still topmost
win.c:11606: Test failed: 3: hwnd 0000000000070148 is still topmost
win.c:11606: Test failed: 4: hwnd 00000000007400F8 is still topmost
win.c:11834: Test failed: 0000000000280082: expected NOT topmost
win.c:11835: Test failed: 00000000007400F8: expected next 0000000000070148, got 0000000000000000
win.c:11835: Test failed: 00000000007400F8: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 0000000000280082 is still topmost
win.c:11606: Test failed: 2: hwnd 00000000003100CE is still topmost
win.c:11606: Test failed: 3: hwnd 0000000000070148 is still topmost
win.c:11606: Test failed: 4: hwnd 00000000007400F8 is still topmost
win.c:11869: Test failed: 00000000007400F8: expected next 0000000000070148, got 0000000000000000
win.c:11869: Test failed: 00000000007400F8: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 0000000000280082 is still topmost
win.c:11606: Test failed: 2: hwnd 00000000003100CE is still topmost
win.c:11606: Test failed: 3: hwnd 0000000000070148 is still topmost
win.c:11606: Test failed: 4: hwnd 00000000007400F8 is still topmost
win.c:11892: Test failed: 00000000007400F8: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 0000000000280082 is still topmost
win.c:11606: Test failed: 2: hwnd 00000000003100CE is still topmost
win.c:11606: Test failed: 3: hwnd 0000000000070148 is still topmost
win.c:11606: Test failed: 4: hwnd 00000000007400F8 is still topmost
win.c:11903: Test failed: 00000000007400F8: expected next 0000000000070148, got 0000000000000000
win.c:11903: Test failed: 00000000007400F8: expected NOT topmost
win.c:11606: Test failed: 1: hwnd 0000000000280082 is still topmost
win.c:11606: Test failed: 2: hwnd 00000000003100CE is still topmost
win.c:11606: Test failed: 3: hwnd 0000000000070148 is still topmost
win.c:11606: Test failed: 4: hwnd 00000000007400F8 is still topmost
win.c:11606: Test failed: 1: hwnd 0000000000280082 is still topmost
win.c:11606: Test failed: 2: hwnd 00000000003100CE is still topmost
win.c:11606: Test failed: 3: hwnd 0000000000070148 is still topmost
win.c:11606: Test failed: 4: hwnd 00000000007400F8 is still topmost
win.c:11606: Test failed: 1: hwnd 0000000000280082 is still topmost
win.c:11606: Test failed: 2: hwnd 00000000003100CE is still topmost
win.c:11606: Test failed: 3: hwnd 0000000000070148 is still topmost
win.c:11606: Test failed: 4: hwnd 00000000007400F8 is still topmost
March 31, 2022
[PATCH 2/2] riched20: Implement callback to IRichEditOleCallback_QueryInsertObject.
by Jinoh Kang
Signed-off-by: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
---
dlls/riched20/caret.c | 11 ++++++++++-
dlls/riched20/editor.c | 3 +--
dlls/riched20/editor.h | 2 +-
dlls/riched20/richole.c | 6 +++++-
dlls/riched20/tests/richole.c | 6 ++----
5 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c
index c8658098e18..09ec0ffc735 100644
--- a/dlls/riched20/caret.c
+++ b/dlls/riched20/caret.c
@@ -456,13 +456,21 @@ static struct re_object* create_re_object(const REOBJECT *reo, ME_Run *run)
return reobj;
}
-void editor_insert_oleobj(ME_TextEditor *editor, const REOBJECT *reo)
+HRESULT editor_insert_oleobj(ME_TextEditor *editor, const REOBJECT *reo)
{
ME_Run *run, *prev;
const WCHAR space = ' ';
struct re_object *reobj_prev = NULL;
ME_Cursor *cursor, cursor_from_ofs;
ME_Style *style;
+ HRESULT hr;
+
+ if (editor->lpOleCallback)
+ {
+ hr = IRichEditOleCallback_QueryInsertObject(editor->lpOleCallback, (LPCLSID)&reo->clsid, reo->pstg, REO_CP_SELECTION);
+ if (hr != S_OK)
+ return hr;
+ }
if (reo->cp == REO_CP_SELECTION)
cursor = editor->pCursors;
@@ -495,6 +503,7 @@ void editor_insert_oleobj(ME_TextEditor *editor, const REOBJECT *reo)
list_add_head(&editor->reobj_list, &run->reobj->entry);
ME_ReleaseStyle( style );
+ return S_OK;
}
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index a8cf3175591..3628e51ac9b 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -1171,8 +1171,7 @@ static HRESULT insert_static_object(ME_TextEditor *editor, HENHMETAFILE hemf, HB
reobject.dwFlags = 0; /* FIXME */
reobject.dwUser = 0;
- editor_insert_oleobj(editor, &reobject);
- hr = S_OK;
+ hr = editor_insert_oleobj(editor, &reobject);
}
if (lpObject) IOleObject_Release(lpObject);
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index e0df63ae92d..3028d9bdbd5 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -187,7 +187,7 @@ int ME_GetSelection(ME_TextEditor *editor, ME_Cursor **from, ME_Cursor **to) DEC
BOOL ME_IsSelection(ME_TextEditor *editor) DECLSPEC_HIDDEN;
void ME_DeleteSelection(ME_TextEditor *editor) DECLSPEC_HIDDEN;
void ME_SendSelChange(ME_TextEditor *editor) DECLSPEC_HIDDEN;
-void editor_insert_oleobj( ME_TextEditor *editor, const REOBJECT *reo ) DECLSPEC_HIDDEN;
+HRESULT editor_insert_oleobj( ME_TextEditor *editor, const REOBJECT *reo ) DECLSPEC_HIDDEN;
BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start, int nChars, BOOL bForce) DECLSPEC_HIDDEN;
int ME_GetTextLength(ME_TextEditor *editor) DECLSPEC_HIDDEN;
int ME_GetTextLengthEx(ME_TextEditor *editor, const GETTEXTLENGTHEX *how) DECLSPEC_HIDDEN;
diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c
index a23f4c82730..936f1c928b3 100644
--- a/dlls/riched20/richole.c
+++ b/dlls/riched20/richole.c
@@ -1361,6 +1361,7 @@ static HRESULT WINAPI
IRichEditOle_fnInsertObject(IRichEditOle *iface, REOBJECT *reo)
{
struct text_services *services = impl_from_IRichEditOle( iface );
+ HRESULT hr;
TRACE("(%p,%p)\n", services, reo);
@@ -1369,7 +1370,10 @@ IRichEditOle_fnInsertObject(IRichEditOle *iface, REOBJECT *reo)
if (reo->cbStruct < sizeof(*reo)) return STG_E_INVALIDPARAMETER;
- editor_insert_oleobj(services->editor, reo);
+ hr = editor_insert_oleobj(services->editor, reo);
+ if (hr != S_OK)
+ return hr;
+
ME_CommitUndo(services->editor);
ME_UpdateRepaint(services->editor, FALSE);
return S_OK;
diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c
index bb99a9a7276..75671bb4482 100644
--- a/dlls/riched20/tests/richole.c
+++ b/dlls/riched20/tests/richole.c
@@ -3403,7 +3403,7 @@ static void _insert_reobject(struct IRichEditOleCallbackImpl *callback, IRichEdi
IOleClientSite *clientsite;
HRESULT hr;
- olecb_expect_QueryInsertObject(callback, line, EXPECT_TODO_WINE | 1, &CLSID_NULL, NULL, REO_CP_SELECTION /* cp overriden */, S_OK);
+ olecb_expect_QueryInsertObject(callback, line, 1, &CLSID_NULL, NULL, REO_CP_SELECTION /* cp overriden */, S_OK);
hr = IRichEditOle_GetClientSite(reole, &clientsite);
ok_(__FILE__,line)(hr == S_OK, "IRichEditOle_GetClientSite got hr %#lx.\n", hr);
fill_reobject_struct(reobj, cp, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, user);
@@ -3477,17 +3477,15 @@ static void subtest_InsertObject(struct IRichEditOleCallbackImpl *callback)
hr = IRichEditOle_GetClientSite(reole, &clientsite);
ok(hr == S_OK, "IRichEditOle_GetClientSite got hr %#lx.\n", hr);
- olecb_expect_QueryInsertObject(callback, __LINE__, EXPECT_TODO_WINE | 1, &CLSID_NULL, NULL, REO_CP_SELECTION, S_FALSE);
+ olecb_expect_QueryInsertObject(callback, __LINE__, 1, &CLSID_NULL, NULL, REO_CP_SELECTION, S_FALSE);
fill_reobject_struct(&reobj, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 0);
hr = IRichEditOle_InsertObject(reole, &reobj);
- todo_wine
ok(hr == S_FALSE, "IRichEditOle_InsertObject got hr %#lx.\n", hr);
olecb_check_QueryInsertObject(callback, __LINE__);
IOleClientSite_Release(clientsite);
count = IRichEditOle_GetObjectCount(reole);
- todo_wine
ok(count == 3, "got wrong object count: %ld\n", count);
}
--
2.34.1
March 31, 2022
[PATCH 1/2] riched20/tests: Add tests for IRichEditOleCallback_QueryInsertObject.
by Jinoh Kang
Signed-off-by: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
---
dlls/riched20/tests/richole.c | 247 ++++++++++++++++++++++++++++++++--
1 file changed, 236 insertions(+), 11 deletions(-)
diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c
index 24284a24484..bb99a9a7276 100644
--- a/dlls/riched20/tests/richole.c
+++ b/dlls/riched20/tests/richole.c
@@ -33,6 +33,169 @@
#include <tom.h>
#include <wine/test.h>
+#define EXPECT_TODO_WINE 0x80000000UL
+
+typedef struct IRichEditOleCallbackImpl {
+ IRichEditOleCallback IRichEditOleCallback_iface;
+ LONG ref;
+ int line;
+
+ ULONG expect_queryinsertobject;
+
+ const CLSID *lpclsid;
+ LPSTORAGE lpstg;
+ LONG cp;
+ HRESULT queryinsertobject_result;
+};
+
+static inline struct IRichEditOleCallbackImpl *impl_from_IRichEditOleCallback(IRichEditOleCallback *iface)
+{
+ return CONTAINING_RECORD(iface, struct IRichEditOleCallbackImpl, IRichEditOleCallback_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_QueryInterface(IRichEditOleCallback *iface, REFIID riid, void **ppvObj)
+{
+ if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IRichEditOleCallback)) {
+ IRichEditOleCallback_AddRef(iface);
+ *ppvObj = iface;
+ return S_OK;
+ }
+ *ppvObj = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE RichEditOleCallbackImpl_AddRef(IRichEditOleCallback *iface)
+{
+ struct IRichEditOleCallbackImpl *This = impl_from_IRichEditOleCallback(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+ return ref;
+}
+
+static ULONG STDMETHODCALLTYPE RichEditOleCallbackImpl_Release(IRichEditOleCallback *iface)
+{
+ struct IRichEditOleCallbackImpl *This = impl_from_IRichEditOleCallback(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+ if (!ref) free(This);
+ return ref;
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_GetNewStorage(IRichEditOleCallback *iface, LPSTORAGE *lplpstg)
+{
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_GetInPlaceContext(IRichEditOleCallback *iface, LPOLEINPLACEFRAME *lplpFrame, LPOLEINPLACEUIWINDOW *lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo)
+{
+ return E_INVALIDARG;
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_ShowContainerUI(IRichEditOleCallback *iface, BOOL fShow)
+{
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_QueryInsertObject(IRichEditOleCallback *iface, LPCLSID lpclsid, LPSTORAGE lpstg, LONG cp)
+{
+ struct IRichEditOleCallbackImpl *This = impl_from_IRichEditOleCallback(iface);
+ ULONG expect = This->expect_queryinsertobject;
+
+ todo_wine_if(expect & EXPECT_TODO_WINE)
+ ok_(__FILE__,This->line)( expect & ~EXPECT_TODO_WINE, "unexpected call to IRichEditOleCallback_QueryInsertObject\n");
+ if (!(expect & ~EXPECT_TODO_WINE)) return S_OK;
+ This->expect_queryinsertobject--;
+
+ if (This->lpclsid && lpclsid)
+ ok_(__FILE__,This->line)( IsEqualGUID(This->lpclsid, lpclsid), "QueryInsertObject lpclsid expected %s, got %s\n", wine_dbgstr_guid( This->lpclsid ), wine_dbgstr_guid( lpclsid ));
+ else
+ ok_(__FILE__,This->line)( This->lpclsid == lpclsid, "QueryInsertObject lpclsid expected %p, got %p\n", This->lpclsid, lpclsid );
+ ok_(__FILE__,This->line)( This->lpstg == lpstg, "QueryInsertObject lpstg expected %p, got %p\n", This->lpstg, lpstg );
+ ok_(__FILE__,This->line)( This->cp == cp, "QueryInsertObject cp expected %ld, got %ld\n", This->cp, cp );
+ return This->queryinsertobject_result;
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_DeleteObject(IRichEditOleCallback *iface, LPOLEOBJECT lpoleobj)
+{
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_QueryAcceptData(IRichEditOleCallback *iface, LPDATAOBJECT lpdataobj, CLIPFORMAT *lpcfFormat, DWORD reco, BOOL fReally, HGLOBAL hMetaPict)
+{
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_ContextSensitiveHelp(IRichEditOleCallback *iface, BOOL fEnterMode)
+{
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_GetClipboardData(IRichEditOleCallback *iface, CHARRANGE *lpchrg, DWORD reco, LPDATAOBJECT *lplpdataobj)
+{
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_GetDragDropEffect(IRichEditOleCallback *iface, BOOL fDrag, DWORD grfKeyState, LPDWORD pdwEffect)
+{
+ if (pdwEffect) *pdwEffect = DROPEFFECT_COPY;
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE RichEditOleCallbackImpl_GetContextMenu(IRichEditOleCallback *iface, WORD seltype, LPOLEOBJECT lpoleobj, CHARRANGE *lpchrg, HMENU *lphmenu)
+{
+ return E_NOTIMPL;
+}
+
+static const struct IRichEditOleCallbackVtbl RichEditOleCallbackImpl_Vtbl = {
+ RichEditOleCallbackImpl_QueryInterface,
+ RichEditOleCallbackImpl_AddRef,
+ RichEditOleCallbackImpl_Release,
+ RichEditOleCallbackImpl_GetNewStorage,
+ RichEditOleCallbackImpl_GetInPlaceContext,
+ RichEditOleCallbackImpl_ShowContainerUI,
+ RichEditOleCallbackImpl_QueryInsertObject,
+ RichEditOleCallbackImpl_DeleteObject,
+ RichEditOleCallbackImpl_QueryAcceptData,
+ RichEditOleCallbackImpl_ContextSensitiveHelp,
+ RichEditOleCallbackImpl_GetClipboardData,
+ RichEditOleCallbackImpl_GetDragDropEffect,
+ RichEditOleCallbackImpl_GetContextMenu,
+};
+
+static HRESULT RichEditOleCallbackImpl_Create(struct IRichEditOleCallbackImpl **objptr)
+{
+ struct IRichEditOleCallbackImpl *obj;
+
+ obj = calloc(sizeof(struct IRichEditOleCallbackImpl), 1);
+ if (!obj) return E_OUTOFMEMORY;
+
+ obj->IRichEditOleCallback_iface.lpVtbl = &RichEditOleCallbackImpl_Vtbl;
+ obj->ref = 1;
+
+ *objptr = obj;
+ return S_OK;
+}
+
+static void olecb_expect_QueryInsertObject(struct IRichEditOleCallbackImpl *This, int line, ULONG expect, const CLSID *lpclsid, LPSTORAGE lpstg, LONG cp, HRESULT result)
+{
+ if (!This) return;
+
+ This->line = line;
+ This->expect_queryinsertobject = expect;
+ This->lpclsid = lpclsid;
+ This->lpstg = lpstg;
+ This->cp = cp;
+ This->queryinsertobject_result = result;
+}
+
+static void olecb_check_QueryInsertObject(struct IRichEditOleCallbackImpl *This, int line)
+{
+ if (!This) return;
+
+ todo_wine_if(This->expect_queryinsertobject & EXPECT_TODO_WINE)
+ ok(!(This->expect_queryinsertobject & ~EXPECT_TODO_WINE), "expected IRichEditOleCallback_QueryInsertObject to be called\n");
+
+ olecb_expect_QueryInsertObject(This, 0, 0, NULL, NULL, 0, S_OK);
+}
+
static HMODULE hmoduleRichEdit;
DEFINE_GUID(GUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
@@ -3233,21 +3396,24 @@ static void _check_reobject_struct(IRichEditOle *reole, LONG index, DWORD flags,
ok_(__FILE__,line)(reobj.dwUser == user, "got wrong user-defined value.\n");
}
-#define INSERT_REOBJECT(reole,reobj,cp,user) \
- _insert_reobject(reole, reobj, cp, user, __LINE__)
-static void _insert_reobject(IRichEditOle *reole, REOBJECT *reobj, LONG cp, DWORD user, int line)
+#define INSERT_REOBJECT(callback,reole,reobj,cp,user) \
+ _insert_reobject(callback, reole, reobj, cp, user, __LINE__)
+static void _insert_reobject(struct IRichEditOleCallbackImpl *callback, IRichEditOle *reole, REOBJECT *reobj, LONG cp, DWORD user, int line)
{
IOleClientSite *clientsite;
HRESULT hr;
+
+ olecb_expect_QueryInsertObject(callback, line, EXPECT_TODO_WINE | 1, &CLSID_NULL, NULL, REO_CP_SELECTION /* cp overriden */, S_OK);
hr = IRichEditOle_GetClientSite(reole, &clientsite);
ok_(__FILE__,line)(hr == S_OK, "IRichEditOle_GetClientSite got hr %#lx.\n", hr);
fill_reobject_struct(reobj, cp, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, user);
hr = IRichEditOle_InsertObject(reole, reobj);
ok_(__FILE__,line)(hr == S_OK, "IRichEditOle_InsertObject got hr %#lx.\n", hr);
IOleClientSite_Release(clientsite);
+ olecb_check_QueryInsertObject(callback, line);
}
-static void test_InsertObject(void)
+static void subtest_InsertObject(struct IRichEditOleCallbackImpl *callback)
{
static CHAR test_text1[] = "abcdefg";
IRichEditOle *reole = NULL;
@@ -3271,6 +3437,12 @@ static void test_InsertObject(void)
BSTR bstr;
create_interfaces(&hwnd, &reole, &doc, &selection);
+ if (callback)
+ {
+ LRESULT sendres = SendMessageA(hwnd, EM_SETOLECALLBACK, 0, (LPARAM)&callback->IRichEditOleCallback_iface);
+ ok( !!sendres, "EM_SETOLECALLBACK should succeed\n" );
+ }
+
SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
hr = IRichEditOle_InsertObject(reole, NULL);
@@ -3278,22 +3450,47 @@ static void test_InsertObject(void)
/* insert object1 in (0, 1)*/
SendMessageA(hwnd, EM_SETSEL, 0, 1);
- INSERT_REOBJECT(reole, &reo1, REO_CP_SELECTION, 1);
+ INSERT_REOBJECT(callback, reole, &reo1, REO_CP_SELECTION, 1);
count = IRichEditOle_GetObjectCount(reole);
ok(count == 1, "got wrong object count: %ld\n", count);
/* insert object2 in (2, 3)*/
SendMessageA(hwnd, EM_SETSEL, 2, 3);
- INSERT_REOBJECT(reole, &reo2, REO_CP_SELECTION, 2);
+ INSERT_REOBJECT(callback, reole, &reo2, REO_CP_SELECTION, 2);
count = IRichEditOle_GetObjectCount(reole);
ok(count == 2, "got wrong object count: %ld\n", count);
/* insert object3 in (1, 2)*/
SendMessageA(hwnd, EM_SETSEL, 1, 2);
- INSERT_REOBJECT(reole, &reo3, REO_CP_SELECTION, 3);
+ INSERT_REOBJECT(callback, reole, &reo3, REO_CP_SELECTION, 3);
count = IRichEditOle_GetObjectCount(reole);
ok(count == 3, "got wrong object count: %ld\n", count);
+ if (callback)
+ {
+ IOleClientSite *clientsite;
+ REOBJECT reobj;
+
+ /* (fail to) insert object1 in (3, 4)*/
+ SendMessageA(hwnd, EM_SETSEL, 3, 4);
+
+ hr = IRichEditOle_GetClientSite(reole, &clientsite);
+ ok(hr == S_OK, "IRichEditOle_GetClientSite got hr %#lx.\n", hr);
+
+ olecb_expect_QueryInsertObject(callback, __LINE__, EXPECT_TODO_WINE | 1, &CLSID_NULL, NULL, REO_CP_SELECTION, S_FALSE);
+ fill_reobject_struct(&reobj, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 0);
+ hr = IRichEditOle_InsertObject(reole, &reobj);
+ todo_wine
+ ok(hr == S_FALSE, "IRichEditOle_InsertObject got hr %#lx.\n", hr);
+ olecb_check_QueryInsertObject(callback, __LINE__);
+
+ IOleClientSite_Release(clientsite);
+
+ count = IRichEditOle_GetObjectCount(reole);
+ todo_wine
+ ok(count == 3, "got wrong object count: %ld\n", count);
+ }
+
/* tests below show that order of rebject (from 0 to 2) is: reo1,reo3,reo2 */
CHECK_REOBJECT_STRUCT(reole, 0, REO_GETOBJ_ALL_INTERFACES, 0, 0, NULL, NULL, reo1.polesite, 1);
CHECK_REOBJECT_STRUCT(reole, 1, REO_GETOBJ_ALL_INTERFACES, 0, 1, NULL, NULL, reo3.polesite, 3);
@@ -3371,8 +3568,8 @@ static void test_InsertObject(void)
SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
/* "abc|d|efg" */
- INSERT_REOBJECT(reole, &reo1, 3, 1);
- INSERT_REOBJECT(reole, &reo2, 5, 2);
+ INSERT_REOBJECT(callback, reole, &reo1, 3, 1);
+ INSERT_REOBJECT(callback, reole, &reo2, 5, 2);
SendMessageW(hwnd, EM_SETSEL, 2, 3);
result = SendMessageW(hwnd, EM_SELECTIONTYPE, 0, 0);
@@ -3473,8 +3670,8 @@ static void test_InsertObject(void)
ok(!result, "Got result %lx.\n", result);
/* "abc|d|efg" */
SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1);
- INSERT_REOBJECT(reole, &reo1, 3, 1);
- INSERT_REOBJECT(reole, &reo2, 5, 2);
+ INSERT_REOBJECT(callback, reole, &reo1, 3, 1);
+ INSERT_REOBJECT(callback, reole, &reo2, 5, 2);
expected_string = L"abc d efg";
charrange.cpMin = 0;
@@ -3551,9 +3748,37 @@ static void test_InsertObject(void)
ok(hr == S_OK, "Got hr %#lx.\n", hr);
todo_wine ok(result == 0xfffc, "Got char: %lc\n", (WCHAR)result);
+ if (callback)
+ {
+ LRESULT sendres = SendMessageA(hwnd, EM_SETOLECALLBACK, 0, 0);
+ ok( !!sendres, "EM_SETOLECALLBACK should succeed\n" );
+ }
+
release_interfaces(&hwnd, &reole, &doc, &selection);
}
+static void test_InsertObject(void)
+{
+ struct IRichEditOleCallbackImpl *callback;
+ HRESULT hr;
+ ULONG ref;
+
+ subtest_InsertObject(NULL);
+
+ hr = RichEditOleCallbackImpl_Create(&callback);
+ ok(SUCCEEDED(hr), "RichEditOleCallbackImpl_Create returned %#lx\n", hr);
+ if (SUCCEEDED(hr))
+ {
+ subtest_InsertObject(callback);
+ ref = IRichEditOleCallback_Release(&callback->IRichEditOleCallback_iface);
+ ok(ref == 0, "expected IRichEditOleCallback recount to be 0, got %lu\n", ref);
+ }
+ else
+ {
+ skip("cannot test InsertObject with callback\n");
+ }
+}
+
static void test_GetStoryLength(void)
{
static const CHAR test_text1[] = "TestSomeText";
--
2.34.1
March 31, 2022