blob: f3b4aefbbc97de2316835fa646689f24c0c8895c [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
Stephan Pleinesf63bde82024-01-13 15:59:33 -080013namespace frc971::wpilib::testing {
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070014namespace {
15namespace chrono = ::std::chrono;
16using ::aos::monotonic_clock;
17} // namespace
18
19class LoopOutputHandlerTest : public ::testing::Test {
20 public:
21 LoopOutputHandlerTest()
Austin Schuh00be38c2019-12-01 18:08:25 -080022 : configuration_(aos::configuration::ReadConfig(
23 "frc971/wpilib/loop_output_handler_test_config.json")),
Alex Perrycb7da4b2019-08-28 19:35:56 -070024 event_loop_factory_(&configuration_.message()),
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080025 loop_output_hander_event_loop_(
26 event_loop_factory_.MakeEventLoop("output")),
27 test_event_loop_(event_loop_factory_.MakeEventLoop("test")) {
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070028 ::aos::testing::EnableTestLogging();
29 }
30
Alex Perrycb7da4b2019-08-28 19:35:56 -070031 aos::FlatbufferDetachedBuffer<aos::Configuration> configuration_;
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070032 ::aos::SimulatedEventLoopFactory event_loop_factory_;
33 ::std::unique_ptr<::aos::EventLoop> loop_output_hander_event_loop_;
34 ::std::unique_ptr<::aos::EventLoop> test_event_loop_;
35};
36
37// Test loop output handler which logs and counts.
38class TestLoopOutputHandler
39 : public LoopOutputHandler<LoopOutputHandlerTestOutput> {
40 public:
41 TestLoopOutputHandler(::aos::EventLoop *event_loop, const ::std::string &name)
42 : LoopOutputHandler(event_loop, name) {}
43
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070044 int count() const { return count_; }
45
46 ::aos::monotonic_clock::time_point last_time() const { return last_time_; }
47 ::aos::monotonic_clock::time_point stop_time() const { return stop_time_; }
48
49 protected:
50 void Write(const LoopOutputHandlerTestOutput &output) override {
Austin Schuh62288252020-11-18 23:26:04 -080051 aos::CheckRealtime();
52 // We don't care if this is RT if we are testing.
53 aos::ScopedNotRealtime nrt;
Alex Perrycb7da4b2019-08-28 19:35:56 -070054 LOG(INFO) << "output " << aos::FlatbufferToJson(&output);
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070055 ++count_;
56 last_time_ = event_loop()->monotonic_now();
57 }
58
59 void Stop() override {
Austin Schuh62288252020-11-18 23:26:04 -080060 aos::CheckRealtime();
61 // We don't care if this is RT if we are testing.
62 aos::ScopedNotRealtime nrt;
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070063 stop_time_ = event_loop()->monotonic_now();
Alex Perrycb7da4b2019-08-28 19:35:56 -070064 LOG(INFO) << "Stopping";
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070065 }
66
67 private:
68 int count_ = 0;
69
70 ::aos::monotonic_clock::time_point last_time_ =
71 ::aos::monotonic_clock::min_time;
72 ::aos::monotonic_clock::time_point stop_time_ =
73 ::aos::monotonic_clock::min_time;
74};
75
76// Test that the watchdog calls Stop at the right time.
77TEST_F(LoopOutputHandlerTest, WatchdogTest) {
78 TestLoopOutputHandler loop_output(loop_output_hander_event_loop_.get(),
Alex Perrycb7da4b2019-08-28 19:35:56 -070079 "/test");
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070080
81 ::aos::Sender<LoopOutputHandlerTestOutput> output_sender =
Alex Perrycb7da4b2019-08-28 19:35:56 -070082 test_event_loop_->MakeSender<LoopOutputHandlerTestOutput>("/test");
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070083
84 const monotonic_clock::time_point start_time =
85 test_event_loop_->monotonic_now();
86
87 int count = 0;
88 // Send outputs for 1 second.
89 ::aos::TimerHandler *timer_handle = test_event_loop_->AddTimer(
90 [this, &start_time, &output_sender, &loop_output, &count]() {
91 EXPECT_EQ(count, loop_output.count());
92 if (test_event_loop_->monotonic_now() <
93 start_time + chrono::seconds(1)) {
Alex Perrycb7da4b2019-08-28 19:35:56 -070094 auto builder = output_sender.MakeBuilder();
95 LoopOutputHandlerTestOutput::Builder output_builder =
96 builder.MakeBuilder<LoopOutputHandlerTestOutput>();
97 output_builder.add_voltage(5.0);
milind1f1dca32021-07-03 13:50:07 -070098 EXPECT_EQ(builder.Send(output_builder.Finish()),
99 aos::RawSender::Error::kOk);
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700100
101 ++count;
102 }
Alex Perrycb7da4b2019-08-28 19:35:56 -0700103 LOG(INFO) << "Ping";
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700104 });
105
106 // Kick off the ping timer handler.
107 test_event_loop_->OnRun([this, &timer_handle]() {
Philipp Schradera6712522023-07-05 20:25:11 -0700108 timer_handle->Schedule(test_event_loop_->monotonic_now(),
109 chrono::milliseconds(5));
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700110 });
111
112 event_loop_factory_.RunFor(chrono::seconds(2));
113
114 // Confirm the watchdog
115 EXPECT_EQ(loop_output.stop_time(),
116 loop_output.last_time() + chrono::milliseconds(100));
117}
118
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800119} // namespace frc971::wpilib::testing