Руслан Урядинский / libuavcan

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers scheduler.cpp Source File

scheduler.cpp

00001 /*
00002  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
00003  */
00004 
00005 #include <gtest/gtest.h>
00006 #include <uavcan/node/timer.hpp>
00007 #include <uavcan/util/method_binder.hpp>
00008 #include "../clock.hpp"
00009 #include "../transport/can/can.hpp"
00010 #include "test_node.hpp"
00011 
00012 #if !defined(UAVCAN_CPP11) || !defined(UAVCAN_CPP_VERSION)
00013 # error UAVCAN_CPP_VERSION
00014 #endif
00015 
00016 struct TimerCallCounter
00017 {
00018     std::vector<uavcan::TimerEvent> events_a;
00019     std::vector<uavcan::TimerEvent> events_b;
00020 
00021     void callA(const uavcan::TimerEvent& ev) { events_a.push_back(ev); }
00022     void callB(const uavcan::TimerEvent& ev) { events_b.push_back(ev); }
00023 
00024     typedef uavcan::MethodBinder<TimerCallCounter*, void (TimerCallCounter::*)(const uavcan::TimerEvent&)> Binder;
00025 
00026     Binder bindA() { return Binder(this, &TimerCallCounter::callA); }
00027     Binder bindB() { return Binder(this, &TimerCallCounter::callB); }
00028 };
00029 
00030 /*
00031  * This test can fail on a non real time system. That's kinda sad but okay.
00032  */
00033 TEST(Scheduler, Timers)
00034 {
00035     SystemClockDriver clock_driver;
00036     CanDriverMock can_driver(2, clock_driver);
00037     TestNode node(can_driver, clock_driver, 1);
00038 
00039     /*
00040      * Registration
00041      */
00042     {
00043         TimerCallCounter tcc;
00044         uavcan::TimerEventForwarder<TimerCallCounter::Binder> a(node, tcc.bindA());
00045         uavcan::TimerEventForwarder<TimerCallCounter::Binder> b(node, tcc.bindB());
00046 
00047         ASSERT_EQ(0, node.getScheduler().getDeadlineScheduler().getNumHandlers());
00048 
00049         const uavcan::MonotonicTime start_ts = clock_driver.getMonotonic();
00050 
00051         a.startOneShotWithDeadline(start_ts + durMono(100000));
00052         b.startPeriodic(durMono(1000));
00053 
00054         ASSERT_EQ(2, node.getScheduler().getDeadlineScheduler().getNumHandlers());
00055 
00056         /*
00057          * Spinning
00058          */
00059         ASSERT_EQ(0, node.spin(start_ts + durMono(1000000)));
00060 
00061         ASSERT_EQ(1, tcc.events_a.size());
00062         ASSERT_TRUE(areTimestampsClose(tcc.events_a[0].scheduled_time, start_ts + durMono(100000)));
00063         ASSERT_TRUE(areTimestampsClose(tcc.events_a[0].scheduled_time, tcc.events_a[0].real_time));
00064 
00065         ASSERT_LT(900, tcc.events_b.size());
00066         ASSERT_GT(1100, tcc.events_b.size());
00067         {
00068             uavcan::MonotonicTime next_expected_deadline = start_ts + durMono(1000);
00069             for (unsigned i = 0; i < tcc.events_b.size(); i++)
00070             {
00071                 ASSERT_TRUE(areTimestampsClose(tcc.events_b[i].scheduled_time, next_expected_deadline));
00072                 ASSERT_TRUE(areTimestampsClose(tcc.events_b[i].scheduled_time, tcc.events_b[i].real_time));
00073                 next_expected_deadline += durMono(1000);
00074             }
00075         }
00076 
00077         /*
00078          * Deinitialization
00079          */
00080         ASSERT_EQ(1, node.getScheduler().getDeadlineScheduler().getNumHandlers());
00081 
00082         ASSERT_FALSE(a.isRunning());
00083         ASSERT_EQ(uavcan::MonotonicDuration::getInfinite(), a.getPeriod());
00084 
00085         ASSERT_TRUE(b.isRunning());
00086         ASSERT_EQ(1000, b.getPeriod().toUSec());
00087     }
00088 
00089     ASSERT_EQ(0, node.getScheduler().getDeadlineScheduler().getNumHandlers()); // Both timers were destroyed by now
00090     ASSERT_EQ(0, node.spin(durMono(1000)));                                    // Spin some more without timers
00091 }
00092 
00093 #if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
00094 
00095 TEST(Scheduler, TimerCpp11)
00096 {
00097     SystemClockDriver clock_driver;
00098     CanDriverMock can_driver(2, clock_driver);
00099     TestNode node(can_driver, clock_driver, 1);
00100 
00101     int count = 0;
00102 
00103     uavcan::Timer tm(node, [&count](const uavcan::TimerEvent&) { count++; });
00104 
00105     ASSERT_EQ(0, node.getScheduler().getDeadlineScheduler().getNumHandlers());
00106     tm.startPeriodic(uavcan::MonotonicDuration::fromMSec(10));
00107     ASSERT_EQ(1, node.getScheduler().getDeadlineScheduler().getNumHandlers());
00108 
00109     ASSERT_EQ(0, node.spin(uavcan::MonotonicDuration::fromMSec(100)));
00110 
00111     std::cout << count << std::endl;
00112     ASSERT_LE(5, count);
00113     ASSERT_GE(15, count);
00114 }
00115 
00116 #endif