blob: b3fbb0d36948bb9f00f0464d63e003c7083e0a48 [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 Schuh62288252020-11-18 23:26:04 -08008#include "aos/realtime.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()
Austin Schuh00be38c2019-12-01 18:08:25 -080024 : configuration_(aos::configuration::ReadConfig(
25 "frc971/wpilib/loop_output_handler_test_config.json")),
Alex Perrycb7da4b2019-08-28 19:35:56 -070026 event_loop_factory_(&configuration_.message()),
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080027 loop_output_hander_event_loop_(
28 event_loop_factory_.MakeEventLoop("output")),
29 test_event_loop_(event_loop_factory_.MakeEventLoop("test")) {
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070030 ::aos::testing::EnableTestLogging();
31 }
32
Alex Perrycb7da4b2019-08-28 19:35:56 -070033 aos::FlatbufferDetachedBuffer<aos::Configuration> configuration_;
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070034 ::aos::SimulatedEventLoopFactory event_loop_factory_;
35 ::std::unique_ptr<::aos::EventLoop> loop_output_hander_event_loop_;
36 ::std::unique_ptr<::aos::EventLoop> test_event_loop_;
37};
38
39// Test loop output handler which logs and counts.
40class TestLoopOutputHandler
41 : public LoopOutputHandler<LoopOutputHandlerTestOutput> {
42 public:
43 TestLoopOutputHandler(::aos::EventLoop *event_loop, const ::std::string &name)
44 : LoopOutputHandler(event_loop, name) {}
45
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070046 int count() const { return count_; }
47
48 ::aos::monotonic_clock::time_point last_time() const { return last_time_; }
49 ::aos::monotonic_clock::time_point stop_time() const { return stop_time_; }
50
51 protected:
52 void Write(const LoopOutputHandlerTestOutput &output) override {
Austin Schuh62288252020-11-18 23:26:04 -080053 aos::CheckRealtime();
54 // We don't care if this is RT if we are testing.
55 aos::ScopedNotRealtime nrt;
Alex Perrycb7da4b2019-08-28 19:35:56 -070056 LOG(INFO) << "output " << aos::FlatbufferToJson(&output);
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070057 ++count_;
58 last_time_ = event_loop()->monotonic_now();
59 }
60
61 void Stop() override {
Austin Schuh62288252020-11-18 23:26:04 -080062 aos::CheckRealtime();
63 // We don't care if this is RT if we are testing.
64 aos::ScopedNotRealtime nrt;
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070065 stop_time_ = event_loop()->monotonic_now();
Alex Perrycb7da4b2019-08-28 19:35:56 -070066 LOG(INFO) << "Stopping";
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070067 }
68
69 private:
70 int count_ = 0;
71
72 ::aos::monotonic_clock::time_point last_time_ =
73 ::aos::monotonic_clock::min_time;
74 ::aos::monotonic_clock::time_point stop_time_ =
75 ::aos::monotonic_clock::min_time;
76};
77
78// Test that the watchdog calls Stop at the right time.
79TEST_F(LoopOutputHandlerTest, WatchdogTest) {
80 TestLoopOutputHandler loop_output(loop_output_hander_event_loop_.get(),
Alex Perrycb7da4b2019-08-28 19:35:56 -070081 "/test");
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070082
83 ::aos::Sender<LoopOutputHandlerTestOutput> output_sender =
Alex Perrycb7da4b2019-08-28 19:35:56 -070084 test_event_loop_->MakeSender<LoopOutputHandlerTestOutput>("/test");
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070085
86 const monotonic_clock::time_point start_time =
87 test_event_loop_->monotonic_now();
88
89 int count = 0;
90 // Send outputs for 1 second.
91 ::aos::TimerHandler *timer_handle = test_event_loop_->AddTimer(
92 [this, &start_time, &output_sender, &loop_output, &count]() {
93 EXPECT_EQ(count, loop_output.count());
94 if (test_event_loop_->monotonic_now() <
95 start_time + chrono::seconds(1)) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070096 auto builder = output_sender.MakeBuilder();
97 LoopOutputHandlerTestOutput::Builder output_builder =
98 builder.MakeBuilder<LoopOutputHandlerTestOutput>();
99 output_builder.add_voltage(5.0);
milind1f1dca32021-07-03 13:50:07 -0700100 EXPECT_EQ(builder.Send(output_builder.Finish()),
101 aos::RawSender::Error::kOk);
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700102
103 ++count;
104 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700105 LOG(INFO) << "Ping";
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700106 });
107
108 // Kick off the ping timer handler.
109 test_event_loop_->OnRun([this, &timer_handle]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700110 timer_handle->Schedule(test_event_loop_->monotonic_now(),
111 chrono::milliseconds(5));
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700112 });
113
114 event_loop_factory_.RunFor(chrono::seconds(2));
115
116 // Confirm the watchdog
117 EXPECT_EQ(loop_output.stop_time(),
118 loop_output.last_time() + chrono::milliseconds(100));
119}
120
121} // namespace testing
122} // namespace wpilib
123} // namespace frc971