blob: 4db9a0ef332b28d8ed84ff18caa7f4a8ac145156 [file] [log] [blame]
Alexander Afanasyevabe952a2013-01-17 17:06:32 -08001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2013 University of California, Los Angeles
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
19 * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
20 */
21
22#include "scheduler.h"
23#include "simple-interval-generator.h"
24#include "one-time-task.h"
25#include "periodic-task.h"
26#include "random-interval-generator.h"
Zhenkai Zhubc2f6282013-01-08 16:40:58 -080027
28#include <boost/test/unit_test.hpp>
29#include <map>
30#include <unistd.h>
31
32using namespace boost;
33using namespace std;
34
35BOOST_AUTO_TEST_SUITE(SchedulerTests)
36
37map<string, int> table;
38
39void func(string str)
40{
41 map<string, int>::iterator it = table.find(str);
42 if (it == table.end())
43 {
44 table.insert(make_pair(str, 1));
45 }
46 else
47 {
48 int count = it->second;
49 count++;
50 table.erase(it);
51 table.insert(make_pair(str, count));
52 }
53}
54
55bool
56matcher(const TaskPtr &task)
57{
58 return task->tag() == "period" || task->tag() == "world";
59}
60
61BOOST_AUTO_TEST_CASE(SchedulerTest)
62{
63 SchedulerPtr scheduler(new Scheduler());
64 IntervalGeneratorPtr generator(new SimpleIntervalGenerator(0.2));
65
66 string tag1 = "hello";
67 string tag2 = "world";
68 string tag3 = "period";
69
Zhenkai Zhu66dc5a92013-01-08 21:41:15 -080070 TaskPtr task1(new OneTimeTask(boost::bind(func, tag1), tag1, scheduler, 0.5));
71 TaskPtr task2(new OneTimeTask(boost::bind(func, tag2), tag2, scheduler, 0.5));
72 TaskPtr task3(new PeriodicTask(boost::bind(func, tag3), tag3, scheduler, generator));
Zhenkai Zhubc2f6282013-01-08 16:40:58 -080073
74 scheduler->start();
Zhenkai Zhu66dc5a92013-01-08 21:41:15 -080075 scheduler->addTask(task1);
76 scheduler->addTask(task2);
Zhenkai Zhubc2f6282013-01-08 16:40:58 -080077 scheduler->addTask(task3);
78 BOOST_CHECK_EQUAL(scheduler->size(), 3);
79 usleep(600000);
80 BOOST_CHECK_EQUAL(scheduler->size(), 1);
Zhenkai Zhu66dc5a92013-01-08 21:41:15 -080081 scheduler->addTask(task1);
Zhenkai Zhubc2f6282013-01-08 16:40:58 -080082 BOOST_CHECK_EQUAL(scheduler->size(), 2);
83 usleep(600000);
Zhenkai Zhu66dc5a92013-01-08 21:41:15 -080084 scheduler->addTask(task1);
Zhenkai Zhubc2f6282013-01-08 16:40:58 -080085 BOOST_CHECK_EQUAL(scheduler->size(), 2);
86 usleep(400000);
87 scheduler->deleteTask(task1->tag());
88 BOOST_CHECK_EQUAL(scheduler->size(), 1);
89 usleep(200000);
90
Zhenkai Zhu66dc5a92013-01-08 21:41:15 -080091 scheduler->addTask(task1);
92 scheduler->addTask(task2);
Zhenkai Zhubc2f6282013-01-08 16:40:58 -080093 BOOST_CHECK_EQUAL(scheduler->size(), 3);
94 usleep(100000);
95 scheduler->deleteTask(bind(matcher, _1));
96 BOOST_CHECK_EQUAL(scheduler->size(), 1);
Zhenkai Zhu06b8e952013-01-15 12:21:15 -080097 usleep(1000000);
Zhenkai Zhubc2f6282013-01-08 16:40:58 -080098
Zhenkai Zhud2ca3922013-01-18 17:58:48 -080099 BOOST_CHECK_EQUAL(scheduler->size(), 0);
100 scheduler->addTask(task1);
101 usleep(400000);
102 BOOST_CHECK_EQUAL(scheduler->size(), 1);
103 scheduler->rescheduleTask(task1);
104 usleep(400000);
105 BOOST_CHECK_EQUAL(scheduler->size(), 1);
106 usleep(110000);
107 BOOST_CHECK_EQUAL(scheduler->size(), 0);
108
Zhenkai Zhubc2f6282013-01-08 16:40:58 -0800109
Zhenkai Zhu06b8e952013-01-15 12:21:15 -0800110 int hello = 0, world = 0, period = 0;
Zhenkai Zhubc2f6282013-01-08 16:40:58 -0800111
112 map<string, int>::iterator it;
113 it = table.find(tag1);
114 if (it != table.end())
115 {
116 hello = it->second;
117 }
118 it = table.find(tag2);
119 if (it != table.end())
120 {
121 world = it->second;
122 }
123 it = table.find(tag3);
124 if (it != table.end())
125 {
126 period = it->second;
127 }
128
Zhenkai Zhud2ca3922013-01-18 17:58:48 -0800129 // added five times, canceled once before invoking callback
130 BOOST_CHECK_EQUAL(hello, 4);
Zhenkai Zhubc2f6282013-01-08 16:40:58 -0800131 // added two times, canceled once by matcher before invoking callback
132 BOOST_CHECK_EQUAL(world, 1);
133 // invoked every 0.2 seconds before deleted by matcher
134 BOOST_CHECK_EQUAL(period, static_cast<int>((0.6 + 0.6 + 0.4 + 0.2 + 0.1) / 0.2));
Zhenkai Zhubc2f6282013-01-08 16:40:58 -0800135
Zhenkai Zhuf8e81e02013-01-15 16:02:47 -0800136 scheduler->shutdown();
Zhenkai Zhubc2f6282013-01-08 16:40:58 -0800137}
138
139BOOST_AUTO_TEST_CASE(GeneratorTest)
140{
141 double interval = 10;
142 double percent = 0.5;
143 int times = 10000;
144 IntervalGeneratorPtr generator(new RandomIntervalGenerator(interval, percent));
145 double sum = 0.0;
146 double min = 2 * interval;
147 double max = -1;
148 for (int i = 0; i < times; i++)
149 {
150 double next = generator->nextInterval();
151 sum += next;
152 if (next > max)
153 {
154 max = next;
155 }
156 if (next < min)
157 {
158 min = next;
159 }
160 }
161
162 BOOST_CHECK( abs(1.0 - (sum / static_cast<double>(times)) / interval) < 0.05);
163 BOOST_CHECK( min > interval * (1 - percent / 2.0));
164 BOOST_CHECK( max < interval * (1 + percent / 2.0));
165 BOOST_CHECK( abs(1.0 - ((max - min) / interval) / percent) < 0.05);
166
167}
168
169BOOST_AUTO_TEST_SUITE_END()