blob: f1d403c280f974de577a8cc3b2e30280661838b0 [file] [log] [blame]
Austin Schuhbd1fe9c2019-06-29 16:35:48 -07001#include "frc971/wpilib/loop_output_handler.h"
2
3#include <chrono>
4
5#include "gtest/gtest.h"
6
Alex Perrycb7da4b2019-08-28 19:35:56 -07007#include "aos/events/simulated_event_loop.h"
Austin Schuhbd1fe9c2019-06-29 16:35:48 -07008#include "aos/logging/logging.h"
Austin Schuhbd1fe9c2019-06-29 16:35:48 -07009#include "aos/testing/test_logging.h"
10#include "aos/time/time.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070011#include "frc971/wpilib/loop_output_handler_test_generated.h"
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070012
13namespace frc971 {
14namespace wpilib {
15namespace testing {
16namespace {
17namespace chrono = ::std::chrono;
18using ::aos::monotonic_clock;
19} // namespace
20
21class LoopOutputHandlerTest : public ::testing::Test {
22 public:
23 LoopOutputHandlerTest()
24 : ::testing::Test(),
Alex Perrycb7da4b2019-08-28 19:35:56 -070025 configuration_(aos::configuration::MergeConfiguration(
26 aos::FlatbufferDetachedBuffer<aos::Configuration>(
27 aos::JsonToFlatbuffer(
28 "{\n"
29 " \"channels\": [ \n"
30 " {\n"
31 " \"name\": \"/test\",\n"
32 " \"type\": "
33 "\"frc971.wpilib.LoopOutputHandlerTestOutput\"\n"
34 " }\n"
35 " ]\n"
36 "}\n",
37 aos::Configuration::MiniReflectTypeTable())))),
38 event_loop_factory_(&configuration_.message()),
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080039 loop_output_hander_event_loop_(
40 event_loop_factory_.MakeEventLoop("output")),
41 test_event_loop_(event_loop_factory_.MakeEventLoop("test")) {
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070042 ::aos::testing::EnableTestLogging();
43 }
44
Alex Perrycb7da4b2019-08-28 19:35:56 -070045 aos::FlatbufferDetachedBuffer<aos::Configuration> configuration_;
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070046 ::aos::SimulatedEventLoopFactory event_loop_factory_;
47 ::std::unique_ptr<::aos::EventLoop> loop_output_hander_event_loop_;
48 ::std::unique_ptr<::aos::EventLoop> test_event_loop_;
49};
50
51// Test loop output handler which logs and counts.
52class TestLoopOutputHandler
53 : public LoopOutputHandler<LoopOutputHandlerTestOutput> {
54 public:
55 TestLoopOutputHandler(::aos::EventLoop *event_loop, const ::std::string &name)
56 : LoopOutputHandler(event_loop, name) {}
57
58 ~TestLoopOutputHandler() { Stop(); }
59
60 int count() const { return count_; }
61
62 ::aos::monotonic_clock::time_point last_time() const { return last_time_; }
63 ::aos::monotonic_clock::time_point stop_time() const { return stop_time_; }
64
65 protected:
66 void Write(const LoopOutputHandlerTestOutput &output) override {
Alex Perrycb7da4b2019-08-28 19:35:56 -070067 LOG(INFO) << "output " << aos::FlatbufferToJson(&output);
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070068 ++count_;
69 last_time_ = event_loop()->monotonic_now();
70 }
71
72 void Stop() override {
73 stop_time_ = event_loop()->monotonic_now();
Alex Perrycb7da4b2019-08-28 19:35:56 -070074 LOG(INFO) << "Stopping";
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070075 }
76
77 private:
78 int count_ = 0;
79
80 ::aos::monotonic_clock::time_point last_time_ =
81 ::aos::monotonic_clock::min_time;
82 ::aos::monotonic_clock::time_point stop_time_ =
83 ::aos::monotonic_clock::min_time;
84};
85
86// Test that the watchdog calls Stop at the right time.
87TEST_F(LoopOutputHandlerTest, WatchdogTest) {
88 TestLoopOutputHandler loop_output(loop_output_hander_event_loop_.get(),
Alex Perrycb7da4b2019-08-28 19:35:56 -070089 "/test");
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070090
91 ::aos::Sender<LoopOutputHandlerTestOutput> output_sender =
Alex Perrycb7da4b2019-08-28 19:35:56 -070092 test_event_loop_->MakeSender<LoopOutputHandlerTestOutput>("/test");
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070093
94 const monotonic_clock::time_point start_time =
95 test_event_loop_->monotonic_now();
96
97 int count = 0;
98 // Send outputs for 1 second.
99 ::aos::TimerHandler *timer_handle = test_event_loop_->AddTimer(
100 [this, &start_time, &output_sender, &loop_output, &count]() {
101 EXPECT_EQ(count, loop_output.count());
102 if (test_event_loop_->monotonic_now() <
103 start_time + chrono::seconds(1)) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700104 auto builder = output_sender.MakeBuilder();
105 LoopOutputHandlerTestOutput::Builder output_builder =
106 builder.MakeBuilder<LoopOutputHandlerTestOutput>();
107 output_builder.add_voltage(5.0);
108 EXPECT_TRUE(builder.Send(output_builder.Finish()));
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700109
110 ++count;
111 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700112 LOG(INFO) << "Ping";
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700113 });
114
115 // Kick off the ping timer handler.
116 test_event_loop_->OnRun([this, &timer_handle]() {
117 timer_handle->Setup(test_event_loop_->monotonic_now(),
118 chrono::milliseconds(5));
119 });
120
121 event_loop_factory_.RunFor(chrono::seconds(2));
122
123 // Confirm the watchdog
124 EXPECT_EQ(loop_output.stop_time(),
125 loop_output.last_time() + chrono::milliseconds(100));
126}
127
128} // namespace testing
129} // namespace wpilib
130} // namespace frc971