1 |
schoenebeck |
63 |
#include "ConditionTest.h" |
2 |
|
|
|
3 |
|
|
#include <iostream> |
4 |
|
|
|
5 |
|
|
CPPUNIT_TEST_SUITE_REGISTRATION(ConditionTest); |
6 |
|
|
|
7 |
schoenebeck |
211 |
using namespace std; |
8 |
schoenebeck |
63 |
|
9 |
schoenebeck |
211 |
|
10 |
schoenebeck |
63 |
// ConditionChecker |
11 |
|
|
|
12 |
schoenebeck |
503 |
ConditionTest::ConditionChecker::ConditionChecker(bool waitFor) : Thread(false, false, 0, -4) { |
13 |
schoenebeck |
63 |
resource = 0; |
14 |
|
|
this->waitFor = waitFor; |
15 |
|
|
} |
16 |
|
|
|
17 |
|
|
int ConditionTest::ConditionChecker::Main() { |
18 |
|
|
condition.WaitAndUnlockIf(!waitFor); |
19 |
|
|
resource++; |
20 |
|
|
} |
21 |
|
|
|
22 |
|
|
|
23 |
|
|
// ConditionSetter |
24 |
|
|
|
25 |
schoenebeck |
503 |
ConditionTest::ConditionSetter::ConditionSetter(Condition* condition, bool toSet) : Thread(false, false, 0, -4) { |
26 |
schoenebeck |
63 |
resource = 0; |
27 |
|
|
this->toSet = toSet; |
28 |
|
|
this->condition = condition; |
29 |
|
|
} |
30 |
|
|
|
31 |
|
|
int ConditionTest::ConditionSetter::Main() { |
32 |
|
|
condition->Set(toSet); |
33 |
|
|
resource++; |
34 |
|
|
} |
35 |
|
|
|
36 |
|
|
|
37 |
|
|
// ConditionCheckerLocking |
38 |
|
|
|
39 |
|
|
Condition ConditionTest::ConditionCheckerLocking::staticcondition; // we sheare the same Condition object between all instances of ConditionCheckerLocking |
40 |
|
|
|
41 |
|
|
ConditionTest::ConditionCheckerLocking::ConditionCheckerLocking(bool waitFor) : ConditionChecker(waitFor) { |
42 |
|
|
doUnlock = false; |
43 |
|
|
} |
44 |
|
|
|
45 |
|
|
int ConditionTest::ConditionCheckerLocking::Main() { |
46 |
|
|
staticcondition.WaitIf(!waitFor); |
47 |
|
|
resource++; |
48 |
nagata |
1649 |
while (!doUnlock) { |
49 |
|
|
usleep(1000); // sleep until ordered to unlock the condition again |
50 |
|
|
#if CONFIG_PTHREAD_TESTCANCEL |
51 |
|
|
TestCancel(); |
52 |
|
|
#endif |
53 |
|
|
} |
54 |
schoenebeck |
63 |
staticcondition.Unlock(); |
55 |
|
|
} |
56 |
|
|
|
57 |
|
|
|
58 |
|
|
// ConditionTest |
59 |
|
|
|
60 |
schoenebeck |
211 |
void ConditionTest::printTestSuiteName() { |
61 |
|
|
cout << "\b \nRunning Condition Tests: " << flush; |
62 |
|
|
} |
63 |
|
|
|
64 |
schoenebeck |
63 |
void ConditionTest::setUp() { |
65 |
|
|
} |
66 |
|
|
|
67 |
|
|
void ConditionTest::tearDown() { |
68 |
|
|
} |
69 |
|
|
|
70 |
|
|
|
71 |
|
|
// Check if Condition class doesn't block if desired condition is already reached |
72 |
|
|
void ConditionTest::testDoesntBlockOnDesiredCondtion() { |
73 |
|
|
ConditionChecker t(false); |
74 |
|
|
t.SignalStartThread(); |
75 |
|
|
usleep(200000); // wait 200ms |
76 |
|
|
CPPUNIT_ASSERT(t.resource == 1); |
77 |
|
|
} |
78 |
|
|
|
79 |
|
|
// Check if Condition class blocks if desired condition is not alredy reached |
80 |
|
|
void ConditionTest::testBlocksIfNotDesiredCondition() { |
81 |
|
|
ConditionChecker t(true); |
82 |
|
|
t.SignalStartThread(); |
83 |
|
|
usleep(400000); // wait 400ms |
84 |
|
|
CPPUNIT_ASSERT(t.resource == 0); |
85 |
|
|
} |
86 |
|
|
|
87 |
|
|
// Check if Condition class blocks until desired condition is reached |
88 |
|
|
void ConditionTest::testBlocksUntilDesiredCondition() { |
89 |
|
|
ConditionChecker checker(true); // let that thread wait until condition equals 'true' |
90 |
|
|
ConditionSetter setter(&checker.condition, true); // let this thread set the condition to 'true' |
91 |
|
|
checker.SignalStartThread(); |
92 |
|
|
usleep(50000); // wait 50ms |
93 |
|
|
CPPUNIT_ASSERT(checker.resource == 0); // check if 'checker' thread has not passed the WaitAndUnlockIf() point yet |
94 |
|
|
setter.SignalStartThread(); |
95 |
|
|
usleep(100000); // wait 100ms |
96 |
|
|
CPPUNIT_ASSERT(checker.resource == 1); // check if 'checker' thread passed the WaitAndUnlockIf() point |
97 |
|
|
} |
98 |
|
|
|
99 |
|
|
// Check if the WaitIf() call blocks concurrent threads until the first WaitIf() caller calls Unlock() |
100 |
|
|
void ConditionTest::testWaitIFBlocksConcurrentThread() { |
101 |
|
|
// if the following three tests fail, then it doesn't make sense to continue with the actual one here |
102 |
|
|
testDoesntBlockOnDesiredCondtion(); |
103 |
|
|
testBlocksIfNotDesiredCondition(); |
104 |
|
|
testBlocksUntilDesiredCondition(); |
105 |
|
|
|
106 |
|
|
// actual new test |
107 |
|
|
ConditionCheckerLocking checker1(false); |
108 |
|
|
ConditionCheckerLocking checker2(false); |
109 |
|
|
checker1.SignalStartThread(); |
110 |
|
|
usleep(200000); // wait 200ms |
111 |
|
|
CPPUNIT_ASSERT(checker1.resource == 1); |
112 |
|
|
checker2.SignalStartThread(); |
113 |
|
|
usleep(200000); // wait 200ms |
114 |
|
|
CPPUNIT_ASSERT(checker2.resource == 0); // check if condition locked by 'checker1' |
115 |
|
|
|
116 |
|
|
// now order 'checker1' thread to Unlock() the condition again |
117 |
|
|
checker1.doUnlock = true; |
118 |
|
|
usleep(200000); // wait 200ms |
119 |
|
|
CPPUNIT_ASSERT(checker2.resource == 1); // check if condition was unlocked by 'checker1' |
120 |
|
|
} |