From 81ea0a6b0ea85c55c2f166b69da652aaab2ef79a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sun, 26 Jul 2009 17:23:28 +0200
Subject: Test LinkLocal service registration.


diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h
index 8e3181e..be0c921 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h
@@ -41,7 +41,7 @@ namespace Swift {
 					MainEventLoop::postEvent(boost::bind(boost::ref(onError)), shared_from_this());
 				}
 				else {
-					DNSSDServiceID service(name, type, domain, interfaceIndex);
+					DNSSDServiceID service(name, domain, type, interfaceIndex);
 					if (flags & kDNSServiceFlagsAdd) {
 						MainEventLoop::postEvent(boost::bind(boost::ref(onServiceAdded), service), shared_from_this());
 					}
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDServiceID.h b/Swiften/LinkLocal/DNSSD/DNSSDServiceID.h
index b1986d3..5243662 100644
--- a/Swiften/LinkLocal/DNSSD/DNSSDServiceID.h
+++ b/Swiften/LinkLocal/DNSSD/DNSSDServiceID.h
@@ -9,31 +9,31 @@ namespace Swift {
 
 			DNSSDServiceID(
 				const String& name, 
-				const String& type, 
-				const String& domain = PresenceServiceType, 
+				const String& domain, 
+				const String& type = PresenceServiceType, 
 				int networkInterface = 0) : 
 					name(name), 
-					type(type), 
 					domain(domain), 
+					type(type), 
 					networkInterface(networkInterface) {
 			}
 
 			bool operator==(const DNSSDServiceID& o) const {
-				return name == o.name && type == o.type && domain == o.domain && (networkInterface != 0 && o.networkInterface != 0 ? networkInterface == o.networkInterface : true);
+				return name == o.name && domain == o.domain && type == o.type && (networkInterface != 0 && o.networkInterface != 0 ? networkInterface == o.networkInterface : true);
 			}
 
 			bool operator<(const DNSSDServiceID& o) const {
 				if (o.name == name) {
-					if (o.type == type) {
-						if (o.domain == domain) {
+					if (o.domain == domain) {
+						if (o.type == type) {
 							return networkInterface < o.networkInterface;
 						}
 						else {
-							return domain < o.domain;
+							return type < o.type;
 						}
 					}
 					else {
-						return type < o.type;
+						return domain < o.domain;
 					}
 				}
 				else {
@@ -45,22 +45,22 @@ namespace Swift {
 				return name;
 			}
 
-			const String& getType() const {
-				return type;
-			}
-
 			const String& getDomain() const {
 				return domain;
 			}
 
+			const String& getType() const {
+				return type;
+			}
+
 			int getNetworkInterfaceID() const {
 				return networkInterface;
 			}
 
 		private:
 			String name;
-			String type;
 			String domain;
+			String type;
 			int networkInterface;
 	};
 }
diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp
index 88c7774..5079192 100644
--- a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp
+++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp
@@ -10,7 +10,7 @@
 
 namespace Swift {
 
-FakeDNSSDQuerier::FakeDNSSDQuerier() {
+FakeDNSSDQuerier::FakeDNSSDQuerier(const String& domain) : domain(domain) {
 }
 
 boost::shared_ptr<DNSSDBrowseQuery> FakeDNSSDQuerier::createBrowseQuery() {
@@ -43,6 +43,10 @@ void FakeDNSSDQuerier::addRunningQuery(boost::shared_ptr<FakeDNSSDQuery> query)
 			}
 		}
 	}
+	else if (boost::shared_ptr<FakeDNSSDRegisterQuery> registerQuery = boost::dynamic_pointer_cast<FakeDNSSDRegisterQuery>(query)) {
+		DNSSDServiceID service(registerQuery->name, domain);
+		MainEventLoop::postEvent(boost::bind(boost::ref(registerQuery->onRegisterFinished), service), shared_from_this());
+	}
 }
 
 void FakeDNSSDQuerier::removeRunningQuery(boost::shared_ptr<FakeDNSSDQuery> query) {
@@ -77,6 +81,15 @@ void FakeDNSSDQuerier::setServiceInfo(const DNSSDServiceID& id, const DNSSDResol
 	}
 }
 
+bool FakeDNSSDQuerier::isServiceRegistered(const String& name, int port, const ByteArray& info) {
+	foreach(const boost::shared_ptr<FakeDNSSDRegisterQuery>& query, getQueries<FakeDNSSDRegisterQuery>()) {
+		if (query->name == name && query->port == port && query->info == info) {
+			return true;
+		}
+	}
+	return false;
+}
+
 void FakeDNSSDQuerier::setBrowseError() {
 	foreach(const boost::shared_ptr<FakeDNSSDBrowseQuery>& query, getQueries<FakeDNSSDBrowseQuery>()) {
 		MainEventLoop::postEvent(boost::ref(query->onError), shared_from_this());
diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h
index 43b717e..f2ec17b 100644
--- a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h
+++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h
@@ -20,7 +20,7 @@ namespace Swift {
 			public EventOwner,
 			public boost::enable_shared_from_this<FakeDNSSDQuerier> {
 		public:
-			FakeDNSSDQuerier();
+			FakeDNSSDQuerier(const String& domain);
 
 			boost::shared_ptr<DNSSDBrowseQuery> createBrowseQuery();
 			boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery(
@@ -36,6 +36,7 @@ namespace Swift {
 			void addService(const DNSSDServiceID& id);
 			void removeService(const DNSSDServiceID& id);
 			void setServiceInfo(const DNSSDServiceID& id, const DNSSDResolveServiceQuery::Result& info);
+			bool isServiceRegistered(const String& name, int port, const ByteArray& info);
 
 			void setBrowseError();
 			void setRegisterError();
@@ -53,6 +54,7 @@ namespace Swift {
 			}
 
 		private:
+			String domain;
 			std::list< boost::shared_ptr<FakeDNSSDQuery> > runningQueries;
 			std::set<DNSSDServiceID> services;
 			typedef std::map<DNSSDServiceID,DNSSDResolveServiceQuery::Result> ServiceInfoMap;
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
index 265acc1..f7c5478 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
@@ -11,7 +11,9 @@ LinkLocalServiceBrowser::LinkLocalServiceBrowser(boost::shared_ptr<DNSSDQuerier>
 }
 
 LinkLocalServiceBrowser::~LinkLocalServiceBrowser() {
-	assert(!isRunning());
+	if (isRunning()) {
+		std::cerr << "WARNING: LinkLocalServiceBrowser still running on destruction" << std::endl;
+	}
 }
 
 
@@ -67,6 +69,7 @@ void LinkLocalServiceBrowser::unregisterService() {
 	assert(registerQuery);
 	registerQuery->unregisterService();
 	registerQuery.reset();
+	selfService.reset();
 }
 
 std::vector<LinkLocalService> LinkLocalServiceBrowser::getServices() const {
@@ -78,6 +81,9 @@ std::vector<LinkLocalService> LinkLocalServiceBrowser::getServices() const {
 }
 
 void LinkLocalServiceBrowser::handleServiceAdded(const DNSSDServiceID& service) {
+	if (selfService && service == *selfService) {
+		return;
+	}
 	boost::shared_ptr<DNSSDResolveServiceQuery> resolveQuery = querier->createResolveServiceQuery(service);
 	resolveQuery->onServiceResolved.connect(
 		boost::bind(&LinkLocalServiceBrowser::handleServiceResolved, this, service, _1));
@@ -89,6 +95,9 @@ void LinkLocalServiceBrowser::handleServiceAdded(const DNSSDServiceID& service)
 }
 
 void LinkLocalServiceBrowser::handleServiceRemoved(const DNSSDServiceID& service) {
+	if (selfService && service == *selfService) {
+		return;
+	}
 	ResolveQueryMap::iterator i = resolveQueries.find(service);
 	assert(i != resolveQueries.end());
 	i->second->stop();
@@ -111,7 +120,10 @@ void LinkLocalServiceBrowser::handleServiceResolved(const DNSSDServiceID& servic
 }
 
 void LinkLocalServiceBrowser::handleRegisterFinished(const boost::optional<DNSSDServiceID>& result) {
-	if (!result) {
+	if (result) {
+		selfService = result;
+	}
+	else {
 		haveError = true;
 		stop();
 	}
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.h b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
index 33c9858..dcdd576 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.h
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
@@ -45,6 +45,7 @@ namespace Swift {
 
 		private:
 			boost::shared_ptr<DNSSDQuerier> querier;
+			boost::optional<DNSSDServiceID> selfService;
 			boost::shared_ptr<DNSSDBrowseQuery> browseQuery;
 			boost::shared_ptr<DNSSDRegisterQuery> registerQuery;
 			typedef std::map<DNSSDServiceID, boost::shared_ptr<DNSSDResolveServiceQuery> > ResolveQueryMap;
diff --git a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
index ab42834..4b66398 100644
--- a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
+++ b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
@@ -18,6 +18,8 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST(testStart);
 		CPPUNIT_TEST(testServiceAdded);
 		CPPUNIT_TEST(testServiceAdded_NoServiceInfo);
+		CPPUNIT_TEST(testServiceAdded_RegisteredService);
+		CPPUNIT_TEST(testServiceAdded_UnregisteredService);
 		CPPUNIT_TEST(testServiceChanged);
 		CPPUNIT_TEST(testServiceRemoved);
 		CPPUNIT_TEST(testError_BrowseErrorAfterStart);
@@ -32,10 +34,14 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 
 		void setUp() {
 			eventLoop = new DummyEventLoop();
-			querier = boost::shared_ptr<FakeDNSSDQuerier>(new FakeDNSSDQuerier());
+			querier = boost::shared_ptr<FakeDNSSDQuerier>(new FakeDNSSDQuerier("wonderland.lit"));
+			aliceServiceID = new DNSSDServiceID("alice", "wonderland.lit");
+			aliceServiceInfo = new DNSSDResolveServiceQuery::Result("_presence._tcp.wonderland.lit", "xmpp.wonderland.lit", 1234, LinkLocalServiceInfo().toTXTRecord());
 			testServiceID = new DNSSDServiceID("foo", "bar.local");
 			testServiceInfo = new DNSSDResolveServiceQuery::Result("_presence._tcp.bar.local", "xmpp.bar.local", 1234, LinkLocalServiceInfo().toTXTRecord());
 			testServiceInfo2 = new DNSSDResolveServiceQuery::Result("_presence.tcp.bar.local", "xmpp.foo.local", 2345, LinkLocalServiceInfo().toTXTRecord());
+			errorStopReceived = false;
+			normalStopReceived = false;
 		}
 
 		void tearDown() {
@@ -97,8 +103,50 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			eventLoop->processEvents();
 
 			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(addedServices.size()));
+			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling->getServices().size()));
+
+			testling->stop();
+		}
+
+		void testServiceAdded_RegisteredService() {
+			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
+			testling->start();
+			eventLoop->processEvents();
+
+			testling->registerService("alice", 1234, LinkLocalServiceInfo());
+			eventLoop->processEvents();
+			querier->setServiceInfo(*aliceServiceID, *aliceServiceInfo);
+			querier->addService(*aliceServiceID);
+			eventLoop->processEvents();
+
+			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(addedServices.size()));
+			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling->getServices().size()));
+
+			testling->stop();
+		}
+
+		void testServiceAdded_UnregisteredService() {
+			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
+			testling->start();
+			eventLoop->processEvents();
+			testling->registerService("alice", 1234, LinkLocalServiceInfo());
+			eventLoop->processEvents();
+			testling->unregisterService();
+			eventLoop->processEvents();
+
+			querier->setServiceInfo(*aliceServiceID, *aliceServiceInfo);
+			querier->addService(*aliceServiceID);
+			eventLoop->processEvents();
+
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size()));
+			CPPUNIT_ASSERT(addedServices[0] == *aliceServiceID);
+			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size()));
+			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(removedServices.size()));
 			std::vector<LinkLocalService> services = testling->getServices();
-			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(services.size()));
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(services.size()));
+			CPPUNIT_ASSERT(*aliceServiceID == services[0].getID());
+			CPPUNIT_ASSERT(aliceServiceInfo->port == services[0].getPort());
+			CPPUNIT_ASSERT(aliceServiceInfo->host == services[0].getHostname());
 
 			testling->stop();
 		}
@@ -156,6 +204,7 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 
 			CPPUNIT_ASSERT(!testling->isRunning());
 			CPPUNIT_ASSERT(testling->hasError());
+			CPPUNIT_ASSERT(errorStopReceived);
 		}
 
 		void testError_BrowseErrorAfterResolve() {
@@ -174,6 +223,7 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			CPPUNIT_ASSERT(testling->hasError());
 			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling->getServices().size()));
 			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size()));
+			CPPUNIT_ASSERT(errorStopReceived);
 		}
 
 		void testRegisterService() {
@@ -181,13 +231,21 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			testling->start();
 			eventLoop->processEvents();
 
+			LinkLocalServiceInfo info;
+			info.setFirstName("Foo");
+			testling->registerService("foo@bar", 1234, info);
+			eventLoop->processEvents();
+
+			CPPUNIT_ASSERT(querier->isServiceRegistered("foo@bar", 1234, info.toTXTRecord()));
+
 			testling->stop();
 		}
 
 		void testRegisterService_Error() {
 			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
 			testling->start();
-			testling->registerService("", 1234);
+			LinkLocalServiceInfo info;
+			testling->registerService("foo@bar", 1234, info);
 			eventLoop->processEvents();
 
 			querier->setRegisterError();
@@ -195,12 +253,26 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 
 			CPPUNIT_ASSERT(!testling->isRunning());
 			CPPUNIT_ASSERT(testling->hasError());
+			CPPUNIT_ASSERT(errorStopReceived);
+			CPPUNIT_ASSERT(!querier->isServiceRegistered("foo@bar", 1234, info.toTXTRecord()));
 		}
 
 		void testRegisterService_Reregister() {
 			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
 			testling->start();
 			eventLoop->processEvents();
+			LinkLocalServiceInfo info;
+			info.setFirstName("Foo");
+			testling->registerService("foo@bar", 1234, info);
+			eventLoop->processEvents();
+			testling->unregisterService();
+			eventLoop->processEvents();
+
+			info.setFirstName("Bar");
+			testling->registerService("bar@baz", 3456, info);
+			eventLoop->processEvents();
+
+			CPPUNIT_ASSERT(querier->isServiceRegistered("bar@baz", 3456, info.toTXTRecord()));
 
 			testling->stop();
 		}
@@ -215,6 +287,8 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 					&LinkLocalServiceBrowserTest::handleServiceChanged, this, _1));
 			testling->onServiceRemoved.connect(boost::bind(
 					&LinkLocalServiceBrowserTest::handleServiceRemoved, this, _1));
+			testling->onStopped.connect(boost::bind(
+					&LinkLocalServiceBrowserTest::handleStopped, this, _1));
 			return testling;
 		}
 
@@ -230,15 +304,30 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			changedServices.push_back(service);
 		}
 
+		void handleStopped(bool error) {
+			CPPUNIT_ASSERT(!errorStopReceived);
+			CPPUNIT_ASSERT(!normalStopReceived);
+			if (error) {
+				errorStopReceived = true;
+			}
+			else {
+				normalStopReceived = true;
+			}
+		}
+
 	private:
 		DummyEventLoop* eventLoop;
 		boost::shared_ptr<FakeDNSSDQuerier> querier;
 		std::vector<DNSSDServiceID> addedServices;
 		std::vector<DNSSDServiceID> changedServices;
 		std::vector<DNSSDServiceID> removedServices;
+		DNSSDServiceID* aliceServiceID;
+		DNSSDResolveServiceQuery::Result* aliceServiceInfo;
 		DNSSDServiceID* testServiceID;
 		DNSSDResolveServiceQuery::Result* testServiceInfo;
 		DNSSDResolveServiceQuery::Result* testServiceInfo2;
+		bool errorStopReceived;
+		bool normalStopReceived;
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(LinkLocalServiceBrowserTest);
-- 
cgit v0.10.2-6-g49f6