Reactos
1/* Message Sequence Testing Code
2 *
3 * Copyright (C) 2007 James Hawkins
4 * Copyright (C) 2007 Lei Zhang
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#pragma once
22
23#include <assert.h>
24#include <windows.h>
25
26#include "wine/heap.h"
27#include "wine/test.h"
28
29/* undocumented SWP flags - from SDK 3.1 */
30#define SWP_NOCLIENTSIZE 0x0800
31#define SWP_NOCLIENTMOVE 0x1000
32
33typedef enum
34{
35 sent = 0x1,
36 posted = 0x2,
37 parent = 0x4,
38 wparam = 0x8,
39 lparam = 0x10,
40 defwinproc = 0x20,
41 beginpaint = 0x40,
42 optional = 0x80,
43 hook = 0x100,
44 winevent_hook =0x200,
45 id = 0x400
46} msg_flags_t;
47
48struct message
49{
50 UINT message; /* the WM_* code */
51 msg_flags_t flags; /* message props */
52 WPARAM wParam; /* expected value of wParam */
53 LPARAM lParam; /* expected value of lParam */
54 UINT id; /* extra message data: id of the window,
55 notify code etc. */
56};
57
58struct msg_sequence
59{
60 int count;
61 int size;
62 struct message *sequence;
63};
64
65static void add_message(struct msg_sequence **seq, int sequence_index,
66 const struct message *msg)
67{
68 struct msg_sequence *msg_seq = seq[sequence_index];
69
70 if (!msg_seq->sequence)
71 {
72 msg_seq->size = 10;
73 msg_seq->sequence = heap_alloc(msg_seq->size * sizeof (struct message));
74 }
75
76 if (msg_seq->count == msg_seq->size)
77 {
78 msg_seq->size *= 2;
79 msg_seq->sequence = heap_realloc(msg_seq->sequence, msg_seq->size * sizeof (struct message));
80 }
81
82 assert(msg_seq->sequence);
83
84 msg_seq->sequence[msg_seq->count].message = msg->message;
85 msg_seq->sequence[msg_seq->count].flags = msg->flags;
86 msg_seq->sequence[msg_seq->count].wParam = msg->wParam;
87 msg_seq->sequence[msg_seq->count].lParam = msg->lParam;
88 msg_seq->sequence[msg_seq->count].id = msg->id;
89
90 msg_seq->count++;
91}
92
93static void flush_sequence(struct msg_sequence **seg, int sequence_index)
94{
95 struct msg_sequence *msg_seq = seg[sequence_index];
96 heap_free(msg_seq->sequence);
97 msg_seq->sequence = NULL;
98 msg_seq->count = msg_seq->size = 0;
99}
100
101static void flush_sequences(struct msg_sequence **seq, int n)
102{
103 int i;
104
105 for (i = 0; i < n; i++)
106 flush_sequence(seq, i);
107}
108
109static void ok_sequence_(struct msg_sequence **seq, int sequence_index,
110 const struct message *expected, const char *context, BOOL todo,
111 const char *file, int line)
112{
113 struct msg_sequence *msg_seq = seq[sequence_index];
114 static const struct message end_of_sequence = {0, 0, 0, 0};
115 const struct message *actual, *sequence;
116 int failcount = 0;
117
118 add_message(seq, sequence_index, &end_of_sequence);
119
120 sequence = msg_seq->sequence;
121 actual = sequence;
122
123 while (expected->message && actual->message)
124 {
125 trace_( file, line)("expected %04x - actual %04x\n", expected->message, actual->message);
126
127 if (expected->message == actual->message)
128 {
129 if (expected->flags & wparam)
130 {
131 if (expected->wParam != actual->wParam && todo)
132 {
133 todo_wine
134 {
135 failcount++;
136 ok_(file, line) (FALSE,
137 "%s: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
138 context, expected->message, expected->wParam, actual->wParam);
139 }
140 }
141 else
142 {
143 ok_(file, line) (expected->wParam == actual->wParam,
144 "%s: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
145 context, expected->message, expected->wParam, actual->wParam);
146 }
147 }
148
149 if (expected->flags & lparam)
150 {
151 if (expected->lParam != actual->lParam && todo)
152 {
153 todo_wine
154 {
155 failcount++;
156 ok_(file, line) (FALSE,
157 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
158 context, expected->message, expected->lParam, actual->lParam);
159 }
160 }
161 else
162 {
163 ok_(file, line) (expected->lParam == actual->lParam,
164 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
165 context, expected->message, expected->lParam, actual->lParam);
166 }
167 }
168
169 if (expected->flags & id)
170 {
171 if (expected->id != actual->id && expected->flags & optional)
172 {
173 expected++;
174 continue;
175 }
176 if (expected->id != actual->id && todo)
177 {
178 todo_wine
179 {
180 failcount++;
181 ok_(file, line) (FALSE,
182 "%s: in msg 0x%04x expecting id 0x%x got 0x%x\n",
183 context, expected->message, expected->id, actual->id);
184 }
185 }
186 else
187 {
188 ok_(file, line) (expected->id == actual->id,
189 "%s: in msg 0x%04x expecting id 0x%x got 0x%x\n",
190 context, expected->message, expected->id, actual->id);
191 }
192 }
193
194 if ((expected->flags & defwinproc) != (actual->flags & defwinproc) && todo)
195 {
196 todo_wine
197 {
198 failcount++;
199 ok_(file, line) (FALSE,
200 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
201 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
202 }
203 }
204 else
205 {
206 ok_(file, line) ((expected->flags & defwinproc) == (actual->flags & defwinproc),
207 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
208 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
209 }
210
211 ok_(file, line) ((expected->flags & beginpaint) == (actual->flags & beginpaint),
212 "%s: the msg 0x%04x should %shave been sent by BeginPaint\n",
213 context, expected->message, (expected->flags & beginpaint) ? "" : "NOT ");
214 ok_(file, line) ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
215 "%s: the msg 0x%04x should have been %s\n",
216 context, expected->message, (expected->flags & posted) ? "posted" : "sent");
217 ok_(file, line) ((expected->flags & parent) == (actual->flags & parent),
218 "%s: the msg 0x%04x was expected in %s\n",
219 context, expected->message, (expected->flags & parent) ? "parent" : "child");
220 ok_(file, line) ((expected->flags & hook) == (actual->flags & hook),
221 "%s: the msg 0x%04x should have been sent by a hook\n",
222 context, expected->message);
223 ok_(file, line) ((expected->flags & winevent_hook) == (actual->flags & winevent_hook),
224 "%s: the msg 0x%04x should have been sent by a winevent hook\n",
225 context, expected->message);
226 expected++;
227 actual++;
228 }
229 else if (expected->flags & optional)
230 expected++;
231 else if (todo)
232 {
233 failcount++;
234 todo_wine
235 {
236 ok_(file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
237 context, expected->message, actual->message);
238 }
239
240 flush_sequence(seq, sequence_index);
241 return;
242 }
243 else
244 {
245 ok_(file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
246 context, expected->message, actual->message);
247 expected++;
248 actual++;
249 }
250 }
251
252 /* skip all optional trailing messages */
253 while (expected->message && ((expected->flags & optional)))
254 expected++;
255
256 if (todo)
257 {
258 todo_wine
259 {
260 if (expected->message || actual->message)
261 {
262 failcount++;
263 ok_(file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
264 context, expected->message, actual->message);
265 }
266 }
267 }
268 else if (expected->message || actual->message)
269 {
270 ok_(file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
271 context, expected->message, actual->message);
272 }
273
274 if(todo && !failcount) /* succeeded yet marked todo */
275 {
276 todo_wine
277 {
278 ok_(file, line)(TRUE, "%s: marked \"todo_wine\" but succeeds\n", context);
279 }
280 }
281
282 flush_sequence(seq, sequence_index);
283}
284
285#define ok_sequence(seq, index, exp, contx, todo) \
286 ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__)
287
288
289static void init_msg_sequences(struct msg_sequence **seq, int n)
290{
291 int i;
292
293 for (i = 0; i < n; i++)
294 seq[i] = heap_alloc_zero(sizeof(struct msg_sequence));
295}