blob: d7ef8cd6f2c5114ae969d07dfc986b7d40ecc659 [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 Schuhbd1fe9c2019-06-29 16:35:48 -070039 loop_output_hander_event_loop_(event_loop_factory_.MakeEventLoop()),
40 test_event_loop_(event_loop_factory_.MakeEventLoop()) {
41 ::aos::testing::EnableTestLogging();
42 }
43
Alex Perrycb7da4b2019-08-28 19:35:56 -070044 aos::FlatbufferDetachedBuffer<aos::Configuration> configuration_;
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070045 ::aos::SimulatedEventLoopFactory event_loop_factory_;
46 ::std::unique_ptr<::aos::EventLoop> loop_output_hander_event_loop_;
47 ::std::unique_ptr<::aos::EventLoop> test_event_loop_;
48};
49
50// Test loop output handler which logs and counts.
51class TestLoopOutputHandler
52 : public LoopOutputHandler<LoopOutputHandlerTestOutput> {
53 public:
54 TestLoopOutputHandler(::aos::EventLoop *event_loop, const ::std::string &name)
55 : LoopOutputHandler(event_loop, name) {}
56
57 ~TestLoopOutputHandler() { Stop(); }
58
59 int count() const { return count_; }
60
61 ::aos::monotonic_clock::time_point last_time() const { return last_time_; }
62 ::aos::monotonic_clock::time_point stop_time() const { return stop_time_; }
63
64 protected:
65 void Write(const LoopOutputHandlerTestOutput &output) override {
Alex Perrycb7da4b2019-08-28 19:35:56 -070066 LOG(INFO) << "output " << aos::FlatbufferToJson(&output);
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070067 ++count_;
68 last_time_ = event_loop()->monotonic_now();
69 }
70
71 void Stop() override {
72 stop_time_ = event_loop()->monotonic_now();
Alex Perrycb7da4b2019-08-28 19:35:56 -070073 LOG(INFO) << "Stopping";
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070074 }
75
76 private:
77 int count_ = 0;
78
79 ::aos::monotonic_clock::time_point last_time_ =
80 ::aos::monotonic_clock::min_time;
81 ::aos::monotonic_clock::time_point stop_time_ =
82 ::aos::monotonic_clock::min_time;
83};
84
85// Test that the watchdog calls Stop at the right time.
86TEST_F(LoopOutputHandlerTest, WatchdogTest) {
87 TestLoopOutputHandler loop_output(loop_output_hander_event_loop_.get(),
Alex Perrycb7da4b2019-08-28 19:35:56 -070088 "/test");
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070089
90 ::aos::Sender<LoopOutputHandlerTestOutput> output_sender =
Alex Perrycb7da4b2019-08-28 19:35:56 -070091 test_event_loop_->MakeSender<LoopOutputHandlerTestOutput>("/test");
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070092
93 const monotonic_clock::time_point start_time =
94 test_event_loop_->monotonic_now();
95
96 int count = 0;
97 // Send outputs for 1 second.
98 ::aos::TimerHandler *timer_handle = test_event_loop_->AddTimer(
99 [this, &start_time, &output_sender, &loop_output, &count]() {
100 EXPECT_EQ(count, loop_output.count());
101 if (test_event_loop_->monotonic_now() <
102 start_time + chrono::seconds(1)) {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700103 auto builder = output_sender.MakeBuilder();
104 LoopOutputHandlerTestOutput::Builder output_builder =
105 builder.MakeBuilder<LoopOutputHandlerTestOutput>();
106 output_builder.add_voltage(5.0);
107 EXPECT_TRUE(builder.Send(output_builder.Finish()));
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700108
109 ++count;
110 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700111 LOG(INFO) << "Ping";
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700112 });
113
114 // Kick off the ping timer handler.
115 test_event_loop_->OnRun([this, &timer_handle]() {
116 timer_handle->Setup(test_event_loop_->monotonic_now(),
117 chrono::milliseconds(5));
118 });
119
120 event_loop_factory_.RunFor(chrono::seconds(2));
121
122 // Confirm the watchdog
123 EXPECT_EQ(loop_output.stop_time(),
124 loop_output.last_time() + chrono::milliseconds(100));
125}
126
127} // namespace testing
128} // namespace wpilib
129} // namespace frc971