Reactos
at master 399 lines 14 kB view raw
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#ifdef __REACTOS__ 22#pragma once 23#endif 24 25#include <assert.h> 26#include <windows.h> 27#include "wine/heap.h" 28#include "wine/test.h" 29 30/* undocumented SWP flags - from SDK 3.1 */ 31#define SWP_NOCLIENTSIZE 0x0800 32#define SWP_NOCLIENTMOVE 0x1000 33 34typedef enum 35{ 36 sent = 0x1, 37 posted = 0x2, 38 parent = 0x4, 39 wparam = 0x8, 40 lparam = 0x10, 41 defwinproc = 0x20, 42 beginpaint = 0x40, 43 optional = 0x80, 44 hook = 0x100, 45 winevent_hook =0x200, 46 id = 0x400, 47 custdraw = 0x800 48} msg_flags_t; 49 50struct message 51{ 52 UINT message; /* the WM_* code */ 53 msg_flags_t flags; /* message props */ 54 WPARAM wParam; /* expected value of wParam */ 55 LPARAM lParam; /* expected value of lParam */ 56 UINT id; /* extra message data: id of the window, 57 notify code etc. */ 58 DWORD stage; /* custom draw stage */ 59}; 60 61struct msg_sequence 62{ 63 int count; 64 int size; 65 struct message *sequence; 66}; 67 68static void add_message(struct msg_sequence **seq, int sequence_index, 69 const struct message *msg) 70{ 71 struct msg_sequence *msg_seq = seq[sequence_index]; 72 73 if (!msg_seq->sequence) 74 { 75 msg_seq->size = 10; 76 msg_seq->sequence = heap_alloc(msg_seq->size * sizeof (*msg_seq->sequence)); 77 } 78 79 if (msg_seq->count == msg_seq->size) 80 { 81 msg_seq->size *= 2; 82 msg_seq->sequence = heap_realloc(msg_seq->sequence, msg_seq->size * sizeof (*msg_seq->sequence)); 83 } 84 85 assert(msg_seq->sequence); 86 87 msg_seq->sequence[msg_seq->count] = *msg; 88 msg_seq->count++; 89} 90 91static inline void flush_sequence(struct msg_sequence **seg, int sequence_index) 92{ 93 struct msg_sequence *msg_seq = seg[sequence_index]; 94 heap_free(msg_seq->sequence); 95 msg_seq->sequence = NULL; 96 msg_seq->count = msg_seq->size = 0; 97} 98 99static inline void flush_sequences(struct msg_sequence **seq, int n) 100{ 101 int i; 102 103 for (i = 0; i < n; i++) 104 flush_sequence(seq, i); 105} 106 107static void dump_sequence( struct msg_sequence **seq, int sequence_index, 108 const struct message *expected, const char *context, 109 const char *file, int line ) 110{ 111 struct msg_sequence *msg_seq = seq[sequence_index]; 112 const struct message *actual, *sequence; 113 unsigned int count = 0; 114 115 sequence = msg_seq->sequence; 116 actual = sequence; 117 118 trace_(file, line)("Failed sequence %s:\n", context ); 119 while (expected->message && actual->message) 120 { 121 trace_(file, line)( " %u: expected: %04x - actual: %04x wp %08lx lp %08lx\n", 122 count, expected->message, actual->message, actual->wParam, actual->lParam ); 123 124 if (expected->message == actual->message) 125 { 126 if ((expected->flags & defwinproc) != (actual->flags & defwinproc) && 127 (expected->flags & optional)) 128 { 129 /* don't match messages if their defwinproc status differs */ 130 expected++; 131 } 132 else 133 { 134 expected++; 135 actual++; 136 } 137 } 138 else 139 { 140 expected++; 141 actual++; 142 } 143 count++; 144 } 145 146 /* optional trailing messages */ 147 while (expected->message && expected->flags & optional) 148 { 149 trace_(file, line)( " %u: expected: msg %04x - actual: nothing\n", count, expected->message ); 150 expected++; 151 count++; 152 } 153 154 if (expected->message) 155 { 156 trace_(file, line)( " %u: expected: msg %04x - actual: nothing\n", count, expected->message ); 157 return; 158 } 159 160 while (actual->message) 161 { 162 trace_(file, line)( " %u: expected: nothing - actual: %04x wp %08lx lp %08lx\n", 163 count, actual->message, actual->wParam, actual->lParam ); 164 actual++; 165 count++; 166 } 167} 168 169static void ok_sequence_(struct msg_sequence **seq, int sequence_index, 170 const struct message *expected_list, const char *context, BOOL todo, 171 const char *file, int line) 172{ 173 static const struct message end_of_sequence = {0, 0, 0, 0}; 174 struct msg_sequence *msg_seq = seq[sequence_index]; 175 const struct message *expected = expected_list; 176 const struct message *actual, *sequence; 177 int failcount = 0, dump = 0; 178 179 add_message(seq, sequence_index, &end_of_sequence); 180 181 sequence = msg_seq->sequence; 182 actual = sequence; 183 184 while (expected->message && actual->message) 185 { 186 if (expected->message == actual->message) 187 { 188 if (expected->flags & wparam) 189 { 190 if (expected->wParam != actual->wParam && todo) 191 { 192 todo_wine 193 { 194 failcount++; 195 dump++; 196 ok_(file, line) (FALSE, 197 "%s: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n", 198 context, expected->message, expected->wParam, actual->wParam); 199 } 200 } 201 else 202 { 203 ok_(file, line) (expected->wParam == actual->wParam, 204 "%s: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n", 205 context, expected->message, expected->wParam, actual->wParam); 206 if (expected->wParam != actual->wParam) dump++; 207 } 208 } 209 210 if (expected->flags & lparam) 211 { 212 if (expected->lParam != actual->lParam && todo) 213 { 214 todo_wine 215 { 216 failcount++; 217 dump++; 218 ok_(file, line) (FALSE, 219 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n", 220 context, expected->message, expected->lParam, actual->lParam); 221 } 222 } 223 else 224 { 225 ok_(file, line) (expected->lParam == actual->lParam, 226 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n", 227 context, expected->message, expected->lParam, actual->lParam); 228 if (expected->lParam != actual->lParam) dump++; 229 } 230 } 231 232 if (expected->flags & custdraw) 233 { 234 if (expected->stage != actual->stage && todo) 235 { 236 todo_wine 237 { 238 failcount++; 239 dump++; 240 ok_(file, line) (FALSE, 241 "%s: in msg 0x%04x expecting cd stage 0x%08x got 0x%08x\n", 242 context, expected->message, expected->stage, actual->stage); 243 } 244 } 245 else 246 { 247 ok_(file, line) (expected->stage == actual->stage, 248 "%s: in msg 0x%04x expecting cd stage 0x%08x got 0x%08x\n", 249 context, expected->message, expected->stage, actual->stage); 250 if (expected->stage != actual->stage) dump++; 251 } 252 } 253 254 if (expected->flags & id) 255 { 256 if (expected->id != actual->id && expected->flags & optional) 257 { 258 expected++; 259 continue; 260 } 261 if (expected->id != actual->id && todo) 262 { 263 todo_wine 264 { 265 failcount++; 266 dump++; 267 ok_(file, line) (FALSE, 268 "%s: in msg 0x%04x expecting id 0x%x got 0x%x\n", 269 context, expected->message, expected->id, actual->id); 270 } 271 } 272 else 273 { 274 ok_(file, line) (expected->id == actual->id, 275 "%s: in msg 0x%04x expecting id 0x%x got 0x%x\n", 276 context, expected->message, expected->id, actual->id); 277 if (expected->id != actual->id) dump++; 278 } 279 } 280 281 if ((expected->flags & defwinproc) != (actual->flags & defwinproc) && todo) 282 { 283 todo_wine 284 { 285 failcount++; 286 dump++; 287 ok_(file, line) (FALSE, 288 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n", 289 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT "); 290 } 291 } 292 else 293 { 294 ok_(file, line) ((expected->flags & defwinproc) == (actual->flags & defwinproc), 295 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n", 296 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT "); 297 if ((expected->flags & defwinproc) != (actual->flags & defwinproc)) dump++; 298 } 299 300 ok_(file, line) ((expected->flags & beginpaint) == (actual->flags & beginpaint), 301 "%s: the msg 0x%04x should %shave been sent by BeginPaint\n", 302 context, expected->message, (expected->flags & beginpaint) ? "" : "NOT "); 303 if ((expected->flags & beginpaint) != (actual->flags & beginpaint)) dump++; 304 305 ok_(file, line) ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)), 306 "%s: the msg 0x%04x should have been %s\n", 307 context, expected->message, (expected->flags & posted) ? "posted" : "sent"); 308 if ((expected->flags & (sent|posted)) != (actual->flags & (sent|posted))) dump++; 309 310 ok_(file, line) ((expected->flags & parent) == (actual->flags & parent), 311 "%s: the msg 0x%04x was expected in %s\n", 312 context, expected->message, (expected->flags & parent) ? "parent" : "child"); 313 if ((expected->flags & parent) != (actual->flags & parent)) dump++; 314 315 ok_(file, line) ((expected->flags & hook) == (actual->flags & hook), 316 "%s: the msg 0x%04x should have been sent by a hook\n", 317 context, expected->message); 318 if ((expected->flags & hook) != (actual->flags & hook)) dump++; 319 320 ok_(file, line) ((expected->flags & winevent_hook) == (actual->flags & winevent_hook), 321 "%s: the msg 0x%04x should have been sent by a winevent hook\n", 322 context, expected->message); 323 if ((expected->flags & winevent_hook) != (actual->flags & winevent_hook)) dump++; 324 325 expected++; 326 actual++; 327 } 328 else if (expected->flags & optional) 329 expected++; 330 else if (todo) 331 { 332 failcount++; 333 dump++; 334 todo_wine 335 { 336 ok_(file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n", 337 context, expected->message, actual->message); 338 } 339 goto done; 340 } 341 else 342 { 343 ok_(file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n", 344 context, expected->message, actual->message); 345 dump++; 346 expected++; 347 actual++; 348 } 349 } 350 351 /* skip all optional trailing messages */ 352 while (expected->message && ((expected->flags & optional))) 353 expected++; 354 355 if (todo) 356 { 357 todo_wine 358 { 359 if (expected->message || actual->message) 360 { 361 failcount++; 362 dump++; 363 ok_(file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n", 364 context, expected->message, actual->message); 365 } 366 } 367 } 368 else if (expected->message || actual->message) 369 { 370 dump++; 371 ok_(file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n", 372 context, expected->message, actual->message); 373 } 374 375 if(todo && !failcount) /* succeeded yet marked todo */ 376 { 377 if (!strcmp(winetest_platform, "wine")) dump++; 378 todo_wine 379 { 380 ok_(file, line)(TRUE, "%s: marked \"todo_wine\" but succeeds\n", context); 381 } 382 } 383 384done: 385 if (dump) dump_sequence( seq, sequence_index, expected_list, context, file, line ); 386 flush_sequence(seq, sequence_index); 387} 388 389#define ok_sequence(seq, index, exp, contx, todo) \ 390 ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__) 391 392 393static void init_msg_sequences(struct msg_sequence **seq, int n) 394{ 395 int i; 396 397 for (i = 0; i < n; i++) 398 seq[i] = heap_alloc_zero(sizeof(*seq[i])); 399}