mirror of
https://github.com/espressif/openthread.git
synced 2026-09-06 01:00:09 +00:00
[message] change queues to use non-circular linked list (#11630)
This commit updates the `MessageQueue` and `PriorityQueue` implementations to use non-circular doubly linked lists instead of the previous circular ones. Using a non-circular list requires the queue to track the head element, but it simplifies common operations like getting the head and iterating over the messages. Particularly, `Message::GetNext()` now simply returns the `mNext` pointer. Previously, `Message` had to store a pointer to its `mQueue` within its `Metadata` to identify the tail of the queue and stop the iteration correctly. This commit also updates the unit tests. In particular, `test_priority_queue` is significantly enhanced to cover many scenarios, such as multiple messages with the same priority, and messages with different priorities being added and removed in various orders.
This commit is contained in:
@@ -133,6 +133,46 @@ void TestMessageQueue(void)
|
||||
messageQueue.Dequeue(*messages[0]);
|
||||
VerifyMessageQueueContent(messageQueue, 0);
|
||||
|
||||
// Enqueue 2 messages and remove them in the same order added.
|
||||
messageQueue.Enqueue(*messages[0]);
|
||||
VerifyMessageQueueContent(messageQueue, 1, messages[0]);
|
||||
messageQueue.Enqueue(*messages[1]);
|
||||
VerifyMessageQueueContent(messageQueue, 2, messages[0], messages[1]);
|
||||
messageQueue.Dequeue(*messages[0]);
|
||||
VerifyMessageQueueContent(messageQueue, 1, messages[1]);
|
||||
messageQueue.Dequeue(*messages[1]);
|
||||
VerifyMessageQueueContent(messageQueue, 0);
|
||||
|
||||
// Enqueue 2 messages and remove them in reverse order added.
|
||||
messageQueue.Enqueue(*messages[0]);
|
||||
VerifyMessageQueueContent(messageQueue, 1, messages[0]);
|
||||
messageQueue.Enqueue(*messages[1]);
|
||||
VerifyMessageQueueContent(messageQueue, 2, messages[0], messages[1]);
|
||||
messageQueue.Dequeue(*messages[1]);
|
||||
VerifyMessageQueueContent(messageQueue, 1, messages[0]);
|
||||
messageQueue.Dequeue(*messages[0]);
|
||||
VerifyMessageQueueContent(messageQueue, 0);
|
||||
|
||||
// Enqueue 2 messages at the head and remove them in the same order added.
|
||||
messageQueue.Enqueue(*messages[0], MessageQueue::kQueuePositionHead);
|
||||
VerifyMessageQueueContent(messageQueue, 1, messages[0]);
|
||||
messageQueue.Enqueue(*messages[1], MessageQueue::kQueuePositionHead);
|
||||
VerifyMessageQueueContent(messageQueue, 2, messages[1], messages[0]);
|
||||
messageQueue.Dequeue(*messages[0]);
|
||||
VerifyMessageQueueContent(messageQueue, 1, messages[1]);
|
||||
messageQueue.Dequeue(*messages[1]);
|
||||
VerifyMessageQueueContent(messageQueue, 0);
|
||||
|
||||
// Enqueue 2 messages at the head and remove them in the reverse order added.
|
||||
messageQueue.Enqueue(*messages[0], MessageQueue::kQueuePositionHead);
|
||||
VerifyMessageQueueContent(messageQueue, 1, messages[0]);
|
||||
messageQueue.Enqueue(*messages[1], MessageQueue::kQueuePositionHead);
|
||||
VerifyMessageQueueContent(messageQueue, 2, messages[1], messages[0]);
|
||||
messageQueue.Dequeue(*messages[1]);
|
||||
VerifyMessageQueueContent(messageQueue, 1, messages[0]);
|
||||
messageQueue.Dequeue(*messages[0]);
|
||||
VerifyMessageQueueContent(messageQueue, 0);
|
||||
|
||||
// Enqueue 5 messages
|
||||
messageQueue.Enqueue(*messages[0]);
|
||||
VerifyMessageQueueContent(messageQueue, 1, messages[0]);
|
||||
@@ -333,8 +373,6 @@ void TestMessageQueueOtApis(void)
|
||||
|
||||
message = otMessageQueueGetNext(&queue2, messages[0]);
|
||||
VerifyOrQuit(message == messages[1], "otMessageQueueGetNext() failed");
|
||||
message = otMessageQueueGetNext(&queue, messages[0]);
|
||||
VerifyOrQuit(message == nullptr, "otMessageQueueGetNext() did not return nullptr for message not in the queue.");
|
||||
|
||||
// Remove all element and make sure queue is empty
|
||||
otMessageQueueDequeue(&queue, messages[2]);
|
||||
|
||||
@@ -37,10 +37,6 @@
|
||||
|
||||
namespace ot {
|
||||
|
||||
#define kNumNewPriorityTestMessages 2
|
||||
#define kNumSetPriorityTestMessages 2
|
||||
#define kNumTestMessages (kNumNewPriorityTestMessages + kNumSetPriorityTestMessages)
|
||||
|
||||
// This function verifies the content of the priority queue to match the passed in messages
|
||||
void VerifyPriorityQueueContent(PriorityQueue &aPriorityQueue, int aExpectedLength, ...)
|
||||
{
|
||||
@@ -135,140 +131,541 @@ void VerifyPriorityQueueContent(PriorityQueue &aPriorityQueue, int aExpectedLeng
|
||||
VerifyOrQuit(message == nullptr, "`for` loop iteration resulted in fewer entries than expected");
|
||||
}
|
||||
|
||||
// NOLINTBEGIN(modernize-loop-convert)
|
||||
void TestPriorityQueue(void)
|
||||
{
|
||||
static constexpr uint16_t kNumNewPriorityTestMessages = 2;
|
||||
static constexpr uint16_t kNumSetPriorityTestMessages = 2;
|
||||
static constexpr uint16_t kNumTestMessages = (kNumNewPriorityTestMessages + kNumSetPriorityTestMessages);
|
||||
|
||||
// Use two char abbreviated names for different priority levels;
|
||||
static constexpr uint8_t kNw = Message::kPriorityNet; // Network level (highest priority)
|
||||
static constexpr uint8_t kHi = Message::kPriorityHigh; // High priority
|
||||
static constexpr uint8_t kMd = Message::kPriorityNormal; // Middle (or Normal) priority
|
||||
static constexpr uint8_t kLo = Message::kPriorityLow; // Low priority.
|
||||
static constexpr uint8_t kNumPriorities = Message::kNumPriorities;
|
||||
|
||||
Instance *instance;
|
||||
MessagePool *messagePool;
|
||||
PriorityQueue queue;
|
||||
Message *msgNet[kNumTestMessages];
|
||||
Message *msgHigh[kNumTestMessages];
|
||||
Message *msgNor[kNumTestMessages];
|
||||
Message *msgLow[kNumTestMessages];
|
||||
Message *msg[kNumPriorities][kNumTestMessages];
|
||||
|
||||
instance = testInitInstance();
|
||||
VerifyOrQuit(instance != nullptr, "Null OpenThread instance");
|
||||
|
||||
messagePool = &instance->Get<MessagePool>();
|
||||
|
||||
// Use the function "Allocate()" to allocate messages with different priorities
|
||||
for (int i = 0; i < kNumNewPriorityTestMessages; i++)
|
||||
for (uint8_t prio = 0; prio < kNumPriorities; prio++)
|
||||
{
|
||||
msgNet[i] = messagePool->Allocate(Message::kTypeIp6, 0, Message::Settings(Message::kPriorityNet));
|
||||
VerifyOrQuit(msgNet[i] != nullptr);
|
||||
msgHigh[i] = messagePool->Allocate(Message::kTypeIp6, 0, Message::Settings(Message::kPriorityHigh));
|
||||
VerifyOrQuit(msgHigh[i] != nullptr);
|
||||
msgNor[i] = messagePool->Allocate(Message::kTypeIp6, 0, Message::Settings(Message::kPriorityNormal));
|
||||
VerifyOrQuit(msgNor[i] != nullptr);
|
||||
msgLow[i] = messagePool->Allocate(Message::kTypeIp6, 0, Message::Settings(Message::kPriorityLow));
|
||||
VerifyOrQuit(msgLow[i] != nullptr);
|
||||
}
|
||||
Message::Priority priority = static_cast<Message::Priority>(prio);
|
||||
|
||||
// Use the function "SetPriority()" to allocate messages with different priorities
|
||||
for (int i = kNumNewPriorityTestMessages; i < kNumTestMessages; i++)
|
||||
{
|
||||
msgNet[i] = messagePool->Allocate(Message::kTypeIp6);
|
||||
VerifyOrQuit(msgNet[i] != nullptr);
|
||||
SuccessOrQuit(msgNet[i]->SetPriority(Message::kPriorityNet));
|
||||
msgHigh[i] = messagePool->Allocate(Message::kTypeIp6);
|
||||
VerifyOrQuit(msgHigh[i] != nullptr);
|
||||
SuccessOrQuit(msgHigh[i]->SetPriority(Message::kPriorityHigh));
|
||||
msgNor[i] = messagePool->Allocate(Message::kTypeIp6);
|
||||
VerifyOrQuit(msgNor[i] != nullptr);
|
||||
SuccessOrQuit(msgNor[i]->SetPriority(Message::kPriorityNormal));
|
||||
msgLow[i] = messagePool->Allocate(Message::kTypeIp6);
|
||||
VerifyOrQuit(msgLow[i] != nullptr);
|
||||
SuccessOrQuit(msgLow[i]->SetPriority(Message::kPriorityLow));
|
||||
// Use the function "Allocate()" to allocate messages with different priorities
|
||||
for (int i = 0; i < kNumNewPriorityTestMessages; i++)
|
||||
{
|
||||
msg[prio][i] = messagePool->Allocate(Message::kTypeIp6, 0, Message::Settings(priority));
|
||||
VerifyOrQuit(msg[prio][i] != nullptr);
|
||||
}
|
||||
|
||||
// Use the function "SetPriority()" to allocate messages with different priorities
|
||||
for (int i = kNumNewPriorityTestMessages; i < kNumTestMessages; i++)
|
||||
{
|
||||
msg[prio][i] = messagePool->Allocate(Message::kTypeIp6);
|
||||
VerifyOrQuit(msg[prio][i] != nullptr);
|
||||
SuccessOrQuit(msg[prio][i]->SetPriority(priority));
|
||||
}
|
||||
}
|
||||
|
||||
// Check the `GetPriority()`
|
||||
for (int i = 0; i < kNumTestMessages; i++)
|
||||
{
|
||||
VerifyOrQuit(msgLow[i]->GetPriority() == Message::kPriorityLow);
|
||||
VerifyOrQuit(msgNor[i]->GetPriority() == Message::kPriorityNormal);
|
||||
VerifyOrQuit(msgHigh[i]->GetPriority() == Message::kPriorityHigh);
|
||||
VerifyOrQuit(msgNet[i]->GetPriority() == Message::kPriorityNet);
|
||||
VerifyOrQuit(msg[kLo][i]->GetPriority() == Message::kPriorityLow);
|
||||
VerifyOrQuit(msg[kMd][i]->GetPriority() == Message::kPriorityNormal);
|
||||
VerifyOrQuit(msg[kHi][i]->GetPriority() == Message::kPriorityHigh);
|
||||
VerifyOrQuit(msg[kNw][i]->GetPriority() == Message::kPriorityNet);
|
||||
}
|
||||
|
||||
// Verify case of an empty queue.
|
||||
VerifyPriorityQueueContent(queue, 0);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Messages with the same priority only.
|
||||
|
||||
for (uint8_t prio = 0; prio < kNumPriorities; prio++)
|
||||
{
|
||||
// Add and remove one message only
|
||||
queue.Enqueue(*msg[prio][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio][0]);
|
||||
queue.Dequeue(*msg[prio][0]);
|
||||
VerifyPriorityQueueContent(queue, 0);
|
||||
|
||||
// Add three messages and then dequeue them in different orders.
|
||||
|
||||
for (uint8_t test = 0; test < 3; test++)
|
||||
{
|
||||
queue.Enqueue(*msg[prio][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio][0]);
|
||||
queue.Enqueue(*msg[prio][1]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio][0], msg[prio][1]);
|
||||
queue.Enqueue(*msg[prio][2]);
|
||||
VerifyPriorityQueueContent(queue, 3, msg[prio][0], msg[prio][1], msg[prio][2]);
|
||||
|
||||
switch (test)
|
||||
{
|
||||
case 0:
|
||||
// Remove the messages in the same order added.
|
||||
queue.Dequeue(*msg[prio][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio][1], msg[prio][2]);
|
||||
queue.Dequeue(*msg[prio][1]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio][2]);
|
||||
queue.Dequeue(*msg[prio][2]);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Remove the message in the reverse order added
|
||||
queue.Dequeue(*msg[prio][2]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio][0], msg[prio][1]);
|
||||
queue.Dequeue(*msg[prio][1]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio][0]);
|
||||
queue.Dequeue(*msg[prio][0]);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Remove the message in random order added.
|
||||
queue.Dequeue(*msg[prio][1]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio][0], msg[prio][2]);
|
||||
queue.Dequeue(*msg[prio][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio][2]);
|
||||
queue.Dequeue(*msg[prio][2]);
|
||||
break;
|
||||
}
|
||||
|
||||
VerifyPriorityQueueContent(queue, 0);
|
||||
}
|
||||
}
|
||||
|
||||
VerifyPriorityQueueContent(queue, 0);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Messages with the two different priorities (`prio1` lower than `prio2`)
|
||||
|
||||
for (uint8_t prio1 = 0; prio1 < kNumPriorities - 1; prio1++)
|
||||
{
|
||||
for (uint8_t prio2 = prio1 + 1; prio2 < kNumPriorities; prio2++)
|
||||
{
|
||||
// Add one message with `prio1` and one with `prio2` and
|
||||
// then remove them. Cover all possible combinations
|
||||
// (order to add and remove).
|
||||
|
||||
for (uint8_t test = 0; test < 4; test++)
|
||||
{
|
||||
switch (test)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
// Add lower priority first, then higher priority
|
||||
queue.Enqueue(*msg[prio1][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio1][0]);
|
||||
queue.Enqueue(*msg[prio2][0]);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
// Add higher priority first, then lower priority
|
||||
queue.Enqueue(*msg[prio2][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio2][0]);
|
||||
queue.Enqueue(*msg[prio1][0]);
|
||||
break;
|
||||
}
|
||||
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio2][0], msg[prio1][0]);
|
||||
|
||||
switch (test)
|
||||
{
|
||||
case 0:
|
||||
case 2:
|
||||
// Remove lower priority first, then higher priority.
|
||||
queue.Dequeue(*msg[prio1][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio2][0]);
|
||||
queue.Dequeue(*msg[prio2][0]);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 3:
|
||||
// Remove higher priority first, then lower priority
|
||||
queue.Dequeue(*msg[prio2][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio1][0]);
|
||||
queue.Dequeue(*msg[prio1][0]);
|
||||
break;
|
||||
}
|
||||
|
||||
VerifyPriorityQueueContent(queue, 0);
|
||||
}
|
||||
|
||||
// Add two messages with `prio1` (lower) and one with
|
||||
// `prio2` (higher) and then remove them. Cover all
|
||||
// possible combinations to add and remove.
|
||||
|
||||
for (uint8_t test = 0; test < 6; test++)
|
||||
{
|
||||
switch (test)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
// Add two lower priority messages first, then one higher priority
|
||||
queue.Enqueue(*msg[prio1][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio1][0]);
|
||||
queue.Enqueue(*msg[prio1][1]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio1][0], msg[prio1][1]);
|
||||
queue.Enqueue(*msg[prio2][0]);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
// Add one higher priority first, then two lower priority messages.
|
||||
queue.Enqueue(*msg[prio2][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio2][0]);
|
||||
queue.Enqueue(*msg[prio1][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio2][0], msg[prio1][0]);
|
||||
queue.Enqueue(*msg[prio1][1]);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
case 5:
|
||||
// Add one lower priority first, then a higher priority, finally one lower priority.
|
||||
queue.Enqueue(*msg[prio1][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio1][0]);
|
||||
queue.Enqueue(*msg[prio2][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio2][0], msg[prio1][0]);
|
||||
queue.Enqueue(*msg[prio1][1]);
|
||||
break;
|
||||
}
|
||||
|
||||
VerifyPriorityQueueContent(queue, 3, msg[prio2][0], msg[prio1][0], msg[prio1][1]);
|
||||
|
||||
switch (test)
|
||||
{
|
||||
case 0:
|
||||
queue.Dequeue(*msg[prio1][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio2][0], msg[prio1][1]);
|
||||
queue.Dequeue(*msg[prio1][1]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio2][0]);
|
||||
queue.Dequeue(*msg[prio2][0]);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
queue.Dequeue(*msg[prio1][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio2][0], msg[prio1][1]);
|
||||
queue.Dequeue(*msg[prio2][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio1][1]);
|
||||
queue.Dequeue(*msg[prio1][1]);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
queue.Dequeue(*msg[prio1][1]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio2][0], msg[prio1][0]);
|
||||
queue.Dequeue(*msg[prio1][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio2][0]);
|
||||
queue.Dequeue(*msg[prio2][0]);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
queue.Dequeue(*msg[prio1][1]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio2][0], msg[prio1][0]);
|
||||
queue.Dequeue(*msg[prio2][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio1][0]);
|
||||
queue.Dequeue(*msg[prio1][0]);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
queue.Dequeue(*msg[prio2][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio1][0], msg[prio1][1]);
|
||||
queue.Dequeue(*msg[prio1][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio1][1]);
|
||||
queue.Dequeue(*msg[prio1][1]);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
queue.Dequeue(*msg[prio2][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio1][0], msg[prio1][1]);
|
||||
queue.Dequeue(*msg[prio1][1]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio1][0]);
|
||||
queue.Dequeue(*msg[prio1][0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VerifyPriorityQueueContent(queue, 0);
|
||||
|
||||
// Add two messages with `prio2` (higher) and one with
|
||||
// `prio1` (lower) and then remove them. Cover all
|
||||
// possible combinations to add and remove.
|
||||
|
||||
for (uint8_t test = 0; test < 6; test++)
|
||||
{
|
||||
switch (test)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
// Add two higher priority messages first, then one lower priority
|
||||
queue.Enqueue(*msg[prio2][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio2][0]);
|
||||
queue.Enqueue(*msg[prio2][1]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio2][0], msg[prio2][1]);
|
||||
queue.Enqueue(*msg[prio1][0]);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
// Add one lower priority first, then two higher priority messages.
|
||||
queue.Enqueue(*msg[prio1][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio1][0]);
|
||||
queue.Enqueue(*msg[prio2][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio2][0], msg[prio1][0]);
|
||||
queue.Enqueue(*msg[prio2][1]);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
case 5:
|
||||
// Add one higher priority first, then a lower priority, finally one higher priority.
|
||||
queue.Enqueue(*msg[prio2][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio2][0]);
|
||||
queue.Enqueue(*msg[prio1][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio2][0], msg[prio1][0]);
|
||||
queue.Enqueue(*msg[prio2][1]);
|
||||
break;
|
||||
}
|
||||
|
||||
VerifyPriorityQueueContent(queue, 3, msg[prio2][0], msg[prio2][1], msg[prio1][0]);
|
||||
|
||||
switch (test)
|
||||
{
|
||||
case 0:
|
||||
queue.Dequeue(*msg[prio2][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio2][1], msg[prio1][0]);
|
||||
queue.Dequeue(*msg[prio2][1]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio1][0]);
|
||||
queue.Dequeue(*msg[prio1][0]);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
queue.Dequeue(*msg[prio2][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio2][1], msg[prio1][0]);
|
||||
queue.Dequeue(*msg[prio1][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio2][1]);
|
||||
queue.Dequeue(*msg[prio2][1]);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
queue.Dequeue(*msg[prio2][1]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio2][0], msg[prio1][0]);
|
||||
queue.Dequeue(*msg[prio2][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio1][0]);
|
||||
queue.Dequeue(*msg[prio1][0]);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
queue.Dequeue(*msg[prio2][1]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio2][0], msg[prio1][0]);
|
||||
queue.Dequeue(*msg[prio1][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio2][0]);
|
||||
queue.Dequeue(*msg[prio2][0]);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
queue.Dequeue(*msg[prio1][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio2][0], msg[prio2][1]);
|
||||
queue.Dequeue(*msg[prio2][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio2][1]);
|
||||
queue.Dequeue(*msg[prio2][1]);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
queue.Dequeue(*msg[prio1][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio2][0], msg[prio2][1]);
|
||||
queue.Dequeue(*msg[prio2][1]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio2][0]);
|
||||
queue.Dequeue(*msg[prio2][0]);
|
||||
break;
|
||||
}
|
||||
|
||||
VerifyPriorityQueueContent(queue, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Messages with the three different priorities (prio1 < prio2 < prio3)
|
||||
|
||||
for (uint8_t prio1 = 0; prio1 < kNumPriorities - 2; prio1++)
|
||||
{
|
||||
for (uint8_t prio2 = prio1 + 1; prio2 < kNumPriorities - 1; prio2++)
|
||||
{
|
||||
for (uint8_t prio3 = prio2 + 1; prio3 < kNumPriorities; prio3++)
|
||||
{
|
||||
for (uint8_t test = 0; test < 6; test++)
|
||||
{
|
||||
switch (test)
|
||||
{
|
||||
case 0:
|
||||
queue.Enqueue(*msg[prio1][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio1][0]);
|
||||
queue.Enqueue(*msg[prio2][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio2][0], msg[prio1][0]);
|
||||
queue.Enqueue(*msg[prio3][0]);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
queue.Enqueue(*msg[prio1][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio1][0]);
|
||||
queue.Enqueue(*msg[prio3][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio3][0], msg[prio1][0]);
|
||||
queue.Enqueue(*msg[prio2][0]);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
queue.Enqueue(*msg[prio2][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio2][0]);
|
||||
queue.Enqueue(*msg[prio1][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio2][0], msg[prio1][0]);
|
||||
queue.Enqueue(*msg[prio3][0]);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
queue.Enqueue(*msg[prio2][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio2][0]);
|
||||
queue.Enqueue(*msg[prio3][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio3][0], msg[prio2][0]);
|
||||
queue.Enqueue(*msg[prio1][0]);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
queue.Enqueue(*msg[prio3][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio3][0]);
|
||||
queue.Enqueue(*msg[prio1][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio3][0], msg[prio1][0]);
|
||||
queue.Enqueue(*msg[prio2][0]);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
queue.Enqueue(*msg[prio3][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio3][0]);
|
||||
queue.Enqueue(*msg[prio2][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio3][0], msg[prio2][0]);
|
||||
queue.Enqueue(*msg[prio1][0]);
|
||||
break;
|
||||
}
|
||||
|
||||
VerifyPriorityQueueContent(queue, 3, msg[prio3][0], msg[prio2][0], msg[prio1][0]);
|
||||
|
||||
switch (test)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
queue.Dequeue(*msg[prio1][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio3][0], msg[prio2][0]);
|
||||
queue.Dequeue(*msg[prio2][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio3][0]);
|
||||
queue.Dequeue(*msg[prio3][0]);
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
queue.Dequeue(*msg[prio3][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[prio2][0], msg[prio1][0]);
|
||||
queue.Dequeue(*msg[prio1][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[prio2][0]);
|
||||
queue.Dequeue(*msg[prio2][0]);
|
||||
break;
|
||||
}
|
||||
|
||||
VerifyPriorityQueueContent(queue, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Add msgs in different orders and check the content of queue.
|
||||
queue.Enqueue(*msgHigh[0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msgHigh[0]);
|
||||
queue.Enqueue(*msgHigh[1]);
|
||||
VerifyPriorityQueueContent(queue, 2, msgHigh[0], msgHigh[1]);
|
||||
queue.Enqueue(*msgNet[0]);
|
||||
VerifyPriorityQueueContent(queue, 3, msgNet[0], msgHigh[0], msgHigh[1]);
|
||||
queue.Enqueue(*msgNet[1]);
|
||||
VerifyPriorityQueueContent(queue, 4, msgNet[0], msgNet[1], msgHigh[0], msgHigh[1]);
|
||||
queue.Enqueue(*msgHigh[2]);
|
||||
VerifyPriorityQueueContent(queue, 5, msgNet[0], msgNet[1], msgHigh[0], msgHigh[1], msgHigh[2]);
|
||||
queue.Enqueue(*msgLow[0]);
|
||||
VerifyPriorityQueueContent(queue, 6, msgNet[0], msgNet[1], msgHigh[0], msgHigh[1], msgHigh[2], msgLow[0]);
|
||||
queue.Enqueue(*msgNor[0]);
|
||||
VerifyPriorityQueueContent(queue, 7, msgNet[0], msgNet[1], msgHigh[0], msgHigh[1], msgHigh[2], msgNor[0],
|
||||
msgLow[0]);
|
||||
queue.Enqueue(*msgHigh[3]);
|
||||
VerifyPriorityQueueContent(queue, 8, msgNet[0], msgNet[1], msgHigh[0], msgHigh[1], msgHigh[2], msgHigh[3],
|
||||
msgNor[0], msgLow[0]);
|
||||
|
||||
queue.Enqueue(*msg[kHi][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[kHi][0]);
|
||||
queue.Enqueue(*msg[kHi][1]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[kHi][0], msg[kHi][1]);
|
||||
queue.Enqueue(*msg[kNw][0]);
|
||||
VerifyPriorityQueueContent(queue, 3, msg[kNw][0], msg[kHi][0], msg[kHi][1]);
|
||||
queue.Enqueue(*msg[kNw][1]);
|
||||
VerifyPriorityQueueContent(queue, 4, msg[kNw][0], msg[kNw][1], msg[kHi][0], msg[kHi][1]);
|
||||
queue.Enqueue(*msg[kHi][2]);
|
||||
VerifyPriorityQueueContent(queue, 5, msg[kNw][0], msg[kNw][1], msg[kHi][0], msg[kHi][1], msg[kHi][2]);
|
||||
queue.Enqueue(*msg[kLo][0]);
|
||||
VerifyPriorityQueueContent(queue, 6, msg[kNw][0], msg[kNw][1], msg[kHi][0], msg[kHi][1], msg[kHi][2], msg[kLo][0]);
|
||||
queue.Enqueue(*msg[kMd][0]);
|
||||
VerifyPriorityQueueContent(queue, 7, msg[kNw][0], msg[kNw][1], msg[kHi][0], msg[kHi][1], msg[kHi][2], msg[kMd][0],
|
||||
msg[kLo][0]);
|
||||
queue.Enqueue(*msg[kHi][3]);
|
||||
VerifyPriorityQueueContent(queue, 8, msg[kNw][0], msg[kNw][1], msg[kHi][0], msg[kHi][1], msg[kHi][2], msg[kHi][3],
|
||||
msg[kMd][0], msg[kLo][0]);
|
||||
|
||||
// Remove messages in different order and check the content of queue in each step.
|
||||
queue.Dequeue(*msgNet[0]);
|
||||
VerifyPriorityQueueContent(queue, 7, msgNet[1], msgHigh[0], msgHigh[1], msgHigh[2], msgHigh[3], msgNor[0],
|
||||
msgLow[0]);
|
||||
queue.Dequeue(*msgHigh[2]);
|
||||
VerifyPriorityQueueContent(queue, 6, msgNet[1], msgHigh[0], msgHigh[1], msgHigh[3], msgNor[0], msgLow[0]);
|
||||
queue.Dequeue(*msgNor[0]);
|
||||
VerifyPriorityQueueContent(queue, 5, msgNet[1], msgHigh[0], msgHigh[1], msgHigh[3], msgLow[0]);
|
||||
queue.Dequeue(*msgHigh[1]);
|
||||
VerifyPriorityQueueContent(queue, 4, msgNet[1], msgHigh[0], msgHigh[3], msgLow[0]);
|
||||
queue.Dequeue(*msgLow[0]);
|
||||
VerifyPriorityQueueContent(queue, 3, msgNet[1], msgHigh[0], msgHigh[3]);
|
||||
queue.Dequeue(*msgNet[1]);
|
||||
VerifyPriorityQueueContent(queue, 2, msgHigh[0], msgHigh[3]);
|
||||
queue.Dequeue(*msgHigh[0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msgHigh[3]);
|
||||
queue.Dequeue(*msgHigh[3]);
|
||||
queue.Dequeue(*msg[kNw][0]);
|
||||
VerifyPriorityQueueContent(queue, 7, msg[kNw][1], msg[kHi][0], msg[kHi][1], msg[kHi][2], msg[kHi][3], msg[kMd][0],
|
||||
msg[kLo][0]);
|
||||
queue.Dequeue(*msg[kHi][2]);
|
||||
VerifyPriorityQueueContent(queue, 6, msg[kNw][1], msg[kHi][0], msg[kHi][1], msg[kHi][3], msg[kMd][0], msg[kLo][0]);
|
||||
queue.Dequeue(*msg[kMd][0]);
|
||||
VerifyPriorityQueueContent(queue, 5, msg[kNw][1], msg[kHi][0], msg[kHi][1], msg[kHi][3], msg[kLo][0]);
|
||||
queue.Dequeue(*msg[kHi][1]);
|
||||
VerifyPriorityQueueContent(queue, 4, msg[kNw][1], msg[kHi][0], msg[kHi][3], msg[kLo][0]);
|
||||
queue.Dequeue(*msg[kLo][0]);
|
||||
VerifyPriorityQueueContent(queue, 3, msg[kNw][1], msg[kHi][0], msg[kHi][3]);
|
||||
queue.Dequeue(*msg[kNw][1]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[kHi][0], msg[kHi][3]);
|
||||
queue.Dequeue(*msg[kHi][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[kHi][3]);
|
||||
queue.Dequeue(*msg[kHi][3]);
|
||||
VerifyPriorityQueueContent(queue, 0);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Validate that priority of an already queued message in a priority queue cannot change
|
||||
queue.Enqueue(*msgNor[0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msgNor[0]);
|
||||
queue.Enqueue(*msgHigh[0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msgHigh[0], msgNor[0]);
|
||||
queue.Enqueue(*msgLow[0]);
|
||||
VerifyPriorityQueueContent(queue, 3, msgHigh[0], msgNor[0], msgLow[0]);
|
||||
queue.Enqueue(*msg[kMd][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[kMd][0]);
|
||||
queue.Enqueue(*msg[kHi][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[kHi][0], msg[kMd][0]);
|
||||
queue.Enqueue(*msg[kLo][0]);
|
||||
VerifyPriorityQueueContent(queue, 3, msg[kHi][0], msg[kMd][0], msg[kLo][0]);
|
||||
|
||||
VerifyOrQuit(msgNor[0]->SetPriority(Message::kPriorityNet) == kErrorInvalidState);
|
||||
VerifyOrQuit(msgLow[0]->SetPriority(Message::kPriorityLow) == kErrorInvalidState);
|
||||
VerifyOrQuit(msgLow[0]->SetPriority(Message::kPriorityNormal) == kErrorInvalidState);
|
||||
VerifyOrQuit(msgHigh[0]->SetPriority(Message::kPriorityNormal) == kErrorInvalidState);
|
||||
VerifyPriorityQueueContent(queue, 3, msgHigh[0], msgNor[0], msgLow[0]);
|
||||
VerifyOrQuit(msg[kMd][0]->SetPriority(Message::kPriorityNet) == kErrorInvalidState);
|
||||
VerifyOrQuit(msg[kLo][0]->SetPriority(Message::kPriorityLow) == kErrorInvalidState);
|
||||
VerifyOrQuit(msg[kLo][0]->SetPriority(Message::kPriorityNormal) == kErrorInvalidState);
|
||||
VerifyOrQuit(msg[kHi][0]->SetPriority(Message::kPriorityNormal) == kErrorInvalidState);
|
||||
VerifyPriorityQueueContent(queue, 3, msg[kHi][0], msg[kMd][0], msg[kLo][0]);
|
||||
|
||||
// Remove messages from the queue
|
||||
queue.Dequeue(*msgHigh[0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msgNor[0], msgLow[0]);
|
||||
queue.Dequeue(*msgLow[0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msgNor[0]);
|
||||
queue.Dequeue(*msgNor[0]);
|
||||
queue.Dequeue(*msg[kHi][0]);
|
||||
VerifyPriorityQueueContent(queue, 2, msg[kMd][0], msg[kLo][0]);
|
||||
queue.Dequeue(*msg[kLo][0]);
|
||||
VerifyPriorityQueueContent(queue, 1, msg[kMd][0]);
|
||||
queue.Dequeue(*msg[kMd][0]);
|
||||
VerifyPriorityQueueContent(queue, 0);
|
||||
|
||||
for (Message *message : msgNor)
|
||||
for (Message *message : msg[kMd])
|
||||
{
|
||||
SuccessOrQuit(message->SetPriority(Message::kPriorityNormal));
|
||||
}
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Range-based `for` and dequeue during iteration
|
||||
|
||||
for (uint16_t removeIndex = 0; removeIndex < 4; removeIndex++)
|
||||
{
|
||||
uint16_t index = 0;
|
||||
|
||||
queue.Enqueue(*msgNor[0]);
|
||||
queue.Enqueue(*msgNor[1]);
|
||||
queue.Enqueue(*msgNor[2]);
|
||||
queue.Enqueue(*msgNor[3]);
|
||||
VerifyPriorityQueueContent(queue, 4, msgNor[0], msgNor[1], msgNor[2], msgNor[3]);
|
||||
queue.Enqueue(*msg[kMd][0]);
|
||||
queue.Enqueue(*msg[kMd][1]);
|
||||
queue.Enqueue(*msg[kMd][2]);
|
||||
queue.Enqueue(*msg[kMd][3]);
|
||||
VerifyPriorityQueueContent(queue, 4, msg[kMd][0], msg[kMd][1], msg[kMd][2], msg[kMd][3]);
|
||||
|
||||
// While iterating over the queue remove the entry at `removeIndex`
|
||||
for (Message &message : queue)
|
||||
@@ -278,7 +675,7 @@ void TestPriorityQueue(void)
|
||||
queue.Dequeue(message);
|
||||
}
|
||||
|
||||
VerifyOrQuit(&message == msgNor[index++]);
|
||||
VerifyOrQuit(&message == msg[kMd][index++]);
|
||||
}
|
||||
|
||||
index = 0;
|
||||
@@ -291,7 +688,7 @@ void TestPriorityQueue(void)
|
||||
index++;
|
||||
}
|
||||
|
||||
VerifyOrQuit(&message == msgNor[index++]);
|
||||
VerifyOrQuit(&message == msg[kMd][index++]);
|
||||
queue.Dequeue(message);
|
||||
}
|
||||
|
||||
@@ -300,6 +697,7 @@ void TestPriorityQueue(void)
|
||||
|
||||
testFreeInstance(instance);
|
||||
}
|
||||
// NOLINTEND(modernize-loop-convert)
|
||||
|
||||
} // namespace ot
|
||||
|
||||
|
||||
Reference in New Issue
Block a user