Commit 82348d8d authored by Stephen Morris's avatar Stephen Morris

Merge branch 'master' into trac1154

parents 54ef8963 ee2a86bd
......@@ -839,6 +839,8 @@ AC_CONFIG_FILES([Makefile
src/lib/python/isc/notify/Makefile
src/lib/python/isc/notify/tests/Makefile
src/lib/python/isc/testutils/Makefile
src/lib/python/isc/bind10/Makefile
src/lib/python/isc/bind10/tests/Makefile
src/lib/config/Makefile
src/lib/config/tests/Makefile
src/lib/config/tests/testdata/Makefile
......@@ -907,7 +909,6 @@ AC_OUTPUT([doc/version.ent
src/bin/bind10/bind10_src.py
src/bin/bind10/run_bind10.sh
src/bin/bind10/tests/bind10_test.py
src/bin/bind10/tests/sockcreator_test.py
src/bin/bindctl/run_bindctl.sh
src/bin/bindctl/bindctl_main.py
src/bin/bindctl/tests/bindctl_test
......
......@@ -56,6 +56,7 @@ EXTRA_DIST += auth_messages.mes
b10_auth_LDADD = $(top_builddir)/src/lib/datasrc/libdatasrc.la
b10_auth_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
b10_auth_LDADD += $(top_builddir)/src/lib/util/libutil.la
b10_auth_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
b10_auth_LDADD += $(top_builddir)/src/lib/cc/libcc.la
b10_auth_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
......
......@@ -17,6 +17,7 @@ query_bench_SOURCES += ../auth_log.h ../auth_log.cc
nodist_query_bench_SOURCES = ../auth_messages.h ../auth_messages.cc
query_bench_LDADD = $(top_builddir)/src/lib/dns/libdns++.la
query_bench_LDADD += $(top_builddir)/src/lib/util/libutil.la
query_bench_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
query_bench_LDADD += $(top_builddir)/src/lib/bench/libbench.la
query_bench_LDADD += $(top_builddir)/src/lib/datasrc/libdatasrc.la
......
......@@ -47,6 +47,7 @@ run_unittests_LDADD += $(SQLITE_LIBS)
run_unittests_LDADD += $(top_builddir)/src/lib/testutils/libtestutils.la
run_unittests_LDADD += $(top_builddir)/src/lib/datasrc/libdatasrc.la
run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
run_unittests_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
run_unittests_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
......
SUBDIRS = . tests
sbin_SCRIPTS = bind10
CLEANFILES = bind10 bind10_src.pyc bind10_messages.py bind10_messages.pyc \
sockcreator.pyc
python_PYTHON = __init__.py sockcreator.py
pythondir = $(pyexecdir)/bind10
CLEANFILES = bind10 bind10_src.pyc bind10_messages.py bind10_messages.pyc
pkglibexecdir = $(libexecdir)/@PACKAGE@
pyexec_DATA = bind10_messages.py
......
......@@ -67,7 +67,7 @@ import isc.util.process
import isc.net.parse
import isc.log
from bind10_messages import *
import bind10.sockcreator
import isc.bind10.sockcreator
isc.log.init("b10-boss")
logger = isc.log.Logger("boss")
......@@ -337,8 +337,8 @@ class BoB:
def start_creator(self):
self.curproc = 'b10-sockcreator'
self.sockcreator = bind10.sockcreator.Creator("@@LIBEXECDIR@@:" +
os.environ['PATH'])
self.sockcreator = isc.bind10.sockcreator.Creator("@@LIBEXECDIR@@:" +
os.environ['PATH'])
def stop_creator(self, kill=False):
if self.sockcreator is None:
......
......@@ -20,7 +20,7 @@ export PYTHON_EXEC
BIND10_PATH=@abs_top_builddir@/src/bin/bind10
PATH=@abs_top_builddir@/src/bin/msgq:@abs_top_builddir@/src/bin/auth:@abs_top_builddir@/src/bin/resolver:@abs_top_builddir@/src/bin/cfgmgr:@abs_top_builddir@/src/bin/cmdctl:@abs_top_builddir@/src/bin/stats:@abs_top_builddir@/src/bin/xfrin:@abs_top_builddir@/src/bin/xfrout:@abs_top_builddir@/src/bin/zonemgr:@abs_top_builddir@/src/bin/dhcp6:$PATH
PATH=@abs_top_builddir@/src/bin/msgq:@abs_top_builddir@/src/bin/auth:@abs_top_builddir@/src/bin/resolver:@abs_top_builddir@/src/bin/cfgmgr:@abs_top_builddir@/src/bin/cmdctl:@abs_top_builddir@/src/bin/stats:@abs_top_builddir@/src/bin/xfrin:@abs_top_builddir@/src/bin/xfrout:@abs_top_builddir@/src/bin/zonemgr:@abs_top_builddir@/src/bin/dhcp6:@abs_top_builddir@/src/bin/sockcreator:$PATH
export PATH
PYTHONPATH=@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/lib/dns/python/.libs:@abs_top_builddir@/src/lib/xfr/.libs:@abs_top_builddir@/src/lib/log/.libs:@abs_top_builddir@/src/lib/util/io/.libs:@abs_top_builddir@/src/lib/python/isc/config:@abs_top_builddir@/src/lib/python/isc/acl/.libs:
......
PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
#PYTESTS = args_test.py bind10_test.py
# NOTE: this has a generated test found in the builddir
PYTESTS = bind10_test.py sockcreator_test.py
PYTESTS = bind10_test.py
# If necessary (rare cases), explicitly specify paths to dynamic libraries
# required by loadable python modules.
......
......@@ -35,6 +35,7 @@ b10_dhcp6_SOURCES = main.cc
b10_dhcp6_SOURCES += dhcp6.h
b10_dhcp6_LDADD = $(top_builddir)/src/lib/datasrc/libdatasrc.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/util/libutil.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/cc/libcc.la
b10_dhcp6_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
......
......@@ -13,6 +13,7 @@ CLEANFILES = *.gcno *.gcda
bin_PROGRAMS = b10-host
b10_host_SOURCES = host.cc
b10_host_LDADD = $(top_builddir)/src/lib/dns/libdns++.la
b10_host_LDADD += $(top_builddir)/src/lib/util/libutil.la
b10_host_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
man_MANS = b10-host.1
......
......@@ -16,6 +16,7 @@ run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
run_unittests_LDADD = $(top_builddir)/src/lib/bench/libbench.la
run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
run_unittests_LDADD += $(GTEST_LDADD)
......
......@@ -56,6 +56,7 @@ run_unittests_LDADD += $(top_builddir)/src/lib/cache/libcache.la
run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
run_unittests_LDADD += $(top_builddir)/src/lib/nsas/libnsas.la
run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
......
......@@ -36,6 +36,7 @@ run_unittests_LDADD = $(GTEST_LDADD)
run_unittests_LDADD += $(SQLITE_LIBS)
run_unittests_LDADD += $(top_builddir)/src/lib/datasrc/libdatasrc.la
run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.la
......
......@@ -13,5 +13,6 @@ noinst_PROGRAMS = rdatarender_bench
rdatarender_bench_SOURCES = rdatarender_bench.cc
rdatarender_bench_LDADD = $(top_builddir)/src/lib/dns/libdns++.la
rdatarender_bench_LDADD += $(top_builddir)/src/lib/util/libutil.la
rdatarender_bench_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
rdatarender_bench_LDADD += $(SQLITE_LIBS)
......@@ -19,6 +19,7 @@
#include <boost/lexical_cast.hpp>
#include <util/buffer.h>
#include <util/strutil.h>
#include <util/encode/base64.h>
#include <dns/messagerenderer.h>
......@@ -30,6 +31,7 @@ using namespace std;
using namespace boost;
using namespace isc::util;
using namespace isc::util::encode;
using namespace isc::util::str;
// BEGIN_ISC_NAMESPACE
// BEGIN_RDATA_NAMESPACE
......@@ -65,45 +67,6 @@ struct TSIG::TSIGImpl {
const vector<uint8_t> other_data_;
};
namespace {
string
getToken(istringstream& iss, const string& full_input) {
string token;
iss >> token;
if (iss.bad() || iss.fail()) {
isc_throw(InvalidRdataText, "Invalid TSIG text: parse error " <<
full_input);
}
return (token);
}
// This helper function converts a string token to an *unsigned* integer.
// NumType is a *signed* integral type (e.g. int32_t) that is sufficiently
// wide to store resulting integers.
// BitSize is the maximum number of bits that the resulting integer can take.
// This function first checks whether the given token can be converted to
// an integer of NumType type. It then confirms the conversion result is
// within the valid range, i.e., [0, 2^NumType - 1]. The second check is
// necessary because lexical_cast<T> where T is an unsigned integer type
// doesn't correctly reject negative numbers when compiled with SunStudio.
template <typename NumType, int BitSize>
NumType
tokenToNum(const string& num_token) {
NumType num;
try {
num = lexical_cast<NumType>(num_token);
} catch (const boost::bad_lexical_cast& ex) {
isc_throw(InvalidRdataText, "Invalid TSIG numeric parameter: " <<
num_token);
}
if (num < 0 || num >= (static_cast<NumType>(1) << BitSize)) {
isc_throw(InvalidRdataText, "Numeric TSIG parameter out of range: " <<
num);
}
return (num);
}
}
/// \brief Constructor from string.
///
/// \c tsig_str must be formatted as follows:
......@@ -148,47 +111,52 @@ tokenToNum(const string& num_token) {
TSIG::TSIG(const std::string& tsig_str) : impl_(NULL) {
istringstream iss(tsig_str);
const Name algorithm(getToken(iss, tsig_str));
const int64_t time_signed = tokenToNum<int64_t, 48>(getToken(iss,
tsig_str));
const int32_t fudge = tokenToNum<int32_t, 16>(getToken(iss, tsig_str));
const int32_t macsize = tokenToNum<int32_t, 16>(getToken(iss, tsig_str));
const string mac_txt = (macsize > 0) ? getToken(iss, tsig_str) : "";
vector<uint8_t> mac;
decodeBase64(mac_txt, mac);
if (mac.size() != macsize) {
isc_throw(InvalidRdataText, "TSIG MAC size and data are inconsistent");
}
const int32_t orig_id = tokenToNum<int32_t, 16>(getToken(iss, tsig_str));
const string error_txt = getToken(iss, tsig_str);
int32_t error = 0;
// XXX: In the initial implementation we hardcode the mnemonics.
// We'll soon generalize this.
if (error_txt == "BADSIG") {
error = 16;
} else if (error_txt == "BADKEY") {
error = 17;
} else if (error_txt == "BADTIME") {
error = 18;
} else {
error = tokenToNum<int32_t, 16>(error_txt);
}
const int32_t otherlen = tokenToNum<int32_t, 16>(getToken(iss, tsig_str));
const string otherdata_txt = (otherlen > 0) ? getToken(iss, tsig_str) : "";
vector<uint8_t> other_data;
decodeBase64(otherdata_txt, other_data);
if (!iss.eof()) {
isc_throw(InvalidRdataText, "Unexpected input for TSIG RDATA: " <<
tsig_str);
try {
const Name algorithm(getToken(iss));
const int64_t time_signed = tokenToNum<int64_t, 48>(getToken(iss));
const int32_t fudge = tokenToNum<int32_t, 16>(getToken(iss));
const int32_t macsize = tokenToNum<int32_t, 16>(getToken(iss));
const string mac_txt = (macsize > 0) ? getToken(iss) : "";
vector<uint8_t> mac;
decodeBase64(mac_txt, mac);
if (mac.size() != macsize) {
isc_throw(InvalidRdataText, "TSIG MAC size and data are inconsistent");
}
const int32_t orig_id = tokenToNum<int32_t, 16>(getToken(iss));
const string error_txt = getToken(iss);
int32_t error = 0;
// XXX: In the initial implementation we hardcode the mnemonics.
// We'll soon generalize this.
if (error_txt == "BADSIG") {
error = 16;
} else if (error_txt == "BADKEY") {
error = 17;
} else if (error_txt == "BADTIME") {
error = 18;
} else {
error = tokenToNum<int32_t, 16>(error_txt);
}
const int32_t otherlen = tokenToNum<int32_t, 16>(getToken(iss));
const string otherdata_txt = (otherlen > 0) ? getToken(iss) : "";
vector<uint8_t> other_data;
decodeBase64(otherdata_txt, other_data);
if (!iss.eof()) {
isc_throw(InvalidRdataText, "Unexpected input for TSIG RDATA: " <<
tsig_str);
}
impl_ = new TSIGImpl(algorithm, time_signed, fudge, mac, orig_id,
error, other_data);
} catch (const StringTokenError& ste) {
isc_throw(InvalidRdataText, "Invalid TSIG text: " << ste.what() <<
": " << tsig_str);
}
impl_ = new TSIGImpl(algorithm, time_signed, fudge, mac, orig_id,
error, other_data);
}
/// \brief Constructor from wire-format data.
......
......@@ -18,6 +18,7 @@
#include <boost/lexical_cast.hpp>
#include <util/buffer.h>
#include <util/strutil.h>
#include <dns/messagerenderer.h>
#include <dns/name.h>
......@@ -26,6 +27,7 @@
using namespace std;
using namespace isc::util;
using namespace isc::util::str;
// BEGIN_ISC_NAMESPACE
// BEGIN_RDATA_NAMESPACE
......@@ -44,39 +46,6 @@ struct SRVImpl {
Name target_;
};
namespace {
string
getToken(istringstream& iss, const string& full_input) {
string token;
iss >> token;
if (iss.bad() || iss.fail()) {
isc_throw(InvalidRdataText, "Invalid SRV text: parse error " <<
full_input);
}
return (token);
}
// This helper function converts a string token to an *unsigned* integer.
// NumType is a *signed* integral type (e.g. int32_t) that is sufficiently
// wide to store resulting integers.
template <typename NumType, int BitSize>
NumType
tokenToNum(const string& num_token) {
NumType num;
try {
num = boost::lexical_cast<NumType>(num_token);
} catch (const boost::bad_lexical_cast& ex) {
isc_throw(InvalidRdataText, "Invalid SRV numeric parameter: " <<
num_token);
}
if (num < 0 || num >= (static_cast<NumType>(1) << BitSize)) {
isc_throw(InvalidRdataText, "Numeric SRV parameter out of range: " <<
num);
}
return (num);
}
}
/// \brief Constructor from string.
///
/// \c srv_str must be formatted as follows:
......@@ -103,17 +72,22 @@ SRV::SRV(const string& srv_str) :
{
istringstream iss(srv_str);
const int32_t priority = tokenToNum<int32_t, 16>(getToken(iss, srv_str));
const int32_t weight = tokenToNum<int32_t, 16>(getToken(iss, srv_str));
const int32_t port = tokenToNum<int32_t, 16>(getToken(iss, srv_str));
const Name targetname(getToken(iss, srv_str));
if (!iss.eof()) {
isc_throw(InvalidRdataText, "Unexpected input for SRV RDATA: " <<
srv_str);
try {
const int32_t priority = tokenToNum<int32_t, 16>(getToken(iss));
const int32_t weight = tokenToNum<int32_t, 16>(getToken(iss));
const int32_t port = tokenToNum<int32_t, 16>(getToken(iss));
const Name targetname(getToken(iss));
if (!iss.eof()) {
isc_throw(InvalidRdataText, "Unexpected input for SRV RDATA: " <<
srv_str);
}
impl_ = new SRVImpl(priority, weight, port, targetname);
} catch (const StringTokenError& ste) {
isc_throw(InvalidRdataText, "Invalid SRV text: " <<
ste.what() << ": " << srv_str);
}
impl_ = new SRVImpl(priority, weight, port, targetname);
}
/// \brief Constructor from wire-format data.
......
SUBDIRS = datasrc cc config log net notify util testutils acl
SUBDIRS = datasrc cc config log net notify util testutils acl bind10
python_PYTHON = __init__.py
......
SUBDIRS = . tests
python_PYTHON = __init__.py sockcreator.py
pythondir = $(pyexecdir)/isc/bind10
PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
#PYTESTS = args_test.py bind10_test.py
# NOTE: this has a generated test found in the builddir
PYTESTS = sockcreator_test.py
EXTRA_DIST = $(PYTESTS)
# If necessary (rare cases), explicitly specify paths to dynamic libraries
# required by loadable python modules.
LIBRARY_PATH_PLACEHOLDER =
if SET_ENV_LIBRARY_PATH
LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/util/io/.libs:$$$(ENV_LIBRARY_PATH)
endif
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
if ENABLE_PYTHON_COVERAGE
touch $(abs_top_srcdir)/.coverage
rm -f .coverage
${LN_S} $(abs_top_srcdir)/.coverage .coverage
endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
$(LIBRARY_PATH_PLACEHOLDER) \
env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_srcdir)/src/bin:$(abs_top_builddir)/src/bin/bind10:$(abs_top_builddir)/src/lib/util/io/.libs \
BIND10_MSGQ_SOCKET_FILE=$(abs_top_builddir)/msgq_socket \
$(PYCOVERAGE_RUN) $(abs_srcdir)/$$pytest || exit ; \
done
......@@ -26,7 +26,7 @@ import socket
from isc.net.addr import IPAddr
import isc.log
from libutil_io_python import send_fd
from bind10.sockcreator import Parser, CreatorError, WrappedSocket
from isc.bind10.sockcreator import Parser, CreatorError, WrappedSocket
class FakeCreator:
"""
......
......@@ -425,7 +425,7 @@ class UIModuleCCSession(MultiConfigData):
raise ModuleCCSessionError("Bad config version")
self._set_current_config(config)
def _add_value_to_list(self, identifier, value):
def _add_value_to_list(self, identifier, value, module_spec):
cur_list, status = self.get_value(identifier)
if not cur_list:
cur_list = []
......@@ -491,7 +491,7 @@ class UIModuleCCSession(MultiConfigData):
if set_value_str is not None:
value_str += set_value_str
value = isc.cc.data.parse_value_str(value_str)
self._add_value_to_list(identifier, value)
self._add_value_to_list(identifier, value, module_spec)
elif 'named_set_item_spec' in module_spec:
item_name = None
item_value = None
......
......@@ -745,6 +745,8 @@ class TestUIModuleCCSession(unittest.TestCase):
uccs.remove_value, "Spec2/item5[123]", None)
uccs.remove_value("Spec2/item5[0]", None)
self.assertEqual({'Spec2': {'item5': []}}, uccs._local_changes)
uccs.add_value("Spec2/item5", None);
self.assertEqual({'Spec2': {'item5': ['']}}, uccs._local_changes)
def test_add_remove_value_named_set(self):
fake_conn = fakeUIConn()
......
......@@ -31,6 +31,7 @@ run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libasiolink.la
run_unittests_LDADD += $(top_builddir)/src/lib/asiodns/libasiodns.la
run_unittests_LDADD += $(top_builddir)/src/lib/resolve/libresolve.la
run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/libutil.la
run_unittests_LDADD += $(top_builddir)/src/lib/log/liblog.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
......
......@@ -132,6 +132,17 @@ format(const std::string& format, const std::vector<std::string>& args) {
return (result);
}
std::string
getToken(std::istringstream& iss) {
string token;
iss >> token;
if (iss.bad() || iss.fail()) {
isc_throw(StringTokenError, "could not read token from string");
}
return (token);
}
} // namespace str
} // namespace util
} // namespace isc
......@@ -18,7 +18,10 @@
#include <algorithm>
#include <cctype>
#include <string>
#include <sstream>
#include <vector>
#include <exceptions/exceptions.h>
#include <boost/lexical_cast.hpp>
namespace isc {
namespace util {
......@@ -26,6 +29,16 @@ namespace str {
/// \brief A Set of C++ Utilities for Manipulating Strings
///
/// \brief A standard string util exception that is thrown if getToken or
/// numToToken are called with bad input data
///
class StringTokenError : public Exception {
public:
StringTokenError(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) {}
};
/// \brief Normalize Backslash
///
/// Only relevant to Windows, this replaces all "\" in a string with "/" and
......@@ -140,6 +153,55 @@ std::string format(const std::string& format,
const std::vector<std::string>& args);
/// \brief Returns one token from the given stringstream
///
/// Using the >> operator, with basic error checking
///
/// \exception StringTokenError if the token cannot be read from the stream
///
/// \param iss stringstream to read one token from
///
/// \return the first token read from the stringstream
std::string getToken(std::istringstream& iss);
/// \brief Converts a string token to an *unsigned* integer.
///
/// The value is converted using a lexical cast, with error and bounds
/// checking.
///
/// NumType is a *signed* integral type (e.g. int32_t) that is sufficiently
/// wide to store resulting integers.
///
/// BitSize is the maximum number of bits that the resulting integer can take.
/// This function first checks whether the given token can be converted to
/// an integer of NumType type. It then confirms the conversion result is
/// within the valid range, i.e., [0, 2^BitSize - 1]. The second check is
/// necessary because lexical_cast<T> where T is an unsigned integer type
/// doesn't correctly reject negative numbers when compiled with SunStudio.
///
/// \exception StringTokenError if the value is out of range, or if it
/// could not be converted
///
/// \param num_token the string token to convert
///
/// \return the converted value, of type NumType
template <typename NumType, int BitSize>
NumType
tokenToNum(const std::string& num_token) {
NumType num;
try {
num = boost::lexical_cast<NumType>(num_token);
} catch (const boost::bad_lexical_cast& ex) {
isc_throw(StringTokenError, "Invalid SRV numeric parameter: " <<
num_token);
}
if (num < 0 || num >= (static_cast<NumType>(1) << BitSize)) {
isc_throw(StringTokenError, "Numeric SRV parameter out of range: " <<
num);
}
return (num);
}
} // namespace str
} // namespace util
} // namespace isc
......
......@@ -12,6 +12,8 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <stdint.h>
#include <string>
#include <gtest/gtest.h>
......@@ -22,17 +24,9 @@ using namespace isc;
using namespace isc::util;
using namespace std;
class StringUtilTest : public ::testing::Test {
protected:
StringUtilTest()
{
}
};
// Check for slash replacement
TEST_F(StringUtilTest, Slash) {
TEST(StringUtilTest, Slash) {
string instring = "";
isc::util::str::normalizeSlash(instring);
......@@ -49,7 +43,7 @@ TEST_F(StringUtilTest, Slash) {
// Check that leading and trailing space trimming works
TEST_F(StringUtilTest, Trim) {
TEST(StringUtilTest, Trim) {
// Empty and full string.
EXPECT_EQ("", isc::util::str::trim(""));
......@@ -71,7 +65,7 @@ TEST_F(StringUtilTest, Trim) {
// returned vector; if not as expected, the following references may be invalid
// so should not be used.
TEST_F(StringUtilTest, Tokens) {
TEST(StringUtilTest, Tokens) {
vector<string> result;
// Default delimiters
......@@ -157,7 +151,7 @@ TEST_F(StringUtilTest, Tokens) {
// Changing case
TEST_F(StringUtilTest, ChangeCase) {
TEST(StringUtilTest, ChangeCase) {
string mixed("abcDEFghiJKLmno123[]{=+--+]}");
string upper("ABCDEFGHIJKLMNO123[]{=+--+]}");
string lower("abcdefghijklmno123[]{=+--+]}");
......@@ -173,7 +167,7 @@ TEST_F(StringUtilTest, ChangeCase) {
// Formatting
TEST_F(StringUtilTest, Formatting) {
TEST(StringUtilTest, Formatting) {