summaryrefslogtreecommitdiff
path: root/cpp/test/IceUtil/timer/Client.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/test/IceUtil/timer/Client.cpp')
-rw-r--r--cpp/test/IceUtil/timer/Client.cpp260
1 files changed, 260 insertions, 0 deletions
diff --git a/cpp/test/IceUtil/timer/Client.cpp b/cpp/test/IceUtil/timer/Client.cpp
new file mode 100644
index 00000000000..a46ec76551d
--- /dev/null
+++ b/cpp/test/IceUtil/timer/Client.cpp
@@ -0,0 +1,260 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#include <IceUtil/Timer.h>
+#include <TestCommon.h>
+
+#include <vector>
+
+using namespace IceUtil;
+using namespace std;
+
+class TestTask : public IceUtil::TimerTask, IceUtil::Monitor<IceUtil::Mutex>
+{
+public:
+
+ TestTask() : _count(0)
+ {
+ }
+
+ TestTask(const IceUtil::Time& scheduledTime) : _scheduledTime(scheduledTime), _count(0)
+ {
+ }
+
+ virtual void
+ runTimerTask()
+ {
+ Lock sync(*this);
+ ++_count;
+ _run = IceUtil::Time::now(IceUtil::Time::Monotonic);
+ //cerr << "run: " << _scheduledTime.toMilliSeconds() << " " << _run.toMilliSeconds() << endl;
+ notifyAll();
+ }
+
+ virtual bool
+ operator<(const TestTask& r) const
+ {
+ return _scheduledTime < r._scheduledTime;
+ }
+
+ virtual bool
+ hasRun() const
+ {
+ Lock sync(*this);
+ return _run != IceUtil::Time();
+ }
+
+ int
+ getCount() const
+ {
+ Lock sync(*this);
+ return _count;
+ }
+
+ virtual IceUtil::Time
+ getRunTime() const
+ {
+ Lock sync(*this);
+ return _run;
+ }
+
+ IceUtil::Time
+ getScheduledTime() const
+ {
+ return _scheduledTime;
+ }
+
+ virtual void
+ waitForRun()
+ {
+ Lock sync(*this);
+ while(_run == IceUtil::Time())
+ {
+ if(!timedWait(IceUtil::Time::seconds(10)))
+ {
+ test(false); // Timeout.
+ }
+ }
+ }
+
+ void
+ clear()
+ {
+ _run = IceUtil::Time();
+ _count = 0;
+ }
+
+private:
+
+ IceUtil::Time _run;
+ IceUtil::Time _scheduledTime;
+ int _count;
+};
+typedef IceUtil::Handle<TestTask> TestTaskPtr;
+
+
+class DestroyTask : public IceUtil::TimerTask, IceUtil::Monitor<IceUtil::Mutex>
+{
+public:
+
+ DestroyTask(const IceUtil::TimerPtr& timer) : _timer(timer), _run(false)
+ {
+ }
+
+ virtual void
+ runTimerTask()
+ {
+ Lock sync(*this);
+ _timer->destroy();
+ _run = true;
+ notify();
+ }
+
+ virtual void
+ waitForRun()
+ {
+ Lock sync(*this);
+ while(!_run)
+ {
+ if(!timedWait(IceUtil::Time::seconds(10)))
+ {
+ test(false); // Timeout.
+ }
+ }
+ }
+
+private:
+
+ IceUtil::TimerPtr _timer;
+ bool _run;
+};
+typedef IceUtil::Handle<DestroyTask> DestroyTaskPtr;
+
+int main(int argc, char* argv[])
+{
+ cout << "testing timer... " << flush;
+ {
+ IceUtil::TimerPtr timer = new IceUtil::Timer();
+
+ {
+ TestTaskPtr task = new TestTask();
+ timer->schedule(task, IceUtil::Time());
+ task->waitForRun();
+ task->clear();
+
+ //
+ // Verify that the same task cannot be scheduled more than once.
+ //
+ timer->schedule(task, IceUtil::Time::milliSeconds(100));
+ try
+ {
+ timer->schedule(task, IceUtil::Time());
+ }
+ catch(const IceUtil::IllegalArgumentException&)
+ {
+ // Expected.
+ }
+ task->waitForRun();
+ task->clear();
+ }
+
+ {
+ TestTaskPtr task = new TestTask();
+ test(!timer->cancel(task));
+ timer->schedule(task, IceUtil::Time::seconds(1));
+ test(!task->hasRun() && timer->cancel(task) && !task->hasRun());
+ test(!timer->cancel(task));
+ IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(1100));
+ test(!task->hasRun());
+ }
+
+ {
+ vector<TestTaskPtr> tasks;
+ IceUtil::Time start = IceUtil::Time::now(IceUtil::Time::Monotonic) + IceUtil::Time::milliSeconds(500);
+ for(int i = 0; i < 20; ++i)
+ {
+ tasks.push_back(new TestTask(IceUtil::Time::milliSeconds(500 + i * 5)));
+ }
+
+ random_shuffle(tasks.begin(), tasks.end());
+ vector<TestTaskPtr>::const_iterator p;
+ for(p = tasks.begin(); p != tasks.end(); ++p)
+ {
+ timer->schedule(*p, (*p)->getScheduledTime());
+ }
+
+ for(p = tasks.begin(); p != tasks.end(); ++p)
+ {
+ (*p)->waitForRun();
+ }
+
+ test(IceUtil::Time::now(IceUtil::Time::Monotonic) > start);
+
+ sort(tasks.begin(), tasks.end());
+ for(p = tasks.begin(); p + 1 != tasks.end(); ++p)
+ {
+ if((*p)->getRunTime() > (*(p + 1))->getRunTime())
+ {
+ test(false);
+ }
+ }
+ }
+
+ {
+ TestTaskPtr task = new TestTask();
+ timer->scheduleRepeated(task, IceUtil::Time::milliSeconds(20));
+ IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(500));
+ test(task->hasRun());
+ test(task->getCount() > 1);
+ test(task->getCount() < 26);
+ test(timer->cancel(task));
+ int count = task->getCount();
+ IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(100));
+ test(count == task->getCount() || count + 1 == task->getCount());
+ }
+
+ timer->destroy();
+ }
+ cout << "ok" << endl;
+
+ cout << "testing timer destroy... " << flush;
+ {
+ {
+ IceUtil::TimerPtr timer = new IceUtil::Timer();
+ DestroyTaskPtr destroyTask = new DestroyTask(timer);
+ timer->schedule(destroyTask, IceUtil::Time());
+ destroyTask->waitForRun();
+ try
+ {
+ timer->schedule(destroyTask, IceUtil::Time());
+ }
+ catch(const IceUtil::IllegalArgumentException&)
+ {
+ // Expected;
+ }
+ }
+ {
+ IceUtil::TimerPtr timer = new IceUtil::Timer();
+ TestTaskPtr testTask = new TestTask();
+ timer->schedule(testTask, IceUtil::Time());
+ timer->destroy();
+ try
+ {
+ timer->schedule(testTask, IceUtil::Time());
+ }
+ catch(const IceUtil::IllegalArgumentException&)
+ {
+ // Expected;
+ }
+ }
+ }
+ cout << "ok" << endl;
+
+ return EXIT_SUCCESS;
+}