1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
// GDBus++ - glib2 GDBus C++ wrapper
//
// SPDX-License-Identifier: AGPL-3.0-only
//
// Copyright (C) OpenVPN Inc <sales@openvpn.net>
// Copyright (C) David Sommerseth <davids@openvpn.net>
//
/**
* @file tests/regression/glib2_utils.cpp
*
* @brief Tests bug fixes in glib2::Utils, to avoid regressions later on
*/
#include <cinttypes>
#include <iostream>
#include <functional>
#include <string>
#include <vector>
#include <glib.h>
#include "../../gdbuspp/glib2/utils.hpp"
bool expect_throw(std::function<void()> &&testfunc, const std::string &error_match)
{
try
{
testfunc();
return false;
}
catch (const glib2::Utils::Exception &ex)
{
std::string err(ex.what());
if (err.find(error_match) != std::string::npos)
{
return true;
}
throw;
}
}
/**
* glib2::Utils::checkParams() should not fail if the data type
* of the input variable is not a container type. The bug discovered
* would result in g_variant_n_children() to make this function misbehave
* and later on potentially crash the program.
*
* If the data type is not a container type, it cannot have any children.
*
* Returns true on errors, otherwise false on success.
*/
bool checkParams_no_fail_no_container()
{
std::vector<std::uint16_t> test_data_array = {{1, 2, 3, 4, 5}};
GVariant *data_array = glib2::Value::CreateVector(test_data_array);
std::cout << "data_array=" << g_variant_print(data_array, true)
<< std::endl;
glib2::Utils::checkParams(__func__, data_array, "aq");
glib2::Utils::checkParams(__func__, data_array, "aq", 5);
expect_throw([data_array]()
{
// Incorrect number of elements; expected to throw an exception
glib2::Utils::checkParams(__func__, data_array, "aq", 2);
},
"Incorrect parameter format: aq, expected aq (elements expected: 2, received: 5)");
GVariant *data_ints = g_variant_new("(qq)", 123, 456);
std::cout << "data_int=" << g_variant_print(data_ints, true) << std::endl;
glib2::Utils::checkParams(__func__, data_ints, "(qq)");
glib2::Utils::checkParams(__func__, data_ints, "(qq)", 2);
expect_throw([data_ints]()
{
// Incorrect number of elements; expected to throw an exception
glib2::Utils::checkParams(__func__, data_ints, "qq", 3);
},
"Incorrect parameter format: (qq), expected qq (elements expected: 3, received: 2)");
GVariantBuilder *data_dict_b = glib2::Builder::Create("a{ss}");
glib2::Builder::Add(data_dict_b, g_variant_new("{ss}", "Key", "Value"));
GVariant *data_dict = glib2::Builder::Finish(data_dict_b);
std::cout << "data_dict=" << g_variant_print(data_dict, true) << std::endl;
glib2::Utils::checkParams(__func__, data_dict, "a{ss}");
glib2::Utils::checkParams(__func__, data_dict, "a{ss}", 1);
expect_throw([data_dict]()
{
// Incorrect number of elements; expected to throw an exception
glib2::Utils::checkParams(__func__, data_dict, "a{ss}", 2);
},
"Incorrect parameter format: a{ss}, expected a{ss} (elements expected: 2, received: 1)");
std::string test_data_string{"Hello tester"};
GVariant *data_string = glib2::Value::Create(test_data_string);
std::cout << "data_string=" << g_variant_print(data_string, true) << std::endl;
glib2::Utils::checkParams(__func__, data_string, "s");
expect_throw([data_string]()
{
// Incorrect number of elements; expected to throw an exception
glib2::Utils::checkParams(__func__, data_string, "s", 1);
},
"Parameter type is not a container, it has no children");
GVariant *data_bool = glib2::Value::Create(true);
std::cout << "data_bool=" << g_variant_print(data_bool, true) << std::endl;
glib2::Utils::checkParams(__func__, data_bool, "b");
expect_throw([data_bool]()
{
// Incorrect number of elements; expected to throw an exception
glib2::Utils::checkParams(__func__, data_bool, "b", 1);
},
"Parameter type is not a container, it has no children");
return false;
}
int main()
{
try
{
return checkParams_no_fail_no_container() ? 1 : 0;
}
catch (const DBus::Exception &excp)
{
std::cout << std::endl
<< "EXCEPTION: " << std::endl
<< " " << excp.what() << std::endl;
return 2;
}
}
|