#include <stdio.h>
#include <Message.h>
#include <OS.h>
#include <Handler.h>
#include <Looper.h>
#include <Messenger.h>
#include <TestUtils.h>
#include <ThreadedTestCaller.h>
#include <cppunit/TestSuite.h>
#include "Helpers.h"
#include "SendMessageTester.h"
#include "SMInvoker.h"
#include "SMLooper.h"
#include "SMReplyTarget.h"
#include "SMTarget.h"
enum target_kind {
TARGET_UNINITIALIZED,
TARGET_LOCAL_PREFERRED,
TARGET_LOCAL_SPECIFIC,
TARGET_REMOTE_PREFERRED,
TARGET_REMOTE_SPECIFIC,
};
class SMTester {
public:
SMTester(target_kind targetKind)
: fTargetKind(targetKind)
{
}
~SMTester()
{
}
void Run(SMInvoker &invoker, bigtime_t targetUnblock,
bigtime_t targetReply, status_t result, bool deliverySuccess,
bool replySuccess, bigtime_t duration)
{
enum { JITTER = 10000 };
enum { SETUP_LATENCY = 100000 };
enum { DELIVERY_LATENCY = 10000 };
enum { TARGET_HEAD_START = 1000 };
if (targetUnblock == 0)
targetUnblock = -TARGET_HEAD_START;
SMTarget *target = NULL;
switch (fTargetKind) {
case TARGET_UNINITIALIZED:
target = new SMTarget;
break;
case TARGET_LOCAL_PREFERRED:
target = new LocalSMTarget(true);
break;
case TARGET_LOCAL_SPECIFIC:
target = new LocalSMTarget(false);
break;
case TARGET_REMOTE_PREFERRED:
target = new RemoteSMTarget(true);
break;
case TARGET_REMOTE_SPECIFIC:
target = new RemoteSMTarget(false);
break;
}
AutoDeleter<SMTarget> deleter(target);
SMReplyTarget replyTarget;
BHandler *replyHandler = replyTarget.Handler();
BMessenger replyMessenger = replyTarget.Messenger();
bigtime_t startTime = system_time() + SETUP_LATENCY;
target->Init(startTime + targetUnblock, targetReply);
BMessenger targetMessenger = target->Messenger();
snooze_until(startTime, B_SYSTEM_TIMEBASE);
status_t actualResult = invoker.Invoke(targetMessenger, replyHandler,
replyMessenger);
bigtime_t actualDuration = system_time() - startTime;
snooze_until(startTime + targetUnblock + targetReply
+ 2 * DELIVERY_LATENCY, B_SYSTEM_TIMEBASE);
bool actualReplySuccess = invoker.ReplySuccess();
if (!invoker.DirectReply())
actualReplySuccess = replyTarget.ReplySuccess();
if (actualResult != result)
printf("result: %lx vs %lx\n", actualResult, result);
CHK(actualResult == result);
CHK(target->DeliverySuccess() == deliverySuccess);
CHK(actualReplySuccess == replySuccess);
CHK(actualDuration > duration - JITTER
&& actualDuration < duration + JITTER);
}
private:
target_kind fTargetKind;
};
SendMessageTester::SendMessageTester()
: BThreadedTestCase(),
fHandler(NULL),
fLooper(NULL)
{
}
SendMessageTester::SendMessageTester(std::string name)
: BThreadedTestCase(name),
fHandler(NULL),
fLooper(NULL)
{
}
SendMessageTester::~SendMessageTester()
{
if (fLooper) {
fLooper->Lock();
if (fHandler) {
fLooper->RemoveHandler(fHandler);
delete fHandler;
}
fLooper->Quit();
}
}
void
SendMessageTester::TestUninitialized()
{
SMTester tester(TARGET_UNINITIALIZED);
NextSubTest();
{
SMInvoker1 invoker1(false);
SMInvoker1 invoker2(true);
tester.Run(invoker1, 0, 0, B_BAD_PORT_ID, false, false, 0);
tester.Run(invoker2, 0, 0, B_BAD_PORT_ID, false, false, 0);
}
NextSubTest();
{
SMInvoker2 invoker1(true, false, B_INFINITE_TIMEOUT);
SMInvoker2 invoker2(true, true, B_INFINITE_TIMEOUT);
tester.Run(invoker1, 0, 0, B_BAD_PORT_ID, false, false, 0);
tester.Run(invoker2, 0, 0, B_BAD_PORT_ID, false, false, 0);
}
NextSubTest();
{
SMInvoker3 invoker1(true, false, B_INFINITE_TIMEOUT);
SMInvoker3 invoker2(true, true, B_INFINITE_TIMEOUT);
tester.Run(invoker1, 0, 0, B_BAD_PORT_ID, false, false, 0);
tester.Run(invoker2, 0, 0, B_BAD_PORT_ID, false, false, 0);
}
NextSubTest();
{
SMInvoker4 invoker1(false);
SMInvoker4 invoker2(true);
#ifdef TEST_OBOS
tester.Run(invoker1, 0, 0, B_BAD_VALUE, false, false, 0);
#else
tester.Run(invoker1, 0, 0, B_BAD_PORT_ID, false, false, 0);
#endif
tester.Run(invoker2, 0, 0, B_BAD_PORT_ID, false, false, 0);
}
NextSubTest();
{
SMInvoker5 invoker1(true, false, B_INFINITE_TIMEOUT,
B_INFINITE_TIMEOUT);
SMInvoker5 invoker2(true, true, B_INFINITE_TIMEOUT,
B_INFINITE_TIMEOUT);
#ifdef TEST_OBOS
tester.Run(invoker1, 0, 0, B_BAD_VALUE, false, false, 0);
#else
tester.Run(invoker1, 0, 0, B_BAD_PORT_ID, false, false, 0);
#endif
tester.Run(invoker2, 0, 0, B_BAD_PORT_ID, false, false, 0);
}
}
void
SendMessageTester::TestInitialized(SMTester &tester)
{
NextSubTest();
{
SMInvoker1 invoker1(false);
SMInvoker1 invoker2(true);
tester.Run(invoker1, 0, 0, B_OK, true, false, 0);
tester.Run(invoker2, 0, 0, B_OK, true, true, 0);
}
NextSubTest();
{
#ifndef TEST_R5
SMInvoker2 invoker1(false, false, B_INFINITE_TIMEOUT);
tester.Run(invoker1, 0, 0, B_BAD_VALUE, false, false, 0);
#endif
}
NextSubTest();
{
SMInvoker2 invoker1(true, false, B_INFINITE_TIMEOUT);
SMInvoker2 invoker2(true, true, B_INFINITE_TIMEOUT);
tester.Run(invoker1, 0, 0, B_OK, true, false, 0);
tester.Run(invoker2, 0, 0, B_OK, true, true, 0);
}
NextSubTest();
{
SMInvoker2 invoker1(true, false, 0);
SMInvoker2 invoker2(true, true, 0);
tester.Run(invoker1, 0, 0, B_OK, true, false, 0);
tester.Run(invoker2, 0, 0, B_OK, true, true, 0);
tester.Run(invoker1, 20000, 0, B_WOULD_BLOCK, false, false, 0);
tester.Run(invoker2, 20000, 0, B_WOULD_BLOCK, false, false, 0);
}
NextSubTest();
{
SMInvoker2 invoker1(true, false, 20000);
SMInvoker2 invoker2(true, true, 20000);
tester.Run(invoker1, 10000, 0, B_OK, true, false, 10000);
tester.Run(invoker2, 10000, 0, B_OK, true, true, 10000);
tester.Run(invoker1, 40000, 0, B_TIMED_OUT, false, false, 20000);
tester.Run(invoker2, 40000, 0, B_TIMED_OUT, false, false, 20000);
}
NextSubTest();
{
#ifndef TEST_R5
SMInvoker3 invoker1(false, false, B_INFINITE_TIMEOUT);
tester.Run(invoker1, 0, 0, B_BAD_VALUE, false, false, 0);
#endif
}
NextSubTest();
{
SMInvoker3 invoker1(true, false, B_INFINITE_TIMEOUT);
SMInvoker3 invoker2(true, true, B_INFINITE_TIMEOUT);
tester.Run(invoker1, 0, 0, B_OK, true, false, 0);
tester.Run(invoker2, 0, 0, B_OK, true, true, 0);
}
NextSubTest();
{
SMInvoker3 invoker1(true, false, 0);
SMInvoker3 invoker2(true, true, 0);
tester.Run(invoker1, 0, 0, B_OK, true, false, 0);
tester.Run(invoker2, 0, 0, B_OK, true, true, 0);
tester.Run(invoker1, 20000, 0, B_WOULD_BLOCK, false, false, 0);
tester.Run(invoker2, 20000, 0, B_WOULD_BLOCK, false, false, 0);
}
NextSubTest();
{
SMInvoker3 invoker1(true, false, 20000);
SMInvoker3 invoker2(true, true, 20000);
tester.Run(invoker1, 10000, 0, B_OK, true, false, 10000);
tester.Run(invoker2, 10000, 0, B_OK, true, true, 10000);
tester.Run(invoker1, 40000, 0, B_TIMED_OUT, false, false, 20000);
tester.Run(invoker2, 40000, 0, B_TIMED_OUT, false, false, 20000);
}
NextSubTest();
{
#ifndef TEST_R5
SMInvoker4 invoker1(false);
#endif
SMInvoker4 invoker2(true);
#ifndef TEST_R5
tester.Run(invoker1, 20000, 20000, B_BAD_VALUE, false, false, 0);
#endif
tester.Run(invoker2, 20000, 20000, B_OK, true, true, 40000);
}
NextSubTest();
{
#ifndef TEST_R5
SMInvoker5 invoker1(false, true, B_INFINITE_TIMEOUT,
B_INFINITE_TIMEOUT);
tester.Run(invoker1, 0, 0, B_BAD_VALUE, false, false, 0);
#endif
}
NextSubTest();
{
SMInvoker5 invoker1(true, true, B_INFINITE_TIMEOUT,
B_INFINITE_TIMEOUT);
SMInvoker5 invoker2(true, true, B_INFINITE_TIMEOUT, 0);
SMInvoker5 invoker3(true, true, B_INFINITE_TIMEOUT, 20000);
tester.Run(invoker1, 0, 0, B_OK, true, true, 0);
tester.Run(invoker1, 10000, 0, B_OK, true, true, 10000);
tester.Run(invoker1, 0, 10000, B_OK, true, true, 10000);
tester.Run(invoker2, 0, 10000, B_WOULD_BLOCK, true, false, 0);
tester.Run(invoker3, 0, 10000, B_OK, true, true, 10000);
tester.Run(invoker3, 20000, 10000, B_OK, true, true, 30000);
tester.Run(invoker3, 0, 30000, B_TIMED_OUT, true, false, 20000);
}
NextSubTest();
{
SMInvoker5 invoker1(true, true, 0, B_INFINITE_TIMEOUT);
SMInvoker5 invoker2(true, true, 0, 0);
SMInvoker5 invoker3(true, true, 0, 20000);
tester.Run(invoker1, 0, 0, B_OK, true, true, 0);
tester.Run(invoker1, 10000, 0, B_WOULD_BLOCK, false, false, 0);
tester.Run(invoker1, 0, 10000, B_OK, true, true, 10000);
tester.Run(invoker2, 10000, 0, B_WOULD_BLOCK, false, false, 0);
tester.Run(invoker2, 0, 10000, B_WOULD_BLOCK, true, false, 0);
tester.Run(invoker3, 0, 10000, B_OK, true, true, 10000);
tester.Run(invoker3, 10000, 10000, B_WOULD_BLOCK, false, false, 0);
tester.Run(invoker3, 0, 30000, B_TIMED_OUT, true, false, 20000);
}
NextSubTest();
{
SMInvoker5 invoker1(true, true, 20000, B_INFINITE_TIMEOUT);
SMInvoker5 invoker2(true, true, 20000, 0);
SMInvoker5 invoker3(true, true, 20000, 20000);
tester.Run(invoker1, 0, 0, B_OK, true, true, 0);
tester.Run(invoker1, 10000, 0, B_OK, true, true, 10000);
tester.Run(invoker1, 30000, 0, B_TIMED_OUT, false, false, 20000);
tester.Run(invoker1, 10000, 20000, B_OK, true, true, 30000);
tester.Run(invoker2, 30000, 0, B_TIMED_OUT, false, false, 20000);
tester.Run(invoker2, 0, 10000, B_WOULD_BLOCK, true, false, 0);
tester.Run(invoker3, 10000, 10000, B_OK, true, true, 20000);
tester.Run(invoker3, 30000, 10000, B_TIMED_OUT, false, false, 20000);
tester.Run(invoker3, 10000, 30000, B_TIMED_OUT, true, false, 30000);
}
}
The different SendMessage() flavors.
*/
void SendMessageTester::SendMessageTest1()
{
TestUninitialized();
target_kind targetKinds[] = {
TARGET_LOCAL_PREFERRED,
TARGET_LOCAL_SPECIFIC,
TARGET_REMOTE_PREFERRED,
TARGET_REMOTE_SPECIFIC
};
int32 targetKindCount = sizeof(targetKinds) / sizeof(target_kind);
for (int32 i = 0; i < targetKindCount; i++) {
SMTester tester(targetKinds[i]);
TestInitialized(tester);
}
}
Test* SendMessageTester::Suite()
{
typedef BThreadedTestCaller<SendMessageTester> TC;
TestSuite* testSuite = new TestSuite;
ADD_TEST4(BMessenger, testSuite, SendMessageTester, SendMessageTest1);
return testSuite;
}