Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infra - Testing #114

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
20 changes: 16 additions & 4 deletions lib/core/mqtt_logger.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#include "mqtt.hpp"
#include "mqtt_logger.hpp"

#include <cstdarg>
#include <cstdio>
#include <utility>

namespace hyped::core {

MqttLogger::MqttLogger(const char *const label,
const LogLevel level,
const core::ITimeSource &timer,
Expand All @@ -19,13 +22,22 @@ MqttLogger::MqttLogger(const char *const label,

void MqttLogger::log(const LogLevel level, const char *format, ...)
{
logger_.log(level, format);
const auto topic = MqttTopic::kTest;
char buffer[256]; // NOLINT
va_list args;
va_start(args, format);
vsprintf(buffer, format, args);
va_end(args);
logger_.log(level, "%s", buffer);
const auto topic = MqttTopic::kLog;
std::shared_ptr<rapidjson::Document> message_payload = std::make_shared<rapidjson::Document>();
message_payload->SetObject();
message_payload->AddMember("log", *format, message_payload->GetAllocator());
const MqttMessage::Header header{.timestamp = 0, .priority = MqttMessagePriority::kCritical};
rapidjson::Value log_string_value;
log_string_value.SetString(buffer, message_payload->GetAllocator());
message_payload->AddMember("log", log_string_value, message_payload->GetAllocator());
const auto now = static_cast<std::uint64_t>(time_source_.now().time_since_epoch().count());
const MqttMessage::Header header{.timestamp = now, .priority = MqttMessagePriority::kCritical};
const MqttMessage message{topic, header, message_payload};
mqtt_->publish(message, MqttMessageQos::kAtLeastOnce);
}

} // namespace hyped::core
8 changes: 4 additions & 4 deletions lib/core/mqtt_topics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

namespace hyped::core {

enum class MqttTopic { kTest, kState };
enum class MqttTopic { kTest, kState, kLog };

const std::unordered_map<MqttTopic, std::string> mqtt_topic_to_string
= {{MqttTopic::kTest, "test"}, {MqttTopic::kState, "state"}};
= {{MqttTopic::kTest, "test"}, {MqttTopic::kState, "state"}, {MqttTopic::kLog, "log"}};
const std::unordered_map<std::string, MqttTopic> mqtt_string_to_topic
= {{"test", MqttTopic::kTest}, {"state", MqttTopic::kState}};
= {{"test", MqttTopic::kTest}, {"state", MqttTopic::kState}, {"log", MqttTopic::kLog}};

} // namespace hyped::core
} // namespace hyped::core
19 changes: 17 additions & 2 deletions lib/utils/dummy_adc.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
#include "dummy_adc.hpp"

#include <optional>
#include <utility>

namespace hyped::utils {

DummyAdc::DummyAdc() : values_(0.0)
{
}

std::optional<core::Float> DummyAdc::readValue()
{
return std::nullopt;
if (values_.empty()) { return std::nullopt; }
const auto val = values_.front();
values_.erase(values_.begin());
return val;
}

void DummyAdc::setValue(std::vector<std::optional<core::Float>> values)
{
values_ = std::move(values);
}

} // namespace hyped::utils
} // namespace hyped::utils
7 changes: 7 additions & 0 deletions lib/utils/dummy_adc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@ namespace hyped::utils {

class DummyAdc : public io::IAdc {
public:
DummyAdc();
~DummyAdc() = default;

std::optional<core::Float> readValue() override;
void setValue(std::vector<std::optional<core::Float>> values);

private:
std::vector<std::optional<core::Float>> values_;
};

} // namespace hyped::utils
26 changes: 22 additions & 4 deletions lib/utils/dummy_i2c.cpp
Original file line number Diff line number Diff line change
@@ -1,30 +1,48 @@
#include "dummy_i2c.hpp"

#include <utility>

namespace hyped::utils {

std::optional<std::uint8_t> DummyI2c::readByte(const std::uint8_t device_address,
const std::uint8_t register_address)
{
return std::nullopt;
if (read_byte_results_.empty()) { return std::nullopt; }
const auto next_byte = read_byte_results_.at(0);
read_byte_results_.erase(read_byte_results_.begin());
return next_byte;
}

core::Result DummyI2c::writeByteToRegister(const std::uint8_t device_address,
const std::uint8_t register_address,
const std::uint8_t data)
{
return core::Result::kFailure;
return writeByte(0, 0);
}

core::Result DummyI2c::writeByteToRegister(const std::uint8_t device_address,
const std::uint16_t register_address,
const std::uint8_t data)
{
return core::Result::kFailure;
return writeByte(0, 0);
}

core::Result DummyI2c::writeByte(const std::uint8_t device_address, const std::uint8_t data)
{
return core::Result::kFailure;
if (write_byte_results_.empty()) { return core::Result::kFailure; }
const auto next_result = write_byte_results_.at(0);
write_byte_results_.erase(write_byte_results_.begin());
return next_result;
}

void DummyI2c::setWriteByteResults(std::vector<core::Result> results)
{
write_byte_results_ = std::move(results);
}

void DummyI2c::setReadByteResults(std::vector<std::optional<std::uint8_t>> results)
{
read_byte_results_ = std::move(results);
}

} // namespace hyped::utils
27 changes: 18 additions & 9 deletions lib/utils/dummy_i2c.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include "dummy_adc.hpp"

#include <io/i2c.hpp>

namespace hyped::utils {
Expand All @@ -13,15 +15,22 @@ namespace hyped::utils {
*/
class DummyI2c : public io::II2c {
public:
std::optional<std::uint8_t> readByte(const std::uint8_t device_address,
const std::uint8_t register_address) override;
core::Result writeByteToRegister(const std::uint8_t device_address,
const std::uint8_t register_address,
const std::uint8_t data) override;
core::Result writeByteToRegister(const std::uint8_t device_address,
const std::uint16_t register_address,
const std::uint8_t data) override;
core::Result writeByte(const std::uint8_t device_address, const std::uint8_t data) override;
virtual std::optional<std::uint8_t> readByte(const std::uint8_t device_address,
const std::uint8_t register_address);
virtual core::Result writeByteToRegister(const std::uint8_t device_address,
const std::uint8_t register_address,
const std::uint8_t data);
virtual core::Result writeByteToRegister(const std::uint8_t device_address,
const std::uint16_t register_address,
const std::uint8_t data);
virtual core::Result writeByte(const std::uint8_t device_address, const std::uint8_t data);

void setWriteByteResults(std::vector<core::Result> results);
void setReadByteResults(std::vector<std::optional<std::uint8_t>> results);

private:
std::vector<core::Result> write_byte_results_;
std::vector<std::optional<std::uint8_t>> read_byte_results_;
};

} // namespace hyped::utils
24 changes: 19 additions & 5 deletions lib/utils/dummy_mqtt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,37 @@

namespace hyped::utils {

void MockMqtt::publish(const core::MqttMessage &message, const core::MqttMessageQos qos)
void DummyMqtt::publish(const core::MqttMessage &message, const core::MqttMessageQos qos)
{
messages_sent_.push_back(message);
}

core::Result MockMqtt::subscribe(const core::MqttTopic topic)
core::Result DummyMqtt::subscribe(const core::MqttTopic topic)
{
return core::Result::kSuccess;
}

core::Result MockMqtt::consume()
core::Result DummyMqtt::consume()
{
return core::Result::kSuccess;
}

std::optional<core::MqttMessage> MockMqtt::getMessage()
std::optional<core::MqttMessage> DummyMqtt::getMessage()
{
return std::nullopt;
if (messages_to_receive_.empty()) { return std::nullopt; }
const auto next_message = messages_to_receive_.at(0);
messages_to_receive_.erase(messages_to_receive_.begin());
return next_message;
}

std::vector<core::MqttMessage> DummyMqtt::getSentMessages()
{
return messages_sent_;
}

void DummyMqtt::addMessageToReceive(const core::MqttMessage &message)
{
messages_to_receive_.emplace_back(message);
}

} // namespace hyped::utils
9 changes: 8 additions & 1 deletion lib/utils/dummy_mqtt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,19 @@

namespace hyped::utils {

class MockMqtt : public core::IMqtt {
class DummyMqtt : public core::IMqtt {
public:
void publish(const core::MqttMessage &message, const core::MqttMessageQos qos) override;
core::Result subscribe(const core::MqttTopic topic) override;
core::Result consume() override;
std::optional<core::MqttMessage> getMessage() override;

std::vector<core::MqttMessage> getSentMessages();
void addMessageToReceive(const core::MqttMessage &message);

private:
std::vector<std::optional<core::MqttMessage>> messages_to_receive_;
std::vector<core::MqttMessage> messages_sent_;
};

} // namespace hyped::utils
76 changes: 76 additions & 0 deletions test/core/mqtt_logger.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include <gtest/gtest.h>

#include "core/mqtt.hpp"
#include "utils/dummy_logger.hpp"
#include <core/mqtt_logger.hpp>
#include <utils/dummy_mqtt.hpp>
#include <utils/manual_time.hpp>

namespace hyped::test {

TEST(MqttLogger, sendMqttMessage)
{
utils::ManualTime manual_time;
auto mqtt = std::make_shared<utils::DummyMqtt>();
utils::DummyLogger logger;
core::MqttLogger mqtt_logger("test", core::LogLevel::kDebug, manual_time, logger, mqtt);
mqtt_logger.log(core::LogLevel::kDebug, "test");
const auto sent_messages = mqtt->getSentMessages();
ASSERT_EQ(sent_messages.size(), 1);
const auto &message = sent_messages.at(0);
ASSERT_EQ(message.topic, core::MqttTopic::kLog);
ASSERT_EQ(message.header.priority, core::MqttMessagePriority::kCritical);
ASSERT_EQ(message.header.timestamp, 0);
const auto &payload = message.payload->GetObject();
ASSERT_EQ(payload.MemberCount(), 1);
ASSERT_TRUE(payload.HasMember("log"));
const auto &log = payload.FindMember("log")->value;
ASSERT_TRUE(log.IsString());
ASSERT_STREQ(log.GetString(), "test");
}

TEST(MqttLogger, correctTime)
{
utils::ManualTime manual_time;
manual_time.set_time(std::chrono::system_clock::from_time_t(3600));
auto mqtt = std::make_shared<utils::DummyMqtt>();
utils::DummyLogger logger;
core::MqttLogger mqtt_logger("test", core::LogLevel::kDebug, manual_time, logger, mqtt);
mqtt_logger.log(core::LogLevel::kDebug, "test");
const auto sent_messages = mqtt->getSentMessages();
ASSERT_EQ(sent_messages.size(), 1);
const auto &message = sent_messages.at(0);
ASSERT_EQ(message.topic, core::MqttTopic::kLog);
ASSERT_EQ(message.header.priority, core::MqttMessagePriority::kCritical);
ASSERT_EQ(message.header.timestamp,
std::chrono::system_clock::from_time_t(3600).time_since_epoch().count());
const auto &payload = message.payload->GetObject();
ASSERT_EQ(payload.MemberCount(), 1);
ASSERT_TRUE(payload.HasMember("log"));
const auto &log = payload.FindMember("log")->value;
ASSERT_TRUE(log.IsString());
ASSERT_STREQ(log.GetString(), "test");
}

TEST(MqttLogger, sendFormattedMessage)
{
utils::ManualTime manual_time;
auto mqtt = std::make_shared<utils::DummyMqtt>();
utils::DummyLogger logger;
core::MqttLogger mqtt_logger("test", core::LogLevel::kDebug, manual_time, logger, mqtt);
mqtt_logger.log(core::LogLevel::kDebug, "test %d", 42);
const auto sent_messages = mqtt->getSentMessages();
ASSERT_EQ(sent_messages.size(), 1);
const auto &message = sent_messages.at(0);
ASSERT_EQ(message.topic, core::MqttTopic::kLog);
ASSERT_EQ(message.header.priority, core::MqttMessagePriority::kCritical);
ASSERT_EQ(message.header.timestamp, 0);
const auto &payload = message.payload->GetObject();
ASSERT_EQ(payload.MemberCount(), 1);
ASSERT_TRUE(payload.HasMember("log"));
const auto &log = payload.FindMember("log")->value;
ASSERT_TRUE(log.IsString());
ASSERT_STREQ(log.GetString(), "test 42");
}

} // namespace hyped::test
26 changes: 26 additions & 0 deletions test/sensors/keyence.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include <gtest/gtest.h>

#include <core/logger.hpp>
#include <sensors/i2c_mux.hpp>
#include <sensors/keyence.hpp>
#include <utils/dummy_gpio.hpp>
#include <utils/dummy_logger.hpp>

namespace hyped::test {

TEST(Keyence, count)
{
std::shared_ptr<utils::DummyGpio> gpio = std::make_shared<utils::DummyGpio>(
[](const std::uint8_t) {
return std::optional<core::DigitalSignal>(core::DigitalSignal::kHigh);
},
[](const std::uint8_t, core::DigitalSignal) { return core::Result::kSuccess; });
utils::DummyLogger logger;
auto keyence = sensors::Keyence::create(logger, gpio, 0);
for (int i = 1; i < 10; i++) {
keyence->updateStripeCount();
ASSERT_EQ(keyence->getStripeCount(), i);
}
}

} // namespace hyped::test
4 changes: 2 additions & 2 deletions test/state_machine/stm_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ void testTransition(const std::shared_ptr<state_machine::StateMachine> &stm,
ASSERT_TRUE(stm->getCurrentState() == expected_state);
}

std::shared_ptr<utils::MockMqtt> getMockMqtt()
std::shared_ptr<utils::DummyMqtt> getMockMqtt()
{
return std::make_shared<utils::MockMqtt>();
return std::make_shared<utils::DummyMqtt>();
}

TEST(StateMachine, cleanRunDynamic)
Expand Down
Loading