diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandSendableButtonTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandSendableButtonTest.java new file mode 100644 index 0000000000..6d2a788de6 --- /dev/null +++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandSendableButtonTest.java @@ -0,0 +1,114 @@ +// 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. + +package edu.wpi.first.wpilibj2.command; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import edu.wpi.first.networktables.BooleanPublisher; +import edu.wpi.first.networktables.NetworkTableInstance; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; +import java.util.concurrent.atomic.AtomicInteger; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class CommandSendableButtonTest extends CommandTestBase { + private NetworkTableInstance m_inst; + private AtomicInteger m_schedule; + private AtomicInteger m_cancel; + private BooleanPublisher m_publish; + private CommandBase m_command; + + @BeforeEach + void setUp() { + m_inst = NetworkTableInstance.create(); + SmartDashboard.setNetworkTableInstance(m_inst); + m_schedule = new AtomicInteger(); + m_cancel = new AtomicInteger(); + m_command = Commands.startEnd(m_schedule::incrementAndGet, m_cancel::incrementAndGet); + m_publish = m_inst.getBooleanTopic("/SmartDashboard/command/running").publish(); + SmartDashboard.putData("command", m_command); + SmartDashboard.updateValues(); + } + + @Test + void trueAndNotScheduledSchedules() { + // Not scheduled and true -> scheduled + CommandScheduler.getInstance().run(); + SmartDashboard.updateValues(); + assertFalse(m_command.isScheduled()); + assertEquals(0, m_schedule.get()); + assertEquals(0, m_cancel.get()); + + m_publish.set(true); + SmartDashboard.updateValues(); + CommandScheduler.getInstance().run(); + assertTrue(m_command.isScheduled()); + assertEquals(1, m_schedule.get()); + assertEquals(0, m_cancel.get()); + } + + @Test + void trueAndScheduledNoOp() { + // Scheduled and true -> no-op + m_command.schedule(); + CommandScheduler.getInstance().run(); + SmartDashboard.updateValues(); + assertTrue(m_command.isScheduled()); + assertEquals(1, m_schedule.get()); + assertEquals(0, m_cancel.get()); + + m_publish.set(true); + SmartDashboard.updateValues(); + CommandScheduler.getInstance().run(); + assertTrue(m_command.isScheduled()); + assertEquals(1, m_schedule.get()); + assertEquals(0, m_cancel.get()); + } + + @Test + void falseAndNotScheduledNoOp() { + // Not scheduled and false -> no-op + CommandScheduler.getInstance().run(); + SmartDashboard.updateValues(); + assertFalse(m_command.isScheduled()); + assertEquals(0, m_schedule.get()); + assertEquals(0, m_cancel.get()); + + m_publish.set(false); + SmartDashboard.updateValues(); + CommandScheduler.getInstance().run(); + assertFalse(m_command.isScheduled()); + assertEquals(0, m_schedule.get()); + assertEquals(0, m_cancel.get()); + } + + @Test + void falseAndScheduledCancel() { + // Scheduled and false -> cancel + m_command.schedule(); + CommandScheduler.getInstance().run(); + SmartDashboard.updateValues(); + assertTrue(m_command.isScheduled()); + assertEquals(1, m_schedule.get()); + assertEquals(0, m_cancel.get()); + + m_publish.set(false); + SmartDashboard.updateValues(); + CommandScheduler.getInstance().run(); + assertFalse(m_command.isScheduled()); + assertEquals(1, m_schedule.get()); + assertEquals(1, m_cancel.get()); + } + + @AfterEach + void tearDown() { + m_publish.close(); + m_inst.close(); + SmartDashboard.setNetworkTableInstance(NetworkTableInstance.getDefault()); + } +} diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandSendableButtonTest.cpp b/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandSendableButtonTest.cpp new file mode 100644 index 0000000000..08caa5cdda --- /dev/null +++ b/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandSendableButtonTest.cpp @@ -0,0 +1,98 @@ +// 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 +#include + +#include "CommandTestBase.h" + +using namespace frc2; + +class CommandSendableButtonTest : public CommandTestBase { + protected: + int m_schedule; + int m_cancel; + nt::BooleanPublisher m_publish; + std::optional m_command; + + void SetUp() override { + m_schedule = 0; + m_cancel = 0; + m_command = cmd::StartEnd([this] { m_schedule++; }, [this] { m_cancel++; }); + m_publish = nt::NetworkTableInstance::GetDefault() + .GetBooleanTopic("/SmartDashboard/command/running") + .Publish(); + frc::SmartDashboard::PutData("command", m_command->get()); + frc::SmartDashboard::UpdateValues(); + } +}; + +TEST_F(CommandSendableButtonTest, trueAndNotScheduledSchedules) { + // Not scheduled and true -> scheduled + GetScheduler().Run(); + frc::SmartDashboard::UpdateValues(); + EXPECT_FALSE(m_command->IsScheduled()); + EXPECT_EQ(0, m_schedule); + EXPECT_EQ(0, m_cancel); + + m_publish.Set(true); + frc::SmartDashboard::UpdateValues(); + GetScheduler().Run(); + EXPECT_TRUE(m_command->IsScheduled()); + EXPECT_EQ(1, m_schedule); + EXPECT_EQ(0, m_cancel); +} + +TEST_F(CommandSendableButtonTest, trueAndScheduledNoOp) { + // Scheduled and true -> no-op + m_command->Schedule(); + GetScheduler().Run(); + frc::SmartDashboard::UpdateValues(); + EXPECT_TRUE(m_command->IsScheduled()); + EXPECT_EQ(1, m_schedule); + EXPECT_EQ(0, m_cancel); + + m_publish.Set(true); + frc::SmartDashboard::UpdateValues(); + GetScheduler().Run(); + EXPECT_TRUE(m_command->IsScheduled()); + EXPECT_EQ(1, m_schedule); + EXPECT_EQ(0, m_cancel); +} + +TEST_F(CommandSendableButtonTest, falseAndNotScheduledNoOp) { + // Not scheduled and false -> no-op + GetScheduler().Run(); + frc::SmartDashboard::UpdateValues(); + EXPECT_FALSE(m_command->IsScheduled()); + EXPECT_EQ(0, m_schedule); + EXPECT_EQ(0, m_cancel); + + m_publish.Set(false); + frc::SmartDashboard::UpdateValues(); + GetScheduler().Run(); + EXPECT_FALSE(m_command->IsScheduled()); + EXPECT_EQ(0, m_schedule); + EXPECT_EQ(0, m_cancel); +} + +TEST_F(CommandSendableButtonTest, falseAndScheduledCancel) { + // Scheduled and false -> cancel + m_command->Schedule(); + GetScheduler().Run(); + frc::SmartDashboard::UpdateValues(); + EXPECT_TRUE(m_command->IsScheduled()); + EXPECT_EQ(1, m_schedule); + EXPECT_EQ(0, m_cancel); + + m_publish.Set(false); + frc::SmartDashboard::UpdateValues(); + GetScheduler().Run(); + EXPECT_FALSE(m_command->IsScheduled()); + EXPECT_EQ(1, m_schedule); + EXPECT_EQ(1, m_cancel); +} diff --git a/wpilibc/src/test/native/cpp/smartdashboard/SendableChooserTest.cpp b/wpilibc/src/test/native/cpp/smartdashboard/SendableChooserTest.cpp new file mode 100644 index 0000000000..c26fad6b3f --- /dev/null +++ b/wpilibc/src/test/native/cpp/smartdashboard/SendableChooserTest.cpp @@ -0,0 +1,60 @@ +// 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 + +#include + +#include "gtest/gtest.h" + +class SendableChooserTest : public ::testing::TestWithParam {}; + +TEST_P(SendableChooserTest, ReturnsSelected) { + frc::SendableChooser chooser; + + for (int i = 1; i <= 3; i++) { + chooser.AddOption(std::to_string(i), i); + } + chooser.SetDefaultOption("0", 0); + + auto pub = nt::NetworkTableInstance::GetDefault() + .GetStringTopic("/SmartDashboard/chooser/selected") + .Publish(); + + frc::SmartDashboard::PutData("chooser", &chooser); + frc::SmartDashboard::UpdateValues(); + pub.Set(std::to_string(GetParam())); + frc::SmartDashboard::UpdateValues(); + EXPECT_EQ(GetParam(), chooser.GetSelected()); +} + +TEST(SendableChooserTest, DefaultIsReturnedOnNoSelect) { + frc::SendableChooser chooser; + + for (int i = 1; i <= 3; i++) { + chooser.AddOption(std::to_string(i), i); + } + + // Use 4 here rather than 0 to make sure it's not default-init int. + chooser.SetDefaultOption("4", 4); + + EXPECT_EQ(4, chooser.GetSelected()); +} + +TEST(SendableChooserTest, + DefaultConstructableIsReturnedOnNoSelectAndNoDefault) { + frc::SendableChooser chooser; + + for (int i = 1; i <= 3; i++) { + chooser.AddOption(std::to_string(i), i); + } + + EXPECT_EQ(0, chooser.GetSelected()); +} + +INSTANTIATE_TEST_SUITE_P(SendableChooserTests, SendableChooserTest, + ::testing::Values(0, 1, 2, 3)); diff --git a/wpilibj/src/test/java/edu/wpi/first/wpilibj/smartdashboard/SendableChooserTest.java b/wpilibj/src/test/java/edu/wpi/first/wpilibj/smartdashboard/SendableChooserTest.java new file mode 100644 index 0000000000..c6bccca1d6 --- /dev/null +++ b/wpilibj/src/test/java/edu/wpi/first/wpilibj/smartdashboard/SendableChooserTest.java @@ -0,0 +1,72 @@ +// 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. + +package edu.wpi.first.wpilibj.smartdashboard; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import edu.wpi.first.networktables.NetworkTableInstance; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +class SendableChooserTest { + private NetworkTableInstance m_inst; + + @BeforeEach + void setUp() { + m_inst = NetworkTableInstance.create(); + SmartDashboard.setNetworkTableInstance(m_inst); + } + + @ValueSource(ints = {0, 1, 2, 3}) + @ParameterizedTest + void returnsSelected(int toSelect) { + try (var chooser = new SendableChooser(); + var publisher = m_inst.getStringTopic("/SmartDashboard/chooser/selected").publish()) { + for (int i = 1; i <= 3; i++) { + chooser.addOption(String.valueOf(i), i); + } + chooser.setDefaultOption(String.valueOf(0), 0); + + SmartDashboard.putData("chooser", chooser); + SmartDashboard.updateValues(); + publisher.set(String.valueOf(toSelect)); + SmartDashboard.updateValues(); + assertEquals(toSelect, chooser.getSelected()); + } + } + + @Test + void defaultIsReturnedOnNoSelect() { + try (var chooser = new SendableChooser()) { + for (int i = 1; i <= 3; i++) { + chooser.addOption(String.valueOf(i), i); + } + chooser.setDefaultOption(String.valueOf(0), 0); + + assertEquals(0, chooser.getSelected()); + } + } + + @Test + void nullIsReturnedOnNoSelectAndNoDefault() { + try (var chooser = new SendableChooser()) { + for (int i = 1; i <= 3; i++) { + chooser.addOption(String.valueOf(i), i); + } + + assertNull(chooser.getSelected()); + } + } + + @AfterEach + void tearDown() { + m_inst.close(); + SmartDashboard.setNetworkTableInstance(NetworkTableInstance.getDefault()); + } +}