Fix shuffleboard C++ tests, and run them on desktop (#1351)

This commit is contained in:
Thad House
2018-10-02 20:55:03 -07:00
committed by Peter Johnson
parent 7b471d8c62
commit fd82153456
12 changed files with 318 additions and 18 deletions

View File

@@ -0,0 +1,19 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "shuffleboard/MockActuatorSendable.h"
using namespace frc;
MockActuatorSendable::MockActuatorSendable(wpi::StringRef name)
: SendableBase(false) {
SetName(name);
}
void MockActuatorSendable::InitSendable(SendableBuilder& builder) {
builder.SetActuator(true);
}

View File

@@ -0,0 +1,105 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "frc/shuffleboard/ShuffleboardInstance.h" // NOLINT(build/include_order)
#include <memory>
#include <string>
#include <networktables/NetworkTableEntry.h>
#include <networktables/NetworkTableInstance.h>
#include "frc/shuffleboard/ShuffleboardInstance.h"
#include "gtest/gtest.h"
#include "shuffleboard/MockActuatorSendable.h"
using namespace frc;
class ShuffleboardInstanceTest : public testing::Test {
void SetUp() override {
m_ntInstance = nt::NetworkTableInstance::Create();
m_shuffleboardInstance =
std::make_unique<detail::ShuffleboardInstance>(m_ntInstance);
}
protected:
nt::NetworkTableInstance m_ntInstance;
std::unique_ptr<detail::ShuffleboardInstance> m_shuffleboardInstance;
};
TEST_F(ShuffleboardInstanceTest, PathFluent) {
auto entry = m_shuffleboardInstance->GetTab("Tab Title")
.GetLayout("List", "List Layout")
.Add("Data", "string")
.WithWidget("Text View")
.GetEntry();
EXPECT_EQ("string", entry.GetString("")) << "Wrong entry value";
EXPECT_EQ("/Shuffleboard/Tab Title/List Layout/Data", entry.GetName())
<< "Entry path generated incorrectly";
}
TEST_F(ShuffleboardInstanceTest, NestedLayoutsFluent) {
auto entry = m_shuffleboardInstance->GetTab("Tab")
.GetLayout("List", "First")
.GetLayout("List", "Second")
.GetLayout("List", "Third")
.GetLayout("List", "Fourth")
.Add("Value", "string")
.GetEntry();
EXPECT_EQ("string", entry.GetString("")) << "Wrong entry value";
EXPECT_EQ("/Shuffleboard/Tab/First/Second/Third/Fourth/Value",
entry.GetName())
<< "Entry path generated incorrectly";
}
TEST_F(ShuffleboardInstanceTest, NestedLayoutsOop) {
ShuffleboardTab& tab = m_shuffleboardInstance->GetTab("Tab");
ShuffleboardLayout& first = tab.GetLayout("List", "First");
ShuffleboardLayout& second = first.GetLayout("List", "Second");
ShuffleboardLayout& third = second.GetLayout("List", "Third");
ShuffleboardLayout& fourth = third.GetLayout("List", "Fourth");
SimpleWidget& widget = fourth.Add("Value", "string");
auto entry = widget.GetEntry();
EXPECT_EQ("string", entry.GetString("")) << "Wrong entry value";
EXPECT_EQ("/Shuffleboard/Tab/First/Second/Third/Fourth/Value",
entry.GetName())
<< "Entry path generated incorrectly";
}
TEST_F(ShuffleboardInstanceTest, LayoutTypeIsSet) {
std::string layoutType = "Type";
m_shuffleboardInstance->GetTab("Tab").GetLayout(layoutType, "Title");
m_shuffleboardInstance->Update();
nt::NetworkTableEntry entry = m_ntInstance.GetEntry(
"/Shuffleboard/.metadata/Tab/Title/PreferredComponent");
EXPECT_EQ(layoutType, entry.GetString("Not Set")) << "Layout type not set";
}
TEST_F(ShuffleboardInstanceTest, NestedActuatoWidgetsAreDisabled) {
MockActuatorSendable sendable("Actuator");
m_shuffleboardInstance->GetTab("Tab")
.GetLayout("Layout", "Title")
.Add(sendable);
auto controllableEntry =
m_ntInstance.GetEntry("/Shuffleboard/Tab/Title/Actuator/.controllable");
m_shuffleboardInstance->Update();
// Note: we use the unsafe `GetBoolean()` method because if the value is NOT
// a boolean, or if it is not present, then something has clearly gone very,
// very wrong
bool controllable = controllableEntry.GetValue()->GetBoolean();
// Sanity check
EXPECT_TRUE(controllable)
<< "The nested actuator widget should be enabled by default";
m_shuffleboardInstance->DisableActuatorWidgets();
controllable = controllableEntry.GetValue()->GetBoolean();
EXPECT_FALSE(controllable)
<< "The nested actuator widget should have been disabled";
}

View File

@@ -0,0 +1,115 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include <array>
#include <memory>
#include <string>
#include <networktables/NetworkTableEntry.h>
#include <networktables/NetworkTableInstance.h>
#include "frc/commands/InstantCommand.h"
#include "frc/shuffleboard/ShuffleboardInstance.h"
#include "frc/shuffleboard/ShuffleboardTab.h"
#include "frc/smartdashboard/Sendable.h"
#include "gtest/gtest.h"
using namespace frc;
class ShuffleboardTabTest : public testing::Test {
void SetUp() override {
m_ntInstance = nt::NetworkTableInstance::Create();
m_instance = std::make_unique<detail::ShuffleboardInstance>(m_ntInstance);
m_tab = &(m_instance->GetTab("Tab"));
}
protected:
nt::NetworkTableInstance m_ntInstance;
ShuffleboardTab* m_tab;
std::unique_ptr<detail::ShuffleboardInstance> m_instance;
};
TEST_F(ShuffleboardTabTest, AddDouble) {
auto entry = m_tab->Add("Double", 1.0).GetEntry();
EXPECT_EQ("/Shuffleboard/Tab/Double", entry.GetName());
EXPECT_FLOAT_EQ(1.0, entry.GetValue()->GetDouble());
}
TEST_F(ShuffleboardTabTest, AddInteger) {
auto entry = m_tab->Add("Int", 1).GetEntry();
EXPECT_EQ("/Shuffleboard/Tab/Int", entry.GetName());
EXPECT_FLOAT_EQ(1.0, entry.GetValue()->GetDouble());
}
TEST_F(ShuffleboardTabTest, AddBoolean) {
auto entry = m_tab->Add("Bool", false).GetEntry();
EXPECT_EQ("/Shuffleboard/Tab/Bool", entry.GetName());
EXPECT_FALSE(entry.GetValue()->GetBoolean());
}
TEST_F(ShuffleboardTabTest, AddString) {
auto entry = m_tab->Add("String", "foobar").GetEntry();
EXPECT_EQ("/Shuffleboard/Tab/String", entry.GetName());
EXPECT_EQ("foobar", entry.GetValue()->GetString());
}
TEST_F(ShuffleboardTabTest, AddNamedSendableWithProperties) {
InstantCommand sendable("Command");
std::string widgetType = "Command Widget";
wpi::StringMap<std::shared_ptr<nt::Value>> map;
map.try_emplace("foo", nt::Value::MakeDouble(1234));
map.try_emplace("bar", nt::Value::MakeString("baz"));
m_tab->Add(sendable).WithWidget(widgetType).WithProperties(map);
m_instance->Update();
std::string meta = "/Shuffleboard/.metadata/Tab/Command";
EXPECT_EQ(1234, m_ntInstance.GetEntry(meta + "/Properties/foo").GetDouble(-1))
<< "Property 'foo' not set correctly";
EXPECT_EQ("baz",
m_ntInstance.GetEntry(meta + "/Properties/bar").GetString(""))
<< "Property 'bar' not set correctly";
EXPECT_EQ(widgetType,
m_ntInstance.GetEntry(meta + "/PreferredComponent").GetString(""))
<< "Preferred component not set correctly";
}
TEST_F(ShuffleboardTabTest, AddNumberArray) {
std::array<double, 3> expect = {{1.0, 2.0, 3.0}};
auto entry = m_tab->Add("DoubleArray", expect).GetEntry();
EXPECT_EQ("/Shuffleboard/Tab/DoubleArray", entry.GetName());
auto actual = entry.GetValue()->GetDoubleArray();
EXPECT_EQ(expect.size(), actual.size());
for (size_t i = 0; i < expect.size(); i++) {
EXPECT_FLOAT_EQ(expect[i], actual[i]);
}
}
TEST_F(ShuffleboardTabTest, AddBooleanArray) {
std::array<bool, 2> expect = {{true, false}};
auto entry = m_tab->Add("BoolArray", expect).GetEntry();
EXPECT_EQ("/Shuffleboard/Tab/BoolArray", entry.GetName());
auto actual = entry.GetValue()->GetBooleanArray();
EXPECT_EQ(expect.size(), actual.size());
for (size_t i = 0; i < expect.size(); i++) {
EXPECT_EQ(expect[i], actual[i]);
}
}
TEST_F(ShuffleboardTabTest, AddStringArray) {
std::array<std::string, 2> expect = {{"foo", "bar"}};
auto entry = m_tab->Add("StringArray", expect).GetEntry();
EXPECT_EQ("/Shuffleboard/Tab/StringArray", entry.GetName());
auto actual = entry.GetValue()->GetStringArray();
EXPECT_EQ(expect.size(), actual.size());
for (size_t i = 0; i < expect.size(); i++) {
EXPECT_EQ(expect[i], actual[i]);
}
}

View File

@@ -0,0 +1,20 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "frc/shuffleboard/Shuffleboard.h"
#include "frc/shuffleboard/ShuffleboardTab.h"
#include "gtest/gtest.h"
using namespace frc;
class ShuffleboardTest : public testing::Test {};
TEST_F(ShuffleboardTest, TabObjectsCached) {
ShuffleboardTab& tab1 = Shuffleboard::GetTab("testTabObjectsCached");
ShuffleboardTab& tab2 = Shuffleboard::GetTab("testTabObjectsCached");
EXPECT_EQ(&tab1, &tab2) << "Tab objects were not cached";
}