1//------------------------------------------------------------------------------
2//	MessengerComparissonTester.cpp
3//
4//------------------------------------------------------------------------------
5
6// Standard Includes -----------------------------------------------------------
7#include <stdio.h>
8
9// System Includes -------------------------------------------------------------
10#include <Message.h>
11#include <OS.h>
12
13#include <Handler.h>
14#include <Looper.h>
15#include <Messenger.h>
16
17// Project Includes ------------------------------------------------------------
18#include <TestUtils.h>
19#include <ThreadedTestCaller.h>
20#include <cppunit/TestSuite.h>
21
22// Local Includes --------------------------------------------------------------
23#include "Helpers.h"
24#include "MessengerComparissonTester.h"
25#include "SMTarget.h"
26
27// Local Defines ---------------------------------------------------------------
28
29// Globals ---------------------------------------------------------------------
30
31//------------------------------------------------------------------------------
32
33struct FakeMessenger {
34	port_id	fPort;
35	int32	fHandlerToken;
36	team_id	fTeam;
37	int32	extra0;
38	int32	extra1;
39	bool	fPreferredTarget;
40	bool	extra2;
41	bool	extra3;
42	bool	extra4;
43};
44
45static
46bool
47operator<(const FakeMessenger& a, const FakeMessenger& b)
48{
49	// significance:
50	// * fPort
51	// * fHandlerToken
52	// * fPreferredTarget
53	// fTeam is insignificant
54	return (a.fPort < b.fPort
55			|| a.fPort == b.fPort
56				&& (a.fHandlerToken < b.fHandlerToken
57					|| a.fHandlerToken == b.fHandlerToken
58						&& !a.fPreferredTarget && b.fPreferredTarget));
59}
60
61static
62bool
63operator!=(const FakeMessenger& a, const FakeMessenger& b)
64{
65	return (a < b || b < a);
66}
67
68static
69bool
70operator==(const FakeMessenger& a, const FakeMessenger& b)
71{
72	return !(a != b);
73}
74
75// constructor
76MessengerComparissonTester::MessengerComparissonTester()
77	: BThreadedTestCase(),
78	  fHandler(NULL),
79	  fLooper(NULL)
80{
81}
82
83// constructor
84MessengerComparissonTester::MessengerComparissonTester(std::string name)
85	: BThreadedTestCase(name),
86	  fHandler(NULL),
87	  fLooper(NULL)
88{
89}
90
91// destructor
92MessengerComparissonTester::~MessengerComparissonTester()
93{
94	if (fLooper) {
95		fLooper->Lock();
96		if (fHandler) {
97			fLooper->RemoveHandler(fHandler);
98			delete fHandler;
99		}
100		fLooper->Quit();
101	}
102}
103
104/*
105	bool operator==(const BMessenger &other) const
106	bool operator!=(const BMessenger &a, const BMessenger &b)
107	@case 1			this (a) and other (b) are uninitialized
108	@results		should return true/false.
109 */
110void MessengerComparissonTester::ComparissonTest1()
111{
112	BMessenger a;
113	BMessenger b;
114	CHK(a == b);
115	CHK(b == a);
116	CHK(!(a != b));
117	CHK(!(b != a));
118}
119
120/*
121	bool operator==(const BMessenger &other) const
122	bool operator!=(const BMessenger &a, const BMessenger &b)
123	@case 1			this (a) is initialized, other (b) is uninitialized,
124					and vice versa
125	@results		should return false/true.
126 */
127void MessengerComparissonTester::ComparissonTest2()
128{
129	// create looper
130	BLooper *looper = new BLooper;
131	looper->Run();
132	LooperQuitter quitter(looper);
133	// create messenger
134	BMessenger a(NULL, looper);
135	BMessenger b;
136	CHK(a != b);
137	CHK(b != a);
138	CHK(!(a == b));
139	CHK(!(b == a));
140}
141
142/*
143	bool operator==(const BMessenger &other) const
144	bool operator!=(const BMessenger &a, const BMessenger &b)
145	bool operator<(const BMessenger &a, const BMessenger &b)
146	@case 3			this and other are initialized, different cases:
147					- same object => true
148					- different objects same target => true
149					- looper preferred handler vs. same looper but the looper
150					  itself as handler => false
151					- looper preferred handler vs. other looper preferred
152					  handler => false
153					- looper preferred handler vs. other looper specific
154					  handler => false
155					- local looper vs. remote looper => false
156 */
157void MessengerComparissonTester::ComparissonTest3()
158{
159	// messenger1: looper and handler
160	BLooper *looper1 = new BLooper;
161	looper1->Run();
162	LooperQuitter quitter1(looper1);
163	BHandler *handler1 = new BHandler;
164	HandlerDeleter deleter1(handler1);
165	CHK(looper1->Lock());
166	looper1->AddHandler(handler1);
167	looper1->Unlock();
168	BMessenger messenger1(handler1, looper1);
169	BMessenger messenger1a(handler1, looper1);
170	// messenger2: looper (1)
171	BMessenger messenger2(NULL, looper1);
172	BMessenger messenger2a(NULL, looper1);
173	// messenger3: looper and handler
174	BLooper *looper2 = new BLooper;
175	looper2->Run();
176	LooperQuitter quitter2(looper2);
177	BHandler *handler2 = new BHandler;
178	HandlerDeleter deleter2(handler2);
179	CHK(looper2->Lock());
180	looper2->AddHandler(handler2);
181	looper2->Unlock();
182	BMessenger messenger3(handler2, looper2);
183	BMessenger messenger3a(handler2, looper2);
184	// messenger4: looper (2)
185	BMessenger messenger4(NULL, looper2);
186	BMessenger messenger4a(NULL, looper2);
187	// remote targets
188	RemoteSMTarget remoteTarget1(false);
189	RemoteSMTarget remoteTarget2(true);
190	BMessenger messenger5(remoteTarget1.Messenger());
191	BMessenger messenger5a(remoteTarget1.Messenger());
192	BMessenger messenger6(remoteTarget2.Messenger());
193	BMessenger messenger6a(remoteTarget2.Messenger());
194
195	// targets -- test data
196	struct target {
197		BMessenger	&messenger;
198		int32		id;			// identifies the target
199	} targets[] = {
200		{ messenger1,	1 },
201		{ messenger1a,	1 },
202		{ messenger2,	2 },
203		{ messenger2,	2 },
204		{ messenger3,	3 },
205		{ messenger3a,	3 },
206		{ messenger4,	4 },
207		{ messenger4a,	4 },
208		{ messenger5,	5 },
209		{ messenger5a,	5 },
210		{ messenger6,	6 },
211		{ messenger6a,	6 },
212	};
213	int32 targetCount = sizeof(targets) / sizeof(target);
214
215	// test
216	for (int32 i = 0; i < targetCount; i++) {
217		NextSubTest();
218		const target &target1 = targets[i];
219		const BMessenger &a = target1.messenger;
220		for (int32 k = 0; k < targetCount; k++) {
221			const target &target2 = targets[k];
222			const BMessenger &b = target2.messenger;
223			bool areEqual = (target1.id == target2.id);
224			CHK((a == b) == areEqual);
225			CHK((b == a) == areEqual);
226			CHK((a != b) == !areEqual);
227			CHK((b != a) == !areEqual);
228		}
229	}
230}
231
232// Compare
233//
234// Helper function for LessTest1().
235static inline
236void
237Compare(const FakeMessenger &fake1, const FakeMessenger &fake2,
238		const BMessenger &messenger1, const BMessenger &messenger2)
239{
240	CHK((messenger1 == messenger2) == (fake1 == fake2));
241	CHK((messenger1 != messenger2) == (fake1 != fake2));
242	CHK((messenger1 < messenger2) == (fake1 < fake2));
243}
244
245/*
246	bool operator<(const BMessenger &a, const BMessenger &b)
247	@case 1			set fields of a and b manually
248	@results		should return whatever the reference implementation
249					returns.
250 */
251void MessengerComparissonTester::LessTest1()
252{
253	port_id ports[] = { -1, 0, 1 } ;
254	int32 tokens[] = { -1, 0, 1 } ;
255	team_id teams[] = { -1, 0, 1 } ;
256	bool preferreds[] = { false, true } ;
257	int32 portCount = sizeof(ports) / sizeof(port_id);
258	int32 tokenCount = sizeof(tokens) / sizeof(int32);
259	int32 teamCount = sizeof(teams) / sizeof(team_id);
260	int32 preferredCount = 2;
261	for (int32 p1 = 0; p1 < portCount; p1++) {
262		port_id port1 = ports[p1];
263		for (int32 to1 = 0; to1 < tokenCount; to1++) {
264			int32 token1 = tokens[to1];
265			for (int32 te1 = 0; te1 < teamCount; te1++) {
266				team_id team1 = teams[te1];
267				for (int32 pr1 = 0; pr1 < preferredCount; pr1++) {
268					bool preferred1 = preferreds[pr1];
269					FakeMessenger fake1;
270					fake1.fPort = port1;
271					fake1.fHandlerToken = token1;
272					fake1.fTeam = team1;
273					fake1.fPreferredTarget = preferred1;
274					BMessenger &messenger1 = *(BMessenger*)&fake1;
275					for (int32 p2 = 0; p2 < portCount; p2++) {
276						port_id port2 = ports[p2];
277						for (int32 to2 = 0; to2 < tokenCount; to2++) {
278							int32 token2 = tokens[to2];
279							for (int32 te2 = 0; te2 < teamCount; te2++) {
280								team_id team2 = teams[te2];
281								for (int32 pr2 = 0; pr2 < preferredCount;
282									 pr2++) {
283									bool preferred2 = preferreds[pr2];
284									FakeMessenger fake2;
285									fake2.fPort = port2;
286									fake2.fHandlerToken = token2;
287									fake2.fTeam = team2;
288									fake2.fPreferredTarget = preferred2;
289									BMessenger &messenger2
290										= *(BMessenger*)&fake2;
291									Compare(fake1, fake2, messenger1,
292											messenger2);
293								}
294							}
295						}
296					}
297				}
298			}
299		}
300	}
301}
302
303
304Test* MessengerComparissonTester::Suite()
305{
306	typedef BThreadedTestCaller<MessengerComparissonTester> TC;
307
308	TestSuite* testSuite = new TestSuite;
309
310	ADD_TEST4(BMessenger, testSuite, MessengerComparissonTester, ComparissonTest1);
311	ADD_TEST4(BMessenger, testSuite, MessengerComparissonTester, ComparissonTest2);
312	ADD_TEST4(BMessenger, testSuite, MessengerComparissonTester, ComparissonTest3);
313	ADD_TEST4(BMessenger, testSuite, MessengerComparissonTester, LessTest1);
314
315	return testSuite;
316}
317
318
319