diff --git a/wpilibc/src/main/native/cpp/Solenoid.cpp b/wpilibc/src/main/native/cpp/Solenoid.cpp index 69723c0fbf..b3ff5cf167 100644 --- a/wpilibc/src/main/native/cpp/Solenoid.cpp +++ b/wpilibc/src/main/native/cpp/Solenoid.cpp @@ -28,8 +28,8 @@ Solenoid::Solenoid(PneumaticsBase* module, int channel) Solenoid::Solenoid(std::shared_ptr module, int channel) : m_module{std::move(module)} { - if (!m_module->CheckSolenoidChannel(m_channel)) { - throw FRC_MakeError(err::ChannelIndexOutOfRange, "Channel {}", m_channel); + if (!m_module->CheckSolenoidChannel(channel)) { + throw FRC_MakeError(err::ChannelIndexOutOfRange, "Channel {}", channel); } m_channel = channel; m_mask = 1 << channel; diff --git a/wpilibc/src/main/native/cpp/simulation/AddressableLEDSim.cpp b/wpilibc/src/main/native/cpp/simulation/AddressableLEDSim.cpp index c2f1b0044b..8114bb36dc 100644 --- a/wpilibc/src/main/native/cpp/simulation/AddressableLEDSim.cpp +++ b/wpilibc/src/main/native/cpp/simulation/AddressableLEDSim.cpp @@ -99,7 +99,7 @@ void AddressableLEDSim::SetRunning(bool running) { } std::unique_ptr AddressableLEDSim::RegisterDataCallback( - NotifyCallback callback, bool initialNotify) { + ConstBufferCallback callback, bool initialNotify) { auto store = std::make_unique( m_index, -1, callback, &HALSIM_CancelAddressableLEDDataCallback); store->SetUid(HALSIM_RegisterAddressableLEDDataCallback( diff --git a/wpilibc/src/main/native/include/frc/PneumaticsControlModule.h b/wpilibc/src/main/native/include/frc/PneumaticsControlModule.h index 6dc81e0331..46953d4250 100644 --- a/wpilibc/src/main/native/include/frc/PneumaticsControlModule.h +++ b/wpilibc/src/main/native/include/frc/PneumaticsControlModule.h @@ -67,7 +67,7 @@ class PneumaticsControlModule private: int m_module; hal::Handle m_handle; - uint32_t m_reservedMask; + uint32_t m_reservedMask{0}; wpi::mutex m_reservedLock; }; } // namespace frc diff --git a/wpilibc/src/main/native/include/frc/simulation/AddressableLEDSim.h b/wpilibc/src/main/native/include/frc/simulation/AddressableLEDSim.h index f6e2488096..1d8db85d21 100644 --- a/wpilibc/src/main/native/include/frc/simulation/AddressableLEDSim.h +++ b/wpilibc/src/main/native/include/frc/simulation/AddressableLEDSim.h @@ -160,7 +160,7 @@ class AddressableLEDSim { * @return the CallbackStore object associated with this callback */ [[nodiscard]] std::unique_ptr RegisterDataCallback( - NotifyCallback callback, bool initialNotify); + ConstBufferCallback callback, bool initialNotify); /** * Get the LED data. diff --git a/wpilibc/src/test/native/cpp/AnalogPotentiometerTest.cpp b/wpilibc/src/test/native/cpp/AnalogPotentiometerTest.cpp new file mode 100644 index 0000000000..de6989486b --- /dev/null +++ b/wpilibc/src/test/native/cpp/AnalogPotentiometerTest.cpp @@ -0,0 +1,92 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include + +#include "frc/AnalogPotentiometer.h" +#include "frc/simulation/AnalogInputSim.h" +#include "frc/simulation/RoboRioSim.h" +#include "gtest/gtest.h" + +namespace frc { +using namespace frc::sim; +TEST(AnalogPotentiometerTest, InitializeWithAnalogInput) { + HAL_Initialize(500, 0); + + AnalogInput ai{0}; + AnalogPotentiometer pot{&ai}; + AnalogInputSim sim{ai}; + + RoboRioSim::ResetData(); + sim.SetVoltage(4.0); + EXPECT_EQ(0.8, pot.Get()); +} + +TEST(AnalogPotentiometerTest, InitializeWithAnalogInputAndScale) { + HAL_Initialize(500, 0); + + AnalogInput ai{0}; + AnalogPotentiometer pot{&ai, 270.0}; + RoboRioSim::ResetData(); + AnalogInputSim sim{ai}; + + sim.SetVoltage(5.0); + EXPECT_EQ(270.0, pot.Get()); + + sim.SetVoltage(2.5); + EXPECT_EQ(135, pot.Get()); + + sim.SetVoltage(0.0); + EXPECT_EQ(0.0, pot.Get()); +} + +TEST(AnalogPotentiometerTest, InitializeWithChannel) { + HAL_Initialize(500, 0); + + AnalogPotentiometer pot{1}; + AnalogInputSim sim{1}; + + sim.SetVoltage(5.0); + EXPECT_EQ(1.0, pot.Get()); +} + +TEST(AnalogPotentiometerTest, InitializeWithChannelAndScale) { + HAL_Initialize(500, 0); + + AnalogPotentiometer pot{1, 180.0}; + RoboRioSim::ResetData(); + AnalogInputSim sim{1}; + + sim.SetVoltage(5.0); + EXPECT_EQ(180.0, pot.Get()); + + sim.SetVoltage(0.0); + EXPECT_EQ(0.0, pot.Get()); +} + +TEST(AnalogPotentiometerTest, WithModifiedBatteryVoltage) { + AnalogPotentiometer pot{1, 180.0, 90.0}; + RoboRioSim::ResetData(); + AnalogInputSim sim{1}; + + // Test at 5v + sim.SetVoltage(5.0); + EXPECT_EQ(270, pot.Get()); + + sim.SetVoltage(0.0); + EXPECT_EQ(90, pot.Get()); + + // Simulate a lower battery voltage + RoboRioSim::SetUserVoltage5V(units::volt_t{2.5}); + + sim.SetVoltage(2.5); + EXPECT_EQ(270, pot.Get()); + + sim.SetVoltage(2.0); + EXPECT_EQ(234, pot.Get()); + + sim.SetVoltage(0.0); + EXPECT_EQ(90, pot.Get()); +} +} // namespace frc diff --git a/wpilibc/src/test/native/cpp/DoubleSolenoidTest.cpp b/wpilibc/src/test/native/cpp/DoubleSolenoidTest.cpp new file mode 100644 index 0000000000..e12c358ffe --- /dev/null +++ b/wpilibc/src/test/native/cpp/DoubleSolenoidTest.cpp @@ -0,0 +1,76 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include + +#include "frc/DoubleSolenoid.h" +#include "frc/PneumaticsControlModule.h" +#include "frc/Solenoid.h" +#include "gtest/gtest.h" + +namespace frc { + +TEST(DoubleSolenoidTest, ValidInitialization) { + PneumaticsControlModule pcm{3}; + DoubleSolenoid solenoid{pcm, 2, 3}; + solenoid.Set(DoubleSolenoid::kReverse); + EXPECT_EQ(DoubleSolenoid::kReverse, solenoid.Get()); + + solenoid.Set(DoubleSolenoid::kForward); + EXPECT_EQ(DoubleSolenoid::kForward, solenoid.Get()); + + solenoid.Set(DoubleSolenoid::kOff); + EXPECT_EQ(DoubleSolenoid::kOff, solenoid.Get()); +} + +TEST(DoubleSolenoidTest, ThrowForwardPortAlreadyInitialized) { + PneumaticsControlModule pcm{5}; + // Single solenoid that is reused for forward port + Solenoid solenoid{pcm, 2}; + EXPECT_THROW(DoubleSolenoid(pcm, 2, 3), std::runtime_error); +} + +TEST(DoubleSolenoidTest, ThrowReversePortAlreadyInitialized) { + PneumaticsControlModule pcm{6}; + // Single solenoid that is reused for forward port + Solenoid solenoid{pcm, 3}; + EXPECT_THROW(DoubleSolenoid(pcm, 2, 3), std::runtime_error); +} + +TEST(DoubleSolenoidTest, ThrowBothPortsAlreadyInitialized) { + PneumaticsControlModule pcm{6}; + // Single solenoid that is reused for forward port + Solenoid solenoid0(pcm, 2); + Solenoid solenoid1(pcm, 3); + EXPECT_THROW(DoubleSolenoid(pcm, 2, 3), std::runtime_error); +} + +TEST(DoubleSolenoidTest, Toggle) { + PneumaticsControlModule pcm{4}; + DoubleSolenoid solenoid{&pcm, 2, 3}; + // Bootstrap it into reverse + solenoid.Set(DoubleSolenoid::kReverse); + + solenoid.Toggle(); + EXPECT_EQ(DoubleSolenoid::kForward, solenoid.Get()); + + solenoid.Toggle(); + EXPECT_EQ(DoubleSolenoid::kReverse, solenoid.Get()); + + // Of shouldn't do anything on toggle + solenoid.Set(DoubleSolenoid::kOff); + solenoid.Toggle(); + EXPECT_EQ(DoubleSolenoid::kOff, solenoid.Get()); +} + +TEST(DoubleSolenoidTest, InvalidForwardPort) { + PneumaticsControlModule pcm{0}; + EXPECT_THROW(DoubleSolenoid(pcm, 100, 1), std::runtime_error); +} + +TEST(DoubleSolenoidTest, InvalidReversePort) { + PneumaticsControlModule pcm{0}; + EXPECT_THROW(DoubleSolenoid(pcm, 0, 100), std::runtime_error); +} +} // namespace frc diff --git a/wpilibc/src/test/native/cpp/JoystickTest.cpp b/wpilibc/src/test/native/cpp/JoystickTest.cpp index 45d4af1c95..56978797d3 100644 --- a/wpilibc/src/test/native/cpp/JoystickTest.cpp +++ b/wpilibc/src/test/native/cpp/JoystickTest.cpp @@ -4,33 +4,17 @@ #include "frc/Joystick.h" // NOLINT(build/include_order) +#include "JoystickTestMacros.h" #include "frc/simulation/JoystickSim.h" #include "gtest/gtest.h" using namespace frc; -TEST(JoystickTests, GetX) { - Joystick joy{1}; - sim::JoystickSim joysim{joy}; +AXIS_TEST(Joystick, X) +AXIS_TEST(Joystick, Y) +AXIS_TEST(Joystick, Z) +AXIS_TEST(Joystick, Throttle) +AXIS_TEST(Joystick, Twist) - joysim.SetX(0.25); - joysim.NotifyNewData(); - ASSERT_NEAR(joy.GetX(), 0.25, 0.001); - - joysim.SetX(0); - joysim.NotifyNewData(); - ASSERT_NEAR(joy.GetX(), 0, 0.001); -} - -TEST(JoystickTests, GetY) { - Joystick joy{1}; - sim::JoystickSim joysim{joy}; - - joysim.SetY(0.25); - joysim.NotifyNewData(); - ASSERT_NEAR(joy.GetY(), 0.25, 0.001); - - joysim.SetY(0); - joysim.NotifyNewData(); - ASSERT_NEAR(joy.GetY(), 0, 0.001); -} +BUTTON_TEST(Joystick, Trigger) +BUTTON_TEST(Joystick, Top) diff --git a/wpilibc/src/test/native/cpp/JoystickTestMacros.h b/wpilibc/src/test/native/cpp/JoystickTestMacros.h new file mode 100644 index 0000000000..f216b1dffc --- /dev/null +++ b/wpilibc/src/test/native/cpp/JoystickTestMacros.h @@ -0,0 +1,81 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#pragma once + +#define AXIS_TEST(JoystickType, AxisName) \ + TEST(JoystickType##Tests, Set##HandType##AxisName##Axis) { \ + JoystickType joy{2}; \ + sim::JoystickType##Sim joysim{joy}; \ + joysim.Set##AxisName(0.35); \ + joysim.NotifyNewData(); \ + ASSERT_NEAR(joy.Get##AxisName(), 0.35, 0.001); \ + } + +#define HANDED_AXIS_TEST_IMPL(JoystickType, HandType, AxisName) \ + TEST(JoystickType##Tests, Set##HandType##AxisName##Axis) { \ + JoystickType joy{2}; \ + sim::JoystickType##Sim joysim{joy}; \ + joysim.Set##AxisName(JoystickType::HandType, 0.35); \ + joysim.NotifyNewData(); \ + ASSERT_NEAR(joy.Get##AxisName(JoystickType::HandType), 0.35, 0.001); \ + } + +#define HANDED_AXIS_TEST(JoystickType, AxisName) \ + HANDED_AXIS_TEST_IMPL(JoystickType, kLeftHand, AxisName) \ + HANDED_AXIS_TEST_IMPL(JoystickType, kRightHand, AxisName) + +#define BUTTON_TEST(JoystickType, ButtonName) \ + TEST(JoystickType##Tests, Set##ButtonName##Button) { \ + JoystickType joy{1}; \ + sim::JoystickType##Sim joysim{joy}; \ + \ + joysim.Set##ButtonName(false); \ + joysim.NotifyNewData(); \ + ASSERT_FALSE(joy.Get##ButtonName()); \ + /* need to call pressed and released to clear flags */ \ + joy.Get##ButtonName##Pressed(); \ + joy.Get##ButtonName##Released(); \ + \ + joysim.Set##ButtonName(true); \ + joysim.NotifyNewData(); \ + ASSERT_TRUE(joy.Get##ButtonName()); \ + ASSERT_TRUE(joy.Get##ButtonName##Pressed()); \ + ASSERT_FALSE(joy.Get##ButtonName##Released()); \ + \ + joysim.Set##ButtonName(false); \ + joysim.NotifyNewData(); \ + ASSERT_FALSE(joy.Get##ButtonName()); \ + ASSERT_FALSE(joy.Get##ButtonName##Pressed()); \ + ASSERT_TRUE(joy.Get##ButtonName##Released()); \ + } + +#define HANDED_BUTTON_TEST_IMPL(JoystickType, HandType, ButtonName) \ + TEST(JoystickType##Tests, Get##HandType##ButtonName##Button) { \ + JoystickType joy{1}; \ + sim::JoystickType##Sim joysim{joy}; \ + \ + joysim.Set##ButtonName(JoystickType::HandType, false); \ + joysim.NotifyNewData(); \ + ASSERT_FALSE(joy.Get##ButtonName(JoystickType::HandType)); \ + /* need to call pressed and released to clear flags */ \ + joy.Get##ButtonName##Pressed(JoystickType::HandType); \ + joy.Get##ButtonName##Released(JoystickType::HandType); \ + \ + joysim.Set##ButtonName(JoystickType::HandType, true); \ + joysim.NotifyNewData(); \ + ASSERT_TRUE(joy.Get##ButtonName(JoystickType::HandType)); \ + ASSERT_TRUE(joy.Get##ButtonName##Pressed(JoystickType::HandType)); \ + ASSERT_FALSE(joy.Get##ButtonName##Released(JoystickType::HandType)); \ + \ + joysim.Set##ButtonName(JoystickType::HandType, false); \ + joysim.NotifyNewData(); \ + ASSERT_FALSE(joy.Get##ButtonName(JoystickType::HandType)); \ + ASSERT_FALSE(joy.Get##ButtonName##Pressed(JoystickType::HandType)); \ + ASSERT_TRUE(joy.Get##ButtonName##Released(JoystickType::HandType)); \ + } + +#define HANDED_BUTTON_TEST(JoystickType, ButtonName) \ + HANDED_BUTTON_TEST_IMPL(JoystickType, kLeftHand, ButtonName) \ + HANDED_BUTTON_TEST_IMPL(JoystickType, kRightHand, ButtonName) diff --git a/wpilibc/src/test/native/cpp/SolenoidTest.cpp b/wpilibc/src/test/native/cpp/SolenoidTest.cpp new file mode 100644 index 0000000000..1935d2fdc2 --- /dev/null +++ b/wpilibc/src/test/native/cpp/SolenoidTest.cpp @@ -0,0 +1,54 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include + +#include "frc/DoubleSolenoid.h" +#include "frc/PneumaticsControlModule.h" +#include "frc/Solenoid.h" +#include "gtest/gtest.h" + +namespace frc { +TEST(SolenoidTest, ValidInitialization) { + PneumaticsControlModule pcm{3}; + Solenoid solenoid{pcm, 2}; + EXPECT_EQ(2, solenoid.GetChannel()); + + solenoid.Set(true); + EXPECT_TRUE(solenoid.Get()); + + solenoid.Set(false); + EXPECT_FALSE(solenoid.Get()); +} + +TEST(SolenoidTest, DoubleInitialization) { + PneumaticsControlModule pcm{3}; + Solenoid solenoid{&pcm, 2}; + EXPECT_THROW(Solenoid(pcm, 2), std::runtime_error); +} + +TEST(SolenoidTest, DoubleInitializationFromDoubleSolenoid) { + PneumaticsControlModule pcm{3}; + DoubleSolenoid solenoid{pcm, 2, 3}; + EXPECT_THROW(Solenoid(pcm, 2), std::runtime_error); +} + +TEST(SolenoidTest, InvalidChannel) { + PneumaticsControlModule pcm{3}; + EXPECT_THROW(Solenoid(pcm, 100), std::runtime_error); +} + +TEST(SolenoidTest, Toggle) { + PneumaticsControlModule pcm{3}; + Solenoid solenoid{pcm, 2}; + solenoid.Set(true); + EXPECT_TRUE(solenoid.Get()); + + solenoid.Toggle(); + EXPECT_FALSE(solenoid.Get()); + + solenoid.Toggle(); + EXPECT_TRUE(solenoid.Get()); +} +} // namespace frc diff --git a/wpilibc/src/test/native/cpp/TestCallbackHelpers.cpp b/wpilibc/src/test/native/cpp/TestCallbackHelpers.cpp new file mode 100644 index 0000000000..d98f539faa --- /dev/null +++ b/wpilibc/src/test/native/cpp/TestCallbackHelpers.cpp @@ -0,0 +1,82 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include "callback_helpers/TestCallbackHelpers.h" + +#include + +#include + +namespace frc::sim { + +void BooleanCallback::HandleCallback(std::string_view name, + const HAL_Value* value) { + if (!value) { + throw std::invalid_argument("Null value"); + } + if (value->type != HAL_BOOLEAN) { + throw std::invalid_argument( + fmt::format("Wrong type '{}' for boolean", value->type).c_str()); + } + m_wasTriggered = true; + m_lastValue = value->data.v_boolean; +} + +void EnumCallback::HandleCallback(std::string_view name, + const HAL_Value* value) { + if (!value) { + throw std::invalid_argument("Null value"); + } + if (value->type != HAL_ENUM) { + throw std::invalid_argument( + fmt::format("Wrong type '{}' for enum", value->type).c_str()); + } + + m_wasTriggered = true; + m_lastValue = value->data.v_enum; +} + +void IntCallback::HandleCallback(std::string_view name, + const HAL_Value* value) { + if (!value) { + throw std::invalid_argument("Null value"); + } + if (value->type != HAL_INT) { + throw std::invalid_argument( + fmt::format("Wrong type '{}' for integer", value->type).c_str()); + } + + m_wasTriggered = true; + m_lastValue = value->data.v_int; +} + +void LongCallback::HandleCallback(std::string_view name, + const HAL_Value* value) { + if (!value) { + throw std::invalid_argument("Null value"); + } + if (value->type != HAL_LONG) { + throw std::invalid_argument( + fmt::format("Wrong type '{}' for long", value->type).c_str()); + } + + m_wasTriggered = true; + m_lastValue = value->data.v_long; +} + +void DoubleCallback::HandleCallback(std::string_view name, + const HAL_Value* value) { + if (!value) { + throw std::invalid_argument("Null value"); + } + if (value->type != HAL_DOUBLE) { + throw std::invalid_argument( + fmt::format("Wrong type '{}' for double", value->type).c_str()); + } + + m_wasTriggered = true; + m_lastValue = value->data.v_double; +} + +} // namespace frc::sim diff --git a/wpilibc/src/test/native/cpp/XboxControllerTest.cpp b/wpilibc/src/test/native/cpp/XboxControllerTest.cpp index 6c5d6f66da..07d20a5902 100644 --- a/wpilibc/src/test/native/cpp/XboxControllerTest.cpp +++ b/wpilibc/src/test/native/cpp/XboxControllerTest.cpp @@ -4,68 +4,22 @@ #include "frc/XboxController.h" // NOLINT(build/include_order) +#include "JoystickTestMacros.h" #include "frc/simulation/XboxControllerSim.h" #include "gtest/gtest.h" using namespace frc; -TEST(XboxControllerTests, GetX) { - XboxController joy{2}; - sim::XboxControllerSim joysim{joy}; +HANDED_BUTTON_TEST(XboxController, Bumper) +HANDED_BUTTON_TEST(XboxController, StickButton) - joysim.SetX(XboxController::kLeftHand, 0.35); - joysim.SetX(XboxController::kRightHand, 0.45); - joysim.NotifyNewData(); - ASSERT_NEAR(joy.GetX(XboxController::kLeftHand), 0.35, 0.001); - ASSERT_NEAR(joy.GetX(XboxController::kRightHand), 0.45, 0.001); -} +BUTTON_TEST(XboxController, AButton) +BUTTON_TEST(XboxController, BButton) +BUTTON_TEST(XboxController, XButton) +BUTTON_TEST(XboxController, YButton) +BUTTON_TEST(XboxController, BackButton) +BUTTON_TEST(XboxController, StartButton) -TEST(XboxControllerTests, GetBumper) { - XboxController joy{1}; - sim::XboxControllerSim joysim{joy}; - - joysim.SetBumper(XboxController::kLeftHand, false); - joysim.SetBumper(XboxController::kRightHand, true); - joysim.NotifyNewData(); - ASSERT_FALSE(joy.GetBumper(XboxController::kLeftHand)); - ASSERT_TRUE(joy.GetBumper(XboxController::kRightHand)); - // need to call pressed and released to clear flags - joy.GetBumperPressed(XboxController::kLeftHand); - joy.GetBumperReleased(XboxController::kLeftHand); - joy.GetBumperPressed(XboxController::kRightHand); - joy.GetBumperReleased(XboxController::kRightHand); - - joysim.SetBumper(XboxController::kLeftHand, true); - joysim.SetBumper(XboxController::kRightHand, false); - joysim.NotifyNewData(); - ASSERT_TRUE(joy.GetBumper(XboxController::kLeftHand)); - ASSERT_TRUE(joy.GetBumperPressed(XboxController::kLeftHand)); - ASSERT_FALSE(joy.GetBumperReleased(XboxController::kLeftHand)); - ASSERT_FALSE(joy.GetBumper(XboxController::kRightHand)); - ASSERT_FALSE(joy.GetBumperPressed(XboxController::kRightHand)); - ASSERT_TRUE(joy.GetBumperReleased(XboxController::kRightHand)); -} - -TEST(XboxControllerTests, GetAButton) { - XboxController joy{1}; - sim::XboxControllerSim joysim{joy}; - - joysim.SetAButton(false); - joysim.NotifyNewData(); - ASSERT_FALSE(joy.GetAButton()); - // need to call pressed and released to clear flags - joy.GetAButtonPressed(); - joy.GetAButtonReleased(); - - joysim.SetAButton(true); - joysim.NotifyNewData(); - ASSERT_TRUE(joy.GetAButton()); - ASSERT_TRUE(joy.GetAButtonPressed()); - ASSERT_FALSE(joy.GetAButtonReleased()); - - joysim.SetAButton(false); - joysim.NotifyNewData(); - ASSERT_FALSE(joy.GetAButton()); - ASSERT_FALSE(joy.GetAButtonPressed()); - ASSERT_TRUE(joy.GetAButtonReleased()); -} +HANDED_AXIS_TEST(XboxController, X) +HANDED_AXIS_TEST(XboxController, Y) +HANDED_AXIS_TEST(XboxController, TriggerAxis) diff --git a/wpilibc/src/test/native/cpp/simulation/AccelerometerSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/AccelerometerSimTest.cpp index 1a59604b1e..3dc8582eda 100644 --- a/wpilibc/src/test/native/cpp/simulation/AccelerometerSimTest.cpp +++ b/wpilibc/src/test/native/cpp/simulation/AccelerometerSimTest.cpp @@ -7,11 +7,13 @@ #include #include +#include "callback_helpers/TestCallbackHelpers.h" +#include "frc/BuiltInAccelerometer.h" #include "gtest/gtest.h" -using namespace frc::sim; +namespace frc::sim { -TEST(AcclerometerSimTests, TestActiveCallback) { +TEST(AcclerometerSimTest, ActiveCallback) { HAL_Initialize(500, 0); BuiltInAccelerometerSim sim; @@ -34,4 +36,103 @@ TEST(AcclerometerSimTests, TestActiveCallback) { EXPECT_TRUE(wasTriggered); EXPECT_TRUE(lastValue); + EXPECT_TRUE(sim.GetActive()); } + +TEST(AcclerometerSimTest, SetX) { + HAL_Initialize(500, 0); + BuiltInAccelerometerSim sim; + sim.ResetData(); + + DoubleCallback callback; + constexpr double kTestValue = 1.91; + + BuiltInAccelerometer accel; + auto cb = sim.RegisterXCallback(callback.GetCallback(), false); + sim.SetX(kTestValue); + EXPECT_EQ(kTestValue, accel.GetX()); + EXPECT_EQ(kTestValue, sim.GetX()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(kTestValue, callback.GetLastValue()); +} + +TEST(AcclerometerSimTest, SetY) { + HAL_Initialize(500, 0); + BuiltInAccelerometerSim sim; + sim.ResetData(); + + DoubleCallback callback; + constexpr double kTestValue = 2.29; + + BuiltInAccelerometer accel; + auto cb = sim.RegisterYCallback(callback.GetCallback(), false); + sim.SetY(kTestValue); + EXPECT_EQ(kTestValue, accel.GetY()); + EXPECT_EQ(kTestValue, sim.GetY()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(kTestValue, callback.GetLastValue()); +} + +TEST(AcclerometerSimTest, SetZ) { + HAL_Initialize(500, 0); + + BuiltInAccelerometer accel; + BuiltInAccelerometerSim sim(accel); + sim.ResetData(); + + DoubleCallback callback; + constexpr double kTestValue = 3.405; + + auto cb = sim.RegisterZCallback(callback.GetCallback(), false); + sim.SetZ(kTestValue); + EXPECT_EQ(kTestValue, accel.GetZ()); + EXPECT_EQ(kTestValue, sim.GetZ()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(kTestValue, callback.GetLastValue()); +} + +TEST(AcclerometerSimTest, SetRange) { + HAL_Initialize(500, 0); + + BuiltInAccelerometerSim sim; + sim.ResetData(); + + EnumCallback callback; + + Accelerometer::Range range = Accelerometer::kRange_4G; + auto cb = sim.RegisterRangeCallback(callback.GetCallback(), false); + BuiltInAccelerometer accel(range); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(static_cast(range), sim.GetRange()); + EXPECT_EQ(static_cast(range), callback.GetLastValue()); + + // 2G + callback.Reset(); + range = Accelerometer::kRange_2G; + accel.SetRange(range); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(static_cast(range), sim.GetRange()); + EXPECT_EQ(static_cast(range), callback.GetLastValue()); + + // 4G + callback.Reset(); + range = Accelerometer::kRange_4G; + accel.SetRange(range); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(static_cast(range), sim.GetRange()); + EXPECT_EQ(static_cast(range), callback.GetLastValue()); + + // 8G + callback.Reset(); + range = Accelerometer::kRange_8G; + accel.SetRange(range); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(static_cast(range), sim.GetRange()); + EXPECT_EQ(static_cast(range), callback.GetLastValue()); + + // 16G - Not supported + callback.Reset(); + EXPECT_THROW(accel.SetRange(Accelerometer::kRange_16G), std::runtime_error); + EXPECT_FALSE(callback.WasTriggered()); +} +} // namespace frc::sim diff --git a/wpilibc/src/test/native/cpp/simulation/AddressableLEDSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/AddressableLEDSimTest.cpp new file mode 100644 index 0000000000..ad4452e13e --- /dev/null +++ b/wpilibc/src/test/native/cpp/simulation/AddressableLEDSimTest.cpp @@ -0,0 +1,129 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include "frc/simulation/AddressableLEDSim.h" // NOLINT(build/include_order) + +#include + +#include "callback_helpers/TestCallbackHelpers.h" +#include "frc/AddressableLED.h" +#include "gtest/gtest.h" + +namespace frc::sim { + +TEST(AddressableLEDSimTest, InitializationCallback) { + HAL_Initialize(500, 0); + + BooleanCallback callback; + AddressableLEDSim sim; + auto cb = sim.RegisterInitializedCallback(callback.GetCallback(), false); + + EXPECT_FALSE(callback.WasTriggered()); + AddressableLED led{0}; + + EXPECT_TRUE(sim.GetInitialized()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); +} + +TEST(AddressableLEDSimTest, SetLength) { + HAL_Initialize(500, 0); + + AddressableLED led{0}; + AddressableLEDSim sim{led}; + IntCallback callback; + + auto cb = sim.RegisterLengthCallback(callback.GetCallback(), false); + + EXPECT_EQ(1, sim.GetLength()); // Defaults to 1 led + + std::array ledData; + led.SetLength(ledData.max_size()); + led.SetData(ledData); + + EXPECT_EQ(50, sim.GetLength()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(50, callback.GetLastValue()); +} + +TEST(AddressableLEDSimTest, SetRunning) { + HAL_Initialize(500, 0); + + AddressableLEDSim sim = AddressableLEDSim::CreateForIndex(0); + BooleanCallback callback; + auto cb = sim.RegisterRunningCallback(callback.GetCallback(), false); + AddressableLED led{0}; + + EXPECT_FALSE(sim.GetRunning()); + + led.Start(); + EXPECT_TRUE(sim.GetRunning()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); + + callback.Reset(); + led.Stop(); + EXPECT_FALSE(sim.GetRunning()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_FALSE(callback.GetLastValue()); +} + +TEST(AddressableLEDSimTest, SetData) { + AddressableLED led{0}; + AddressableLEDSim sim = AddressableLEDSim::CreateForChannel(0); + + bool callbackHit = false; + std::array setData; + auto cb = sim.RegisterDataCallback( + [&](std::string_view, const unsigned char* buffer, unsigned int count) { + ASSERT_EQ(count, 12u); + EXPECT_EQ(0, buffer[0]); + EXPECT_EQ(0, buffer[1]); + EXPECT_EQ(255u, buffer[2]); + EXPECT_EQ(0, buffer[3]); + + EXPECT_EQ(0, buffer[4]); + EXPECT_EQ(255u, buffer[5]); + EXPECT_EQ(0, buffer[6]); + EXPECT_EQ(0, buffer[7]); + + EXPECT_EQ(255u, buffer[8]); + EXPECT_EQ(0, buffer[9]); + EXPECT_EQ(0, buffer[10]); + EXPECT_EQ(0, buffer[11]); + + callbackHit = true; + }, + false); + + std::array ledData; + led.SetLength(ledData.max_size()); + + ledData[0].SetRGB(255, 0, 0); + ledData[1].SetRGB(0, 255, 0); + ledData[2].SetRGB(0, 0, 255); + led.SetData(ledData); + + EXPECT_TRUE(callbackHit); + + std::array simData; + sim.GetData(simData.data()); + + EXPECT_EQ(0xFF, simData[0].r); + EXPECT_EQ(0x00, simData[0].g); + EXPECT_EQ(0x00, simData[0].b); + EXPECT_EQ(0x00, simData[0].padding); + + EXPECT_EQ(0x00, simData[1].r); + EXPECT_EQ(0xFF, simData[1].g); + EXPECT_EQ(0x00, simData[1].b); + EXPECT_EQ(0x00, simData[1].padding); + + EXPECT_EQ(0x00, simData[2].r); + EXPECT_EQ(0x00, simData[2].g); + EXPECT_EQ(0xFF, simData[2].b); + EXPECT_EQ(0x00, simData[2].padding); +} + +} // namespace frc::sim diff --git a/wpilibc/src/test/native/cpp/simulation/AnalogGyroSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/AnalogGyroSimTest.cpp new file mode 100644 index 0000000000..07eddee0a9 --- /dev/null +++ b/wpilibc/src/test/native/cpp/simulation/AnalogGyroSimTest.cpp @@ -0,0 +1,86 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include "frc/simulation/AnalogGyroSim.h" // NOLINT(build/include_order) + +#include + +#include "callback_helpers/TestCallbackHelpers.h" +#include "frc/AnalogGyro.h" +#include "frc/AnalogInput.h" +#include "gtest/gtest.h" + +namespace frc::sim { + +TEST(AnalogGyroSimTest, InitializeGyro) { + HAL_Initialize(500, 0); + AnalogGyroSim sim{0}; + EXPECT_FALSE(sim.GetInitialized()); + + BooleanCallback initializedCallback; + + auto cb = + sim.RegisterInitializedCallback(initializedCallback.GetCallback(), false); + AnalogGyro gyro(0); + EXPECT_TRUE(sim.GetInitialized()); + EXPECT_TRUE(initializedCallback.WasTriggered()); + EXPECT_TRUE(initializedCallback.GetLastValue()); +} + +TEST(AnalogGyroSimTest, SetAngle) { + HAL_Initialize(500, 0); + + AnalogGyroSim sim{0}; + DoubleCallback callback; + + AnalogInput ai(0); + AnalogGyro gyro(&ai); + auto cb = sim.RegisterAngleCallback(callback.GetCallback(), false); + EXPECT_EQ(0, gyro.GetAngle()); + + constexpr double kTestAngle = 35.04; + sim.SetAngle(kTestAngle); + EXPECT_EQ(kTestAngle, sim.GetAngle()); + EXPECT_EQ(kTestAngle, gyro.GetAngle()); + EXPECT_EQ(-kTestAngle, gyro.GetRotation2d().Degrees().to()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(kTestAngle, callback.GetLastValue()); +} + +TEST(AnalogGyroSimTest, SetRate) { + HAL_Initialize(500, 0); + + AnalogGyroSim sim{0}; + DoubleCallback callback; + + std::shared_ptr ai(new AnalogInput(0)); + AnalogGyro gyro(ai); + auto cb = sim.RegisterRateCallback(callback.GetCallback(), false); + EXPECT_EQ(0, gyro.GetRate()); + + constexpr double kTestRate = -19.1; + sim.SetRate(kTestRate); + EXPECT_EQ(kTestRate, sim.GetRate()); + EXPECT_EQ(kTestRate, gyro.GetRate()); + + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(kTestRate, callback.GetLastValue()); +} + +TEST(AnalogGyroSimTest, Reset) { + HAL_Initialize(500, 0); + + AnalogInput ai{0}; + AnalogGyro gyro(&ai); + AnalogGyroSim sim(gyro); + sim.SetAngle(12.34); + sim.SetRate(43.21); + + sim.ResetData(); + EXPECT_EQ(0, sim.GetAngle()); + EXPECT_EQ(0, sim.GetRate()); + EXPECT_EQ(0, gyro.GetAngle()); + EXPECT_EQ(0, gyro.GetRate()); +} +} // namespace frc::sim diff --git a/wpilibc/src/test/native/cpp/simulation/AnalogInputSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/AnalogInputSimTest.cpp new file mode 100644 index 0000000000..8b4569ebf0 --- /dev/null +++ b/wpilibc/src/test/native/cpp/simulation/AnalogInputSimTest.cpp @@ -0,0 +1,188 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include "frc/simulation/AnalogInputSim.h" // NOLINT(build/include_order) + +#include + +#include "callback_helpers/TestCallbackHelpers.h" +#include "frc/AnalogInput.h" +#include "gtest/gtest.h" + +namespace frc::sim { + +TEST(AnalogInputSimTest, SetInitialized) { + HAL_Initialize(500, 0); + + AnalogInputSim sim{5}; + BooleanCallback callback; + + auto cb = sim.RegisterInitializedCallback(callback.GetCallback(), false); + AnalogInput input{5}; + + EXPECT_TRUE(sim.GetInitialized()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); +} + +TEST(AnalogInputSimTest, SetVoltage) { + HAL_Initialize(500, 0); + + AnalogInputSim sim{5}; + DoubleCallback callback; + + auto cb = sim.RegisterVoltageCallback(callback.GetCallback(), false); + AnalogInput input{5}; + + for (int i = 0; i < 50; ++i) { + double voltage = i * .1; + + callback.Reset(); + + sim.SetVoltage(0); + EXPECT_NEAR(sim.GetVoltage(), 0, 0.001) << " on " << i; + EXPECT_NEAR(input.GetVoltage(), 0, 0.001) << " on " << i; + // 0 -> 0 isn't a change, so callback not called + if (i > 2) { + EXPECT_TRUE(callback.WasTriggered()) << " on " << i; + EXPECT_EQ(0, callback.GetLastValue()) << " on " << i; + } + + callback.Reset(); + sim.SetVoltage(voltage); + EXPECT_NEAR(sim.GetVoltage(), voltage, 0.001) << " on " << i; + EXPECT_NEAR(input.GetVoltage(), voltage, 0.001) << " on " << i; + + // 0 -> 0 isn't a change, so callback not called + if (i != 0) { + EXPECT_TRUE(callback.WasTriggered()) << " on " << i; + EXPECT_EQ(voltage, callback.GetLastValue()) << " on " << i; + } + } +} + +TEST(AnalogInputSimTest, SetOverSampleBits) { + HAL_Initialize(500, 0); + AnalogInput input{5}; + AnalogInputSim sim(input); + + IntCallback callback; + auto cb = sim.RegisterOversampleBitsCallback(callback.GetCallback(), false); + + input.SetOversampleBits(3504); + EXPECT_EQ(3504, sim.GetOversampleBits()); + EXPECT_EQ(3504, input.GetOversampleBits()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(3504, callback.GetLastValue()); +} + +TEST(AnalogInputSimTest, SetAverageBits) { + HAL_Initialize(500, 0); + AnalogInput input{5}; + AnalogInputSim sim(input); + + IntCallback callback; + auto cb = sim.RegisterAverageBitsCallback(callback.GetCallback(), false); + + input.SetAverageBits(3504); + EXPECT_EQ(3504, sim.GetAverageBits()); + EXPECT_EQ(3504, input.GetAverageBits()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(3504, callback.GetLastValue()); +} + +TEST(AnalogInputSimTest, InitAccumulator) { + HAL_Initialize(500, 0); + AnalogInput input{0}; + AnalogInputSim sim(input); + + BooleanCallback callback; + auto cb = + sim.RegisterAccumulatorInitializedCallback(callback.GetCallback(), false); + + input.InitAccumulator(); + input.ResetAccumulator(); + EXPECT_TRUE(sim.GetAccumulatorInitialized()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); +} + +TEST(AnalogInputSimTest, InitAccumulatorOnInvalidPort) { + HAL_Initialize(500, 0); + AnalogInput input{5}; + AnalogInputSim sim(input); + + BooleanCallback callback; + auto cb = + sim.RegisterAccumulatorInitializedCallback(callback.GetCallback(), false); + + EXPECT_THROW(input.InitAccumulator(), std::runtime_error); + EXPECT_FALSE(callback.WasTriggered()); +} + +TEST(AnalogInputSimTest, SetAccumulatorValue) { + HAL_Initialize(500, 0); + AnalogInput input{0}; + AnalogInputSim sim(input); + + LongCallback callback; + auto cb = sim.RegisterAccumulatorValueCallback(callback.GetCallback(), false); + + input.InitAccumulator(); + sim.SetAccumulatorValue(3504191229); + EXPECT_EQ(3504191229, sim.GetAccumulatorValue()); + EXPECT_EQ(3504191229, input.GetAccumulatorValue()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(3504191229, callback.GetLastValue()); +} + +TEST(AnalogInputSimTest, SetAccumulatorCount) { + HAL_Initialize(500, 0); + AnalogInput input{0}; + AnalogInputSim sim(input); + + LongCallback callback; + auto cb = sim.RegisterAccumulatorCountCallback(callback.GetCallback(), false); + + input.InitAccumulator(); + sim.SetAccumulatorCount(3504191229); + EXPECT_EQ(3504191229, sim.GetAccumulatorCount()); + EXPECT_EQ(3504191229, input.GetAccumulatorCount()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(3504191229, callback.GetLastValue()); +} + +TEST(AnalogInputSimTest, SetAccumulatorDeadband) { + HAL_Initialize(500, 0); + AnalogInput input{0}; + AnalogInputSim sim(input); + + IntCallback callback; + auto cb = + sim.RegisterAccumulatorDeadbandCallback(callback.GetCallback(), false); + + input.InitAccumulator(); + input.SetAccumulatorDeadband(3504); + EXPECT_EQ(3504, sim.GetAccumulatorDeadband()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(3504, callback.GetLastValue()); +} + +TEST(AnalogInputSimTest, SetAccumulatorCenter) { + HAL_Initialize(500, 0); + AnalogInput input{0}; + AnalogInputSim sim(input); + + IntCallback callback; + auto cb = + sim.RegisterAccumulatorCenterCallback(callback.GetCallback(), false); + + input.InitAccumulator(); + input.SetAccumulatorCenter(3504); + EXPECT_EQ(3504, sim.GetAccumulatorCenter()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(3504, callback.GetLastValue()); +} + +} // namespace frc::sim diff --git a/wpilibc/src/test/native/cpp/simulation/AnalogOutputSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/AnalogOutputSimTest.cpp new file mode 100644 index 0000000000..630f2c99cd --- /dev/null +++ b/wpilibc/src/test/native/cpp/simulation/AnalogOutputSimTest.cpp @@ -0,0 +1,89 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include "frc/simulation/AnalogOutputSim.h" // NOLINT(build/include_order) + +#include + +#include "callback_helpers/TestCallbackHelpers.h" +#include "frc/AnalogOutput.h" +#include "gtest/gtest.h" + +namespace frc::sim { + +TEST(AnalogOutputSimTest, Initialize) { + HAL_Initialize(500, 0); + + AnalogOutputSim outputSim{0}; + EXPECT_FALSE(outputSim.GetInitialized()); + + BooleanCallback callback; + + auto cb = + outputSim.RegisterInitializedCallback(callback.GetCallback(), false); + AnalogOutput output(0); + EXPECT_TRUE(outputSim.GetInitialized()); + + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); +} + +TEST(AnalogOutputSimTest, SetCallback) { + HAL_Initialize(500, 0); + + AnalogOutput output{0}; + output.SetVoltage(0.5); + + AnalogOutputSim outputSim(output); + + DoubleCallback voltageCallback; + + auto cb = + outputSim.RegisterVoltageCallback(voltageCallback.GetCallback(), false); + + EXPECT_FALSE(voltageCallback.WasTriggered()); + + for (int i = 0; i < 50; ++i) { + double voltage = i * .1; + voltageCallback.Reset(); + + output.SetVoltage(0); + + EXPECT_EQ(0, output.GetVoltage()); + EXPECT_EQ(0, outputSim.GetVoltage()); + + // 0 -> 0 isn't a change, so callback not called + if (i > 2) { + EXPECT_TRUE(voltageCallback.WasTriggered()) << " on " << i; + EXPECT_NEAR(voltageCallback.GetLastValue(), 0, 0.001) << " on " << i; + } + + voltageCallback.Reset(); + + output.SetVoltage(voltage); + + EXPECT_EQ(voltage, output.GetVoltage()); + EXPECT_EQ(voltage, outputSim.GetVoltage()); + + // 0 -> 0 isn't a change, so callback not called + if (i != 0) { + EXPECT_TRUE(voltageCallback.WasTriggered()); + EXPECT_NEAR(voltageCallback.GetLastValue(), voltage, 0.001); + } + } +} + +TEST(AnalogOutputSimTest, Reset) { + HAL_Initialize(500, 0); + + AnalogOutputSim outputSim{0}; + + AnalogOutput output{0}; + output.SetVoltage(1.2); + + outputSim.ResetData(); + EXPECT_EQ(0, output.GetVoltage()); + EXPECT_EQ(0, outputSim.GetVoltage()); +} +} // namespace frc::sim diff --git a/wpilibc/src/test/native/cpp/simulation/AnalogTriggerSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/AnalogTriggerSimTest.cpp new file mode 100644 index 0000000000..5e9e28e610 --- /dev/null +++ b/wpilibc/src/test/native/cpp/simulation/AnalogTriggerSimTest.cpp @@ -0,0 +1,55 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include "frc/simulation/AnalogTriggerSim.h" // NOLINT(build/include_order) + +#include + +#include "callback_helpers/TestCallbackHelpers.h" +#include "frc/AnalogTrigger.h" +#include "gtest/gtest.h" + +namespace frc::sim { + +TEST(AnalogTriggerSimTest, Initialization) { + HAL_Initialize(500, 0); + + AnalogTriggerSim sim = AnalogTriggerSim::CreateForIndex(0); + EXPECT_FALSE(sim.GetInitialized()); + + BooleanCallback callback; + auto cb = sim.RegisterInitializedCallback(callback.GetCallback(), false); + + AnalogTrigger trigger{0}; + EXPECT_TRUE(sim.GetInitialized()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); +} + +TEST(AnalogTriggerSimTest, TriggerLowerBound) { + HAL_Initialize(500, 0); + + AnalogTrigger trigger{0}; + AnalogTriggerSim sim(trigger); + + DoubleCallback lowerCallback; + DoubleCallback upperCallback; + auto lowerCb = + sim.RegisterTriggerLowerBoundCallback(lowerCallback.GetCallback(), false); + auto upperCb = + sim.RegisterTriggerUpperBoundCallback(upperCallback.GetCallback(), false); + + trigger.SetLimitsVoltage(0.299, 1.91); + + EXPECT_EQ(0.299, sim.GetTriggerLowerBound()); + EXPECT_EQ(1.91, sim.GetTriggerUpperBound()); + + EXPECT_TRUE(lowerCallback.WasTriggered()); + EXPECT_EQ(0.299, lowerCallback.GetLastValue()); + + EXPECT_TRUE(upperCallback.WasTriggered()); + EXPECT_EQ(1.91, upperCallback.GetLastValue()); +} + +} // namespace frc::sim diff --git a/wpilibc/src/test/native/cpp/simulation/CTREPCMSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/CTREPCMSimTest.cpp new file mode 100644 index 0000000000..0af7572e75 --- /dev/null +++ b/wpilibc/src/test/native/cpp/simulation/CTREPCMSimTest.cpp @@ -0,0 +1,150 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include "frc/simulation/CTREPCMSim.h" // NOLINT(build/include_order) + +#include + +#include "callback_helpers/TestCallbackHelpers.h" +#include "frc/DoubleSolenoid.h" +#include "frc/PneumaticsControlModule.h" +#include "gtest/gtest.h" + +namespace frc::sim { + +TEST(CTREPCMSimTest, InitializedCallback) { + CTREPCMSim sim; + + sim.ResetData(); + EXPECT_FALSE(sim.GetInitialized()); + + BooleanCallback callback; + auto cb = sim.RegisterInitializedCallback(callback.GetCallback(), false); + + PneumaticsControlModule pcm; + EXPECT_TRUE(sim.GetInitialized()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); +} + +TEST(CTREPCMSimTest, SolenoidOutput) { + PneumaticsControlModule pcm; + CTREPCMSim sim(pcm); + sim.ResetData(); + + DoubleSolenoid doubleSolenoid{pcm, 3, 4}; + + BooleanCallback callback3; + BooleanCallback callback4; + auto cb3 = + sim.RegisterSolenoidOutputCallback(3, callback3.GetCallback(), false); + auto cb4 = + sim.RegisterSolenoidOutputCallback(4, callback4.GetCallback(), false); + + callback3.Reset(); + callback4.Reset(); + doubleSolenoid.Set(DoubleSolenoid::kReverse); + EXPECT_FALSE(callback3.WasTriggered()); + EXPECT_FALSE(callback3.GetLastValue()); + EXPECT_TRUE(callback4.WasTriggered()); + EXPECT_TRUE(callback4.GetLastValue()); + EXPECT_FALSE(sim.GetSolenoidOutput(3)); + EXPECT_TRUE(sim.GetSolenoidOutput(4)); + EXPECT_EQ(0b00010000, pcm.GetSolenoids()); + EXPECT_EQ(0b00010000, sim.GetAllSolenoidOutputs()); + + callback3.Reset(); + callback4.Reset(); + doubleSolenoid.Set(DoubleSolenoid::kForward); + EXPECT_TRUE(callback3.WasTriggered()); + EXPECT_TRUE(callback3.GetLastValue()); + EXPECT_TRUE(callback4.WasTriggered()); + EXPECT_FALSE(callback4.GetLastValue()); + EXPECT_TRUE(sim.GetSolenoidOutput(3)); + EXPECT_FALSE(sim.GetSolenoidOutput(4)); + EXPECT_EQ(0b00001000, pcm.GetSolenoids()); + EXPECT_EQ(0b00001000, sim.GetAllSolenoidOutputs()); + + callback3.Reset(); + callback4.Reset(); + doubleSolenoid.Set(DoubleSolenoid::kOff); + EXPECT_TRUE(callback3.WasTriggered()); + EXPECT_FALSE(callback3.GetLastValue()); + EXPECT_FALSE(callback4.WasTriggered()); + EXPECT_FALSE(callback4.GetLastValue()); + EXPECT_FALSE(sim.GetSolenoidOutput(3)); + EXPECT_FALSE(sim.GetSolenoidOutput(4)); + EXPECT_EQ(0b00000000, pcm.GetSolenoids()); + EXPECT_EQ(0b00000000, sim.GetAllSolenoidOutputs()); +} + +TEST(CTREPCMSimTest, SetCompressorOn) { + PneumaticsControlModule pcm; + CTREPCMSim sim(pcm); + sim.ResetData(); + + BooleanCallback callback; + auto cb = sim.RegisterCompressorOnCallback(callback.GetCallback(), false); + + EXPECT_FALSE(pcm.GetCompressor()); + EXPECT_FALSE(pcm.GetCompressor()); + sim.SetCompressorOn(true); + EXPECT_TRUE(sim.GetCompressorOn()); + EXPECT_TRUE(pcm.GetCompressor()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); +} + +TEST(CTREPCMSimTest, SetClosedLoopEnabled) { + PneumaticsControlModule pcm; + CTREPCMSim sim(pcm); + sim.ResetData(); + + BooleanCallback callback; + auto cb = + sim.RegisterClosedLoopEnabledCallback(callback.GetCallback(), false); + + pcm.SetClosedLoopControl(false); + EXPECT_FALSE(pcm.GetClosedLoopControl()); + + pcm.SetClosedLoopControl(true); + EXPECT_TRUE(sim.GetClosedLoopEnabled()); + EXPECT_TRUE(pcm.GetClosedLoopControl()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); +} + +TEST(CTREPCMSimTest, SetPressureSwitchEnabled) { + PneumaticsControlModule pcm; + CTREPCMSim sim(pcm); + sim.ResetData(); + + BooleanCallback callback; + auto cb = sim.RegisterPressureSwitchCallback(callback.GetCallback(), false); + + EXPECT_FALSE(pcm.GetPressureSwitch()); + + sim.SetPressureSwitch(true); + EXPECT_TRUE(sim.GetPressureSwitch()); + EXPECT_TRUE(pcm.GetPressureSwitch()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); +} + +TEST(CTREPCMSimTest, SetCompressorCurrent) { + PneumaticsControlModule pcm; + CTREPCMSim sim(pcm); + sim.ResetData(); + + DoubleCallback callback; + auto cb = + sim.RegisterCompressorCurrentCallback(callback.GetCallback(), false); + + sim.SetCompressorCurrent(35.04); + EXPECT_EQ(35.04, sim.GetCompressorCurrent()); + EXPECT_EQ(35.04, pcm.GetCompressorCurrent()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(35.04, callback.GetLastValue()); +} +} // namespace frc::sim diff --git a/wpilibc/src/test/native/cpp/simulation/DIOSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/DIOSimTest.cpp new file mode 100644 index 0000000000..338d24ebf5 --- /dev/null +++ b/wpilibc/src/test/native/cpp/simulation/DIOSimTest.cpp @@ -0,0 +1,80 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include "frc/simulation/DIOSim.h" // NOLINT(build/include_order) + +#include + +#include "callback_helpers/TestCallbackHelpers.h" +#include "frc/DigitalInput.h" +#include "frc/DigitalOutput.h" +#include "gtest/gtest.h" + +namespace frc::sim { + +TEST(DIOSimTest, Initialization) { + HAL_Initialize(500, 0); + DIOSim sim{2}; + sim.ResetData(); + EXPECT_FALSE(sim.GetInitialized()); + + BooleanCallback initializeCallback; + BooleanCallback isInputCallback; + + auto initializeCb = + sim.RegisterInitializedCallback(initializeCallback.GetCallback(), false); + auto inputCb = + sim.RegisterIsInputCallback(isInputCallback.GetCallback(), false); + + DigitalOutput output(2); + EXPECT_TRUE(sim.GetInitialized()); + EXPECT_TRUE(initializeCallback.WasTriggered()); + EXPECT_TRUE(initializeCallback.GetLastValue()); + EXPECT_FALSE(sim.GetIsInput()); + EXPECT_TRUE(isInputCallback.WasTriggered()); + EXPECT_FALSE(isInputCallback.GetLastValue()); + + initializeCallback.Reset(); + sim.SetInitialized(false); + EXPECT_TRUE(initializeCallback.WasTriggered()); + EXPECT_FALSE(initializeCallback.GetLastValue()); +} + +TEST(DIOSimTest, Input) { + HAL_Initialize(500, 0); + + DigitalInput input{0}; + DIOSim sim(input); + EXPECT_TRUE(sim.GetIsInput()); + + BooleanCallback valueCallback; + + auto cb = sim.RegisterValueCallback(valueCallback.GetCallback(), false); + EXPECT_TRUE(input.Get()); + EXPECT_TRUE(sim.GetValue()); + + EXPECT_FALSE(valueCallback.WasTriggered()); + sim.SetValue(false); + EXPECT_TRUE(valueCallback.WasTriggered()); + EXPECT_FALSE(valueCallback.GetLastValue()); +} + +TEST(DIOSimTest, Output) { + HAL_Initialize(500, 0); + DigitalOutput output{0}; + DIOSim sim(output); + EXPECT_FALSE(sim.GetIsInput()); + + BooleanCallback valueCallback; + + auto cb = sim.RegisterValueCallback(valueCallback.GetCallback(), false); + EXPECT_FALSE(output.Get()); + EXPECT_FALSE(sim.GetValue()); + + EXPECT_FALSE(valueCallback.WasTriggered()); + output.Set(true); + EXPECT_TRUE(valueCallback.WasTriggered()); + EXPECT_TRUE(valueCallback.GetLastValue()); +} +} // namespace frc::sim diff --git a/wpilibc/src/test/native/cpp/simulation/DigitalPWMSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/DigitalPWMSimTest.cpp new file mode 100644 index 0000000000..fd62edcc2c --- /dev/null +++ b/wpilibc/src/test/native/cpp/simulation/DigitalPWMSimTest.cpp @@ -0,0 +1,57 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include "frc/simulation/DigitalPWMSim.h" // NOLINT(build/include_order) + +#include + +#include "callback_helpers/TestCallbackHelpers.h" +#include "frc/DigitalOutput.h" +#include "gtest/gtest.h" + +namespace frc::sim { + +TEST(DigitalPWMSimTest, Initialize) { + HAL_Initialize(500, 0); + + DigitalOutput output{0}; + DigitalPWMSim sim(output); + EXPECT_FALSE(sim.GetInitialized()); + + BooleanCallback initializeCallback; + auto initCb = + sim.RegisterInitializedCallback(initializeCallback.GetCallback(), false); + + DoubleCallback dutyCycleCallback; + auto dutyCycleCB = + sim.RegisterDutyCycleCallback(dutyCycleCallback.GetCallback(), false); + + constexpr double kTestDutyCycle = 0.191; + output.EnablePWM(kTestDutyCycle); + + EXPECT_TRUE(sim.GetInitialized()); + EXPECT_TRUE(initializeCallback.WasTriggered()); + EXPECT_TRUE(initializeCallback.GetLastValue()); + + EXPECT_EQ(kTestDutyCycle, sim.GetDutyCycle()); + EXPECT_TRUE(dutyCycleCallback.WasTriggered()); + EXPECT_EQ(kTestDutyCycle, dutyCycleCallback.GetLastValue()); +} + +TEST(DigitalPWMSimTest, SetPin) { + HAL_Initialize(500, 0); + + DigitalOutput output{2}; + DigitalPWMSim sim(output); + + IntCallback callback; + auto cb = sim.RegisterPinCallback(callback.GetCallback(), false); + + sim.SetPin(191); + EXPECT_EQ(191, sim.GetPin()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(191, callback.GetLastValue()); +} + +} // namespace frc::sim diff --git a/wpilibc/src/test/native/cpp/simulation/DriverStationSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/DriverStationSimTest.cpp new file mode 100644 index 0000000000..9a76140bee --- /dev/null +++ b/wpilibc/src/test/native/cpp/simulation/DriverStationSimTest.cpp @@ -0,0 +1,238 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include +#include + +#include "callback_helpers/TestCallbackHelpers.h" +#include "frc/DriverStation.h" +#include "frc/Joystick.h" +#include "frc/RobotState.h" +#include "frc/simulation/DriverStationSim.h" +#include "frc/simulation/SimHooks.h" +#include "gtest/gtest.h" + +using namespace frc; +using namespace frc::sim; + +TEST(DriverStationTest, Enabled) { + HAL_Initialize(500, 0); + DriverStationSim::ResetData(); + + EXPECT_FALSE(DriverStation::IsEnabled()); + BooleanCallback callback; + auto cb = + DriverStationSim::RegisterEnabledCallback(callback.GetCallback(), false); + DriverStationSim::SetEnabled(true); + DriverStationSim::NotifyNewData(); + EXPECT_TRUE(DriverStationSim::GetEnabled()); + EXPECT_TRUE(DriverStation::IsEnabled()); + EXPECT_TRUE(RobotState::IsEnabled()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); +} + +TEST(DriverStationTest, AutonomousMode) { + HAL_Initialize(500, 0); + DriverStationSim::ResetData(); + + EXPECT_FALSE(DriverStation::IsAutonomous()); + BooleanCallback callback; + auto cb = DriverStationSim::RegisterAutonomousCallback(callback.GetCallback(), + false); + DriverStationSim::SetAutonomous(true); + DriverStationSim::NotifyNewData(); + EXPECT_TRUE(DriverStationSim::GetAutonomous()); + EXPECT_TRUE(DriverStation::IsAutonomous()); + EXPECT_TRUE(RobotState::IsAutonomous()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); +} + +TEST(DriverStationTest, TestMode) { + HAL_Initialize(500, 0); + DriverStationSim::ResetData(); + + EXPECT_FALSE(DriverStation::IsTest()); + BooleanCallback callback; + auto cb = + DriverStationSim::RegisterTestCallback(callback.GetCallback(), false); + DriverStationSim::SetTest(true); + DriverStationSim::NotifyNewData(); + EXPECT_TRUE(DriverStationSim::GetTest()); + EXPECT_TRUE(DriverStation::IsTest()); + EXPECT_TRUE(RobotState::IsTest()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); +} + +TEST(DriverStationTest, Estop) { + HAL_Initialize(500, 0); + DriverStationSim::ResetData(); + + EXPECT_FALSE(DriverStation::IsEStopped()); + BooleanCallback callback; + auto cb = + DriverStationSim::RegisterEStopCallback(callback.GetCallback(), false); + DriverStationSim::SetEStop(true); + DriverStationSim::NotifyNewData(); + EXPECT_TRUE(DriverStationSim::GetEStop()); + EXPECT_TRUE(DriverStation::IsEStopped()); + EXPECT_TRUE(RobotState::IsEStopped()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); +} + +TEST(DriverStationTest, FmsAttached) { + HAL_Initialize(500, 0); + DriverStationSim::ResetData(); + + EXPECT_FALSE(DriverStation::IsFMSAttached()); + BooleanCallback callback; + auto cb = DriverStationSim::RegisterFmsAttachedCallback( + callback.GetCallback(), false); + DriverStationSim::SetFmsAttached(true); + DriverStationSim::NotifyNewData(); + EXPECT_TRUE(DriverStationSim::GetFmsAttached()); + EXPECT_TRUE(DriverStation::IsFMSAttached()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); +} + +TEST(DriverStationTest, DsAttached) { + HAL_Initialize(500, 0); + DriverStationSim::ResetData(); + + DriverStationSim::NotifyNewData(); + EXPECT_TRUE(DriverStation::IsDSAttached()); + + BooleanCallback callback; + auto cb = DriverStationSim::RegisterDsAttachedCallback(callback.GetCallback(), + false); + DriverStationSim::SetDsAttached(false); + DriverStationSim::NotifyNewData(); + EXPECT_FALSE(DriverStationSim::GetDsAttached()); + EXPECT_FALSE(DriverStation::IsDSAttached()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_FALSE(callback.GetLastValue()); +} + +TEST(DriverStationTest, AllianceStationId) { + HAL_Initialize(500, 0); + DriverStationSim::ResetData(); + + EnumCallback callback; + + HAL_AllianceStationID allianceStation = HAL_AllianceStationID_kBlue2; + DriverStationSim::SetAllianceStationId(allianceStation); + + auto cb = DriverStationSim::RegisterAllianceStationIdCallback( + callback.GetCallback(), false); + // B1 + allianceStation = HAL_AllianceStationID_kBlue1; + DriverStationSim::SetAllianceStationId(allianceStation); + EXPECT_EQ(allianceStation, DriverStationSim::GetAllianceStationId()); + EXPECT_EQ(DriverStation::kBlue, DriverStation::GetAlliance()); + EXPECT_EQ(1, DriverStation::GetLocation()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(allianceStation, callback.GetLastValue()); + + // B2 + allianceStation = HAL_AllianceStationID_kBlue2; + DriverStationSim::SetAllianceStationId(allianceStation); + EXPECT_EQ(allianceStation, DriverStationSim::GetAllianceStationId()); + EXPECT_EQ(DriverStation::kBlue, DriverStation::GetAlliance()); + EXPECT_EQ(2, DriverStation::GetLocation()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(allianceStation, callback.GetLastValue()); + + // B3 + allianceStation = HAL_AllianceStationID_kBlue3; + DriverStationSim::SetAllianceStationId(allianceStation); + EXPECT_EQ(allianceStation, DriverStationSim::GetAllianceStationId()); + EXPECT_EQ(DriverStation::kBlue, DriverStation::GetAlliance()); + EXPECT_EQ(3, DriverStation::GetLocation()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(allianceStation, callback.GetLastValue()); + + // R1 + allianceStation = HAL_AllianceStationID_kRed1; + DriverStationSim::SetAllianceStationId(allianceStation); + EXPECT_EQ(allianceStation, DriverStationSim::GetAllianceStationId()); + EXPECT_EQ(DriverStation::kRed, DriverStation::GetAlliance()); + EXPECT_EQ(1, DriverStation::GetLocation()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(allianceStation, callback.GetLastValue()); + + // R2 + allianceStation = HAL_AllianceStationID_kRed2; + DriverStationSim::SetAllianceStationId(allianceStation); + EXPECT_EQ(allianceStation, DriverStationSim::GetAllianceStationId()); + EXPECT_EQ(DriverStation::kRed, DriverStation::GetAlliance()); + EXPECT_EQ(2, DriverStation::GetLocation()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(allianceStation, callback.GetLastValue()); + + // R3 + allianceStation = HAL_AllianceStationID_kRed3; + DriverStationSim::SetAllianceStationId(allianceStation); + EXPECT_EQ(allianceStation, DriverStationSim::GetAllianceStationId()); + EXPECT_EQ(DriverStation::kRed, DriverStation::GetAlliance()); + EXPECT_EQ(3, DriverStation::GetLocation()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(allianceStation, callback.GetLastValue()); +} + +TEST(DriverStationTest, ReplayNumber) { + HAL_Initialize(500, 0); + DriverStationSim::ResetData(); + + DriverStationSim::SetReplayNumber(4); + DriverStationSim::NotifyNewData(); + EXPECT_EQ(4, DriverStation::GetReplayNumber()); +} + +TEST(DriverStationTest, MatchNumber) { + HAL_Initialize(500, 0); + DriverStationSim::ResetData(); + + DriverStationSim::SetMatchNumber(3); + DriverStationSim::NotifyNewData(); + EXPECT_EQ(3, DriverStation::GetMatchNumber()); +} + +TEST(DriverStationTest, MatchTime) { + HAL_Initialize(500, 0); + DriverStationSim::ResetData(); + + DoubleCallback callback; + auto cb = DriverStationSim::RegisterMatchTimeCallback(callback.GetCallback(), + false); + constexpr double kTestTime = 19.174; + DriverStationSim::SetMatchTime(kTestTime); + EXPECT_EQ(kTestTime, DriverStationSim::GetMatchTime()); + EXPECT_EQ(kTestTime, DriverStation::GetMatchTime()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(kTestTime, callback.GetLastValue()); +} + +TEST(DriverStationTest, SetGameSpecificMessage) { + HAL_Initialize(500, 0); + DriverStationSim::ResetData(); + + constexpr auto message = "Hello World!"; + DriverStationSim::SetGameSpecificMessage(message); + DriverStationSim::NotifyNewData(); + EXPECT_EQ(message, DriverStation::GetGameSpecificMessage()); +} + +TEST(DriverStationTest, SetEventName) { + HAL_Initialize(500, 0); + DriverStationSim::ResetData(); + + constexpr auto message = "The Best Event"; + DriverStationSim::SetEventName(message); + DriverStationSim::NotifyNewData(); + EXPECT_EQ(message, DriverStation::GetEventName()); +} diff --git a/wpilibc/src/test/native/cpp/simulation/DutyCycleEncoderSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/DutyCycleEncoderSimTest.cpp new file mode 100644 index 0000000000..8249499b02 --- /dev/null +++ b/wpilibc/src/test/native/cpp/simulation/DutyCycleEncoderSimTest.cpp @@ -0,0 +1,35 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include "frc/simulation/DutyCycleEncoderSim.h" // NOLINT(build/include_order) + +#include + +#include "callback_helpers/TestCallbackHelpers.h" +#include "frc/DutyCycleEncoder.h" +#include "gtest/gtest.h" + +namespace frc::sim { + +TEST(DutyCycleEncoderSimTest, Set) { + HAL_Initialize(500, 0); + + DutyCycleEncoder enc{0}; + DutyCycleEncoderSim sim(enc); + + constexpr units::turn_t kTestValue{5.67}; + sim.Set(kTestValue); + EXPECT_EQ(kTestValue, enc.Get()); +} + +TEST(DutyCycleEncoderSimTest, SetDistance) { + HAL_Initialize(500, 0); + + DutyCycleEncoder enc{0}; + DutyCycleEncoderSim sim(enc); + sim.SetDistance(19.1); + EXPECT_EQ(19.1, enc.GetDistance()); +} + +} // namespace frc::sim diff --git a/wpilibc/src/test/native/cpp/simulation/DutyCycleSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/DutyCycleSimTest.cpp new file mode 100644 index 0000000000..56e0592fd6 --- /dev/null +++ b/wpilibc/src/test/native/cpp/simulation/DutyCycleSimTest.cpp @@ -0,0 +1,70 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include "frc/simulation/DutyCycleSim.h" // NOLINT(build/include_order) + +#include + +#include "callback_helpers/TestCallbackHelpers.h" +#include "frc/DigitalInput.h" +#include "frc/DutyCycle.h" +#include "gtest/gtest.h" + +namespace frc::sim { + +TEST(DutyCycleSimTest, Initialization) { + HAL_Initialize(500, 0); + DutyCycleSim sim = DutyCycleSim::CreateForIndex(0); + EXPECT_FALSE(sim.GetInitialized()); + + BooleanCallback callback; + auto cb = sim.RegisterInitializedCallback(callback.GetCallback(), false); + + DigitalInput di{2}; + DutyCycle dc{&di}; + EXPECT_TRUE(sim.GetInitialized()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); + + callback.Reset(); + sim.SetInitialized(false); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_FALSE(callback.GetLastValue()); +} + +TEST(DutyCycleSimTest, SetFrequency) { + HAL_Initialize(500, 0); + + DigitalInput di{2}; + DutyCycle dc{di}; + DutyCycleSim sim(dc); + + IntCallback callback; + auto cb = sim.RegisterFrequencyCallback(callback.GetCallback(), false); + + sim.SetFrequency(191); + EXPECT_EQ(191, sim.GetFrequency()); + EXPECT_EQ(191, dc.GetFrequency()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(191, callback.GetLastValue()); +} + +TEST(DutyCycleSimTest, SetOutput) { + HAL_Initialize(500, 0); + + DigitalInput di{2}; + DutyCycle dc{di}; + DutyCycleSim sim(dc); + + DoubleCallback callback; + auto cb = sim.RegisterOutputCallback(callback.GetCallback(), false); + + sim.SetOutput(229.174); + EXPECT_EQ(229.174, sim.GetOutput()); + EXPECT_EQ(229.174, dc.GetOutput()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(229.174, callback.GetLastValue()); +} + +} // namespace frc::sim diff --git a/wpilibc/src/test/native/cpp/simulation/EncoderSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/EncoderSimTest.cpp new file mode 100644 index 0000000000..58a147dfa0 --- /dev/null +++ b/wpilibc/src/test/native/cpp/simulation/EncoderSimTest.cpp @@ -0,0 +1,230 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include "frc/simulation/EncoderSim.h" // NOLINT(build/include_order) + +#include + +#include "callback_helpers/TestCallbackHelpers.h" +#include "frc/Encoder.h" +#include "gtest/gtest.h" + +namespace frc::sim { + +namespace { +constexpr double kDefaultDistancePerPulse = .0005; +} // namespace + +TEST(EncoderSimTest, Initialize) { + HAL_Initialize(500, 0); + + EncoderSim sim = EncoderSim::CreateForIndex(0); + sim.ResetData(); + + BooleanCallback callback; + auto cb = sim.RegisterInitializedCallback(callback.GetCallback(), false); + + Encoder encoder(0, 1); + + EXPECT_TRUE(sim.GetInitialized()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); +} + +TEST(EncoderSimTest, Rate) { + HAL_Initialize(500, 0); + + Encoder encoder(0, 1); + EncoderSim sim(encoder); + sim.ResetData(); + + encoder.SetDistancePerPulse(kDefaultDistancePerPulse); + + sim.SetRate(1.91); + EXPECT_EQ(1.91, sim.GetRate()); +} + +TEST(EncoderSimTest, Count) { + HAL_Initialize(500, 0); + + Encoder encoder(0, 1); + EncoderSim sim(encoder); + sim.ResetData(); + + encoder.SetDistancePerPulse(kDefaultDistancePerPulse); + + IntCallback callback; + auto cb = sim.RegisterCountCallback(callback.GetCallback(), false); + sim.SetCount(3504); + EXPECT_EQ(3504, sim.GetCount()); + + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(3504, encoder.Get()); + EXPECT_EQ(3504, callback.GetLastValue()); +} + +TEST(EncoderSimTest, Distance) { + HAL_Initialize(500, 0); + + Encoder encoder(0, 1); + EncoderSim sim(encoder); + sim.ResetData(); + + encoder.SetDistancePerPulse(kDefaultDistancePerPulse); + + sim.SetDistance(229.174); + EXPECT_EQ(229.174, sim.GetDistance()); + EXPECT_EQ(229.174, encoder.GetDistance()); +} + +TEST(EncoderSimTest, Period) { + HAL_Initialize(500, 0); + + Encoder encoder(0, 1); + EncoderSim sim(encoder); + sim.ResetData(); + + encoder.SetDistancePerPulse(kDefaultDistancePerPulse); + + DoubleCallback callback; + auto cb = sim.RegisterPeriodCallback(callback.GetCallback(), false); + sim.SetPeriod(123.456); + EXPECT_EQ(123.456, sim.GetPeriod()); + EXPECT_EQ(123.456, encoder.GetPeriod().to()); + EXPECT_EQ(kDefaultDistancePerPulse / 123.456, encoder.GetRate()); + + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(123.456, callback.GetLastValue()); +} + +TEST(EncoderSimTest, SetMaxPeriod) { + HAL_Initialize(500, 0); + + Encoder encoder(0, 1); + EncoderSim sim(encoder); + sim.ResetData(); + + encoder.SetDistancePerPulse(kDefaultDistancePerPulse); + + DoubleCallback callback; + auto cb = sim.RegisterMaxPeriodCallback(callback.GetCallback(), false); + + encoder.SetMaxPeriod(units::second_t{123.456}); + EXPECT_EQ(123.456, sim.GetMaxPeriod()); + + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(123.456, callback.GetLastValue()); +} + +TEST(EncoderSimTest, SetDirection) { + HAL_Initialize(500, 0); + + Encoder encoder(0, 1); + EncoderSim sim(encoder); + sim.ResetData(); + + encoder.SetDistancePerPulse(kDefaultDistancePerPulse); + + BooleanCallback callback; + auto cb = sim.RegisterDirectionCallback(callback.GetCallback(), false); + + sim.SetDirection(true); + EXPECT_TRUE(sim.GetDirection()); + EXPECT_TRUE(encoder.GetDirection()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); + + sim.SetDirection(false); + EXPECT_FALSE(sim.GetDirection()); + EXPECT_FALSE(encoder.GetDirection()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_FALSE(callback.GetLastValue()); +} + +TEST(EncoderSimTest, SetReverseDirection) { + HAL_Initialize(500, 0); + + Encoder encoder(0, 1); + EncoderSim sim(encoder); + sim.ResetData(); + + encoder.SetDistancePerPulse(kDefaultDistancePerPulse); + + BooleanCallback callback; + auto cb = sim.RegisterReverseDirectionCallback(callback.GetCallback(), false); + + encoder.SetReverseDirection(true); + EXPECT_TRUE(sim.GetReverseDirection()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); + + encoder.SetReverseDirection(false); + EXPECT_FALSE(sim.GetReverseDirection()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_FALSE(callback.GetLastValue()); +} + +TEST(EncoderSimTest, SetSamplesToAverage) { + HAL_Initialize(500, 0); + + Encoder encoder(0, 1); + EncoderSim sim(encoder); + sim.ResetData(); + + encoder.SetDistancePerPulse(kDefaultDistancePerPulse); + + IntCallback callback; + auto cb = sim.RegisterSamplesToAverageCallback(callback.GetCallback(), false); + + encoder.SetSamplesToAverage(57); + EXPECT_EQ(57, sim.GetSamplesToAverage()); + EXPECT_EQ(57, encoder.GetSamplesToAverage()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(57, callback.GetLastValue()); +} + +TEST(EncoderSimTest, SetDistancePerPulse) { + HAL_Initialize(500, 0); + + Encoder encoder(0, 1); + EncoderSim sim(encoder); + sim.ResetData(); + + DoubleCallback callback; + auto cb = sim.RegisterDistancePerPulseCallback(callback.GetCallback(), false); + + encoder.SetDistancePerPulse(.03405); + EXPECT_EQ(.03405, sim.GetDistancePerPulse()); + EXPECT_EQ(.03405, encoder.GetDistancePerPulse()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(.03405, callback.GetLastValue()); +} + +TEST(EncoderSimTest, Reset) { + HAL_Initialize(500, 0); + + Encoder encoder(0, 1); + EncoderSim sim(encoder); + sim.ResetData(); + + encoder.SetDistancePerPulse(kDefaultDistancePerPulse); + + BooleanCallback callback; + auto cb = sim.RegisterResetCallback(callback.GetCallback(), false); + + sim.SetCount(3504); + sim.SetDistance(229.191); + + encoder.Reset(); + EXPECT_TRUE(sim.GetReset()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); + + EXPECT_EQ(0, sim.GetCount()); + EXPECT_EQ(0, encoder.Get()); + EXPECT_EQ(0, sim.GetDistance()); + EXPECT_EQ(0, encoder.GetDistance()); +} + +} // namespace frc::sim diff --git a/wpilibc/src/test/native/cpp/simulation/PDPSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/PDPSimTest.cpp new file mode 100644 index 0000000000..e5d28d2283 --- /dev/null +++ b/wpilibc/src/test/native/cpp/simulation/PDPSimTest.cpp @@ -0,0 +1,82 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include "frc/simulation/PowerDistributionSim.h" // NOLINT(build/include_order) + +#include + +#include "callback_helpers/TestCallbackHelpers.h" +#include "frc/PowerDistribution.h" +#include "gtest/gtest.h" + +namespace frc::sim { + +TEST(PowerDistributionSimTest, Initialize) { + HAL_Initialize(500, 0); + PowerDistributionSim sim{2}; + EXPECT_FALSE(sim.GetInitialized()); + + BooleanCallback callback; + + auto cb = sim.RegisterInitializedCallback(callback.GetCallback(), false); + PowerDistribution pdp(2); + EXPECT_TRUE(sim.GetInitialized()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); + + callback.Reset(); + sim.SetInitialized(false); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_FALSE(callback.GetLastValue()); +} + +TEST(PowerDistributionSimTest, SetTemperature) { + HAL_Initialize(500, 0); + PowerDistribution pdp{2}; + PowerDistributionSim sim(pdp); + + DoubleCallback callback; + auto cb = sim.RegisterTemperatureCallback(callback.GetCallback(), false); + + sim.SetTemperature(35.04); + EXPECT_EQ(35.04, sim.GetTemperature()); + EXPECT_EQ(35.04, pdp.GetTemperature()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); +} + +TEST(PowerDistributionSimTest, SetVoltage) { + HAL_Initialize(500, 0); + PowerDistribution pdp{2}; + PowerDistributionSim sim(pdp); + + DoubleCallback callback; + auto cb = sim.RegisterVoltageCallback(callback.GetCallback(), false); + + sim.SetVoltage(35.04); + EXPECT_EQ(35.04, sim.GetVoltage()); + EXPECT_EQ(35.04, pdp.GetVoltage()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); +} + +TEST(PowerDistributionSimTest, SetCurrent) { + HAL_Initialize(500, 0); + PowerDistribution pdp{2}; + PowerDistributionSim sim(pdp); + + for (int channel = 0; channel < HAL_GetNumPDPChannels(); ++channel) { + DoubleCallback callback; + auto cb = + sim.RegisterCurrentCallback(channel, callback.GetCallback(), false); + + const double kTestCurrent = 35.04 + channel; + sim.SetCurrent(channel, kTestCurrent); + EXPECT_EQ(kTestCurrent, sim.GetCurrent(channel)); + EXPECT_EQ(kTestCurrent, pdp.GetCurrent(channel)); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); + } +} +} // namespace frc::sim diff --git a/wpilibc/src/test/native/cpp/simulation/PWMSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/PWMSimTest.cpp new file mode 100644 index 0000000000..0df35907d7 --- /dev/null +++ b/wpilibc/src/test/native/cpp/simulation/PWMSimTest.cpp @@ -0,0 +1,120 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include "frc/simulation/PWMSim.h" // NOLINT(build/include_order) + +#include + +#include "callback_helpers/TestCallbackHelpers.h" +#include "frc/PWM.h" +#include "gtest/gtest.h" + +namespace frc::sim { + +TEST(PWMSimTest, Initialize) { + HAL_Initialize(500, 0); + + PWMSim sim{0}; + sim.ResetData(); + EXPECT_FALSE(sim.GetInitialized()); + + BooleanCallback callback; + + auto cb = sim.RegisterInitializedCallback(callback.GetCallback(), false); + PWM pwm{0}; + EXPECT_TRUE(sim.GetInitialized()); +} + +TEST(PWMSimTest, SetRawValue) { + HAL_Initialize(500, 0); + + PWMSim sim{0}; + sim.ResetData(); + EXPECT_FALSE(sim.GetInitialized()); + + IntCallback callback; + + auto cb = sim.RegisterRawValueCallback(callback.GetCallback(), false); + PWM pwm{0}; + sim.SetRawValue(229); + EXPECT_EQ(229, sim.GetRawValue()); + EXPECT_EQ(229, pwm.GetRaw()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(229, callback.GetLastValue()); +} + +TEST(PWMSimTest, SetSpeed) { + HAL_Initialize(500, 0); + + PWMSim sim{0}; + sim.ResetData(); + EXPECT_FALSE(sim.GetInitialized()); + + DoubleCallback callback; + + auto cb = sim.RegisterSpeedCallback(callback.GetCallback(), false); + PWM pwm{0}; + constexpr double kTestValue = 0.3504; + pwm.SetSpeed(kTestValue); + + EXPECT_EQ(kTestValue, sim.GetSpeed()); + EXPECT_EQ(kTestValue, pwm.GetSpeed()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(kTestValue, callback.GetLastValue()); +} + +TEST(PWMSimTest, SetPosition) { + HAL_Initialize(500, 0); + + PWMSim sim{0}; + sim.ResetData(); + EXPECT_FALSE(sim.GetInitialized()); + + DoubleCallback callback; + + auto cb = sim.RegisterPositionCallback(callback.GetCallback(), false); + PWM pwm{0}; + constexpr double kTestValue = 0.3504; + pwm.SetPosition(kTestValue); + + EXPECT_EQ(kTestValue, sim.GetPosition()); + EXPECT_EQ(kTestValue, pwm.GetPosition()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(kTestValue, callback.GetLastValue()); +} + +TEST(PWMSimTest, SetPeriodScale) { + HAL_Initialize(500, 0); + + PWMSim sim{0}; + sim.ResetData(); + EXPECT_FALSE(sim.GetInitialized()); + + IntCallback callback; + + auto cb = sim.RegisterPeriodScaleCallback(callback.GetCallback(), false); + PWM pwm{0}; + sim.SetPeriodScale(3504); + EXPECT_EQ(3504, sim.GetPeriodScale()); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(3504, callback.GetLastValue()); +} + +TEST(PWMSimTest, SetZeroLatch) { + HAL_Initialize(500, 0); + + PWMSim sim{0}; + sim.ResetData(); + EXPECT_FALSE(sim.GetInitialized()); + + BooleanCallback callback; + + auto cb = sim.RegisterZeroLatchCallback(callback.GetCallback(), false); + PWM pwm{0}; + pwm.SetZeroLatch(); + + EXPECT_TRUE(callback.WasTriggered()); +} + +} // namespace frc::sim diff --git a/wpilibc/src/test/native/cpp/simulation/RelaySimTest.cpp b/wpilibc/src/test/native/cpp/simulation/RelaySimTest.cpp new file mode 100644 index 0000000000..292d6290bb --- /dev/null +++ b/wpilibc/src/test/native/cpp/simulation/RelaySimTest.cpp @@ -0,0 +1,204 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include "frc/simulation/RelaySim.h" // NOLINT(build/include_order) + +#include + +#include "callback_helpers/TestCallbackHelpers.h" +#include "frc/Relay.h" +#include "gtest/gtest.h" + +namespace frc::sim { + +TEST(RelaySimTest, InitializationBidrectional) { + HAL_Initialize(500, 0); + + RelaySim sim(0); + sim.ResetData(); + + BooleanCallback forwardCallback; + BooleanCallback reverseCallback; + + EXPECT_FALSE(sim.GetInitializedForward()); + EXPECT_FALSE(sim.GetInitializedReverse()); + + auto fwdCb = sim.RegisterInitializedForwardCallback( + forwardCallback.GetCallback(), false); + auto revCb = sim.RegisterInitializedReverseCallback( + reverseCallback.GetCallback(), false); + Relay relay{0}; + + EXPECT_TRUE(sim.GetInitializedForward()); + EXPECT_TRUE(sim.GetInitializedReverse()); + + EXPECT_TRUE(forwardCallback.WasTriggered()); + EXPECT_TRUE(forwardCallback.GetLastValue()); + EXPECT_TRUE(reverseCallback.WasTriggered()); + EXPECT_TRUE(reverseCallback.GetLastValue()); +} + +TEST(RelaySimTest, InitializationForwardOnly) { + HAL_Initialize(500, 0); + + RelaySim sim{0}; + sim.ResetData(); + + BooleanCallback forwardCallback; + BooleanCallback reverseCallback; + + EXPECT_FALSE(sim.GetInitializedForward()); + EXPECT_FALSE(sim.GetInitializedReverse()); + + auto fwdCb = sim.RegisterInitializedForwardCallback( + forwardCallback.GetCallback(), false); + auto revCb = sim.RegisterInitializedReverseCallback( + reverseCallback.GetCallback(), false); + Relay relay(0, Relay::kForwardOnly); + + EXPECT_TRUE(sim.GetInitializedForward()); + EXPECT_FALSE(sim.GetInitializedReverse()); + + EXPECT_TRUE(forwardCallback.WasTriggered()); + EXPECT_TRUE(forwardCallback.GetLastValue()); + EXPECT_FALSE(reverseCallback.WasTriggered()); +} + +TEST(RelaySimTest, InitializationReverseOnly) { + HAL_Initialize(500, 0); + + RelaySim sim{0}; + sim.ResetData(); + + BooleanCallback forwardCallback; + BooleanCallback reverseCallback; + + EXPECT_FALSE(sim.GetInitializedForward()); + EXPECT_FALSE(sim.GetInitializedReverse()); + + auto fwdCb = sim.RegisterInitializedForwardCallback( + forwardCallback.GetCallback(), false); + auto revCb = sim.RegisterInitializedReverseCallback( + reverseCallback.GetCallback(), false); + Relay relay(0, Relay::kReverseOnly); + + EXPECT_FALSE(sim.GetInitializedForward()); + EXPECT_TRUE(sim.GetInitializedReverse()); + + EXPECT_FALSE(forwardCallback.WasTriggered()); + EXPECT_TRUE(reverseCallback.WasTriggered()); + EXPECT_TRUE(reverseCallback.GetLastValue()); +} + +TEST(RelaySimTest, BidirectionalSetForward) { + HAL_Initialize(500, 0); + + RelaySim sim{0}; + BooleanCallback forwardCallback; + BooleanCallback reverseCallback; + + Relay relay{0}; + auto fwdCb = + sim.RegisterForwardCallback(forwardCallback.GetCallback(), false); + auto revCb = + sim.RegisterReverseCallback(reverseCallback.GetCallback(), false); + + relay.Set(Relay::kForward); + EXPECT_EQ(Relay::kForward, relay.Get()); + EXPECT_TRUE(sim.GetForward()); + EXPECT_FALSE(sim.GetReverse()); + + EXPECT_TRUE(forwardCallback.WasTriggered()); + EXPECT_TRUE(forwardCallback.GetLastValue()); + EXPECT_FALSE(reverseCallback.WasTriggered()); +} + +TEST(RelaySimTest, BidirectionalSetReverse) { + HAL_Initialize(500, 0); + + RelaySim sim{0}; + BooleanCallback forwardCallback; + BooleanCallback reverseCallback; + + Relay relay{0}; + auto fwdCb = + sim.RegisterForwardCallback(forwardCallback.GetCallback(), false); + auto revCb = + sim.RegisterReverseCallback(reverseCallback.GetCallback(), false); + + relay.Set(Relay::kReverse); + EXPECT_EQ(Relay::kReverse, relay.Get()); + EXPECT_FALSE(sim.GetForward()); + EXPECT_TRUE(sim.GetReverse()); + + EXPECT_FALSE(forwardCallback.WasTriggered()); + EXPECT_TRUE(reverseCallback.WasTriggered()); + EXPECT_TRUE(reverseCallback.GetLastValue()); +} + +TEST(RelaySimTest, BidirectionalSetOn) { + HAL_Initialize(500, 0); + + RelaySim sim{0}; + BooleanCallback forwardCallback; + BooleanCallback reverseCallback; + + Relay relay{0}; + auto fwdCb = + sim.RegisterForwardCallback(forwardCallback.GetCallback(), false); + auto revCb = + sim.RegisterReverseCallback(reverseCallback.GetCallback(), false); + + relay.Set(Relay::kOn); + EXPECT_EQ(Relay::kOn, relay.Get()); + EXPECT_TRUE(sim.GetForward()); + EXPECT_TRUE(sim.GetReverse()); + + EXPECT_TRUE(forwardCallback.WasTriggered()); + EXPECT_TRUE(forwardCallback.GetLastValue()); + EXPECT_TRUE(reverseCallback.WasTriggered()); + EXPECT_TRUE(reverseCallback.GetLastValue()); +} + +TEST(RelaySimTest, BidirectionalSetOff) { + HAL_Initialize(500, 0); + + RelaySim sim{0}; + BooleanCallback forwardCallback; + BooleanCallback reverseCallback; + + Relay relay{0}; + auto fwdCb = + sim.RegisterForwardCallback(forwardCallback.GetCallback(), false); + auto revCb = + sim.RegisterReverseCallback(reverseCallback.GetCallback(), false); + + // Bootstrap into a non-off state to verify the callbacks + relay.Set(Relay::kOn); + forwardCallback.Reset(); + reverseCallback.Reset(); + + relay.Set(Relay::kOff); + EXPECT_EQ(Relay::kOff, relay.Get()); + EXPECT_FALSE(sim.GetForward()); + EXPECT_FALSE(sim.GetReverse()); + + EXPECT_TRUE(forwardCallback.WasTriggered()); + EXPECT_FALSE(forwardCallback.GetLastValue()); + EXPECT_TRUE(reverseCallback.WasTriggered()); + EXPECT_FALSE(reverseCallback.GetLastValue()); +} + +TEST(RelaySimTest, StopMotor) { + Relay relay{0}; + RelaySim sim(relay); + + // Bootstrap into non-off state + relay.Set(Relay::kOn); + + relay.StopMotor(); + EXPECT_EQ(Relay::kOff, relay.Get()); +} + +} // namespace frc::sim diff --git a/wpilibc/src/test/native/cpp/simulation/RoboRioSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/RoboRioSimTest.cpp new file mode 100644 index 0000000000..cadf78b6da --- /dev/null +++ b/wpilibc/src/test/native/cpp/simulation/RoboRioSimTest.cpp @@ -0,0 +1,195 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include "frc/simulation/RoboRioSim.h" // NOLINT(build/include_order) + +#include +#include + +#include "callback_helpers/TestCallbackHelpers.h" +#include "frc/RobotController.h" +#include "gtest/gtest.h" + +namespace frc::sim { + +TEST(RoboRioSimTest, FPGAButton) { + RoboRioSim::ResetData(); + + int dummyStatus = 0; + + BooleanCallback callback; + auto cb = + RoboRioSim::RegisterFPGAButtonCallback(callback.GetCallback(), false); + RoboRioSim::SetFPGAButton(true); + EXPECT_TRUE(RoboRioSim::GetFPGAButton()); + EXPECT_TRUE(HAL_GetFPGAButton(&dummyStatus)); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_TRUE(callback.GetLastValue()); + + callback.Reset(); + RoboRioSim::SetFPGAButton(false); + EXPECT_FALSE(RoboRioSim::GetFPGAButton()); + EXPECT_FALSE(HAL_GetFPGAButton(&dummyStatus)); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_FALSE(callback.GetLastValue()); +} + +TEST(RoboRioSimTest, SetVin) { + RoboRioSim::ResetData(); + + DoubleCallback voltageCallback; + DoubleCallback currentCallback; + auto voltageCb = RoboRioSim::RegisterVInVoltageCallback( + voltageCallback.GetCallback(), false); + auto currentCb = RoboRioSim::RegisterVInCurrentCallback( + currentCallback.GetCallback(), false); + constexpr double kTestVoltage = 1.91; + constexpr double kTestCurrent = 35.04; + + RoboRioSim::SetVInVoltage(units::volt_t{kTestVoltage}); + EXPECT_TRUE(voltageCallback.WasTriggered()); + EXPECT_EQ(kTestVoltage, voltageCallback.GetLastValue()); + EXPECT_EQ(kTestVoltage, RoboRioSim::GetVInVoltage().to()); + EXPECT_EQ(kTestVoltage, RobotController::GetInputVoltage()); + + RoboRioSim::SetVInCurrent(units::ampere_t{kTestCurrent}); + EXPECT_TRUE(currentCallback.WasTriggered()); + EXPECT_EQ(kTestCurrent, currentCallback.GetLastValue()); + EXPECT_EQ(kTestCurrent, RoboRioSim::GetVInCurrent().to()); + EXPECT_EQ(kTestCurrent, RobotController::GetInputCurrent()); +} + +TEST(RoboRioSimTest, Set6V) { + RoboRioSim::ResetData(); + + DoubleCallback voltageCallback; + DoubleCallback currentCallback; + BooleanCallback activeCallback; + IntCallback faultCallback; + auto voltageCb = RoboRioSim::RegisterUserVoltage6VCallback( + voltageCallback.GetCallback(), false); + auto currentCb = RoboRioSim::RegisterUserCurrent6VCallback( + currentCallback.GetCallback(), false); + auto activeCb = RoboRioSim::RegisterUserActive6VCallback( + activeCallback.GetCallback(), false); + auto faultsCb = RoboRioSim::RegisterUserFaults6VCallback( + faultCallback.GetCallback(), false); + constexpr double kTestVoltage = 22.9; + constexpr double kTestCurrent = 174; + constexpr int kTestFaults = 229; + + RoboRioSim::SetUserVoltage6V(units::volt_t{kTestVoltage}); + EXPECT_TRUE(voltageCallback.WasTriggered()); + EXPECT_EQ(kTestVoltage, voltageCallback.GetLastValue()); + EXPECT_EQ(kTestVoltage, RoboRioSim::GetUserVoltage6V().to()); + EXPECT_EQ(kTestVoltage, RobotController::GetVoltage6V()); + + RoboRioSim::SetUserCurrent6V(units::ampere_t{kTestCurrent}); + EXPECT_TRUE(currentCallback.WasTriggered()); + EXPECT_EQ(kTestCurrent, currentCallback.GetLastValue()); + EXPECT_EQ(kTestCurrent, RoboRioSim::GetUserCurrent6V().to()); + EXPECT_EQ(kTestCurrent, RobotController::GetCurrent6V()); + + RoboRioSim::SetUserActive6V(false); + EXPECT_TRUE(activeCallback.WasTriggered()); + EXPECT_FALSE(activeCallback.GetLastValue()); + EXPECT_FALSE(RoboRioSim::GetUserActive6V()); + EXPECT_FALSE(RobotController::GetEnabled6V()); + + RoboRioSim::SetUserFaults6V(kTestFaults); + EXPECT_TRUE(faultCallback.WasTriggered()); + EXPECT_EQ(kTestFaults, faultCallback.GetLastValue()); + EXPECT_EQ(kTestFaults, RoboRioSim::GetUserFaults6V()); + EXPECT_EQ(kTestFaults, RobotController::GetFaultCount6V()); +} + +TEST(RoboRioSimTest, Set5V) { + RoboRioSim::ResetData(); + + DoubleCallback voltageCallback; + DoubleCallback currentCallback; + BooleanCallback activeCallback; + IntCallback faultCallback; + auto voltageCb = RoboRioSim::RegisterUserVoltage5VCallback( + voltageCallback.GetCallback(), false); + auto currentCb = RoboRioSim::RegisterUserCurrent5VCallback( + currentCallback.GetCallback(), false); + auto activeCb = RoboRioSim::RegisterUserActive5VCallback( + activeCallback.GetCallback(), false); + auto faultsCb = RoboRioSim::RegisterUserFaults5VCallback( + faultCallback.GetCallback(), false); + constexpr double kTestVoltage = 22.9; + constexpr double kTestCurrent = 174; + constexpr int kTestFaults = 229; + + RoboRioSim::SetUserVoltage5V(units::volt_t{kTestVoltage}); + EXPECT_TRUE(voltageCallback.WasTriggered()); + EXPECT_EQ(kTestVoltage, voltageCallback.GetLastValue()); + EXPECT_EQ(kTestVoltage, RoboRioSim::GetUserVoltage5V().to()); + EXPECT_EQ(kTestVoltage, RobotController::GetVoltage5V()); + + RoboRioSim::SetUserCurrent5V(units::ampere_t{kTestCurrent}); + EXPECT_TRUE(currentCallback.WasTriggered()); + EXPECT_EQ(kTestCurrent, currentCallback.GetLastValue()); + EXPECT_EQ(kTestCurrent, RoboRioSim::GetUserCurrent5V().to()); + EXPECT_EQ(kTestCurrent, RobotController::GetCurrent5V()); + + RoboRioSim::SetUserActive5V(false); + EXPECT_TRUE(activeCallback.WasTriggered()); + EXPECT_FALSE(activeCallback.GetLastValue()); + EXPECT_FALSE(RoboRioSim::GetUserActive5V()); + EXPECT_FALSE(RobotController::GetEnabled5V()); + + RoboRioSim::SetUserFaults5V(kTestFaults); + EXPECT_TRUE(faultCallback.WasTriggered()); + EXPECT_EQ(kTestFaults, faultCallback.GetLastValue()); + EXPECT_EQ(kTestFaults, RoboRioSim::GetUserFaults5V()); + EXPECT_EQ(kTestFaults, RobotController::GetFaultCount5V()); +} + +TEST(RoboRioSimTest, Set3V3) { + RoboRioSim::ResetData(); + + DoubleCallback voltageCallback; + DoubleCallback currentCallback; + BooleanCallback activeCallback; + IntCallback faultCallback; + auto voltageCb = RoboRioSim::RegisterUserVoltage3V3Callback( + voltageCallback.GetCallback(), false); + auto currentCb = RoboRioSim::RegisterUserCurrent3V3Callback( + currentCallback.GetCallback(), false); + auto activeCb = RoboRioSim::RegisterUserActive3V3Callback( + activeCallback.GetCallback(), false); + auto faultsCb = RoboRioSim::RegisterUserFaults3V3Callback( + faultCallback.GetCallback(), false); + constexpr double kTestVoltage = 22.9; + constexpr double kTestCurrent = 174; + constexpr int kTestFaults = 229; + + RoboRioSim::SetUserVoltage3V3(units::volt_t{kTestVoltage}); + EXPECT_TRUE(voltageCallback.WasTriggered()); + EXPECT_EQ(kTestVoltage, voltageCallback.GetLastValue()); + EXPECT_EQ(kTestVoltage, RoboRioSim::GetUserVoltage3V3().to()); + EXPECT_EQ(kTestVoltage, RobotController::GetVoltage3V3()); + + RoboRioSim::SetUserCurrent3V3(units::ampere_t{kTestCurrent}); + EXPECT_TRUE(currentCallback.WasTriggered()); + EXPECT_EQ(kTestCurrent, currentCallback.GetLastValue()); + EXPECT_EQ(kTestCurrent, RoboRioSim::GetUserCurrent3V3().to()); + EXPECT_EQ(kTestCurrent, RobotController::GetCurrent3V3()); + + RoboRioSim::SetUserActive3V3(false); + EXPECT_TRUE(activeCallback.WasTriggered()); + EXPECT_FALSE(activeCallback.GetLastValue()); + EXPECT_FALSE(RoboRioSim::GetUserActive3V3()); + EXPECT_FALSE(RobotController::GetEnabled3V3()); + + RoboRioSim::SetUserFaults3V3(kTestFaults); + EXPECT_TRUE(faultCallback.WasTriggered()); + EXPECT_EQ(kTestFaults, faultCallback.GetLastValue()); + EXPECT_EQ(kTestFaults, RoboRioSim::GetUserFaults3V3()); + EXPECT_EQ(kTestFaults, RobotController::GetFaultCount3V3()); +} + +} // namespace frc::sim diff --git a/wpilibc/src/test/native/cpp/simulation/StateSpaceSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/StateSpaceSimTest.cpp index ba089d54c1..9fafe7c9ef 100644 --- a/wpilibc/src/test/native/cpp/simulation/StateSpaceSimTest.cpp +++ b/wpilibc/src/test/native/cpp/simulation/StateSpaceSimTest.cpp @@ -36,6 +36,9 @@ TEST(StateSpaceSimTest, TestFlywheelSim) { frc::sim::EncoderSim encoderSim{encoder}; frc::PWMVictorSPX motor{0}; + frc::sim::RoboRioSim::ResetData(); + encoderSim.ResetData(); + for (int i = 0; i < 100; i++) { // RobotPeriodic runs first auto voltageOut = controller.Calculate(encoder.GetRate(), 200.0); diff --git a/wpilibc/src/test/native/include/callback_helpers/TestCallbackHelpers.h b/wpilibc/src/test/native/include/callback_helpers/TestCallbackHelpers.h new file mode 100644 index 0000000000..646bcdd406 --- /dev/null +++ b/wpilibc/src/test/native/include/callback_helpers/TestCallbackHelpers.h @@ -0,0 +1,64 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#pragma once + +#include +#include + +#include + +namespace frc::sim { + +template +class BaseCallbackHelper { + public: + bool WasTriggered() const { return m_wasTriggered; } + ValueType GetLastValue() const { return m_lastValue; } + + void Reset() { + m_wasTriggered = false; + m_lastValue = 0; + } + + virtual void HandleCallback(std::string_view name, + const HAL_Value* value) = 0; + + std::function GetCallback() { + return [&](std::string_view name, const HAL_Value* value) { + HandleCallback(name, value); + }; + } + + protected: + bool m_wasTriggered{false}; + ValueType m_lastValue{0}; +}; + +class BooleanCallback : public BaseCallbackHelper { + public: + void HandleCallback(std::string_view name, const HAL_Value* value) override; +}; + +class EnumCallback : public BaseCallbackHelper { + public: + void HandleCallback(std::string_view name, const HAL_Value* value) override; +}; + +class IntCallback : public BaseCallbackHelper { + public: + void HandleCallback(std::string_view name, const HAL_Value* value) override; +}; + +class LongCallback : public BaseCallbackHelper { + public: + void HandleCallback(std::string_view name, const HAL_Value* value) override; +}; + +class DoubleCallback : public BaseCallbackHelper { + public: + void HandleCallback(std::string_view name, const HAL_Value* value) override; +}; + +} // namespace frc::sim