44#include " configuration.h"
55#include " mesh-pb-constants.h"
66#include " mesh/MeshService.h"
7+ #include " mesh/NodeDB.h"
78#include " mesh/StreamAPI.h"
89#include " mesh/StreamFrameWriter.h"
910#include < algorithm>
@@ -136,6 +137,13 @@ class StreamAPITestShim : public StreamAPI
136137 }
137138};
138139
140+ // / Minimal PhoneAPI transport for config-stream tests.
141+ class PhoneAPITestShim : public PhoneAPI
142+ {
143+ protected:
144+ bool checkIsConnected () override { return true ; }
145+ };
146+
139147// / Exposes framed-log hooks and records best-effort writes.
140148class LogHookStreamAPI : public StreamAPI
141149{
@@ -475,6 +483,45 @@ static void test_lockdown_admin_gate_rejects_undecodable_admin(void)
475483 " undecodable ADMIN_APP payload must not pass through even when authorized" );
476484}
477485
486+ static void test_want_config_includes_status_message_module_config (void )
487+ {
488+ ScopedMeshService scopedService;
489+ NodeDB testNodeDB;
490+ NodeDB *const savedNodeDB = nodeDB;
491+ nodeDB = &testNodeDB;
492+ const auto savedModuleConfig = moduleConfig;
493+ moduleConfig.has_statusmessage = true ;
494+ strncpy (moduleConfig.statusmessage .node_status , " Ready" , sizeof (moduleConfig.statusmessage .node_status ) - 1 );
495+ moduleConfig.statusmessage .node_status [sizeof (moduleConfig.statusmessage .node_status ) - 1 ] = ' \0 ' ;
496+
497+ meshtastic_ToRadio request = meshtastic_ToRadio_init_zero;
498+ request.which_payload_variant = meshtastic_ToRadio_want_config_id_tag;
499+ request.want_config_id = SPECIAL_NONCE_ONLY_CONFIG ;
500+ uint8_t requestBytes[meshtastic_ToRadio_size];
501+ const size_t requestSize = pb_encode_to_bytes (requestBytes, sizeof (requestBytes), &meshtastic_ToRadio_msg, &request);
502+
503+ PhoneAPITestShim api;
504+ api.handleToRadio (requestBytes, requestSize);
505+
506+ bool foundStatusMessageConfig = false ;
507+ for (unsigned i = 0 ; i < 64 && !foundStatusMessageConfig; ++i) {
508+ uint8_t responseBytes[meshtastic_FromRadio_size];
509+ const size_t responseSize = api.getFromRadio (responseBytes);
510+ meshtastic_FromRadio response = meshtastic_FromRadio_init_zero;
511+ TEST_ASSERT_TRUE (pb_decode_from_bytes (responseBytes, responseSize, &meshtastic_FromRadio_msg, &response));
512+ if (response.which_payload_variant == meshtastic_FromRadio_moduleConfig_tag &&
513+ response.moduleConfig .which_payload_variant == meshtastic_ModuleConfig_statusmessage_tag) {
514+ foundStatusMessageConfig = true ;
515+ TEST_ASSERT_EQUAL_STRING (" Ready" , response.moduleConfig .payload_variant .statusmessage .node_status );
516+ }
517+ }
518+
519+ api.close ();
520+ moduleConfig = savedModuleConfig;
521+ nodeDB = savedNodeDB;
522+ TEST_ASSERT_TRUE (foundStatusMessageConfig);
523+ }
524+
478525// / Unity per-test setup; fixtures are local to each test.
479526void setUp (void ) {}
480527// / Unity per-test teardown; fixtures clean themselves up.
@@ -496,6 +543,7 @@ void setup()
496543 RUN_TEST (test_stream_api_gates_logs_and_marks_them_best_effort);
497544 RUN_TEST (test_lockdown_admin_gate_ignores_wire_from);
498545 RUN_TEST (test_lockdown_admin_gate_rejects_undecodable_admin);
546+ RUN_TEST (test_want_config_includes_status_message_module_config);
499547 // usingProtobufs intentionally has no reset path, so this must run last.
500548 RUN_TEST (test_serial_console_suppresses_raw_output_in_protobuf_mode);
501549 exit (UNITY_END ());
0 commit comments