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 #include <timestamp_tools/trigger_matcher.h>
00036 #include <gtest/gtest.h>
00037 #include <queue>
00038
00040
00041 class QueuedChecker
00042 {
00043 std::queue< std::pair<double, int> > incoming_;
00044
00045 public:
00046 timestamp_tools::QueuedTriggerMatcher<int> tm;
00047
00048 QueuedChecker() : tm(1, 10, 5)
00049 {
00050 tm.setTrigDelay(0.2);
00051 timestamp_tools::QueuedTriggerMatcher<int>::MatchCallback bound_cb = boost::bind(&QueuedChecker::callback, this, _1, _2);
00052 tm.setMatchCallback(bound_cb);
00053
00054
00055 tm.triggerCallback(0);
00056 expectEmpty(0);
00057 tm.dataCallback(1, 1);
00058 expectEmpty(1);
00059 tm.triggerCallback(2);
00060 expectHead(0.2, 1);
00061 expectEmpty(2);
00062 tm.dataCallback(3, 2);
00063 expectHead(2.2, 2);
00064 expectEmpty(3);
00065 }
00066
00067 void expectEmpty(double time)
00068 {
00069 EXPECT_TRUE(incoming_.empty()) << "QueuedChecker queue not empty at time " << time
00070 << " contains " << incoming_.front().first << ", " << incoming_.front().second;
00071 }
00072
00073 void expectHead(double time, int data)
00074 {
00075 if (incoming_.empty())
00076 {
00077 ADD_FAILURE() << "QueuedChecker queue empty when checking " << time << ", " << data;
00078 return;
00079 }
00080
00081 std::pair<double, int> &head = incoming_.front();
00082
00083 EXPECT_EQ(time, head.first) << "Timestamp mismatch when checking " << time << ", " << data;
00084 EXPECT_EQ(data, head.second) << "Data mismatch when checking " << time << ", " << data;
00085
00086 incoming_.pop();
00087 }
00088
00089 void callback(const ros::Time &time, const boost::shared_ptr<int const> &data)
00090 {
00091 incoming_.push(std::pair<double, int>(time.toSec(), *data));
00092 }
00093 };
00094
00095 TEST(QueuedTriggerMatcher, BasicFunctionality)
00096 {
00097 QueuedChecker c;
00098
00099
00100 c.tm.triggerCallback(4);
00101 c.expectEmpty(4);
00102 c.tm.triggerCallback(6);
00103 c.expectEmpty(6);
00104 c.tm.triggerCallback(8);
00105 c.expectEmpty(8);
00106 c.tm.dataCallback(5, 3);
00107 c.expectHead(4.2, 3);
00108 c.expectEmpty(5);
00109 c.tm.dataCallback(7, 4);
00110 c.expectHead(6.2, 4);
00111 c.expectEmpty(7);
00112 c.tm.dataCallback(9, 5);
00113 c.expectHead(8.2, 5);
00114 c.expectEmpty(9);
00115
00116
00117 c.tm.dataCallback(11, 6);
00118 c.expectEmpty(11);
00119 c.tm.dataCallback(13, 7);
00120 c.expectEmpty(13);
00121 c.tm.dataCallback(15, 8);
00122 c.expectEmpty(15);
00123 c.tm.triggerCallback(10);
00124 c.expectHead(10.2, 6);
00125 c.expectEmpty(10);
00126 c.tm.triggerCallback(12);
00127 c.expectHead(12.2, 7);
00128 c.expectEmpty(12);
00129 c.tm.triggerCallback(14);
00130 c.expectHead(14.2, 8);
00131 c.expectEmpty(14);
00132 }
00133
00134 TEST(QueuedTriggerMatcher, TestReset)
00135 {
00136 QueuedChecker c;
00137
00138 c.tm.triggerCallback(4);
00139 c.expectEmpty(4);
00140 c.tm.reset();
00141 c.tm.dataCallback(5, 3);
00142 c.expectEmpty(5);
00143 c.tm.triggerCallback(6);
00144 c.expectEmpty(6);
00145 c.tm.dataCallback(7, 4);
00146 c.expectEmpty(7);
00147 c.tm.triggerCallback(8);
00148 c.expectHead(6.2, 4);
00149 c.expectEmpty(8);
00150 c.tm.dataCallback(9, 5);
00151 c.expectHead(8.2, 5);
00152 c.expectEmpty(9);
00153
00154 c.tm.dataCallback(5, 3);
00155 c.expectEmpty(5);
00156 c.tm.reset();
00157 c.expectEmpty(5.1);
00158 c.tm.triggerCallback(4);
00159 c.expectEmpty(4);
00160 c.tm.triggerCallback(6);
00161 c.expectEmpty(6);
00162 c.tm.dataCallback(7, 4);
00163 c.expectEmpty(7);
00164 c.tm.triggerCallback(8);
00165 c.expectHead(6.2, 4);
00166 c.expectEmpty(8);
00167 c.tm.dataCallback(9, 5);
00168 c.expectHead(8.2, 5);
00169 c.expectEmpty(9);
00170 }
00171
00172 TEST(QueuedTriggerMatcher, MissingTrigger)
00173 {
00174 QueuedChecker c;
00175
00176
00177 c.tm.triggerCallback(6);
00178 c.expectEmpty(6);
00179 c.tm.triggerCallback(8);
00180 c.expectEmpty(8);
00181 c.tm.dataCallback(5, 3);
00182 c.expectEmpty(5);
00183 c.tm.dataCallback(7, 4);
00184 c.expectHead(6.2, 4);
00185 c.expectEmpty(7);
00186 c.tm.dataCallback(9, 5);
00187 c.expectHead(8.2, 5);
00188 c.expectEmpty(9);
00189 }
00190
00191 TEST(QueuedTriggerMatcher, MissingData)
00192 {
00193 QueuedChecker c;
00194
00195
00196 c.tm.triggerCallback(4);
00197 c.expectEmpty(4);
00198 c.tm.triggerCallback(6);
00199 c.expectEmpty(6);
00200 c.tm.triggerCallback(8);
00201 c.expectEmpty(8);
00202 c.tm.triggerCallback(10);
00203 c.expectEmpty(10);
00204 c.tm.triggerCallback(12);
00205 c.expectEmpty(12);
00206 c.tm.dataCallback(7, 4);
00207 c.expectHead(4.2, 4);
00208 c.expectEmpty(7);
00209 c.tm.dataCallback(9, 5);
00210 c.expectHead(8.2, 5);
00211 c.expectEmpty(9);
00212 c.tm.dataCallback(11, 6);
00213 c.expectHead(10.2, 6);
00214 c.expectEmpty(11);
00215 c.tm.dataCallback(13, 7);
00216 c.expectHead(12.2, 7);
00217 c.expectEmpty(13);
00218 }
00219
00220 TEST(QueuedTriggerMatcher, MissingDataZeroLateTolerance)
00221 {
00222 QueuedChecker c;
00223
00224 c.tm.setLateDataCountAllowed(0);
00225
00226
00227 c.tm.triggerCallback(4);
00228 c.expectEmpty(4);
00229 c.tm.triggerCallback(6);
00230 c.expectEmpty(6);
00231 c.tm.triggerCallback(8);
00232 c.expectEmpty(8);
00233 c.tm.triggerCallback(10);
00234 c.expectEmpty(10);
00235 c.tm.triggerCallback(12);
00236 c.expectEmpty(12);
00237 c.tm.triggerCallback(14);
00238 c.expectEmpty(14);
00239 c.tm.dataCallback(5, 4);
00240 c.expectHead(4.2, 4);
00241 c.expectEmpty(5);
00242 c.tm.dataCallback(9, 5);
00243 c.expectHead(8.2, 5);
00244 c.expectEmpty(9);
00245 c.tm.dataCallback(11, 6);
00246 c.expectHead(10.2, 6);
00247 c.expectEmpty(11);
00248 c.tm.dataCallback(13, 7);
00249 c.expectHead(12.2, 7);
00250 c.expectEmpty(13);
00251 }
00252
00253 TEST(QueuedTriggerMatcher, TriggerQueueOverflow)
00254 {
00255 QueuedChecker c;
00256
00257 double trig_time = 4;
00258 for (int i = 0; i < 15; i++)
00259 {
00260 c.tm.triggerCallback(trig_time);
00261 c.expectEmpty(trig_time);
00262 trig_time += 2;
00263 }
00264 c.tm.dataCallback(15, 15);
00265 c.expectHead(14.2, 15);
00266 c.expectEmpty(15);
00267 }
00268
00269 TEST(QueuedTriggerMatcher, DataQueueOverflow)
00270 {
00271 QueuedChecker c;
00272
00273 double data_time = 5;
00274 for (int i = 0; i < 10; i++)
00275 {
00276 c.tm.dataCallback(data_time, data_time);
00277 c.expectEmpty(data_time);
00278 data_time += 2;
00279 }
00280 c.tm.triggerCallback(14);
00281 c.expectHead(14.2, 15);
00282 c.expectEmpty(14);
00283 }
00284
00285 TEST(TriggerMatcher, TimeoutCheck)
00286 {
00287 timestamp_tools::TriggerMatcher tm(1, 10);
00288
00289
00290 EXPECT_EQ(timestamp_tools::TriggerMatcher::RetryLater, tm.getTimestampBlocking(ros::Time(0), 0.5));
00291 }
00292
00293 TEST(TriggerMatcher, TriggerFirstCheck)
00294 {
00295 timestamp_tools::TriggerMatcher tm(1, 10);
00296
00297 tm.triggerCallback(1);
00298 tm.triggerCallback(2);
00299 tm.triggerCallback(3);
00300
00301 EXPECT_EQ(ros::Time(1), tm.getTimestampBlocking(ros::Time(1.5), 1)) << "Testing getTimestampBlocking without timeout";
00302 EXPECT_EQ(ros::Time(2), tm.getTimestampBlocking(ros::Time(2.5))) << "Testing getTimestampBlocking with timeout";
00303 }
00304
00305 TEST(TriggerMatcher, TestReset)
00306 {
00307 timestamp_tools::TriggerMatcher tm(1, 10);
00308
00309 tm.triggerCallback(1);
00310 tm.triggerCallback(2);
00311 tm.reset();
00312 tm.triggerCallback(3);
00313 tm.triggerCallback(4);
00314
00315 EXPECT_EQ(timestamp_tools::TriggerMatcher::DropData, tm.getTimestampBlocking(ros::Time(1.5), 1)) << "Testing getTimestampBlocking without timeout";
00316 EXPECT_EQ(ros::Time(3), tm.getTimestampBlocking(ros::Time(3.5))) << "Testing getTimestampBlocking with timeout";
00317 }
00318
00319
00320 void AsyncGenTrigger(timestamp_tools::TriggerMatcher *tm, double time, int delay)
00321 {
00322 sleep(delay);
00323 tm->triggerCallback(time);
00324 }
00325
00326 TEST(TriggerMatcher, DataFirstCheck)
00327 {
00328 timestamp_tools::TriggerMatcher tm(1, 10);
00329
00330 tm.triggerCallback(5);
00331 boost::function<void(void)> agt = boost::bind(&AsyncGenTrigger, &tm, 7.0, 2);
00332 boost::thread trigger_thread(agt);
00333
00334 EXPECT_EQ(timestamp_tools::TriggerMatcher::RetryLater, tm.getTimestampBlocking(ros::Time(5.5), 0.5)) << "getTimestampBlocking should have timed out or test computer is VERY slow";
00335 EXPECT_EQ(ros::Time(5), tm.getTimestampBlocking(ros::Time(6.0))) << "getTimestampBlocking should have received timestamp";
00336
00337 trigger_thread.join();
00338 }
00339
00340
00341 int main(int argc, char **argv){
00342 for (int i = 0; i < argc; i++)
00343 printf("%s\n", argv[i]);
00344 testing::InitGoogleTest(&argc, argv);
00345 return RUN_ALL_TESTS();
00346 }