Some more BLooper unit tests, with some minor resulting tweaks to BLooper.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@264 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
ejakowatz 2002-07-17 06:18:27 +00:00
parent 4f139d7754
commit 38f5ceca01
9 changed files with 483 additions and 28 deletions

View File

@ -271,7 +271,6 @@ bool BLooper::IsMessageWaiting() const
{
if (!IsLocked())
{
// TODO: test
debugger("The Looper must be locked before calling IsMsgWaiting");
return false;
}
@ -337,8 +336,6 @@ bool BLooper::RemoveHandler(BHandler* handler)
debugger("Looper must be locked before calling RemoveHandler.");
}
// TODO: test
// Need to ensure this algo reflects what actually happens
if (handler->Looper() == this && fHandlers.RemoveItem(handler))
{
if (handler == fPreferred)
@ -370,7 +367,10 @@ BHandler* BLooper::HandlerAt(int32 index) const
//------------------------------------------------------------------------------
int32 BLooper::IndexOf(BHandler* handler) const
{
AssertLocked();
if (!IsLocked())
{
debugger("Looper must be locked before calling IndexOf.");
}
// TODO: test
// ensure the B_ERROR gets returned if the handler isn't in the list

View File

@ -1,4 +1,25 @@
MessageQueue()
BLooper(const char* name = NULL,
int32 priority = B_NORMAL_PRIORITY,
int32 port_capacity = B_LOOPER_PORT_DEFAULT_CAPACITY);
~BLooper();
BLooper(BMessage* data);
Instantiate(BMessage* data);
Archive(BMessage* data, bool deep = true) const;
PostMessage(uint32 command);
PostMessage(BMessage* message);
PostMessage(uint32 command,
BHandler* handler,
BHandler* reply_to = NULL);
PostMessage(BMessage* message,
BHandler* handler,
BHandler* reply_to = NULL);
DispatchMessage(BMessage* message, BHandler* handler);
MessageReceived(BMessage* msg);
CurrentMessage() const;
DetachCurrentMessage();
MessageQueue() const;
IsMessageWaiting()
--------------
case 1: looper is unlocked and queue is empty
case 2: looper is unlocked and queue is filled
@ -6,10 +27,59 @@ case 3: looper is locked and queue is empty
case 4: looper is locked and queue is filled
case 5: looper is locked, message is posted, queue is emptied
AddHandler(BHandler* handler);
RemoveHandler(BHandler* handler)
--------------
case : handler is NULL
case : handler doesn't belong to this looper
case : handler is valid, looper is unlocked
case : handler doesn't belong to this looper, looper is unlocked
case : handler has filters; FilterList() should be NULL on remove
case 1: handler is NULL
case 2: handler doesn't belong to this looper
case 3: handler is valid, looper is unlocked
case 4: handler doesn't belong to this looper, looper is unlocked
case 5: handler has filters; FilterList() should be NULL on remove
CountHandlers() const;
--------------
case : No handlers added
case : Several handlers added, then removed
HandlerAt(int32 index) const;
--------------
case : No handlers added, check for looper itself
case : Index out of range (CountHandlers() + 1)
case : Several handlers added, checked against expected indices
IndexOf(BHandler* handler) const;
--------------
case 1: handler is NULL
case 2: handler is valid, doesn't belong to this looper
case 3: handler is valid, belongs to looper
case 4: handler is valid, one of many added and removed
case 5: handler is valid, looper is unlocked
PreferredHandler() const;
SetPreferredHandler(BHandler* handler);
Run();
Quit();
QuitRequested();
Lock();
Unlock();
IsLocked() const;
LockWithTimeout(bigtime_t timeout);
Thread() const;
Team() const;
LooperForThread(thread_id tid);
LockingThread() const;
CountLocks() const;
CountLockRequests() const;
Sem() const;
ResolveSpecifier(BMessage* msg,
int32 index,
BMessage* specifier,
int32 form,
const char* property);
GetSupportedSuites(BMessage* data);
AddCommonFilter(BMessageFilter* filter);
RemoveCommonFilter(BMessageFilter* filter);
SetCommonFilterList(BList* filters);
CommonFilterList() const;
Perform(perform_code d, void* arg);

View File

@ -0,0 +1,77 @@
//------------------------------------------------------------------------------
// CountHandlersTest.cpp
//
//------------------------------------------------------------------------------
// Standard Includes -----------------------------------------------------------
// System Includes -------------------------------------------------------------
#include <Handler.h>
#include <Looper.h>
// Project Includes ------------------------------------------------------------
// Local Includes --------------------------------------------------------------
#include "CountHandlersTest.h"
// Local Defines ---------------------------------------------------------------
// Globals ---------------------------------------------------------------------
//------------------------------------------------------------------------------
/**
CountHandlers()
@case No handlers added
@results
*/
void TCountHandlersTest::CountHandlersTest1()
{
BLooper Looper;
CPPUNIT_ASSERT(Looper.CountHandlers() == 1);
}
//------------------------------------------------------------------------------
/**
CountHandlers()
@case Several handlers added, then removed
@results
*/
void TCountHandlersTest::CountHandlersTest2()
{
BLooper Looper;
BHandler Handler1;
BHandler Handler2;
BHandler Handler3;
Looper.AddHandler(&Handler1);
CPPUNIT_ASSERT(Looper.CountHandlers() == 2);
Looper.AddHandler(&Handler2);
CPPUNIT_ASSERT(Looper.CountHandlers() == 3);
Looper.AddHandler(&Handler3);
CPPUNIT_ASSERT(Looper.CountHandlers() == 4);
Looper.RemoveHandler(&Handler3);
CPPUNIT_ASSERT(Looper.CountHandlers() == 3);
Looper.RemoveHandler(&Handler2);
CPPUNIT_ASSERT(Looper.CountHandlers() == 2);
Looper.RemoveHandler(&Handler1);
CPPUNIT_ASSERT(Looper.CountHandlers() == 1);
}
//------------------------------------------------------------------------------
TestSuite* TCountHandlersTest::Suite()
{
TestSuite* suite = new TestSuite("BLooper::CountHandlers()");
ADD_TEST(suite, TCountHandlersTest, CountHandlersTest1);
ADD_TEST(suite, TCountHandlersTest, CountHandlersTest2);
return suite;
}
//------------------------------------------------------------------------------
/*
* $Log $
*
* $Id $
*
*/

View File

@ -0,0 +1,42 @@
//------------------------------------------------------------------------------
// CountHandlersTest.h
//
//------------------------------------------------------------------------------
#ifndef COUNTHANDLERSTEST_H
#define COUNTHANDLERSTEST_H
// Standard Includes -----------------------------------------------------------
// System Includes -------------------------------------------------------------
// Project Includes ------------------------------------------------------------
// Local Includes --------------------------------------------------------------
#include "../common.h"
// Local Defines ---------------------------------------------------------------
// Globals ---------------------------------------------------------------------
class TCountHandlersTest : public TestCase
{
public:
TCountHandlersTest() {;}
TCountHandlersTest(std::string name) : TestCase(name) {;}
void CountHandlersTest1();
void CountHandlersTest2();
static TestSuite* Suite();
};
#endif //COUNTHANDLERSTEST_H
/*
* $Log $
*
* $Id $
*
*/

View File

@ -0,0 +1,181 @@
//------------------------------------------------------------------------------
// IndexOfTest.cpp
//
//------------------------------------------------------------------------------
// Standard Includes -----------------------------------------------------------
// System Includes -------------------------------------------------------------
#include <Handler.h>
#include <Looper.h>
// Project Includes ------------------------------------------------------------
// Local Includes --------------------------------------------------------------
#include "IndexOfTest.h"
// Local Defines ---------------------------------------------------------------
// Globals ---------------------------------------------------------------------
//------------------------------------------------------------------------------
/**
IndexOf(BHandler* handler)
@case handler is NULL
@param handler NULL
@results IndexOf() returns B_ERROR
*/
void TIndexOfTest::IndexOfTest1()
{
BLooper Looper;
CPPUNIT_ASSERT(Looper.IndexOf(NULL) == B_ERROR);
}
//------------------------------------------------------------------------------
/**
IndexOf(BHandler* handler)
@case handler is valid, doesn't belong to this looper
@param handler Valid BHandler pointer, not assigned to this looper
@results IndexOf() returns B_ERROR
*/
void TIndexOfTest::IndexOfTest2()
{
BLooper Looper;
BHandler Handler;
CPPUNIT_ASSERT(Looper.IndexOf(&Handler) == B_ERROR);
}
//------------------------------------------------------------------------------
/**
IndexOf(BHandler* handler)
@case handler is valid, belongs to looper
@param handler Valid BHandler pointer, assigned to this looper
@results IndexOf returns 1
*/
void TIndexOfTest::IndexOfTest3()
{
BLooper Looper;
BHandler Handler;
Looper.AddHandler(&Handler);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler) == 1);
}
//------------------------------------------------------------------------------
/**
IndexOf(BHandler* handler)
@case handler is valid, one of many added and removed
@param handler Valid BHandler pointer, assigned to this looper
@results IndexOf() returns correct index for each handler
*/
void TIndexOfTest::IndexOfTest4()
{
BLooper Looper;
BHandler Handler1;
BHandler Handler2;
BHandler Handler3;
BHandler Handler4;
BHandler Handler5;
Looper.AddHandler(&Handler1);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler1) == 1);
Looper.AddHandler(&Handler2);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler1) == 1);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler2) == 2);
Looper.AddHandler(&Handler3);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler1) == 1);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler2) == 2);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler3) == 3);
Looper.AddHandler(&Handler4);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler1) == 1);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler2) == 2);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler3) == 3);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler4) == 4);
Looper.AddHandler(&Handler5);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler1) == 1);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler2) == 2);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler3) == 3);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler4) == 4);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler5) == 5);
// Now we remove them
Looper.RemoveHandler(&Handler5);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler1) == 1);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler2) == 2);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler3) == 3);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler4) == 4);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler5) == B_ERROR);
Looper.RemoveHandler(&Handler4);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler1) == 1);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler2) == 2);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler3) == 3);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler4) == B_ERROR);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler5) == B_ERROR);
Looper.RemoveHandler(&Handler3);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler1) == 1);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler2) == 2);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler3) == B_ERROR);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler4) == B_ERROR);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler5) == B_ERROR);
Looper.RemoveHandler(&Handler2);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler1) == 1);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler2) == B_ERROR);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler3) == B_ERROR);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler4) == B_ERROR);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler5) == B_ERROR);
Looper.RemoveHandler(&Handler1);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler1) == B_ERROR);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler2) == B_ERROR);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler3) == B_ERROR);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler4) == B_ERROR);
CPPUNIT_ASSERT(Looper.IndexOf(&Handler5) == B_ERROR);
}
//------------------------------------------------------------------------------
/**
IndexOf(BHandler* handler)
@case handler is valid, looper is unlocked
@param handler Valid BHandler pointer, assigned to this looper
@results IndexOf returns 1. Debugger message "Looper must be locked
before calling IndexOf."
*/
void TIndexOfTest::IndexOfTest5()
{
DEBUGGER_ESCAPE;
BLooper Looper;
BHandler Handler;
Looper.AddHandler(&Handler);
Looper.Unlock();
CPPUNIT_ASSERT(Looper.IndexOf(&Handler) == 1);
}
//------------------------------------------------------------------------------
/**
IndexOf(BHandler* handler)
@case handler is "this"
@param handler The looper's this pointer
@result IndexOf() returns 0
*/
void TIndexOfTest::IndexOfTest6()
{
BLooper Looper;
CPPUNIT_ASSERT(Looper.IndexOf(&Looper) == 0);
}
//------------------------------------------------------------------------------
TestSuite* TIndexOfTest::Suite()
{
TestSuite* suite = new TestSuite("BLooper::IndexOf(BHandler*)");
ADD_TEST(suite, TIndexOfTest, IndexOfTest1);
ADD_TEST(suite, TIndexOfTest, IndexOfTest2);
ADD_TEST(suite, TIndexOfTest, IndexOfTest3);
ADD_TEST(suite, TIndexOfTest, IndexOfTest4);
ADD_TEST(suite, TIndexOfTest, IndexOfTest5);
ADD_TEST(suite, TIndexOfTest, IndexOfTest6);
return suite;
}
//------------------------------------------------------------------------------
/*
* $Log $
*
* $Id $
*
*/

View File

@ -0,0 +1,46 @@
//------------------------------------------------------------------------------
// IndexOfTest.h
//
//------------------------------------------------------------------------------
#ifndef INDEXOFTEST_H
#define INDEXOFTEST_H
// Standard Includes -----------------------------------------------------------
// System Includes -------------------------------------------------------------
// Project Includes ------------------------------------------------------------
// Local Includes --------------------------------------------------------------
#include "../common.h"
// Local Defines ---------------------------------------------------------------
// Globals ---------------------------------------------------------------------
class TIndexOfTest : public TestCase
{
public:
TIndexOfTest() {;}
TIndexOfTest(std::string name) : TestCase(name) {;}
void IndexOfTest1();
void IndexOfTest2();
void IndexOfTest3();
void IndexOfTest4();
void IndexOfTest5();
void IndexOfTest6();
static TestSuite* Suite();
};
#endif //INDEXOFTEST_H
/*
* $Log $
*
* $Id $
*
*/

View File

@ -23,7 +23,11 @@
port_id _get_looper_port_(const BLooper* looper);
//------------------------------------------------------------------------------
//case 1: looper is unlocked and queue is empty
/**
IsMessageWaiting()
@case looper is unlocked and queue is empty
@results IsMessageWaiting() returns false
*/
void TIsMessageWaitingTest::IsMessageWaiting1()
{
DEBUGGER_ESCAPE;
@ -33,7 +37,11 @@ void TIsMessageWaitingTest::IsMessageWaiting1()
CPPUNIT_ASSERT(!Looper.IsMessageWaiting());
}
//------------------------------------------------------------------------------
//case 2: looper is unlocked and queue is filled
/**
IsMessageWaiting()
@case looper is unlocked and queue is filled
@results IsMessageWaiting() returns false
*/
void TIsMessageWaitingTest::IsMessageWaiting2()
{
DEBUGGER_ESCAPE;
@ -44,7 +52,15 @@ void TIsMessageWaitingTest::IsMessageWaiting2()
CPPUNIT_ASSERT(!Looper.IsMessageWaiting());
}
//------------------------------------------------------------------------------
//case 3: looper is locked and queue is empty
/**
IsMessageWaiting()
@case looper is locked and queue is empty
@results IsMessageWaiting() returns false
@note R5 will return true in this test. The extra testing below
indicates that the R5 version probably returns != 0 from
port_buffer_size_etc(), resulting in an incorrect true in cases
where the operation would block.
*/
void TIsMessageWaitingTest::IsMessageWaiting3()
{
BLooper Looper;
@ -73,7 +89,11 @@ void TIsMessageWaitingTest::IsMessageWaiting3()
#endif
}
//------------------------------------------------------------------------------
//case 4: looper is locked and queue is filled
/**
IsMessageWaiting()
@case looper is locked and queue is filled
@results IsMessageWaiting() returns true.
*/
void TIsMessageWaitingTest::IsMessageWaiting4()
{
BLooper Looper;
@ -82,7 +102,29 @@ void TIsMessageWaitingTest::IsMessageWaiting4()
CPPUNIT_ASSERT(Looper.IsMessageWaiting());
}
//------------------------------------------------------------------------------
//case 5: looper is locked, message is posted, queue is empty
/**
IsMessageWaiting()
@case looper is locked, message is posted, queue is empty
@results IsMessageWaiting() returns true.
@note The first assert always worked under R5 but only sometimes for
OBOS. Answer: the OBOS implementation of BLooper was attempting
to lock itself prior to fetching the message from the queue. I
moved the lock attempt after the fetch and it worked the same.
I realized that if the system was loaded heavily enough, the
assert might still fail simply because the looper would not have
had enough time to get to the fetch (thereby emptying the queue),
so the assert is no longer used. If we do manage to call
IsMessageWaiting() before the fetch happens (which does happen
every once in a while), we still get a true result because the
port buffer is checked. Later: it's finally dawned on me that
if the system is loaded *lightly* enough, the message will not
only get fetched, but popped off the queue as well. Since R5
returns the bogus true, the second assert works even when the
message has been de-queued. OBOS, of course, will (correctly)
fail the assert in that situation. Unfortunately, that renders
this test completely unreliable. It is pulled until a fully
reliable test can be devised.
*/
void TIsMessageWaitingTest::IsMessageWaiting5()
{
BLooper* Looper = new BLooper(__PRETTY_FUNCTION__);
@ -94,13 +136,6 @@ void TIsMessageWaitingTest::IsMessageWaiting5()
// CPPUNIT_ASSERT(Looper->MessageQueue()->IsEmpty());
CPPUNIT_ASSERT(Looper->IsMessageWaiting());
// Tests to help figure out why the first assert above always worked under R5
// but only sometimes for OBOS. Answer: the OBOS implementation of BLooper
// was attempting to lock itself prior to fetching the message from the queue.
// I moved the lock attempt after the fetch and it worked the same. I realized
// that if the system was loaded heavily enough, the assert might still fail
// simply because the looper would not had enough time to get to the fetch
// (thereby emptying the queue), so the assert is no longer used.
#if 0
ssize_t count;
do
@ -139,7 +174,9 @@ Test* TIsMessageWaitingTest::Suite()
ADD_TEST(suite, TIsMessageWaitingTest, IsMessageWaiting2);
ADD_TEST(suite, TIsMessageWaitingTest, IsMessageWaiting3);
ADD_TEST(suite, TIsMessageWaitingTest, IsMessageWaiting4);
ADD_TEST(suite, TIsMessageWaitingTest, IsMessageWaiting5);
// See note for test
// ADD_TEST(suite, TIsMessageWaitingTest, IsMessageWaiting5);
return suite;
}

View File

@ -4,6 +4,8 @@ CommonUnitTest BLooperTester
: main.cpp
IsMessageWaitingTest.cpp
RemoveHandlerTest.cpp
IndexOfTest.cpp
CountHandlersTest.cpp
: kits app
: <boot!home!config!lib>libopenbeos.so be stdc++.r4
: be stdc++.r4

View File

@ -11,17 +11,15 @@
#include <be/app/Messenger.h>
#include <be/app/MessageFilter.h>
#if !defined(SYSTEM_TEST)
#include <be/app/Looper.h>
#else
#include "../../../../source/lib/application/headers/Looper.h"
#endif
#include <Looper.h>
// Project Includes ------------------------------------------------------------
// Local Includes --------------------------------------------------------------
#include "IsMessageWaitingTest.h"
#include "RemoveHandlerTest.h"
#include "IndexOfTest.h"
#include "CountHandlersTest.h"
// Local Defines ---------------------------------------------------------------
@ -43,6 +41,8 @@ Test* addonTestFunc(void)
tests->addTest(TIsMessageWaitingTest::Suite());
tests->addTest(TRemoveHandlerTest::Suite());
tests->addTest(TIndexOfTest::Suite());
tests->addTest(TCountHandlersTest::Suite());
return tests;
}