2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-31 22:15:23 +00:00

[master] Merge branch 'trac3508' (version reporting)

Conflicts:
	ChangeLog
This commit is contained in:
Tomek Mrugalski
2014-08-11 23:00:55 +02:00
21 changed files with 252 additions and 30 deletions

View File

@@ -1,3 +1,7 @@
818. [func] tomek
DHCPv4,DHCPv6 and DDNS components now report their versions.
(Trac #3508, git 3f46c74ffa0ea1197e1fa62cb2f6580931be35f3)
817. [bug] marcin 817. [bug] marcin
DHCPv4 and DHCPv6 servers will log an error during an attempt to DHCPv4 and DHCPv6 servers will log an error during an attempt to
open socket on the interface which is down or not configured. open socket on the interface which is down or not configured.

View File

@@ -29,6 +29,19 @@ AC_CONFIG_MACRO_DIR([m4macros])
# Checks for programs. # Checks for programs.
AC_PROG_CXX AC_PROG_CXX
# Check for exact Kea version.
AC_MSG_CHECKING(whether this is a tarball or git source)
if test -d "${srcdir}/.git"; then
KEA_SRCID="git `(cd "${top_srcdir}";git rev-parse HEAD)`"
AC_MSG_RESULT("git")
else
KEA_SRCID="tarball"
AC_MSG_RESULT("tarball")
fi
# Export EXTENDED_VERSION to config.h
# This will be either "tarball" or "git abcd".
AC_DEFINE_UNQUOTED([EXTENDED_VERSION], ["${KEA_SRCID}"], [Extended Kea version])
# Enable low-performing debugging facilities? This option optionally # Enable low-performing debugging facilities? This option optionally
# enables some debugging aids that perform slowly and hence aren't built # enables some debugging aids that perform slowly and hence aren't built
# by default. # by default.
@@ -1481,6 +1494,11 @@ AC_OUTPUT
dnl Print the results dnl Print the results
dnl dnl
EXTENDED_VERSION=${PACKAGE_VERSION}
if test "$KEA_SRCID" != ""; then
EXTENDED_VERSION="${EXTENDED_VERSION} ($KEA_SRCID)"
fi
cat > config.report << END cat > config.report << END
Kea source configure results: Kea source configure results:
@@ -1489,6 +1507,7 @@ cat > config.report << END
Package: Package:
Name: ${PACKAGE_NAME} Name: ${PACKAGE_NAME}
Version: ${PACKAGE_VERSION} Version: ${PACKAGE_VERSION}
Extended version:${EXTENDED_VERSION}
OS Family: ${OS_TYPE} OS Family: ${OS_TYPE}
Using GNU sed: ${GNU_SED} Using GNU sed: ${GNU_SED}

View File

@@ -31,7 +31,7 @@
# least subnet and pool entries. # least subnet and pool entries.
"subnet6": [ "subnet6": [
{ {
"pool": [ "2001:db8:1::/80" ], "pools": [ { "pool": "2001:db8:1::/80" } ],
"subnet": "2001:db8:1::/64", "subnet": "2001:db8:1::/64",
"interface": "eth0" "interface": "eth0"
} }

View File

@@ -58,9 +58,41 @@
Kea, is a separate binary that can be run on its own or through Kea, is a separate binary that can be run on its own or through
<command>keactl</command> (see <xref linkend="keactrl"/>). In <command>keactl</command> (see <xref linkend="keactrl"/>). In
normal operation, controlling <command>kea-dhcp-ddns</command> normal operation, controlling <command>kea-dhcp-ddns</command>
with <command>keactl</command> is recommended. with <command>keactl</command> is recommended. However, it is also
possible to run the DHCP-DDNS server directly. It accepts the
following command-line switches:
</para> </para>
<itemizedlist>
<listitem>
<simpara>
<command>-c <replaceable>file</replaceable></command> -
specifies the configuration file. This is the only mandatory
switch.</simpara>
</listitem>
<listitem>
<simpara>
<command>-d</command> - specifies whether the server
logging should be switched to debug/verbose mode. In verbose mode,
the logging severity and debuglevel specified in a configuration
file are ignored and "debug" severity and the maximum debuglevel
(99) are assumed. The flag is convenient, for temporarily
switching the server into maximum verbosity, e.g. when
debugging.</simpara>
</listitem>
<listitem>
<simpara>
<command>-v</command> - prints out Kea version and exits.
</simpara>
</listitem>
<listitem>
<simpara>
<command>-V</command> - prints out Kea extended version with
additional parameters and exits.
</simpara>
</listitem>
</itemizedlist>
<para> <para>
Upon start up the module will load its configuration and begin listening Upon start up the module will load its configuration and begin listening
for NCRs based on that configuration. for NCRs based on that configuration.

View File

@@ -28,8 +28,8 @@
</listitem> </listitem>
<listitem> <listitem>
<simpara> <simpara>
<command>-v</command> - specifies whether the server <command>-d</command> - specifies whether the server
logging should be switched to verbose mode. In verbose mode, logging should be switched to debug/verbose mode. In verbose mode,
the logging severity and debuglevel specified in a configuration the logging severity and debuglevel specified in a configuration
file are ignored and "debug" severity and the maximum debuglevel file are ignored and "debug" severity and the maximum debuglevel
(99) are assumed. The flag is convenient, for temporarily (99) are assumed. The flag is convenient, for temporarily
@@ -44,6 +44,17 @@
ports other than default DHCPv4 ports will not be able to ports other than default DHCPv4 ports will not be able to
handle regular DHCPv4 queries.</simpara> handle regular DHCPv4 queries.</simpara>
</listitem> </listitem>
<listitem>
<simpara>
<command>-v</command> - prints out Kea version and exits.
</simpara>
</listitem>
<listitem>
<simpara>
<command>-V</command> - prints out Kea extended version with
additional parameters and exits.
</simpara>
</listitem>
</itemizedlist> </itemizedlist>
<para> <para>

View File

@@ -42,6 +42,17 @@
ports other than default DHCPv6 ports will not be able to ports other than default DHCPv6 ports will not be able to
handle regular DHCPv6 queries.</simpara> handle regular DHCPv6 queries.</simpara>
</listitem> </listitem>
<listitem>
<simpara>
<command>-v</command> - prints out Kea version and exits.
</simpara>
</listitem>
<listitem>
<simpara>
<command>-V</command> - prints out Kea extended version with
additional parameters and exits.
</simpara>
</listitem>
</itemizedlist> </itemizedlist>
<para> <para>

View File

@@ -457,9 +457,9 @@ error after receiving a signal. This is a programmatic error and should be
reported. While The application will likely continue to operating, it may be reported. While The application will likely continue to operating, it may be
unable to respond correctly to signals. unable to respond correctly to signals.
% DHCP_DDNS_STARTING DHCP-DDNS starting, pid: %1 % DHCP_DDNS_STARTING DHCP-DDNS starting, pid: %1, version: %2
This is an informational message issued when controller for the This is an informational message issued when controller for the
service first starts. service first starts. Version is also reported.
% DHCP_DDNS_STARTING_TRANSACTION Transaction Key: %1 % DHCP_DDNS_STARTING_TRANSACTION Transaction Key: %1
This is a debug message issued when DHCP-DDNS has begun a transaction for This is a debug message issued when DHCP-DDNS has begun a transaction for

View File

@@ -12,7 +12,7 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE. // PERFORMANCE OF THIS SOFTWARE.
#include <config.h>
#include <d2/d2_log.h> #include <d2/d2_log.h>
#include <config/ccsession.h> #include <config/ccsession.h>
#include <d2/d_controller.h> #include <d2/d_controller.h>
@@ -21,6 +21,7 @@
#include <dhcpsrv/configuration.h> #include <dhcpsrv/configuration.h>
#include <sstream> #include <sstream>
#include <unistd.h>
namespace isc { namespace isc {
namespace d2 { namespace d2 {
@@ -68,7 +69,7 @@ DControllerBase::launch(int argc, char* argv[], const bool test_mode) {
// Log the starting of the service. Although this is the controller // Log the starting of the service. Although this is the controller
// module, use a "DHCP_DDNS_" prefix to the module (to conform to the // module, use a "DHCP_DDNS_" prefix to the module (to conform to the
// principle of least astonishment). // principle of least astonishment).
LOG_INFO(dctl_logger, DHCP_DDNS_STARTING).arg(getpid()); LOG_INFO(dctl_logger, DHCP_DDNS_STARTING).arg(getpid()).arg(VERSION);
try { try {
// Step 2 is to create and initialize the application process object. // Step 2 is to create and initialize the application process object.
initProcess(); initProcess();
@@ -132,14 +133,24 @@ DControllerBase::parseArgs(int argc, char* argv[])
int ch; int ch;
opterr = 0; opterr = 0;
optind = 1; optind = 1;
std::string opts("vc:" + getCustomOpts()); std::string opts("dvVc:" + getCustomOpts());
while ((ch = getopt(argc, argv, opts.c_str())) != -1) { while ((ch = getopt(argc, argv, opts.c_str())) != -1) {
switch (ch) { switch (ch) {
case 'v': case 'd':
// Enables verbose logging. // Enables verbose logging.
verbose_ = true; verbose_ = true;
break; break;
case 'v':
// Print just Kea version and exit
std::cout << getVersion(false) << std::endl;
exit(EXIT_SUCCESS);
case 'V':
// Print extended Kea version and exit
std::cout << getVersion(true) << std::endl;
exit(EXIT_SUCCESS);
case 'c': case 'c':
// config file name // config file name
if (optarg == NULL) { if (optarg == NULL) {
@@ -399,7 +410,10 @@ DControllerBase::usage(const std::string & text)
std::cerr << "Usage: " << bin_name_ << std::endl std::cerr << "Usage: " << bin_name_ << std::endl
<< " -c <config file name> : mandatory," << " -c <config file name> : mandatory,"
<< " specifies name of configuration file " << std::endl << " specifies name of configuration file " << std::endl
<< " -v: optional, verbose output " << std::endl; << " -d: optional, verbose output " << std::endl
<< " -v: print version number and exit" << std::endl
<< " -V: print extended version information and exit"
<< std::endl;
// add any derivation specific usage // add any derivation specific usage
std::cerr << getUsageText() << std::endl; std::cerr << getUsageText() << std::endl;
@@ -422,3 +436,19 @@ dhcp::Daemon::loggerInit(const char* log_name, bool verbose) {
} }
}; // namespace isc }; // namespace isc
std::string
isc::dhcp::Daemon::getVersion(bool extended) {
std::stringstream tmp;
tmp << VERSION;
if (extended) {
tmp << std::endl << EXTENDED_VERSION;
// @todo print more details (is it Botan or OpenSSL build,
// with or without MySQL/Postgres? What compilation options were
// used? etc)
}
return (tmp.str());
}

View File

@@ -16,6 +16,8 @@
CFG_FILE=@abs_top_builddir@/src/bin/d2/tests/test_config.json CFG_FILE=@abs_top_builddir@/src/bin/d2/tests/test_config.json
# Path to the D2 log file. # Path to the D2 log file.
LOG_FILE=@abs_top_builddir@/src/bin/d2/tests/test.log LOG_FILE=@abs_top_builddir@/src/bin/d2/tests/test.log
# Expected version
EXPECTED_VERSION="@PACKAGE_VERSION@"
# D2 configuration to be stored in the configuration file. # D2 configuration to be stored in the configuration file.
CONFIG="{ CONFIG="{
\"DhcpDdns\": \"DhcpDdns\":
@@ -236,3 +238,4 @@ shutdown_test() {
dynamic_reconfiguration_test dynamic_reconfiguration_test
shutdown_test "dhcp-ddns.sigterm_test" 15 shutdown_test "dhcp-ddns.sigterm_test" 15
shutdown_test "dhcp-ddns.sigint_test" 2 shutdown_test "dhcp-ddns.sigint_test" 2
version_test "dhcp-ddns.version"

View File

@@ -351,9 +351,10 @@ core component within the DHCPv4 server (the Dhcpv4 server object)
has failed. As a result, the server will exit. The reason for the has failed. As a result, the server will exit. The reason for the
failure is given within the message. failure is given within the message.
% DHCP4_STARTING server starting % DHCP4_STARTING Kea DHCPv4 server version %1 starting
This informational message indicates that the DHCPv4 server has This informational message indicates that the DHCPv4 server has
processed any command-line switches and is starting. processed any command-line switches and is starting. The version
is also printed.
% DHCP4_START_INFO pid: %1, port: %2, verbose: %3 % DHCP4_START_INFO pid: %1, port: %2, verbose: %3
This is a debug message issued during the DHCPv4 server startup. This is a debug message issued during the DHCPv4 server startup.

View File

@@ -2036,5 +2036,21 @@ Dhcpv4Srv::d2ClientErrorHandler(const
CfgMgr::instance().getD2ClientMgr().suspendUpdates(); CfgMgr::instance().getD2ClientMgr().suspendUpdates();
} }
std::string
Daemon::getVersion(bool extended) {
std::stringstream tmp;
tmp << VERSION;
if (extended) {
tmp << endl << EXTENDED_VERSION;
// @todo print more details (is it Botan or OpenSSL build,
// with or without MySQL/Postgres? What compilation options were
// used? etc)
}
return (tmp.str());
}
} // namespace dhcp } // namespace dhcp
} // namespace isc } // namespace isc

View File

@@ -41,13 +41,21 @@ const char* const DHCP4_NAME = "kea-dhcp4";
const char* const DHCP4_LOGGER_NAME = "kea-dhcp4"; const char* const DHCP4_LOGGER_NAME = "kea-dhcp4";
/// @brief Prints Kea Usage and exits
///
/// Note: This function never returns. It terminates the process.
void void
usage() { usage() {
cerr << "Usage: " << DHCP4_NAME << " [-v] [-p number] [-c file]" << endl; cerr << "Kea DHCPv4 server, version " << VERSION << endl;
cerr << " -v: verbose output" << endl; cerr << endl;
cerr << "Usage: " << DHCP4_NAME
<< " [-v] [-V] [-d] [-p number] [-c file]" << endl;
cerr << " -c file: specify configuration file" << endl;
cerr << " -d: debug mode with extra verbosity (former -v)" << endl;
cerr << " -p number: specify non-standard port number 1-65535 " cerr << " -p number: specify non-standard port number 1-65535 "
<< "(useful for testing only)" << endl; << "(useful for testing only)" << endl;
cerr << " -c file: specify configuration file" << endl; cerr << " -v: print version number and exit" << endl;
cerr << " -V: print extended version and exit" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} // end of anonymous namespace } // end of anonymous namespace
@@ -62,12 +70,20 @@ main(int argc, char* argv[]) {
// The standard config file // The standard config file
std::string config_file(""); std::string config_file("");
while ((ch = getopt(argc, argv, "vp:c:")) != -1) { while ((ch = getopt(argc, argv, "dvVp:c:")) != -1) {
switch (ch) { switch (ch) {
case 'v': case 'd':
verbose_mode = true; verbose_mode = true;
break; break;
case 'v':
cout << Daemon::getVersion(false) << endl;
return (EXIT_SUCCESS);
case 'V':
cout << Daemon::getVersion(false) << endl;
return (EXIT_SUCCESS);
case 'p': case 'p':
try { try {
port_number = boost::lexical_cast<int>(optarg); port_number = boost::lexical_cast<int>(optarg);
@@ -111,7 +127,7 @@ main(int argc, char* argv[]) {
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_START, DHCP4_START_INFO) LOG_DEBUG(dhcp4_logger, DBG_DHCP4_START, DHCP4_START_INFO)
.arg(getpid()).arg(port_number).arg(verbose_mode ? "yes" : "no"); .arg(getpid()).arg(port_number).arg(verbose_mode ? "yes" : "no");
LOG_INFO(dhcp4_logger, DHCP4_STARTING); LOG_INFO(dhcp4_logger, DHCP4_STARTING).arg(VERSION);
// Create the server instance. // Create the server instance.
ControlledDhcpv4Srv server(port_number); ControlledDhcpv4Srv server(port_number);

View File

@@ -16,6 +16,8 @@
CFG_FILE=@abs_top_builddir@/src/bin/dhcp4/tests/test_config.json CFG_FILE=@abs_top_builddir@/src/bin/dhcp4/tests/test_config.json
# Path to the Kea log file. # Path to the Kea log file.
LOG_FILE=@abs_top_builddir@/src/bin/dhcp4/tests/test.log LOG_FILE=@abs_top_builddir@/src/bin/dhcp4/tests/test.log
# Expected version
EXPECTED_VERSION="@PACKAGE_VERSION@"
# Kea configuration to be stored in the configuration file. # Kea configuration to be stored in the configuration file.
CONFIG="{ CONFIG="{
\"Dhcp4\": \"Dhcp4\":
@@ -256,3 +258,4 @@ shutdown_test() {
dynamic_reconfiguration_test dynamic_reconfiguration_test
shutdown_test "dhcpv4.sigterm_test" 15 shutdown_test "dhcpv4.sigterm_test" 15
shutdown_test "dhcpv4.sigint_test" 2 shutdown_test "dhcpv4.sigint_test" 2
version_test "dhcpv4.version"

View File

@@ -540,9 +540,10 @@ standalone mode, not connected to the message queue. Standalone mode
is only useful during program development, and should not be used in a is only useful during program development, and should not be used in a
production environment. production environment.
% DHCP6_STARTING server starting % DHCP6_STARTING Kea DHCPv6 server version %1 starting
This informational message indicates that the IPv6 DHCP server has This informational message indicates that the IPv6 DHCP server has
processed any command-line switches and is starting. processed any command-line switches and is starting. The version
is also printed.
% DHCP6_START_INFO pid: %1, port: %2, verbose: %3 % DHCP6_START_INFO pid: %1, port: %2, verbose: %3
This is a debug message issued during the IPv6 DHCP server startup. This is a debug message issued during the IPv6 DHCP server startup.

View File

@@ -2697,5 +2697,21 @@ Dhcpv6Srv::d2ClientErrorHandler(const
CfgMgr::instance().getD2ClientMgr().suspendUpdates(); CfgMgr::instance().getD2ClientMgr().suspendUpdates();
} }
std::string
Daemon::getVersion(bool extended) {
std::stringstream tmp;
tmp << VERSION;
if (extended) {
tmp << endl << EXTENDED_VERSION;
// @todo print more details (is it Botan or OpenSSL build,
// with or without MySQL/Postgres? What compilation options were
// used? etc)
}
return (tmp.str());
}
}; };
}; };

View File

@@ -41,13 +41,21 @@ const char* const DHCP6_NAME = "kea-dhcp6";
const char* const DHCP6_LOGGER_NAME = "kea-dhcp6"; const char* const DHCP6_LOGGER_NAME = "kea-dhcp6";
/// @brief Prints Kea Usage and exits
///
/// Note: This function never returns. It terminates the process.
void void
usage() { usage() {
cerr << "Usage: " << DHCP6_NAME << " [-v] [-p port_number] [-c cfgfile]" << endl; cerr << "Kea DHCPv6 server, version " << VERSION << endl;
cerr << " -v: verbose output" << endl; cerr << endl;
cerr << "Usage: " << DHCP6_NAME
<< " [-c cfgfile] [-v] [-V] [-d] [-p port_number]" << endl;
cerr << " -c file: specify configuration file" << endl;
cerr << " -v: print version number and exit." << endl;
cerr << " -V: print extended version and exit" << endl;
cerr << " -d: debug mode with extra verbosity (former -v)" << endl;
cerr << " -p number: specify non-standard port number 1-65535 " cerr << " -p number: specify non-standard port number 1-65535 "
<< "(useful for testing only)" << endl; << "(useful for testing only)" << endl;
cerr << " -c file: specify configuration file" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} // end of anonymous namespace } // end of anonymous namespace
@@ -62,12 +70,20 @@ main(int argc, char* argv[]) {
// The standard config file // The standard config file
std::string config_file(""); std::string config_file("");
while ((ch = getopt(argc, argv, "vp:c:")) != -1) { while ((ch = getopt(argc, argv, "dvVp:c:")) != -1) {
switch (ch) { switch (ch) {
case 'v': case 'd':
verbose_mode = true; verbose_mode = true;
break; break;
case 'v':
cout << Daemon::getVersion(false) << endl;
return (EXIT_SUCCESS);
case 'V':
cout << Daemon::getVersion(true) << endl;
return (EXIT_SUCCESS);
case 'p': // port number case 'p': // port number
try { try {
port_number = boost::lexical_cast<int>(optarg); port_number = boost::lexical_cast<int>(optarg);
@@ -112,7 +128,7 @@ main(int argc, char* argv[]) {
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_START_INFO) LOG_DEBUG(dhcp6_logger, DBG_DHCP6_START, DHCP6_START_INFO)
.arg(getpid()).arg(port_number).arg(verbose_mode ? "yes" : "no"); .arg(getpid()).arg(port_number).arg(verbose_mode ? "yes" : "no");
LOG_INFO(dhcp6_logger, DHCP6_STARTING); LOG_INFO(dhcp6_logger, DHCP6_STARTING).arg(VERSION);
// Create the server instance. // Create the server instance.
ControlledDhcpv6Srv server(port_number); ControlledDhcpv6Srv server(port_number);

View File

@@ -16,6 +16,8 @@
CFG_FILE=@abs_top_builddir@/src/bin/dhcp6/tests/test_config.json CFG_FILE=@abs_top_builddir@/src/bin/dhcp6/tests/test_config.json
# Path to the Kea log file. # Path to the Kea log file.
LOG_FILE=@abs_top_builddir@/src/bin/dhcp6/tests/test.log LOG_FILE=@abs_top_builddir@/src/bin/dhcp6/tests/test.log
# Expected version
EXPECTED_VERSION="@PACKAGE_VERSION@"
# Kea configuration to be stored in the configuration file. # Kea configuration to be stored in the configuration file.
CONFIG="{ CONFIG="{
\"Dhcp6\": \"Dhcp6\":
@@ -257,5 +259,6 @@ shutdown_test() {
} }
dynamic_reconfiguration_test dynamic_reconfiguration_test
shutdown_test "dhcpv4.sigterm_test" 15 shutdown_test "dhcpv6.sigterm_test" 15
shutdown_test "dhcpv4.sigint_test" 2 shutdown_test "dhcpv6.sigint_test" 2
version_test "dhcpv6.version"

View File

@@ -284,7 +284,7 @@ case ${command} in
args="-c ${kea_config_file}" args="-c ${kea_config_file}"
if [ "${kea_verbose}" = "yes" ]; then if [ "${kea_verbose}" = "yes" ]; then
args="${args} -v" args="${args} -d"
fi fi
# Run servers if they are on the list of servers from the command line # Run servers if they are on the list of servers from the command line

View File

@@ -151,6 +151,17 @@ public:
return (verbose_); return (verbose_);
} }
/// @brief returns Kea version on stdout and exits.
///
/// With extended == false, this method returns a simple string
/// containing version number. With extended == true, it returns
/// also additional information about sources. It is expected to
/// return extra information about dependencies and used DB backends.
///
/// @param extended print additional information?
/// @return text string
static std::string getVersion(bool extended);
protected: protected:
/// @brief Invokes handler for the next received signal. /// @brief Invokes handler for the next received signal.

View File

@@ -23,8 +23,17 @@ using namespace isc;
using namespace isc::dhcp; using namespace isc::dhcp;
using namespace isc::data; using namespace isc::data;
std::string isc::dhcp::Daemon::getVersion(bool extended) {
if (extended) {
return (std::string("EXTENDED"));
} else {
return (std::string("BASIC"));
}
}
namespace { namespace {
// Very simple test. Checks whether Daemon can be instantiated and its // Very simple test. Checks whether Daemon can be instantiated and its
// default parameters are sane // default parameters are sane
TEST(DaemonTest, constructor) { TEST(DaemonTest, constructor) {

View File

@@ -401,3 +401,23 @@ must be a number"
# Actually send a signal. # Actually send a signal.
kill -${sig} ${_GET_PIDS} kill -${sig} ${_GET_PIDS}
} }
# This test verifies that the binary is reporting its version properly.
version_test() {
test_name=${1} # Test name
# Log the start of the test and print test name.
test_start ${test_name}
# Remove dangling Kea instances and remove log files.
cleanup
REPORTED_VERSION="`${bin_path}/${bin} -v`"
if test "${REPORTED_VERSION}" == "${EXPECTED_VERSION}"; then
test_finish 0
else
printf "ERROR: Expected version ${EXPECTED_VERSION}, got ${REPORTED_VERSION}\n"
test_finish 1
fi
}