-/* uTest Copyright (C) 2011 Data Differential, http://datadifferential.com/
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * libtest
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * Use and distribution licensed under the BSD license. See
- * the COPYING file in the parent directory for full text.
*/
+
#pragma once
enum test_return_t {
#include <libtest/common.h>
#include <libtest/gearmand.h>
-#include "util/instance.h"
-#include "util/operation.h"
+#include "util/instance.hpp"
+#include "util/operation.hpp"
-using namespace gearman_util;
+using namespace datadifferential;
using namespace libtest;
#include <cassert>
#include <sys/wait.h>
#include <unistd.h>
-#include <libtest/server.h>
-#include <libtest/wait.h>
-
#include <libgearman/gearman.h>
#ifndef __INTEL_COMPILER
#pragma GCC diagnostic ignored "-Wold-style-cast"
#endif
-class GetPid : public Instance::Finish
+class GetPid : public util::Instance::Finish
{
private:
pid_t _pid;
if (_pid < 1)
{
_pid= -1;
- return true;
+ return false;
}
- return false;
+ return true;
}
};
pid_t get_pid(bool error_is_ok)
{
+ if (not pid_file().empty())
+ {
+ Wait wait(pid_file(), 0);
+
+ if (error_is_ok and not wait.successful())
+ {
+ Error << "Pidfile was not found:" << pid_file();
+ return -1;
+ }
+ }
+
GetPid *get_instance_pid;
- Instance instance(hostname(), port());
+ util::Instance instance(hostname(), port());
instance.set_finish(get_instance_pid= new GetPid);
- instance.push(new Operation(test_literal_param("getpid\r\n"), true));
+ instance.push(new util::Operation(test_literal_param("getpid\r\n"), true));
- if (not instance.run() and not error_is_ok)
+ if (error_is_ok and instance.run() == false)
{
Error << "Failed to obtain pid of server";
}
- _pid= get_instance_pid->pid();
-
- return _pid;
+ return get_instance_pid->pid();
}
bool ping()
if (gearman_success(gearman_client_add_server(client, hostname().c_str(), port())))
{
- gearman_return_t rc= gearman_client_echo(client, gearman_literal_param("This is my echo test"));
+ gearman_return_t rc= gearman_client_echo(client, test_literal_param("This is my echo test"));
if (gearman_success(rc))
{
libtest/stats.h \
libtest/stream.h \
libtest/strerror.h \
+ libtest/string.hpp \
libtest/test.h \
libtest/test.hpp \
libtest/visibility.h \
{
Wait wait(pid_file(), 0);
- if (not wait.successful())
+ if (error_is_ok and not wait.successful())
{
Error << "Pidfile was not found:" << pid_file();
return -1;
}
}
+ pid_t local_pid;
memcached_return_t rc;
if (has_socket())
{
- _pid= libmemcached_util_getpid(socket().c_str(), port(), &rc);
+ local_pid= libmemcached_util_getpid(socket().c_str(), port(), &rc);
}
else
{
- _pid= libmemcached_util_getpid(hostname().c_str(), port(), &rc);
+ local_pid= libmemcached_util_getpid(hostname().c_str(), port(), &rc);
}
- if ((memcached_failed(rc) or _pid < 1) and not error_is_ok)
+ if (error_is_ok and ((memcached_failed(rc) or local_pid < 1)))
{
- Error << "libmemcached_util_getpid(" << memcached_strerror(NULL, rc) << ") pid: " << _pid << " for:" << *this;
+ Error << "libmemcached_util_getpid(" << memcached_strerror(NULL, rc) << ") pid: " << local_pid << " for:" << *this;
}
- return _pid;
+ return local_pid;
}
bool ping()
Server::~Server()
{
- if (has_pid() and not kill())
+ if (has_pid() and not kill(_pid))
{
Error << "Unable to kill:" << *this;
}
pid_t current_pid;
while (--limit and (current_pid= get_pid()) != -1)
{
- if (kill())
+ if (kill(current_pid))
{
Log << "Killed existing server," << *this << " with pid:" << current_pid;
nap();
bool Server::start()
{
// If we find that we already have a pid then kill it.
- if (has_pid() and not kill())
+ if (has_pid() and not kill(_pid))
{
- Error << "Could not kill() existing server during start()";
+ Error << "Could not kill() existing server during start() pid:" << _pid;
return false;
}
assert(not has_pid());
}
// A failing get_pid() at this point is considered an error
- _pid= get_pid(false);
+ _pid= get_pid(true);
return has_pid();
}
return bool(getenv("LIBTEST_MANUAL_VALGRIND"));
}
-bool Server::kill()
+bool Server::kill(pid_t pid_arg)
{
- if (has_pid() and kill_pid(_pid)) // If we kill it, reset
+ if (check_pid(pid_arg) and kill_pid(pid_arg)) // If we kill it, reset
{
if (broken_pid_file() and not pid_file().empty())
{
{
for (std::vector<Server *>::iterator iter= servers.begin(); iter != servers.end(); iter++)
{
- if ((*iter)->has_pid() and not (*iter)->kill())
+ if ((*iter)->has_pid() and not (*iter)->kill((*iter)->pid()))
{
Error << "Unable to kill:" << *(*iter);
}
bool server_startup(server_startup_st& construct, const std::string& server_type, in_port_t try_port, int argc, const char *argv[])
{
- Logn();
+ Outn();
// Look to see if we are being provided ports to use
{
if (construct.is_debug())
{
- Log << "Pausing for startup, hit return when ready.";
+ Out << "Pausing for startup, hit return when ready.";
std::string gdb_command= server->base_command();
std::string options;
- Log << "run " << server->args(options);
+ Out << "run " << server->args(options);
getchar();
}
else if (not server->start())
}
else
{
- Log << "STARTING SERVER(pid:" << server->pid() << "): " << server->running();
+ Out << "STARTING SERVER(pid:" << server->pid() << "): " << server->running();
}
construct.push_server(server);
set_default_port(server->port());
}
- Logn();
+ Outn();
return true;
}
bool server_startup_st::start_socket_server(const std::string& server_type, const in_port_t try_port, int argc, const char *argv[])
{
- Logn();
+ (void)try_port;
+ Outn();
Server *server= NULL;
if (0)
if (is_debug())
{
- Log << "Pausing for startup, hit return when ready.";
+ Out << "Pausing for startup, hit return when ready.";
std::string gdb_command= server->base_command();
std::string options;
- Log << "run " << server->args(options);
+ Out << "run " << server->args(options);
getchar();
}
else if (not server->start())
}
else
{
- Log << "STARTING SERVER(pid:" << server->pid() << "): " << server->running();
+ Out << "STARTING SERVER(pid:" << server->pid() << "): " << server->running();
}
push_server(server);
set_default_socket(server->socket().c_str());
- Logn();
+ Outn();
return true;
}
std::string _log_file;
std::string _base_command; // executable command which include libtool, valgrind, gdb, etc
std::string _running; // Current string being used for system()
+ pid_t _pid;
protected:
- pid_t _pid;
in_port_t _port;
std::string _hostname;
std::string _extra_args;
virtual bool ping()= 0;
- virtual pid_t get_pid(bool error_is_ok= true)= 0;
+ virtual pid_t get_pid(bool error_is_ok= false)= 0;
virtual bool build(int argc, const char *argv[])= 0;
return (_pid > 1);
}
+ bool check_pid(pid_t pid_arg) const
+ {
+ return (pid_arg > 1);
+ }
+
bool is_socket() const
{
return _hostname[0] == '/';
std::string log_and_pid();
- bool kill();
+ bool kill(pid_t pid_arg);
bool start();
bool command(std::string& command_arg);
#define Out stream::cout(NULL, __LINE__, __func__)
+#define Outn() stream::cout(NULL, __LINE__, __func__) << " "
+
#define Log stream::clog(NULL, __LINE__, __func__)
#define Logn() stream::clog(NULL, __LINE__, __func__) << " "
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * libtest
+ *
+ * Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include "util/string.hpp"
+
+#define test_literal_param util_literal_param
+#define test_literal_param_size util_literal_param_size
+#define test_string_make_from_cstr util_string_make_from_cstr
+#define test_array_length util_array_length
static void stats_print(Stats *stats)
{
- Log << "\tTotal Collections\t\t\t\t" << stats->collection_total;
- Log << "\tFailed Collections\t\t\t\t" << stats->collection_failed;
- Log << "\tSkipped Collections\t\t\t\t" << stats->collection_skipped;
- Log << "\tSucceeded Collections\t\t\t\t" << stats->collection_success;
- Logn();
- Log << "Total\t\t\t\t" << stats->total;
- Log << "\tFailed\t\t\t" << stats->failed;
- Log << "\tSkipped\t\t\t" << stats->skipped;
- Log << "\tSucceeded\t\t" << stats->success;
+ Out << "\tTotal Collections\t\t\t\t" << stats->collection_total;
+ Out << "\tFailed Collections\t\t\t\t" << stats->collection_failed;
+ Out << "\tSkipped Collections\t\t\t\t" << stats->collection_skipped;
+ Out << "\tSucceeded Collections\t\t\t\t" << stats->collection_success;
+ Outn();
+ Out << "Total\t\t\t\t" << stats->total;
+ Out << "\tFailed\t\t\t" << stats->failed;
+ Out << "\tSkipped\t\t\t" << stats->skipped;
+ Out << "\tSucceeded\t\t" << stats->success;
}
static long int timedif(struct timeval a, struct timeval b)
if (collection_to_run)
{
- Log << "Only testing " << collection_to_run;
+ Out << "Only testing " << collection_to_run;
}
char *wildcard= NULL;
case TEST_FATAL:
case TEST_FAILURE:
- Error << next->name << " [ failed ]";
+ Out << next->name << " [ failed ]";
failed= true;
set_shutdown(SHUTDOWN_GRACEFUL);
goto cleanup;
case TEST_SKIPPED:
- Log << next->name << " [ skipping ]";
+ Out << next->name << " [ skipping ]";
skipped= true;
goto cleanup;
test_assert(0, "Allocation failure, or unknown return");
}
- Log << "Collection: " << next->name;
+ Out << "Collection: " << next->name;
for (test_st *run= next->tests; run->name; run++)
{
switch (return_code)
{
case TEST_SUCCESS:
- Log << "\tTesting " << run->name << "\t\t\t\t\t" << load_time / 1000 << "." << load_time % 1000 << "[ " << test_strerror(return_code) << " ]";
+ Out << "\tTesting " << run->name << "\t\t\t\t\t" << load_time / 1000 << "." << load_time % 1000 << "[ " << test_strerror(return_code) << " ]";
stats.success++;
break;
case TEST_FAILURE:
stats.failed++;
failed= true;
- Log << "\tTesting " << run->name << "\t\t\t\t\t" << "[ " << test_strerror(return_code) << " ]";
+ Out << "\tTesting " << run->name << "\t\t\t\t\t" << "[ " << test_strerror(return_code) << " ]";
break;
case TEST_SKIPPED:
stats.skipped++;
skipped= true;
- Log << "\tTesting " << run->name << "\t\t\t\t\t" << "[ " << test_strerror(return_code) << " ]";
+ Out << "\tTesting " << run->name << "\t\t\t\t\t" << "[ " << test_strerror(return_code) << " ]";
break;
case TEST_MEMORY_ALLOCATION_FAILURE:
}
world->shutdown(creators_ptr);
- Logn();
+ Outn();
}
if (not is_shutdown())
shutdown_t status= get_shutdown();
if (status == SHUTDOWN_FORCED)
{
- Log << "Tests were aborted.";
+ Out << "Tests were aborted.";
exit_code= EXIT_FAILURE;
}
else if (stats.collection_failed)
{
- Log << "Some test failed.";
+ Out << "Some test failed.";
exit_code= EXIT_FAILURE;
}
else if (stats.collection_skipped)
{
- Log << "Some tests were skipped.";
+ Out << "Some tests were skipped.";
}
else
{
- Log << "All tests completed successfully.";
+ Out << "All tests completed successfully.";
}
stats_print(&stats);
delete world;
- Logn(); // Generate a blank to break up the messages if make check/test has been run
+ Outn(); // Generate a blank to break up the messages if make check/test has been run
return exit_code;
}
#include <libtest/get.h>
#include <libtest/stream.h>
#include <libtest/cmdline.h>
+#include <libtest/string.hpp>
#pragma once
LIBTEST_API
bool test_is_local(void);
-
-#ifdef __cplusplus
-#define test_literal_param(X) (X), (static_cast<size_t>((sizeof(X) - 1)))
-#else
-#define test_literal_param(X) (X), ((size_t)((sizeof(X) - 1)))
-#endif
-
-#define test_string_make_from_cstr(X) (X), ((X) ? strlen(X) : 0)
-
-#define test_array_length(__array) sizeof(__array)/sizeof(&__array)
server_startup_st *servers= (server_startup_st*)object;
test_true(servers);
-#if !defined(MEMCACHED_BINARY) && !defined(HAVE_LIBMEMCACHED)
+#if !defined(MEMCACHED_BINARY) || !defined(HAVE_LIBMEMCACHED)
return TEST_SKIPPED;
#endif
server_startup_st *servers= (server_startup_st*)object;
test_true(servers);
-#if !defined(MEMCACHED_BINARY) && !defined(HAVE_LIBMEMCACHED)
+#if !defined(MEMCACHED_BINARY) || !defined(HAVE_LIBMEMCACHED)
return TEST_SKIPPED;
#endif
$(VALGRIND_COMMAND) $(MEMSLAP_COMMAND)
PHONY += valgrind
-valgrind: tests/testapp tests/testhashkit valgrind-mem valgrind-hash valgrind-memcat valgrind-memcp valgrind-memrm valgrind-memerror valgrind-memdump valgrind-memflush valgrind-memstat
+valgrind: valgrind-mem valgrind-hash valgrind-memcat valgrind-memcp valgrind-memrm valgrind-memerror valgrind-memdump valgrind-memflush valgrind-memstat
+
+helgrind-cycle: tests/cycle
+ $(HELGRIND_COMMAND) $(CYCLE_COMMAND)
+
+helgrind-mem: tests/testapp
+ $(HELGRIND_COMMAND) $(MEM_COMMAND)
+
+helgrind-atom: tests/atomsmasher
+ $(HELGRIND_COMMAND) $(ATOM_COMMAND)
+
+helgrind-udp: tests/testudp
+ $(HELGRIND_COMMAND) $(UDP_COMMAND)
+
+helgrind-plus: tests/testplus
+ $(HELGRIND_COMMAND) $(TESTPLUS_COMMAND)
+
+helgrind-hash: tests/testhashkit
+ $(HELGRIND_COMMAND) $(HASH_COMMAND)
+
+helgrind-hashplus: tests/hashplus
+ $(HELGRIND_COMMAND) $(HASHPLUS_COMMAND)
+
+helgrind-memslap: clients/memslap
+ $(HELGRIND_COMMAND) $(MEMSLAP_COMMAND)
+
+PHONY += helgrind
+helgrind: helgrind-mem helgrind-hash helgrind-memcat helgrind-memcp helgrind-memrm helgrind-memerror helgrind-memdump helgrind-memflush helgrind-memstat
PHONY += cachegrind
CLEANFILES += tests/cachegrind.out