1 //------------------------------------------------------------------------------ 2 // SendMessageTester.cpp 3 // 4 //------------------------------------------------------------------------------ 5 6 // Standard Includes ----------------------------------------------------------- 7 #include <stdio.h> 8 9 // System Includes ------------------------------------------------------------- 10 #include <Message.h> 11 #include <OS.h> 12 #include <Handler.h> 13 #include <Looper.h> 14 #include <Messenger.h> 15 16 // Project Includes ------------------------------------------------------------ 17 #include <TestUtils.h> 18 #include <ThreadedTestCaller.h> 19 #include <cppunit/TestSuite.h> 20 21 // Local Includes -------------------------------------------------------------- 22 #include "Helpers.h" 23 #include "SendMessageTester.h" 24 #include "SMInvoker.h" 25 #include "SMLooper.h" 26 #include "SMReplyTarget.h" 27 #include "SMTarget.h" 28 29 // Local Defines --------------------------------------------------------------- 30 31 // Globals --------------------------------------------------------------------- 32 33 // target flavors 34 enum target_kind { 35 TARGET_UNINITIALIZED, 36 TARGET_LOCAL_PREFERRED, 37 TARGET_LOCAL_SPECIFIC, 38 TARGET_REMOTE_PREFERRED, 39 TARGET_REMOTE_SPECIFIC, 40 }; 41 42 // tester class 43 class SMTester { 44 public: 45 SMTester(target_kind targetKind) 46 : fTargetKind(targetKind) 47 { 48 } 49 50 ~SMTester() 51 { 52 } 53 54 void Run(SMInvoker &invoker, bigtime_t targetUnblock, 55 bigtime_t targetReply, status_t result, bool deliverySuccess, 56 bool replySuccess, bigtime_t duration) 57 { 58 //printf("SMTester::Run(%lld, %lld, %lx, %d, %d, %lld)\n", targetUnblock, 59 //targetReply, result, deliverySuccess, replySuccess, duration); 60 enum { JITTER = 10000 }; 61 enum { SETUP_LATENCY = 100000 }; 62 enum { DELIVERY_LATENCY = 10000 }; 63 enum { TARGET_HEAD_START = 1000 }; 64 if (targetUnblock == 0) 65 targetUnblock = -TARGET_HEAD_START; 66 // create the target 67 SMTarget *target = NULL; 68 switch (fTargetKind) { 69 case TARGET_UNINITIALIZED: 70 target = new SMTarget; 71 break; 72 case TARGET_LOCAL_PREFERRED: 73 target = new LocalSMTarget(true); 74 break; 75 case TARGET_LOCAL_SPECIFIC: 76 target = new LocalSMTarget(false); 77 break; 78 case TARGET_REMOTE_PREFERRED: 79 target = new RemoteSMTarget(true); 80 break; 81 case TARGET_REMOTE_SPECIFIC: 82 target = new RemoteSMTarget(false); 83 break; 84 } 85 AutoDeleter<SMTarget> deleter(target); 86 // create the reply target 87 SMReplyTarget replyTarget; 88 // init the target and send the message 89 BHandler *replyHandler = replyTarget.Handler(); 90 BMessenger replyMessenger = replyTarget.Messenger(); 91 bigtime_t startTime = system_time() + SETUP_LATENCY; 92 target->Init(startTime + targetUnblock, targetReply); 93 BMessenger targetMessenger = target->Messenger(); 94 snooze_until(startTime, B_SYSTEM_TIMEBASE); 95 status_t actualResult = invoker.Invoke(targetMessenger, replyHandler, 96 replyMessenger); 97 bigtime_t actualDuration = system_time() - startTime; 98 //printf("duration: %lld vs %lld\n", actualDuration, duration); 99 // We need to wait for the reply, if reply mode is asynchronous. 100 snooze_until(startTime + targetUnblock + targetReply 101 + 2 * DELIVERY_LATENCY, B_SYSTEM_TIMEBASE); 102 bool actualReplySuccess = invoker.ReplySuccess(); 103 if (!invoker.DirectReply()) 104 actualReplySuccess = replyTarget.ReplySuccess(); 105 // check the results 106 if (actualResult != result) 107 printf("result: %lx vs %lx\n", actualResult, result); 108 CHK(actualResult == result); 109 CHK(target->DeliverySuccess() == deliverySuccess); 110 CHK(actualReplySuccess == replySuccess); 111 CHK(actualDuration > duration - JITTER 112 && actualDuration < duration + JITTER); 113 } 114 115 private: 116 target_kind fTargetKind; 117 }; 118 119 120 //------------------------------------------------------------------------------ 121 122 // constructor 123 SendMessageTester::SendMessageTester() 124 : BThreadedTestCase(), 125 fHandler(NULL), 126 fLooper(NULL) 127 { 128 } 129 130 // constructor 131 SendMessageTester::SendMessageTester(std::string name) 132 : BThreadedTestCase(name), 133 fHandler(NULL), 134 fLooper(NULL) 135 { 136 } 137 138 // destructor 139 SendMessageTester::~SendMessageTester() 140 { 141 if (fLooper) { 142 fLooper->Lock(); 143 if (fHandler) { 144 fLooper->RemoveHandler(fHandler); 145 delete fHandler; 146 } 147 fLooper->Quit(); 148 } 149 } 150 151 // TestUninitialized 152 void 153 SendMessageTester::TestUninitialized() 154 { 155 SMTester tester(TARGET_UNINITIALIZED); 156 // status_t SendMessage(uint32 command, BHandler *replyTo) const 157 NextSubTest(); 158 { 159 SMInvoker1 invoker1(false); 160 SMInvoker1 invoker2(true); 161 tester.Run(invoker1, 0, 0, B_BAD_PORT_ID, false, false, 0); 162 tester.Run(invoker2, 0, 0, B_BAD_PORT_ID, false, false, 0); 163 } 164 // status_t SendMessage(BMessage *message, BHandler *replyTo, 165 // bigtime_t timeout) const 166 NextSubTest(); 167 { 168 SMInvoker2 invoker1(true, false, B_INFINITE_TIMEOUT); 169 SMInvoker2 invoker2(true, true, B_INFINITE_TIMEOUT); 170 tester.Run(invoker1, 0, 0, B_BAD_PORT_ID, false, false, 0); 171 tester.Run(invoker2, 0, 0, B_BAD_PORT_ID, false, false, 0); 172 } 173 // status_t SendMessage(BMessage *message, BMessenger replyTo, 174 // bigtime_t timeout) const 175 NextSubTest(); 176 { 177 SMInvoker3 invoker1(true, false, B_INFINITE_TIMEOUT); 178 SMInvoker3 invoker2(true, true, B_INFINITE_TIMEOUT); 179 tester.Run(invoker1, 0, 0, B_BAD_PORT_ID, false, false, 0); 180 tester.Run(invoker2, 0, 0, B_BAD_PORT_ID, false, false, 0); 181 } 182 // status_t SendMessage(uint32 command, BMessage *reply) const 183 NextSubTest(); 184 { 185 SMInvoker4 invoker1(false); 186 SMInvoker4 invoker2(true); 187 // We check the parameters first. 188 #ifdef TEST_OBOS 189 tester.Run(invoker1, 0, 0, B_BAD_VALUE, false, false, 0); 190 #else 191 tester.Run(invoker1, 0, 0, B_BAD_PORT_ID, false, false, 0); 192 #endif 193 tester.Run(invoker2, 0, 0, B_BAD_PORT_ID, false, false, 0); 194 } 195 // status_t SendMessage(BMessage *message, BMessage *reply, 196 // bigtime_t deliveryTimeout, 197 // bigtime_t replyTimeout) const 198 NextSubTest(); 199 { 200 SMInvoker5 invoker1(true, false, B_INFINITE_TIMEOUT, 201 B_INFINITE_TIMEOUT); 202 SMInvoker5 invoker2(true, true, B_INFINITE_TIMEOUT, 203 B_INFINITE_TIMEOUT); 204 #ifdef TEST_OBOS 205 tester.Run(invoker1, 0, 0, B_BAD_VALUE, false, false, 0); 206 #else 207 tester.Run(invoker1, 0, 0, B_BAD_PORT_ID, false, false, 0); 208 #endif 209 tester.Run(invoker2, 0, 0, B_BAD_PORT_ID, false, false, 0); 210 } 211 } 212 213 // TestInitialized 214 void 215 SendMessageTester::TestInitialized(SMTester &tester) 216 { 217 // status_t SendMessage(uint32 command, BHandler *replyTo) const 218 NextSubTest(); 219 { 220 SMInvoker1 invoker1(false); 221 SMInvoker1 invoker2(true); 222 tester.Run(invoker1, 0, 0, B_OK, true, false, 0); 223 tester.Run(invoker2, 0, 0, B_OK, true, true, 0); 224 } 225 // status_t SendMessage(BMessage *message, BHandler *replyTo, 226 // bigtime_t timeout) const 227 NextSubTest(); 228 { 229 // R5 crashes when passing a NULL message. 230 #ifndef TEST_R5 231 SMInvoker2 invoker1(false, false, B_INFINITE_TIMEOUT); 232 tester.Run(invoker1, 0, 0, B_BAD_VALUE, false, false, 0); 233 #endif 234 } 235 NextSubTest(); 236 { 237 SMInvoker2 invoker1(true, false, B_INFINITE_TIMEOUT); 238 SMInvoker2 invoker2(true, true, B_INFINITE_TIMEOUT); 239 tester.Run(invoker1, 0, 0, B_OK, true, false, 0); 240 tester.Run(invoker2, 0, 0, B_OK, true, true, 0); 241 } 242 NextSubTest(); 243 { 244 SMInvoker2 invoker1(true, false, 0); 245 SMInvoker2 invoker2(true, true, 0); 246 tester.Run(invoker1, 0, 0, B_OK, true, false, 0); 247 tester.Run(invoker2, 0, 0, B_OK, true, true, 0); 248 tester.Run(invoker1, 20000, 0, B_WOULD_BLOCK, false, false, 0); 249 tester.Run(invoker2, 20000, 0, B_WOULD_BLOCK, false, false, 0); 250 } 251 NextSubTest(); 252 { 253 SMInvoker2 invoker1(true, false, 20000); 254 SMInvoker2 invoker2(true, true, 20000); 255 tester.Run(invoker1, 10000, 0, B_OK, true, false, 10000); 256 tester.Run(invoker2, 10000, 0, B_OK, true, true, 10000); 257 tester.Run(invoker1, 40000, 0, B_TIMED_OUT, false, false, 20000); 258 tester.Run(invoker2, 40000, 0, B_TIMED_OUT, false, false, 20000); 259 } 260 // status_t SendMessage(BMessage *message, BMessenger replyTo, 261 // bigtime_t timeout) const 262 NextSubTest(); 263 { 264 // R5 crashes when passing a NULL message. 265 #ifndef TEST_R5 266 SMInvoker3 invoker1(false, false, B_INFINITE_TIMEOUT); 267 tester.Run(invoker1, 0, 0, B_BAD_VALUE, false, false, 0); 268 #endif 269 } 270 NextSubTest(); 271 { 272 SMInvoker3 invoker1(true, false, B_INFINITE_TIMEOUT); 273 SMInvoker3 invoker2(true, true, B_INFINITE_TIMEOUT); 274 tester.Run(invoker1, 0, 0, B_OK, true, false, 0); 275 tester.Run(invoker2, 0, 0, B_OK, true, true, 0); 276 } 277 NextSubTest(); 278 { 279 SMInvoker3 invoker1(true, false, 0); 280 SMInvoker3 invoker2(true, true, 0); 281 tester.Run(invoker1, 0, 0, B_OK, true, false, 0); 282 tester.Run(invoker2, 0, 0, B_OK, true, true, 0); 283 tester.Run(invoker1, 20000, 0, B_WOULD_BLOCK, false, false, 0); 284 tester.Run(invoker2, 20000, 0, B_WOULD_BLOCK, false, false, 0); 285 } 286 NextSubTest(); 287 { 288 SMInvoker3 invoker1(true, false, 20000); 289 SMInvoker3 invoker2(true, true, 20000); 290 tester.Run(invoker1, 10000, 0, B_OK, true, false, 10000); 291 tester.Run(invoker2, 10000, 0, B_OK, true, true, 10000); 292 tester.Run(invoker1, 40000, 0, B_TIMED_OUT, false, false, 20000); 293 tester.Run(invoker2, 40000, 0, B_TIMED_OUT, false, false, 20000); 294 } 295 // status_t SendMessage(uint32 command, BMessage *reply) const 296 NextSubTest(); 297 { 298 // R5 crashes when passing a NULL reply message 299 #ifndef TEST_R5 300 SMInvoker4 invoker1(false); 301 #endif 302 SMInvoker4 invoker2(true); 303 #ifndef TEST_R5 304 tester.Run(invoker1, 20000, 20000, B_BAD_VALUE, false, false, 0); 305 #endif 306 tester.Run(invoker2, 20000, 20000, B_OK, true, true, 40000); 307 } 308 // status_t SendMessage(BMessage *message, BMessage *reply, 309 // bigtime_t deliveryTimeout, 310 // bigtime_t replyTimeout) const 311 NextSubTest(); 312 { 313 // R5 crashes when passing a NULL message. 314 #ifndef TEST_R5 315 SMInvoker5 invoker1(false, true, B_INFINITE_TIMEOUT, 316 B_INFINITE_TIMEOUT); 317 tester.Run(invoker1, 0, 0, B_BAD_VALUE, false, false, 0); 318 #endif 319 } 320 NextSubTest(); 321 { 322 SMInvoker5 invoker1(true, true, B_INFINITE_TIMEOUT, 323 B_INFINITE_TIMEOUT); 324 SMInvoker5 invoker2(true, true, B_INFINITE_TIMEOUT, 0); 325 SMInvoker5 invoker3(true, true, B_INFINITE_TIMEOUT, 20000); 326 tester.Run(invoker1, 0, 0, B_OK, true, true, 0); 327 tester.Run(invoker1, 10000, 0, B_OK, true, true, 10000); 328 tester.Run(invoker1, 0, 10000, B_OK, true, true, 10000); 329 // These two are race-conditional: The sending task must be pre-empted 330 // before reading from the reply port and the target must reply before 331 // the sending task gets another time slice. 332 // tester.Run(invoker2, 0, 0, B_OK, true, true, 0); 333 // tester.Run(invoker2, 10000, 0, B_OK, true, true, 10000); 334 tester.Run(invoker2, 0, 10000, B_WOULD_BLOCK, true, false, 0); 335 tester.Run(invoker3, 0, 10000, B_OK, true, true, 10000); 336 tester.Run(invoker3, 20000, 10000, B_OK, true, true, 30000); 337 tester.Run(invoker3, 0, 30000, B_TIMED_OUT, true, false, 20000); 338 } 339 NextSubTest(); 340 { 341 SMInvoker5 invoker1(true, true, 0, B_INFINITE_TIMEOUT); 342 SMInvoker5 invoker2(true, true, 0, 0); 343 SMInvoker5 invoker3(true, true, 0, 20000); 344 tester.Run(invoker1, 0, 0, B_OK, true, true, 0); 345 tester.Run(invoker1, 10000, 0, B_WOULD_BLOCK, false, false, 0); 346 tester.Run(invoker1, 0, 10000, B_OK, true, true, 10000); 347 // This one is race-conditional: The sending task must be pre-empted 348 // before reading from the reply port and the target must reply before 349 // the sending task gets another time slice. 350 // tester.Run(invoker2, 0, 0, B_OK, true, true, 0); 351 tester.Run(invoker2, 10000, 0, B_WOULD_BLOCK, false, false, 0); 352 tester.Run(invoker2, 0, 10000, B_WOULD_BLOCK, true, false, 0); 353 tester.Run(invoker3, 0, 10000, B_OK, true, true, 10000); 354 tester.Run(invoker3, 10000, 10000, B_WOULD_BLOCK, false, false, 0); 355 tester.Run(invoker3, 0, 30000, B_TIMED_OUT, true, false, 20000); 356 } 357 NextSubTest(); 358 { 359 SMInvoker5 invoker1(true, true, 20000, B_INFINITE_TIMEOUT); 360 SMInvoker5 invoker2(true, true, 20000, 0); 361 SMInvoker5 invoker3(true, true, 20000, 20000); 362 tester.Run(invoker1, 0, 0, B_OK, true, true, 0); 363 tester.Run(invoker1, 10000, 0, B_OK, true, true, 10000); 364 tester.Run(invoker1, 30000, 0, B_TIMED_OUT, false, false, 20000); 365 tester.Run(invoker1, 10000, 20000, B_OK, true, true, 30000); 366 // These two are race-conditional: The sending task must be pre-empted 367 // before reading from the reply port and the target must reply before 368 // the sending task gets another time slice. 369 // tester.Run(invoker2, 0, 0, B_OK, true, true, 0); 370 // tester.Run(invoker2, 10000, 0, B_OK, true, true, 0); 371 tester.Run(invoker2, 30000, 0, B_TIMED_OUT, false, false, 20000); 372 tester.Run(invoker2, 0, 10000, B_WOULD_BLOCK, true, false, 0); 373 tester.Run(invoker3, 10000, 10000, B_OK, true, true, 20000); 374 tester.Run(invoker3, 30000, 10000, B_TIMED_OUT, false, false, 20000); 375 tester.Run(invoker3, 10000, 30000, B_TIMED_OUT, true, false, 30000); 376 } 377 } 378 379 /* 380 The different SendMessage() flavors. 381 */ 382 void SendMessageTester::SendMessageTest1() 383 { 384 TestUninitialized(); 385 target_kind targetKinds[] = { 386 TARGET_LOCAL_PREFERRED, 387 TARGET_LOCAL_SPECIFIC, 388 TARGET_REMOTE_PREFERRED, 389 TARGET_REMOTE_SPECIFIC 390 }; 391 int32 targetKindCount = sizeof(targetKinds) / sizeof(target_kind); 392 for (int32 i = 0; i < targetKindCount; i++) { 393 SMTester tester(targetKinds[i]); 394 TestInitialized(tester); 395 } 396 } 397 398 399 Test* SendMessageTester::Suite() 400 { 401 typedef BThreadedTestCaller<SendMessageTester> TC; 402 403 TestSuite* testSuite = new TestSuite; 404 405 ADD_TEST4(BMessenger, testSuite, SendMessageTester, SendMessageTest1); 406 407 return testSuite; 408 } 409 410 411