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 33 typedef 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 48 struct 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 58 struct msg_sequence 59 { 60 int count; 61 int size; 62 struct message *sequence; 63 }; 64 65 static 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 93 static 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 101 static 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 109 static 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 289 static 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 } 296