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 /* undocumented SWP flags - from SDK 3.1 */ 24 #define SWP_NOCLIENTSIZE 0x0800 25 #define SWP_NOCLIENTMOVE 0x1000 26 27 typedef enum 28 { 29 sent = 0x1, 30 posted = 0x2, 31 parent = 0x4, 32 wparam = 0x8, 33 lparam = 0x10, 34 defwinproc = 0x20, 35 beginpaint = 0x40, 36 optional = 0x80, 37 hook = 0x100, 38 winevent_hook =0x200, 39 id = 0x400 40 } msg_flags_t; 41 42 struct message 43 { 44 UINT message; /* the WM_* code */ 45 msg_flags_t flags; /* message props */ 46 WPARAM wParam; /* expected value of wParam */ 47 LPARAM lParam; /* expected value of lParam */ 48 UINT id; /* extra message data: id of the window, 49 notify code etc. */ 50 }; 51 52 struct msg_sequence 53 { 54 int count; 55 int size; 56 struct message *sequence; 57 }; 58 59 static void add_message(struct msg_sequence **seq, int sequence_index, 60 const struct message *msg) 61 { 62 struct msg_sequence *msg_seq = seq[sequence_index]; 63 64 if (!msg_seq->sequence) 65 { 66 msg_seq->size = 10; 67 msg_seq->sequence = HeapAlloc(GetProcessHeap(), 0, 68 msg_seq->size * sizeof (struct message)); 69 } 70 71 if (msg_seq->count == msg_seq->size) 72 { 73 msg_seq->size *= 2; 74 msg_seq->sequence = HeapReAlloc(GetProcessHeap(), 0, 75 msg_seq->sequence, 76 msg_seq->size * sizeof (struct message)); 77 } 78 79 assert(msg_seq->sequence); 80 81 msg_seq->sequence[msg_seq->count].message = msg->message; 82 msg_seq->sequence[msg_seq->count].flags = msg->flags; 83 msg_seq->sequence[msg_seq->count].wParam = msg->wParam; 84 msg_seq->sequence[msg_seq->count].lParam = msg->lParam; 85 msg_seq->sequence[msg_seq->count].id = msg->id; 86 87 msg_seq->count++; 88 } 89 90 static void flush_sequence(struct msg_sequence **seg, int sequence_index) 91 { 92 struct msg_sequence *msg_seq = seg[sequence_index]; 93 HeapFree(GetProcessHeap(), 0, msg_seq->sequence); 94 msg_seq->sequence = NULL; 95 msg_seq->count = msg_seq->size = 0; 96 } 97 98 static void flush_sequences(struct msg_sequence **seq, int n) 99 { 100 int i; 101 102 for (i = 0; i < n; i++) 103 flush_sequence(seq, i); 104 } 105 106 static void ok_sequence_(struct msg_sequence **seq, int sequence_index, 107 const struct message *expected, const char *context, BOOL todo, 108 const char *file, int line) 109 { 110 struct msg_sequence *msg_seq = seq[sequence_index]; 111 static const struct message end_of_sequence = {0, 0, 0, 0}; 112 const struct message *actual, *sequence; 113 int failcount = 0; 114 115 add_message(seq, sequence_index, &end_of_sequence); 116 117 sequence = msg_seq->sequence; 118 actual = sequence; 119 120 while (expected->message && actual->message) 121 { 122 trace_( file, line)("expected %04x - actual %04x\n", expected->message, actual->message); 123 124 if (expected->message == actual->message) 125 { 126 if (expected->flags & wparam) 127 { 128 if (expected->wParam != actual->wParam && todo) 129 { 130 todo_wine 131 { 132 failcount++; 133 ok_(file, line) (FALSE, 134 "%s: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n", 135 context, expected->message, expected->wParam, actual->wParam); 136 } 137 } 138 else 139 { 140 ok_(file, line) (expected->wParam == actual->wParam, 141 "%s: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n", 142 context, expected->message, expected->wParam, actual->wParam); 143 } 144 } 145 146 if (expected->flags & lparam) 147 { 148 if (expected->lParam != actual->lParam && todo) 149 { 150 todo_wine 151 { 152 failcount++; 153 ok_(file, line) (FALSE, 154 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n", 155 context, expected->message, expected->lParam, actual->lParam); 156 } 157 } 158 else 159 { 160 ok_(file, line) (expected->lParam == actual->lParam, 161 "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n", 162 context, expected->message, expected->lParam, actual->lParam); 163 } 164 } 165 166 if (expected->flags & id) 167 { 168 if (expected->id != actual->id && expected->flags & optional) 169 { 170 expected++; 171 continue; 172 } 173 if (expected->id != actual->id && todo) 174 { 175 todo_wine 176 { 177 failcount++; 178 ok_(file, line) (FALSE, 179 "%s: in msg 0x%04x expecting id 0x%x got 0x%x\n", 180 context, expected->message, expected->id, actual->id); 181 } 182 } 183 else 184 { 185 ok_(file, line) (expected->id == actual->id, 186 "%s: in msg 0x%04x expecting id 0x%x got 0x%x\n", 187 context, expected->message, expected->id, actual->id); 188 } 189 } 190 191 if ((expected->flags & defwinproc) != (actual->flags & defwinproc) && todo) 192 { 193 todo_wine 194 { 195 failcount++; 196 ok_(file, line) (FALSE, 197 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n", 198 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT "); 199 } 200 } 201 else 202 { 203 ok_(file, line) ((expected->flags & defwinproc) == (actual->flags & defwinproc), 204 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n", 205 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT "); 206 } 207 208 ok_(file, line) ((expected->flags & beginpaint) == (actual->flags & beginpaint), 209 "%s: the msg 0x%04x should %shave been sent by BeginPaint\n", 210 context, expected->message, (expected->flags & beginpaint) ? "" : "NOT "); 211 ok_(file, line) ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)), 212 "%s: the msg 0x%04x should have been %s\n", 213 context, expected->message, (expected->flags & posted) ? "posted" : "sent"); 214 ok_(file, line) ((expected->flags & parent) == (actual->flags & parent), 215 "%s: the msg 0x%04x was expected in %s\n", 216 context, expected->message, (expected->flags & parent) ? "parent" : "child"); 217 ok_(file, line) ((expected->flags & hook) == (actual->flags & hook), 218 "%s: the msg 0x%04x should have been sent by a hook\n", 219 context, expected->message); 220 ok_(file, line) ((expected->flags & winevent_hook) == (actual->flags & winevent_hook), 221 "%s: the msg 0x%04x should have been sent by a winevent hook\n", 222 context, expected->message); 223 expected++; 224 actual++; 225 } 226 else if (expected->flags & optional) 227 expected++; 228 else if (todo) 229 { 230 failcount++; 231 todo_wine 232 { 233 ok_(file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n", 234 context, expected->message, actual->message); 235 } 236 237 flush_sequence(seq, sequence_index); 238 return; 239 } 240 else 241 { 242 ok_(file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n", 243 context, expected->message, actual->message); 244 expected++; 245 actual++; 246 } 247 } 248 249 /* skip all optional trailing messages */ 250 while (expected->message && ((expected->flags & optional))) 251 expected++; 252 253 if (todo) 254 { 255 todo_wine 256 { 257 if (expected->message || actual->message) 258 { 259 failcount++; 260 ok_(file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n", 261 context, expected->message, actual->message); 262 } 263 } 264 } 265 else if (expected->message || actual->message) 266 { 267 ok_(file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n", 268 context, expected->message, actual->message); 269 } 270 271 if(todo && !failcount) /* succeeded yet marked todo */ 272 { 273 todo_wine 274 { 275 ok_(file, line)(TRUE, "%s: marked \"todo_wine\" but succeeds\n", context); 276 } 277 } 278 279 flush_sequence(seq, sequence_index); 280 } 281 282 #define ok_sequence(seq, index, exp, contx, todo) \ 283 ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__) 284 285 286 static void init_msg_sequences(struct msg_sequence **seq, int n) 287 { 288 int i; 289 290 for (i = 0; i < n; i++) 291 seq[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct msg_sequence)); 292 } 293