made RawQueue options type-safe
diff --git a/aos/linux_code/ipc_lib/ipc_lib.gyp b/aos/linux_code/ipc_lib/ipc_lib.gyp
index edca758..35091e5 100644
--- a/aos/linux_code/ipc_lib/ipc_lib.gyp
+++ b/aos/linux_code/ipc_lib/ipc_lib.gyp
@@ -50,6 +50,9 @@
'core_lib',
'<(AOS)/build/aos.gyp:logging_interface',
],
+ 'export_dependent_settings': [
+ '<(AOS)/build/aos.gyp:logging_interface',
+ ],
},
{
'target_name': 'raw_queue_test',
@@ -66,6 +69,7 @@
'<(AOS)/common/common.gyp:time',
'<(AOS)/common/common.gyp:die',
'<(AOS)/common/util/util.gyp:thread',
+ '<(AOS)/common/util/util.gyp:death_test_log_implementation',
],
},
{
diff --git a/aos/linux_code/ipc_lib/queue.cc b/aos/linux_code/ipc_lib/queue.cc
index a3ec15a..e8e81dc 100644
--- a/aos/linux_code/ipc_lib/queue.cc
+++ b/aos/linux_code/ipc_lib/queue.cc
@@ -12,7 +12,6 @@
#include <memory>
#include <algorithm>
-#include "aos/common/logging/logging.h"
#include "aos/common/type_traits.h"
#include "aos/linux_code/ipc_lib/core_lib.h"
@@ -35,11 +34,11 @@
} // namespace
-const int RawQueue::kPeek;
-const int RawQueue::kFromEnd;
-const int RawQueue::kNonBlock;
-const int RawQueue::kBlock;
-const int RawQueue::kOverride;
+constexpr Options<RawQueue>::Option RawQueue::kPeek;
+constexpr Options<RawQueue>::Option RawQueue::kFromEnd;
+constexpr Options<RawQueue>::Option RawQueue::kNonBlock;
+constexpr Options<RawQueue>::Option RawQueue::kBlock;
+constexpr Options<RawQueue>::Option RawQueue::kOverride;
// This is what gets stuck in before each queue message in memory. It is always
// allocated aligned to 8 bytes and its size has to maintain that alignment for
@@ -297,9 +296,9 @@
return r;
}
-bool RawQueue::WriteMessage(void *msg, int options) {
+bool RawQueue::DoWriteMessage(void *msg, Options<RawQueue> options) {
if (kWriteDebug) {
- printf("queue: %p->WriteMessage(%p, %x)\n", this, msg, options);
+ printf("queue: %p->WriteMessage(%p, %x)\n", this, msg, options.printable());
}
{
MutexLocker locker(&data_lock_);
@@ -324,6 +323,7 @@
DecrementMessageReferenceCount(data_[data_start_]);
data_start_ = index_add1(data_start_);
} else { // kBlock
+ assert(options & kBlock);
if (kWriteDebug) {
printf("queue: going to wait for writable_ of %p\n", this);
}
@@ -370,7 +370,7 @@
}
}
-bool RawQueue::ReadCommonStart(int options, int *index) {
+bool RawQueue::ReadCommonStart(Options<RawQueue> options, int *index) {
while (data_start_ == data_end_ || ((index != NULL) && messages_ <= *index)) {
if (options & kNonBlock) {
if (kReadDebug) {
@@ -378,6 +378,7 @@
}
return false;
} else { // kBlock
+ assert(options & kBlock);
if (kReadDebug) {
printf("queue: going to wait for readable_ of %p\n", this);
}
@@ -407,10 +408,10 @@
return pos;
}
-const void *RawQueue::ReadMessage(int options) {
+const void *RawQueue::DoReadMessage(Options<RawQueue> options) {
// TODO(brians): Test this function.
if (kReadDebug) {
- printf("queue: %p->ReadMessage(%x)\n", this, options);
+ printf("queue: %p->ReadMessage(%x)\n", this, options.printable());
}
void *msg = NULL;
@@ -468,10 +469,11 @@
return msg;
}
-const void *RawQueue::ReadMessageIndex(int options, int *index) {
+const void *RawQueue::DoReadMessageIndex(Options<RawQueue> options,
+ int *index) {
if (kReadDebug) {
printf("queue: %p->ReadMessageIndex(%x, %p(*=%d))\n",
- this, options, index, *index);
+ this, options.printable(), index, *index);
}
void *msg = NULL;
@@ -491,7 +493,10 @@
printf("queue: %p reading from c1: %d\n", this, LastMessageIndex());
}
msg = data_[LastMessageIndex()];
- if (!(options & kPeek)) *index = messages_;
+
+ // We'd skip this if we had kPeek, but kPeek | kFromEnd isn't valid for
+ // reading with an index.
+ *index = messages_;
} else {
// Where we're going to start reading.
int my_start;
diff --git a/aos/linux_code/ipc_lib/queue.h b/aos/linux_code/ipc_lib/queue.h
index 5edce62..31e8075 100644
--- a/aos/linux_code/ipc_lib/queue.h
+++ b/aos/linux_code/ipc_lib/queue.h
@@ -6,6 +6,8 @@
#include "aos/linux_code/ipc_lib/shared_mem.h"
#include "aos/common/mutex.h"
#include "aos/common/condition.h"
+#include "aos/common/util/options.h"
+#include "aos/common/logging/logging.h"
// TODO(brians) add valgrind client requests to the queue and shared_mem_malloc
// code to make checking for leaks work better
@@ -56,38 +58,45 @@
int recycle_hash, int recycle_queue_length,
RawQueue **recycle);
- // Constants for passing to options arguments.
- // The non-conflicting ones can be combined with bitwise-or.
-
// Doesn't update the currently read index (the read messages in the queue or
// the index). This means the returned message (and any others skipped with
// kFromEnd) will be left in the queue.
// For reading only.
- static const int kPeek = 0x0001;
+ // Not valid for ReadMessageIndex combined with kFromEnd.
+ static constexpr Options<RawQueue>::Option kPeek{0x0001};
// Reads the last message in the queue instead of just the next one.
// NOTE: This removes all of the messages until the last one from the queue
// (which means that nobody else will read them).
// For reading only.
- static const int kFromEnd = 0x0002;
+ // Not valid for ReadMessageIndex combined with kPeek.
+ static constexpr Options<RawQueue>::Option kFromEnd{0x0002};
// Causes reads to return NULL and writes to fail instead of waiting.
// For reading and writing.
- static const int kNonBlock = 0x0004;
+ static constexpr Options<RawQueue>::Option kNonBlock{0x0004};
// Causes things to block.
- // IMPORTANT: Has a value of 0 so that it is the default. This has to stay
- // this way.
// For reading and writing.
- static const int kBlock = 0x0000;
+ static constexpr Options<RawQueue>::Option kBlock{0x0008};
// Causes writes to overwrite the oldest message in the queue instead of
// blocking.
// For writing only.
- static const int kOverride = 0x0008;
+ static constexpr Options<RawQueue>::Option kOverride{0x0010};
// Writes a message into the queue.
// This function takes ownership of msg.
// NOTE: msg must point to a valid message from this queue
// Returns true on success. A return value of false means msg has already been
// freed.
- bool WriteMessage(void *msg, int options);
+ bool WriteMessage(void *msg, Options<RawQueue> options) {
+ static constexpr Options<RawQueue> kWriteFailureOptions =
+ kNonBlock | kBlock | kOverride;
+ if (!options.NoOthersSet(kWriteFailureOptions)) {
+ LOG(FATAL, "illegal write options in %x\n", options.printable());
+ }
+ if (!options.ExactlyOneSet(kWriteFailureOptions)) {
+ LOG(FATAL, "invalid write options %x\n", options.printable());
+ }
+ return DoWriteMessage(msg, options);
+ }
// Reads a message out of the queue.
// The return value will have at least the length of this queue's worth of
@@ -96,13 +105,26 @@
// messsage. Do not cast the const away!
// IMPORTANT: The return value (if not NULL) must eventually be passed to
// FreeMessage.
- const void *ReadMessage(int options);
+ const void *ReadMessage(Options<RawQueue> options) {
+ CheckReadOptions(options);
+ return DoReadMessage(options);
+ }
// The same as ReadMessage, except it will never return the
// same message twice (when used with the same index argument). However,
// may not return some messages that pass through the queue.
// *index should start as 0. index does not have to be in shared memory, but
// it can be.
- const void *ReadMessageIndex(int options, int *index);
+ // Calling with both kPeek and kFromEnd in options isn't valid because that
+ // would mean ignoring index, which would make this function the same as
+ // ReadMessage (which should be used instead).
+ const void *ReadMessageIndex(Options<RawQueue> options, int *index) {
+ CheckReadOptions(options);
+ static constexpr Options<RawQueue> kFromEndAndPeek = kFromEnd | kPeek;
+ if (options.AllSet(kFromEndAndPeek)) {
+ LOG(FATAL, "ReadMessageIndex(kFromEnd | kPeek) is not allowed\n");
+ }
+ return DoReadMessageIndex(options, index);
+ }
// Retrieves ("allocates") a message that can then be written to the queue.
// NOTE: the return value will be completely uninitialized
@@ -125,6 +147,22 @@
private:
struct MessageHeader;
+ // The public wrappers around these are inlined and do argument checking.
+ bool DoWriteMessage(void *msg, Options<RawQueue> options);
+ const void *DoReadMessage(Options<RawQueue> options);
+ const void *DoReadMessageIndex(Options<RawQueue> options, int *index);
+ void CheckReadOptions(Options<RawQueue> options) {
+ static constexpr Options<RawQueue> kValidOptions =
+ kPeek | kFromEnd | kNonBlock | kBlock;
+ if (!options.NoOthersSet(kValidOptions)) {
+ LOG(FATAL, "illegal read options in %x\n", options.printable());
+ }
+ static constexpr Options<RawQueue> kBlockChoices = kNonBlock | kBlock;
+ if (!options.ExactlyOneSet(kBlockChoices)) {
+ LOG(FATAL, "invalid read options %x\n", options.printable());
+ }
+ }
+
// Adds 1 to the given index and handles wrapping correctly.
int index_add1(int index);
@@ -175,7 +213,7 @@
// Must be called with data_lock_ locked.
// *read_data will be initialized.
// Returns with a readable message in data_ or false.
- bool ReadCommonStart(int options, int *index);
+ bool ReadCommonStart(Options<RawQueue> options, int *index);
// Deals with setting/unsetting readable_ and writable_.
// Must be called after data_lock_ has been unlocked.
// read_data should be the same thing that was passed in to ReadCommonStart.
diff --git a/aos/linux_code/ipc_lib/raw_queue_test.cc b/aos/linux_code/ipc_lib/raw_queue_test.cc
index 65f2308..c85d36a 100644
--- a/aos/linux_code/ipc_lib/raw_queue_test.cc
+++ b/aos/linux_code/ipc_lib/raw_queue_test.cc
@@ -17,6 +17,8 @@
#include "aos/common/logging/logging.h"
#include "aos/common/die.h"
#include "aos/common/util/thread.h"
+#include "aos/common/util/options.h"
+#include "aos/common/util/death_test_log_implementation.h"
using ::testing::AssertionResult;
using ::testing::AssertionSuccess;
@@ -266,7 +268,7 @@
};
struct MessageArgs {
RawQueue *const queue;
- int flags;
+ Options<RawQueue> flags;
int16_t data; // -1 means NULL expected
};
static void WriteTestMessage(MessageArgs *args, char *failure) {
@@ -278,8 +280,8 @@
}
msg->data = args->data;
if (!args->queue->WriteMessage(msg, args->flags)) {
- snprintf(failure, kFailureSize, "write_msg_free(%p, %p, %d) failed",
- args->queue, msg, args->flags);
+ snprintf(failure, kFailureSize, "%p->WriteMessage(%p, %x) failed",
+ args->queue, msg, args->flags.printable());
}
}
static void ReadTestMessage(MessageArgs *args, char *failure) {
@@ -310,47 +312,50 @@
private:
GlobalCoreInstance my_core;
};
+
char *RawQueueTest::fatal_failure;
std::map<RawQueueTest::ChildID, RawQueueTest::ForkedProcess *>
RawQueueTest::children_;
constexpr time::Time RawQueueTest::kHangTime;
constexpr time::Time RawQueueTest::kForkSleep;
+typedef RawQueueTest RawQueueDeathTest;
+
TEST_F(RawQueueTest, Reading) {
RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
- MessageArgs args{queue, 0, -1};
+ MessageArgs args{queue, RawQueue::kBlock, -1};
args.flags = RawQueue::kNonBlock;
EXPECT_RETURNS(ReadTestMessage, &args);
args.flags = RawQueue::kNonBlock | RawQueue::kPeek;
EXPECT_RETURNS(ReadTestMessage, &args);
- args.flags = 0;
+ args.flags = RawQueue::kBlock;
EXPECT_HANGS(ReadTestMessage, &args);
- args.flags = RawQueue::kPeek;
+ args.flags = RawQueue::kPeek | RawQueue::kBlock;
EXPECT_HANGS(ReadTestMessage, &args);
args.data = 254;
args.flags = RawQueue::kBlock;
EXPECT_RETURNS(WriteTestMessage, &args);
- args.flags = RawQueue::kPeek;
+ args.flags = RawQueue::kPeek | RawQueue::kBlock;
EXPECT_RETURNS(ReadTestMessage, &args);
- args.flags = RawQueue::kPeek;
+ args.flags = RawQueue::kPeek | RawQueue::kBlock;
EXPECT_RETURNS(ReadTestMessage, &args);
args.flags = RawQueue::kPeek | RawQueue::kNonBlock;
EXPECT_RETURNS(ReadTestMessage, &args);
- args.flags = 0;
+ args.flags = RawQueue::kBlock;
EXPECT_RETURNS(ReadTestMessage, &args);
- args.flags = 0;
+ args.flags = RawQueue::kBlock;
args.data = -1;
EXPECT_HANGS(ReadTestMessage, &args);
args.flags = RawQueue::kNonBlock;
EXPECT_RETURNS(ReadTestMessage, &args);
- args.flags = 0;
+ args.flags = RawQueue::kBlock;
args.data = 971;
EXPECT_RETURNS_FAILS(ReadTestMessage, &args);
}
TEST_F(RawQueueTest, Writing) {
RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
- MessageArgs args{queue, 0, 973};
+ MessageArgs args{queue, RawQueue::kBlock, 973};
args.flags = RawQueue::kBlock;
EXPECT_RETURNS(WriteTestMessage, &args);
@@ -360,28 +365,28 @@
EXPECT_RETURNS_FAILS(WriteTestMessage, &args);
args.flags = RawQueue::kNonBlock;
EXPECT_RETURNS_FAILS(WriteTestMessage, &args);
- args.flags = RawQueue::kPeek;
+ args.flags = RawQueue::kPeek | RawQueue::kBlock;
EXPECT_RETURNS(ReadTestMessage, &args);
args.data = 971;
args.flags = RawQueue::kOverride;
EXPECT_RETURNS(WriteTestMessage, &args);
args.flags = RawQueue::kOverride;
EXPECT_RETURNS(WriteTestMessage, &args);
- args.flags = 0;
+ args.flags = RawQueue::kBlock;
EXPECT_RETURNS(ReadTestMessage, &args);
args.flags = RawQueue::kNonBlock;
EXPECT_RETURNS(WriteTestMessage, &args);
- args.flags = 0;
+ args.flags = RawQueue::kBlock;
EXPECT_RETURNS(ReadTestMessage, &args);
args.flags = RawQueue::kOverride;
EXPECT_RETURNS(WriteTestMessage, &args);
- args.flags = 0;
+ args.flags = RawQueue::kBlock;
EXPECT_RETURNS(ReadTestMessage, &args);
}
TEST_F(RawQueueTest, MultiRead) {
RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage), 1, 1);
- MessageArgs args{queue, 0, 1323};
+ MessageArgs args{queue, RawQueue::kBlock, 1323};
args.flags = RawQueue::kBlock;
EXPECT_RETURNS(WriteTestMessage, &args);
@@ -402,16 +407,17 @@
// message to use for it).
TestMessage *msg = static_cast<TestMessage *>(queue->GetMessage());
ASSERT_NE(nullptr, msg);
- ASSERT_TRUE(queue->WriteMessage(msg, 0));
- const void *read_msg = queue->ReadMessage(0);
+ ASSERT_TRUE(queue->WriteMessage(msg, RawQueue::kBlock));
+ const void *read_msg = queue->ReadMessage(RawQueue::kBlock);
EXPECT_NE(nullptr, read_msg);
msg = static_cast<TestMessage *>(queue->GetMessage());
queue->FreeMessage(read_msg);
ASSERT_NE(nullptr, msg);
- ASSERT_TRUE(queue->WriteMessage(msg, 0));
+ ASSERT_TRUE(queue->WriteMessage(msg, RawQueue::kBlock));
int index = 0;
- const void *second_read_msg = queue->ReadMessageIndex(0, &index);
+ const void *second_read_msg =
+ queue->ReadMessageIndex(RawQueue::kBlock, &index);
EXPECT_NE(nullptr, second_read_msg);
EXPECT_NE(read_msg, second_read_msg)
<< "We already took that message out of the queue.";
@@ -424,7 +430,8 @@
RawQueue *const queue = RawQueue::Fetch("Queue", sizeof(TestMessage),
1, 2, 2, 2, &recycle_queue);
ASSERT_NE(reinterpret_cast<RawQueue *>(23), recycle_queue);
- MessageArgs args{queue, 0, 973}, recycle{recycle_queue, 0, 973};
+ MessageArgs args{queue, RawQueue::kBlock, 973},
+ recycle{recycle_queue, RawQueue::kBlock, 973};
args.flags = RawQueue::kBlock;
EXPECT_RETURNS(WriteTestMessage, &args);
@@ -450,7 +457,7 @@
EXPECT_HANGS(ReadTestMessage, &recycle);
args.data = 254;
- args.flags = RawQueue::kPeek;
+ args.flags = RawQueue::kPeek | RawQueue::kBlock;
EXPECT_RETURNS(ReadTestMessage, &args);
recycle.flags = RawQueue::kBlock;
EXPECT_HANGS(ReadTestMessage, &recycle);
@@ -524,8 +531,8 @@
queue->FreeMessage(peek_message);
index = 0;
- peek_message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
- RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd, &index));
+ peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
+ RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
ASSERT_NE(nullptr, message);
@@ -561,8 +568,8 @@
queue->FreeMessage(peek_message);
index = 0;
- peek_message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
- RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd, &index));
+ peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
+ RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
ASSERT_NE(nullptr, message);
@@ -594,8 +601,8 @@
queue->FreeMessage(peek_message);
index = 0;
- peek_message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
- RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd, &index));
+ peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
+ RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
ASSERT_NE(nullptr, message);
@@ -639,8 +646,8 @@
queue->FreeMessage(peek_message);
index = 0;
- peek_message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
- RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd, &index));
+ peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
+ RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
ASSERT_NE(nullptr, message);
@@ -674,8 +681,8 @@
queue->FreeMessage(peek_message);
index = 0;
- peek_message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
- RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd, &index));
+ peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
+ RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
ASSERT_NE(nullptr, message);
@@ -731,8 +738,8 @@
queue->FreeMessage(peek_message);
index = 0;
- peek_message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
- RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd, &index));
+ peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
+ RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
ASSERT_NE(nullptr, message);
@@ -768,8 +775,8 @@
queue->FreeMessage(peek_message);
index = 0;
- peek_message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
- RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd, &index));
+ peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
+ RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
ASSERT_NE(nullptr, message);
@@ -817,8 +824,8 @@
queue->FreeMessage(peek_message);
index = 0;
- peek_message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
- RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd, &index));
+ peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
+ RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
ASSERT_NE(nullptr, message);
@@ -856,8 +863,8 @@
queue->FreeMessage(peek_message);
index = 0;
- peek_message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
- RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd, &index));
+ peek_message = static_cast<const TestMessage *>(queue->ReadMessage(
+ RawQueue::kNonBlock | RawQueue::kPeek | RawQueue::kFromEnd));
message = static_cast<const TestMessage *>(queue->ReadMessageIndex(
RawQueue::kNonBlock | RawQueue::kFromEnd, &index));
ASSERT_NE(nullptr, message);
@@ -933,8 +940,12 @@
PushMessage(queue, 971);
int free_before = queue->FreeMessages();
- const void *const message1 = queue->ReadMessage(RawQueue::kPeek);
- const void *const message2 = queue->ReadMessage(RawQueue::kPeek);
+ const void *const message1 =
+ queue->ReadMessage(RawQueue::kPeek | RawQueue::kNonBlock);
+ const void *const message2 =
+ queue->ReadMessage(RawQueue::kPeek | RawQueue::kNonBlock);
+ ASSERT_NE(nullptr, message1);
+ ASSERT_NE(nullptr, message2);
EXPECT_EQ(free_before, queue->FreeMessages());
util::FunctionThread t1([message1, queue](util::Thread *) {
queue->FreeMessage(message1);
@@ -949,5 +960,61 @@
EXPECT_EQ(free_before, queue->FreeMessages());
}
+TEST_F(RawQueueDeathTest, OptionsValidation) {
+ RawQueue *const queue = RawQueue::Fetch("Queue", 1, 1, 1);
+
+ EXPECT_DEATH(
+ {
+ logging::AddImplementation(new util::DeathTestLogImplementation());
+ queue->WriteMessage(nullptr, RawQueue::kPeek);
+ },
+ ".*illegal write option.*");
+ EXPECT_DEATH(
+ {
+ logging::AddImplementation(new util::DeathTestLogImplementation());
+ queue->WriteMessage(nullptr, RawQueue::kFromEnd);
+ },
+ ".*illegal write option.*");
+ EXPECT_DEATH(
+ {
+ logging::AddImplementation(new util::DeathTestLogImplementation());
+ queue->WriteMessage(nullptr, RawQueue::kPeek | RawQueue::kFromEnd);
+ },
+ ".*illegal write option.*");
+ EXPECT_DEATH(
+ {
+ logging::AddImplementation(new util::DeathTestLogImplementation());
+ queue->WriteMessage(nullptr, RawQueue::kNonBlock | RawQueue::kBlock);
+ },
+ ".*invalid write option.*");
+
+ EXPECT_DEATH(
+ {
+ logging::AddImplementation(new util::DeathTestLogImplementation());
+ queue->ReadMessageIndex(
+ RawQueue::kBlock | RawQueue::kFromEnd | RawQueue::kPeek, nullptr);
+ },
+ ".*ReadMessageIndex.*is not allowed.*");
+ EXPECT_DEATH(
+ {
+ logging::AddImplementation(new util::DeathTestLogImplementation());
+ queue->ReadMessageIndex(RawQueue::kOverride, nullptr);
+ },
+ ".*illegal read option.*");
+ EXPECT_DEATH(
+ {
+ logging::AddImplementation(new util::DeathTestLogImplementation());
+ queue->ReadMessageIndex(RawQueue::kOverride | RawQueue::kBlock,
+ nullptr);
+ },
+ ".*illegal read option.*");
+ EXPECT_DEATH(
+ {
+ logging::AddImplementation(new util::DeathTestLogImplementation());
+ queue->ReadMessage(RawQueue::kNonBlock | RawQueue::kBlock);
+ },
+ ".*invalid read option.*");
+}
+
} // namespace testing
} // namespace aos
diff --git a/aos/linux_code/logging/linux_logging.cc b/aos/linux_code/logging/linux_logging.cc
index cdb052a..2bd5bce 100644
--- a/aos/linux_code/logging/linux_logging.cc
+++ b/aos/linux_code/logging/linux_logging.cc
@@ -77,7 +77,7 @@
AddImplementation(new LinuxQueueLogImplementation());
}
-const LogMessage *ReadNext(int flags, int *index) {
+const LogMessage *ReadNext(Options<RawQueue> flags, int *index) {
return static_cast<const LogMessage *>(queue->ReadMessageIndex(flags, index));
}
@@ -85,7 +85,7 @@
return ReadNext(RawQueue::kBlock);
}
-const LogMessage *ReadNext(int flags) {
+const LogMessage *ReadNext(Options<RawQueue> flags) {
const LogMessage *r = NULL;
do {
r = static_cast<const LogMessage *>(queue->ReadMessage(flags));
diff --git a/aos/linux_code/logging/linux_logging.h b/aos/linux_code/logging/linux_logging.h
index 3dc8763..63eeaf1 100644
--- a/aos/linux_code/logging/linux_logging.h
+++ b/aos/linux_code/logging/linux_logging.h
@@ -2,8 +2,12 @@
#define AOS_LINUX_CODE_LOGGING_LOGGING_H_
#include "aos/common/logging/logging_impl.h"
+#include "aos/common/util/options.h"
namespace aos {
+
+class RawQueue;
+
namespace logging {
namespace linux_code {
@@ -16,8 +20,8 @@
// Fairly simple wrappers around the raw queue calls.
// This one never returns NULL if flags contains BLOCK.
-const LogMessage *ReadNext(int flags);
-const LogMessage *ReadNext(int flags, int *index);
+const LogMessage *ReadNext(Options<RawQueue> flags);
+const LogMessage *ReadNext(Options<RawQueue> flags, int *index);
const LogMessage *ReadNext();
LogMessage *Get();
void Free(const LogMessage *msg);
diff --git a/aos/linux_code/queue-tmpl.h b/aos/linux_code/queue-tmpl.h
index 522bf6b..719af5d 100644
--- a/aos/linux_code/queue-tmpl.h
+++ b/aos/linux_code/queue-tmpl.h
@@ -72,8 +72,10 @@
template <class T>
bool Queue<T>::FetchLatest() {
Init();
- const T *msg = static_cast<const T *>(queue_->ReadMessageIndex(
- RawQueue::kFromEnd | RawQueue::kNonBlock, &index_));
+ static constexpr Options<RawQueue> kOptions =
+ RawQueue::kFromEnd | RawQueue::kNonBlock;
+ const T *msg =
+ static_cast<const T *>(queue_->ReadMessageIndex(kOptions, &index_));
// Only update the internal pointer if we got a new message.
if (msg != NULL && msg != queue_msg_.get()) {
queue_msg_.reset(msg);