summaryrefslogtreecommitdiffstats
blob: 222491b4e93e70849fc9d36b0bbced066c2f9380 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
 * Copyright (c) 2014 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 <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/smart_ptr/make_shared.hpp>

#include <Swiften/Base/foreach.h>
#include "Swift/Controllers/ContactSuggester.h"

using namespace Swift;

class ContactSuggesterTest : public CppUnit::TestFixture {
	CPPUNIT_TEST_SUITE(ContactSuggesterTest);
	CPPUNIT_TEST(equalityTest);
	CPPUNIT_TEST(lexicographicalSortTest);
	CPPUNIT_TEST(sortTest);
	CPPUNIT_TEST_SUITE_END();

public:

	std::vector<std::string> wordList() {
		const std::string words[] = {
			"abc",
			"ab",
			"bc",
			"d"
		};

		return std::vector<std::string>(words, words+sizeof(words)/sizeof(*words));
	}

	std::vector<StatusShow::Type> statusList() {
		StatusShow::Type types[] = {
			StatusShow::Online,
			StatusShow::Away,
			StatusShow::FFC,
			StatusShow::XA,
			StatusShow::DND,
			StatusShow::None
		};

		return std::vector<StatusShow::Type>(types, types+sizeof(types)/sizeof(*types));
	}

	std::vector<Contact::ref> contactList() {
		std::vector<Contact::ref> contacts;
		std::vector<std::string> words = wordList();
		std::vector<StatusShow::Type> statuses = statusList();
		foreach (const std::string& name, words) {
			foreach (const std::string& jid, words) {
				foreach (const StatusShow::Type& status, statuses) {
					contacts.push_back(boost::make_shared<Contact>(name, jid, status, ""));
				}
			}
		}
		return contacts;
	}

	/* a = a */
	bool isReflexive(const boost::function<bool (const Contact::ref&, const Contact::ref&)>& comparitor) {
		std::vector<Contact::ref> contacts = contactList();
		foreach (const Contact::ref& a, contacts) {
			if (!comparitor(a, a)) {
				return false;
			}
		}
		return true;
	}

	/* a = b -> b = a */
	bool isSymmetric(const boost::function<bool (const Contact::ref&, const Contact::ref&)>& comparitor) {
		std::vector<Contact::ref> contacts = contactList();
		foreach (const Contact::ref& a, contacts) {
			foreach (const Contact::ref& b, contacts) {
				if (comparitor(a, b)) {
					if (!comparitor(b, a)) {
						return false;
					}
				}
			}
		}
		return true;
	}

	/* a = b && b = c -> a = c */
	bool isTransitive(const boost::function<bool (const Contact::ref&, const Contact::ref&)>& comparitor) {
		std::vector<Contact::ref> contacts = contactList();
		foreach (const Contact::ref& a, contacts) {
			foreach (const Contact::ref& b, contacts) {
				foreach (const Contact::ref& c, contacts) {
					if (comparitor(a, b) && comparitor(b, c)) {
						if (!comparitor(a, c)) {
							return false;
						}
					}
				}
			}
		}
		return true;
	}

	void equalityTest() {
		CPPUNIT_ASSERT(isReflexive(Contact::equalityPredicate));
		CPPUNIT_ASSERT(isSymmetric(Contact::equalityPredicate));
		CPPUNIT_ASSERT(isTransitive(Contact::equalityPredicate));
	}

	void lexicographicalSortTest() {
		CPPUNIT_ASSERT(isTransitive(Contact::lexicographicalSortPredicate));
	}

	void sortTest() {
		std::vector<std::string> words = wordList();
		foreach (const std::string& word, words) {
			CPPUNIT_ASSERT(isTransitive(boost::bind(Contact::sortPredicate, _1, _2, word)));
		}
	}

};

CPPUNIT_TEST_SUITE_REGISTRATION(ContactSuggesterTest);