00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <gtest/gtest.h>
00037 #include <ros/callback_queue.h>
00038 #include <ros/console.h>
00039
00040 #include <boost/shared_ptr.hpp>
00041 #include <boost/bind.hpp>
00042 #include <boost/thread.hpp>
00043 #include <boost/function.hpp>
00044
00045 using namespace ros;
00046
00047 class CountingCallback : public CallbackInterface
00048 {
00049 public:
00050 CountingCallback()
00051 : count(0)
00052 {}
00053
00054 virtual CallResult call()
00055 {
00056 boost::mutex::scoped_lock lock(mutex);
00057 ++count;
00058
00059 return Success;
00060 }
00061
00062 boost::mutex mutex;
00063 size_t count;
00064 };
00065 typedef boost::shared_ptr<CountingCallback> CountingCallbackPtr;
00066
00067 TEST(CallbackQueue, singleCallback)
00068 {
00069 CountingCallbackPtr cb(new CountingCallback);
00070 CallbackQueue queue;
00071 queue.addCallback(cb, 1);
00072 queue.callOne();
00073
00074 EXPECT_EQ(cb->count, 1U);
00075
00076 queue.addCallback(cb, 1);
00077 queue.callAvailable();
00078
00079 EXPECT_EQ(cb->count, 2U);
00080
00081 queue.callOne();
00082 EXPECT_EQ(cb->count, 2U);
00083
00084 queue.callAvailable();
00085 EXPECT_EQ(cb->count, 2U);
00086 }
00087
00088 TEST(CallbackQueue, multipleCallbacksCallAvailable)
00089 {
00090 CountingCallbackPtr cb(new CountingCallback);
00091 CallbackQueue queue;
00092 for (uint32_t i = 0; i < 1000; ++i)
00093 {
00094 queue.addCallback(cb, 1);
00095 }
00096
00097 queue.callAvailable();
00098
00099 EXPECT_EQ(cb->count, 1000U);
00100 }
00101
00102 TEST(CallbackQueue, multipleCallbacksCallOne)
00103 {
00104 CountingCallbackPtr cb(new CountingCallback);
00105 CallbackQueue queue;
00106 for (uint32_t i = 0; i < 1000; ++i)
00107 {
00108 queue.addCallback(cb, 1);
00109 }
00110
00111 for (uint32_t i = 0; i < 1000; ++i)
00112 {
00113 queue.callOne();
00114 EXPECT_EQ(cb->count, i + 1);
00115 }
00116 }
00117
00118 TEST(CallbackQueue, remove)
00119 {
00120 CountingCallbackPtr cb1(new CountingCallback);
00121 CountingCallbackPtr cb2(new CountingCallback);
00122 CallbackQueue queue;
00123 queue.addCallback(cb1, 1);
00124 queue.addCallback(cb2, 2);
00125 queue.removeByID(1);
00126 queue.callAvailable();
00127
00128 EXPECT_EQ(cb1->count, 0U);
00129 EXPECT_EQ(cb2->count, 1U);
00130 }
00131
00132 class SelfRemovingCallback : public CallbackInterface
00133 {
00134 public:
00135 SelfRemovingCallback(CallbackQueue* queue, uint64_t id)
00136 : count(0)
00137 , queue(queue)
00138 , id(id)
00139 {}
00140
00141 virtual CallResult call()
00142 {
00143 ++count;
00144
00145 queue->removeByID(id);
00146
00147 return Success;
00148 }
00149
00150 size_t count;
00151
00152 CallbackQueue* queue;
00153 uint64_t id;
00154 };
00155 typedef boost::shared_ptr<SelfRemovingCallback> SelfRemovingCallbackPtr;
00156
00157 TEST(CallbackQueue, removeSelf)
00158 {
00159 CallbackQueue queue;
00160 SelfRemovingCallbackPtr cb(new SelfRemovingCallback(&queue, 1));
00161 queue.addCallback(cb, 1);
00162 queue.addCallback(cb, 1);
00163 queue.addCallback(cb, 1);
00164
00165 queue.callAvailable();
00166
00167 EXPECT_EQ(cb->count, 1U);
00168 }
00169
00170 class RecursiveCallback : public CallbackInterface
00171 {
00172 public:
00173 RecursiveCallback(CallbackQueue* queue, bool use_available)
00174 : count(0)
00175 , queue(queue)
00176 , use_available(use_available)
00177 {}
00178
00179 virtual CallResult call()
00180 {
00181 ++count;
00182
00183 if (count < 3)
00184 {
00185 if (use_available)
00186 {
00187 queue->callAvailable();
00188 }
00189 else
00190 {
00191 queue->callOne();
00192 }
00193 }
00194
00195 return Success;
00196 }
00197
00198 size_t count;
00199
00200 CallbackQueue* queue;
00201 bool use_available;
00202 };
00203 typedef boost::shared_ptr<RecursiveCallback> RecursiveCallbackPtr;
00204
00205 TEST(CallbackQueue, recursive1)
00206 {
00207 CallbackQueue queue;
00208 RecursiveCallbackPtr cb(new RecursiveCallback(&queue, true));
00209 queue.addCallback(cb, 1);
00210 queue.addCallback(cb, 1);
00211 queue.addCallback(cb, 1);
00212 queue.callAvailable();
00213
00214 EXPECT_EQ(cb->count, 3U);
00215 }
00216
00217 TEST(CallbackQueue, recursive2)
00218 {
00219 CallbackQueue queue;
00220 RecursiveCallbackPtr cb(new RecursiveCallback(&queue, false));
00221 queue.addCallback(cb, 1);
00222 queue.addCallback(cb, 1);
00223 queue.addCallback(cb, 1);
00224 queue.callOne();
00225
00226 EXPECT_EQ(cb->count, 3U);
00227 }
00228
00229 TEST(CallbackQueue, recursive3)
00230 {
00231 CallbackQueue queue;
00232 RecursiveCallbackPtr cb(new RecursiveCallback(&queue, false));
00233 queue.addCallback(cb, 1);
00234 queue.addCallback(cb, 1);
00235 queue.addCallback(cb, 1);
00236 queue.callAvailable();
00237
00238 EXPECT_EQ(cb->count, 3U);
00239 }
00240
00241 TEST(CallbackQueue, recursive4)
00242 {
00243 CallbackQueue queue;
00244 RecursiveCallbackPtr cb(new RecursiveCallback(&queue, true));
00245 queue.addCallback(cb, 1);
00246 queue.addCallback(cb, 1);
00247 queue.addCallback(cb, 1);
00248 queue.callOne();
00249
00250 EXPECT_EQ(cb->count, 3U);
00251 }
00252
00253 void callAvailableThread(CallbackQueue* queue, bool& done)
00254 {
00255 while (!done)
00256 {
00257 queue->callAvailable(ros::WallDuration(0.1));
00258 }
00259 }
00260
00261 size_t runThreadedTest(const CountingCallbackPtr& cb, const boost::function<void(CallbackQueue*, bool&)>& threadFunc)
00262 {
00263 CallbackQueue queue;
00264 boost::thread_group tg;
00265 bool done = false;
00266
00267 for (uint32_t i = 0; i < 10; ++i)
00268 {
00269 tg.create_thread(boost::bind(threadFunc, &queue, boost::ref(done)));
00270 }
00271
00272 ros::WallTime start = ros::WallTime::now();
00273 size_t i = 0;
00274 while (ros::WallTime::now() - start < ros::WallDuration(5))
00275 {
00276 queue.addCallback(cb);
00277 ++i;
00278 }
00279
00280 while (!queue.isEmpty())
00281 {
00282 ros::WallDuration(0.01).sleep();
00283 }
00284
00285 done = true;
00286 tg.join_all();
00287
00288 return i;
00289 }
00290
00291 TEST(CallbackQueue, threadedCallAvailable)
00292 {
00293 CountingCallbackPtr cb(new CountingCallback);
00294 size_t i = runThreadedTest(cb, callAvailableThread);
00295 ROS_INFO_STREAM(i);
00296 EXPECT_EQ(cb->count, i);
00297 }
00298
00299 void callOneThread(CallbackQueue* queue, bool& done)
00300 {
00301 while (!done)
00302 {
00303 queue->callOne(ros::WallDuration(0.1));
00304 }
00305 }
00306
00307 TEST(CallbackQueue, threadedCallOne)
00308 {
00309 CountingCallbackPtr cb(new CountingCallback);
00310 size_t i = runThreadedTest(cb, callOneThread);
00311 ROS_INFO_STREAM(i);
00312 EXPECT_EQ(cb->count, i);
00313 }
00314
00315 int main(int argc, char** argv)
00316 {
00317 testing::InitGoogleTest(&argc, argv);
00318 return RUN_ALL_TESTS();
00319 }
00320
00321
00322