blob: a74b762f217dcedf1c250957a0d8ba4a3e69ee60 [file] [log] [blame]
#include "frc971/wpilib/loop_output_handler.h"
#include <chrono>
#include "gtest/gtest.h"
#include "aos/events/simulated_event_loop.h"
#include "aos/logging/logging.h"
#include "aos/testing/test_logging.h"
#include "aos/time/time.h"
#include "frc971/wpilib/loop_output_handler_test_generated.h"
namespace frc971 {
namespace wpilib {
namespace testing {
namespace {
namespace chrono = ::std::chrono;
using ::aos::monotonic_clock;
} // namespace
class LoopOutputHandlerTest : public ::testing::Test {
public:
LoopOutputHandlerTest()
: configuration_(aos::configuration::ReadConfig(
"frc971/wpilib/loop_output_handler_test_config.json")),
event_loop_factory_(&configuration_.message()),
loop_output_hander_event_loop_(
event_loop_factory_.MakeEventLoop("output")),
test_event_loop_(event_loop_factory_.MakeEventLoop("test")) {
::aos::testing::EnableTestLogging();
}
aos::FlatbufferDetachedBuffer<aos::Configuration> configuration_;
::aos::SimulatedEventLoopFactory event_loop_factory_;
::std::unique_ptr<::aos::EventLoop> loop_output_hander_event_loop_;
::std::unique_ptr<::aos::EventLoop> test_event_loop_;
};
// Test loop output handler which logs and counts.
class TestLoopOutputHandler
: public LoopOutputHandler<LoopOutputHandlerTestOutput> {
public:
TestLoopOutputHandler(::aos::EventLoop *event_loop, const ::std::string &name)
: LoopOutputHandler(event_loop, name) {}
~TestLoopOutputHandler() { Stop(); }
int count() const { return count_; }
::aos::monotonic_clock::time_point last_time() const { return last_time_; }
::aos::monotonic_clock::time_point stop_time() const { return stop_time_; }
protected:
void Write(const LoopOutputHandlerTestOutput &output) override {
LOG(INFO) << "output " << aos::FlatbufferToJson(&output);
++count_;
last_time_ = event_loop()->monotonic_now();
}
void Stop() override {
stop_time_ = event_loop()->monotonic_now();
LOG(INFO) << "Stopping";
}
private:
int count_ = 0;
::aos::monotonic_clock::time_point last_time_ =
::aos::monotonic_clock::min_time;
::aos::monotonic_clock::time_point stop_time_ =
::aos::monotonic_clock::min_time;
};
// Test that the watchdog calls Stop at the right time.
TEST_F(LoopOutputHandlerTest, WatchdogTest) {
TestLoopOutputHandler loop_output(loop_output_hander_event_loop_.get(),
"/test");
::aos::Sender<LoopOutputHandlerTestOutput> output_sender =
test_event_loop_->MakeSender<LoopOutputHandlerTestOutput>("/test");
const monotonic_clock::time_point start_time =
test_event_loop_->monotonic_now();
int count = 0;
// Send outputs for 1 second.
::aos::TimerHandler *timer_handle = test_event_loop_->AddTimer(
[this, &start_time, &output_sender, &loop_output, &count]() {
EXPECT_EQ(count, loop_output.count());
if (test_event_loop_->monotonic_now() <
start_time + chrono::seconds(1)) {
auto builder = output_sender.MakeBuilder();
LoopOutputHandlerTestOutput::Builder output_builder =
builder.MakeBuilder<LoopOutputHandlerTestOutput>();
output_builder.add_voltage(5.0);
EXPECT_TRUE(builder.Send(output_builder.Finish()));
++count;
}
LOG(INFO) << "Ping";
});
// Kick off the ping timer handler.
test_event_loop_->OnRun([this, &timer_handle]() {
timer_handle->Setup(test_event_loop_->monotonic_now(),
chrono::milliseconds(5));
});
event_loop_factory_.RunFor(chrono::seconds(2));
// Confirm the watchdog
EXPECT_EQ(loop_output.stop_time(),
loop_output.last_time() + chrono::milliseconds(100));
}
} // namespace testing
} // namespace wpilib
} // namespace frc971