First BRoster::Launch() tests. Helper classes for tests are almost complete. Not added to the build yet.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1249 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -191,4 +191,83 @@ case 10:ref is valid, file has no type, sniffing results in a type,
|
|||||||
type is set on file,
|
type is set on file,
|
||||||
FindApp(const char*, entry_ref*) cases 4-16 (== common cases 2-14)
|
FindApp(const char*, entry_ref*) cases 4-16 (== common cases 2-14)
|
||||||
|
|
||||||
|
status_t Launch(const char *mimeType, BMessage *initialMsgs,
|
||||||
|
team_id *appTeam) const
|
||||||
|
case 1: mimeType is NULL =>
|
||||||
|
Should return B_BAD_VALUE.
|
||||||
|
case 2: mimeType is invalid =>
|
||||||
|
Should return B_BAD_VALUE.
|
||||||
|
case 3: uninstalled type mimeType =>
|
||||||
|
Should return B_LAUNCH_FAILED_APP_NOT_FOUND.
|
||||||
|
case 4: installed type mimeType, no preferred app =>
|
||||||
|
Should return B_LAUNCH_FAILED_NO_PREFERRED_APP.
|
||||||
|
case 5: installed type mimeType, preferred app, app type not installed,
|
||||||
|
app has no signature =>
|
||||||
|
Should return B_LAUNCH_FAILED_APP_NOT_FOUND.
|
||||||
|
case 6: installed type mimeType, preferred app, app type not installed,
|
||||||
|
app has signature =>
|
||||||
|
Should return B_OK and set the ref to refer to the application's
|
||||||
|
executable. Should install the app type and set the app hint on it.
|
||||||
|
case 7: installed type mimeType, preferred app, app type installed,
|
||||||
|
app has signature =>
|
||||||
|
Should return B_OK and set the ref to refer to the application's
|
||||||
|
executable. Should set the app hint on the app type.
|
||||||
|
case 8: installed type mimeType, preferred app, app type installed,
|
||||||
|
app has signature, app has no execute permission =>
|
||||||
|
Should return B_OK and set the ref to refer to the application's
|
||||||
|
executable. Should set the app hint on the app type.
|
||||||
|
case 9: installed type mimeType, preferred app, app type installed,
|
||||||
|
two apps have the signature =>
|
||||||
|
Should return B_OK and set the ref to refer to the application
|
||||||
|
executable with the most recent modification time. Should set the app
|
||||||
|
hint on the app type.
|
||||||
|
case 10:installed type mimeType, preferred app, app type installed,
|
||||||
|
two apps have the signature, one has a version info, the other one is
|
||||||
|
newer =>
|
||||||
|
Should return B_OK and set the ref to refer to the application
|
||||||
|
executable with version info. Should set the app hint on the app type.
|
||||||
|
case 11:installed type mimeType, preferred app, app type installed,
|
||||||
|
two apps have the signature, both apps have a version info =>
|
||||||
|
Should return B_OK and set the ref to refer to the application
|
||||||
|
executable with the greater version. Should set the app
|
||||||
|
hint on the app type.
|
||||||
|
case 12:installed type mimeType, preferred app, app type installed,
|
||||||
|
preferred app type has an app hint that points to an app with a
|
||||||
|
different signature =>
|
||||||
|
Should return B_OK and set the ref to refer to the application's
|
||||||
|
executable. Should remove the incorrect app hint on the app type.
|
||||||
|
(OBOS: Should set the correct app hint.
|
||||||
|
Don't even return the wrong app?)
|
||||||
|
case 13:installed type mimeType, preferred app, app type installed,
|
||||||
|
preferred app type has an app hint pointing to void,
|
||||||
|
a differently named app with this signature exists =>
|
||||||
|
Should return B_OK and set the ref to refer to the application's
|
||||||
|
executable. (not R5: Should update the app hint on the app type?)
|
||||||
|
case 14:mimeType is app signature, not installed =>
|
||||||
|
Should return B_OK and set the ref to refer to the application
|
||||||
|
executable. Should set the app hint on the app type.
|
||||||
|
case 15:mimeType is installed, but has no preferred application,
|
||||||
|
super type has preferred application =>
|
||||||
|
Should return B_OK and set the ref to refer to the application
|
||||||
|
executable associated with the preferred app of the supertype.
|
||||||
|
Should set the app hint on the app type.
|
||||||
|
case 16:installed type mimeType, preferred app, app type not installed,
|
||||||
|
app has signature, app is trash =>
|
||||||
|
Should return B_LAUNCH_FAILED_APP_IN_TRASH.
|
||||||
|
|
||||||
|
status_t Launch(const char *mimeType, BList *messageList,
|
||||||
|
team_id *appTeam) const
|
||||||
|
|
||||||
|
status_t Launch(const char *mimeType, int argc, char **args,
|
||||||
|
team_id *appTeam) const
|
||||||
|
|
||||||
|
status_t Launch(const entry_ref *ref, const BMessage *initialMessage,
|
||||||
|
team_id *app_team) const
|
||||||
|
|
||||||
|
status_t Launch(const entry_ref *ref, const BList *messageList,
|
||||||
|
team_id *appTeam) const
|
||||||
|
|
||||||
|
status_t Launch(const entry_ref *ref, int argc, const char * const *args,
|
||||||
|
team_id *appTeam) const
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,893 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// LaunchTester.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 "LaunchTester.h"
|
||||||
|
#include "LaunchTesterHelper.h"
|
||||||
|
#include "RosterTestAppDefs.h"
|
||||||
|
|
||||||
|
// Local Defines ---------------------------------------------------------------
|
||||||
|
|
||||||
|
// Globals ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static const char *testerSignature
|
||||||
|
= "application/x-vnd.obos-roster-launch-test";
|
||||||
|
static const char *uninstalledType
|
||||||
|
= "application/x-vnd.obos-roster-launch-uninstalled";
|
||||||
|
static const char *appType1 = "application/x-vnd.obos-roster-launch-app1";
|
||||||
|
static const char *appType2 = "application/x-vnd.obos-roster-launch-app2";
|
||||||
|
static const char *fileType1 = "application/x-vnd.obos-roster-launch-file1";
|
||||||
|
static const char *fileType2 = "application/x-vnd.obos-roster-launch-file2";
|
||||||
|
static const char *textTestType = "text/x-vnd.obos-roster-launch";
|
||||||
|
|
||||||
|
static const char *testDir = "/tmp/testdir";
|
||||||
|
static const char *appFile1 = "/tmp/testdir/app1";
|
||||||
|
static const char *appFile2 = "/tmp/testdir/app2";
|
||||||
|
//static const char *testFile1 = "/tmp/testdir/testFile1";
|
||||||
|
//static const char *testLink1 = "/tmp/testdir/testLink1";
|
||||||
|
static const char *trashAppName = "roster-launch-app";
|
||||||
|
|
||||||
|
// dump_messenger
|
||||||
|
/*static
|
||||||
|
void
|
||||||
|
dump_messenger(BMessenger messenger)
|
||||||
|
{
|
||||||
|
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*)&messenger;
|
||||||
|
printf("BMessenger: fPort: %ld\n"
|
||||||
|
" fHandlerToken: %ld\n"
|
||||||
|
" fTeam: %ld\n"
|
||||||
|
" fPreferredTarget: %d\n",
|
||||||
|
fake.fPort, fake.fHandlerToken, fake.fTeam, fake.fPreferredTarget);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
// get_trash_app_file
|
||||||
|
static
|
||||||
|
const char*
|
||||||
|
get_trash_app_file()
|
||||||
|
{
|
||||||
|
static char trashAppFile[B_PATH_NAME_LENGTH];
|
||||||
|
static bool initialized = false;
|
||||||
|
if (!initialized) {
|
||||||
|
BPath path;
|
||||||
|
CHK(find_directory(B_TRASH_DIRECTORY, &path) == B_OK);
|
||||||
|
CHK(path.Append(trashAppName) == B_OK);
|
||||||
|
strcpy(trashAppFile, path.Path());
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
return trashAppFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
// install_type
|
||||||
|
static
|
||||||
|
void
|
||||||
|
install_type(const char *type, const char *preferredApp = NULL,
|
||||||
|
const char *snifferRule = NULL)
|
||||||
|
{
|
||||||
|
BMimeType mimeType(type);
|
||||||
|
if (!mimeType.IsInstalled())
|
||||||
|
CHK(mimeType.Install() == B_OK);
|
||||||
|
if (preferredApp)
|
||||||
|
CHK(mimeType.SetPreferredApp(preferredApp) == B_OK);
|
||||||
|
if (snifferRule)
|
||||||
|
CHK(mimeType.SetSnifferRule(snifferRule) == B_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ref_for_path
|
||||||
|
static
|
||||||
|
entry_ref
|
||||||
|
ref_for_path(const char *filename)
|
||||||
|
{
|
||||||
|
entry_ref ref;
|
||||||
|
BEntry entry;
|
||||||
|
CHK(entry.SetTo(filename, true) == B_OK);
|
||||||
|
CHK(entry.GetRef(&ref) == B_OK);
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ref_for_team
|
||||||
|
static
|
||||||
|
entry_ref
|
||||||
|
ref_for_team(team_id team)
|
||||||
|
{
|
||||||
|
BRoster roster;
|
||||||
|
app_info info;
|
||||||
|
CHK(roster.GetRunningAppInfo(team, &info) == B_OK);
|
||||||
|
return info.ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create_app
|
||||||
|
static
|
||||||
|
void
|
||||||
|
create_app(const char *filename, const char *signature,
|
||||||
|
bool install = false, bool makeExecutable = true)
|
||||||
|
{
|
||||||
|
BString testApp;
|
||||||
|
CHK(find_test_app("RosterLaunchTestApp1", &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);
|
||||||
|
CHK(appFileInfo.SetSignature(signature) == B_OK);
|
||||||
|
CHK(appFileInfo.SetAppFlags(B_SINGLE_LAUNCH) == B_OK);
|
||||||
|
if (install)
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create_file
|
||||||
|
/*static
|
||||||
|
entry_ref
|
||||||
|
create_file(const char *filename, const char *type,
|
||||||
|
const char *preferredApp = NULL, const char *appHintPath = NULL,
|
||||||
|
const char *contents = NULL)
|
||||||
|
{
|
||||||
|
if (contents)
|
||||||
|
system((string("echo -n \"") + contents + "\" > " + filename).c_str());
|
||||||
|
else
|
||||||
|
system((string("touch ") + filename).c_str());
|
||||||
|
if (type || preferredApp || appHintPath) {
|
||||||
|
BFile file;
|
||||||
|
CHK(file.SetTo(filename, B_READ_WRITE) == B_OK);
|
||||||
|
BNodeInfo nodeInfo;
|
||||||
|
CHK(nodeInfo.SetTo(&file) == B_OK);
|
||||||
|
if (type)
|
||||||
|
CHK(nodeInfo.SetType(type) == B_OK);
|
||||||
|
if (preferredApp)
|
||||||
|
CHK(nodeInfo.SetPreferredApp(preferredApp) == B_OK);
|
||||||
|
if (appHintPath) {
|
||||||
|
entry_ref appHint(ref_for_path(appHintPath));
|
||||||
|
CHK(nodeInfo.SetAppHint(&appHint) == B_OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ref_for_path(filename);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// check_app_type
|
||||||
|
static
|
||||||
|
void
|
||||||
|
check_app_type(const char *signature, const char *filename)
|
||||||
|
{
|
||||||
|
BMimeType type(signature);
|
||||||
|
CHK(type.IsInstalled() == true);
|
||||||
|
if (filename) {
|
||||||
|
entry_ref appHint;
|
||||||
|
CHK(type.GetAppHint(&appHint) == B_OK);
|
||||||
|
CHK(ref_for_path(filename) == appHint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_file_time
|
||||||
|
static
|
||||||
|
void
|
||||||
|
set_file_time(const char *filename, time_t time)
|
||||||
|
{
|
||||||
|
utimbuf buffer;
|
||||||
|
buffer.actime = time;
|
||||||
|
buffer.modtime = time;
|
||||||
|
CHK(utime(filename, &buffer) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_version
|
||||||
|
static
|
||||||
|
void
|
||||||
|
set_version(const char *filename, uint32 version)
|
||||||
|
{
|
||||||
|
version_info versionInfo = { 1, 1, 1, 1, version, "short1", "long1" };
|
||||||
|
BFile file;
|
||||||
|
CHK(file.SetTo(filename, B_READ_WRITE) == B_OK);
|
||||||
|
BAppFileInfo appFileInfo;
|
||||||
|
CHK(appFileInfo.SetTo(&file) == B_OK);
|
||||||
|
CHK(appFileInfo.SetVersionInfo(&versionInfo, B_APP_VERSION_KIND) == B_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set_type_app_hint
|
||||||
|
static
|
||||||
|
void
|
||||||
|
set_type_app_hint(const char *signature, const char *filename)
|
||||||
|
{
|
||||||
|
BMimeType type(signature);
|
||||||
|
if (!type.IsInstalled());
|
||||||
|
CHK(type.Install() == B_OK);
|
||||||
|
entry_ref fileRef(ref_for_path(filename));
|
||||||
|
CHK(type.SetAppHint(&fileRef) == B_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// setUp
|
||||||
|
void
|
||||||
|
LaunchTester::setUp()
|
||||||
|
{
|
||||||
|
fApplication = new RosterLaunchApp(testerSignature);
|
||||||
|
system((string("mkdir ") + testDir).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// tearDown
|
||||||
|
void
|
||||||
|
LaunchTester::tearDown()
|
||||||
|
{
|
||||||
|
BMimeType(uninstalledType).Delete();
|
||||||
|
BMimeType(appType1).Delete();
|
||||||
|
BMimeType(appType2).Delete();
|
||||||
|
BMimeType(fileType1).Delete();
|
||||||
|
BMimeType(fileType2).Delete();
|
||||||
|
BMimeType(textTestType).Delete();
|
||||||
|
delete fApplication;
|
||||||
|
system((string("rm -rf ") + testDir).c_str());
|
||||||
|
system((string("rm -f ") + get_trash_app_file()).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@case 1 uninstalled type mimeType
|
||||||
|
@results Should return B_LAUNCH_FAILED_APP_NOT_FOUND.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
void
|
||||||
|
CommonLaunchTest1(LaunchCaller &caller)
|
||||||
|
{
|
||||||
|
LaunchContext context(caller);
|
||||||
|
BRoster roster;
|
||||||
|
team_id team;
|
||||||
|
CHK(context(uninstalledType, &team) == B_LAUNCH_FAILED_APP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@case 2 installed type mimeType, no preferred app
|
||||||
|
@results Should return B_LAUNCH_FAILED_NO_PREFERRED_APP.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
void
|
||||||
|
CommonLaunchTest2(LaunchCaller &caller)
|
||||||
|
{
|
||||||
|
LaunchContext context(caller);
|
||||||
|
BRoster roster;
|
||||||
|
install_type(fileType1);
|
||||||
|
team_id team;
|
||||||
|
CHK(context(fileType1, &team) == B_LAUNCH_FAILED_NO_PREFERRED_APP);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@case 3 installed type mimeType, preferred app, app type not
|
||||||
|
installed, app has no signature
|
||||||
|
@results Should return B_LAUNCH_FAILED_APP_NOT_FOUND.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
void
|
||||||
|
CommonLaunchTest3(LaunchCaller &caller)
|
||||||
|
{
|
||||||
|
LaunchContext context(caller);
|
||||||
|
BRoster roster;
|
||||||
|
install_type(fileType1, appType1);
|
||||||
|
team_id team;
|
||||||
|
CHK(context(fileType1, &team) == B_LAUNCH_FAILED_APP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@case 4 installed type mimeType, preferred app, app type not
|
||||||
|
installed, app has signature
|
||||||
|
@results Should return B_OK and set the ref to refer to the
|
||||||
|
application's executable. Should install the app type and
|
||||||
|
set the app hint on it.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
void
|
||||||
|
CommonLaunchTest4(LaunchCaller &caller)
|
||||||
|
{
|
||||||
|
LaunchContext context(caller);
|
||||||
|
BRoster roster;
|
||||||
|
create_app(appFile1, appType1);
|
||||||
|
install_type(fileType1, appType1);
|
||||||
|
team_id team;
|
||||||
|
CHK(context(fileType1, &team) == B_OK);
|
||||||
|
entry_ref ref = ref_for_team(team);
|
||||||
|
CHK(ref_for_path(appFile1) == ref);
|
||||||
|
check_app_type(appType1, appFile1);
|
||||||
|
int32 cookie = 0;
|
||||||
|
context.CheckNextMessage(team, cookie, MSG_STARTED);
|
||||||
|
context.CheckNextMessage(team, cookie, MSG_READY_TO_RUN);
|
||||||
|
context.CheckNextMessage(team, cookie, MSG_QUIT_REQUESTED);
|
||||||
|
context.CheckNextMessage(team, cookie, MSG_TERMINATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@case 5 installed type mimeType, preferred app, app type installed,
|
||||||
|
app has signature
|
||||||
|
@results Should return B_OK and set the ref to refer to the
|
||||||
|
application'sexecutable. Should set the app hint on the
|
||||||
|
app type.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
void
|
||||||
|
CommonLaunchTest5(LaunchCaller &caller)
|
||||||
|
{
|
||||||
|
LaunchContext context(caller);
|
||||||
|
BRoster roster;
|
||||||
|
create_app(appFile1, appType1, true);
|
||||||
|
install_type(fileType1, appType1);
|
||||||
|
team_id team;
|
||||||
|
CHK(context(fileType1, &team) == B_OK);
|
||||||
|
entry_ref ref = ref_for_team(team);
|
||||||
|
CHK(ref_for_path(appFile1) == ref);
|
||||||
|
check_app_type(appType1, appFile1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@case 6 installed type mimeType, preferred app, app type installed,
|
||||||
|
app has signature, app has no execute permission
|
||||||
|
@results Should return B_OK and set the ref to refer to the
|
||||||
|
application's executable. Should set the app hint on the
|
||||||
|
app type.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
void
|
||||||
|
CommonLaunchTest6(LaunchCaller &caller)
|
||||||
|
{
|
||||||
|
LaunchContext context(caller);
|
||||||
|
BRoster roster;
|
||||||
|
create_app(appFile1, appType1, true, false);
|
||||||
|
install_type(fileType1, appType1);
|
||||||
|
team_id team;
|
||||||
|
CHK(context(fileType1, &team) == B_OK);
|
||||||
|
entry_ref ref = ref_for_team(team);
|
||||||
|
CHK(ref_for_path(appFile1) == ref);
|
||||||
|
check_app_type(appType1, appFile1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@case 7 installed type mimeType, preferred app, app type installed,
|
||||||
|
two apps have the signature
|
||||||
|
@results Should return B_OK and set the ref to refer to the
|
||||||
|
application executable with the most recent modification
|
||||||
|
time. Should set the app hint on the app type.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
void
|
||||||
|
CommonLaunchTest7(LaunchCaller &caller)
|
||||||
|
{
|
||||||
|
LaunchContext context(caller);
|
||||||
|
BRoster roster;
|
||||||
|
create_app(appFile1, appType1);
|
||||||
|
create_app(appFile2, appType1, true);
|
||||||
|
set_file_time(appFile2, time(NULL) + 1);
|
||||||
|
install_type(fileType1, appType1);
|
||||||
|
team_id team;
|
||||||
|
CHK(context(fileType1, &team) == B_OK);
|
||||||
|
entry_ref ref = ref_for_team(team);
|
||||||
|
CHK(ref_for_path(appFile2) == ref);
|
||||||
|
check_app_type(appType1, appFile2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@case 8 installed type mimeType, preferred app, app type installed,
|
||||||
|
two apps have the signature, one has a version info, the
|
||||||
|
other one is newer
|
||||||
|
@results Should return B_OK and set the ref to refer to the
|
||||||
|
application executable with version info. Should set the
|
||||||
|
app hint on the app type.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
void
|
||||||
|
CommonLaunchTest8(LaunchCaller &caller)
|
||||||
|
{
|
||||||
|
LaunchContext context(caller);
|
||||||
|
BRoster roster;
|
||||||
|
create_app(appFile1, appType1);
|
||||||
|
set_version(appFile1, 1);
|
||||||
|
create_app(appFile2, appType1, true);
|
||||||
|
set_file_time(appFile2, time(NULL) + 1);
|
||||||
|
install_type(fileType1, appType1);
|
||||||
|
team_id team;
|
||||||
|
CHK(context(fileType1, &team) == B_OK);
|
||||||
|
entry_ref ref = ref_for_team(team);
|
||||||
|
CHK(ref_for_path(appFile1) == ref);
|
||||||
|
check_app_type(appType1, appFile1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@case 9 installed type mimeType, preferred app, app type installed,
|
||||||
|
two apps have the signature, both apps have a version info
|
||||||
|
@results Should return B_OK and set the ref to refer to the
|
||||||
|
application executable with the greater version. Should
|
||||||
|
set the app hint on the app type.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
void
|
||||||
|
CommonLaunchTest9(LaunchCaller &caller)
|
||||||
|
{
|
||||||
|
LaunchContext context(caller);
|
||||||
|
BRoster roster;
|
||||||
|
create_app(appFile1, appType1);
|
||||||
|
set_version(appFile1, 2);
|
||||||
|
create_app(appFile2, appType1, true);
|
||||||
|
set_version(appFile1, 1);
|
||||||
|
set_file_time(appFile2, time(NULL) + 1);
|
||||||
|
install_type(fileType1, appType1);
|
||||||
|
team_id team;
|
||||||
|
CHK(context(fileType1, &team) == B_OK);
|
||||||
|
entry_ref ref = ref_for_team(team);
|
||||||
|
CHK(ref_for_path(appFile1) == ref);
|
||||||
|
check_app_type(appType1, appFile1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@case 10 installed type mimeType, preferred app, app type installed,
|
||||||
|
preferred app type has an app hint that points to an app
|
||||||
|
with a different signature
|
||||||
|
@results Should return B_OK and set the ref to refer to the
|
||||||
|
application's executable. Should remove the incorrect app
|
||||||
|
hint on the app type. (OBOS: Should set the correct app
|
||||||
|
hint. Don't even return the wrong app?)
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
void
|
||||||
|
CommonLaunchTest10(LaunchCaller &caller)
|
||||||
|
{
|
||||||
|
LaunchContext context(caller);
|
||||||
|
BRoster roster;
|
||||||
|
create_app(appFile1, appType2);
|
||||||
|
set_type_app_hint(appType1, appFile1);
|
||||||
|
entry_ref appHint;
|
||||||
|
CHK(BMimeType(appType1).GetAppHint(&appHint) == B_OK);
|
||||||
|
install_type(fileType1, appType1);
|
||||||
|
team_id team;
|
||||||
|
CHK(context(fileType1, &team) == B_OK);
|
||||||
|
entry_ref ref = ref_for_team(team);
|
||||||
|
CHK(ref_for_path(appFile1) == ref);
|
||||||
|
CHK(BMimeType(appType1).GetAppHint(&appHint) == B_ENTRY_NOT_FOUND);
|
||||||
|
CHK(BMimeType(appType2).IsInstalled() == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@case 11 installed type mimeType, preferred app, app type installed,
|
||||||
|
preferred app type has an app hint pointing to void,
|
||||||
|
a differently named app with this signature exists
|
||||||
|
@results Should return B_OK and set the ref to refer to the
|
||||||
|
application's executable. Should update the app
|
||||||
|
hint on the app type.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
void
|
||||||
|
CommonLaunchTest11(LaunchCaller &caller)
|
||||||
|
{
|
||||||
|
LaunchContext context(caller);
|
||||||
|
BRoster roster;
|
||||||
|
create_app(appFile1, appType1);
|
||||||
|
set_type_app_hint(appType1, appFile2);
|
||||||
|
install_type(fileType1, appType1);
|
||||||
|
team_id team;
|
||||||
|
CHK(context(fileType1, &team) == B_OK);
|
||||||
|
entry_ref ref = ref_for_team(team);
|
||||||
|
CHK(ref_for_path(appFile1) == ref);
|
||||||
|
check_app_type(appType1, appFile1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@case 12 mimeType is app signature, not installed
|
||||||
|
@results Should return B_OK and set the ref to refer to the
|
||||||
|
application executable. Should set the app hint on the
|
||||||
|
app type.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
void
|
||||||
|
CommonLaunchTest12(LaunchCaller &caller)
|
||||||
|
{
|
||||||
|
LaunchContext context(caller);
|
||||||
|
BRoster roster;
|
||||||
|
create_app(appFile1, appType1);
|
||||||
|
team_id team;
|
||||||
|
CHK(context(appType1, &team) == B_OK);
|
||||||
|
entry_ref ref = ref_for_team(team);
|
||||||
|
CHK(ref_for_path(appFile1) == ref);
|
||||||
|
check_app_type(appType1, appFile1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@case 13 mimeType is installed, but has no preferred application,
|
||||||
|
super type has preferred application
|
||||||
|
@results Should return B_OK and set the ref to refer to the
|
||||||
|
application executable associated with the preferred app
|
||||||
|
of the supertype. Should set the app hint on the app type.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
void
|
||||||
|
CommonLaunchTest13(LaunchCaller &caller)
|
||||||
|
{
|
||||||
|
LaunchContext context(caller);
|
||||||
|
BRoster roster;
|
||||||
|
// make sure, the original preferred app for the "text" supertype is
|
||||||
|
// re-installed
|
||||||
|
struct TextTypeSaver {
|
||||||
|
TextTypeSaver()
|
||||||
|
{
|
||||||
|
BMimeType textType("text");
|
||||||
|
hasPreferredApp
|
||||||
|
= (textType.GetPreferredApp(preferredApp) == B_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
~TextTypeSaver()
|
||||||
|
{
|
||||||
|
BMimeType textType("text");
|
||||||
|
textType.SetPreferredApp(hasPreferredApp ? preferredApp : NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasPreferredApp;
|
||||||
|
char preferredApp[B_MIME_TYPE_LENGTH];
|
||||||
|
} _saver;
|
||||||
|
|
||||||
|
create_app(appFile1, appType1);
|
||||||
|
CHK(BMimeType("text").SetPreferredApp(appType1) == B_OK);
|
||||||
|
install_type(textTestType);
|
||||||
|
team_id team;
|
||||||
|
CHK(context(textTestType, &team) == B_OK);
|
||||||
|
entry_ref ref = ref_for_team(team);
|
||||||
|
CHK(ref_for_path(appFile1) == ref);
|
||||||
|
check_app_type(appType1, appFile1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@case 14 installed type mimeType, preferred app, app type not installed,
|
||||||
|
app has signature, app is trash
|
||||||
|
@results Should return B_LAUNCH_FAILED_APP_IN_TRASH.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
void
|
||||||
|
CommonLaunchTest14(LaunchCaller &caller)
|
||||||
|
{
|
||||||
|
LaunchContext context(caller);
|
||||||
|
BRoster roster;
|
||||||
|
create_app(get_trash_app_file(), appType1);
|
||||||
|
install_type(fileType1, appType1);
|
||||||
|
team_id team;
|
||||||
|
CHK(context(fileType1, &team) == B_LAUNCH_FAILED_APP_IN_TRASH);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef void commonTestFunction(LaunchCaller &caller);
|
||||||
|
static commonTestFunction *commonTestFunctions[] = {
|
||||||
|
CommonLaunchTest1, CommonLaunchTest2, CommonLaunchTest3,
|
||||||
|
CommonLaunchTest4, CommonLaunchTest5, CommonLaunchTest6,
|
||||||
|
CommonLaunchTest7, CommonLaunchTest8, CommonLaunchTest9,
|
||||||
|
CommonLaunchTest10, CommonLaunchTest11, CommonLaunchTest12,
|
||||||
|
CommonLaunchTest13, CommonLaunchTest14
|
||||||
|
};
|
||||||
|
static int32 commonTestFunctionCount
|
||||||
|
= sizeof(commonTestFunctions) / sizeof(commonTestFunction*);
|
||||||
|
|
||||||
|
/*
|
||||||
|
status_t Launch(const char *mimeType, BMessage *initialMsgs,
|
||||||
|
team_id *appTeam) const
|
||||||
|
@case 1 mimeType is NULL
|
||||||
|
@results Should return B_BAD_VALUE.
|
||||||
|
*/
|
||||||
|
void LaunchTester::LaunchTestA1()
|
||||||
|
{
|
||||||
|
BRoster roster;
|
||||||
|
CHK(roster.Launch((const char*)NULL, (BMessage*)NULL, NULL)
|
||||||
|
== B_BAD_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
status_t Launch(const char *mimeType, BMessage *initialMsgs,
|
||||||
|
team_id *appTeam) const
|
||||||
|
@case 2 mimeType is invalid
|
||||||
|
@results Should return B_BAD_VALUE.
|
||||||
|
*/
|
||||||
|
void LaunchTester::LaunchTestA2()
|
||||||
|
{
|
||||||
|
BRoster roster;
|
||||||
|
entry_ref ref;
|
||||||
|
CHK(roster.Launch("invalid/mine/type", (BMessage*)NULL, NULL)
|
||||||
|
== B_BAD_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// LaunchTypeCaller
|
||||||
|
class LaunchTypeCaller : public LaunchCaller {
|
||||||
|
public:
|
||||||
|
virtual status_t operator()(const char *type, team_id *team)
|
||||||
|
{
|
||||||
|
BRoster roster;
|
||||||
|
return roster.Launch(type, (BMessage*)NULL, team);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
status_t Launch(const char *mimeType, BMessage *initialMsgs,
|
||||||
|
team_id *appTeam) const
|
||||||
|
@case 3 Launch(const char*, entry_ref*) cases 3-16
|
||||||
|
(== common cases 1-14)
|
||||||
|
*/
|
||||||
|
void LaunchTester::LaunchTestA3()
|
||||||
|
{
|
||||||
|
LaunchTypeCaller caller;
|
||||||
|
for (int32 i = 0; i < commonTestFunctionCount; i++) {
|
||||||
|
NextSubTest();
|
||||||
|
(*commonTestFunctions[i])(caller);
|
||||||
|
tearDown();
|
||||||
|
setUp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
status_t Launch(entry_ref *ref, entry_ref *app) const
|
||||||
|
@case 1 ref or app are NULL
|
||||||
|
@results Should return B_BAD_VALUE.
|
||||||
|
*/
|
||||||
|
void LaunchTester::LaunchTestB1()
|
||||||
|
{
|
||||||
|
BRoster roster;
|
||||||
|
CHK(roster.Launch((entry_ref*)NULL, NULL) == B_BAD_VALUE);
|
||||||
|
// R5: Crashes when passing a NULL (app) ref.
|
||||||
|
#ifndef TEST_R5
|
||||||
|
create_app(appFile1, appType1);
|
||||||
|
entry_ref fileRef(create_file(testFile1, fileType1, appType1));
|
||||||
|
CHK(roster.Launch(&fileRef, NULL) == B_BAD_VALUE);
|
||||||
|
#endif
|
||||||
|
entry_ref ref;
|
||||||
|
CHK(roster.Launch((entry_ref*)NULL, &ref) == B_BAD_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
status_t Launch(entry_ref *ref, entry_ref *app) const
|
||||||
|
@case 2 ref doesn't refer to an existing entry =>
|
||||||
|
@results Should return B_ENTRY_NOT_FOUND.
|
||||||
|
*/
|
||||||
|
void LaunchTester::LaunchTestB2()
|
||||||
|
{
|
||||||
|
BRoster roster;
|
||||||
|
entry_ref fileRef(ref_for_path(testFile1));
|
||||||
|
entry_ref ref;
|
||||||
|
CHK(roster.Launch(&fileRef, &ref) == B_ENTRY_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
status_t Launch(entry_ref *ref, entry_ref *app) const
|
||||||
|
@case 3 ref is valid, file has type and preferred app, preferred
|
||||||
|
app is in trash
|
||||||
|
@results Should return B_LAUNCH_FAILED_APP_IN_TRASH.
|
||||||
|
*/
|
||||||
|
void LaunchTester::LaunchTestB3()
|
||||||
|
{
|
||||||
|
BRoster roster;
|
||||||
|
create_app(get_trash_app_file(), appType1);
|
||||||
|
entry_ref fileRef(create_file(testFile1, fileType1, appType1));
|
||||||
|
entry_ref ref;
|
||||||
|
CHK(roster.Launch(&fileRef, &ref) == B_LAUNCH_FAILED_APP_IN_TRASH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
status_t Launch(entry_ref *ref, entry_ref *app) const
|
||||||
|
@case 4 ref is valid, file has type and preferred app, app type is
|
||||||
|
not installed, app exists and has signature
|
||||||
|
@results Should return B_OK and set the ref to refer to the file's
|
||||||
|
(not the file type's) preferred application's executable.
|
||||||
|
Should install the app type and set the app hint on it.
|
||||||
|
*/
|
||||||
|
void LaunchTester::LaunchTestB4()
|
||||||
|
{
|
||||||
|
BRoster roster;
|
||||||
|
create_app(appFile1, appType1);
|
||||||
|
create_app(appFile2, appType2);
|
||||||
|
install_type(fileType1, appType1);
|
||||||
|
entry_ref fileRef(create_file(testFile1, fileType1, appType2));
|
||||||
|
entry_ref ref;
|
||||||
|
CHK(roster.Launch(&fileRef, &ref) == B_OK);
|
||||||
|
CHK(ref_for_path(appFile2) == ref);
|
||||||
|
check_app_type(appType2, appFile2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
status_t Launch(entry_ref *ref, entry_ref *app) const
|
||||||
|
@case 5 ref is valid, file has no type, but preferred app,
|
||||||
|
app type is not installed, app exists and has signature
|
||||||
|
@results Should return B_OK and set the ref to refer to the
|
||||||
|
application's executable. Should install the app type and
|
||||||
|
set the app hint on it.
|
||||||
|
*/
|
||||||
|
void LaunchTester::LaunchTestB5()
|
||||||
|
{
|
||||||
|
BRoster roster;
|
||||||
|
create_app(appFile1, appType1);
|
||||||
|
entry_ref fileRef(create_file(testFile1, NULL, appType1));
|
||||||
|
entry_ref ref;
|
||||||
|
CHK(roster.Launch(&fileRef, &ref) == B_OK);
|
||||||
|
CHK(ref_for_path(appFile1) == ref);
|
||||||
|
check_app_type(appType1, appFile1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
status_t Launch(entry_ref *ref, entry_ref *app) const
|
||||||
|
@case 6 ref is valid, file has type and app hint, the type's
|
||||||
|
preferred app type is not installed, app exists and has
|
||||||
|
signature
|
||||||
|
@results Should return B_OK and set the ref to refer to the file
|
||||||
|
type's preferred application's executable. Should install
|
||||||
|
the app type and set the app hint on it.
|
||||||
|
*/
|
||||||
|
void LaunchTester::LaunchTestB6()
|
||||||
|
{
|
||||||
|
BRoster roster;
|
||||||
|
create_app(appFile1, appType1);
|
||||||
|
create_app(appFile2, appType2);
|
||||||
|
install_type(fileType1, appType1);
|
||||||
|
entry_ref fileRef(create_file(testFile1, fileType1, NULL, appFile2));
|
||||||
|
entry_ref ref;
|
||||||
|
CHK(roster.Launch(&fileRef, &ref) == B_OK);
|
||||||
|
CHK(ref_for_path(appFile1) == ref);
|
||||||
|
check_app_type(appType1, appFile1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
status_t Launch(entry_ref *ref, entry_ref *app) const
|
||||||
|
@case 7 ref is valid, file has type, the type's preferred app
|
||||||
|
type is not installed, app exists and has signature,
|
||||||
|
file is executable
|
||||||
|
@results Should return B_OK and set the ref to refer to the file.
|
||||||
|
Should not set the app hint on the app or file type (Why?).
|
||||||
|
*/
|
||||||
|
void LaunchTester::LaunchTestB7()
|
||||||
|
{
|
||||||
|
BRoster roster;
|
||||||
|
create_app(appFile1, appType1);
|
||||||
|
install_type(fileType1, appType1);
|
||||||
|
entry_ref fileRef(create_file(testFile1, fileType1));
|
||||||
|
system((string("chmod a+x ") + testFile1).c_str());
|
||||||
|
entry_ref ref;
|
||||||
|
CHK(roster.Launch(&fileRef, &ref) == B_OK);
|
||||||
|
CHK(ref_for_path(testFile1) == ref);
|
||||||
|
CHK(BMimeType(appType1).IsInstalled() == false);
|
||||||
|
CHK(BMimeType(fileType1).GetAppHint(&ref) == B_ENTRY_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
status_t Launch(entry_ref *ref, entry_ref *app) const
|
||||||
|
@case 8 ref is valid and refers to a link to a file, file has type,
|
||||||
|
the type's preferred app type is not installed,
|
||||||
|
app exists and has signature
|
||||||
|
@results Should return B_OK and set the ref to refer to the file
|
||||||
|
type's preferred application's executable. Should install
|
||||||
|
the app type and set the app hint on it.
|
||||||
|
*/
|
||||||
|
void LaunchTester::LaunchTestB8()
|
||||||
|
{
|
||||||
|
BRoster roster;
|
||||||
|
create_app(appFile1, appType1);
|
||||||
|
install_type(fileType1, appType1);
|
||||||
|
create_file(testFile1, fileType1);
|
||||||
|
system((string("ln -s ") + testFile1 + " " + testLink1).c_str());
|
||||||
|
entry_ref linkRef(ref_for_path(testLink1));
|
||||||
|
entry_ref ref;
|
||||||
|
CHK(roster.Launch(&linkRef, &ref) == B_OK);
|
||||||
|
CHK(ref_for_path(appFile1) == ref);
|
||||||
|
check_app_type(appType1, appFile1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileWithTypeCaller
|
||||||
|
class FileWithTypeCaller : public LaunchCaller {
|
||||||
|
public:
|
||||||
|
virtual status_t operator()(const char *type, entry_ref *ref)
|
||||||
|
{
|
||||||
|
BRoster roster;
|
||||||
|
entry_ref fileRef(create_file(testFile1, type));
|
||||||
|
return roster.Launch(&fileRef, ref);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
status_t Launch(entry_ref *ref, entry_ref *app) const
|
||||||
|
@case 9 ref is valid, file has no type, sniffing results in a type,
|
||||||
|
type is set on file,
|
||||||
|
Launch(const char*, entry_ref*) cases 4-16
|
||||||
|
(== common cases 2-14)
|
||||||
|
*/
|
||||||
|
void LaunchTester::LaunchTestB9()
|
||||||
|
{
|
||||||
|
FileWithTypeCaller caller;
|
||||||
|
for (int32 i = 0; i < commonTestFunctionCount; i++) {
|
||||||
|
NextSubTest();
|
||||||
|
(*commonTestFunctions[i])(caller);
|
||||||
|
tearDown();
|
||||||
|
setUp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SniffFileTypeCaller
|
||||||
|
class SniffFileTypeCaller : public LaunchCaller {
|
||||||
|
public:
|
||||||
|
virtual status_t operator()(const char *type, entry_ref *ref)
|
||||||
|
{
|
||||||
|
BRoster roster;
|
||||||
|
entry_ref fileRef(create_file(testFile1, type, NULL, NULL,
|
||||||
|
"UnIQe pAtTeRn"));
|
||||||
|
install_type(fileType1, NULL, "1.0 [0] ('UnIQe pAtTeRn')");
|
||||||
|
return roster.Launch(&fileRef, ref);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
status_t Launch(entry_ref *ref, entry_ref *app) const
|
||||||
|
@case 10 ref is valid, file has no type, sniffing results in a type,
|
||||||
|
type is set on file,
|
||||||
|
Launch(const char*, entry_ref*) cases 3-16
|
||||||
|
(== common cases 1-14)
|
||||||
|
*/
|
||||||
|
void LaunchTester::LaunchTestB10()
|
||||||
|
{
|
||||||
|
SniffFileTypeCaller caller;
|
||||||
|
for (int32 i = 1; i < commonTestFunctionCount; i++) {
|
||||||
|
NextSubTest();
|
||||||
|
(*commonTestFunctions[i])(caller);
|
||||||
|
tearDown();
|
||||||
|
setUp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // 0
|
||||||
|
|
||||||
|
|
||||||
|
Test* LaunchTester::Suite()
|
||||||
|
{
|
||||||
|
TestSuite* SuiteOfTests = new TestSuite;
|
||||||
|
|
||||||
|
ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestA1);
|
||||||
|
ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestA2);
|
||||||
|
ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestA3);
|
||||||
|
|
||||||
|
// ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestB1);
|
||||||
|
// ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestB2);
|
||||||
|
// ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestB3);
|
||||||
|
// ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestB4);
|
||||||
|
// ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestB5);
|
||||||
|
// ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestB6);
|
||||||
|
// ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestB7);
|
||||||
|
// ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestB8);
|
||||||
|
// ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestB9);
|
||||||
|
// ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestB10);
|
||||||
|
|
||||||
|
return SuiteOfTests;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// LaunchTester.h
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef LAUNCH_TESTER_H
|
||||||
|
#define LAUNCH_TESTER_H
|
||||||
|
|
||||||
|
// Standard Includes -----------------------------------------------------------
|
||||||
|
|
||||||
|
// System Includes -------------------------------------------------------------
|
||||||
|
|
||||||
|
// Project Includes ------------------------------------------------------------
|
||||||
|
#include <TestCase.h>
|
||||||
|
|
||||||
|
// Local Includes --------------------------------------------------------------
|
||||||
|
#include "../common.h"
|
||||||
|
|
||||||
|
// Local Defines ---------------------------------------------------------------
|
||||||
|
|
||||||
|
// Globals ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
class LaunchTester : public BTestCase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LaunchTester() {;}
|
||||||
|
LaunchTester(std::string name) : BTestCase(name) {;}
|
||||||
|
|
||||||
|
void setUp();
|
||||||
|
void tearDown();
|
||||||
|
|
||||||
|
void LaunchTestA1();
|
||||||
|
void LaunchTestA2();
|
||||||
|
void LaunchTestA3();
|
||||||
|
|
||||||
|
// void LaunchTestB1();
|
||||||
|
// void LaunchTestB2();
|
||||||
|
// void LaunchTestB3();
|
||||||
|
// void LaunchTestB4();
|
||||||
|
// void LaunchTestB5();
|
||||||
|
// void LaunchTestB6();
|
||||||
|
// void LaunchTestB7();
|
||||||
|
// void LaunchTestB8();
|
||||||
|
// void LaunchTestB9();
|
||||||
|
// void LaunchTestB10();
|
||||||
|
|
||||||
|
static Test* Suite();
|
||||||
|
|
||||||
|
private:
|
||||||
|
BApplication *fApplication;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LAUNCH_TESTER_H
|
||||||
@@ -0,0 +1,349 @@
|
|||||||
|
// LaunchTesterHelper.cpp
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <Autolock.h>
|
||||||
|
#include <List.h>
|
||||||
|
#include <Message.h>
|
||||||
|
#include <Messenger.h>
|
||||||
|
|
||||||
|
#include "LaunchTesterHelper.h"
|
||||||
|
#include "RosterTestAppDefs.h"
|
||||||
|
|
||||||
|
/////////////////
|
||||||
|
// LaunchContext
|
||||||
|
|
||||||
|
class LaunchContext::Message {
|
||||||
|
public:
|
||||||
|
BMessage message;
|
||||||
|
bigtime_t when;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LaunchContext::AppInfo {
|
||||||
|
public:
|
||||||
|
AppInfo(team_id team)
|
||||||
|
: fTeam(team),
|
||||||
|
fMessenger(),
|
||||||
|
fMessages(),
|
||||||
|
fTerminating(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~AppInfo()
|
||||||
|
{
|
||||||
|
for (int32 i = 0; LaunchContext::Message *message = MessageAt(i); i++)
|
||||||
|
delete message;
|
||||||
|
}
|
||||||
|
|
||||||
|
team_id Team() const
|
||||||
|
{
|
||||||
|
return fTeam;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetMessenger(BMessenger messenger)
|
||||||
|
{
|
||||||
|
fMessenger = messenger;
|
||||||
|
}
|
||||||
|
|
||||||
|
BMessenger Messenger() const
|
||||||
|
{
|
||||||
|
return fMessenger;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Terminate()
|
||||||
|
{
|
||||||
|
if (!fTerminating && fMessenger.IsValid())
|
||||||
|
{
|
||||||
|
fTerminating = true;
|
||||||
|
fMessenger.SendMessage(B_QUIT_REQUESTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddMessage(const BMessage &_message)
|
||||||
|
{
|
||||||
|
LaunchContext::Message *message = new LaunchContext::Message;
|
||||||
|
message->message = _message;
|
||||||
|
message->when = system_time();
|
||||||
|
fMessages.AddItem(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchContext::Message *MessageAt(int32 index) const
|
||||||
|
{
|
||||||
|
return (LaunchContext::Message*)fMessages.ItemAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
team_id fTeam;
|
||||||
|
BMessenger fMessenger;
|
||||||
|
BList fMessages;
|
||||||
|
bool fTerminating;
|
||||||
|
};
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
LaunchContext::LaunchContext(LaunchCaller &caller)
|
||||||
|
: fCaller(caller),
|
||||||
|
fAppInfos(),
|
||||||
|
fLock(),
|
||||||
|
fAppThread(B_ERROR),
|
||||||
|
fTerminator(B_ERROR),
|
||||||
|
fTerminating(false)
|
||||||
|
{
|
||||||
|
RosterLaunchApp *app = dynamic_cast<RosterLaunchApp*>(be_app);
|
||||||
|
app->SetLaunchContext(this);
|
||||||
|
app->Unlock();
|
||||||
|
fAppThread = spawn_thread(AppThreadEntry, "app thread", B_NORMAL_PRIORITY,
|
||||||
|
this);
|
||||||
|
if (fAppThread >= 0) {
|
||||||
|
status_t error = resume_thread(fAppThread);
|
||||||
|
if (error != B_OK)
|
||||||
|
printf("ERROR: Couldn't resume app thread: %s\n", strerror(error));
|
||||||
|
} else
|
||||||
|
printf("ERROR: Couldn't spawn app thread: %s\n", strerror(fAppThread));
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
LaunchContext::~LaunchContext()
|
||||||
|
{
|
||||||
|
Terminate();
|
||||||
|
// cleanup
|
||||||
|
for (int32 i = 0; AppInfo *info = AppInfoAt(i); i++)
|
||||||
|
delete info;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ()
|
||||||
|
status_t
|
||||||
|
LaunchContext::operator()(const char *type, team_id *team)
|
||||||
|
{
|
||||||
|
BAutolock _lock(fLock);
|
||||||
|
status_t result = fCaller(type, team);
|
||||||
|
if (result == B_OK) {
|
||||||
|
if (team)
|
||||||
|
CreateAppInfo(*team);
|
||||||
|
else {
|
||||||
|
// Note: Here's a race condition. If Terminate() is called, before
|
||||||
|
// we've received the first message from the test app, then
|
||||||
|
// there's a good chance that we quit the application before
|
||||||
|
// having received any message (or at least not all messages)
|
||||||
|
// from the test app. We wait some time to minimize the chance...
|
||||||
|
snooze(100000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleMessage
|
||||||
|
void
|
||||||
|
LaunchContext::HandleMessage(BMessage *message)
|
||||||
|
{
|
||||||
|
BAutolock _lock(fLock);
|
||||||
|
switch (message->what) {
|
||||||
|
case MSG_STARTED:
|
||||||
|
case MSG_TERMINATED:
|
||||||
|
case MSG_ARGV_RECEIVED:
|
||||||
|
case MSG_REFS_RECEIVED:
|
||||||
|
case MSG_MESSAGE_RECEIVED:
|
||||||
|
case MSG_QUIT_REQUESTED:
|
||||||
|
case MSG_READY_TO_RUN:
|
||||||
|
{
|
||||||
|
BMessenger messenger = message->ReturnAddress();
|
||||||
|
AppInfo *info = CreateAppInfo(messenger);
|
||||||
|
info->AddMessage(*message);
|
||||||
|
if (fTerminating)
|
||||||
|
TerminateApp(info);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Terminate
|
||||||
|
void
|
||||||
|
LaunchContext::Terminate()
|
||||||
|
{
|
||||||
|
fLock.Lock();
|
||||||
|
if (!fTerminating) {
|
||||||
|
fTerminating = true;
|
||||||
|
// tell all test apps to quit
|
||||||
|
for (int32 i = 0; AppInfo *info = AppInfoAt(i); i++)
|
||||||
|
TerminateApp(info);
|
||||||
|
// start terminator
|
||||||
|
fTerminator = spawn_thread(TerminatorEntry, "terminator",
|
||||||
|
B_NORMAL_PRIORITY, this);
|
||||||
|
if (fTerminator >= 0) {
|
||||||
|
status_t error = resume_thread(fTerminator);
|
||||||
|
if (error != B_OK) {
|
||||||
|
printf("ERROR: Couldn't resume terminator thread: %s\n",
|
||||||
|
strerror(error));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("ERROR: Couldn't spawn terminator thread: %s\n",
|
||||||
|
strerror(fTerminator));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fLock.Unlock();
|
||||||
|
// wait for the app to terminate
|
||||||
|
int32 dummy;
|
||||||
|
wait_for_thread(fAppThread, &dummy);
|
||||||
|
wait_for_thread(fTerminator, &dummy);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TeamAt
|
||||||
|
team_id
|
||||||
|
LaunchContext::TeamAt(int32 index) const
|
||||||
|
{
|
||||||
|
BAutolock _lock(fLock);
|
||||||
|
team_id team = B_ERROR;
|
||||||
|
if (AppInfo *info = AppInfoAt(index))
|
||||||
|
team = info->Team();
|
||||||
|
return team;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextMessageFrom
|
||||||
|
BMessage*
|
||||||
|
LaunchContext::NextMessageFrom(team_id team, int32 &cookie, bigtime_t *time)
|
||||||
|
{
|
||||||
|
BAutolock _lock(fLock);
|
||||||
|
BMessage *message = NULL;
|
||||||
|
if (AppInfo *info = AppInfoFor(team)) {
|
||||||
|
if (Message *contextMessage = info->MessageAt(cookie++)) {
|
||||||
|
message = new BMessage(contextMessage->message);
|
||||||
|
delete contextMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckNextMessage
|
||||||
|
bool
|
||||||
|
LaunchContext::CheckNextMessage(team_id team, int32 &cookie, uint32 what)
|
||||||
|
{
|
||||||
|
BMessage *message = NextMessageFrom(team, cookie);
|
||||||
|
return (message && message->what == what);
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppInfoAt
|
||||||
|
LaunchContext::AppInfo*
|
||||||
|
LaunchContext::AppInfoAt(int32 index) const
|
||||||
|
{
|
||||||
|
return (AppInfo*)fAppInfos.ItemAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppInfoFor
|
||||||
|
LaunchContext::AppInfo*
|
||||||
|
LaunchContext::AppInfoFor(team_id team) const
|
||||||
|
{
|
||||||
|
for (int32 i = 0; AppInfo *info = AppInfoAt(i); i++) {
|
||||||
|
if (info->Team() == team)
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateAppInfo
|
||||||
|
LaunchContext::AppInfo*
|
||||||
|
LaunchContext::CreateAppInfo(BMessenger messenger)
|
||||||
|
{
|
||||||
|
return CreateAppInfo(messenger.Team(), &messenger);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateAppInfo
|
||||||
|
LaunchContext::AppInfo*
|
||||||
|
LaunchContext::CreateAppInfo(team_id team, const BMessenger *messenger)
|
||||||
|
{
|
||||||
|
AppInfo *info = AppInfoFor(team);
|
||||||
|
if (!info) {
|
||||||
|
info = new AppInfo(team);
|
||||||
|
fAppInfos.AddItem(info);
|
||||||
|
}
|
||||||
|
if (messenger && !info->Messenger().IsValid())
|
||||||
|
info->SetMessenger(*messenger);
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TerminateApp
|
||||||
|
void
|
||||||
|
LaunchContext::TerminateApp(AppInfo *info)
|
||||||
|
{
|
||||||
|
if (info)
|
||||||
|
info->Terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Terminator
|
||||||
|
int32
|
||||||
|
LaunchContext::Terminator()
|
||||||
|
{
|
||||||
|
bool allGone = false;
|
||||||
|
while (!allGone) {
|
||||||
|
allGone = true;
|
||||||
|
fLock.Lock();
|
||||||
|
for (int32 i = 0; AppInfo *info = AppInfoAt(i); i++) {
|
||||||
|
team_info teamInfo;
|
||||||
|
allGone &= (get_team_info(info->Team(), &teamInfo) != B_OK);
|
||||||
|
}
|
||||||
|
fLock.Unlock();
|
||||||
|
if (!allGone)
|
||||||
|
snooze(10000);
|
||||||
|
}
|
||||||
|
be_app->PostMessage(B_QUIT_REQUESTED, be_app);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppThreadEntry
|
||||||
|
int32
|
||||||
|
LaunchContext::AppThreadEntry(void *)
|
||||||
|
{
|
||||||
|
be_app->Lock();
|
||||||
|
be_app->Run();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TerminatorEntry
|
||||||
|
int32
|
||||||
|
LaunchContext::TerminatorEntry(void *data)
|
||||||
|
{
|
||||||
|
return ((LaunchContext*)data)->Terminator();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////
|
||||||
|
// RosterLaunchApp
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
RosterLaunchApp::RosterLaunchApp(const char *signature)
|
||||||
|
: BApplication(signature),
|
||||||
|
fMessageQueue(),
|
||||||
|
fLaunchContext(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageReceived
|
||||||
|
void
|
||||||
|
RosterLaunchApp::MessageReceived(BMessage *message)
|
||||||
|
{
|
||||||
|
if (fLaunchContext)
|
||||||
|
fLaunchContext->HandleMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageQueue
|
||||||
|
BMessageQueue&
|
||||||
|
RosterLaunchApp::MessageQueue()
|
||||||
|
{
|
||||||
|
return fMessageQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLaunchContext
|
||||||
|
void
|
||||||
|
RosterLaunchApp::SetLaunchContext(LaunchContext *context)
|
||||||
|
{
|
||||||
|
fLaunchContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLaunchContext
|
||||||
|
LaunchContext *
|
||||||
|
RosterLaunchApp::GetLaunchContext() const
|
||||||
|
{
|
||||||
|
return fLaunchContext;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
// LaunchTesterHelper.h
|
||||||
|
|
||||||
|
#ifndef LAUNCH_TESTER_HELPER_H
|
||||||
|
#define LAUNCH_TESTER_HELPER_H
|
||||||
|
|
||||||
|
#include <Application.h>
|
||||||
|
#include <Locker.h>
|
||||||
|
#include <MessageQueue.h>
|
||||||
|
#include <OS.h>
|
||||||
|
|
||||||
|
// LaunchCaller
|
||||||
|
class LaunchCaller {
|
||||||
|
public:
|
||||||
|
virtual status_t operator()(const char *type, team_id *team) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// LaunchContext
|
||||||
|
class LaunchContext {
|
||||||
|
public:
|
||||||
|
LaunchContext(LaunchCaller &caller);
|
||||||
|
~LaunchContext();
|
||||||
|
|
||||||
|
status_t operator()(const char *type, team_id *team);
|
||||||
|
|
||||||
|
void HandleMessage(BMessage *message);
|
||||||
|
|
||||||
|
void Terminate();
|
||||||
|
|
||||||
|
team_id TeamAt(int32 index) const;
|
||||||
|
|
||||||
|
BMessage *NextMessageFrom(team_id team, int32 &cookie,
|
||||||
|
bigtime_t *time = NULL);
|
||||||
|
bool CheckNextMessage(team_id team, int32 &cookie, uint32 what);
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Message;
|
||||||
|
class AppInfo;
|
||||||
|
|
||||||
|
private:
|
||||||
|
AppInfo *AppInfoAt(int32 index) const;
|
||||||
|
AppInfo *AppInfoFor(team_id team) const;
|
||||||
|
AppInfo *CreateAppInfo(team_id team, const BMessenger *messenger = NULL);
|
||||||
|
AppInfo *CreateAppInfo(BMessenger messenger);
|
||||||
|
void TerminateApp(AppInfo *info);
|
||||||
|
|
||||||
|
int32 Terminator();
|
||||||
|
|
||||||
|
static int32 AppThreadEntry(void *data);
|
||||||
|
static int32 TerminatorEntry(void *data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
LaunchCaller &fCaller;
|
||||||
|
BList fAppInfos;
|
||||||
|
mutable BLocker fLock;
|
||||||
|
thread_id fAppThread;
|
||||||
|
thread_id fTerminator;
|
||||||
|
bool fTerminating;
|
||||||
|
};
|
||||||
|
|
||||||
|
// RosterLaunchApp
|
||||||
|
class RosterLaunchApp : public BApplication {
|
||||||
|
public:
|
||||||
|
RosterLaunchApp(const char *signature);
|
||||||
|
|
||||||
|
virtual void MessageReceived(BMessage *message);
|
||||||
|
|
||||||
|
BMessageQueue &MessageQueue();
|
||||||
|
|
||||||
|
void SetLaunchContext(LaunchContext *context);
|
||||||
|
LaunchContext *GetLaunchContext() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
BMessageQueue fMessageQueue;
|
||||||
|
LaunchContext *fLaunchContext;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LAUNCH_TESTER_HELPER_H
|
||||||
Reference in New Issue
Block a user