From 5698df1c136ebfbf943139b27732bf271e007875 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Thu, 24 Feb 2011 22:50:17 +0100
Subject: Added Sluift client test script and the necessary infrastructure.


diff --git a/3rdParty/Lua/SConscript b/3rdParty/Lua/SConscript
index 9d0315e..f69c3cd 100644
--- a/3rdParty/Lua/SConscript
+++ b/3rdParty/Lua/SConscript
@@ -8,12 +8,14 @@ if env.get("LUA_BUNDLED", False) :
 
 	if env["SCONS_STAGE"] == "flags" :
 		cppdefines = []
+		if not env["optimize"] :
+			cppdefines.append("LUA_USE_APICHECK")
 		if env["PLATFORM"] == "win32" :
 			pass
 		elif env["PLATFORM"] == "darwin" :
-			cppdefines = ["LUA_USE_POSIX", "LUA_USE_DLOPEN"]
+			cppdefines += ["LUA_USE_POSIX", "LUA_USE_DLOPEN"]
 		else :
-			cppdefines = ["LUA_USE_POSIX", "LUA_USE_DLOPEN"]
+			cppdefines += ["LUA_USE_POSIX", "LUA_USE_DLOPEN"]
 
 		env["LUA_FLAGS"] = {
 				"CPPDEFINES": cppdefines,
diff --git a/Sluift/client_test.lua b/Sluift/client_test.lua
new file mode 100644
index 0000000..afb8147
--- /dev/null
+++ b/Sluift/client_test.lua
@@ -0,0 +1,32 @@
+require "sluift"
+
+--sluift.debug = true
+client1_jid = os.getenv("SWIFT_CLIENTTEST_JID") .. "/Client1"
+client2_jid = os.getenv("SWIFT_CLIENTTEST_JID") .. "/Client2"
+password = os.getenv("SWIFT_CLIENTTEST_PASS")
+
+print "Connecting client 1"
+client1 = sluift.connect(client1_jid, password)
+client1:send_presence("I'm here")
+
+print "Connecting client 2"
+client2 = sluift.connect(client2_jid, password)
+client2:send_presence("I'm here")
+
+print "Checking version of client 2 from client 1"
+client2:set_version({name = "Sluift Test", version = "1.0"})
+client2_version = client1:get_version(client2_jid)
+assert(client2_version["name"] == "Sluift Test")
+assert(client2_version["version"] == "1.0")
+
+print "Sending message from client 1 to client 2"
+client1:send_message(client2_jid, "Hello")
+received_message = client2:for_event(function(event) 
+		if event["type"] == "message" and event["from"] == client1_jid then
+			return event["body"]
+		end
+	end)
+assert(received_message == "Hello")
+
+client1:disconnect()
+client2:disconnect()
diff --git a/Sluift/linit.c b/Sluift/linit.c
deleted file mode 100644
index 4cb4c26..0000000
--- a/Sluift/linit.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $
-** Initialization of libraries for lua.c
-** See Copyright Notice in lua.h
-*/
-
-
-#define linit_c
-#define LUA_LIB
-
-#include "lua.h"
-
-#include "lualib.h"
-#include "lauxlib.h"
-#include "sluift.h"
-
-
-static const luaL_Reg lualibs[] = {
-  {"", luaopen_base},
-  {LUA_LOADLIBNAME, luaopen_package},
-  {LUA_TABLIBNAME, luaopen_table},
-  {LUA_IOLIBNAME, luaopen_io},
-  {LUA_OSLIBNAME, luaopen_os},
-  {LUA_STRLIBNAME, luaopen_string},
-  {LUA_MATHLIBNAME, luaopen_math},
-  {LUA_DBLIBNAME, luaopen_debug},
-	{"sluift", luaopen_sluift},
-  {NULL, NULL}
-};
-
-
-LUALIB_API void luaL_openlibs (lua_State *L) {
-  const luaL_Reg *lib = lualibs;
-  for (; lib->func; lib++) {
-    lua_pushcfunction(L, lib->func);
-    lua_pushstring(L, lib->name);
-    lua_call(L, 1, 0);
-  }
-}
-
diff --git a/Sluift/sluift.cpp b/Sluift/sluift.cpp
index 5a9fbd5..895d90d 100644
--- a/Sluift/sluift.cpp
+++ b/Sluift/sluift.cpp
@@ -11,6 +11,7 @@ extern "C" {
 
 #include <iostream>
 #include <string>
+#include <deque>
 
 #include <Swiften/Client/Client.h>
 #include <Swiften/Client/ClientXMLTracer.h>
@@ -51,6 +52,8 @@ class SluiftClient {
 		SluiftClient(const JID& jid, const std::string& password, bool debug = false) : tracer(NULL) {
 			client = new Client(jid, password, &networkFactories);
 			client->setAlwaysTrustCertificates();
+			client->onMessageReceived.connect(boost::bind(&SluiftClient::handleIncomingEvent, this, _1));
+			client->onPresenceReceived.connect(boost::bind(&SluiftClient::handleIncomingEvent, this, _1));
 			if (debug) {
 				tracer = new ClientXMLTracer(client);
 			}
@@ -79,6 +82,10 @@ class SluiftClient {
 			client->sendMessage(message);
 		}
 
+		void sendPresence(const std::string& status) {
+			client->sendPresence(boost::make_shared<Presence>(status));
+		}
+
 		void disconnect() {
 			client->disconnect();
 			while (client->isActive()) {
@@ -86,6 +93,10 @@ class SluiftClient {
 			}
 		}
 
+		void setSoftwareVersion(const std::string& name, const std::string& version, const std::string& os) {
+			client->setSoftwareVersion(name, version, os);
+		}
+
 		boost::optional<SoftwareVersion> getSoftwareVersion(const JID& jid) {
 			GetSoftwareVersionRequest::ref request = GetSoftwareVersionRequest::create(jid, client->getIQRouter());
 			request->onResponse.connect(boost::bind(&SluiftClient::handleSoftwareVersionResponse, this, _1, _2));
@@ -98,7 +109,31 @@ class SluiftClient {
 			return softwareVersion;
 		}
 
+		Stanza::ref getNextEvent() {
+			if (client->isActive() && !pendingEvents.empty()) {
+				Stanza::ref event = pendingEvents.front();
+				pendingEvents.pop_front();
+				return event;
+			}
+			while (client->isActive() && pendingEvents.empty()) {
+				processEvents();
+			}
+			if (client->isActive()) {
+				assert(!pendingEvents.empty());
+				Stanza::ref event = pendingEvents.front();
+				pendingEvents.pop_front();
+				return event;
+			}
+			else {
+				return Stanza::ref();
+			}
+		}
+
 	private:
+		void handleIncomingEvent(Stanza::ref stanza) {
+			pendingEvents.push_back(stanza);
+		}
+
 		void processEvents() {
 			eventLoop.runUntilEvents();
 		}
@@ -120,6 +155,7 @@ class SluiftClient {
 		ClientXMLTracer* tracer;
 		boost::optional<SoftwareVersion> softwareVersion;
 		ErrorPayload::ref error;
+		std::deque<Stanza::ref> pendingEvents;
 };
 
 
@@ -141,6 +177,19 @@ static int sluift_client_disconnect(lua_State *L) {
 	return 0;
 }
 
+static int sluift_client_set_version(lua_State *L) {
+	SluiftClient* client = getClient(L);
+	luaL_checktype(L, 2, LUA_TTABLE);
+	lua_getfield(L, 2, "name");
+	const char* rawName = lua_tostring(L, -1);
+	lua_getfield(L, 2, "version");
+	const char* rawVersion = lua_tostring(L, -1);
+	lua_getfield(L, 2, "os");
+	const char* rawOS = lua_tostring(L, -1);
+	client->setSoftwareVersion(rawName ? rawName : "", rawVersion ? rawVersion : "", rawOS ? rawOS : "");
+	lua_pop(L, 3);
+	return 0;
+}
 
 static int sluift_client_get_version(lua_State *L) {
 	SluiftClient* client = getClient(L);
@@ -167,6 +216,68 @@ static int sluift_client_send_message(lua_State *L) {
 	return 0;
 }
 
+static int sluift_client_send_presence(lua_State *L) {
+	getClient(L)->sendPresence(std::string(luaL_checkstring(L, 2)));
+	return 0;
+}
+
+static int sluift_client_for_event (lua_State *L) {
+	SluiftClient* client = getClient(L);
+	luaL_checktype(L, 2, LUA_TFUNCTION);
+	while (true) {
+		Stanza::ref event = client->getNextEvent();
+		if (!event) {
+			// We got disconnected
+			lua_pushnil(L);
+			lua_pushliteral(L, "disconnected");
+			return 2;
+		}
+		else {
+			// Push the function on the stack
+			lua_pushvalue(L, 2);
+
+			bool emitEvent = false;
+			if (Message::ref message = boost::dynamic_pointer_cast<Message>(event)) {
+				lua_createtable(L, 0, 3);
+				lua_pushliteral(L, "message");
+				lua_setfield(L, -2, "type");
+				lua_pushstring(L, message->getFrom().toString().c_str());
+				lua_setfield(L, -2, "from");
+				lua_pushstring(L, message->getBody().c_str());
+				lua_setfield(L, -2, "body");
+				emitEvent = true;
+			}
+			else if (Presence::ref presence = boost::dynamic_pointer_cast<Presence>(event)) {
+				lua_createtable(L, 0, 3);
+				lua_pushliteral(L, "presence");
+				lua_setfield(L, -2, "type");
+				lua_pushstring(L, presence->getFrom().toString().c_str());
+				lua_setfield(L, -2, "from");
+				lua_pushstring(L, presence->getStatus().c_str());
+				lua_setfield(L, -2, "status");
+				emitEvent = true;
+			}
+			else {
+				assert(false);
+			}
+			if (emitEvent) {
+				int oldTop = lua_gettop(L) - 2;
+				lua_call(L, 1, LUA_MULTRET);
+				int returnValues = lua_gettop(L) - oldTop;
+				if (returnValues > 0) {
+					lua_remove(L, -1 - returnValues);
+					return returnValues;
+				}
+			}
+			else {
+				// Remove the function from the stack again, since
+				// we're not calling the function
+				lua_pop(L, 1);
+			}
+		}
+	}
+}
+
 static int sluift_client_gc (lua_State *L) {
 	SluiftClient* client = getClient(L);
 	delete client;
@@ -178,7 +289,10 @@ static const luaL_reg sluift_client_functions[] = {
 	{"is_connected", sluift_client_is_connected},
 	{"disconnect",  sluift_client_disconnect},
 	{"send_message", sluift_client_send_message},
+	{"send_presence", sluift_client_send_presence},
+	{"set_version", sluift_client_set_version},
 	{"get_version", sluift_client_get_version},
+	{"for_event", sluift_client_for_event},
 	{"__gc", sluift_client_gc},
 	{NULL, NULL}
 };
diff --git a/Swiften/Client/Client.cpp b/Swiften/Client/Client.cpp
index 904f722..7918c46 100644
--- a/Swiften/Client/Client.cpp
+++ b/Swiften/Client/Client.cpp
@@ -93,8 +93,8 @@ XMPPRoster* Client::getRoster() const {
 	return roster;
 }
 
-void Client::setSoftwareVersion(const std::string& name, const std::string& version) {
-	softwareVersionResponder->setVersion(name, version);
+void Client::setSoftwareVersion(const std::string& name, const std::string& version, const std::string& os) {
+	softwareVersionResponder->setVersion(name, version, os);
 }
 
 void Client::requestRoster() {
diff --git a/Swiften/Client/Client.h b/Swiften/Client/Client.h
index 868c9c4..d5db1ac 100644
--- a/Swiften/Client/Client.h
+++ b/Swiften/Client/Client.h
@@ -56,7 +56,7 @@ namespace Swift {
 			 *
 			 * This will be used to respond to version queries from other entities.
 			 */
-			void setSoftwareVersion(const std::string& name, const std::string& version);
+			void setSoftwareVersion(const std::string& name, const std::string& version, const std::string& os);
 
 			/** 
 			 * Returns a representation of the roster.
diff --git a/Swiften/Queries/Responders/SoftwareVersionResponder.cpp b/Swiften/Queries/Responders/SoftwareVersionResponder.cpp
index 0b8362c..445dcc7 100644
--- a/Swiften/Queries/Responders/SoftwareVersionResponder.cpp
+++ b/Swiften/Queries/Responders/SoftwareVersionResponder.cpp
@@ -12,13 +12,14 @@ namespace Swift {
 SoftwareVersionResponder::SoftwareVersionResponder(IQRouter* router) : GetResponder<SoftwareVersion>(router) {
 }
 
-void SoftwareVersionResponder::setVersion(const std::string& client, const std::string& version) {
+void SoftwareVersionResponder::setVersion(const std::string& client, const std::string& version, const std::string& os) {
 	this->client = client;
 	this->version = version;
+	this->os = os;
 }
 
 bool SoftwareVersionResponder::handleGetRequest(const JID& from, const JID&, const std::string& id, boost::shared_ptr<SoftwareVersion>) {
-	sendResponse(from, id, boost::shared_ptr<SoftwareVersion>(new SoftwareVersion(client, version)));
+	sendResponse(from, id, boost::shared_ptr<SoftwareVersion>(new SoftwareVersion(client, version, os)));
 	return true;
 }
 
diff --git a/Swiften/Queries/Responders/SoftwareVersionResponder.h b/Swiften/Queries/Responders/SoftwareVersionResponder.h
index f6a3d52..cbda54c 100644
--- a/Swiften/Queries/Responders/SoftwareVersionResponder.h
+++ b/Swiften/Queries/Responders/SoftwareVersionResponder.h
@@ -16,7 +16,7 @@ namespace Swift {
 		public:
 			SoftwareVersionResponder(IQRouter* router);
 
-			void setVersion(const std::string& client, const std::string& version);
+			void setVersion(const std::string& client, const std::string& version, const std::string& os = "");
 
 		private:
 			virtual bool handleGetRequest(const JID& from, const JID& to, const std::string& id, boost::shared_ptr<SoftwareVersion> payload);
@@ -24,5 +24,6 @@ namespace Swift {
 		private:
 			std::string client;
 			std::string version;
+			std::string os;
 	};
 }
-- 
cgit v0.10.2-6-g49f6