xref: /haiku/src/tests/kits/app/blooper/IsMessageWaitingTest.cpp (revision 268f99dd7dc4bd7474a8bd2742d3f1ec1de6752a)
1 //------------------------------------------------------------------------------
2 //	IsMessageWaitingTest.cpp
3 //
4 //------------------------------------------------------------------------------
5 
6 // Standard Includes -----------------------------------------------------------
7 #include <iostream>
8 #include <posix/string.h>
9 
10 // System Includes -------------------------------------------------------------
11 #include <Looper.h>
12 #include <Message.h>
13 #include <MessageQueue.h>
14 
15 // Project Includes ------------------------------------------------------------
16 
17 // Local Includes --------------------------------------------------------------
18 #include "IsMessageWaitingTest.h"
19 
20 // Local Defines ---------------------------------------------------------------
21 
22 // Globals ---------------------------------------------------------------------
23 port_id _get_looper_port_(const BLooper* looper);
24 
25 //------------------------------------------------------------------------------
26 /**
27 	IsMessageWaiting()
28 	@case		looper is unlocked and queue is empty
29 	@results	IsMessageWaiting() returns false
30  */
IsMessageWaiting1()31 void TIsMessageWaitingTest::IsMessageWaiting1()
32 {
33 	DEBUGGER_ESCAPE;
34 
35 	BLooper Looper;
36 	Looper.Unlock();
37 	CPPUNIT_ASSERT(!Looper.IsMessageWaiting());
38 }
39 //------------------------------------------------------------------------------
40 /**
41 	IsMessageWaiting()
42 	@case		looper is unlocked and queue is filled
43 	@results	IsMessageWaiting() returns false
44  */
IsMessageWaiting2()45 void TIsMessageWaitingTest::IsMessageWaiting2()
46 {
47 	DEBUGGER_ESCAPE;
48 
49 	BLooper Looper;
50 	Looper.Unlock();
51 	Looper.PostMessage('1234');
52 	CPPUNIT_ASSERT(!Looper.IsMessageWaiting());
53 }
54 //------------------------------------------------------------------------------
55 /**
56 	IsMessageWaiting()
57 	@case		looper is locked and queue is empty
58 	@results	IsMessageWaiting() returns false
59 	@note		R5 will return true in this test.  The extra testing below
60 				indicates that the R5 version probably returns != 0 from
61 				port_buffer_size_etc(), resulting in an incorrect true in cases
62 				where the operation would block.
63  */
IsMessageWaiting3()64 void TIsMessageWaitingTest::IsMessageWaiting3()
65 {
66 	BLooper Looper;
67 	Looper.Lock();
68 #ifndef TEST_R5
69 	CPPUNIT_ASSERT(!Looper.IsMessageWaiting());
70 #else
71 #if 0
72 	// Testing to figure out why we get false positives from the R5
73 	// implementation of BLooper::IsMessageWaiting().  Basically, it tests for
74 	// port_buffer_size_etc() != 0 -- which means that return values like
75 	// B_WOULD_BLOCK make the function return true, which is just not correct.
76 	CPPUNIT_ASSERT(Looper.IsLocked());
77 	CPPUNIT_ASSERT(Looper.MessageQueue()->IsEmpty());
78 
79 	int32 count;
80 	do
81 	{
82 		count = port_buffer_size_etc(_get_looper_port_(&Looper), B_TIMEOUT, 0);
83 	} while (count == B_INTERRUPTED);
84 
85 	CPPUNIT_ASSERT(count < 0);
86 	cout << endl << "port_buffer_size_etc: " << strerror(count) << endl;
87 #endif
88 	CPPUNIT_ASSERT(Looper.IsMessageWaiting());
89 #endif
90 }
91 //------------------------------------------------------------------------------
92 /**
93 	IsMessageWaiting()
94 	@case		looper is locked and queue is filled
95 	@results	IsMessageWaiting() returns true.
96  */
IsMessageWaiting4()97 void TIsMessageWaitingTest::IsMessageWaiting4()
98 {
99 	BLooper Looper;
100 	Looper.Lock();
101 	Looper.PostMessage('1234');
102 	CPPUNIT_ASSERT(Looper.IsMessageWaiting());
103 }
104 //------------------------------------------------------------------------------
105 /**
106 	IsMessageWaiting()
107 	@case		looper is locked, message is posted, queue is empty
108 	@results	IsMessageWaiting() returns true.
109 	@note		The first assert always worked under R5 but only sometimes for
110 				Haiku.  Answer: the Haiku implementation of BLooper was attempting
111 				to lock itself prior to fetching the message from the queue.  I
112 				moved the lock attempt after the fetch and it worked the same.
113 				I realized that if the system was loaded heavily enough, the
114 				assert might still fail simply because the looper would not have
115 				had enough time to get to the fetch (thereby emptying the queue),
116 				so the assert is no longer used.  If we do manage to call
117 				IsMessageWaiting() before the fetch happens (which does happen
118 				every once in a while), we still get a true result because the
119 				port buffer is checked.  Later: it's finally dawned on me that
120 				if the system is loaded *lightly* enough, the message will not
121 				only get fetched, but popped off the queue as well.  Since R5
122 				returns the bogus true, the second assert works even when the
123 				message has been de-queued.  Haiku, of course, will (correctly)
124 				fail the assert in that situation.  Unfortunately, that renders
125 				this test completely unreliable.  It is pulled until a fully
126 				reliable test can be devised.
127  */
IsMessageWaiting5()128 void TIsMessageWaitingTest::IsMessageWaiting5()
129 {
130 	BLooper* Looper = new BLooper(__PRETTY_FUNCTION__);
131 	Looper->Run();
132 
133 	// Prevent a port read
134 	Looper->Lock();
135 	Looper->PostMessage('1234');
136 //	CPPUNIT_ASSERT(Looper->MessageQueue()->IsEmpty());
137 	CPPUNIT_ASSERT(Looper->IsMessageWaiting());
138 
139 #if 0
140 	ssize_t count;
141 	do
142 	{
143 		count = port_buffer_size_etc(_get_looper_port_(Looper), B_TIMEOUT, 0);
144 	} while (count == B_INTERRUPTED);
145 
146 	cout << endl << "port_buffer_size_etc: ";
147 	if (count < 0)
148 	{
149 		cout << strerror(count);
150 	}
151 	else
152 	{
153 		cout << count << endl;
154 		char* buffer = new char[count];
155 		int32 code;
156 		read_port(_get_looper_port_(Looper), &code, (void*)buffer, count);
157 		cout << "code: " << code << endl;
158 		cout << "buffer: ";
159 		for (int32 i = 0; i < count; ++i)
160 		{
161 			cout << buffer[i];
162 		}
163 		cout << endl;
164 	}
165 	cout << endl;
166 #endif
167 }
168 //------------------------------------------------------------------------------
Suite()169 Test* TIsMessageWaitingTest::Suite()
170 {
171 	TestSuite* suite = new TestSuite("BLooper::IsMessageWaiting()");
172 
173 	ADD_TEST4(BLooper, suite, TIsMessageWaitingTest, IsMessageWaiting1);
174 	ADD_TEST4(BLooper, suite, TIsMessageWaitingTest, IsMessageWaiting2);
175 	ADD_TEST4(BLooper, suite, TIsMessageWaitingTest, IsMessageWaiting3);
176 	ADD_TEST4(BLooper, suite, TIsMessageWaitingTest, IsMessageWaiting4);
177 
178 	// See note for test
179 //	ADD_TEST4(BLooper, suite, TIsMessageWaitingTest, IsMessageWaiting5);
180 
181 	return suite;
182 }
183 //------------------------------------------------------------------------------
184 
185 /*
186  * $Log $
187  *
188  * $Id  $
189  *
190  */
191 
192 
193