Commit 6169072e authored by Jerry's avatar Jerry

Add zonemgr TODO list and revert to r2688 for merge


git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac289@2730 e5f2f494-b856-4b98-b285-d166d9295462
parent 0eac466c
bind10-devel-20100812 released on August 12, 2010
84. [bug] jinmei, jerry
This is a quick fix patch for the issue: AXFR fails half the
time because of connection problems. xfrout client will make
a new connection every time. (Trac #299, svn r2697)
83. [build]*
The configure --with-boost-lib option is removed. It was not
used since the build included ASIO. (svn r2684)
82. [func] jinmei
bin/auth: Added -u option to allow the effective process user
of the authoritative server after invocation. The same option to
the boss process will be propagated to b10-auth, too.
(Trac #268, svn r2675)
81. [func] jinmei
Added a C++ framework for micro benchmark tests. A supplemental
library functions to build query data for the tests were also
provided. (Trac #241, svn r2664)
80. [bug] jelte
bindctl no longer accepts configuration changes for unknown or
non-running modules (for the latter, this is until we have a
way to verify those options, at which point it'll be allowed
again).
(Trac #99, r2657)
79. [func] feng, jinmei
Refactored the ASIO link interfaces to move incoming XFR and
NOTIFY processing to the auth server class. Wrapper classes for
......@@ -225,11 +196,7 @@ bind10-devel-20100602 released on June 2, 2010
a remote server. (Trac #218, svn r2038)
49. [func]* jelte
Use unix domain sockets for msgq. For b10-msgq, the command
line options --msgq-port and -m were removed. For bind10,
the -msgq-port option was removed, and the -m command line
option was changed to be a filename (instead of port number).
(Trac #183, svn r2009)
Use unix domain sockets for msgq. (Trac #183, svn r2009)
48. [func] jelte
bin/auth: Use asio's io_service for the msgq handling.
......
......@@ -41,8 +41,8 @@ report-coverage:
coverage: clean-coverage perform-coverage report-coverage
#### include external sources in the distributed tarball:
EXTRA_DIST = ext/asio/README
EXTRA_DIST += ext/asio/asio/local/stream_protocol.hpp
# EXTRA_DIST = ext/asio/README
EXTRA_DIST = ext/asio/asio/local/stream_protocol.hpp
EXTRA_DIST += ext/asio/asio/local/basic_endpoint.hpp
EXTRA_DIST += ext/asio/asio/local/datagram_protocol.hpp
EXTRA_DIST += ext/asio/asio/local/connect_pair.hpp
......
......@@ -256,6 +256,14 @@ if test "${boost_include_path}" ; then
fi
AC_SUBST(BOOST_INCLUDES)
AC_ARG_WITH([boost-lib],
AC_HELP_STRING([--with-boost-lib=PATH],
[specify exact directory for Boost libraries]),
[if test "$withval" != "yes" -a "$withval" != "no"; then
BOOST_LDFLAGS="-L$withval"
fi])
AC_SUBST(BOOST_LDFLAGS)
#
# Check availability of gtest, which will be used for unit tests.
#
......@@ -407,9 +415,6 @@ AC_CONFIG_FILES([Makefile
src/bin/zonemgr/tests/Makefile
src/bin/usermgr/Makefile
src/lib/Makefile
src/lib/bench/Makefile
src/lib/bench/example/Makefile
src/lib/bench/tests/Makefile
src/lib/cc/Makefile
src/lib/python/Makefile
src/lib/python/isc/Makefile
......
......@@ -568,7 +568,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = ../src/lib/cc ../src/lib/config ../src/lib/dns ../src/lib/exceptions ../src/lib/datasrc ../src/bin/auth ../src/lib/bench
INPUT = ../src/lib/cc ../src/lib/config ../src/lib/dns ../src/lib/exceptions ../src/lib/datasrc ../src/bin/auth
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
......
This diff is collapsed.
......@@ -75,8 +75,9 @@
data source backend is SQLite3. The authoritative server
requires SQLite 3.3.9 or newer.
The <command>b10-xfrin</command> and <command>b10-xfrout</command>
modules require the libpython3 library and the Python
_sqlite3.so module.
modules require the libboost library,
libpython3 library,
and the Python _sqlite3.so module.
</para></note>
<!-- TODO: this will change ... -->
......@@ -271,8 +272,9 @@ var/
</para>
<para>
The Python Library and Python _sqlite3 module are required to
enable the Xfrout and Xfrin support.
The Boost Library, Python Library,
and Python _sqlite3 module are required to enable the
Xfrout and Xfrin support.
</para>
<note><simpara>
......@@ -484,6 +486,14 @@ var/
</listitem>
</varlistentry>
<varlistentry>
<term>--with-boost-lib</term>
<listitem>
<simpara>Define the path to find the Boost library.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>--with-pythonpath</term>
<listitem>
......@@ -510,10 +520,10 @@ var/
<para>
For example, the following configures it to
find the Boost headers, find the
find the Boost headers and library, find the
Python interpreter, and sets the installation location:
<screen>$ <userinput>./configure \
<screen>$ <userinput>./configure --with-boost-lib=/usr/pkg/lib \
--with-boost-include=/usr/pkg/include \
--with-pythonpath=/usr/pkg/bin/python3.1 \
--prefix=/opt/bind10</userinput></screen>
......@@ -547,6 +557,14 @@ var/
<para>The install step may require superuser privileges.</para>
</note>
<!-- Trac #148 -->
<note><simpara>
Depending on your system and the location of your Boost
Python and Python shared libraries, you may need to
configure your run-time linker to find them (such as
setting LD_LIBRARY_PATH).
</simpara></note>
</section>
<!-- TODO: tests -->
......
ASIO library header files
Version 1.4.5 (2010-05-12)
Downloaded from http://sourceforge.net/projects/asio/files
Project page: http://think-async.com/Asio
No local modifications.
......@@ -47,7 +47,6 @@ libasio_link_a_CPPFLAGS = $(AM_CPPFLAGS)
BUILT_SOURCES = spec_config.h
pkglibexec_PROGRAMS = b10-auth
b10_auth_SOURCES = auth_srv.cc auth_srv.h
b10_auth_SOURCES += change_user.cc change_user.h
b10_auth_SOURCES += common.h
b10_auth_SOURCES += main.cc
b10_auth_LDADD = $(top_builddir)/src/lib/datasrc/.libs/libdatasrc.a
......
......@@ -368,7 +368,6 @@ public:
dns_message_(Message::PARSE),
custom_callback_(NULL)
{
socket_.set_option(socket_base::reuse_address(true));
// Set v6-only (we use a different instantiation for v4,
// otherwise asio will bind to both v4 and v6
if (addr.is_v6()) {
......
......@@ -342,8 +342,10 @@ AuthSrvImpl::processAxfrQuery(const IOMessage& io_message, Message& message,
}
try {
xfrout_client_.connect();
xfrout_connected_ = true;
if (!xfrout_connected_) {
xfrout_client_.connect();
xfrout_connected_ = true;
}
xfrout_client_.sendXfroutRequestInfo(
io_message.getSocket().getNative(),
io_message.getData(),
......@@ -366,10 +368,6 @@ AuthSrvImpl::processAxfrQuery(const IOMessage& io_message, Message& message,
verbose_mode_);
return (true);
}
xfrout_client_.disconnect();
xfrout_connected_ = false;
return (false);
}
......
......@@ -2,12 +2,12 @@
.\" Title: b10-auth
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
.\" Date: July 29, 2010
.\" Date: March 16, 2010
.\" Manual: BIND10
.\" Source: BIND10
.\" Language: English
.\"
.TH "B10\-AUTH" "8" "July 29, 2010" "BIND10" "BIND10"
.TH "B10\-AUTH" "8" "March 16, 2010" "BIND10" "BIND10"
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
......@@ -22,7 +22,7 @@
b10-auth \- Authoritative DNS server
.SH "SYNOPSIS"
.HP \w'\fBb10\-auth\fR\ 'u
\fBb10\-auth\fR [\fB\-4\fR] [\fB\-6\fR] [\fB\-a\ \fR\fB\fIaddress\fR\fR] [\fB\-n\fR] [\fB\-p\ \fR\fB\fInumber\fR\fR] [\fB\-u\ \fR\fB\fIusername\fR\fR] [\fB\-v\fR]
\fBb10\-auth\fR [\fB\-4\fR] [\fB\-6\fR] [\fB\-p\ \fR\fB\fInumber\fR\fR] [\fB\-v\fR]
.SH "DESCRIPTION"
.PP
The
......@@ -64,30 +64,13 @@ The arguments are as follows:
\fB\-4\fR
.RS 4
Enables IPv4 only mode\&. This switch may not be used with
\fB\-6\fR
nor
\fB\-a\fR\&. By default, it listens on both IPv4 and IPv6 (if capable)\&.
\fB\-6\fR\&. By default, it listens on both IPv4 and IPv6 (if capable)\&.
.RE
.PP
\fB\-6\fR
.RS 4
Enables IPv6 only mode\&. This switch may not be used with
\fB\-4\fR
nor
\fB\-a\fR\&. By default, it listens on both IPv4 and IPv6 (if capable)\&.
.RE
.PP
\fB\-a \fR\fB\fIaddress\fR\fR
.RS 4
The IPv4 or IPv6 address to listen on\&. This switch may not be used with
\fB\-4\fR
nor
\fB\-6\fR\&. The default is to listen on all addresses\&. (This is a short term workaround\&. This argument may change\&.)
.RE
.PP
\fB\-n\fR
.RS 4
Do not cache answers in memory\&. The default is to use the cache for faster responses\&. The cache keeps the most recent 30,000 answers (positive and negative) in memory for 30 seconds (instead of querying the data source, such as SQLite3 database, each time)\&.
\fB\-4\fR\&. By default, it listens on both IPv4 and IPv6 (if capable)\&.
.RE
.PP
\fB\-p \fR\fB\fInumber\fR\fR
......@@ -110,15 +93,6 @@ The Y1 prototype runs on all interfaces and on this nonstandard port\&.
.RE
.RE
.PP
\fB\-u \fR\fB\fIusername\fR\fR
.RS 4
The user name of the
\fBb10\-auth\fR
daemon\&. If specified, the daemon changes the process owner to the specified user\&. The
\fIusername\fR
must be either a valid numeric user ID or a valid user name\&. By default the daemon runs as the user who invokes it\&.
.RE
.PP
\fB\-v\fR
.RS 4
Enabled verbose mode\&. This enables diagnostic messages to STDERR\&.
......
......@@ -21,7 +21,7 @@
<refentry>
<refentryinfo>
<date>July 29, 2010</date>
<date>March 16, 2010</date>
</refentryinfo>
<refmeta>
......@@ -47,10 +47,7 @@
<command>b10-auth</command>
<arg><option>-4</option></arg>
<arg><option>-6</option></arg>
<arg><option>-a <replaceable>address</replaceable></option></arg>
<arg><option>-n</option></arg>
<arg><option>-p <replaceable>number</replaceable></option></arg>
<arg><option>-u <replaceable>username</replaceable></option></arg>
<arg><option>-v</option></arg>
</cmdsynopsis>
</refsynopsisdiv>
......@@ -98,8 +95,7 @@
<term><option>-4</option></term>
<listitem><para>
Enables IPv4 only mode.
This switch may not be used with <option>-6</option> nor
<option>-a</option>.
This switch may not be used with <option>-6</option>.
By default, it listens on both IPv4 and IPv6 (if capable).
</para></listitem>
</varlistentry>
......@@ -108,36 +104,11 @@
<term><option>-6</option></term>
<listitem><para>
Enables IPv6 only mode.
This switch may not be used with <option>-4</option> nor
<option>-a</option>.
This switch may not be used with <option>-4</option>.
By default, it listens on both IPv4 and IPv6 (if capable).
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-a <replaceable>address</replaceable></option></term>
<listitem>
<para>The IPv4 or IPv6 address to listen on.
This switch may not be used with <option>-4</option> nor
<option>-6</option>.
The default is to listen on all addresses.
(This is a short term workaround. This argument may change.)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-n</option></term>
<listitem><para>
Do not cache answers in memory.
The default is to use the cache for faster responses.
The cache keeps the most recent 30,000 answers (positive
and negative) in memory for 30 seconds (instead of querying
the data source, such as SQLite3 database, each time).
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-p <replaceable>number</replaceable></option></term>
<listitem><para>
......@@ -148,20 +119,6 @@
</listitem>
</varlistentry>
<varlistentry>
<term><option>-u <replaceable>username</replaceable></option></term>
<listitem>
<para>
The user name of the <command>b10-auth</command> daemon.
If specified, the daemon changes the process owner to the
specified user.
The <replaceable>username</replaceable> must be either a
valid numeric user ID or a valid user name.
By default the daemon runs as the user who invokes it.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-v</option></term>
<listitem><para>
......
// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
// $Id$
#include <errno.h>
#include <string.h>
#include <pwd.h>
#include <unistd.h>
#include <boost/lexical_cast.hpp>
#include <exceptions/exceptions.h>
#include <auth/common.h>
using namespace boost;
void
changeUser(const char* const username) {
const struct passwd *runas_pw = NULL;
runas_pw = getpwnam(username);
endpwent();
if (runas_pw == NULL) {
try {
runas_pw = getpwuid(lexical_cast<uid_t>(username));
endpwent();
} catch (const bad_lexical_cast&) {
; // fall through to isc_throw below.
}
}
if (runas_pw == NULL) {
isc_throw(FatalError, "Unknown user name or UID:" << username);
}
if (setgid(runas_pw->pw_gid) < 0) {
isc_throw(FatalError, "setgid() failed: " << strerror(errno));
}
if (setuid(runas_pw->pw_uid) < 0) {
isc_throw(FatalError, "setuid() failed: " << strerror(errno));
}
}
// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
// $Id$
#ifndef __CHANGE_USER_H
#define __CHANGE_USER_H 1
/// \brief Change the run time user.
///
/// This function changes the user and its group of the authoritative server
/// process.
///
/// On success the user ID of the process is changed to the specified user,
/// and the group is changed to that of the new user.
///
/// This is considered a short term workaround until we develop clearer
/// privilege separation, where the server won't even have to open privileged
/// ports and can be started by a non privileged user from the beginning.
/// This function therefore ignores some corner case problems (see below)
/// which we would address otherwise.
///
/// \c username can be either a textual user name or its numeric ID.
/// If the specified user name (or ID) doesn't specify a local user ID
/// or the user originally starting the process doesn't have a permission
/// of changing the user to \c username, this function throws an exception
/// of class \c FatalError.
///
/// This function internally uses system libraries that do not guarantee
/// reentrancy. In fact, it doesn't even expect to be called more than once.
/// The behavior is undefined if this function is called from multiple threads
/// simultaneously or more generally called multiple times.
///
/// This function only offers the basic exception guarantee, that is, if
/// an exception is thrown from this function, it's possible that an exception
/// is thrown after changing the group ID. This function doesn't recover
/// from that situation. In practice, the process is expected to consider
/// this event a fatal error and will immediately exit, and shouldn't cause
/// a real trouble.
///
/// \param username User name or ID of the new effective user.
void changeUser(const char* const username);
#endif // __CHANGE_USER_H
// Local Variables:
// mode: c++
// End:
......@@ -41,7 +41,6 @@
#include <auth/spec_config.h>
#include <auth/common.h>
#include <auth/change_user.h>
#include <auth/auth_srv.h>
#include <auth/asio_link.h>
......@@ -98,10 +97,9 @@ main(int argc, char* argv[]) {
int ch;
const char* port = DNSPORT;
const char* address = NULL;
const char* uid = NULL;
bool use_ipv4 = true, use_ipv6 = true, cache = true;
while ((ch = getopt(argc, argv, "46a:np:u:v")) != -1) {
while ((ch = getopt(argc, argv, "46a:np:v")) != -1) {
switch (ch) {
case '4':
// Note that -4 means "ipv4 only", we need to set "use_ipv6" here,
......@@ -123,9 +121,6 @@ main(int argc, char* argv[]) {
case 'p':
port = optarg;
break;
case 'u':
uid = optarg;
break;
case 'v':
verbose_mode = true;
break;
......@@ -156,13 +151,7 @@ main(int argc, char* argv[]) {
Session* xfrin_session = NULL;
bool xfrin_session_established = false; // XXX (see Trac #287)
ModuleCCSession* config_session = NULL;
string xfrout_socket_path;
if (getenv("B10_FROM_BUILD") != NULL) {
xfrout_socket_path = string(getenv("B10_FROM_BUILD")) + "/auth_xfrout_conn";
} else {
xfrout_socket_path = UNIX_SOCKET_FILE;
}
XfroutClient xfrout_client(xfrout_socket_path);
XfroutClient xfrout_client(UNIX_SOCKET_FILE);
try {
string specfile;
if (getenv("B10_FROM_BUILD")) {
......@@ -199,10 +188,6 @@ main(int argc, char* argv[]) {
my_command_handler);
cout << "[b10-auth] Configuration channel established." << endl;
if (uid != NULL) {
changeUser(uid);
}
xfrin_session = new Session(io_service->get_io_service());
cout << "[b10-auth] Xfrin session channel created." << endl;
xfrin_session->establish(NULL);
......
......@@ -13,9 +13,7 @@ TESTS += run_unittests
run_unittests_SOURCES = $(top_srcdir)/src/lib/dns/tests/unittest_util.h
run_unittests_SOURCES += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
run_unittests_SOURCES += ../auth_srv.h ../auth_srv.cc
run_unittests_SOURCES += ../change_user.h ../change_user.cc
run_unittests_SOURCES += auth_srv_unittest.cc
run_unittests_SOURCES += change_user_unittest.cc
run_unittests_SOURCES += asio_link_unittest.cc
run_unittests_SOURCES += run_unittests.cc
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
......
......@@ -108,14 +108,8 @@ TEST(IOServiceTest, badAddress) {
TEST(IOServiceTest, unavailableAddress) {
// These addresses should generally be unavailable as a valid local
// address, although there's no guarantee in theory.
EXPECT_THROW(IOService(NULL, *TEST_PORT, *"ffff:ffff::"), IOError);
EXPECT_THROW(IOService(NULL, *TEST_PORT, *"255.255.0.0"), IOError);
// Some OSes would simply reject binding attempt for an AF_INET6 socket
// to an IPv4-mapped IPv6 address. Even if those that allow it, since
// the corresponding IPv4 address is the same as the one used in the
// AF_INET socket case above, it should at least show the same result
// as the previous one.
EXPECT_THROW(IOService(NULL, *TEST_PORT, *"::ffff:255.255.0.0"), IOError);
}
TEST(IOServiceTest, duplicateBind) {
......
......@@ -469,7 +469,7 @@ TEST_F(AuthSrvTest, AXFRSuccess) {
// so we shouldn't have to respond.
EXPECT_EQ(false, server.processMessage(*io_message, parse_message,
response_renderer));
EXPECT_FALSE(xfrout.isConnected());
EXPECT_TRUE(xfrout.isConnected());
}
TEST_F(AuthSrvTest, AXFRConnectFail) {
......@@ -481,8 +481,6 @@ TEST_F(AuthSrvTest, AXFRConnectFail) {
response_renderer));
headerCheck(parse_message, default_qid, Rcode::SERVFAIL(),
opcode.getCode(), QR_FLAG, 1, 0, 0, 0);
// For a shot term workaround with xfrout we currently close the connection
// for each AXFR attempt
EXPECT_FALSE(xfrout.isConnected());
}
......@@ -492,7 +490,7 @@ TEST_F(AuthSrvTest, AXFRSendFail) {
createRequestPacket(opcode, Name("example.com"), RRClass::IN(),
RRType::AXFR(), IPPROTO_TCP);
server.processMessage(*io_message, parse_message, response_renderer);
EXPECT_FALSE(xfrout.isConnected()); // see above
EXPECT_TRUE(xfrout.isConnected());
xfrout.disableSend();
parse_message.clear(Message::PARSE);
......
// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
// $Id$
#include <stdlib.h>
#include <unistd.h> // for getuid
#include <string>
#include <boost/lexical_cast.hpp>
#include <gtest/gtest.h>
#include <auth/common.h>
#include <auth/change_user.h>
using namespace std;
namespace {
TEST(ChangeUserTest, changeToTheSameUser) {
const char* const my_username = getenv("USER");
// normally the USER environment variable should be set to the name
// of the local user running this test, but it's not always the case.
if (my_username == NULL) {
cerr << "Environment variable USER is undefined, skipping the test"
<< endl;
return;
}
// changing to the run time user should succeed.
EXPECT_NO_THROW(changeUser(my_username));
}
TEST(ChangeUserTest, changeToTheSameUserId) {
// same as above, but using numeric user ID
EXPECT_NO_THROW(changeUser(
(boost::lexical_cast<string>(getuid())).c_str()));
}
TEST(ChangeUserTest, badUID) {
// -1 should be an invalid numeric UID, and (hopefully) shouldn't be
// a valid textual username.
EXPECT_THROW(changeUser("-1"), FatalError);
}
TEST(ChangeUserTest, promotionAttempt) {
// change to root should fail unless the running user is a super user.