//------------------------------------------------------------------------------
//	LaunchTester.cpp
//
//------------------------------------------------------------------------------

// Standard Includes -----------------------------------------------------------
#include <stdio.h>
#include <utime.h>

// System Includes -------------------------------------------------------------
#include <Message.h>
#include <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, bool traverse = true)
{
	entry_ref ref;
	BEntry entry;
	CHK(entry.SetTo(filename, traverse) == 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,
		   uint32 appFlags = B_SINGLE_LAUNCH)
{
	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);
	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);
}

// 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;
	BRoster roster;
	team_id team;
	CHK(context(caller, 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;
	BRoster roster;
	install_type(fileType1);
	team_id team;
	CHK(context(caller, 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;
	BRoster roster;
	install_type(fileType1, appType1);
	team_id team;
	CHK(context(caller, 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 team to the ID of the team
					running the application's executable. Should install the
					app type and set the app hint on it.
*/
static
void
CommonLaunchTest4(LaunchCaller &caller)
{
	LaunchContext context;
	BRoster roster;
	create_app(appFile1, appType1);
	install_type(fileType1, appType1);
	team_id team;
	CHK(context(caller, fileType1, &team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckMessageMessages(caller, team, cookie));
	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	@case 5			installed type mimeType, preferred app, app type installed,
					app has signature
	@results		Should return B_OK and set team to the ID of the team
					running the application's executable. Should set the app
					hint on the app type.
*/
static
void
CommonLaunchTest5(LaunchCaller &caller)
{
	LaunchContext context;
	BRoster roster;
	create_app(appFile1, appType1, true);
	install_type(fileType1, appType1);
	team_id team;
	CHK(context(caller, fileType1, &team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckMessageMessages(caller, team, cookie));
	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	@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 team to the ID of the team
					running the application's executable. Should set the app
					hint on the app type.
*/
static
void
CommonLaunchTest6(LaunchCaller &caller)
{
	LaunchContext context;
	BRoster roster;
	create_app(appFile1, appType1, true, false);
	install_type(fileType1, appType1);
	team_id team;
	CHK(context(caller, fileType1, &team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckMessageMessages(caller, team, cookie));
	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	@case 7			installed type mimeType, preferred app, app type installed,
					two apps have the signature
	@results		Should return B_OK and set team to the ID of the team
					running 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;
	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(caller, fileType1, &team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile2) == ref);
	check_app_type(appType1, appFile2);
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckMessageMessages(caller, team, cookie));
	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	@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 team to the ID of the team
					running the application executable with version info.
					Should set the app hint on the app type.
*/
static
void
CommonLaunchTest8(LaunchCaller &caller)
{
	LaunchContext context;
	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(caller, fileType1, &team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckMessageMessages(caller, team, cookie));
	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	@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 team to the ID of the team
					running the application executable with the greater
					version. Should set the app hint on the app type.
*/
static
void
CommonLaunchTest9(LaunchCaller &caller)
{
	LaunchContext context;
	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(caller, fileType1, &team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckMessageMessages(caller, team, cookie));
	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	@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 team to the ID of the team
					running 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;
	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(caller, 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);
// OBOS: We set the app hint for app type 2. There's no reason not to do it.
#ifdef TEST_R5
	CHK(BMimeType(appType2).IsInstalled() == false);
#else
	check_app_type(appType2, appFile1);
#endif
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckMessageMessages(caller, team, cookie));
	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	@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 team to the ID of the team
					running the application's executable. Should update the
					app hint on the app type.
*/
static
void
CommonLaunchTest11(LaunchCaller &caller)
{
	LaunchContext context;
	BRoster roster;
	create_app(appFile1, appType1);
	set_type_app_hint(appType1, appFile2);
	install_type(fileType1, appType1);
	team_id team;
	CHK(context(caller, fileType1, &team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckMessageMessages(caller, team, cookie));
	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	@case 12		mimeType is app signature, not installed
	@results		Should return B_OK and set team to the ID of the team
					running the application executable. Should set the app
					hint on the app type.
*/
static
void
CommonLaunchTest12(LaunchCaller &caller)
{
	LaunchContext context;
	BRoster roster;
	create_app(appFile1, appType1);
	team_id team;
	CHK(context(caller, appType1, &team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckMessageMessages(caller, team, cookie));
	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	@case 13		mimeType is installed, but has no preferred application,
					super type has preferred application
	@results		Should return B_OK and set team to the ID of the team
					running 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;
	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(caller, textTestType, &team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckMessageMessages(caller, team, cookie));
	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	@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;
	BRoster roster;
	create_app(get_trash_app_file(), appType1);
	install_type(fileType1, appType1);
	team_id team;
	CHK(context(caller, fileType1, &team) == B_LAUNCH_FAILED_APP_IN_TRASH);
}

/*
	@case 15		installed type mimeType, preferred app, app type not
					installed, app has signature, team is NULL
	@results		Should return B_OK and set team to the ID of the team
					running the application's executable. Should install the
					app type and set the app hint on it.
*/
static
void
CommonLaunchTest15(LaunchCaller &caller)
{
	LaunchContext context;
	BRoster roster;
	create_app(appFile1, appType1);
	install_type(fileType1, appType1);
	CHK(context(caller, fileType1, NULL) == B_OK);
	context.WaitForMessage(MSG_STARTED, true);
	team_id team = context.TeamAt(0);
	CHK(team >= 0);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckMessageMessages(caller, team, cookie));
	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	@case 16		launch the app two times: B_MULTIPLE_LAUNCH | B_ARGV_ONLY
	@results		first app:	ArgvReceived(), ReadyToRun(), QuitRequested()
					second app:	ArgvReceived(), ReadyToRun(), QuitRequested()
*/
static
void
CommonLaunchTest16(LaunchCaller &caller)
{
	LaunchCaller &caller2 = caller.Clone();
	LaunchContext context;
	BRoster roster;
	create_app(appFile1, appType1, false, true,
			   B_MULTIPLE_LAUNCH | B_ARGV_ONLY);
	install_type(fileType1, appType1);
	// launch app 1
	team_id team1;
	CHK(context(caller, fileType1, &team1) == B_OK);
	entry_ref ref1 = ref_for_team(team1);
	CHK(ref_for_path(appFile1) == ref1);
	check_app_type(appType1, appFile1);
	context.WaitForMessage(team1, MSG_STARTED);
	// launch app 2
	team_id team2;
	CHK(context(caller2, fileType1, &team2) == B_OK);
	entry_ref ref2 = ref_for_team(team2);
	CHK(ref_for_path(appFile1) == ref2);
	check_app_type(appType1, appFile1);
	// checks 1
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team1, cookie, &ref1));
//	CHK(context.CheckMessageMessages(caller, team1, cookie));
	CHK(context.CheckArgvMessage(caller, team1, cookie, &ref1));
//	if (caller.SupportsRefs() && !caller.SupportsArgv())
//		CHK(context.CheckRefsMessage(caller, team1, cookie));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_TERMINATED));
	// checks 2
	cookie = 0;
	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller2, team2, cookie, &ref2));
//	CHK(context.CheckMessageMessages(caller2, team2, cookie));
	CHK(context.CheckArgvMessage(caller2, team2, cookie, &ref2));
//	if (caller.SupportsRefs() && !caller.SupportsArgv())
//		CHK(context.CheckRefsMessage(caller2, team2, cookie));
	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_TERMINATED));
}

/*
	@case 17		launch the app two times: B_MULTIPLE_LAUNCH | B_ARGV_ONLY
	@results		first app:	{Message,Argv,Refs}Received()*, ReadyToRun(),
								QuitRequested()
					second app:	{Message,Argv,Refs}Received()*, ReadyToRun(),
								QuitRequested()
*/
static
void
CommonLaunchTest17(LaunchCaller &caller)
{
	LaunchCaller &caller2 = caller.Clone();
	LaunchContext context;
	BRoster roster;
	create_app(appFile1, appType1, false, true,
			   B_MULTIPLE_LAUNCH);
	install_type(fileType1, appType1);
	// launch app 1
	team_id team1;
	CHK(context(caller, fileType1, &team1) == B_OK);
	entry_ref ref1 = ref_for_team(team1);
	CHK(ref_for_path(appFile1) == ref1);
	check_app_type(appType1, appFile1);
	context.WaitForMessage(team1, MSG_STARTED);
	// launch app 2
	team_id team2;
	CHK(context(caller2, fileType1, &team2) == B_OK);
	entry_ref ref2 = ref_for_team(team2);
	CHK(ref_for_path(appFile1) == ref2);
	check_app_type(appType1, appFile1);
	// checks 1
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team1, cookie, &ref1));
	CHK(context.CheckMessageMessages(caller, team1, cookie));
	CHK(context.CheckArgvMessage(caller, team1, cookie, &ref1));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller, team1, cookie));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_TERMINATED));
	// checks 2
	cookie = 0;
	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller2, team2, cookie, &ref2));
	CHK(context.CheckMessageMessages(caller2, team2, cookie));
	CHK(context.CheckArgvMessage(caller2, team2, cookie, &ref2));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller2, team2, cookie));
	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_TERMINATED));
}

/*
	@case 18		launch the app two times: B_SINGLE_LAUNCH | B_ARGV_ONLY
	@results		first app:	ArgvReceived(), ReadyToRun(), QuitRequested()
								(No second ArgvReceived()!)
					second app:	Launch() fails with B_ALREADY_RUNNING
*/
static
void
CommonLaunchTest18(LaunchCaller &caller)
{
	LaunchCaller &caller2 = caller.Clone();
	LaunchContext context;
	BRoster roster;
	create_app(appFile1, appType1, false, true,
			   B_SINGLE_LAUNCH | B_ARGV_ONLY);
	install_type(fileType1, appType1);
	// launch app 1
	team_id team1;
	CHK(context(caller, fileType1, &team1) == B_OK);
	entry_ref ref1 = ref_for_team(team1);
	CHK(ref_for_path(appFile1) == ref1);
	check_app_type(appType1, appFile1);
	context.WaitForMessage(team1, MSG_STARTED);
	// launch app 2
	team_id team2;
	CHK(context(caller2, fileType1, &team2) == B_ALREADY_RUNNING);
	// checks 1
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team1, cookie, &ref1));
//	CHK(context.CheckMessageMessages(caller, team1, cookie));
	CHK(context.CheckArgvMessage(caller, team1, cookie, &ref1));
//	if (caller.SupportsRefs() && !caller.SupportsArgv())
//		CHK(context.CheckRefsMessage(caller, team1, cookie));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_TERMINATED));
}

/*
	@case 19		launch the app two times: B_SINGLE_LAUNCH
	@results		first app:	{Message,Argv,Refs}Received()*, ReadyToRun(),
								{Message,Argv,Refs}Received()*, QuitRequested()
					second app:	Launch() fails with B_ALREADY_RUNNING
*/
static
void
CommonLaunchTest19(LaunchCaller &caller)
{
	LaunchCaller &caller2 = caller.Clone();
	LaunchContext context;
	BRoster roster;
	create_app(appFile1, appType1, false, true,
			   B_SINGLE_LAUNCH);
	install_type(fileType1, appType1);
	// launch app 1
	team_id team1;
	CHK(context(caller, fileType1, &team1) == B_OK);
	entry_ref ref1 = ref_for_team(team1);
	CHK(ref_for_path(appFile1) == ref1);
	check_app_type(appType1, appFile1);
	context.WaitForMessage(team1, MSG_STARTED);
	// launch app 2
	team_id team2;
	CHK(context(caller2, fileType1, &team2) == B_ALREADY_RUNNING);
	// checks 1
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team1, cookie, &ref1));
	CHK(context.CheckMessageMessages(caller, team1, cookie));
	CHK(context.CheckArgvMessage(caller, team1, cookie, &ref1));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller, team1, cookie));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckMessageMessages(caller, team1, cookie));
	CHK(context.CheckArgvMessage(caller, team1, cookie, &ref1));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller, team1, cookie));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_TERMINATED));
}

/*
	@case 20		launch two apps with the same signature:
					B_SINGLE_LAUNCH | B_ARGV_ONLY
	@results		first app:	ArgvReceived(), ReadyToRun(), QuitRequested()
					second app:	ArgvReceived(), ReadyToRun(), QuitRequested()
*/
static
void
CommonLaunchTest20(LaunchCaller &caller)
{
	LaunchCaller &caller2 = caller.Clone();
	LaunchContext context;
	BRoster roster;
	// launch app 1
	create_app(appFile1, appType1, false, true,
			   B_SINGLE_LAUNCH | B_ARGV_ONLY);
	install_type(fileType1, appType1);
	team_id team1;
	CHK(context(caller, fileType1, &team1) == B_OK);
	entry_ref ref1 = ref_for_team(team1);
	CHK(ref_for_path(appFile1) == ref1);
	check_app_type(appType1, appFile1);
	context.WaitForMessage(team1, MSG_STARTED);
	// launch app 2 (greater modification time)
	CHK(BMimeType(appType1).Delete() == B_OK);
	create_app(appFile2, appType1, false, true,
			   B_SINGLE_LAUNCH | B_ARGV_ONLY);
	set_file_time(appFile2, time(NULL) + 1);
	team_id team2;
	CHK(context(caller2, fileType1, &team2) == B_OK);
	entry_ref ref2 = ref_for_team(team2);
	CHK(ref_for_path(appFile2) == ref2);
	check_app_type(appType1, appFile2);
	// checks 1
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team1, cookie, &ref1));
//	CHK(context.CheckMessageMessages(caller, team1, cookie));
	CHK(context.CheckArgvMessage(caller, team1, cookie, &ref1));
//	if (caller.SupportsRefs() && !caller.SupportsArgv())
//		CHK(context.CheckRefsMessage(caller, team1, cookie));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_TERMINATED));
	// checks 2
	cookie = 0;
	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller2, team2, cookie, &ref2));
//	CHK(context.CheckMessageMessages(caller2, team2, cookie));
	CHK(context.CheckArgvMessage(caller2, team2, cookie, &ref2));
//	if (caller.SupportsRefs() && !caller.SupportsArgv())
//		CHK(context.CheckRefsMessage(caller2, team2, cookie));
	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_TERMINATED));
}

/*
	@case 21		launch two apps with the same signature: B_SINGLE_LAUNCH
	@results		first app:	{Message,Argv,Refs}Received()*, ReadyToRun(),
								QuitRequested()
					second app:	{Message,Argv,Refs}Received()*, ReadyToRun(),
								QuitRequested()
*/
static
void
CommonLaunchTest21(LaunchCaller &caller)
{
	LaunchCaller &caller2 = caller.Clone();
	LaunchContext context;
	BRoster roster;
	// launch app 1
	create_app(appFile1, appType1, false, true,
			   B_SINGLE_LAUNCH);
	install_type(fileType1, appType1);
	team_id team1;
	CHK(context(caller, fileType1, &team1) == B_OK);
	entry_ref ref1 = ref_for_team(team1);
	CHK(ref_for_path(appFile1) == ref1);
	check_app_type(appType1, appFile1);
	context.WaitForMessage(team1, MSG_STARTED);
	// launch app 2 (greater modification time)
	CHK(BMimeType(appType1).Delete() == B_OK);
	create_app(appFile2, appType1, false, true,
			   B_SINGLE_LAUNCH);
	set_file_time(appFile2, time(NULL) + 1);
	team_id team2;
	CHK(context(caller2, fileType1, &team2) == B_OK);
	entry_ref ref2 = ref_for_team(team2);
	CHK(ref_for_path(appFile2) == ref2);
	check_app_type(appType1, appFile2);
	// checks 1
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team1, cookie, &ref1));
	CHK(context.CheckMessageMessages(caller, team1, cookie));
	CHK(context.CheckArgvMessage(caller, team1, cookie, &ref1));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller, team1, cookie));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_TERMINATED));
	// checks 2
	cookie = 0;
	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller2, team2, cookie, &ref2));
	CHK(context.CheckMessageMessages(caller2, team2, cookie));
	CHK(context.CheckArgvMessage(caller2, team2, cookie, &ref2));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller2, team2, cookie));
	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller2, team2, cookie, MSG_TERMINATED));
}

/*
	@case 22		launch the app two times: B_EXCLUSIVE_LAUNCH | B_ARGV_ONLY
	@results		first app:	ArgvReceived(), ReadyToRun(), QuitRequested()
								(No second ArgvReceived()!)
					second app:	Launch() fails with B_ALREADY_RUNNING
*/
static
void
CommonLaunchTest22(LaunchCaller &caller)
{
	LaunchCaller &caller2 = caller.Clone();
	LaunchContext context;
	BRoster roster;
	create_app(appFile1, appType1, false, true,
			   B_EXCLUSIVE_LAUNCH | B_ARGV_ONLY);
	install_type(fileType1, appType1);
	// launch app 1
	team_id team1;
	CHK(context(caller, fileType1, &team1) == B_OK);
	entry_ref ref1 = ref_for_team(team1);
	CHK(ref_for_path(appFile1) == ref1);
	check_app_type(appType1, appFile1);
	context.WaitForMessage(team1, MSG_STARTED);
	// launch app 2
	team_id team2;
	CHK(context(caller2, fileType1, &team2) == B_ALREADY_RUNNING);
	// checks 1
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team1, cookie, &ref1));
//	CHK(context.CheckMessageMessages(caller, team1, cookie));
	CHK(context.CheckArgvMessage(caller, team1, cookie, &ref1));
//	if (caller.SupportsRefs() && !caller.SupportsArgv())
//		CHK(context.CheckRefsMessage(caller, team1, cookie));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_TERMINATED));
}

/*
	@case 23		launch the app two times: B_EXCLUSIVE_LAUNCH
	@results		first app:	{Message,Argv,Refs}Received()*, ReadyToRun(),
								{Message,Argv,Refs}Received()*, QuitRequested()
					second app:	Launch() fails with B_ALREADY_RUNNING
*/
static
void
CommonLaunchTest23(LaunchCaller &caller)
{
	LaunchCaller &caller2 = caller.Clone();
	LaunchContext context;
	BRoster roster;
	create_app(appFile1, appType1, false, true,
			   B_EXCLUSIVE_LAUNCH);
	install_type(fileType1, appType1);
	// launch app 1
	team_id team1;
	CHK(context(caller, fileType1, &team1) == B_OK);
	entry_ref ref1 = ref_for_team(team1);
	CHK(ref_for_path(appFile1) == ref1);
	check_app_type(appType1, appFile1);
	context.WaitForMessage(team1, MSG_STARTED);
	// launch app 2
	team_id team2;
	CHK(context(caller2, fileType1, &team2) == B_ALREADY_RUNNING);
	// checks 1
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team1, cookie, &ref1));
	CHK(context.CheckMessageMessages(caller, team1, cookie));
	CHK(context.CheckArgvMessage(caller, team1, cookie, &ref1));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller, team1, cookie));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckMessageMessages(caller, team1, cookie));
	CHK(context.CheckArgvMessage(caller, team1, cookie, &ref1));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller, team1, cookie));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_TERMINATED));
}

/*
	@case 24		launch two apps with the same signature:
					B_EXCLUSIVE_LAUNCH | B_ARGV_ONLY
	@results		first app:	ArgvReceived(), ReadyToRun(), QuitRequested()
								(No second ArgvReceived()!)
					second app:	Launch() fails with B_ALREADY_RUNNING
*/
static
void
CommonLaunchTest24(LaunchCaller &caller)
{
	LaunchCaller &caller2 = caller.Clone();
	LaunchContext context;
	BRoster roster;
	// launch app 1
	create_app(appFile1, appType1, false, true,
			   B_EXCLUSIVE_LAUNCH | B_ARGV_ONLY);
	install_type(fileType1, appType1);
	team_id team1;
	CHK(context(caller, fileType1, &team1) == B_OK);
	entry_ref ref1 = ref_for_team(team1);
	CHK(ref_for_path(appFile1) == ref1);
	check_app_type(appType1, appFile1);
	context.WaitForMessage(team1, MSG_STARTED);
	// launch app 2 (greater modification time)
	CHK(BMimeType(appType1).Delete() == B_OK);
	create_app(appFile2, appType1, false, true,
			   B_EXCLUSIVE_LAUNCH | B_ARGV_ONLY);
	set_file_time(appFile2, time(NULL) + 1);
	team_id team2;
	CHK(context(caller2, fileType1, &team2) == B_ALREADY_RUNNING);
	// checks 1
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team1, cookie, &ref1));
//	CHK(context.CheckMessageMessages(caller, team1, cookie));
	CHK(context.CheckArgvMessage(caller, team1, cookie, &ref1));
//	if (caller.SupportsRefs() && !caller.SupportsArgv())
//		CHK(context.CheckRefsMessage(caller, team1, cookie));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_TERMINATED));
}

/*
	@case 25		launch two apps with the same signature:
					B_EXCLUSIVE_LAUNCH
	@results		first app:	{Message,Argv,Refs}Received()*, ReadyToRun(),
								{Message,Argv,Refs}Received()*, QuitRequested()
					second app:	Launch() fails with B_ALREADY_RUNNING
*/
static
void
CommonLaunchTest25(LaunchCaller &caller)
{
	LaunchCaller &caller2 = caller.Clone();
	LaunchContext context;
	BRoster roster;
	// launch app 1
	create_app(appFile1, appType1, false, true,
			   B_EXCLUSIVE_LAUNCH);
	install_type(fileType1, appType1);
	team_id team1;
	CHK(context(caller, fileType1, &team1) == B_OK);
	entry_ref ref1 = ref_for_team(team1);
	CHK(ref_for_path(appFile1) == ref1);
	check_app_type(appType1, appFile1);
	context.WaitForMessage(team1, MSG_STARTED);
	// launch app 2 (greater modification time)
	CHK(BMimeType(appType1).Delete() == B_OK);
	create_app(appFile2, appType1, false, true,
			   B_EXCLUSIVE_LAUNCH);
	set_file_time(appFile2, time(NULL) + 1);
	team_id team2;
	CHK(context(caller2, fileType1, &team2) == B_ALREADY_RUNNING);
	entry_ref ref2 = ref_for_path(appFile2);
	// checks 1
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team1, cookie, &ref1));
	CHK(context.CheckMessageMessages(caller, team1, cookie));
	CHK(context.CheckArgvMessage(caller, team1, cookie, &ref1));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller, team1, cookie));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckMessageMessages(caller, team1, cookie));
	CHK(context.CheckArgvMessage(caller, team1, cookie, &ref2));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller, team1, cookie));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_TERMINATED));
}

/*
	@case 26		launch two apps with the same signature:
					first: B_EXCLUSIVE_LAUNCH,
					second: B_EXCLUSIVE_LAUNCH | B_ARGV_ONLY =>
	@results		first app:	{Message,Argv,Refs}Received()*, ReadyToRun(),
								QuitRequested()
					second app:	Launch() fails with B_ALREADY_RUNNING
*/
static
void
CommonLaunchTest26(LaunchCaller &caller)
{
	LaunchCaller &caller2 = caller.Clone();
	LaunchContext context;
	BRoster roster;
	// launch app 1
	create_app(appFile1, appType1, false, true,
			   B_EXCLUSIVE_LAUNCH);
	install_type(fileType1, appType1);
	team_id team1;
	CHK(context(caller, fileType1, &team1) == B_OK);
	entry_ref ref1 = ref_for_team(team1);
	CHK(ref_for_path(appFile1) == ref1);
	check_app_type(appType1, appFile1);
	context.WaitForMessage(team1, MSG_STARTED);
	// launch app 2 (greater modification time)
	CHK(BMimeType(appType1).Delete() == B_OK);
	create_app(appFile2, appType1, false, true,
			   B_EXCLUSIVE_LAUNCH | B_ARGV_ONLY);
	set_file_time(appFile2, time(NULL) + 1);
	team_id team2;
	CHK(context(caller2, fileType1, &team2) == B_ALREADY_RUNNING);
	entry_ref ref2 = ref_for_path(appFile2);
	// checks 1
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team1, cookie, &ref1));
	CHK(context.CheckMessageMessages(caller, team1, cookie));
	CHK(context.CheckArgvMessage(caller, team1, cookie, &ref1));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller, team1, cookie));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_TERMINATED));
}

/*
	@case 27		launch two apps with the same signature:
					first: B_EXCLUSIVE_LAUNCH | B_ARGV_ONLY,
					second: B_EXCLUSIVE_LAUNCH
	@results		first app:	ArgvReceived(), ReadyToRun(), QuitRequested()
								(No second ArgvReceived()!)
					second app:	Launch() fails with B_ALREADY_RUNNING
*/
static
void
CommonLaunchTest27(LaunchCaller &caller)
{
	LaunchCaller &caller2 = caller.Clone();
	LaunchContext context;
	BRoster roster;
	// launch app 1
	create_app(appFile1, appType1, false, true,
			   B_EXCLUSIVE_LAUNCH | B_ARGV_ONLY);
	install_type(fileType1, appType1);
	team_id team1;
	CHK(context(caller, fileType1, &team1) == B_OK);
	entry_ref ref1 = ref_for_team(team1);
	CHK(ref_for_path(appFile1) == ref1);
	check_app_type(appType1, appFile1);
	context.WaitForMessage(team1, MSG_STARTED);
	// launch app 2 (greater modification time)
	CHK(BMimeType(appType1).Delete() == B_OK);
	create_app(appFile2, appType1, false, true,
			   B_EXCLUSIVE_LAUNCH);
	set_file_time(appFile2, time(NULL) + 1);
	team_id team2;
	CHK(context(caller2, fileType1, &team2) == B_ALREADY_RUNNING);
	// checks 1
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team1, cookie, &ref1));
//	CHK(context.CheckMessageMessages(caller, team1, cookie));
	CHK(context.CheckArgvMessage(caller, team1, cookie, &ref1));
//	if (caller.SupportsRefs() && !caller.SupportsArgv())
//		CHK(context.CheckRefsMessage(caller, team1, cookie));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team1, cookie, MSG_TERMINATED));
}

/*
	@case 28		installed type mimeType, preferred app, app type installed,
					preferred app type has an app hint pointing to void,
					no app with this signature exists
	@results		Should return B_LAUNCH_FAILED_APP_NOT_FOUND and unset the
					app type's app hint.
*/
static
void
CommonLaunchTest28(LaunchCaller &caller)
{
	LaunchContext context;
	BRoster roster;
	set_type_app_hint(appType1, appFile1);
	install_type(fileType1, appType1);
	team_id team;
	CHK(context(caller, fileType1, &team) == B_LAUNCH_FAILED_APP_NOT_FOUND);
	entry_ref appHint;
	CHK(BMimeType(appType1).GetAppHint(&appHint) == B_ENTRY_NOT_FOUND);
}

/*
	@case 29		installed type mimeType, preferred app, app type installed,
					preferred app type has an app hint pointing to a cyclic
					link, no app with this signature exists
	@results		Should return
					OBOS: B_LAUNCH_FAILED_APP_NOT_FOUND and unset the app
					type's app hint.
					R5: B_ENTRY_NOT_FOUND or B_LAUNCH_FAILED_NO_RESOLVE_LINK.
*/
static
void
CommonLaunchTest29(LaunchCaller &caller)
{
	LaunchContext context;
	BRoster roster;
	set_type_app_hint(appType1, appFile1);
	install_type(fileType1, appType1);
	system((string("ln -s ") + appFile1 + " " + appFile1).c_str());
	team_id team;
	entry_ref appHint;
#if TEST_R5
	if (caller.SupportsRefs()) {
		CHK(context(caller, fileType1, &team)
			== B_LAUNCH_FAILED_NO_RESOLVE_LINK);
	} else
		CHK(context(caller, fileType1, &team) == B_ENTRY_NOT_FOUND);
	CHK(BMimeType(appType1).GetAppHint(&appHint) == B_OK);
	CHK(appHint == ref_for_path(appFile1, false));
#else
	CHK(context(caller, fileType1, &team) == B_LAUNCH_FAILED_APP_NOT_FOUND);
	CHK(BMimeType(appType1).GetAppHint(&appHint) == B_ENTRY_NOT_FOUND);
#endif
}

/*
	@case 30		installed type mimeType, preferred app, app type installed,
					preferred app type has an app hint that points to an app
					without a signature, app will pass a different signature
					to the BApplication constructor
	@results		Should return B_OK and set team to the ID of the team
					running the application's executable. Should remove the
					incorrect app hint on the app type.
					BRoster::GetRunningAppInfo() should return an app_info
					with the signature passed to the BApplication constructor.
*/
static
void
CommonLaunchTest30(LaunchCaller &caller)
{
	LaunchContext context;
	BRoster roster;
	create_app(appFile1, NULL);
	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(caller, fileType1, &team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
// OBOS: We unset the app hint for the app type. R5 leaves it untouched.
#ifdef TEST_R5
	check_app_type(appType1, appFile1);
#else
	CHK(BMimeType(appType1).GetAppHint(&appHint) == B_ENTRY_NOT_FOUND);
#endif
	context.WaitForMessage(team, MSG_STARTED, true);
	app_info appInfo;
	CHK(roster.GetRunningAppInfo(team, &appInfo) == B_OK);
// R5 keeps appType1, OBOS updates the signature
#ifdef TEST_R5
	CHK(!strcmp(appInfo.signature, appType1));
#else
	CHK(!strcmp(appInfo.signature, kDefaultTestAppSignature));
#endif
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckMessageMessages(caller, team, cookie));
	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	if (caller.SupportsRefs() && !caller.SupportsArgv())
		CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

typedef void commonTestFunction(LaunchCaller &caller);
static commonTestFunction *commonTestFunctions[] = {
	CommonLaunchTest1, CommonLaunchTest2, CommonLaunchTest3,
	CommonLaunchTest4, CommonLaunchTest5, CommonLaunchTest6,
	CommonLaunchTest7, CommonLaunchTest8, CommonLaunchTest9,
	CommonLaunchTest10, CommonLaunchTest11, CommonLaunchTest12,
	CommonLaunchTest13, CommonLaunchTest14, CommonLaunchTest15,
	CommonLaunchTest16, CommonLaunchTest17, CommonLaunchTest18,
	CommonLaunchTest19, CommonLaunchTest20, CommonLaunchTest21,
	CommonLaunchTest22, CommonLaunchTest23, CommonLaunchTest24,
	CommonLaunchTest25, CommonLaunchTest26, CommonLaunchTest27,
	CommonLaunchTest28, CommonLaunchTest29, CommonLaunchTest30
};
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;
	BMessage message;
	CHK(roster.Launch((const char*)NULL, &message, 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;
	BMessage message;
	CHK(roster.Launch("invalid/mine/type", &message, NULL) == B_BAD_VALUE);
}

// LaunchTypeCaller1
class LaunchTypeCaller1 : public LaunchCaller {
public:
	virtual status_t operator()(const char *type, BList *messages, int32 argc,
								const char **argv, team_id *team)
	{
		BMessage *message = (messages ? (BMessage*)messages->ItemAt(0L)
									  : NULL);
		BRoster roster;
		return roster.Launch(type, message, team);
	}

	virtual LaunchCaller *CloneInternal()
	{
		return new LaunchTypeCaller1;
	}
};

/*
	status_t Launch(const char *mimeType, BMessage *initialMsgs,
					team_id *appTeam) const
	@case 3			common cases 1-14
*/
void LaunchTester::LaunchTestA3()
{
	LaunchTypeCaller1 caller;
	for (int32 i = 0; i < commonTestFunctionCount; i++) {
		NextSubTest();
		(*commonTestFunctions[i])(caller);
		tearDown();
		setUp();
	}
}

/*
	status_t Launch(const char *mimeType, BMessage *initialMsgs,
					team_id *appTeam) const
	@case 4			installed type mimeType, preferred app, app type not
					installed, app has signature, NULL initialMsg
	@results		Should return B_OK and set team to the ID of the team
					running the application's executable. Should install the
					app type and set the app hint on it.
*/
void LaunchTester::LaunchTestA4()
{
	LaunchTypeCaller1 caller;
	LaunchContext context;
	BRoster roster;
	create_app(appFile1, appType1);
	install_type(fileType1, appType1);
	team_id team;
	CHK(context(caller, fileType1, NULL, LaunchContext::kStandardArgc,
				LaunchContext::kStandardArgv, &team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
//	CHK(context.CheckMessageMessages(caller, team, cookie));
//	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
//	CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	status_t Launch(const char *mimeType, BList *messageList,
					team_id *appTeam) const
	@case 1			mimeType is NULL
	@results		Should return B_BAD_VALUE.
*/
void LaunchTester::LaunchTestB1()
{
	BRoster roster;
	BList list;
	CHK(roster.Launch((const char*)NULL, &list, 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::LaunchTestB2()
{
	BRoster roster;
	BList list;
	CHK(roster.Launch("invalid/mine/type", &list, NULL) == B_BAD_VALUE);
}

// LaunchTypeCaller2
class LaunchTypeCaller2 : public LaunchCaller {
public:
	virtual status_t operator()(const char *type, BList *messages, int32 argc,
								const char **argv, team_id *team)
	{
		BRoster roster;
		return roster.Launch(type, messages, team);
	}
	virtual int32 SupportsMessages() const { return 1000; }

	virtual LaunchCaller *CloneInternal()
	{
		return new LaunchTypeCaller2;
	}
};

/*
	status_t Launch(const char *mimeType, BList *messageList,
					team_id *appTeam) const
	@case 3			common cases 1-14
*/
void LaunchTester::LaunchTestB3()
{
	LaunchTypeCaller2 caller;
	for (int32 i = 0; i < commonTestFunctionCount; i++) {
		NextSubTest();
		(*commonTestFunctions[i])(caller);
		tearDown();
		setUp();
	}
}

/*
	status_t Launch(const char *mimeType, BList *messageList,
					team_id *appTeam) const
	@case 4			installed type mimeType, preferred app, app type not
					installed, app has signature, NULL messageList
	@results		Should return B_OK and set team to the ID of the team
					running the application's executable. Should install the
					app type and set the app hint on it.
*/
void LaunchTester::LaunchTestB4()
{
	LaunchTypeCaller2 caller;
	LaunchContext context;
	BRoster roster;
	create_app(appFile1, appType1);
	install_type(fileType1, appType1);
	team_id team;
	CHK(context(caller, fileType1, NULL, LaunchContext::kStandardArgc,
				LaunchContext::kStandardArgv, &team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
//	CHK(context.CheckMessageMessages(caller, team, cookie));
//	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
//	CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	status_t Launch(const char *mimeType, BList *messageList,
					team_id *appTeam) const
	@case 5			installed type mimeType, preferred app, app type not
					installed, app has signature, empty messageList
	@results		Should return B_OK and set team to the ID of the team
					running the application's executable. Should install the
					app type and set the app hint on it.
*/
void LaunchTester::LaunchTestB5()
{
	LaunchTypeCaller2 caller;
	LaunchContext context;
	BRoster roster;
	create_app(appFile1, appType1);
	install_type(fileType1, appType1);
	team_id team;
	BList list;
	CHK(context(caller, fileType1, &list, LaunchContext::kStandardArgc,
				LaunchContext::kStandardArgv, &team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
//	CHK(context.CheckMessageMessages(caller, team, cookie));
//	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
//	CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	status_t Launch(const char *mimeType, int argc, char **args,
					team_id *appTeam) const
	@case 1			mimeType is NULL or argc > 0 and args is NULL
	@results		Should return B_BAD_VALUE.
*/
void LaunchTester::LaunchTestC1()
{
	BRoster roster;
	char *argv[] = { "Hey!" };
	CHK(roster.Launch((const char*)NULL, 1, argv, NULL) == B_BAD_VALUE);
	CHK(roster.Launch((const char*)NULL, 1, (char**)NULL, NULL)
		== B_BAD_VALUE);
}

/*
	status_t Launch(const char *mimeType, int argc, char **args,
					team_id *appTeam) const
	@case 2			mimeType is invalid
	@results		Should return B_BAD_VALUE.
*/
void LaunchTester::LaunchTestC2()
{
	BRoster roster;
	BList list;
	char *argv[] = { "Hey!" };
	CHK(roster.Launch("invalid/mine/type", 1, argv, NULL) == B_BAD_VALUE);
}

// LaunchTypeCaller3
class LaunchTypeCaller3 : public LaunchCaller {
public:
	virtual status_t operator()(const char *type, BList *messages, int32 argc,
								const char **argv, team_id *team)
	{
		BRoster roster;
		return roster.Launch(type, argc, const_cast<char**>(argv), team);
	}
	virtual int32 SupportsMessages() const { return 0; }

	virtual LaunchCaller *CloneInternal()
	{
		return new LaunchTypeCaller3;
	}
};

/*
	status_t Launch(const char *mimeType, int argc, char **args,
					team_id *appTeam) const
	@case 3			common cases 1-14
*/
void LaunchTester::LaunchTestC3()
{
	LaunchTypeCaller3 caller;
	for (int32 i = 0; i < commonTestFunctionCount; i++) {
		NextSubTest();
		(*commonTestFunctions[i])(caller);
		tearDown();
		setUp();
	}
}

/*
	status_t Launch(const char *mimeType, int argc, char **args,
					team_id *appTeam) const
	@case 4			installed type mimeType, preferred app, app type not
					installed, app has signature, NULL args, argc is 0
	@results		Should return B_OK and set team to the ID of the team
					running the application's executable. Should install the
					app type and set the app hint on it.
*/
void LaunchTester::LaunchTestC4()
{
	LaunchTypeCaller3 caller;
	LaunchContext context;
	BRoster roster;
	create_app(appFile1, appType1);
	install_type(fileType1, appType1);
	team_id team;
	CHK(context(caller, fileType1, NULL, 0, (const char**)NULL, &team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);
	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref, 0, NULL));
//	CHK(context.CheckMessageMessages(caller, team, cookie));
//	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
//	CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

// SimpleFileCaller1
class SimpleFileCaller1 : public LaunchCaller {
public:
	SimpleFileCaller1() : fRef() {}
	SimpleFileCaller1(const entry_ref &ref) : fRef(ref) {}
	virtual ~SimpleFileCaller1() {}
	virtual status_t operator()(const char *type, BList *messages, int32 argc,
								const char **argv, team_id *team)
	{
		BRoster roster;
		BMessage *message = (messages ? (BMessage*)messages->ItemAt(0L)
									  : NULL);
		return roster.Launch(&fRef, message, team);
	}
	virtual bool SupportsRefs() const { return true; }
	virtual const entry_ref *Ref() const { return &fRef; }

	virtual LaunchCaller *CloneInternal()
	{
		return new SimpleFileCaller1;
	}

protected:
	entry_ref fRef;
};

// FileWithTypeCaller1
class FileWithTypeCaller1 : public SimpleFileCaller1 {
public:
	virtual status_t operator()(const char *type, BList *messages, int32 argc,
								const char **argv, team_id *team)
	{
		BRoster roster;
		BMessage *message = (messages ? (BMessage*)messages->ItemAt(0L)
									  : NULL);
		fRef = create_file(testFile1, type);
		return roster.Launch(&fRef, message, team);
	}

	virtual LaunchCaller *CloneInternal()
	{
		return new FileWithTypeCaller1;
	}
};

// SniffFileTypeCaller1
class SniffFileTypeCaller1 : public SimpleFileCaller1 {
public:
	virtual status_t operator()(const char *type, BList *messages, int32 argc,
								const char **argv, team_id *team)
	{
		BRoster roster;
		BMessage *message = (messages ? (BMessage*)messages->ItemAt(0L)
									  : NULL);
		fRef = create_file(testFile1, type, NULL, NULL, "UnIQe pAtTeRn");
		install_type(fileType1, NULL, "1.0 [0] ('UnIQe pAtTeRn')");
		return roster.Launch(&fRef, message, team);
	}

	virtual LaunchCaller *CloneInternal()
	{
		return new SniffFileTypeCaller1;
	}
};

/*
	status_t Launch(const entry_ref *ref, const BMessage *initialMessage,
					team_id *app_team) const
	@case 1			ref is NULL
	@results		Should return B_BAD_VALUE.
*/
void LaunchTester::LaunchTestD1()
{
	BRoster roster;
	BMessage message;
	CHK(roster.Launch((const entry_ref*)NULL, &message, NULL) == B_BAD_VALUE);
}

/*
	status_t Launch(const entry_ref *ref, const BMessage *initialMessage,
					team_id *app_team) const
	@case 2			ref doesn't refer to an existing entry
	@results		Should return B_ENTRY_NOT_FOUND.
*/
void LaunchTester::LaunchTestD2()
{
	BRoster roster;
	BMessage message;
	entry_ref fileRef(ref_for_path(testFile1));
	CHK(roster.Launch(&fileRef, &message, NULL) == B_ENTRY_NOT_FOUND);
}

/*
	status_t Launch(const entry_ref *ref, const BMessage *initialMessage,
					team_id *app_team) const
	@case 3			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 team to the ID of the team
					running 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::LaunchTestD3()
{
	BRoster roster;
	create_app(appFile1, appType1);
	create_app(appFile2, appType2);
	install_type(fileType1, appType1);
	entry_ref fileRef(create_file(testFile1, fileType1, appType2));
	SimpleFileCaller1 caller(fileRef);
	LaunchContext context;
	team_id team;
	CHK(context(caller, fileType1, context.StandardMessages(),
				LaunchContext::kStandardArgc, LaunchContext::kStandardArgv,
				&team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile2) == ref);
	check_app_type(appType2, appFile2);

	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckMessageMessages(caller, team, cookie));
//	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	status_t Launch(const entry_ref *ref, const BMessage *initialMessage,
					team_id *app_team) const
	@case 4			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 team to the ID of the team
					running the application's executable. Should install the
					app type and set the app hint on it.
*/
void LaunchTester::LaunchTestD4()
{
	BRoster roster;
	create_app(appFile1, appType1);
	entry_ref fileRef(create_file(testFile1, NULL, appType1));
	SimpleFileCaller1 caller(fileRef);
	LaunchContext context;
	team_id team;
	CHK(context(caller, fileType1, context.StandardMessages(),
				LaunchContext::kStandardArgc, LaunchContext::kStandardArgv,
				&team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);

	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckMessageMessages(caller, team, cookie));
//	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	status_t Launch(const entry_ref *ref, const BMessage *initialMessage,
					team_id *app_team) const
	@case 5			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 team to the ID of the team
					running the file type's preferred application's executable.
					Should install the app type and set the app hint on it.
*/
void LaunchTester::LaunchTestD5()
{
	BRoster roster;
	create_app(appFile1, appType1);
	create_app(appFile2, appType2);
	install_type(fileType1, appType1);
	entry_ref fileRef(create_file(testFile1, fileType1, NULL, appFile2));
	SimpleFileCaller1 caller(fileRef);
	LaunchContext context;
	team_id team;
	CHK(context(caller, fileType1, context.StandardMessages(),
				LaunchContext::kStandardArgc, LaunchContext::kStandardArgv,
				&team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);

	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckMessageMessages(caller, team, cookie));
//	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	status_t Launch(const entry_ref *ref, const BMessage *initialMessage,
					team_id *app_team) const
	@case 6			ref is valid, file has type, the type's preferred app
					type is not installed, app exists and has signature, file
					has executable permission, but is not executable
	@results		Should return B_LAUNCH_FAILED_EXECUTABLE.
					Should not set the app hint on the app or file type.
*/
void LaunchTester::LaunchTestD6()
{
	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());
	BMessage message;
	team_id team;
	CHK(roster.Launch(&fileRef, &message, &team)
		== B_LAUNCH_FAILED_EXECUTABLE);
	CHK(BMimeType(appType1).IsInstalled() == false);
	CHK(BMimeType(fileType1).GetAppHint(&fileRef) == B_ENTRY_NOT_FOUND);
}

/*
	status_t Launch(const entry_ref *ref, const BMessage *initialMessage,
					team_id *app_team) const
	@case 7			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 team to the ID of the team
					running the file type's preferred application's executable.
					Should install the app type and set the app hint on it.
*/
void LaunchTester::LaunchTestD7()
{
	BRoster roster;
	create_app(appFile1, appType1);
	install_type(fileType1, appType1);
	create_file(testFile1, fileType1);
	system((string("ln -s ") + testFile1 + " " + testLink1).c_str());
	entry_ref fileRef(ref_for_path(testFile1, false));
	entry_ref linkRef(ref_for_path(testLink1, false));
	SimpleFileCaller1 caller(linkRef);
	LaunchContext context;
	team_id team;
	CHK(context(caller, fileType1, context.StandardMessages(),
				LaunchContext::kStandardArgc, LaunchContext::kStandardArgv,
				&team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);

	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckMessageMessages(caller, team, cookie));
//	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	CHK(context.CheckRefsMessage(caller, team, cookie, &fileRef));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	status_t Launch(const entry_ref *ref, const BMessage *initialMessage,
					team_id *app_team) const
	@case 8			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::LaunchTestD8()
{
	FileWithTypeCaller1 caller;
	for (int32 i = 0; i < commonTestFunctionCount; i++) {
		NextSubTest();
		(*commonTestFunctions[i])(caller);
		tearDown();
		setUp();
	}
}

/*
	status_t Launch(const entry_ref *ref, const BMessage *initialMessage,
					team_id *app_team) 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 3-16
					(== common cases 1-14)
*/
void LaunchTester::LaunchTestD9()
{
	SniffFileTypeCaller1 caller;
	for (int32 i = 1; i < commonTestFunctionCount; i++) {
		NextSubTest();
		(*commonTestFunctions[i])(caller);
		tearDown();
		setUp();
	}
}

/*
	status_t Launch(const entry_ref *ref, const BMessage *initialMessage,
					team_id *app_team) const
	@case 10		ref is valid, file has no type, but preferred app, app
					type is not installed, app exists and has signature,
					NULL initialMessage
	@results		Should return B_OK and set team to the ID of the team
					running the application's executable. Should install the
					app type and set the app hint on it.
*/
void LaunchTester::LaunchTestD10()
{
	BRoster roster;
	create_app(appFile1, appType1);
	entry_ref fileRef(create_file(testFile1, NULL, appType1));
	SimpleFileCaller1 caller(fileRef);
	LaunchContext context;
	team_id team;
	CHK(context(caller, fileType1, NULL, LaunchContext::kStandardArgc,
				LaunchContext::kStandardArgv, &team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);

	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
//	CHK(context.CheckMessageMessages(caller, team, cookie));
//	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	status_t Launch(const entry_ref *ref, const BMessage *initialMessage,
					team_id *app_team) const
	@case 11		ref is valid and refers to a cyclic link
	@results		Should return B_LAUNCH_FAILED_NO_RESOLVE_LINK.
*/
void LaunchTester::LaunchTestD11()
{
	BRoster roster;
	system((string("ln -s ") + testLink1 + " " + testLink1).c_str());
	entry_ref linkRef(ref_for_path(testLink1, false));
	BMessage message;
	team_id team;
	CHK(roster.Launch(&linkRef, &message, &team)
		== B_LAUNCH_FAILED_NO_RESOLVE_LINK);
}

/*
	status_t Launch(const entry_ref *ref, const BMessage *initialMessage,
					team_id *app_team) const
	@case 12		ref is valid and refers to a link to void
	@results		Should return B_LAUNCH_FAILED_NO_RESOLVE_LINK.
*/
void LaunchTester::LaunchTestD12()
{
	BRoster roster;
	system((string("ln -s ") + testFile1 + " " + testLink1).c_str());
	entry_ref linkRef(ref_for_path(testLink1, false));
	BMessage message;
	team_id team;
	CHK(roster.Launch(&linkRef, &message, &team)
		== B_LAUNCH_FAILED_NO_RESOLVE_LINK);
}

/*
	status_t Launch(const entry_ref *ref, const BMessage *initialMessage,
					team_id *app_team) const
	@case 13		ref is valid and refers to an executable without signature
	@results		Should return B_OK and set team to the ID of the team
					running the application's executable.
*/
void LaunchTester::LaunchTestD13()
{
	BRoster roster;
	create_app(appFile1, NULL);
	entry_ref fileRef(ref_for_path(appFile1));
	SimpleFileCaller1 caller(fileRef);
	LaunchContext context;
	team_id team;
	CHK(context(caller, appType1, context.StandardMessages(),
				LaunchContext::kStandardArgc, LaunchContext::kStandardArgv,
				&team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	context.WaitForMessage(team, MSG_STARTED, true);
	app_info appInfo;
	CHK(roster.GetRunningAppInfo(team, &appInfo) == B_OK);
	CHK(!strcmp(appInfo.signature, kDefaultTestAppSignature));

	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
//	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckArgsMessage(caller, team, cookie, &ref, NULL,
								 0, NULL, MSG_MAIN_ARGS));
	CHK(context.CheckMessageMessages(caller, team, cookie));
//	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
//	CHK(context.CheckArgsMessage(caller, team, cookie, &ref, NULL,
//								 LaunchContext::kStandardArgc,
//								 LaunchContext::kStandardArgv,
//								 MSG_ARGV_RECEIVED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

// SimpleFileCaller2
class SimpleFileCaller2 : public LaunchCaller {
public:
	SimpleFileCaller2() : fRef() {}
	SimpleFileCaller2(const entry_ref &ref) : fRef(ref) {}
	virtual ~SimpleFileCaller2() {}
	virtual status_t operator()(const char *type, BList *messages, int32 argc,
								const char **argv, team_id *team)
	{
		BRoster roster;
		return roster.Launch(&fRef, messages, team);
	}
	virtual int32 SupportsMessages() const { return 1000; }
	virtual bool SupportsRefs() const { return true; }
	virtual const entry_ref *Ref() const { return &fRef; }

	virtual LaunchCaller *CloneInternal()
	{
		return new SimpleFileCaller2;
	}

protected:
	entry_ref fRef;
};

// FileWithTypeCaller2
class FileWithTypeCaller2 : public SimpleFileCaller2 {
public:
	virtual status_t operator()(const char *type, BList *messages, int32 argc,
								const char **argv, team_id *team)
	{
		BRoster roster;
		fRef = create_file(testFile1, type);
		return roster.Launch(&fRef, messages, team);
	}

	virtual LaunchCaller *CloneInternal()
	{
		return new FileWithTypeCaller2;
	}
};

// SniffFileTypeCaller2
class SniffFileTypeCaller2 : public SimpleFileCaller2 {
public:
	virtual status_t operator()(const char *type, BList *messages, int32 argc,
								const char **argv, team_id *team)
	{
		BRoster roster;
		fRef = create_file(testFile1, type, NULL, NULL, "UnIQe pAtTeRn");
		install_type(fileType1, NULL, "1.0 [0] ('UnIQe pAtTeRn')");
		return roster.Launch(&fRef, messages, team);
	}

	virtual LaunchCaller *CloneInternal()
	{
		return new SniffFileTypeCaller2;
	}
};

/*
	status_t Launch(const entry_ref *ref, const BList *messageList,
					team_id *appTeam) const
	@case 1			ref is NULL
	@results		Should return B_BAD_VALUE.
*/
void LaunchTester::LaunchTestE1()
{
	BRoster roster;
	BList list;
	CHK(roster.Launch((const entry_ref*)NULL, &list, NULL) == B_BAD_VALUE);
}

/*
	status_t Launch(const entry_ref *ref, const BList *messageList,
					team_id *appTeam) const
	@case 2			ref doesn't refer to an existing entry
	@results		Should return B_ENTRY_NOT_FOUND.
*/
void LaunchTester::LaunchTestE2()
{
	BRoster roster;
	BMessage message;
	entry_ref fileRef(ref_for_path(testFile1));
	BList list;
	CHK(roster.Launch(&fileRef, &list, NULL) == B_ENTRY_NOT_FOUND);
}

/*
	status_t Launch(const entry_ref *ref, const BList *messageList,
					team_id *appTeam) const
	@case 3			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 team to the ID of the team
					running 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::LaunchTestE3()
{
	BRoster roster;
	create_app(appFile1, appType1);
	create_app(appFile2, appType2);
	install_type(fileType1, appType1);
	entry_ref fileRef(create_file(testFile1, fileType1, appType2));
	SimpleFileCaller2 caller(fileRef);
	LaunchContext context;
	team_id team;
	CHK(context(caller, fileType1, context.StandardMessages(),
				LaunchContext::kStandardArgc, LaunchContext::kStandardArgv,
				&team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile2) == ref);
	check_app_type(appType2, appFile2);

	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckMessageMessages(caller, team, cookie));
//	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	status_t Launch(const entry_ref *ref, const BList *messageList,
					team_id *appTeam) const
	@case 4			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 team to the ID of the team
					running the application's executable. Should install the
					app type and set the app hint on it.
*/
void LaunchTester::LaunchTestE4()
{
	BRoster roster;
	create_app(appFile1, appType1);
	entry_ref fileRef(create_file(testFile1, NULL, appType1));
	SimpleFileCaller2 caller(fileRef);
	LaunchContext context;
	team_id team;
	CHK(context(caller, fileType1, context.StandardMessages(),
				LaunchContext::kStandardArgc, LaunchContext::kStandardArgv,
				&team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);

	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckMessageMessages(caller, team, cookie));
//	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	status_t Launch(const entry_ref *ref, const BList *messageList,
					team_id *appTeam) const
	@case 5			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 team to the ID of the team
					running the file type's preferred application's executable.
					Should install the app type and set the app hint on it.
*/
void LaunchTester::LaunchTestE5()
{
	BRoster roster;
	create_app(appFile1, appType1);
	create_app(appFile2, appType2);
	install_type(fileType1, appType1);
	entry_ref fileRef(create_file(testFile1, fileType1, NULL, appFile2));
	SimpleFileCaller2 caller(fileRef);
	LaunchContext context;
	team_id team;
	CHK(context(caller, fileType1, context.StandardMessages(),
				LaunchContext::kStandardArgc, LaunchContext::kStandardArgv,
				&team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);

	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckMessageMessages(caller, team, cookie));
//	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	status_t Launch(const entry_ref *ref, const BList *messageList,
					team_id *appTeam) const
	@case 6			ref is valid, file has type, the type's preferred app
					type is not installed, app exists and has signature, file
					has executable permission, but is not executable
	@results		Should return B_LAUNCH_FAILED_EXECUTABLE.
					Should not set the app hint on the app or file type.
*/
void LaunchTester::LaunchTestE6()
{
	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());
	BList list;
	team_id team;
	CHK(roster.Launch(&fileRef, &list, &team) == B_LAUNCH_FAILED_EXECUTABLE);
	CHK(BMimeType(appType1).IsInstalled() == false);
	CHK(BMimeType(fileType1).GetAppHint(&fileRef) == B_ENTRY_NOT_FOUND);
}

/*
	status_t Launch(const entry_ref *ref, const BList *messageList,
					team_id *appTeam) const
	@case 7			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 team to the ID of the team
					running the file type's preferred application's executable.
					Should install the app type and set the app hint on it.
*/
void LaunchTester::LaunchTestE7()
{
	BRoster roster;
	create_app(appFile1, appType1);
	install_type(fileType1, appType1);
	create_file(testFile1, fileType1);
	system((string("ln -s ") + testFile1 + " " + testLink1).c_str());
	entry_ref fileRef(ref_for_path(testFile1, false));
	entry_ref linkRef(ref_for_path(testLink1, false));
	SimpleFileCaller2 caller(linkRef);
	LaunchContext context;
	team_id team;
	CHK(context(caller, fileType1, context.StandardMessages(),
				LaunchContext::kStandardArgc, LaunchContext::kStandardArgv,
				&team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);

	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckMessageMessages(caller, team, cookie));
//	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	CHK(context.CheckRefsMessage(caller, team, cookie, &fileRef));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	status_t Launch(const entry_ref *ref, const BList *messageList,
					team_id *appTeam) const
	@case 8			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::LaunchTestE8()
{
	FileWithTypeCaller2 caller;
	for (int32 i = 0; i < commonTestFunctionCount; i++) {
		NextSubTest();
		(*commonTestFunctions[i])(caller);
		tearDown();
		setUp();
	}
}

/*
	status_t Launch(const entry_ref *ref, const BList *messageList,
					team_id *appTeam) 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 3-16
					(== common cases 1-14)
*/
void LaunchTester::LaunchTestE9()
{
	SniffFileTypeCaller2 caller;
	for (int32 i = 1; i < commonTestFunctionCount; i++) {
		NextSubTest();
		(*commonTestFunctions[i])(caller);
		tearDown();
		setUp();
	}
}

/*
	status_t Launch(const entry_ref *ref, const BList *messageList,
					team_id *appTeam) const
	@case 10		ref is valid, file has no type, but preferred app, app
					type is not installed, app exists and has signature,
					NULL messageList
	@results		Should return B_OK and set team to the ID of the team
					running the application's executable. Should install the
					app type and set the app hint on it.
*/
void LaunchTester::LaunchTestE10()
{
	BRoster roster;
	create_app(appFile1, appType1);
	entry_ref fileRef(create_file(testFile1, NULL, appType1));
	SimpleFileCaller2 caller(fileRef);
	LaunchContext context;
	team_id team;
	CHK(context(caller, fileType1, NULL, LaunchContext::kStandardArgc,
				LaunchContext::kStandardArgv, &team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);

	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
//	CHK(context.CheckMessageMessages(caller, team, cookie));
//	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	status_t Launch(const entry_ref *ref, const BList *messageList,
					team_id *appTeam) const
	@case 11		ref is valid, file has no type, but preferred app, app
					type is not installed, app exists and has signature,
					empty messageList
	@results		Should return B_OK and set team to the ID of the team
					running the application's executable. Should install the
					app type and set the app hint on it.
*/
void LaunchTester::LaunchTestE11()
{
	BRoster roster;
	create_app(appFile1, appType1);
	entry_ref fileRef(create_file(testFile1, NULL, appType1));
	SimpleFileCaller2 caller(fileRef);
	LaunchContext context;
	team_id team;
	BList list;
	CHK(context(caller, fileType1, &list, LaunchContext::kStandardArgc,
				LaunchContext::kStandardArgv, &team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);

	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
//	CHK(context.CheckMessageMessages(caller, team, cookie));
//	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	status_t Launch(const entry_ref *ref, const BList *messageList,
					team_id *appTeam) const
	@case 12		ref is valid and refers to a cyclic link
	@results		Should return B_LAUNCH_FAILED_NO_RESOLVE_LINK.
*/
void LaunchTester::LaunchTestE12()
{
	BRoster roster;
	system((string("ln -s ") + testLink1 + " " + testLink1).c_str());
	entry_ref linkRef(ref_for_path(testLink1, false));
	BMessage message;
	team_id team;
	BList list;
	CHK(roster.Launch(&linkRef, &list, &team)
		== B_LAUNCH_FAILED_NO_RESOLVE_LINK);
}

/*
	status_t Launch(const entry_ref *ref, const BList *messageList,
					team_id *appTeam) const
	@case 13		ref is valid and refers to a link to void
	@results		Should return B_LAUNCH_FAILED_NO_RESOLVE_LINK.
*/
void LaunchTester::LaunchTestE13()
{
	BRoster roster;
	system((string("ln -s ") + testFile1 + " " + testLink1).c_str());
	entry_ref linkRef(ref_for_path(testLink1, false));
	BMessage message;
	team_id team;
	BList list;
	CHK(roster.Launch(&linkRef, &list, &team)
		== B_LAUNCH_FAILED_NO_RESOLVE_LINK);
}

/*
	status_t Launch(const entry_ref *ref, const BList *messageList,
					team_id *appTeam) const
	@case 14		ref is valid and refers to an executable without signature
	@results		Should return B_OK and set team to the ID of the team
					running the application's executable.
*/
void LaunchTester::LaunchTestE14()
{
	BRoster roster;
	create_app(appFile1, NULL);
	entry_ref fileRef(ref_for_path(appFile1));
	SimpleFileCaller2 caller(fileRef);
	LaunchContext context;
	team_id team;
	CHK(context(caller, appType1, context.StandardMessages(),
				LaunchContext::kStandardArgc, LaunchContext::kStandardArgv,
				&team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	context.WaitForMessage(team, MSG_STARTED, true);
	app_info appInfo;
	CHK(roster.GetRunningAppInfo(team, &appInfo) == B_OK);
	CHK(!strcmp(appInfo.signature, kDefaultTestAppSignature));

	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
//	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckArgsMessage(caller, team, cookie, &ref, NULL,
								 0, NULL, MSG_MAIN_ARGS));
	CHK(context.CheckMessageMessages(caller, team, cookie));
//	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
//	CHK(context.CheckArgsMessage(caller, team, cookie, &ref, NULL,
//								 LaunchContext::kStandardArgc,
//								 LaunchContext::kStandardArgv,
//								 MSG_ARGV_RECEIVED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

// SimpleFileCaller3
class SimpleFileCaller3 : public LaunchCaller {
public:
	SimpleFileCaller3() : fRef() {}
	SimpleFileCaller3(const entry_ref &ref) : fRef(ref) {}
	virtual ~SimpleFileCaller3() {}
	virtual status_t operator()(const char *type, BList *messages, int32 argc,
								const char **argv, team_id *team)
	{
		BRoster roster;
		return roster.Launch(&fRef, argc, argv, team);
	}
	virtual int32 SupportsMessages() const { return 0; }
	virtual bool SupportsRefs() const { return true; }
	virtual const entry_ref *Ref() const { return &fRef; }

	virtual LaunchCaller *CloneInternal()
	{
		return new SimpleFileCaller3;
	}

protected:
	entry_ref fRef;
};

// FileWithTypeCaller3
class FileWithTypeCaller3 : public SimpleFileCaller3 {
public:
	virtual status_t operator()(const char *type, BList *messages, int32 argc,
								const char **argv, team_id *team)
	{
		BRoster roster;
		fRef = create_file(testFile1, type);
		return roster.Launch(&fRef, argc, argv, team);
	}

	virtual LaunchCaller *CloneInternal()
	{
		return new FileWithTypeCaller3;
	}
};

// SniffFileTypeCaller3
class SniffFileTypeCaller3 : public SimpleFileCaller3 {
public:
	virtual status_t operator()(const char *type, BList *messages, int32 argc,
								const char **argv, team_id *team)
	{
		BRoster roster;
		fRef = create_file(testFile1, type, NULL, NULL, "UnIQe pAtTeRn");
		install_type(fileType1, NULL, "1.0 [0] ('UnIQe pAtTeRn')");
		return roster.Launch(&fRef, argc, argv, team);
	}

	virtual LaunchCaller *CloneInternal()
	{
		return new SniffFileTypeCaller3;
	}
};

/*
	status_t Launch(const entry_ref *ref, int argc, const char * const *args,
					team_id *appTeam) const
	@case 1			ref is NULL
	@results		Should return B_BAD_VALUE.
*/
void LaunchTester::LaunchTestF1()
{
	BRoster roster;
	char *argv[] = { "Hey!" };
	CHK(roster.Launch((const entry_ref*)NULL, 1, argv, NULL) == B_BAD_VALUE);
}

/*
	status_t Launch(const entry_ref *ref, int argc, const char * const *args,
					team_id *appTeam) const
	@case 2			ref doesn't refer to an existing entry
	@results		Should return B_ENTRY_NOT_FOUND.
*/
void LaunchTester::LaunchTestF2()
{
	BRoster roster;
	BMessage message;
	entry_ref fileRef(ref_for_path(testFile1));
	char *argv[] = { "Hey!" };
	CHK(roster.Launch(&fileRef, 1, argv, NULL) == B_ENTRY_NOT_FOUND);
}

/*
	status_t Launch(const entry_ref *ref, int argc, const char * const *args,
					team_id *appTeam) const
	@case 3			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 team to the ID of the team
					running 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::LaunchTestF3()
{
	BRoster roster;
	create_app(appFile1, appType1);
	create_app(appFile2, appType2);
	install_type(fileType1, appType1);
	entry_ref fileRef(create_file(testFile1, fileType1, appType2));
	SimpleFileCaller3 caller(fileRef);
	LaunchContext context;
	team_id team;
	CHK(context(caller, fileType1, context.StandardMessages(),
				LaunchContext::kStandardArgc, LaunchContext::kStandardArgv,
				&team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile2) == ref);
	check_app_type(appType2, appFile2);

	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
//	CHK(context.CheckMessageMessages(caller, team, cookie));
	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
//	CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	status_t Launch(const entry_ref *ref, int argc, const char * const *args,
					team_id *appTeam) const
	@case 4			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 team to the ID of the team
					running the application's executable. Should install the
					app type and set the app hint on it.
*/
void LaunchTester::LaunchTestF4()
{
	BRoster roster;
	create_app(appFile1, appType1);
	entry_ref fileRef(create_file(testFile1, NULL, appType1));
	SimpleFileCaller3 caller(fileRef);
	LaunchContext context;
	team_id team;
	CHK(context(caller, fileType1, context.StandardMessages(),
				LaunchContext::kStandardArgc, LaunchContext::kStandardArgv,
				&team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);

	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
//	CHK(context.CheckMessageMessages(caller, team, cookie));
	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
//	CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	status_t Launch(const entry_ref *ref, int argc, const char * const *args,
					team_id *appTeam) const
	@case 5			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 team to the ID of the team
					running the file type's preferred application's executable.
					Should install the app type and set the app hint on it.
*/
void LaunchTester::LaunchTestF5()
{
	BRoster roster;
	create_app(appFile1, appType1);
	create_app(appFile2, appType2);
	install_type(fileType1, appType1);
	entry_ref fileRef(create_file(testFile1, fileType1, NULL, appFile2));
	SimpleFileCaller3 caller(fileRef);
	LaunchContext context;
	team_id team;
	CHK(context(caller, fileType1, context.StandardMessages(),
				LaunchContext::kStandardArgc, LaunchContext::kStandardArgv,
				&team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);

	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
//	CHK(context.CheckMessageMessages(caller, team, cookie));
	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
//	CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	status_t Launch(const entry_ref *ref, int argc, const char * const *args,
					team_id *appTeam) const
	@case 6			ref is valid, file has type, the type's preferred app
					type is not installed, app exists and has signature, file
					has executable permission, but is not executable
	@results		Should return B_LAUNCH_FAILED_EXECUTABLE.
					Should not set the app hint on the app or file type.
*/
void LaunchTester::LaunchTestF6()
{
	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());
	team_id team;
	char *argv[] = { "Hey!" };
	CHK(roster.Launch(&fileRef, 1, argv, &team) == B_LAUNCH_FAILED_EXECUTABLE);
	CHK(BMimeType(appType1).IsInstalled() == false);
	CHK(BMimeType(fileType1).GetAppHint(&fileRef) == B_ENTRY_NOT_FOUND);
}

/*
	status_t Launch(const entry_ref *ref, int argc, const char * const *args,
					team_id *appTeam) const
	@case 7			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 team to the ID of the team
					running the file type's preferred application's executable.
					Should install the app type and set the app hint on it.
*/
void LaunchTester::LaunchTestF7()
{
	BRoster roster;
	create_app(appFile1, appType1);
	install_type(fileType1, appType1);
	create_file(testFile1, fileType1);
	system((string("ln -s ") + testFile1 + " " + testLink1).c_str());
	entry_ref fileRef(ref_for_path(testFile1, false));
	entry_ref linkRef(ref_for_path(testLink1, false));
	SimpleFileCaller3 caller(linkRef);
	LaunchContext context;
	team_id team;
	CHK(context(caller, fileType1, context.StandardMessages(),
				LaunchContext::kStandardArgc, LaunchContext::kStandardArgv,
				&team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);

	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
//	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckArgsMessage(caller, team, cookie, &ref, &fileRef,
								 LaunchContext::kStandardArgc,
								 LaunchContext::kStandardArgv, MSG_MAIN_ARGS));
//	CHK(context.CheckMessageMessages(caller, team, cookie));
//	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	CHK(context.CheckArgsMessage(caller, team, cookie, &ref, &fileRef,
								 LaunchContext::kStandardArgc,
								 LaunchContext::kStandardArgv,
								 MSG_ARGV_RECEIVED));
//	CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	status_t Launch(const entry_ref *ref, int argc, const char * const *args,
					team_id *appTeam) const
	@case 8			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::LaunchTestF8()
{
	FileWithTypeCaller3 caller;
	for (int32 i = 0; i < commonTestFunctionCount; i++) {
		NextSubTest();
		(*commonTestFunctions[i])(caller);
		tearDown();
		setUp();
	}
}

/*
	status_t Launch(const entry_ref *ref, int argc, const char * const *args,
					team_id *appTeam) 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 3-16
					(== common cases 1-14)
*/
void LaunchTester::LaunchTestF9()
{
	SniffFileTypeCaller3 caller;
	for (int32 i = 1; i < commonTestFunctionCount; i++) {
		NextSubTest();
		(*commonTestFunctions[i])(caller);
		tearDown();
		setUp();
	}
}

/*
	status_t Launch(const entry_ref *ref, int argc, const char * const *args,
					team_id *appTeam) const
	@case 10		ref is valid, file has no type, but preferred app, app
					type is not installed, app exists and has signature,
					NULL args, argc is 0
	@results		Should return B_OK and set team to the ID of the team
					running the application's executable. Should install the
					app type and set the app hint on it. argv are ignored.
*/
void LaunchTester::LaunchTestF10()
{
	BRoster roster;
	create_app(appFile1, appType1);
	entry_ref fileRef(create_file(testFile1, NULL, appType1));
	SimpleFileCaller3 caller(fileRef);
	LaunchContext context;
	team_id team;
	CHK(context(caller, fileType1, NULL, 0, NULL, &team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);

	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref, 0, NULL));
//	CHK(context.CheckMessageMessages(caller, team, cookie));
//	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	status_t Launch(const entry_ref *ref, int argc, const char * const *args,
					team_id *appTeam) const
	@case 11		ref is valid, file has no type, but preferred app, app
					type is not installed, app exists and has signature,
					NULL args, argc > 0
	@results		Should return B_OK and set team to the ID of the team
					running the application's executable. Should install the
					app type and set the app hint on it. argv are ignored.
*/
void LaunchTester::LaunchTestF11()
{
	BRoster roster;
	create_app(appFile1, appType1);
	entry_ref fileRef(create_file(testFile1, NULL, appType1));
	SimpleFileCaller3 caller(fileRef);
	LaunchContext context;
	team_id team;
	CHK(context(caller, fileType1, NULL, 1, NULL, &team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	check_app_type(appType1, appFile1);

	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref, 0, NULL));
//	CHK(context.CheckMessageMessages(caller, team, cookie));
//	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	CHK(context.CheckRefsMessage(caller, team, cookie));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}

/*
	status_t Launch(const entry_ref *ref, int argc, const char * const *args,
					team_id *appTeam) const
	@case 12		ref is valid and refers to a cyclic link
	@results		Should return B_LAUNCH_FAILED_NO_RESOLVE_LINK.
*/
void LaunchTester::LaunchTestF12()
{
	BRoster roster;
	system((string("ln -s ") + testLink1 + " " + testLink1).c_str());
	entry_ref linkRef(ref_for_path(testLink1, false));
	BMessage message;
	team_id team;
	CHK(roster.Launch(&linkRef, LaunchContext::kStandardArgc,
					  LaunchContext::kStandardArgv, &team)
		== B_LAUNCH_FAILED_NO_RESOLVE_LINK);
}

/*
	status_t Launch(const entry_ref *ref, int argc, const char * const *args,
					team_id *appTeam) const
	@case 13		ref is valid and refers to a link to void
	@results		Should return B_LAUNCH_FAILED_NO_RESOLVE_LINK.
*/
void LaunchTester::LaunchTestF13()
{
	BRoster roster;
	system((string("ln -s ") + testFile1 + " " + testLink1).c_str());
	entry_ref linkRef(ref_for_path(testLink1, false));
	BMessage message;
	team_id team;
	CHK(roster.Launch(&linkRef, LaunchContext::kStandardArgc,
					  LaunchContext::kStandardArgv, &team)
		== B_LAUNCH_FAILED_NO_RESOLVE_LINK);
}

/*
	status_t Launch(const entry_ref *ref, int argc, const char * const *args,
					team_id *appTeam) const
	@case 14		ref is valid and refers to an executable without signature
	@results		Should return B_OK and set team to the ID of the team
					running the application's executable.
*/
void LaunchTester::LaunchTestF14()
{
	BRoster roster;
	create_app(appFile1, NULL);
	entry_ref fileRef(ref_for_path(appFile1));
	SimpleFileCaller3 caller(fileRef);
	LaunchContext context;
	team_id team;
	CHK(context(caller, appType1, context.StandardMessages(),
				LaunchContext::kStandardArgc, LaunchContext::kStandardArgv,
				&team) == B_OK);
	entry_ref ref = ref_for_team(team);
	CHK(ref_for_path(appFile1) == ref);
	context.WaitForMessage(team, MSG_STARTED, true);
	app_info appInfo;
	CHK(roster.GetRunningAppInfo(team, &appInfo) == B_OK);
	CHK(!strcmp(appInfo.signature, kDefaultTestAppSignature));

	context.Terminate();
	int32 cookie = 0;
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_STARTED));
//	CHK(context.CheckMainArgsMessage(caller, team, cookie, &ref));
	CHK(context.CheckArgsMessage(caller, team, cookie, &ref, NULL,
								 LaunchContext::kStandardArgc,
								 LaunchContext::kStandardArgv,
								 MSG_MAIN_ARGS));
//	CHK(context.CheckMessageMessages(caller, team, cookie));
//	CHK(context.CheckArgvMessage(caller, team, cookie, &ref));
	CHK(context.CheckArgsMessage(caller, team, cookie, &ref, NULL,
								 LaunchContext::kStandardArgc,
								 LaunchContext::kStandardArgv,
								 MSG_ARGV_RECEIVED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_READY_TO_RUN));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_QUIT_REQUESTED));
	CHK(context.CheckNextMessage(caller, team, cookie, MSG_TERMINATED));
}


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, LaunchTestA4);

	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, LaunchTestC1);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestC2);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestC3);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestC4);

	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestD1);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestD2);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestD3);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestD4);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestD5);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestD6);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestD7);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestD8);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestD9);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestD10);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestD11);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestD12);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestD13);

	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestE1);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestE2);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestE3);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestE4);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestE5);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestE6);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestE7);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestE8);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestE9);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestE10);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestE11);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestE12);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestE13);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestE14);

	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestF1);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestF2);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestF3);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestF4);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestF5);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestF6);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestF7);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestF8);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestF9);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestF10);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestF11);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestF12);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestF13);
	ADD_TEST4(BRoster, SuiteOfTests, LaunchTester, LaunchTestF14);

	return SuiteOfTests;
}

