2017-12-19 00:04:06 +00:00
|
|
|
/**
|
2016-02-11 19:48:58 +00:00
|
|
|
* Copyright (c) 2014-present, Facebook, Inc.
|
2014-12-18 18:50:47 +00:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
2019-02-19 18:52:19 +00:00
|
|
|
* This source code is licensed in accordance with the terms specified in
|
|
|
|
* the LICENSE file found in the root directory of this source tree.
|
2014-12-18 18:50:47 +00:00
|
|
|
*/
|
2014-09-12 04:44:10 +00:00
|
|
|
|
2018-07-12 17:03:57 +00:00
|
|
|
#include <string>
|
2018-09-21 18:54:31 +00:00
|
|
|
#include <unordered_map>
|
2018-07-12 17:03:57 +00:00
|
|
|
|
2014-09-12 04:44:10 +00:00
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
2018-09-21 18:54:31 +00:00
|
|
|
#include <osquery/utils/conversions/tryto.h>
|
2016-02-12 17:39:20 +00:00
|
|
|
|
2014-09-12 04:44:10 +00:00
|
|
|
namespace osquery {
|
|
|
|
|
|
|
|
class ConversionsTests : public testing::Test {};
|
|
|
|
|
2018-07-03 16:12:17 +00:00
|
|
|
|
|
|
|
TEST_F(ConversionsTests, tryTo_same_type) {
|
|
|
|
class First {};
|
|
|
|
// rvalue
|
|
|
|
auto ret0 = tryTo<First>(First{});
|
|
|
|
ASSERT_FALSE(ret0.isError());
|
|
|
|
|
|
|
|
auto test_lvalue = First{};
|
|
|
|
auto ret1 = tryTo<First>(test_lvalue);
|
|
|
|
ASSERT_FALSE(ret1.isError());
|
|
|
|
|
|
|
|
const auto const_test_lvalue = First{};
|
|
|
|
auto ret2 = tryTo<First>(const_test_lvalue);
|
|
|
|
ASSERT_FALSE(ret2.isError());
|
2014-09-12 04:44:10 +00:00
|
|
|
}
|
2018-07-12 14:07:36 +00:00
|
|
|
|
2018-07-12 17:03:57 +00:00
|
|
|
template <typename ValueType, typename StrType>
|
|
|
|
void testTryToForRvalue(ValueType value, const StrType& str) {
|
|
|
|
auto ret = tryTo<ValueType>(StrType{str});
|
|
|
|
ASSERT_FALSE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.get(), value);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename ValueType, typename StrType>
|
|
|
|
void testTryToForLValue(ValueType value, StrType str) {
|
|
|
|
auto ret = tryTo<ValueType>(str);
|
|
|
|
ASSERT_FALSE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.get(), value);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename ValueType, typename StrType>
|
|
|
|
void testTryToForConstLValue(ValueType value, const StrType str) {
|
|
|
|
auto ret = tryTo<ValueType>(str);
|
|
|
|
ASSERT_FALSE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.get(), value);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename ValueType, typename StrType>
|
|
|
|
void testTryToForString(ValueType value, const StrType str) {
|
|
|
|
testTryToForRvalue(value, str);
|
|
|
|
testTryToForLValue(value, str);
|
|
|
|
testTryToForConstLValue(value, str);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename ValueType>
|
|
|
|
void testTryToForValue(ValueType value) {
|
|
|
|
testTryToForString(value, std::to_string(value));
|
|
|
|
testTryToForString(value, std::to_wstring(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename IntType>
|
|
|
|
void testTryToForUnsignedInt() {
|
|
|
|
testTryToForValue<IntType>(119);
|
|
|
|
testTryToForValue<IntType>(std::numeric_limits<IntType>::max());
|
|
|
|
testTryToForValue<IntType>(std::numeric_limits<IntType>::min());
|
|
|
|
testTryToForValue<IntType>(std::numeric_limits<IntType>::lowest());
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"0xfb"}, 16);
|
|
|
|
ASSERT_FALSE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.get(), 251);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"FB"}, 16);
|
|
|
|
ASSERT_FALSE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.get(), 251);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"0xFb"}, 16);
|
|
|
|
ASSERT_FALSE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.get(), 251);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"E1bC2"}, 16);
|
|
|
|
ASSERT_FALSE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.get(), 924610);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"10101"}, 2);
|
|
|
|
ASSERT_FALSE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.get(), 21);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"035"}, 8);
|
|
|
|
ASSERT_FALSE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.get(), 29);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"47"}, 8);
|
|
|
|
ASSERT_FALSE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.get(), 39);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"+15"});
|
|
|
|
ASSERT_FALSE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.get(), 15);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"+1A"}, 16);
|
|
|
|
ASSERT_FALSE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.get(), 26);
|
|
|
|
}
|
|
|
|
// failure tests
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{""});
|
|
|
|
ASSERT_TRUE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"x"});
|
|
|
|
ASSERT_TRUE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"xor"});
|
|
|
|
ASSERT_TRUE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{".1"});
|
|
|
|
ASSERT_TRUE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"(10)"});
|
|
|
|
ASSERT_TRUE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"O"});
|
|
|
|
ASSERT_TRUE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"lO0"});
|
|
|
|
ASSERT_TRUE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"IV"});
|
|
|
|
ASSERT_TRUE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"s1"});
|
|
|
|
ASSERT_TRUE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"u1"});
|
|
|
|
ASSERT_TRUE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"#12"});
|
|
|
|
ASSERT_TRUE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"%99"});
|
|
|
|
ASSERT_TRUE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"*483"});
|
|
|
|
ASSERT_TRUE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"/488"});
|
|
|
|
ASSERT_TRUE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"\\493"});
|
|
|
|
ASSERT_TRUE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"+ 19"});
|
|
|
|
ASSERT_TRUE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string(2, '\0'));
|
|
|
|
ASSERT_TRUE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename IntType>
|
|
|
|
void testTryToForSignedInt() {
|
|
|
|
testTryToForUnsignedInt<IntType>();
|
|
|
|
testTryToForValue<int>(-126);
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"-7A"}, 16);
|
|
|
|
ASSERT_FALSE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.get(), -122);
|
|
|
|
}
|
|
|
|
// failure tests
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"--14779"});
|
|
|
|
ASSERT_TRUE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"+-1813"});
|
|
|
|
ASSERT_TRUE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto ret = tryTo<IntType>(std::string{"- 3"});
|
|
|
|
ASSERT_TRUE(ret.isError());
|
|
|
|
ASSERT_EQ(ret.getErrorCode(), ConversionError::InvalidArgument);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ConversionsTests, try_i_to_string_and_back) {
|
|
|
|
testTryToForSignedInt<int>();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ConversionsTests, try_l_to_string_and_back) {
|
|
|
|
testTryToForSignedInt<long>();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ConversionsTests, try_ll_to_string_and_back) {
|
|
|
|
testTryToForSignedInt<long long>();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ConversionsTests, try_i32_to_string_and_back) {
|
|
|
|
testTryToForSignedInt<std::int32_t>();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ConversionsTests, try_i64_to_string_and_back) {
|
|
|
|
testTryToForSignedInt<std::int64_t>();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ConversionsTests, try_imax_to_string_and_back) {
|
|
|
|
testTryToForSignedInt<std::intmax_t>();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ConversionsTests, try_u_to_string_and_back) {
|
|
|
|
testTryToForUnsignedInt<unsigned>();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ConversionsTests, try_ul_to_string_and_back) {
|
|
|
|
testTryToForUnsignedInt<unsigned long>();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ConversionsTests, try_ull_to_string_and_back) {
|
|
|
|
testTryToForUnsignedInt<unsigned long long>();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ConversionsTests, try_u32_to_string_and_back) {
|
|
|
|
testTryToForUnsignedInt<std::uint32_t>();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ConversionsTests, try_u64_to_string_and_back) {
|
|
|
|
testTryToForUnsignedInt<std::uint64_t>();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ConversionsTests, try_umax_to_string_and_back) {
|
|
|
|
testTryToForUnsignedInt<std::uintmax_t>();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ConversionsTests, try_size_t_to_string_and_back) {
|
|
|
|
testTryToForUnsignedInt<std::size_t>();
|
|
|
|
}
|
|
|
|
|
2018-07-12 14:07:36 +00:00
|
|
|
TEST_F(ConversionsTests, tryTo_string_to_boolean_valid_args) {
|
|
|
|
const auto test_table = std::unordered_map<std::string, bool>{
|
|
|
|
{"1", true}, {"0", false}, {"y", true},
|
|
|
|
{"n", false}, {"yes", true}, {"yEs", true},
|
|
|
|
{"Yes", true}, {"no", false}, {"No", false},
|
|
|
|
{"t", true}, {"T", true}, {"f", false},
|
|
|
|
{"F", false}, {"true", true}, {"True", true},
|
|
|
|
{"tRUE", true}, {"false", false}, {"fALse", false},
|
|
|
|
{"ok", true}, {"OK", true}, {"Ok", true},
|
|
|
|
{"enable", true}, {"Enable", true}, {"ENABLE", true},
|
|
|
|
{"disable", false}, {"Disable", false}, {"DISABLE", false},
|
|
|
|
};
|
|
|
|
for (const auto& argAndAnswer : test_table) {
|
|
|
|
auto exp = tryTo<bool>(argAndAnswer.first);
|
|
|
|
ASSERT_FALSE(exp.isError());
|
|
|
|
EXPECT_EQ(argAndAnswer.second, exp.get());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ConversionsTests, tryTo_string_to_boolean_invalid_args) {
|
|
|
|
const auto test_table = std::vector<std::string>{
|
|
|
|
"", "\0", "\n", "\x06", "\x15", "\x27", "ADS",
|
|
|
|
"7251", "20.09", "M0V+K7V", "+", "-", ".", "@",
|
|
|
|
"1.0", "11", "00", " 0", "1 ", "2", "10",
|
|
|
|
"100%", "_0", "1_", "1.", "2.", "E", "a",
|
|
|
|
"b", "d", "e", "o", "p", "uh", "nix",
|
|
|
|
"nixie", "nixy", "nixey", "nay", "nah", "no way", "veto",
|
|
|
|
"yea", "yeah", "yep", "okey", "aye", "roger", "uh-huh",
|
|
|
|
"righto", "yup", "yuppers", "ja", "surely", "amen", "totally",
|
|
|
|
"sure", "yessir", "true.", "tru", "tr", "tr.", "ff",
|
|
|
|
"yy", "nn", "nope", "null", "nil", "dis", "able",
|
|
|
|
"pos", "neg", "ack", "ACK", "NAK", "enabled", "disabled",
|
|
|
|
"valid", "invalid", "void", "allow", "permit", "positive", "negative",
|
|
|
|
};
|
|
|
|
for (const auto& wrong : test_table) {
|
|
|
|
auto exp = tryTo<bool>(wrong);
|
|
|
|
ASSERT_TRUE(exp.isError());
|
|
|
|
EXPECT_EQ(ConversionError::InvalidArgument, exp.getErrorCode());
|
|
|
|
}
|
|
|
|
}
|
2018-08-07 17:33:50 +00:00
|
|
|
|
2018-07-03 16:12:17 +00:00
|
|
|
} // namespace osquery
|