blob: fe56d312496f26833a80ad0f7af27d264ac63d7b [file] [log] [blame]
Marc Slemko6f038a72006-08-03 18:58:09 +00001#include <concurrency/TimerManager.h>
2#include <concurrency/PosixThreadFactory.h>
3#include <concurrency/Monitor.h>
4#include <concurrency/Util.h>
Marc Slemko8a40a762006-07-19 17:46:50 +00005
6#include <assert.h>
7#include <iostream>
8
9namespace facebook { namespace thrift { namespace concurrency { namespace test {
10
11using namespace facebook::thrift::concurrency;
12
13/** ThreadManagerTests class
14
15 @author marc
16 @version $Id:$ */
17
18class TimerManagerTests {
19
Marc Slemko6f038a72006-08-03 18:58:09 +000020 public:
21
22 static const double ERROR;
23
Marc Slemko8a40a762006-07-19 17:46:50 +000024 class Task: public Runnable {
25
26 public:
27
Marc Slemko6f038a72006-08-03 18:58:09 +000028 Task(Monitor& monitor, long long timeout) :
29 _timeout(timeout),
30 _startTime(Util::currentTime()),
31 _monitor(monitor),
32 _success(false),
Marc Slemko8a40a762006-07-19 17:46:50 +000033 _done(false) {}
34
Marc Slemko6f038a72006-08-03 18:58:09 +000035 ~Task() {std::cerr << this << std::endl;}
36
Marc Slemko8a40a762006-07-19 17:46:50 +000037 void run() {
38
Marc Slemko9f27a4e2006-07-19 20:02:22 +000039 _endTime = Util::currentTime();
40
41 // Figure out error percentage
42
43 long long delta = _endTime - _startTime;
44
45
46 delta = delta > _timeout ? delta - _timeout : _timeout - delta;
47
48 float error = delta / _timeout;
49
Marc Slemko6f038a72006-08-03 18:58:09 +000050 if(error < ERROR) {
Marc Slemko9f27a4e2006-07-19 20:02:22 +000051 _success = true;
52 }
53
Marc Slemko8a40a762006-07-19 17:46:50 +000054 _done = true;
Marc Slemko6f038a72006-08-03 18:58:09 +000055
56 std::cout << "\t\t\tTimerManagerTests::Task[" << this << "] done" << std::endl; //debug
57
Marc Slemko8a40a762006-07-19 17:46:50 +000058 {Synchronized s(_monitor);
59 _monitor.notifyAll();
60 }
61 }
Marc Slemko9f27a4e2006-07-19 20:02:22 +000062
Marc Slemko6f038a72006-08-03 18:58:09 +000063
Marc Slemko9f27a4e2006-07-19 20:02:22 +000064
65 long long _timeout;
66 long long _startTime;
67 long long _endTime;
Marc Slemko8a40a762006-07-19 17:46:50 +000068 Monitor& _monitor;
Marc Slemko9f27a4e2006-07-19 20:02:22 +000069 bool _success;
Marc Slemko8a40a762006-07-19 17:46:50 +000070 bool _done;
71 };
72
Marc Slemko9f27a4e2006-07-19 20:02:22 +000073 /** This test creates two tasks and waits for the first to expire within 10% of the expected expiration time. It then verifies that
74 the timer manager properly clean up itself and the remaining orphaned timeout task when the manager goes out of scope and its
75 destructor is called. */
Marc Slemko8a40a762006-07-19 17:46:50 +000076
Marc Slemko9f27a4e2006-07-19 20:02:22 +000077 bool test00(long long timeout=1000LL) {
Marc Slemko8a40a762006-07-19 17:46:50 +000078
Marc Slemko6f038a72006-08-03 18:58:09 +000079 shared_ptr<TimerManagerTests::Task> orphanTask = shared_ptr<TimerManagerTests::Task>(new TimerManagerTests::Task(_monitor, 10 * timeout));
Marc Slemko8a40a762006-07-19 17:46:50 +000080
Marc Slemko9f27a4e2006-07-19 20:02:22 +000081 {
Marc Slemko8a40a762006-07-19 17:46:50 +000082
Marc Slemko9f27a4e2006-07-19 20:02:22 +000083 TimerManager timerManager;
84
Marc Slemko6f038a72006-08-03 18:58:09 +000085 timerManager.threadFactory(shared_ptr<PosixThreadFactory>(new PosixThreadFactory()));
Marc Slemko9f27a4e2006-07-19 20:02:22 +000086
87 timerManager.start();
88
89 assert(timerManager.state() == TimerManager::STARTED);
Marc Slemko8a40a762006-07-19 17:46:50 +000090
Marc Slemko6f038a72006-08-03 18:58:09 +000091 shared_ptr<TimerManagerTests::Task> task = shared_ptr<TimerManagerTests::Task>(new TimerManagerTests::Task(_monitor, timeout));
Marc Slemko8a40a762006-07-19 17:46:50 +000092
Marc Slemko9f27a4e2006-07-19 20:02:22 +000093 {Synchronized s(_monitor);
Marc Slemko8a40a762006-07-19 17:46:50 +000094
Marc Slemko9f27a4e2006-07-19 20:02:22 +000095 timerManager.add(orphanTask, 10 * timeout);
Marc Slemko8a40a762006-07-19 17:46:50 +000096
Marc Slemko9f27a4e2006-07-19 20:02:22 +000097 timerManager.add(task, timeout);
98
99 _monitor.wait();
100 }
101
102 assert(task->_done);
103
104
105 std::cout << "\t\t\t" << (task->_success ? "Success" : "Failure") << "!" << std::endl;
Marc Slemko8a40a762006-07-19 17:46:50 +0000106 }
107
Marc Slemko9f27a4e2006-07-19 20:02:22 +0000108 // timerManager.stop(); This is where it happens via destructor
Marc Slemko8a40a762006-07-19 17:46:50 +0000109
Marc Slemko9f27a4e2006-07-19 20:02:22 +0000110 assert(!orphanTask->_done);
Marc Slemko8a40a762006-07-19 17:46:50 +0000111
Marc Slemko8a40a762006-07-19 17:46:50 +0000112 return true;
113 }
114
115 friend class TestTask;
116
117 Monitor _monitor;
118};
Marc Slemko8a40a762006-07-19 17:46:50 +0000119
Marc Slemko6f038a72006-08-03 18:58:09 +0000120const double TimerManagerTests::ERROR = .20;
121
Marc Slemko8a40a762006-07-19 17:46:50 +0000122}}}} // facebook::thrift::concurrency
123