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 34enum 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 43class SMTester { 44public: 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 106if (actualResult != result) 107printf("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 115private: 116 target_kind fTargetKind; 117}; 118 119 120//------------------------------------------------------------------------------ 121 122// constructor 123SendMessageTester::SendMessageTester() 124 : BThreadedTestCase(), 125 fHandler(NULL), 126 fLooper(NULL) 127{ 128} 129 130// constructor 131SendMessageTester::SendMessageTester(std::string name) 132 : BThreadedTestCase(name), 133 fHandler(NULL), 134 fLooper(NULL) 135{ 136} 137 138// destructor 139SendMessageTester::~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 152void 153SendMessageTester::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 214void 215SendMessageTester::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 */ 382void 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 399Test* 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