unit-test: add basic header validation tests
Ensure header size is correct and write tests to validate it.
The goal of this patch series is to match with the validation done
within openslp (slp_v2message.c, SLPv2MessageParseHeader)
Change-Id: I42aace162051a9e4795ebbaf36f193efe4738dcd
Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
diff --git a/meson.build b/meson.build
index 679ecad..4c28048 100644
--- a/meson.build
+++ b/meson.build
@@ -23,3 +23,19 @@
install: true,
install_dir: get_option('sbindir'),
)
+
+build_tests = get_option('tests')
+gtest = dependency('gtest', main: true, disabler: true, required: build_tests)
+gmock = dependency('gmock', disabler: true, required: build_tests)
+ test(
+ 'test_slp_parser',
+ executable('test_slp_parser',
+ './test/slp_parser_test.cpp',
+ 'slp_parser.cpp',
+ dependencies: [
+ gtest,
+ ],
+ implicit_include_directories: true,
+ include_directories: '../'
+ )
+ )
diff --git a/meson.options b/meson.options
new file mode 100644
index 0000000..0fc2767
--- /dev/null
+++ b/meson.options
@@ -0,0 +1 @@
+option('tests', type: 'feature', description: 'Build tests')
diff --git a/slp_parser.cpp b/slp_parser.cpp
index 4c008ad..293cba7 100644
--- a/slp_parser.cpp
+++ b/slp_parser.cpp
@@ -33,43 +33,55 @@
Message req{};
int rc = slp::SUCCESS;
- std::copy_n(buff.data(), slp::header::SIZE_VERSION, &req.header.version);
-
- std::copy_n(buff.data() + slp::header::OFFSET_FUNCTION,
- slp::header::SIZE_VERSION, &req.header.functionID);
-
- std::copy_n(buff.data() + slp::header::OFFSET_LENGTH,
- slp::header::SIZE_LENGTH, req.header.length.data());
-
- std::copy_n(buff.data() + slp::header::OFFSET_FLAGS,
- slp::header::SIZE_FLAGS, (uint8_t*)&req.header.flags);
-
- req.header.flags = endian::from_network(req.header.flags);
- std::copy_n(buff.data() + slp::header::OFFSET_EXT, slp::header::SIZE_EXT,
- req.header.extOffset.data());
-
- std::copy_n(buff.data() + slp::header::OFFSET_XID, slp::header::SIZE_XID,
- (uint8_t*)&req.header.xid);
-
- req.header.xid = endian::from_network(req.header.xid);
-
- uint16_t langtagLen;
-
- std::copy_n(buff.data() + slp::header::OFFSET_LANG_LEN,
- slp::header::SIZE_LANG, (uint8_t*)&langtagLen);
-
- langtagLen = endian::from_network(langtagLen);
-
- req.header.langtag.insert(
- 0, (const char*)buff.data() + slp::header::OFFSET_LANG, langtagLen);
-
- /* check for the validity of the function */
- if (req.header.functionID <
- static_cast<uint8_t>(slp::FunctionType::SRVRQST) ||
- req.header.functionID > static_cast<uint8_t>(slp::FunctionType::SAADV))
+ if (buff.size() < slp::header::MIN_LEN)
{
+ std::cerr << "Invalid msg size: " << buff.size() << std::endl;
rc = static_cast<int>(slp::Error::PARSE_ERROR);
}
+ else
+ {
+ std::copy_n(buff.data(), slp::header::SIZE_VERSION,
+ &req.header.version);
+
+ std::copy_n(buff.data() + slp::header::OFFSET_FUNCTION,
+ slp::header::SIZE_VERSION, &req.header.functionID);
+
+ std::copy_n(buff.data() + slp::header::OFFSET_LENGTH,
+ slp::header::SIZE_LENGTH, req.header.length.data());
+
+ std::copy_n(buff.data() + slp::header::OFFSET_FLAGS,
+ slp::header::SIZE_FLAGS, (uint8_t*)&req.header.flags);
+
+ req.header.flags = endian::from_network(req.header.flags);
+ std::copy_n(buff.data() + slp::header::OFFSET_EXT,
+ slp::header::SIZE_EXT, req.header.extOffset.data());
+
+ std::copy_n(buff.data() + slp::header::OFFSET_XID,
+ slp::header::SIZE_XID, (uint8_t*)&req.header.xid);
+
+ req.header.xid = endian::from_network(req.header.xid);
+
+ uint16_t langtagLen;
+
+ std::copy_n(buff.data() + slp::header::OFFSET_LANG_LEN,
+ slp::header::SIZE_LANG, (uint8_t*)&langtagLen);
+
+ langtagLen = endian::from_network(langtagLen);
+
+ req.header.langtag.insert(
+ 0, (const char*)buff.data() + slp::header::OFFSET_LANG, langtagLen);
+
+ /* check for the validity of the function */
+ if (req.header.functionID <
+ static_cast<uint8_t>(slp::FunctionType::SRVRQST) ||
+ req.header.functionID >
+ static_cast<uint8_t>(slp::FunctionType::SAADV))
+ {
+ std::cerr << "Invalid function ID: " << req.header.functionID
+ << std::endl;
+ rc = static_cast<int>(slp::Error::PARSE_ERROR);
+ }
+ }
return std::make_tuple(rc, std::move(req));
}
diff --git a/test/slp_parser_test.cpp b/test/slp_parser_test.cpp
new file mode 100644
index 0000000..3615c93
--- /dev/null
+++ b/test/slp_parser_test.cpp
@@ -0,0 +1,42 @@
+#include "slp.hpp"
+#include "slp_meta.hpp"
+
+#include <gtest/gtest.h>
+
+/* 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Version | Function-ID | Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Length, contd.|O|F|R| reserved |Next Ext Offset|
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Next Extension Offset, contd.| XID |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Language Tag Length | Language Tag \
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
+
+TEST(parseHeaderTest, BasicGoodPath)
+{
+ // Basic buffer with valid Function-ID
+ slp::buffer testData{0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+ slp::Message req;
+ int rc = slp::SUCCESS;
+ std::tie(rc, req) = slp::parser::internal::parseHeader(testData);
+
+ EXPECT_EQ(rc, 0);
+}
+
+TEST(parseHeaderTest, InvalidBufferSize)
+{
+ // 1 byte too small
+ slp::buffer testData{0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+ slp::Message req;
+ int rc = slp::SUCCESS;
+ std::tie(rc, req) = slp::parser::internal::parseHeader(testData);
+
+ EXPECT_NE(rc, 0);
+}