From fde71bd59b1412ae475c06f2d4100ce088e86af6 Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Thu, 1 Mar 2012 08:03:50 +0000
Subject: Unit tests for SettingsProviderHierachy

Also fixing up errors they found and an uninitialised read  left-over from the original patch.

diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index dcbba34..aedee4c 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -113,6 +113,8 @@ ChatsManager::ChatsManager(
 
 	settings_->onSettingChanged.connect(boost::bind(&ChatsManager::handleSettingChanged, this, _1));
 
+	userWantsReceipts_ = settings_->getSetting(SettingConstants::REQUEST_DELIVERYRECEIPTS);
+
 	setupBookmarks();
 	loadRecents();
 }
diff --git a/Swift/Controllers/SConscript b/Swift/Controllers/SConscript
index 02e212b..70085a6 100644
--- a/Swift/Controllers/SConscript
+++ b/Swift/Controllers/SConscript
@@ -84,4 +84,5 @@ if env["SCONS_STAGE"] == "build" :
 			File("Chat/UnitTest/MUCControllerTest.cpp"),
 			File("UnitTest/MockChatWindow.cpp"),
 			File("UnitTest/ChatMessageSummarizerTest.cpp"),
+			File("Settings/UnitTest/SettingsProviderHierachyTest.cpp"),
 		])
diff --git a/Swift/Controllers/Settings/DummySettingsProvider.h b/Swift/Controllers/Settings/DummySettingsProvider.h
index bb7d2e6..1d6059f 100644
--- a/Swift/Controllers/Settings/DummySettingsProvider.h
+++ b/Swift/Controllers/Settings/DummySettingsProvider.h
@@ -39,11 +39,18 @@ class DummySettingsProvider : public SettingsProvider {
 		virtual std::vector<std::string> getAvailableProfiles() {return std::vector<std::string>();}
 		virtual void createProfile(const std::string& ) {}
 		virtual void removeProfile(const std::string& ) {}
-		virtual bool getIsSettingFinal(const std::string& ) {return false;}
+		virtual bool getIsSettingFinal(const std::string& settingPath) {return finals.count(settingPath);}
+		void setFinal(const std::string& settingPath) {
+			finals.insert(settingPath);
+		}
+		virtual bool hasSetting(const std::string& key) {
+			return stringValues.find(key) != stringValues.end() || intValues.find(key) != intValues.end() || boolValues.find(key) != boolValues.end();
+		}
 	private:
 		std::map<std::string, std::string> stringValues;
 		std::map<std::string, int> intValues;
 		std::map<std::string, bool> boolValues;
+		std::set<std::string> finals;
 };
 
 }
diff --git a/Swift/Controllers/Settings/SettingsProvider.h b/Swift/Controllers/Settings/SettingsProvider.h
index e884add..458653b 100644
--- a/Swift/Controllers/Settings/SettingsProvider.h
+++ b/Swift/Controllers/Settings/SettingsProvider.h
@@ -55,6 +55,7 @@ class SettingsProvider {
 		bool getIsSettingFinal(const Setting<T>& setting) {
 			return getIsSettingFinal(setting.getKey());
 		}
+		virtual bool hasSetting(const std::string& key) = 0;
 
 		friend class SettingsProviderHierachy;
 	protected:
diff --git a/Swift/Controllers/Settings/SettingsProviderHierachy.cpp b/Swift/Controllers/Settings/SettingsProviderHierachy.cpp
index 3b7d13c..40a9025 100644
--- a/Swift/Controllers/Settings/SettingsProviderHierachy.cpp
+++ b/Swift/Controllers/Settings/SettingsProviderHierachy.cpp
@@ -13,14 +13,27 @@ namespace Swift {
 SettingsProviderHierachy::~SettingsProviderHierachy() {
 }
 
+bool SettingsProviderHierachy::hasSetting(const std::string& key) {
+	foreach (SettingsProvider* provider, providers_) {
+		if (provider->hasSetting(key)) {
+			return true;
+		}
+	}
+	return false;
+}
+
 std::string SettingsProviderHierachy::getSetting(const Setting<std::string>& setting) {
+	std::string value = setting.getDefaultValue();
 	foreach (SettingsProvider* provider, providers_) {
 		std::string providerSetting = provider->getSetting(setting);
-		if (providerSetting != setting.getDefaultValue()) {
-			return providerSetting;
+		if (provider->hasSetting(setting.getKey())) {
+			value = providerSetting;
+		}
+		if (provider->getIsSettingFinal(setting.getKey())) {
+			return value;
 		}
 	}
-	return setting.getDefaultValue();
+	return value;
 }
 
 void SettingsProviderHierachy::storeSetting(const Setting<std::string>& setting, const std::string& settingValue) {
@@ -30,13 +43,17 @@ void SettingsProviderHierachy::storeSetting(const Setting<std::string>& setting,
 }
 
 bool SettingsProviderHierachy::getSetting(const Setting<bool>& setting) {
+	bool value = setting.getDefaultValue();
 	foreach (SettingsProvider* provider, providers_) {
 		bool providerSetting = provider->getSetting(setting);
-		if (providerSetting != setting.getDefaultValue()) {
-			return providerSetting;
+		if (provider->hasSetting(setting.getKey())) {
+			value = providerSetting;
+			if (provider->getIsSettingFinal(setting.getKey())) {
+				return providerSetting;
+			}
 		}
 	}
-	return setting.getDefaultValue();
+	return value;
 }
 
 void SettingsProviderHierachy::storeSetting(const Setting<bool>& setting, const bool& settingValue) {
@@ -46,13 +63,17 @@ void SettingsProviderHierachy::storeSetting(const Setting<bool>& setting, const
 }
 
 int SettingsProviderHierachy::getSetting(const Setting<int>& setting) {
+	int value = setting.getDefaultValue();
 	foreach (SettingsProvider* provider, providers_) {
 		int providerSetting = provider->getSetting(setting);
-		if (providerSetting != setting.getDefaultValue()) {
-			return providerSetting;
+		if (provider->hasSetting(setting.getKey())) {
+			value = providerSetting;
+			if (provider->getIsSettingFinal(setting.getKey())) {
+				return providerSetting;
+			}
 		}
 	}
-	return setting.getDefaultValue();
+	return value;
 }
 
 void SettingsProviderHierachy::storeSetting(const Setting<int>& setting, const int& settingValue) {
diff --git a/Swift/Controllers/Settings/SettingsProviderHierachy.h b/Swift/Controllers/Settings/SettingsProviderHierachy.h
index b7f6961..b16b33e 100644
--- a/Swift/Controllers/Settings/SettingsProviderHierachy.h
+++ b/Swift/Controllers/Settings/SettingsProviderHierachy.h
@@ -22,6 +22,7 @@ class SettingsProviderHierachy : public SettingsProvider {
 		virtual std::vector<std::string> getAvailableProfiles();
 		virtual void createProfile(const std::string& profile);
 		virtual void removeProfile(const std::string& profile);
+		virtual bool hasSetting(const std::string& key);
 	protected:
 		virtual bool getIsSettingFinal(const std::string& settingPath);
 
diff --git a/Swift/Controllers/Settings/UnitTest/SettingsProviderHierachyTest.cpp b/Swift/Controllers/Settings/UnitTest/SettingsProviderHierachyTest.cpp
new file mode 100644
index 0000000..aa4d14f
--- /dev/null
+++ b/Swift/Controllers/Settings/UnitTest/SettingsProviderHierachyTest.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include <Swift/Controllers/Settings/SettingsProviderHierachy.h>
+#include <Swift/Controllers/Settings/DummySettingsProvider.h>
+#include <Swift/Controllers/Settings/XMLSettingsProvider.h>
+
+using namespace Swift;
+using namespace std;
+
+class SettingsProviderHierachyTest : public CppUnit::TestFixture {
+	CPPUNIT_TEST_SUITE(SettingsProviderHierachyTest);
+	CPPUNIT_TEST(testEmpty);
+	CPPUNIT_TEST(testTop);
+	CPPUNIT_TEST(testBottom);
+	CPPUNIT_TEST(testBoth);
+	CPPUNIT_TEST(testTopDefault);
+	CPPUNIT_TEST(testBottomOverrides);
+	CPPUNIT_TEST(testFinal);
+	CPPUNIT_TEST_SUITE_END();
+
+public:
+	SettingsProviderHierachyTest() : setting1("somekey", 42) {};
+
+	void setUp() {
+		bottom = new DummySettingsProvider();
+		top = new DummySettingsProvider();
+		testling = new SettingsProviderHierachy();
+		testling->addProviderToTopOfStack(bottom);
+		testling->addProviderToTopOfStack(top);
+	}
+
+	void tearDown() {
+		delete testling;
+		delete top;
+		delete bottom;
+	}
+
+	void testEmpty() {
+		CPPUNIT_ASSERT_EQUAL(42, testling->getSetting(setting1));
+	}
+
+	void testTop() {
+		top->storeSetting(setting1, 37);
+		CPPUNIT_ASSERT_EQUAL(37, testling->getSetting(setting1));
+	}
+
+	void testBottom() {
+		bottom->storeSetting(setting1, 17);
+		CPPUNIT_ASSERT_EQUAL(17, testling->getSetting(setting1));
+	}
+
+	void testBoth() {
+		bottom->storeSetting(setting1, 17);
+		top->storeSetting(setting1, 37);
+		CPPUNIT_ASSERT_EQUAL(37, testling->getSetting(setting1));
+	}
+
+	void testTopDefault() {
+		bottom->storeSetting(setting1, 17);
+		top->storeSetting(setting1, 42);
+		CPPUNIT_ASSERT_EQUAL(42, testling->getSetting(setting1));
+	}
+
+	void testBottomOverrides() {
+		bottom->storeSetting(setting1, 17);
+		bottom->setFinal(setting1.getKey());
+		top->storeSetting(setting1, 5);
+		CPPUNIT_ASSERT_EQUAL(17, testling->getSetting(setting1));
+	}
+
+	void testFinal() {
+		bottom->storeSetting(setting1, 17);
+		bottom->setFinal(setting1.getKey());
+		testling->storeSetting(setting1, 5);
+		CPPUNIT_ASSERT_EQUAL(17, testling->getSetting(setting1));
+	}
+private:
+	SettingsProviderHierachy* testling;
+	DummySettingsProvider* bottom;
+	DummySettingsProvider* top;
+	SettingsProvider::Setting<int> setting1;
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SettingsProviderHierachyTest);
diff --git a/Swift/Controllers/Settings/XMLSettingsProvider.cpp b/Swift/Controllers/Settings/XMLSettingsProvider.cpp
index 3710072..e83ed24 100644
--- a/Swift/Controllers/Settings/XMLSettingsProvider.cpp
+++ b/Swift/Controllers/Settings/XMLSettingsProvider.cpp
@@ -36,6 +36,11 @@ XMLSettingsProvider::~XMLSettingsProvider() {
 
 }
 
+bool XMLSettingsProvider::hasSetting(const std::string& key) {
+	return (values_.find(key) != values_.end());
+}
+
+
 std::string XMLSettingsProvider::getSetting(const Setting<std::string>& setting) {
 	if (values_.find(setting.getKey()) != values_.end()) {
 		std::string value = values_[setting.getKey()];
diff --git a/Swift/Controllers/Settings/XMLSettingsProvider.h b/Swift/Controllers/Settings/XMLSettingsProvider.h
index 61abd11..e03d3c1 100644
--- a/Swift/Controllers/Settings/XMLSettingsProvider.h
+++ b/Swift/Controllers/Settings/XMLSettingsProvider.h
@@ -27,6 +27,8 @@ class XMLSettingsProvider : public SettingsProvider, public XMLParserClient {
 		virtual std::vector<std::string> getAvailableProfiles();
 		virtual void createProfile(const std::string& profile);
 		virtual void removeProfile(const std::string& profile);
+		virtual bool hasSetting(const std::string& key);
+
 
 		virtual void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes);
 		virtual void handleEndElement(const std::string& element, const std::string& ns);
diff --git a/Swift/QtUI/QtSettingsProvider.cpp b/Swift/QtUI/QtSettingsProvider.cpp
index 0c4d49b..64e88d4 100644
--- a/Swift/QtUI/QtSettingsProvider.cpp
+++ b/Swift/QtUI/QtSettingsProvider.cpp
@@ -18,6 +18,11 @@ QtSettingsProvider::~QtSettingsProvider() {
 
 }
 
+bool QtSettingsProvider::hasSetting(const std::string& key) {
+	return !settings_.value(key.c_str()).isNull();
+}
+
+
 std::string QtSettingsProvider::getSetting(const Setting<std::string>& setting) {
 	QVariant variant = settings_.value(setting.getKey().c_str());
 	return variant.isNull() ? setting.getDefaultValue() : std::string(variant.toString().toUtf8());
diff --git a/Swift/QtUI/QtSettingsProvider.h b/Swift/QtUI/QtSettingsProvider.h
index ececa6e..e85bfb5 100644
--- a/Swift/QtUI/QtSettingsProvider.h
+++ b/Swift/QtUI/QtSettingsProvider.h
@@ -25,6 +25,7 @@ class QtSettingsProvider : public SettingsProvider {
 		virtual std::vector<std::string> getAvailableProfiles();
 		virtual void createProfile(const std::string& profile);
 		virtual void removeProfile(const std::string& profile);
+		virtual bool hasSetting(const std::string& key);
 		QSettings* getQSettings();
 	protected:
 		virtual bool getIsSettingFinal(const std::string& settingPath);
diff --git a/Swiften/Client/CoreClient.h b/Swiften/Client/CoreClient.h
index 1b875d2..c9a6f30 100644
--- a/Swiften/Client/CoreClient.h
+++ b/Swiften/Client/CoreClient.h
@@ -202,8 +202,6 @@ namespace Swift {
 			 */
 			virtual void handleConnected() {};
 
-			bool isCAPIURI();
-
 		private:
 			void handleConnectorFinished(boost::shared_ptr<Connection>);
 			void handleStanzaChannelAvailableChanged(bool available);
-- 
cgit v0.10.2-6-g49f6