2007-02-18 00:27:05 +01:00
|
|
|
/* Message Sequence Testing Code
|
|
|
|
*
|
|
|
|
* Copyright (C) 2007 James Hawkins
|
|
|
|
* Copyright (C) 2007 Lei Zhang
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <windows.h>
|
2018-02-15 09:00:08 +01:00
|
|
|
#include "wine/heap.h"
|
2007-02-18 00:27:05 +01:00
|
|
|
#include "wine/test.h"
|
|
|
|
|
|
|
|
/* undocumented SWP flags - from SDK 3.1 */
|
|
|
|
#define SWP_NOCLIENTSIZE 0x0800
|
|
|
|
#define SWP_NOCLIENTMOVE 0x1000
|
|
|
|
|
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
sent = 0x1,
|
|
|
|
posted = 0x2,
|
|
|
|
parent = 0x4,
|
|
|
|
wparam = 0x8,
|
|
|
|
lparam = 0x10,
|
|
|
|
defwinproc = 0x20,
|
|
|
|
beginpaint = 0x40,
|
|
|
|
optional = 0x80,
|
|
|
|
hook = 0x100,
|
2007-02-28 18:05:32 +01:00
|
|
|
winevent_hook =0x200,
|
2014-04-21 07:15:35 +02:00
|
|
|
id = 0x400,
|
|
|
|
custdraw = 0x800
|
2007-02-18 00:27:05 +01:00
|
|
|
} msg_flags_t;
|
|
|
|
|
|
|
|
struct message
|
|
|
|
{
|
|
|
|
UINT message; /* the WM_* code */
|
|
|
|
msg_flags_t flags; /* message props */
|
|
|
|
WPARAM wParam; /* expected value of wParam */
|
|
|
|
LPARAM lParam; /* expected value of lParam */
|
2009-05-11 23:16:12 +02:00
|
|
|
UINT id; /* extra message data: id of the window,
|
|
|
|
notify code etc. */
|
2014-04-21 07:15:35 +02:00
|
|
|
DWORD stage; /* custom draw stage */
|
2007-02-18 00:27:05 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
struct msg_sequence
|
|
|
|
{
|
|
|
|
int count;
|
|
|
|
int size;
|
|
|
|
struct message *sequence;
|
|
|
|
};
|
|
|
|
|
2009-08-23 10:39:27 +02:00
|
|
|
static void add_message(struct msg_sequence **seq, int sequence_index,
|
|
|
|
const struct message *msg)
|
|
|
|
{
|
|
|
|
struct msg_sequence *msg_seq = seq[sequence_index];
|
|
|
|
|
|
|
|
if (!msg_seq->sequence)
|
|
|
|
{
|
|
|
|
msg_seq->size = 10;
|
2018-02-15 09:00:08 +01:00
|
|
|
msg_seq->sequence = heap_alloc(msg_seq->size * sizeof (*msg_seq->sequence));
|
2009-08-23 10:39:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (msg_seq->count == msg_seq->size)
|
|
|
|
{
|
|
|
|
msg_seq->size *= 2;
|
2018-02-15 09:00:08 +01:00
|
|
|
msg_seq->sequence = heap_realloc(msg_seq->sequence, msg_seq->size * sizeof (*msg_seq->sequence));
|
2009-08-23 10:39:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
assert(msg_seq->sequence);
|
|
|
|
|
2014-04-21 07:15:35 +02:00
|
|
|
msg_seq->sequence[msg_seq->count] = *msg;
|
2009-08-23 10:39:27 +02:00
|
|
|
msg_seq->count++;
|
|
|
|
}
|
|
|
|
|
2010-11-06 09:54:12 +01:00
|
|
|
static inline void flush_sequence(struct msg_sequence **seg, int sequence_index)
|
2009-08-23 10:39:27 +02:00
|
|
|
{
|
|
|
|
struct msg_sequence *msg_seq = seg[sequence_index];
|
2018-02-15 09:00:08 +01:00
|
|
|
heap_free(msg_seq->sequence);
|
2009-08-23 10:39:27 +02:00
|
|
|
msg_seq->sequence = NULL;
|
|
|
|
msg_seq->count = msg_seq->size = 0;
|
|
|
|
}
|
|
|
|
|
2010-11-06 09:54:12 +01:00
|
|
|
static inline void flush_sequences(struct msg_sequence **seq, int n)
|
2009-08-23 10:39:27 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
flush_sequence(seq, i);
|
|
|
|
}
|
|
|
|
|
2014-06-12 10:18:23 +02:00
|
|
|
static void dump_sequence( struct msg_sequence **seq, int sequence_index,
|
|
|
|
const struct message *expected, const char *context,
|
|
|
|
const char *file, int line )
|
|
|
|
{
|
|
|
|
struct msg_sequence *msg_seq = seq[sequence_index];
|
|
|
|
const struct message *actual, *sequence;
|
|
|
|
unsigned int count = 0;
|
|
|
|
|
|
|
|
sequence = msg_seq->sequence;
|
|
|
|
actual = sequence;
|
|
|
|
|
|
|
|
trace_(file, line)("Failed sequence %s:\n", context );
|
|
|
|
while (expected->message && actual->message)
|
|
|
|
{
|
2022-02-28 08:25:25 +01:00
|
|
|
trace_(file, line)( " %u: expected: %04x - actual: %04x wp %08Ix lp %08Ix\n",
|
2014-06-12 10:18:23 +02:00
|
|
|
count, expected->message, actual->message, actual->wParam, actual->lParam );
|
|
|
|
|
|
|
|
if (expected->message == actual->message)
|
|
|
|
{
|
|
|
|
if ((expected->flags & defwinproc) != (actual->flags & defwinproc) &&
|
|
|
|
(expected->flags & optional))
|
|
|
|
{
|
|
|
|
/* don't match messages if their defwinproc status differs */
|
|
|
|
expected++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
expected++;
|
|
|
|
actual++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
expected++;
|
|
|
|
actual++;
|
|
|
|
}
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* optional trailing messages */
|
|
|
|
while (expected->message && expected->flags & optional)
|
|
|
|
{
|
|
|
|
trace_(file, line)( " %u: expected: msg %04x - actual: nothing\n", count, expected->message );
|
|
|
|
expected++;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (expected->message)
|
|
|
|
{
|
|
|
|
trace_(file, line)( " %u: expected: msg %04x - actual: nothing\n", count, expected->message );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (actual->message)
|
|
|
|
{
|
2022-02-28 08:25:25 +01:00
|
|
|
trace_(file, line)( " %u: expected: nothing - actual: %04x wp %08Ix lp %08Ix\n",
|
2014-06-12 10:18:23 +02:00
|
|
|
count, actual->message, actual->wParam, actual->lParam );
|
|
|
|
actual++;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-23 10:39:27 +02:00
|
|
|
static void ok_sequence_(struct msg_sequence **seq, int sequence_index,
|
2017-09-12 21:53:01 +02:00
|
|
|
const struct message *expected_list, const char *context, BOOL todo,
|
2009-08-23 10:39:27 +02:00
|
|
|
const char *file, int line)
|
|
|
|
{
|
|
|
|
static const struct message end_of_sequence = {0, 0, 0, 0};
|
2017-09-12 21:53:01 +02:00
|
|
|
struct msg_sequence *msg_seq = seq[sequence_index];
|
|
|
|
const struct message *expected = expected_list;
|
2009-08-23 10:39:27 +02:00
|
|
|
const struct message *actual, *sequence;
|
2014-06-12 10:18:23 +02:00
|
|
|
int failcount = 0, dump = 0;
|
2009-08-23 10:39:27 +02:00
|
|
|
|
|
|
|
add_message(seq, sequence_index, &end_of_sequence);
|
|
|
|
|
|
|
|
sequence = msg_seq->sequence;
|
|
|
|
actual = sequence;
|
|
|
|
|
|
|
|
while (expected->message && actual->message)
|
|
|
|
{
|
|
|
|
if (expected->message == actual->message)
|
|
|
|
{
|
|
|
|
if (expected->flags & wparam)
|
|
|
|
{
|
|
|
|
if (expected->wParam != actual->wParam && todo)
|
|
|
|
{
|
|
|
|
todo_wine
|
|
|
|
{
|
|
|
|
failcount++;
|
2014-06-12 10:18:23 +02:00
|
|
|
dump++;
|
2009-08-23 10:39:27 +02:00
|
|
|
ok_(file, line) (FALSE,
|
2022-02-28 08:25:25 +01:00
|
|
|
"%s: in msg 0x%04x expecting wParam 0x%Ix got 0x%Ix\n",
|
2009-08-23 10:39:27 +02:00
|
|
|
context, expected->message, expected->wParam, actual->wParam);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ok_(file, line) (expected->wParam == actual->wParam,
|
2022-02-28 08:25:25 +01:00
|
|
|
"%s: in msg 0x%04x expecting wParam 0x%Ix got 0x%Ix\n",
|
2009-08-23 10:39:27 +02:00
|
|
|
context, expected->message, expected->wParam, actual->wParam);
|
2014-06-12 10:18:23 +02:00
|
|
|
if (expected->wParam != actual->wParam) dump++;
|
2009-08-23 10:39:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (expected->flags & lparam)
|
|
|
|
{
|
|
|
|
if (expected->lParam != actual->lParam && todo)
|
|
|
|
{
|
|
|
|
todo_wine
|
|
|
|
{
|
|
|
|
failcount++;
|
2014-06-12 10:18:23 +02:00
|
|
|
dump++;
|
2009-08-23 10:39:27 +02:00
|
|
|
ok_(file, line) (FALSE,
|
2022-02-28 08:25:25 +01:00
|
|
|
"%s: in msg 0x%04x expecting lParam 0x%Ix got 0x%Ix\n",
|
2009-08-23 10:39:27 +02:00
|
|
|
context, expected->message, expected->lParam, actual->lParam);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ok_(file, line) (expected->lParam == actual->lParam,
|
2022-02-28 08:25:25 +01:00
|
|
|
"%s: in msg 0x%04x expecting lParam 0x%Ix got 0x%Ix\n",
|
2009-08-23 10:39:27 +02:00
|
|
|
context, expected->message, expected->lParam, actual->lParam);
|
2014-06-12 10:18:23 +02:00
|
|
|
if (expected->lParam != actual->lParam) dump++;
|
2009-08-23 10:39:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-21 07:15:35 +02:00
|
|
|
if (expected->flags & custdraw)
|
|
|
|
{
|
|
|
|
if (expected->stage != actual->stage && todo)
|
|
|
|
{
|
|
|
|
todo_wine
|
|
|
|
{
|
|
|
|
failcount++;
|
2014-06-12 10:18:23 +02:00
|
|
|
dump++;
|
2014-04-21 07:15:35 +02:00
|
|
|
ok_(file, line) (FALSE,
|
2022-02-28 08:25:25 +01:00
|
|
|
"%s: in msg 0x%04x expecting cd stage 0x%08lx got 0x%08lx\n",
|
2014-04-21 07:15:35 +02:00
|
|
|
context, expected->message, expected->stage, actual->stage);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ok_(file, line) (expected->stage == actual->stage,
|
2022-02-28 08:25:25 +01:00
|
|
|
"%s: in msg 0x%04x expecting cd stage 0x%08lx got 0x%08lx\n",
|
2014-04-21 07:15:35 +02:00
|
|
|
context, expected->message, expected->stage, actual->stage);
|
2014-06-12 10:18:23 +02:00
|
|
|
if (expected->stage != actual->stage) dump++;
|
2014-04-21 07:15:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-23 10:39:27 +02:00
|
|
|
if (expected->flags & id)
|
|
|
|
{
|
|
|
|
if (expected->id != actual->id && expected->flags & optional)
|
|
|
|
{
|
|
|
|
expected++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (expected->id != actual->id && todo)
|
|
|
|
{
|
|
|
|
todo_wine
|
|
|
|
{
|
|
|
|
failcount++;
|
2014-06-12 10:18:23 +02:00
|
|
|
dump++;
|
2009-08-23 10:39:27 +02:00
|
|
|
ok_(file, line) (FALSE,
|
comctl32/tests: Print id value as decimal.
All the notification codes (printed as an id) have negative base value
(SBN_, UDN_, HDN_, BCN_, TBN_, TTN_, RBN_, TRBN_, PGN_, TVN_, LVN_, TCN_,
CBEN_, IPN_, MCN_, DTN_), and printing them as decimal helps to quickly
identify the corresponding notification value in cases when an id in
the message sequence doesn't match. Custom ids in the message sequences
have small numbers (0, 1, 2, ...), so they also get printed correctly.
Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru>
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
2022-02-11 15:24:31 +01:00
|
|
|
"%s: in msg 0x%04x expecting id %d got %d\n",
|
2009-08-23 10:39:27 +02:00
|
|
|
context, expected->message, expected->id, actual->id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ok_(file, line) (expected->id == actual->id,
|
comctl32/tests: Print id value as decimal.
All the notification codes (printed as an id) have negative base value
(SBN_, UDN_, HDN_, BCN_, TBN_, TTN_, RBN_, TRBN_, PGN_, TVN_, LVN_, TCN_,
CBEN_, IPN_, MCN_, DTN_), and printing them as decimal helps to quickly
identify the corresponding notification value in cases when an id in
the message sequence doesn't match. Custom ids in the message sequences
have small numbers (0, 1, 2, ...), so they also get printed correctly.
Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru>
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
2022-02-11 15:24:31 +01:00
|
|
|
"%s: in msg 0x%04x expecting id %d got %d\n",
|
2009-08-23 10:39:27 +02:00
|
|
|
context, expected->message, expected->id, actual->id);
|
2014-06-12 10:18:23 +02:00
|
|
|
if (expected->id != actual->id) dump++;
|
2009-08-23 10:39:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((expected->flags & defwinproc) != (actual->flags & defwinproc) && todo)
|
|
|
|
{
|
|
|
|
todo_wine
|
|
|
|
{
|
|
|
|
failcount++;
|
2014-06-12 10:18:23 +02:00
|
|
|
dump++;
|
2009-08-23 10:39:27 +02:00
|
|
|
ok_(file, line) (FALSE,
|
|
|
|
"%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
|
|
|
|
context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ok_(file, line) ((expected->flags & defwinproc) == (actual->flags & defwinproc),
|
|
|
|
"%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
|
|
|
|
context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
|
2014-06-12 10:18:23 +02:00
|
|
|
if ((expected->flags & defwinproc) != (actual->flags & defwinproc)) dump++;
|
2009-08-23 10:39:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ok_(file, line) ((expected->flags & beginpaint) == (actual->flags & beginpaint),
|
|
|
|
"%s: the msg 0x%04x should %shave been sent by BeginPaint\n",
|
|
|
|
context, expected->message, (expected->flags & beginpaint) ? "" : "NOT ");
|
2014-06-12 10:18:23 +02:00
|
|
|
if ((expected->flags & beginpaint) != (actual->flags & beginpaint)) dump++;
|
|
|
|
|
2009-08-23 10:39:27 +02:00
|
|
|
ok_(file, line) ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
|
|
|
|
"%s: the msg 0x%04x should have been %s\n",
|
|
|
|
context, expected->message, (expected->flags & posted) ? "posted" : "sent");
|
2014-06-12 10:18:23 +02:00
|
|
|
if ((expected->flags & (sent|posted)) != (actual->flags & (sent|posted))) dump++;
|
|
|
|
|
2009-08-23 10:39:27 +02:00
|
|
|
ok_(file, line) ((expected->flags & parent) == (actual->flags & parent),
|
|
|
|
"%s: the msg 0x%04x was expected in %s\n",
|
|
|
|
context, expected->message, (expected->flags & parent) ? "parent" : "child");
|
2014-06-12 10:18:23 +02:00
|
|
|
if ((expected->flags & parent) != (actual->flags & parent)) dump++;
|
|
|
|
|
2009-08-23 10:39:27 +02:00
|
|
|
ok_(file, line) ((expected->flags & hook) == (actual->flags & hook),
|
|
|
|
"%s: the msg 0x%04x should have been sent by a hook\n",
|
|
|
|
context, expected->message);
|
2014-06-12 10:18:23 +02:00
|
|
|
if ((expected->flags & hook) != (actual->flags & hook)) dump++;
|
|
|
|
|
2009-08-23 10:39:27 +02:00
|
|
|
ok_(file, line) ((expected->flags & winevent_hook) == (actual->flags & winevent_hook),
|
|
|
|
"%s: the msg 0x%04x should have been sent by a winevent hook\n",
|
|
|
|
context, expected->message);
|
2014-06-12 10:18:23 +02:00
|
|
|
if ((expected->flags & winevent_hook) != (actual->flags & winevent_hook)) dump++;
|
|
|
|
|
2009-08-23 10:39:27 +02:00
|
|
|
expected++;
|
|
|
|
actual++;
|
|
|
|
}
|
|
|
|
else if (expected->flags & optional)
|
|
|
|
expected++;
|
|
|
|
else if (todo)
|
|
|
|
{
|
|
|
|
failcount++;
|
2014-06-12 10:18:23 +02:00
|
|
|
dump++;
|
2009-08-23 10:39:27 +02:00
|
|
|
todo_wine
|
|
|
|
{
|
|
|
|
ok_(file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
|
|
|
|
context, expected->message, actual->message);
|
|
|
|
}
|
2014-06-12 10:18:23 +02:00
|
|
|
goto done;
|
2009-08-23 10:39:27 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ok_(file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
|
|
|
|
context, expected->message, actual->message);
|
2014-06-12 10:18:23 +02:00
|
|
|
dump++;
|
2009-08-23 10:39:27 +02:00
|
|
|
expected++;
|
|
|
|
actual++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* skip all optional trailing messages */
|
|
|
|
while (expected->message && ((expected->flags & optional)))
|
|
|
|
expected++;
|
|
|
|
|
|
|
|
if (todo)
|
|
|
|
{
|
|
|
|
todo_wine
|
|
|
|
{
|
|
|
|
if (expected->message || actual->message)
|
|
|
|
{
|
|
|
|
failcount++;
|
2014-06-12 10:18:23 +02:00
|
|
|
dump++;
|
2009-08-23 10:39:27 +02:00
|
|
|
ok_(file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
|
|
|
|
context, expected->message, actual->message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (expected->message || actual->message)
|
|
|
|
{
|
2014-06-12 10:18:23 +02:00
|
|
|
dump++;
|
2009-08-23 10:39:27 +02:00
|
|
|
ok_(file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
|
|
|
|
context, expected->message, actual->message);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(todo && !failcount) /* succeeded yet marked todo */
|
|
|
|
{
|
2017-04-07 16:02:01 +02:00
|
|
|
if (!strcmp(winetest_platform, "wine")) dump++;
|
2009-08-23 10:39:27 +02:00
|
|
|
todo_wine
|
|
|
|
{
|
|
|
|
ok_(file, line)(TRUE, "%s: marked \"todo_wine\" but succeeds\n", context);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-12 10:18:23 +02:00
|
|
|
done:
|
2017-09-12 21:53:01 +02:00
|
|
|
if (dump) dump_sequence( seq, sequence_index, expected_list, context, file, line );
|
2009-08-23 10:39:27 +02:00
|
|
|
flush_sequence(seq, sequence_index);
|
|
|
|
}
|
2007-02-18 00:27:05 +01:00
|
|
|
|
|
|
|
#define ok_sequence(seq, index, exp, contx, todo) \
|
|
|
|
ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__)
|
|
|
|
|
|
|
|
|
2009-08-23 10:39:27 +02:00
|
|
|
static void init_msg_sequences(struct msg_sequence **seq, int n)
|
|
|
|
{
|
|
|
|
int i;
|
2007-02-18 00:27:05 +01:00
|
|
|
|
2009-08-23 10:39:27 +02:00
|
|
|
for (i = 0; i < n; i++)
|
2018-02-15 09:00:08 +01:00
|
|
|
seq[i] = heap_alloc_zero(sizeof(*seq[i]));
|
2009-08-23 10:39:27 +02:00
|
|
|
}
|