mirror of
https://github.com/alexhopeoconnor/firmware.git
synced 2026-10-14 15:31:31 +10:00
bring back tests
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
#include "../test_helpers.h"
|
||||
|
||||
static void assert_encrypted_packet(const std::string &json, const meshtastic_MeshPacket &packet)
|
||||
{
|
||||
TEST_ASSERT_TRUE(json.length() > 0);
|
||||
|
||||
Json::Value root = parse_json(json);
|
||||
TEST_ASSERT_TRUE(root.isObject());
|
||||
|
||||
TEST_ASSERT_TRUE(root.isMember("from"));
|
||||
TEST_ASSERT_EQUAL(packet.from, root["from"].asUInt());
|
||||
|
||||
TEST_ASSERT_TRUE(root.isMember("to"));
|
||||
TEST_ASSERT_EQUAL(packet.to, root["to"].asUInt());
|
||||
|
||||
TEST_ASSERT_TRUE(root.isMember("id"));
|
||||
TEST_ASSERT_EQUAL(packet.id, root["id"].asUInt());
|
||||
|
||||
TEST_ASSERT_TRUE(root.isMember("bytes"));
|
||||
TEST_ASSERT_TRUE(root["bytes"].isString());
|
||||
|
||||
TEST_ASSERT_TRUE(root.isMember("size"));
|
||||
TEST_ASSERT_EQUAL(packet.encrypted.size, (int)root["size"].asInt());
|
||||
|
||||
std::string encrypted_hex = root["bytes"].asString();
|
||||
TEST_ASSERT_EQUAL(packet.encrypted.size * 2, encrypted_hex.length());
|
||||
}
|
||||
|
||||
void test_encrypted_packet_serialization()
|
||||
{
|
||||
const char *data = "encrypted_payload_data";
|
||||
meshtastic_MeshPacket packet =
|
||||
create_test_packet(meshtastic_PortNum_TEXT_MESSAGE_APP, reinterpret_cast<const uint8_t *>(data), strlen(data),
|
||||
meshtastic_MeshPacket_encrypted_tag);
|
||||
std::string json = MeshPacketSerializer::JsonSerializeEncrypted(&packet);
|
||||
|
||||
assert_encrypted_packet(json, packet);
|
||||
}
|
||||
|
||||
void test_empty_encrypted_packet()
|
||||
{
|
||||
meshtastic_MeshPacket packet =
|
||||
create_test_packet(meshtastic_PortNum_TEXT_MESSAGE_APP, nullptr, 0, meshtastic_MeshPacket_encrypted_tag);
|
||||
std::string json = MeshPacketSerializer::JsonSerializeEncrypted(&packet);
|
||||
|
||||
assert_encrypted_packet(json, packet);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "../test_helpers.h"
|
||||
|
||||
static size_t encode_user_info(uint8_t *buffer, size_t buffer_size)
|
||||
{
|
||||
meshtastic_User user = meshtastic_User_init_zero;
|
||||
strcpy(user.short_name, "TEST");
|
||||
strcpy(user.long_name, "Test User");
|
||||
strcpy(user.id, "!12345678");
|
||||
user.hw_model = meshtastic_HardwareModel_HELTEC_V3;
|
||||
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, buffer_size);
|
||||
pb_encode(&stream, &meshtastic_User_msg, &user);
|
||||
return stream.bytes_written;
|
||||
}
|
||||
|
||||
void test_nodeinfo_serialization()
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
size_t payload_size = encode_user_info(buffer, sizeof(buffer));
|
||||
|
||||
meshtastic_MeshPacket packet = create_test_packet(meshtastic_PortNum_NODEINFO_APP, buffer, payload_size);
|
||||
|
||||
std::string json = MeshPacketSerializer::JsonSerialize(&packet, false);
|
||||
TEST_ASSERT_TRUE(json.length() > 0);
|
||||
|
||||
Json::Value root = parse_json(json);
|
||||
TEST_ASSERT_TRUE(root.isObject());
|
||||
|
||||
TEST_ASSERT_TRUE(root.isMember("type"));
|
||||
TEST_ASSERT_EQUAL_STRING("nodeinfo", root["type"].asString().c_str());
|
||||
|
||||
TEST_ASSERT_TRUE(root.isMember("payload"));
|
||||
TEST_ASSERT_TRUE(root["payload"].isObject());
|
||||
|
||||
const Json::Value &payload = root["payload"];
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("shortname"));
|
||||
TEST_ASSERT_EQUAL_STRING("TEST", payload["shortname"].asString().c_str());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("longname"));
|
||||
TEST_ASSERT_EQUAL_STRING("Test User", payload["longname"].asString().c_str());
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#include "../test_helpers.h"
|
||||
|
||||
static size_t encode_position(uint8_t *buffer, size_t buffer_size)
|
||||
{
|
||||
meshtastic_Position position = meshtastic_Position_init_zero;
|
||||
position.latitude_i = 374208000;
|
||||
position.longitude_i = -1221981000;
|
||||
position.altitude = 123;
|
||||
position.time = 1609459200;
|
||||
position.has_altitude = true;
|
||||
position.has_latitude_i = true;
|
||||
position.has_longitude_i = true;
|
||||
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, buffer_size);
|
||||
pb_encode(&stream, &meshtastic_Position_msg, &position);
|
||||
return stream.bytes_written;
|
||||
}
|
||||
|
||||
void test_position_serialization()
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
size_t payload_size = encode_position(buffer, sizeof(buffer));
|
||||
|
||||
meshtastic_MeshPacket packet = create_test_packet(meshtastic_PortNum_POSITION_APP, buffer, payload_size);
|
||||
|
||||
std::string json = MeshPacketSerializer::JsonSerialize(&packet, false);
|
||||
TEST_ASSERT_TRUE(json.length() > 0);
|
||||
|
||||
Json::Value root = parse_json(json);
|
||||
TEST_ASSERT_TRUE(root.isObject());
|
||||
|
||||
TEST_ASSERT_TRUE(root.isMember("type"));
|
||||
TEST_ASSERT_EQUAL_STRING("position", root["type"].asString().c_str());
|
||||
|
||||
TEST_ASSERT_TRUE(root.isMember("payload"));
|
||||
TEST_ASSERT_TRUE(root["payload"].isObject());
|
||||
|
||||
const Json::Value &payload = root["payload"];
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("latitude_i"));
|
||||
TEST_ASSERT_EQUAL(374208000, payload["latitude_i"].asInt());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("longitude_i"));
|
||||
TEST_ASSERT_EQUAL(-1221981000, payload["longitude_i"].asInt());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("altitude"));
|
||||
TEST_ASSERT_EQUAL(123, payload["altitude"].asInt());
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
#include "../test_helpers.h"
|
||||
|
||||
static void fill_all_env_metrics(meshtastic_Telemetry &telemetry)
|
||||
{
|
||||
telemetry.variant.environment_metrics.temperature = 23.56f;
|
||||
telemetry.variant.environment_metrics.has_temperature = true;
|
||||
telemetry.variant.environment_metrics.relative_humidity = 65.43f;
|
||||
telemetry.variant.environment_metrics.has_relative_humidity = true;
|
||||
telemetry.variant.environment_metrics.barometric_pressure = 1013.27f;
|
||||
telemetry.variant.environment_metrics.has_barometric_pressure = true;
|
||||
|
||||
telemetry.variant.environment_metrics.gas_resistance = 50.58f;
|
||||
telemetry.variant.environment_metrics.has_gas_resistance = true;
|
||||
telemetry.variant.environment_metrics.iaq = 120;
|
||||
telemetry.variant.environment_metrics.has_iaq = true;
|
||||
|
||||
telemetry.variant.environment_metrics.voltage = 3.34f;
|
||||
telemetry.variant.environment_metrics.has_voltage = true;
|
||||
telemetry.variant.environment_metrics.current = 0.53f;
|
||||
telemetry.variant.environment_metrics.has_current = true;
|
||||
|
||||
telemetry.variant.environment_metrics.lux = 450.12f;
|
||||
telemetry.variant.environment_metrics.has_lux = true;
|
||||
telemetry.variant.environment_metrics.white_lux = 380.95f;
|
||||
telemetry.variant.environment_metrics.has_white_lux = true;
|
||||
telemetry.variant.environment_metrics.ir_lux = 25.37f;
|
||||
telemetry.variant.environment_metrics.has_ir_lux = true;
|
||||
telemetry.variant.environment_metrics.uv_lux = 15.68f;
|
||||
telemetry.variant.environment_metrics.has_uv_lux = true;
|
||||
|
||||
telemetry.variant.environment_metrics.distance = 150.29f;
|
||||
telemetry.variant.environment_metrics.has_distance = true;
|
||||
|
||||
telemetry.variant.environment_metrics.wind_direction = 180;
|
||||
telemetry.variant.environment_metrics.has_wind_direction = true;
|
||||
telemetry.variant.environment_metrics.wind_speed = 5.52f;
|
||||
telemetry.variant.environment_metrics.has_wind_speed = true;
|
||||
telemetry.variant.environment_metrics.wind_gust = 8.24f;
|
||||
telemetry.variant.environment_metrics.has_wind_gust = true;
|
||||
telemetry.variant.environment_metrics.wind_lull = 2.13f;
|
||||
telemetry.variant.environment_metrics.has_wind_lull = true;
|
||||
|
||||
telemetry.variant.environment_metrics.weight = 75.56f;
|
||||
telemetry.variant.environment_metrics.has_weight = true;
|
||||
|
||||
telemetry.variant.environment_metrics.radiation = 0.13f;
|
||||
telemetry.variant.environment_metrics.has_radiation = true;
|
||||
|
||||
telemetry.variant.environment_metrics.rainfall_1h = 2.57f;
|
||||
telemetry.variant.environment_metrics.has_rainfall_1h = true;
|
||||
telemetry.variant.environment_metrics.rainfall_24h = 15.89f;
|
||||
telemetry.variant.environment_metrics.has_rainfall_24h = true;
|
||||
|
||||
telemetry.variant.environment_metrics.soil_moisture = 85;
|
||||
telemetry.variant.environment_metrics.has_soil_moisture = true;
|
||||
telemetry.variant.environment_metrics.soil_temperature = 18.54f;
|
||||
telemetry.variant.environment_metrics.has_soil_temperature = true;
|
||||
}
|
||||
|
||||
static size_t encode_telemetry_device_metrics(uint8_t *buffer, size_t buffer_size)
|
||||
{
|
||||
meshtastic_Telemetry telemetry = meshtastic_Telemetry_init_zero;
|
||||
telemetry.time = 1609459200;
|
||||
telemetry.which_variant = meshtastic_Telemetry_device_metrics_tag;
|
||||
telemetry.variant.device_metrics.battery_level = 85;
|
||||
telemetry.variant.device_metrics.has_battery_level = true;
|
||||
telemetry.variant.device_metrics.voltage = 3.72f;
|
||||
telemetry.variant.device_metrics.has_voltage = true;
|
||||
telemetry.variant.device_metrics.channel_utilization = 15.56f;
|
||||
telemetry.variant.device_metrics.has_channel_utilization = true;
|
||||
telemetry.variant.device_metrics.air_util_tx = 8.23f;
|
||||
telemetry.variant.device_metrics.has_air_util_tx = true;
|
||||
telemetry.variant.device_metrics.uptime_seconds = 12345;
|
||||
telemetry.variant.device_metrics.has_uptime_seconds = true;
|
||||
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, buffer_size);
|
||||
pb_encode(&stream, &meshtastic_Telemetry_msg, &telemetry);
|
||||
return stream.bytes_written;
|
||||
}
|
||||
|
||||
static size_t encode_telemetry_environment_metrics_empty(uint8_t *buffer, size_t buffer_size)
|
||||
{
|
||||
meshtastic_Telemetry telemetry = meshtastic_Telemetry_init_zero;
|
||||
telemetry.time = 1609459200;
|
||||
telemetry.which_variant = meshtastic_Telemetry_environment_metrics_tag;
|
||||
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, buffer_size);
|
||||
pb_encode(&stream, &meshtastic_Telemetry_msg, &telemetry);
|
||||
return stream.bytes_written;
|
||||
}
|
||||
|
||||
static size_t encode_telemetry_environment_metrics(uint8_t *buffer, size_t buffer_size)
|
||||
{
|
||||
meshtastic_Telemetry telemetry = meshtastic_Telemetry_init_zero;
|
||||
telemetry.time = 1609459200;
|
||||
telemetry.which_variant = meshtastic_Telemetry_environment_metrics_tag;
|
||||
fill_all_env_metrics(telemetry);
|
||||
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, buffer_size);
|
||||
pb_encode(&stream, &meshtastic_Telemetry_msg, &telemetry);
|
||||
return stream.bytes_written;
|
||||
}
|
||||
|
||||
static Json::Value serialize_and_get_payload(meshtastic_PortNum port, const uint8_t *buffer, size_t payload_size)
|
||||
{
|
||||
meshtastic_MeshPacket packet = create_test_packet(port, buffer, payload_size);
|
||||
std::string json = MeshPacketSerializer::JsonSerialize(&packet, false);
|
||||
TEST_ASSERT_TRUE(json.length() > 0);
|
||||
|
||||
Json::Value root = parse_json(json);
|
||||
TEST_ASSERT_TRUE(root.isObject());
|
||||
TEST_ASSERT_TRUE(root.isMember("payload"));
|
||||
TEST_ASSERT_TRUE(root["payload"].isObject());
|
||||
return root;
|
||||
}
|
||||
|
||||
void test_telemetry_device_metrics_serialization()
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
size_t payload_size = encode_telemetry_device_metrics(buffer, sizeof(buffer));
|
||||
|
||||
Json::Value root = serialize_and_get_payload(meshtastic_PortNum_TELEMETRY_APP, buffer, payload_size);
|
||||
|
||||
TEST_ASSERT_TRUE(root.isMember("type"));
|
||||
TEST_ASSERT_EQUAL_STRING("telemetry", root["type"].asString().c_str());
|
||||
|
||||
const Json::Value &payload = root["payload"];
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("battery_level"));
|
||||
TEST_ASSERT_EQUAL(85, payload["battery_level"].asInt());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("voltage"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 3.72f, payload["voltage"].asFloat());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("channel_utilization"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 15.56f, payload["channel_utilization"].asFloat());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("uptime_seconds"));
|
||||
TEST_ASSERT_EQUAL(12345, payload["uptime_seconds"].asInt());
|
||||
}
|
||||
|
||||
void test_telemetry_environment_metrics_serialization()
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
size_t payload_size = encode_telemetry_environment_metrics(buffer, sizeof(buffer));
|
||||
|
||||
Json::Value root = serialize_and_get_payload(meshtastic_PortNum_TELEMETRY_APP, buffer, payload_size);
|
||||
const Json::Value &payload = root["payload"];
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("temperature"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 23.56f, payload["temperature"].asFloat());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("relative_humidity"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 65.43f, payload["relative_humidity"].asFloat());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("distance"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 150.29f, payload["distance"].asFloat());
|
||||
}
|
||||
|
||||
void test_telemetry_environment_metrics_comprehensive()
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
size_t payload_size = encode_telemetry_environment_metrics(buffer, sizeof(buffer));
|
||||
|
||||
Json::Value root = serialize_and_get_payload(meshtastic_PortNum_TELEMETRY_APP, buffer, payload_size);
|
||||
const Json::Value &payload = root["payload"];
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("temperature"));
|
||||
TEST_ASSERT_TRUE(payload.isMember("relative_humidity"));
|
||||
TEST_ASSERT_TRUE(payload.isMember("barometric_pressure"));
|
||||
TEST_ASSERT_TRUE(payload.isMember("gas_resistance"));
|
||||
TEST_ASSERT_TRUE(payload.isMember("voltage"));
|
||||
TEST_ASSERT_TRUE(payload.isMember("current"));
|
||||
TEST_ASSERT_TRUE(payload.isMember("iaq"));
|
||||
TEST_ASSERT_TRUE(payload.isMember("distance"));
|
||||
TEST_ASSERT_TRUE(payload.isMember("lux"));
|
||||
TEST_ASSERT_TRUE(payload.isMember("white_lux"));
|
||||
TEST_ASSERT_TRUE(payload.isMember("wind_direction"));
|
||||
TEST_ASSERT_TRUE(payload.isMember("wind_speed"));
|
||||
TEST_ASSERT_TRUE(payload.isMember("wind_gust"));
|
||||
TEST_ASSERT_TRUE(payload.isMember("wind_lull"));
|
||||
TEST_ASSERT_TRUE(payload.isMember("radiation"));
|
||||
}
|
||||
|
||||
void test_telemetry_environment_metrics_missing_fields()
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
size_t payload_size = encode_telemetry_environment_metrics(buffer, sizeof(buffer));
|
||||
|
||||
Json::Value root = serialize_and_get_payload(meshtastic_PortNum_TELEMETRY_APP, buffer, payload_size);
|
||||
const Json::Value &payload = root["payload"];
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("ir_lux"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 25.37f, payload["ir_lux"].asFloat());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("uv_lux"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 15.68f, payload["uv_lux"].asFloat());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("weight"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 75.56f, payload["weight"].asFloat());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("rainfall_1h"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 2.57f, payload["rainfall_1h"].asFloat());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("rainfall_24h"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 15.89f, payload["rainfall_24h"].asFloat());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("soil_moisture"));
|
||||
TEST_ASSERT_EQUAL(85, payload["soil_moisture"].asInt());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("soil_temperature"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 18.54f, payload["soil_temperature"].asFloat());
|
||||
}
|
||||
|
||||
// Canary test: if a new env field is added to the protobuf but not to the serializer
|
||||
// (or to fill_all_env_metrics), this test will fail.
|
||||
void test_telemetry_environment_metrics_complete_coverage()
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
size_t payload_size = encode_telemetry_environment_metrics(buffer, sizeof(buffer));
|
||||
|
||||
Json::Value root = serialize_and_get_payload(meshtastic_PortNum_TELEMETRY_APP, buffer, payload_size);
|
||||
const Json::Value &payload = root["payload"];
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("temperature"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 23.56f, payload["temperature"].asFloat());
|
||||
TEST_ASSERT_TRUE(payload.isMember("relative_humidity"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 65.43f, payload["relative_humidity"].asFloat());
|
||||
TEST_ASSERT_TRUE(payload.isMember("barometric_pressure"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 1013.27f, payload["barometric_pressure"].asFloat());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("gas_resistance"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 50.58f, payload["gas_resistance"].asFloat());
|
||||
TEST_ASSERT_TRUE(payload.isMember("iaq"));
|
||||
TEST_ASSERT_EQUAL(120, payload["iaq"].asInt());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("voltage"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 3.34f, payload["voltage"].asFloat());
|
||||
TEST_ASSERT_TRUE(payload.isMember("current"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 0.53f, payload["current"].asFloat());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("lux"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 450.12f, payload["lux"].asFloat());
|
||||
TEST_ASSERT_TRUE(payload.isMember("white_lux"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 380.95f, payload["white_lux"].asFloat());
|
||||
TEST_ASSERT_TRUE(payload.isMember("ir_lux"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 25.37f, payload["ir_lux"].asFloat());
|
||||
TEST_ASSERT_TRUE(payload.isMember("uv_lux"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 15.68f, payload["uv_lux"].asFloat());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("distance"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 150.29f, payload["distance"].asFloat());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("wind_direction"));
|
||||
TEST_ASSERT_EQUAL(180, payload["wind_direction"].asInt());
|
||||
TEST_ASSERT_TRUE(payload.isMember("wind_speed"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 5.52f, payload["wind_speed"].asFloat());
|
||||
TEST_ASSERT_TRUE(payload.isMember("wind_gust"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 8.24f, payload["wind_gust"].asFloat());
|
||||
TEST_ASSERT_TRUE(payload.isMember("wind_lull"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 2.13f, payload["wind_lull"].asFloat());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("weight"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 75.56f, payload["weight"].asFloat());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("radiation"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 0.13f, payload["radiation"].asFloat());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("rainfall_1h"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 2.57f, payload["rainfall_1h"].asFloat());
|
||||
TEST_ASSERT_TRUE(payload.isMember("rainfall_24h"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 15.89f, payload["rainfall_24h"].asFloat());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("soil_moisture"));
|
||||
TEST_ASSERT_EQUAL(85, payload["soil_moisture"].asInt());
|
||||
TEST_ASSERT_TRUE(payload.isMember("soil_temperature"));
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 18.54f, payload["soil_temperature"].asFloat());
|
||||
}
|
||||
|
||||
void test_telemetry_environment_metrics_unset_fields()
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
size_t payload_size = encode_telemetry_environment_metrics_empty(buffer, sizeof(buffer));
|
||||
|
||||
Json::Value root = serialize_and_get_payload(meshtastic_PortNum_TELEMETRY_APP, buffer, payload_size);
|
||||
const Json::Value &payload = root["payload"];
|
||||
|
||||
TEST_ASSERT_FALSE(payload.isMember("temperature"));
|
||||
TEST_ASSERT_FALSE(payload.isMember("relative_humidity"));
|
||||
TEST_ASSERT_FALSE(payload.isMember("barometric_pressure"));
|
||||
TEST_ASSERT_FALSE(payload.isMember("gas_resistance"));
|
||||
TEST_ASSERT_FALSE(payload.isMember("iaq"));
|
||||
TEST_ASSERT_FALSE(payload.isMember("voltage"));
|
||||
TEST_ASSERT_FALSE(payload.isMember("current"));
|
||||
TEST_ASSERT_FALSE(payload.isMember("lux"));
|
||||
TEST_ASSERT_FALSE(payload.isMember("white_lux"));
|
||||
TEST_ASSERT_FALSE(payload.isMember("ir_lux"));
|
||||
TEST_ASSERT_FALSE(payload.isMember("uv_lux"));
|
||||
TEST_ASSERT_FALSE(payload.isMember("distance"));
|
||||
TEST_ASSERT_FALSE(payload.isMember("wind_direction"));
|
||||
TEST_ASSERT_FALSE(payload.isMember("wind_speed"));
|
||||
TEST_ASSERT_FALSE(payload.isMember("wind_gust"));
|
||||
TEST_ASSERT_FALSE(payload.isMember("wind_lull"));
|
||||
TEST_ASSERT_FALSE(payload.isMember("weight"));
|
||||
TEST_ASSERT_FALSE(payload.isMember("radiation"));
|
||||
TEST_ASSERT_FALSE(payload.isMember("rainfall_1h"));
|
||||
TEST_ASSERT_FALSE(payload.isMember("rainfall_24h"));
|
||||
TEST_ASSERT_FALSE(payload.isMember("soil_moisture"));
|
||||
TEST_ASSERT_FALSE(payload.isMember("soil_temperature"));
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
#include "../test_helpers.h"
|
||||
|
||||
static void verify_text_message_packet_structure(const std::string &json, const char *expected_text)
|
||||
{
|
||||
TEST_ASSERT_TRUE(json.length() > 0);
|
||||
|
||||
Json::Value root = parse_json(json);
|
||||
TEST_ASSERT_TRUE(root.isObject());
|
||||
|
||||
TEST_ASSERT_TRUE(root.isMember("from"));
|
||||
TEST_ASSERT_EQUAL(0x11223344u, root["from"].asUInt());
|
||||
TEST_ASSERT_TRUE(root.isMember("to"));
|
||||
TEST_ASSERT_EQUAL(0x55667788u, root["to"].asUInt());
|
||||
TEST_ASSERT_TRUE(root.isMember("id"));
|
||||
TEST_ASSERT_EQUAL(0x9999u, root["id"].asUInt());
|
||||
|
||||
TEST_ASSERT_TRUE(root.isMember("type"));
|
||||
TEST_ASSERT_EQUAL_STRING("text", root["type"].asString().c_str());
|
||||
|
||||
TEST_ASSERT_TRUE(root.isMember("payload"));
|
||||
TEST_ASSERT_TRUE(root["payload"].isObject());
|
||||
|
||||
const Json::Value &payload = root["payload"];
|
||||
TEST_ASSERT_TRUE(payload.isMember("text"));
|
||||
TEST_ASSERT_EQUAL_STRING(expected_text, payload["text"].asString().c_str());
|
||||
}
|
||||
|
||||
void test_text_message_serialization()
|
||||
{
|
||||
const char *test_text = "Hello Meshtastic!";
|
||||
meshtastic_MeshPacket packet =
|
||||
create_test_packet(meshtastic_PortNum_TEXT_MESSAGE_APP, reinterpret_cast<const uint8_t *>(test_text), strlen(test_text));
|
||||
|
||||
std::string json = MeshPacketSerializer::JsonSerialize(&packet, false);
|
||||
verify_text_message_packet_structure(json, test_text);
|
||||
}
|
||||
|
||||
void test_text_message_serialization_null()
|
||||
{
|
||||
meshtastic_MeshPacket packet = create_test_packet(meshtastic_PortNum_TEXT_MESSAGE_APP, nullptr, 0);
|
||||
|
||||
std::string json = MeshPacketSerializer::JsonSerialize(&packet, false);
|
||||
verify_text_message_packet_structure(json, "");
|
||||
}
|
||||
|
||||
void test_text_message_serialization_long_text()
|
||||
{
|
||||
constexpr size_t MAX_MESSAGE_SIZE = 200;
|
||||
std::string long_text(MAX_MESSAGE_SIZE, 'A');
|
||||
|
||||
meshtastic_MeshPacket packet = create_test_packet(meshtastic_PortNum_TEXT_MESSAGE_APP,
|
||||
reinterpret_cast<const uint8_t *>(long_text.c_str()), long_text.length());
|
||||
|
||||
std::string json = MeshPacketSerializer::JsonSerialize(&packet, false);
|
||||
verify_text_message_packet_structure(json, long_text.c_str());
|
||||
}
|
||||
|
||||
void test_text_message_serialization_oversized()
|
||||
{
|
||||
constexpr size_t OVERSIZED_MESSAGE = 250;
|
||||
std::string oversized_text(OVERSIZED_MESSAGE, 'B');
|
||||
|
||||
meshtastic_MeshPacket packet = create_test_packet(
|
||||
meshtastic_PortNum_TEXT_MESSAGE_APP, reinterpret_cast<const uint8_t *>(oversized_text.c_str()), oversized_text.length());
|
||||
|
||||
std::string json = MeshPacketSerializer::JsonSerialize(&packet, false);
|
||||
std::string expected_text = oversized_text.substr(0, 234);
|
||||
verify_text_message_packet_structure(json, expected_text.c_str());
|
||||
}
|
||||
|
||||
void test_text_message_serialization_invalid_utf8()
|
||||
{
|
||||
const uint8_t invalid_utf8[] = {0xFF, 0xFE, 0xFD, 0x00};
|
||||
meshtastic_MeshPacket packet =
|
||||
create_test_packet(meshtastic_PortNum_TEXT_MESSAGE_APP, invalid_utf8, sizeof(invalid_utf8) - 1);
|
||||
|
||||
std::string json = MeshPacketSerializer::JsonSerialize(&packet, false);
|
||||
TEST_ASSERT_TRUE(json.length() > 0);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#include "../test_helpers.h"
|
||||
|
||||
static size_t encode_waypoint(uint8_t *buffer, size_t buffer_size)
|
||||
{
|
||||
meshtastic_Waypoint waypoint = meshtastic_Waypoint_init_zero;
|
||||
waypoint.id = 12345;
|
||||
waypoint.latitude_i = 374208000;
|
||||
waypoint.longitude_i = -1221981000;
|
||||
waypoint.expire = 1609459200 + 3600;
|
||||
strcpy(waypoint.name, "Test Point");
|
||||
strcpy(waypoint.description, "Test waypoint description");
|
||||
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, buffer_size);
|
||||
pb_encode(&stream, &meshtastic_Waypoint_msg, &waypoint);
|
||||
return stream.bytes_written;
|
||||
}
|
||||
|
||||
void test_waypoint_serialization()
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
size_t payload_size = encode_waypoint(buffer, sizeof(buffer));
|
||||
|
||||
meshtastic_MeshPacket packet = create_test_packet(meshtastic_PortNum_WAYPOINT_APP, buffer, payload_size);
|
||||
|
||||
std::string json = MeshPacketSerializer::JsonSerialize(&packet, false);
|
||||
TEST_ASSERT_TRUE(json.length() > 0);
|
||||
|
||||
Json::Value root = parse_json(json);
|
||||
TEST_ASSERT_TRUE(root.isObject());
|
||||
|
||||
TEST_ASSERT_TRUE(root.isMember("type"));
|
||||
TEST_ASSERT_EQUAL_STRING("waypoint", root["type"].asString().c_str());
|
||||
|
||||
TEST_ASSERT_TRUE(root.isMember("payload"));
|
||||
TEST_ASSERT_TRUE(root["payload"].isObject());
|
||||
|
||||
const Json::Value &payload = root["payload"];
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("id"));
|
||||
TEST_ASSERT_EQUAL(12345, payload["id"].asInt());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.isMember("name"));
|
||||
TEST_ASSERT_EQUAL_STRING("Test Point", payload["name"].asString().c_str());
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include "serialization/MeshPacketSerializer.h"
|
||||
#include <Arduino.h>
|
||||
#include <json/json.h>
|
||||
#include <memory>
|
||||
#include <meshtastic/mesh.pb.h>
|
||||
#include <meshtastic/mqtt.pb.h>
|
||||
#include <meshtastic/telemetry.pb.h>
|
||||
#include <pb_decode.h>
|
||||
#include <pb_encode.h>
|
||||
#include <unity.h>
|
||||
|
||||
// Parse a JSON string into a Json::Value; returns Json::nullValue on failure.
|
||||
static inline Json::Value parse_json(const std::string &s)
|
||||
{
|
||||
Json::CharReaderBuilder b;
|
||||
Json::Value root;
|
||||
std::string errs;
|
||||
std::unique_ptr<Json::CharReader> reader(b.newCharReader());
|
||||
if (!reader->parse(s.c_str(), s.c_str() + s.size(), &root, &errs))
|
||||
return Json::Value();
|
||||
return root;
|
||||
}
|
||||
|
||||
// Helper function to create a test packet with the given port and payload
|
||||
static meshtastic_MeshPacket create_test_packet(meshtastic_PortNum port, const uint8_t *payload, size_t payload_size,
|
||||
int payload_variant = meshtastic_MeshPacket_decoded_tag)
|
||||
{
|
||||
meshtastic_MeshPacket packet = meshtastic_MeshPacket_init_zero;
|
||||
|
||||
packet.id = 0x9999;
|
||||
packet.from = 0x11223344;
|
||||
packet.to = 0x55667788;
|
||||
packet.channel = 0;
|
||||
packet.hop_limit = 3;
|
||||
packet.want_ack = false;
|
||||
packet.priority = meshtastic_MeshPacket_Priority_UNSET;
|
||||
packet.rx_time = 1609459200;
|
||||
packet.rx_snr = 10.5f;
|
||||
packet.hop_start = 3;
|
||||
packet.rx_rssi = -85;
|
||||
packet.delayed = meshtastic_MeshPacket_Delayed_NO_DELAY;
|
||||
|
||||
// Set decoded variant
|
||||
packet.which_payload_variant = payload_variant;
|
||||
packet.decoded.portnum = port;
|
||||
if (payload_variant == meshtastic_MeshPacket_encrypted_tag && payload) {
|
||||
packet.encrypted.size = payload_size;
|
||||
memcpy(packet.encrypted.bytes, payload, packet.encrypted.size);
|
||||
}
|
||||
if (payload && payload_size)
|
||||
memcpy(packet.decoded.payload.bytes, payload, payload_size);
|
||||
packet.decoded.payload.size = payload_size;
|
||||
packet.decoded.want_response = false;
|
||||
packet.decoded.dest = 0x55667788;
|
||||
packet.decoded.source = 0x11223344;
|
||||
packet.decoded.request_id = 0;
|
||||
packet.decoded.reply_id = 0;
|
||||
packet.decoded.emoji = 0;
|
||||
|
||||
return packet;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "test_helpers.h"
|
||||
#include <Arduino.h>
|
||||
#include <unity.h>
|
||||
|
||||
// Forward declarations for test functions
|
||||
void test_text_message_serialization();
|
||||
void test_text_message_serialization_null();
|
||||
void test_text_message_serialization_long_text();
|
||||
void test_text_message_serialization_oversized();
|
||||
void test_text_message_serialization_invalid_utf8();
|
||||
void test_position_serialization();
|
||||
void test_nodeinfo_serialization();
|
||||
void test_waypoint_serialization();
|
||||
void test_telemetry_device_metrics_serialization();
|
||||
void test_telemetry_environment_metrics_serialization();
|
||||
void test_telemetry_environment_metrics_comprehensive();
|
||||
void test_telemetry_environment_metrics_missing_fields();
|
||||
void test_telemetry_environment_metrics_complete_coverage();
|
||||
void test_telemetry_environment_metrics_unset_fields();
|
||||
void test_encrypted_packet_serialization();
|
||||
void test_empty_encrypted_packet();
|
||||
|
||||
void setup()
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
|
||||
// Text message tests
|
||||
RUN_TEST(test_text_message_serialization);
|
||||
RUN_TEST(test_text_message_serialization_null);
|
||||
RUN_TEST(test_text_message_serialization_long_text);
|
||||
RUN_TEST(test_text_message_serialization_oversized);
|
||||
RUN_TEST(test_text_message_serialization_invalid_utf8);
|
||||
|
||||
// Position tests
|
||||
RUN_TEST(test_position_serialization);
|
||||
|
||||
// Nodeinfo tests
|
||||
RUN_TEST(test_nodeinfo_serialization);
|
||||
|
||||
// Waypoint tests
|
||||
RUN_TEST(test_waypoint_serialization);
|
||||
|
||||
// Telemetry tests
|
||||
RUN_TEST(test_telemetry_device_metrics_serialization);
|
||||
RUN_TEST(test_telemetry_environment_metrics_serialization);
|
||||
RUN_TEST(test_telemetry_environment_metrics_comprehensive);
|
||||
RUN_TEST(test_telemetry_environment_metrics_missing_fields);
|
||||
RUN_TEST(test_telemetry_environment_metrics_complete_coverage);
|
||||
RUN_TEST(test_telemetry_environment_metrics_unset_fields);
|
||||
|
||||
// Encrypted packet test
|
||||
RUN_TEST(test_encrypted_packet_serialization);
|
||||
RUN_TEST(test_empty_encrypted_packet);
|
||||
|
||||
UNITY_END();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
delay(1000);
|
||||
}
|
||||
Reference in New Issue
Block a user