Changeset - 819c52172d94
CMakeLists.txt
Show inline comments
 
@@ -110,6 +110,7 @@ ADD_SUBDIRECTORY(include)
 
ADD_SUBDIRECTORY(examples)
 
ADD_SUBDIRECTORY(spectrum)
 
ADD_SUBDIRECTORY(backends)
 
ADD_SUBDIRECTORY(tests)
 

	
 
if(DOXYGEN_FOUND)
 
	message("Docs              : yes")
backends/libircclient-qt/session.cpp
Show inline comments
 
@@ -17,6 +17,7 @@ MyIrcSession::MyIrcSession(const std::string &user, NetworkPlugin *np, QObject*
 
{
 
	this->np = np;
 
	this->user = user;
 
	connect(this, SIGNAL(disconnected()), SLOT(on_disconnected()));
 
}
 

	
 
void MyIrcSession::on_connected(){
 
@@ -26,6 +27,7 @@ void MyIrcSession::on_connected(){
 
void MyIrcSession::on_disconnected()
 
{
 
    std::cout << "disconnected:\n";
 
    np->handleDisconnected(user, "", 0, "");
 
}
 

	
 
void MyIrcSession::on_bufferAdded(Irc::Buffer* buffer)
backends/libpurple/main.cpp
Show inline comments
 
@@ -118,7 +118,7 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 
			}
 
		}
 

	
 
		virtual void handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id) {
 
		void handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				serv_get_info(purple_account_get_connection(account), legacyName.c_str());
 
@@ -126,6 +126,18 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 
			}
 
		}
 

	
 
		void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::string &groups) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				PurpleBuddy *buddy = purple_find_buddy(account, buddyName.c_str());
 
				if (buddy) {
 
					purple_blist_alias_buddy(buddy, alias.c_str());
 
					purple_blist_server_alias_buddy(buddy, alias.c_str());
 
					serv_alias_buddy(buddy);
 
				}
 
			}
 
		}
 

	
 
		std::map<std::string, PurpleAccount *> m_sessions;
 
		std::map<PurpleAccount *, std::string> m_accounts;
 
		std::map<std::string, unsigned int> m_vcards;
 
@@ -479,6 +491,9 @@ static PurpleCoreUiOps coreUiOps =
 
};
 

	
 
static void signed_on(PurpleConnection *gc, gpointer unused) {
 
	for (int i = 0; i<1500; i++) {
 
		std::cout << "A\n";
 
	}
 
	PurpleAccount *account = purple_connection_get_account(gc);
 
	np->handleConnected(np->m_accounts[account]);
 
}
include/transport/networkplugin.h
Show inline comments
 
@@ -64,6 +64,7 @@ class NetworkPlugin {
 
		virtual void handleVCardRequest(const std::string &/*user*/, const std::string &/*legacyName*/, unsigned int /*id*/) {}
 
		virtual void handleJoinRoomRequest(const std::string &/*user*/, const std::string &/*room*/, const std::string &/*nickname*/, const std::string &/*pasword*/) {}
 
		virtual void handleLeaveRoomRequest(const std::string &/*user*/, const std::string &/*room*/) {}
 
		virtual void handleBuddyUpdatedRequest(const std::string &/*user*/, const std::string &/*buddyName*/, const std::string &/*alias*/, const std::string &/*groups*/) {}
 
		
 

	
 
	private:
 
@@ -74,6 +75,7 @@ class NetworkPlugin {
 
		void handleJoinRoomPayload(const std::string &payload);
 
		void handleLeaveRoomPayload(const std::string &payload);
 
		void handleVCardPayload(const std::string &payload);
 
		void handleBuddyChangedPayload(const std::string &payload);
 
		void handleDataRead(const Swift::SafeByteArray&);
 
		void _handleConnected(bool error);
 
		void handleDisconnected();
include/transport/networkpluginserver.h
Show inline comments
 
@@ -74,6 +74,10 @@ class NetworkPluginServer {
 
		void handleUserReadyToConnect(User *user);
 
		void handleUserDestroyed(User *user);
 

	
 
		void handleBuddyUpdated(Buddy *buddy, const Swift::RosterItemPayload &item);
 
		void handleBuddyRemoved(Buddy *buddy);
 
		void handleBuddyAdded(Buddy *buddy, const Swift::RosterItemPayload &item);
 

	
 
		void handleVCardRequired(User *user, const std::string &name, unsigned int id);
 

	
 
		void send(boost::shared_ptr<Swift::Connection> &, const std::string &data);
include/transport/rostermanager.h
Show inline comments
 
@@ -60,6 +60,8 @@ class RosterManager {
 

	
 
		void setStorageBackend(StorageBackend *storageBackend);
 

	
 
		void storeBuddy(Buddy *buddy);
 

	
 
		Swift::RosterPayload::ref generateRosterPayload();
 

	
 
		/// Returns user associated with this roster.
include/transport/rosterresponder.h
Show inline comments
 
@@ -28,12 +28,19 @@
 
namespace Transport {
 

	
 
class UserManager;
 
class Buddy;
 

	
 
class RosterResponder : public Swift::Responder<Swift::RosterPayload> {
 
	public:
 
		RosterResponder(Swift::IQRouter *router, UserManager *userManager);
 
		~RosterResponder();
 

	
 
		boost::signal<void (Buddy *, const Swift::RosterItemPayload &item)> onBuddyUpdated;
 

	
 
		boost::signal<void (Buddy *)> onBuddyRemoved;
 

	
 
		boost::signal<void (Buddy *, const Swift::RosterItemPayload &item)> onBuddyAdded;
 

	
 
	private:
 
		virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::RosterPayload> payload);
 
		virtual bool handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::RosterPayload> payload);
include/transport/transport.h
Show inline comments
 
@@ -31,6 +31,7 @@
 
#include "Swiften/Network/BoostTimerFactory.h"
 
#include "Swiften/Network/BoostIOServiceThread.h"
 
#include "Swiften/Server/UserRegistry.h"
 
#include "Swiften/Base/SafeByteArray.h"
 
#include <boost/bind.hpp>
 
#include "transport/config.h"
 
#include "transport/factory.h"
src/localbuddy.cpp
Show inline comments
 
@@ -24,6 +24,7 @@
 
namespace Transport {
 

	
 
LocalBuddy::LocalBuddy(RosterManager *rosterManager, long id) : Buddy(rosterManager, id) {
 
	m_status = Swift::StatusShow::None;
 
}
 

	
 
LocalBuddy::~LocalBuddy() {
src/networkplugin.cpp
Show inline comments
 
@@ -265,8 +265,18 @@ void NetworkPlugin::handleVCardPayload(const std::string &data) {
 
	handleVCardRequest(payload.username(), payload.buddyname(), payload.id());
 
}
 

	
 
void NetworkPlugin::handleBuddyChangedPayload(const std::string &data) {
 
	pbnetwork::Buddy payload;
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 

	
 
	handleBuddyUpdatedRequest(payload.username(), payload.buddyname(), payload.alias(), payload.groups());
 
}
 

	
 
void NetworkPlugin::handleDataRead(const Swift::SafeByteArray &data) {
 
	m_data.insert(m_data.begin(), data.begin(), data.end());
 
	m_data.insert(m_data.end(), data.begin(), data.end());
 

	
 
	while (m_data.size() != 0) {
 
		unsigned int expected_size;
 
@@ -310,6 +320,9 @@ void NetworkPlugin::handleDataRead(const Swift::SafeByteArray &data) {
 
			case pbnetwork::WrapperMessage_Type_TYPE_VCARD:
 
				handleVCardPayload(wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_BUDDY_CHANGED:
 
				handleBuddyChangedPayload(wrapper.payload());
 
				break;
 
			default:
 
				return;
 
		}
src/networkpluginserver.cpp
Show inline comments
 
@@ -90,7 +90,7 @@ static int exec_(const char *path, const char *host, const char *port, const cha
 
	if ( pid == 0 ) {
 
		// child process
 
		execlp(path, path, "--host", host, "--port", port, config, NULL);
 
		exit(1);
 
		abort();
 
	} else if ( pid < 0 ) {
 
		// fork failed
 
		status = -1;
 
@@ -128,6 +128,9 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U
 
	m_vcardResponder->start();
 

	
 
	m_rosterResponder = new RosterResponder(component->getIQRouter(), userManager);
 
	m_rosterResponder->onBuddyAdded.connect(boost::bind(&NetworkPluginServer::handleBuddyAdded, this, _1, _2));
 
	m_rosterResponder->onBuddyRemoved.connect(boost::bind(&NetworkPluginServer::handleBuddyRemoved, this, _1));
 
	m_rosterResponder->onBuddyUpdated.connect(boost::bind(&NetworkPluginServer::handleBuddyUpdated, this, _1, _2));
 
	m_rosterResponder->start();
 

	
 
	m_server = component->getNetworkFactories()->getConnectionFactory()->createConnectionServer(10000);
 
@@ -195,12 +198,12 @@ void NetworkPluginServer::handleDisconnectedPayload(const std::string &data) {
 
		return;
 
	}
 

	
 
	m_component->m_userRegistry->onPasswordInvalid(payload.user());
 

	
 
	User *user = m_userManager->getUser(payload.user());
 
	if (!user) {
 
		return;
 
	}
 

	
 
	m_component->m_userRegistry->onPasswordInvalid(payload.user());
 
	user->handleDisconnected(payload.message());
 
}
 

	
 
@@ -322,8 +325,7 @@ void NetworkPluginServer::handleConvMessagePayload(const std::string &data, bool
 
}
 

	
 
void NetworkPluginServer::handleDataRead(Client *c, const Swift::SafeByteArray &data) {
 
	c->data.insert(c->data.begin(), data.begin(), data.end());
 

	
 
	c->data.insert(c->data.end(), data.begin(), data.end());
 
	while (c->data.size() != 0) {
 
		unsigned int expected_size;
 

	
 
@@ -339,8 +341,9 @@ void NetworkPluginServer::handleDataRead(Client *c, const Swift::SafeByteArray &
 

	
 
		pbnetwork::WrapperMessage wrapper;
 
		if (wrapper.ParseFromArray(&c->data[4], expected_size) == false) {
 
			std::cout << "PARSING ERROR " << expected_size << "\n";
 
			c->data.erase(c->data.begin(), c->data.begin() + 4 + expected_size);
 
			return;
 
			continue;
 
		}
 
		c->data.erase(c->data.begin(), c->data.begin() + 4 + expected_size);
 

	
 
@@ -399,6 +402,10 @@ void NetworkPluginServer::pingTimeout() {
 

	
 
void NetworkPluginServer::handleUserCreated(User *user) {
 
	Client *c = getFreeClient();
 
	if (!c) {
 
		user->handleDisconnected("Internal Server Error, please reconnect.");
 
		return;
 
	}
 
	user->setData(c);
 
	c->users.push_back(user);
 

	
 
@@ -513,6 +520,36 @@ void NetworkPluginServer::handleMessageReceived(NetworkConversation *conv, boost
 
	send(c->connection, message);
 
}
 

	
 
void NetworkPluginServer::handleBuddyRemoved(Buddy *buddy) {
 
	
 
}
 

	
 
void NetworkPluginServer::handleBuddyUpdated(Buddy *b, const Swift::RosterItemPayload &item) {
 
	User *user = b->getRosterManager()->getUser();
 

	
 
	dynamic_cast<LocalBuddy *>(b)->setAlias(item.getName());
 
	user->getRosterManager()->storeBuddy(b);
 

	
 
	pbnetwork::Buddy buddy;
 
	buddy.set_username(user->getJID().toBare());
 
	buddy.set_buddyname(b->getName());
 
	buddy.set_alias(b->getAlias());
 
	buddy.set_groups(b->getGroups().size() == 0 ? "" : b->getGroups()[0]);
 
	buddy.set_status(Swift::StatusShow::None);
 

	
 
	std::string message;
 
	buddy.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_BUDDY_CHANGED);
 

	
 
	Client *c = (Client *) user->getData();
 
	send(c->connection, message);
 
}
 

	
 
void NetworkPluginServer::handleBuddyAdded(Buddy *buddy, const Swift::RosterItemPayload &item) {
 
	handleBuddyUpdated(buddy, item);
 
}
 

	
 
void NetworkPluginServer::handleVCardRequired(User *user, const std::string &name, unsigned int id) {
 
	std::cout << "VCARD REQUIRED " << name << " " << id << "\n";
 
	pbnetwork::VCard vcard;
src/rostermanager.cpp
Show inline comments
 
@@ -119,6 +119,12 @@ void RosterManager::unsetBuddy(Buddy *buddy) {
 
	onBuddyUnset(buddy);
 
}
 

	
 
void RosterManager::storeBuddy(Buddy *buddy) {
 
	if (m_rosterStorage) {
 
		m_rosterStorage->storeBuddy(buddy);
 
	}
 
}
 

	
 
void RosterManager::handleBuddyRosterPushResponse(Swift::ErrorPayload::ref error, const std::string &key) {
 
	if (m_buddies[key] != NULL) {
 
		m_buddies[key]->handleBuddyChanged();
src/rosterresponder.cpp
Show inline comments
 
@@ -27,6 +27,7 @@
 
#include "transport/user.h"
 
#include "transport/usermanager.h"
 
#include "transport/rostermanager.h"
 
#include "transport/buddy.h"
 

	
 
using namespace Swift;
 
using namespace boost;
 
@@ -67,6 +68,41 @@ bool RosterResponder::handleGetRequest(const Swift::JID& from, const Swift::JID&
 

	
 
bool RosterResponder::handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::RosterPayload> payload) {
 
	sendResponse(from, id, boost::shared_ptr<RosterPayload>(new RosterPayload()));
 

	
 
	User *user = m_userManager->getUser(from.toBare().toString());
 
	if (!user) {
 
		return true;
 
	}
 

	
 
	if (payload->getItems().size() == 0) {
 
		return true;
 
	}
 

	
 
	Swift::RosterItemPayload item = payload->getItems()[0];
 

	
 
	Buddy *buddy = user->getRosterManager()->getBuddy(Buddy::JIDToLegacyName(item.getJID()));
 
	if (buddy) {
 
		if (item.getSubscription() == Swift::RosterItemPayload::Remove) {
 
			onBuddyRemoved(buddy);
 
		}
 
		else {
 
			onBuddyUpdated(buddy, item);
 
		}
 
	}
 
	else if (item.getSubscription() != Swift::RosterItemPayload::Remove) {
 
		// Roster push for this new buddy is sent by RosterManager
 
		BuddyInfo buddyInfo;
 
		buddyInfo.id = -1;
 
		buddyInfo.alias = item.getName();
 
		buddyInfo.legacyName = Buddy::JIDToLegacyName(item.getJID());
 
		buddyInfo.subscription = "both";
 
		buddyInfo.flags = 0;
 

	
 
		buddy = user->getComponent()->getFactory()->createBuddy(user->getRosterManager(), buddyInfo);
 
		user->getRosterManager()->setBuddy(buddy);
 
		onBuddyAdded(buddy, item);
 
	}
 

	
 
	return true;
 
}
 

	
src/sqlite3backend.cpp
Show inline comments
 
@@ -240,7 +240,7 @@ long SQLite3Backend::addBuddy(long userId, const BuddyInfo &buddyInfo) {
 
	BIND_INT(m_addBuddy, userId);
 
	BIND_STR(m_addBuddy, buddyInfo.legacyName);
 
	BIND_STR(m_addBuddy, buddyInfo.subscription);
 
	BIND_STR(m_addBuddy, buddyInfo.groups[0]); // TODO: serialize groups
 
	BIND_STR(m_addBuddy, buddyInfo.groups.size() == 0 ? "" : buddyInfo.groups[0]); // TODO: serialize groups
 
	BIND_STR(m_addBuddy, buddyInfo.alias);
 
	BIND_INT(m_addBuddy, buddyInfo.flags);
 

	
tests/CMakeLists.txt
Show inline comments
 
new file 100644
 
ADD_SUBDIRECTORY(login)
 
ADD_SUBDIRECTORY(login_bad_name)
 
ADD_SUBDIRECTORY(login_bad_name2)
 

	
 
add_custom_target(tests python runtests.py WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
tests/login/CMakeLists.txt
Show inline comments
 
new file 100644
 
FILE(GLOB SRC *.cpp)
 
 
ADD_EXECUTABLE(login_test ${SRC})
 
 
TARGET_LINK_LIBRARIES(login_test transport ${SWIFTEN_LIBRARIES} -lgconf-2 -lgobject-2.0 -lglib-2.0)
 
tests/login/main.cpp
Show inline comments
 
new file 100644
 
#include <iostream>
 
#include <boost/bind.hpp>
 

	
 
#include <Swiften/Swiften.h>
 
#include <Swiften/Client/ClientOptions.h>
 

	
 
using namespace Swift;
 
using namespace boost;
 

	
 
Client* client;
 

	
 
static void handleDisconnected(const boost::optional<ClientError> &) {
 
	exit(1);
 
}
 

	
 
static void handleConnected() {
 
	exit(0);
 
}
 

	
 
static void handleMessageReceived(Message::ref message) {
 
	// Echo back the incoming message
 
	message->setTo(message->getFrom());
 
	message->setFrom(JID());
 
	client->sendMessage(message);
 
}
 

	
 
int main(int, char **argv) {
 
	SimpleEventLoop eventLoop;
 
	BoostNetworkFactories networkFactories(&eventLoop);
 

	
 
	client = new Client(argv[1], argv[2], &networkFactories);
 
	client->setAlwaysTrustCertificates();
 
	client->onConnected.connect(&handleConnected);
 
	client->onDisconnected.connect(bind(&handleDisconnected, _1));
 
	client->onMessageReceived.connect(bind(&handleMessageReceived, _1));
 
	ClientOptions opt;
 
	opt.allowPLAINOverNonTLS = true;
 
	client->connect(opt);
 

	
 
	eventLoop.run();
 

	
 
	delete client;
 
	return 0;
 
}
tests/login_bad_name/CMakeLists.txt
Show inline comments
 
new file 100644
 
FILE(GLOB SRC *.cpp)
 
 
ADD_EXECUTABLE(login_bad_name_test ${SRC})
 
 
TARGET_LINK_LIBRARIES(login_bad_name_test transport ${SWIFTEN_LIBRARIES} -lgconf-2 -lgobject-2.0 -lglib-2.0)
 
tests/login_bad_name/main.cpp
Show inline comments
 
new file 100644
 
#include <iostream>
 
#include <boost/bind.hpp>
 

	
 
#include <Swiften/Swiften.h>
 
#include <Swiften/Client/ClientOptions.h>
 

	
 
using namespace Swift;
 
using namespace boost;
 

	
 
Client* client;
 

	
 
static void handleDisconnected(const boost::optional<ClientError> &error) {
 
	exit(error->getType() != ClientError::AuthenticationFailedError);
 
}
 

	
 
static void handleConnected() {
 
	exit(1);
 
}
 

	
 
static void handleMessageReceived(Message::ref message) {
 
	// Echo back the incoming message
 
	message->setTo(message->getFrom());
 
	message->setFrom(JID());
 
	client->sendMessage(message);
 
}
 

	
 
int main(int, char **argv) {
 
	SimpleEventLoop eventLoop;
 
	BoostNetworkFactories networkFactories(&eventLoop);
 

	
 
	JID jid(JID(argv[1]).getNode() + "something", JID(argv[1]).getDomain());
 
	client = new Client(jid, argv[2], &networkFactories);
 
	client->setAlwaysTrustCertificates();
 
	client->onConnected.connect(&handleConnected);
 
	client->onDisconnected.connect(bind(&handleDisconnected, _1));
 
	client->onMessageReceived.connect(bind(&handleMessageReceived, _1));
 
	ClientOptions opt;
 
	opt.allowPLAINOverNonTLS = true;
 
	client->connect(opt);
 

	
 
	eventLoop.run();
 

	
 
	delete client;
 
	return 0;
 
}
tests/login_bad_name2/.nolibircclient-qt
Show inline comments
 
new file 100644
tests/login_bad_name2/CMakeLists.txt
Show inline comments
 
new file 100644
 
FILE(GLOB SRC *.cpp)
 
 
ADD_EXECUTABLE(login_bad_name2_test ${SRC})
 
 
TARGET_LINK_LIBRARIES(login_bad_name2_test transport ${SWIFTEN_LIBRARIES} -lgconf-2 -lgobject-2.0 -lglib-2.0)
 
tests/login_bad_name2/main.cpp
Show inline comments
 
new file 100644
 
#include <iostream>
 
#include <boost/bind.hpp>
 

	
 
#include <Swiften/Swiften.h>
 
#include <Swiften/Client/ClientOptions.h>
 

	
 
using namespace Swift;
 
using namespace boost;
 

	
 
Client* client;
 

	
 
static void handleDisconnected(const boost::optional<ClientError> &error) {
 
	exit(error->getType() != ClientError::AuthenticationFailedError);
 
}
 

	
 
static void handleConnected() {
 
	exit(1);
 
}
 

	
 
static void handleMessageReceived(Message::ref message) {
 
	// Echo back the incoming message
 
	message->setTo(message->getFrom());
 
	message->setFrom(JID());
 
	client->sendMessage(message);
 
}
 

	
 
int main(int, char **argv) {
 
	SimpleEventLoop eventLoop;
 
	BoostNetworkFactories networkFactories(&eventLoop);
 

	
 
	JID jid(std::string("something") + JID(argv[1]).getNode(), JID(argv[1]).getDomain());
 
	client = new Client(jid, argv[2], &networkFactories);
 
	client->setAlwaysTrustCertificates();
 
	client->onConnected.connect(&handleConnected);
 
	client->onDisconnected.connect(bind(&handleDisconnected, _1));
 
	client->onMessageReceived.connect(bind(&handleMessageReceived, _1));
 
	ClientOptions opt;
 
	opt.allowPLAINOverNonTLS = true;
 
	client->connect(opt);
 

	
 
	eventLoop.run();
 

	
 
	delete client;
 
	return 0;
 
}
tests/runtests.py
Show inline comments
 
new file 100644
 
import os
 
import sys
 
from subprocess import *
 
import time
 

	
 
def run_spectrum(backend, test):
 
	os.system("rm test.sql")
 
	f = open("sample.cfg", "w")
 
	f.write("\
 
	[service]\n\
 
	jid = localhost\n\
 
	password = secret\n\
 
	server = 127.0.0.1\n\
 
	port = 5222\n\
 
	server_mode = 1\n\
 
	backend=../backends/%s/%s_backend\n\
 
	protocol=prpl-jabber\n\
 
\
 
	[database]\n\
 
	database = test.sql\n\
 
	prefix=icq\n\
 
	" % (backend, backend)
 
	)
 
	f.close()
 
	p = Popen("../spectrum/src/spectrum sample.cfg > " + backend + "_" + test + ".log 2>&1", shell=True)
 
	time.sleep(4)
 
	return p
 

	
 
def one_test_run():
 
	os.system("killall spectrum 2> /dev/null")
 
	os.system("rm *.log")
 

	
 
	for backend in os.listdir("../backends"):
 
		if not os.path.isdir("../backends/" + backend) or backend == "CMakeFiles":
 
			continue
 

	
 
		for d in os.listdir("."):
 
			binary = d + "/" + d + "_test"
 
			if not os.path.exists(binary):
 
				continue
 

	
 
			if os.path.exists(d + "/.no" + backend):
 
				continue
 

	
 
			p = run_spectrum(backend, d)
 

	
 
			if backend.find("purple") >= 0:
 
				p = Popen(binary + " pyjim%jabber.cz@localhost test", shell=True)
 
			else:
 
				p = Popen(binary + " testnickname%irc.freenode.net@localhost test", shell=True)
 

	
 
			seconds = 0
 
			while p.poll() is None and seconds < 20:
 
				time.sleep(1)
 
				seconds += 1
 

	
 
			if p.returncode == 0 and seconds < 20:
 
				print "[ PASS ]", backend, binary
 
				
 
			else:
 
				if seconds == 20:
 
					print "[ TIME ]", backend, binary
 
				else:
 
					print "[ FAIL ]", backend, binary
 

	
 
			os.system("killall spectrum 2> /dev/null")
 

	
 
one_test_run()
 

	
 

	
0 comments (0 inline, 0 general)