[network-diag] introduce AnswerBuilder to manage answer messages (#12887)

This commit introduces `AnswerBuilder` class to track and manage
Network Diagnostic answer messages. This class is used when the
response to a query requires multiple CoAP answer messages. It
automatically manages the inclusion of the Query ID and the Answer
TLVs(providing message indexing and "more-to-follow" flags) in each
allocated answer message, while maintaining all answer messages in a
queue. The `NetworkDiagnostic::Server` is updated to use the
`AnswerBuilder`, simplifying the logic for preparing and sending
answers.

The `AnswerBuilder` class is added in a new header file
`network_diagnostic_types.hpp` to allow for its reuse by other
modules in the future.
This commit is contained in:
Abtin Keshavarzian
2026-04-17 11:21:59 -07:00
committed by GitHub
parent 254043deec
commit 7eb59f71da
9 changed files with 380 additions and 113 deletions
+54
View File
@@ -286,6 +286,59 @@ void TestMessageQueue(void)
testFreeInstance(sInstance);
}
void TestMessageQueueEnqueueAllFrom(void)
{
// Validates the behavior of `MessageQueue::EnqueueAllFrom()` method.
MessageQueue messageQueue1;
MessageQueue messageQueue2;
Message *messages[kNumTestMessages];
sInstance = testInitInstance();
VerifyOrQuit(sInstance != nullptr);
sMessagePool = &sInstance->Get<MessagePool>();
for (Message *&msg : messages)
{
msg = sMessagePool->Allocate(Message::kTypeIp6);
VerifyOrQuit(msg != nullptr, "Message::Allocate() failed");
}
// Case 1: Both queues are empty
messageQueue1.EnqueueAllFrom(messageQueue2);
VerifyMessageQueueContent(messageQueue1, 0);
VerifyMessageQueueContent(messageQueue2, 0);
// Case 2: Target queue (Q1) is empty, input queue (Q2) is non-empty
messageQueue2.Enqueue(*messages[0]);
messageQueue2.Enqueue(*messages[1]);
VerifyMessageQueueContent(messageQueue2, 2, messages[0], messages[1]);
messageQueue1.EnqueueAllFrom(messageQueue2);
VerifyMessageQueueContent(messageQueue1, 2, messages[0], messages[1]);
VerifyMessageQueueContent(messageQueue2, 0);
// Case 3: Target queue (Q1) is non-empty, input queue (Q2) is empty
messageQueue1.EnqueueAllFrom(messageQueue2);
VerifyMessageQueueContent(messageQueue1, 2, messages[0], messages[1]);
VerifyMessageQueueContent(messageQueue2, 0);
// Case 4: Both queues are non-empty
messageQueue2.Enqueue(*messages[2]);
VerifyMessageQueueContent(messageQueue2, 1, messages[2]);
messageQueue1.EnqueueAllFrom(messageQueue2);
VerifyMessageQueueContent(messageQueue1, 3, messages[0], messages[1], messages[2]);
VerifyMessageQueueContent(messageQueue2, 0);
// Case 5: Using the same queue as both the target and input queues
messageQueue1.EnqueueAllFrom(messageQueue1);
VerifyMessageQueueContent(messageQueue1, 3, messages[0], messages[1], messages[2]);
messageQueue2.EnqueueAllFrom(messageQueue2);
VerifyMessageQueueContent(messageQueue2, 0);
testFreeInstance(sInstance);
}
// This function verifies the content of the message queue to match the passed in messages
void VerifyMessageQueueContentUsingOtApi(otMessageQueue *aQueue, int aExpectedLength, ...)
{
@@ -386,6 +439,7 @@ void TestMessageQueueOtApis(void)
int main(void)
{
ot::TestMessageQueue();
ot::TestMessageQueueEnqueueAllFrom();
ot::TestMessageQueueOtApis();
printf("All tests passed\n");
return 0;