BRoster watching tests added.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1574 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2002-10-18 14:02:04 +00:00
parent 6d8943122a
commit f4e4e1c602
3 changed files with 692 additions and 0 deletions

View File

@ -0,0 +1,462 @@
//------------------------------------------------------------------------------
// RosterWatchingTester.cpp
//
//------------------------------------------------------------------------------
// Standard Includes -----------------------------------------------------------
#include <stdio.h>
#include <utime.h>
// System Includes -------------------------------------------------------------
#include <be/app/Message.h>
#include <be/kernel/OS.h>
#include <AppFileInfo.h>
#include <Application.h>
#include <File.h>
#include <FindDirectory.h>
#include <Handler.h>
#include <Looper.h>
#include <Message.h>
#include <MessageQueue.h>
#include <Path.h>
#include <Roster.h>
#include <String.h>
// Project Includes ------------------------------------------------------------
#include <TestShell.h>
#include <TestUtils.h>
#include <cppunit/TestAssert.h>
// Local Includes --------------------------------------------------------------
#include "AppRunner.h"
#include "RosterWatchingTester.h"
#include "LaunchTesterHelper.h"
#include "RosterTestAppDefs.h"
// Local Defines ---------------------------------------------------------------
// Globals ---------------------------------------------------------------------
//------------------------------------------------------------------------------
static const char *testerSignature
= "application/x-vnd.obos-roster-watching-test";
static const char *appType1 = "application/x-vnd.obos-roster-watching-app1";
static const char *appType2 = "application/x-vnd.obos-roster-watching-app2";
static const char *appType3 = "application/x-vnd.obos-roster-watching-app3";
static const char *appType4 = "application/x-vnd.obos-roster-watching-app4";
//static const char *appType5 = "application/x-vnd.obos-roster-watching-app5";
static const char *testDir = "/tmp/testdir";
static const char *appFile1 = "/tmp/testdir/app1";
static const char *appFile2 = "/tmp/testdir/app2";
static const char *appFile3 = "/tmp/testdir/app3";
static const char *appFile4 = "/tmp/testdir/app4";
//static const char *appFile5 = "/tmp/testdir/app5";
// ref_for_path
static
entry_ref
ref_for_path(const char *filename, bool traverse = true)
{
entry_ref ref;
BEntry entry;
CHK(entry.SetTo(filename, traverse) == B_OK);
CHK(entry.GetRef(&ref) == B_OK);
return ref;
}
// create_app
static
entry_ref
create_app(const char *filename, const char *signature,
bool install = false, bool makeExecutable = true,
uint32 appFlags = B_SINGLE_LAUNCH)
{
BString testApp;
CHK(find_test_app("RosterWatchingTestApp1", &testApp) == B_OK);
system((string("cp ") + testApp.String() + " " + filename).c_str());
if (makeExecutable)
system((string("chmod a+x ") + filename).c_str());
BFile file;
CHK(file.SetTo(filename, B_READ_WRITE) == B_OK);
BAppFileInfo appFileInfo;
CHK(appFileInfo.SetTo(&file) == B_OK);
if (signature)
CHK(appFileInfo.SetSignature(signature) == B_OK);
CHK(appFileInfo.SetAppFlags(appFlags) == B_OK);
if (install && signature)
CHK(BMimeType(signature).Install() == B_OK);
// We write the signature into a separate attribute, just in case we
// decide to also test files without BEOS:APP_SIG attribute.
BString signatureString(signature);
file.WriteAttrString("signature", &signatureString);
return ref_for_path(filename);
}
// app_info_for_team
static
app_info
app_info_for_team(team_id team)
{
app_info info;
CHK(be_roster->GetRunningAppInfo(team, &info) == B_OK);
return info;
}
// check_watching_message
void
check_watching_message(LaunchContext &context, team_id team, int32 &cookie,
const app_info &info, uint32 messageCode)
{
// wait for and get the message
CHK(context.WaitForMessage(team, MSG_MESSAGE_RECEIVED, false,
B_INFINITE_TIMEOUT, cookie));
BMessage *container = context.NextMessageFrom(team, cookie);
CHK(container != NULL);
CHK(container->what == MSG_MESSAGE_RECEIVED);
BMessage message;
CHK(container->FindMessage("message", &message) == B_OK);
// check the message
if (message.what != messageCode)
printf("message.what: %.4s vs messageCode: %.4s\n", (char*)&message.what,
(char*)&messageCode);
CHK(message.what == messageCode);
// team
team_id foundTeam;
CHK(message.FindInt32("be:team", &foundTeam) == B_OK);
CHK(foundTeam == info.team);
// thread
thread_id thread;
CHK(message.FindInt32("be:thread", &thread) == B_OK);
CHK(thread == info.thread);
// signature
const char *signature = NULL;
CHK(message.FindString("be:signature", &signature) == B_OK);
CHK(!strcmp(signature, info.signature));
// ref
entry_ref ref;
CHK(message.FindRef("be:ref", &ref) == B_OK);
CHK(ref == info.ref);
// flags
uint32 flags;
CHK(message.FindInt32("be:flags", (int32*)&flags) == B_OK);
CHK(flags == info.flags);
}
// setUp
void
RosterWatchingTester::setUp()
{
RosterLaunchApp *app = new RosterLaunchApp(testerSignature);
fApplication = app;
app->SetHandler(new RosterBroadcastHandler);
system((string("mkdir ") + testDir).c_str());
}
// tearDown
void
RosterWatchingTester::tearDown()
{
BMimeType(appType1).Delete();
BMimeType(appType2).Delete();
BMimeType(appType3).Delete();
BMimeType(appType4).Delete();
// BMimeType(appType5).Delete();
delete fApplication;
system((string("rm -rf ") + testDir).c_str());
}
// SimpleAppLauncher
class SimpleAppLauncher : public LaunchCaller {
public:
SimpleAppLauncher() : fRef() {}
SimpleAppLauncher(const entry_ref &ref) : fRef(ref) {}
virtual ~SimpleAppLauncher() {}
virtual status_t operator()(const char *type, BList *messages, int32 argc,
const char **argv, team_id *team)
{
return be_roster->Launch(&fRef, (BMessage*)NULL, team);
}
virtual bool SupportsRefs() const { return true; }
virtual const entry_ref *Ref() const { return &fRef; }
virtual LaunchCaller *CloneInternal()
{
return new SimpleAppLauncher;
}
protected:
entry_ref fRef;
};
/*
status_t StartWatching(BMessenger target, uint32 eventMask) const
status_t StopWatching(BMessenger target) const
@case 1 {Start,Stop}Watching() with invalid messenger or invalid
flags; StopWatching() non-watching messenger =>
@results Should return B_OK; B_BAD_VALUE.
*/
void RosterWatchingTester::WatchingTest1()
{
BRoster roster;
BMessenger target;
// not valid, not watching
CHK(roster.StopWatching(target) == B_BAD_VALUE);
// not valid
CHK(roster.StartWatching(target, B_REQUEST_LAUNCHED | B_REQUEST_QUIT
| B_REQUEST_ACTIVATED) == B_OK);
CHK(roster.StopWatching(target) == B_OK);
// invalid flags
CHK(roster.StartWatching(target, 0) == B_OK);
CHK(roster.StopWatching(target) == B_OK);
// valid, but not watching
CHK(roster.StopWatching(be_app_messenger) == B_BAD_VALUE);
}
/*
status_t StartWatching(BMessenger target, uint32 eventMask) const
status_t StopWatching(BMessenger target) const
@case 2 several apps, several watchers, different eventMasks
@results Should return B_OK...
Watching ends, when target has become invalid and the next watching
message is tried to be sent.
*/
void RosterWatchingTester::WatchingTest2()
{
LaunchContext context;
BRoster roster;
// launch app 1
entry_ref ref1(create_app(appFile1, appType1));
SimpleAppLauncher caller1(ref1);
team_id team1;
CHK(context(caller1, appType1, &team1) == B_OK);
context.WaitForMessage(team1, MSG_READY_TO_RUN);
BMessenger target1(NULL, team1);
app_info appInfo1(app_info_for_team(team1));
CHK(roster.StartWatching(target1, B_REQUEST_LAUNCHED | B_REQUEST_QUIT
| B_REQUEST_ACTIVATED) == B_OK);
// messages: app 1
int32 cookie1 = 0;
CHK(context.CheckNextMessage(caller1, team1, cookie1, MSG_STARTED));
CHK(context.CheckMainArgsMessage(caller1, team1, cookie1, &ref1, false));
CHK(context.CheckNextMessage(caller1, team1, cookie1, MSG_READY_TO_RUN));
// launch app 2
entry_ref ref2(create_app(appFile2, appType2, false, true,
B_SINGLE_LAUNCH | B_ARGV_ONLY));
SimpleAppLauncher caller2(ref2);
team_id team2;
CHK(context(caller2, appType2, &team2) == B_OK);
context.WaitForMessage(team2, MSG_READY_TO_RUN);
BMessenger target2(context.AppMessengerFor(team2));
CHK(target2.IsValid());
app_info appInfo2(app_info_for_team(team2));
CHK(roster.StartWatching(target2, B_REQUEST_LAUNCHED) == B_OK);
// messages: app 2
int32 cookie2 = 0;
CHK(context.CheckNextMessage(caller2, team2, cookie2, MSG_STARTED));
CHK(context.CheckMainArgsMessage(caller2, team2, cookie2, &ref2, false));
CHK(context.CheckNextMessage(caller2, team2, cookie2, MSG_READY_TO_RUN));
// messages: app 1
check_watching_message(context, team1, cookie1, appInfo2,
B_SOME_APP_LAUNCHED);
// launch app 3
entry_ref ref3(create_app(appFile3, appType3));
SimpleAppLauncher caller3(ref3);
team_id team3;
CHK(context(caller3, appType3, &team3) == B_OK);
context.WaitForMessage(team3, MSG_READY_TO_RUN);
BMessenger target3(NULL, team3);
app_info appInfo3(app_info_for_team(team3));
CHK(roster.StartWatching(target3, B_REQUEST_QUIT) == B_OK);
// messages: app 3
int32 cookie3 = 0;
CHK(context.CheckNextMessage(caller3, team3, cookie3, MSG_STARTED));
CHK(context.CheckMainArgsMessage(caller3, team3, cookie3, &ref3, false));
CHK(context.CheckNextMessage(caller3, team3, cookie3, MSG_READY_TO_RUN));
// messages: app 2
check_watching_message(context, team2, cookie2, appInfo3,
B_SOME_APP_LAUNCHED);
// messages: app 1
check_watching_message(context, team1, cookie1, appInfo3,
B_SOME_APP_LAUNCHED);
// launch app 4
entry_ref ref4(create_app(appFile4, appType4));
SimpleAppLauncher caller4(ref4);
team_id team4;
CHK(context(caller4, appType4, &team4) == B_OK);
context.WaitForMessage(team4, MSG_READY_TO_RUN);
BMessenger target4(NULL, team4);
app_info appInfo4(app_info_for_team(team4));
// messages: app 4
int32 cookie4 = 0;
CHK(context.CheckNextMessage(caller4, team4, cookie4, MSG_STARTED));
CHK(context.CheckMainArgsMessage(caller4, team4, cookie4, &ref4, false));
CHK(context.CheckNextMessage(caller4, team4, cookie4, MSG_READY_TO_RUN));
// messages: app 3
// none
// messages: app 2
check_watching_message(context, team2, cookie2, appInfo4,
B_SOME_APP_LAUNCHED);
// messages: app 1
check_watching_message(context, team1, cookie1, appInfo4,
B_SOME_APP_LAUNCHED);
// terminate app 4
context.TerminateApp(team4);
// messages: app 3
check_watching_message(context, team3, cookie3, appInfo4,
B_SOME_APP_QUIT);
// messages: app 2
// none
// messages: app 1
check_watching_message(context, team1, cookie1, appInfo4,
B_SOME_APP_QUIT);
// stop watching app 1
CHK(roster.StopWatching(target1) == B_OK);
// terminate app 2
context.TerminateApp(team2);
CHK(roster.StopWatching(target2) == B_OK);
// messages: app 3
check_watching_message(context, team3, cookie3, appInfo2,
B_SOME_APP_QUIT);
// messages: app 1
// none
// terminate app 3
context.TerminateApp(team3);
// OBOS handles app termination a bit different. At the point, when the
// application unregisters itself from the registrar, its port is still
// valid.
#ifdef TEST_R5
CHK(roster.StopWatching(target3) == B_BAD_VALUE);
#else
CHK(roster.StopWatching(target3) == B_OK);
#endif
// messages: app 1
// none
// remaining messages
context.Terminate();
// app 1
CHK(context.CheckNextMessage(caller1, team1, cookie1, MSG_QUIT_REQUESTED));
CHK(context.CheckNextMessage(caller1, team1, cookie1, MSG_TERMINATED));
// app 2
CHK(context.CheckNextMessage(caller2, team2, cookie2, MSG_QUIT_REQUESTED));
CHK(context.CheckNextMessage(caller2, team2, cookie2, MSG_TERMINATED));
// app 3
CHK(context.CheckNextMessage(caller3, team3, cookie3, MSG_QUIT_REQUESTED));
CHK(context.CheckNextMessage(caller3, team3, cookie3, MSG_TERMINATED));
// app 4
CHK(context.CheckNextMessage(caller4, team4, cookie4, MSG_QUIT_REQUESTED));
CHK(context.CheckNextMessage(caller4, team4, cookie4, MSG_TERMINATED));
}
/*
status_t StartWatching(BMessenger target, uint32 eventMask) const
status_t StopWatching(BMessenger target) const
@case 3 call StartWatching() twice, second time with different
masks
@results Should return B_OK. The second call simply overrides the
first one.
*/
void RosterWatchingTester::WatchingTest3()
{
LaunchContext context;
BRoster roster;
// launch app 1
entry_ref ref1(create_app(appFile1, appType1));
SimpleAppLauncher caller1(ref1);
team_id team1;
CHK(context(caller1, appType1, &team1) == B_OK);
context.WaitForMessage(team1, MSG_READY_TO_RUN);
BMessenger target1(NULL, team1);
app_info appInfo1(app_info_for_team(team1));
CHK(roster.StartWatching(target1, B_REQUEST_LAUNCHED | B_REQUEST_QUIT
| B_REQUEST_ACTIVATED) == B_OK);
// messages: app 1
int32 cookie1 = 0;
CHK(context.CheckNextMessage(caller1, team1, cookie1, MSG_STARTED));
CHK(context.CheckMainArgsMessage(caller1, team1, cookie1, &ref1, false));
CHK(context.CheckNextMessage(caller1, team1, cookie1, MSG_READY_TO_RUN));
// app 1: another StartWatching() with different event mask
CHK(roster.StartWatching(target1, B_REQUEST_QUIT) == B_OK);
// launch app 2
entry_ref ref2(create_app(appFile2, appType2, false, true,
B_SINGLE_LAUNCH | B_ARGV_ONLY));
SimpleAppLauncher caller2(ref2);
team_id team2;
CHK(context(caller2, appType2, &team2) == B_OK);
context.WaitForMessage(team2, MSG_READY_TO_RUN);
BMessenger target2(context.AppMessengerFor(team2));
CHK(target2.IsValid());
app_info appInfo2(app_info_for_team(team2));
CHK(roster.StartWatching(target2, B_REQUEST_QUIT) == B_OK);
// messages: app 2
int32 cookie2 = 0;
CHK(context.CheckNextMessage(caller2, team2, cookie2, MSG_STARTED));
CHK(context.CheckMainArgsMessage(caller2, team2, cookie2, &ref2, false));
CHK(context.CheckNextMessage(caller2, team2, cookie2, MSG_READY_TO_RUN));
// messages: app 1
// none
// app 2: another StartWatching() with different event mask
CHK(roster.StartWatching(target2, B_REQUEST_LAUNCHED) == B_OK);
// launch app 3
entry_ref ref3(create_app(appFile3, appType3));
SimpleAppLauncher caller3(ref3);
team_id team3;
CHK(context(caller3, appType3, &team3) == B_OK);
context.WaitForMessage(team3, MSG_READY_TO_RUN);
BMessenger target3(NULL, team3);
app_info appInfo3(app_info_for_team(team3));
// messages: app 3
int32 cookie3 = 0;
CHK(context.CheckNextMessage(caller3, team3, cookie3, MSG_STARTED));
CHK(context.CheckMainArgsMessage(caller3, team3, cookie3, &ref3, false));
CHK(context.CheckNextMessage(caller3, team3, cookie3, MSG_READY_TO_RUN));
// messages: app 2
check_watching_message(context, team2, cookie2, appInfo3,
B_SOME_APP_LAUNCHED);
// messages: app 1
// none
// terminate app 3
context.TerminateApp(team3);
// messages: app 3
// none
// messages: app 2
// none
// messages: app 1
check_watching_message(context, team1, cookie1, appInfo3,
B_SOME_APP_QUIT);
// terminate app 2
context.TerminateApp(team2);
CHK(roster.StopWatching(target2) == B_OK);
// messages: app 1
check_watching_message(context, team1, cookie1, appInfo2,
B_SOME_APP_QUIT);
// remaining messages
context.Terminate();
// app 1
CHK(context.CheckNextMessage(caller1, team1, cookie1, MSG_QUIT_REQUESTED));
CHK(context.CheckNextMessage(caller1, team1, cookie1, MSG_TERMINATED));
// app 2
CHK(context.CheckNextMessage(caller2, team2, cookie2, MSG_QUIT_REQUESTED));
CHK(context.CheckNextMessage(caller2, team2, cookie2, MSG_TERMINATED));
// app 3
CHK(context.CheckNextMessage(caller3, team3, cookie3, MSG_QUIT_REQUESTED));
CHK(context.CheckNextMessage(caller3, team3, cookie3, MSG_TERMINATED));
}
Test* RosterWatchingTester::Suite()
{
TestSuite* SuiteOfTests = new TestSuite;
ADD_TEST4(BRoster, SuiteOfTests, RosterWatchingTester, WatchingTest1);
ADD_TEST4(BRoster, SuiteOfTests, RosterWatchingTester, WatchingTest2);
ADD_TEST4(BRoster, SuiteOfTests, RosterWatchingTester, WatchingTest3);
return SuiteOfTests;
}

View File

@ -0,0 +1,42 @@
//------------------------------------------------------------------------------
// RosterWatchingTester.h
//
//------------------------------------------------------------------------------
#ifndef ROSTER_WATCHING_TESTER_H
#define ROSTER_WATCHING_TESTER_H
// Standard Includes -----------------------------------------------------------
// System Includes -------------------------------------------------------------
// Project Includes ------------------------------------------------------------
#include <TestCase.h>
// Local Includes --------------------------------------------------------------
#include "../common.h"
// Local Defines ---------------------------------------------------------------
// Globals ---------------------------------------------------------------------
class RosterWatchingTester : public BTestCase
{
public:
RosterWatchingTester() {;}
RosterWatchingTester(std::string name) : BTestCase(name) {;}
void setUp();
void tearDown();
void WatchingTest1();
void WatchingTest2();
void WatchingTest3();
static Test* Suite();
private:
BApplication *fApplication;
};
#endif // ROSTER_WATCHING_TESTER_H

View File

@ -0,0 +1,188 @@
// RosterWatchingTestApp1.cpp
#include <stdio.h>
#include <string.h>
#include <Application.h>
#include <Entry.h>
#include <File.h>
#include <Message.h>
#include <Messenger.h>
#include <OS.h>
#include <Resources.h>
#include <Roster.h>
#include <String.h>
#include "RosterTestAppDefs.h"
BMessenger unitTesterMessenger;
static const char *kUnitTesterSignature
= "application/x-vnd.obos-roster-watching-test";
// init_unit_tester_messenger
static
status_t
init_unit_tester_messenger()
{
// Unfortunately BeOS R5 doesn't update the roster-side information about
// the app looper's port ID once a BApplication has been created, and
// thus we can't construct a BMessenger targeting a BApplication created
// after the first one using the signature/team ID constructor.
// We need to do some hacking.
struct fake_messenger {
port_id fPort;
int32 fHandlerToken;
team_id fTeam;
int32 extra0;
int32 extra1;
bool fPreferredTarget;
bool extra2;
bool extra3;
bool extra4;
} &fake = *(fake_messenger*)&unitTesterMessenger;
// get team
status_t error = B_OK;
fake.fTeam = BRoster().TeamFor(kUnitTesterSignature);
if (fake.fTeam < 0)
error = fake.fTeam;
// find app looper port
bool found = false;
int32 cookie = 0;
port_info info;
while (error == B_OK && !found) {
error = get_next_port_info(fake.fTeam, &cookie, &info);
found = (error == B_OK && !strcmp("AppLooperPort", info.name));
}
// init messenger
if (error == B_OK) {
fake.fPort = info.port;
fake.fHandlerToken = 0;
fake.fPreferredTarget = true;
}
return error;
}
// get_app_path
status_t
get_app_path(char *buffer)
{
status_t error = (buffer ? B_OK : B_BAD_VALUE);
image_info info;
int32 cookie = 0;
bool found = false;
if (error == B_OK) {
while (!found && get_next_image_info(0, &cookie, &info) == B_OK) {
if (info.type == B_APP_IMAGE) {
strncpy(buffer, info.name, B_PATH_NAME_LENGTH);
buffer[B_PATH_NAME_LENGTH] = 0;
found = true;
}
}
}
if (error == B_OK && !found)
error = B_ENTRY_NOT_FOUND;
return error;
}
// TestApp
class TestApp : public BApplication {
public:
TestApp(const char *signature) : BApplication(signature)
{
}
virtual void ArgvReceived(int32 argc, char **argv)
{
BMessage message(MSG_ARGV_RECEIVED);
message.AddInt32("argc", argc);
for (int32 i = 0; i < argc; i++)
message.AddString("argv", argv[i]);
unitTesterMessenger.SendMessage(&message);
}
virtual void RefsReceived(BMessage *_message)
{
BMessage message(*_message);
message.what = MSG_REFS_RECEIVED;
unitTesterMessenger.SendMessage(&message);
}
virtual void MessageReceived(BMessage *_message)
{
BMessage message(MSG_MESSAGE_RECEIVED);
message.AddMessage("message", _message);
message.AddInt32("sender", _message->ReturnAddress().Team());
switch (_message->what) {
case B_SOME_APP_LAUNCHED:
case B_SOME_APP_QUIT:
case B_SOME_APP_ACTIVATED:
message.AddBool("don't ignore", true);
break;
}
unitTesterMessenger.SendMessage(&message);
}
virtual bool QuitRequested()
{
unitTesterMessenger.SendMessage(MSG_QUIT_REQUESTED);
return true;
}
virtual void ReadyToRun()
{
unitTesterMessenger.SendMessage(MSG_READY_TO_RUN);
}
};
// main
int
main(int argc, char **argv)
{
// find app file and get signature from resources
char path[B_PATH_NAME_LENGTH];
status_t error = get_app_path(path);
char signature[B_MIME_TYPE_LENGTH];
if (error == B_OK) {
// init app file
BFile file;
error = file.SetTo(path, B_READ_ONLY);
// get signature
BString signatureString;
if (error == B_OK) {
if (file.ReadAttrString("signature", &signatureString) == B_OK
&& signatureString.Length() > 0) {
strcpy(signature, signatureString.String());
} else
strcpy(signature, kDefaultTestAppSignature);
} else
printf("ERROR: Couldn't init app file: %s\n", strerror(error));
} else
printf("ERROR: Couldn't get app ref: %s\n", strerror(error));
// create the app
TestApp *app = NULL;
if (error == B_OK) {
app = new TestApp(signature);
// unitTesterMessenger = BMessenger(kUnitTesterSignature);
error = init_unit_tester_messenger();
if (error != B_OK)
printf("ERROR: Couldn't init messenger: %s\n", strerror(error));
// send started message
BMessage message(MSG_STARTED);
message.AddString("path", path);
unitTesterMessenger.SendMessage(&message);
// send main() args message
BMessage argsMessage(MSG_MAIN_ARGS);
argsMessage.AddInt32("argc", argc);
for (int i = 0; i < argc; i++)
argsMessage.AddString("argv", argv[i]);
unitTesterMessenger.SendMessage(&argsMessage);
// run the app
app->Run();
delete app;
// send terminated message
unitTesterMessenger.SendMessage(MSG_TERMINATED);
}
return 0;
}