global_time_sync_master.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /*
  2. * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
  3. */
  4. #include <gtest/gtest.h>
  5. #include <uavcan/protocol/global_time_sync_master.hpp>
  6. #include <uavcan/protocol/global_time_sync_slave.hpp>
  7. #include "helpers.hpp"
  8. struct GlobalTimeSyncMasterTestNode
  9. {
  10. SystemClockDriver clock;
  11. PairableCanDriver can;
  12. TestNode node;
  13. GlobalTimeSyncMasterTestNode(uavcan::NodeID nid)
  14. : can(clock)
  15. , node(can, clock, nid)
  16. { }
  17. };
  18. struct GlobalTimeSyncTestNetwork
  19. {
  20. GlobalTimeSyncMasterTestNode slave;
  21. GlobalTimeSyncMasterTestNode master_low;
  22. GlobalTimeSyncMasterTestNode master_high;
  23. GlobalTimeSyncTestNetwork()
  24. : slave(64)
  25. , master_low(120)
  26. , master_high(8)
  27. {
  28. slave.can.others.insert(&master_low.can);
  29. master_low.can.others.insert(&slave.can);
  30. master_high.can.others.insert(&slave.can);
  31. }
  32. void spinAll(uavcan::MonotonicDuration duration = uavcan::MonotonicDuration::fromMSec(9))
  33. {
  34. assert(!duration.isNegative());
  35. unsigned nspins3 = unsigned(duration.toMSec() / 3);
  36. nspins3 = nspins3 ? nspins3 : 2;
  37. while (nspins3 --> 0)
  38. {
  39. ASSERT_LE(0, slave.node.spin(uavcan::MonotonicDuration::fromMSec(1)));
  40. ASSERT_LE(0, master_low.node.spin(uavcan::MonotonicDuration::fromMSec(1)));
  41. ASSERT_LE(0, master_high.node.spin(uavcan::MonotonicDuration::fromMSec(1)));
  42. }
  43. }
  44. };
  45. TEST(GlobalTimeSyncMaster, Basic)
  46. {
  47. GlobalTimeSyncTestNetwork nwk;
  48. uavcan::GlobalDataTypeRegistry::instance().reset();
  49. uavcan::DefaultDataTypeRegistrator<uavcan::protocol::GlobalTimeSync> _reg1;
  50. uavcan::GlobalTimeSyncSlave slave(nwk.slave.node);
  51. uavcan::GlobalTimeSyncMaster master_low(nwk.master_low.node);
  52. uavcan::GlobalTimeSyncMaster master_high(nwk.master_high.node);
  53. ASSERT_FALSE(master_low.isInitialized());
  54. ASSERT_LE(0, slave.start());
  55. ASSERT_LE(0, master_low.init());
  56. ASSERT_LE(0, master_high.init());
  57. ASSERT_TRUE(master_low.isInitialized());
  58. ASSERT_FALSE(slave.isActive());
  59. /*
  60. * Simple synchronization
  61. */
  62. ASSERT_LE(0, master_low.publish()); // Update
  63. nwk.spinAll();
  64. usleep(400000);
  65. ASSERT_LE(0, master_low.publish()); // Adjustment
  66. nwk.spinAll();
  67. // Synchronization complete.
  68. ASSERT_TRUE(areTimestampsClose(nwk.slave.clock.getUtc(), nwk.master_low.clock.getUtc()));
  69. ASSERT_TRUE(slave.isActive());
  70. ASSERT_EQ(nwk.master_low.node.getNodeID(), slave.getMasterNodeID());
  71. /*
  72. * Moving clocks forward and re-syncing with another master
  73. */
  74. static const uavcan::UtcDuration OneDay = uavcan::UtcDuration::fromMSec(24 * 3600 * 1000);
  75. nwk.master_high.clock.utc_adjustment = OneDay;
  76. usleep(400000);
  77. ASSERT_LE(0, master_low.publish()); // Update from the old master
  78. nwk.spinAll();
  79. ASSERT_LE(0, master_high.publish()); // Update from the new master
  80. nwk.spinAll();
  81. usleep(400000);
  82. ASSERT_LE(0, master_low.publish()); // Adjustment from the old master (ignored now)
  83. ASSERT_LE(0, master_high.publish()); // Adjustment from the new master (accepted)
  84. nwk.spinAll();
  85. // Synchronization complete.
  86. ASSERT_TRUE(areTimestampsClose(nwk.slave.clock.getUtc(), nwk.master_high.clock.getUtc()));
  87. ASSERT_FALSE(areTimestampsClose(nwk.slave.clock.getUtc(), nwk.master_low.clock.getUtc()));
  88. ASSERT_TRUE(slave.isActive());
  89. ASSERT_EQ(nwk.master_high.node.getNodeID(), slave.getMasterNodeID());
  90. /*
  91. * Frequent calls to publish()
  92. */
  93. ASSERT_LE(0, master_low.publish()); // Dropped
  94. ASSERT_LE(0, master_low.publish()); // Dropped
  95. ASSERT_LE(0, master_low.publish()); // Dropped
  96. ASSERT_TRUE(nwk.slave.can.read_queue.empty());
  97. usleep(400000);
  98. ASSERT_LE(0, master_low.publish()); // Accepted
  99. ASSERT_FALSE(nwk.slave.can.read_queue.empty());
  100. nwk.spinAll();
  101. // Synchronization did not change
  102. ASSERT_TRUE(areTimestampsClose(nwk.slave.clock.getUtc(), nwk.master_high.clock.getUtc()));
  103. ASSERT_FALSE(areTimestampsClose(nwk.slave.clock.getUtc(), nwk.master_low.clock.getUtc()));
  104. ASSERT_TRUE(slave.isActive());
  105. ASSERT_EQ(nwk.master_high.node.getNodeID(), slave.getMasterNodeID());
  106. }