From 1be0350e7ae7a566896a9fe52863dcc22433fc8a Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Wed, 2 May 2012 11:38:32 -0700 Subject: [PATCH] Update libtest. --- libtest/collection.cc | 179 +++++++++++++++++++++ libtest/collection.h | 50 ++++++ libtest/common.h | 1 - libtest/fatal.cc | 13 +- libtest/fatal.hpp | 24 +++ libtest/framework.cc | 146 ++++++++++++++++- libtest/framework.h | 67 +++++++- libtest/include.am | 5 +- libtest/main.cc | 289 +++++++--------------------------- libtest/port.cc | 1 - libtest/server.cc | 21 +-- libtest/server_container.cc | 13 +- libtest/server_container.h | 4 +- libtest/stream.cc | 64 ++++++++ libtest/stream.h | 127 +++++++-------- libtest/test.hpp | 3 +- libtest/{stats.h => timer.cc} | 36 ++--- libtest/timer.hpp | 113 +++++++++++++ tests/cycle.cc | 4 +- tests/failure.cc | 6 +- tests/include.am | 23 +-- tests/runner.h | 2 + 22 files changed, 822 insertions(+), 369 deletions(-) create mode 100644 libtest/collection.cc create mode 100644 libtest/stream.cc rename libtest/{stats.h => timer.cc} (80%) create mode 100644 libtest/timer.hpp diff --git a/libtest/collection.cc b/libtest/collection.cc new file mode 100644 index 00000000..c6fec1eb --- /dev/null +++ b/libtest/collection.cc @@ -0,0 +1,179 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Data Differential YATL (i.e. libtest) library + * + * Copyright (C) 2012 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. + * + */ + +#include + +#include + +static test_return_t runner_code(Framework* frame, + test_st* run, + libtest::Timer& _timer) +{ // Runner Code + + assert(frame->runner()); + assert(run->test_fn); + + test_return_t return_code; + try + { + _timer.reset(); + return_code= frame->runner()->run(run->test_fn, frame->creators_ptr()); + } + // Special case where check for the testing of the exception + // system. + catch (libtest::fatal &e) + { + if (libtest::fatal::is_disabled()) + { + libtest::fatal::increment_disabled_counter(); + return_code= TEST_SUCCESS; + } + else + { + throw; + } + } + + _timer.sample(); + + return return_code; +} + +namespace libtest { + +Collection::Collection(Framework* frame_arg, + collection_st* arg) : + _name(arg->name), + _pre(arg->pre), + _post(arg->post), + _tests(arg->tests), + _frame(frame_arg), + _success(0), + _skipped(0), + _failed(0), + _total(0) +{ + fatal_assert(arg); +} + +test_return_t Collection::exec() +{ + Out << "Collection: " << _name; + + if (test_success(_frame->runner()->pre(_pre, _frame->creators_ptr()))) + { + for (test_st *run= _tests; run->name; run++) + { + long int load_time= 0; + + if (_frame->match(run->name)) + { + continue; + } + _total++; + + test_return_t return_code; + try + { + if (run->requires_flush) + { + if (test_failed(_frame->runner()->flush(_frame->creators_ptr()))) + { + Error << "frame->runner()->flush(creators_ptr)"; + _skipped++; + continue; + } + } + + return_code= runner_code(_frame, run, _timer); + } + catch (libtest::fatal &e) + { + Error << "Fatal exception was thrown: " << e.what(); + return_code= TEST_FAILURE; + _failed++; + throw; + } + + switch (return_code) + { + case TEST_SUCCESS: + Out << "\tTesting " + << run->name + << "\t\t\t\t\t" + << _timer + << " [ " << test_strerror(return_code) << " ]"; + _success++; + break; + + case TEST_FAILURE: + _failed++; + Out << "\tTesting " << run->name << "\t\t\t\t\t" << "[ " << test_strerror(return_code) << " ]"; + break; + + case TEST_SKIPPED: + _skipped++; + Out << "\tTesting " << run->name << "\t\t\t\t\t" << "[ " << test_strerror(return_code) << " ]"; + break; + + default: + fatal_message("invalid return code"); + } +#if 0 + @TODO add code here to allow for a collection to define a method to reset to allow tests to continue. +#endif + } + + (void) _frame->runner()->post(_post, _frame->creators_ptr()); + } + + if (_failed == 0 and _skipped == 0 and _success) + { + return TEST_SUCCESS; + } + + if (_failed) + { + return TEST_FAILURE; + } + + fatal_assert(_skipped or _success == 0); + + return TEST_SKIPPED; +} + +} // namespace libtest + diff --git a/libtest/collection.h b/libtest/collection.h index 044acf03..91c76a6d 100644 --- a/libtest/collection.h +++ b/libtest/collection.h @@ -36,6 +36,10 @@ #pragma once +#include + +class Framework; + /** A structure which describes a collection of test cases. */ @@ -46,4 +50,50 @@ struct collection_st { struct test_st *tests; }; +namespace libtest { + +class Collection { +public: + Collection(Framework*, collection_st*); + + test_return_t exec(); + + const char* name() + { + return _name; + } + + uint32_t success() + { + return _success; + } + + uint32_t skipped() + { + return _skipped; + } + + uint32_t failed() + { + return _failed; + } + + uint32_t total() + { + return _total; + } + +private: + const char *_name; + test_callback_fn *_pre; + test_callback_fn *_post; + struct test_st *_tests; + Framework* _frame; + uint32_t _success; + uint32_t _skipped; + uint32_t _failed; + uint32_t _total; + libtest::Timer _timer; +}; +} // namespace libtest diff --git a/libtest/common.h b/libtest/common.h index a9221916..777d21c3 100644 --- a/libtest/common.h +++ b/libtest/common.h @@ -76,6 +76,5 @@ #include #include -#include #include diff --git a/libtest/fatal.cc b/libtest/fatal.cc index 75e276d5..9ab3292f 100644 --- a/libtest/fatal.cc +++ b/libtest/fatal.cc @@ -40,16 +40,21 @@ namespace libtest { -fatal::fatal(const char *file, int line, const char *func, const char *format, ...) : - std::runtime_error(func) +fatal::fatal(const char *file_arg, int line_arg, const char *func_arg, const char *format, ...) : + std::runtime_error(func_arg), + _file(file_arg), + _line(line_arg), + _func(func_arg) { va_list args; va_start(args, format); char last_error[BUFSIZ]; - (void)vsnprintf(last_error, sizeof(last_error), format, args); + int last_error_length= vsnprintf(last_error, sizeof(last_error), format, args); va_end(args); - snprintf(_error_message, sizeof(_error_message), "%s:%d FATAL:%s (%s)", file, int(line), last_error, func); + strncpy(_mesg, last_error, sizeof(_mesg)); + + snprintf(_error_message, sizeof(_error_message), "%s:%d FATAL:%s (%s)", _file, int(_line), last_error, _func); } static bool _disabled= false; diff --git a/libtest/fatal.hpp b/libtest/fatal.hpp index bc288afe..54f672b6 100644 --- a/libtest/fatal.hpp +++ b/libtest/fatal.hpp @@ -56,6 +56,11 @@ public: return _error_message; } + const char* mesg() const throw() + { + return _error_message; + } + // The following are just for unittesting the exception class static bool is_disabled(); static void disable(); @@ -63,8 +68,27 @@ public: static uint32_t disabled_counter(); static void increment_disabled_counter(); + int line() + { + return _line; + } + + const char* file() + { + return _file; + } + + const char* func() + { + return _func; + } + private: char _error_message[BUFSIZ]; + char _mesg[BUFSIZ]; + int _line; + const char* _file; + const char* _func; }; class disconnected : std::runtime_error diff --git a/libtest/framework.cc b/libtest/framework.cc index 3bab5f0a..114dae46 100644 --- a/libtest/framework.cc +++ b/libtest/framework.cc @@ -35,19 +35,38 @@ */ #include + #include +#include +#include + #include using namespace libtest; -Framework::Framework() : +Framework::Framework(libtest::SignalThread& signal, + const std::string& only_run_arg, + const std::string& wildcard_arg) : collections(NULL), + _total(0), + _success(0), + _skipped(0), + _failed(0), _create(NULL), _destroy(NULL), _runner(NULL), _socket(false), - _creators_ptr(NULL) + _creators_ptr(NULL), + _signal(signal), + _only_run(only_run_arg), + _wildcard(wildcard_arg) { + get_world(this); + + for (collection_st *next= collections; next and next->name; next++) + { + _collection.push_back(new Collection(this, next)); + } } Framework::~Framework() @@ -60,6 +79,121 @@ Framework::~Framework() _servers.shutdown(); delete _runner; + + for (std::vector::iterator iter= _collection.begin(); + iter != _collection.end(); + iter++) + { + delete *iter; + } +} + +bool Framework::match(const char* arg) +{ + if (_wildcard.empty() == false and fnmatch(_wildcard.c_str(), arg, 0)) + { + return true; + } + + return false; +} + +void Framework::exec() +{ + for (std::vector::iterator iter= _collection.begin(); + iter != _collection.end() and (_signal.is_shutdown() == false); + iter++) + { + if (_only_run.empty() == false and + fnmatch(_only_run.c_str(), (*iter)->name(), 0)) + { + continue; + } + + _total++; + + try { + switch ((*iter)->exec()) + { + case TEST_FAILURE: + _failed++; + break; + + case TEST_SKIPPED: + _skipped++; + break; + + // exec() can return SUCCESS, but that doesn't mean that some tests did + // not fail or get skipped. + case TEST_SUCCESS: + _success++; + break; + } + } + catch (libtest::fatal& e) + { + stream::cerr(e.file(), e.line(), e.func()) << e.mesg(); + } + catch (libtest::disconnected& e) + { + Error << "Unhandled disconnection occurred:" << e.what(); + throw; + } + + Outn(); + } +} + +uint32_t Framework::sum_total() +{ + uint32_t count= 0; + for (std::vector::iterator iter= _collection.begin(); + iter != _collection.end(); + iter++) + { + count+= (*iter)->total(); + } + + return count; +} + +uint32_t Framework::sum_success() +{ + uint32_t count= 0; + for (std::vector::iterator iter= _collection.begin(); + iter != _collection.end(); + iter++) + { + count+= (*iter)->success(); + } + + return count; +} + +uint32_t Framework::sum_skipped() +{ + uint32_t count= 0; + for (std::vector::iterator iter= _collection.begin(); + iter != _collection.end(); + iter++) + { + count+= (*iter)->skipped(); + } + + return count; +} + +uint32_t Framework::sum_failed() +{ + uint32_t count= 0; + for (std::vector::iterator iter= _collection.begin(); + iter != _collection.end(); + iter++) + { + count+= (*iter)->failed(); + } + + return count; } libtest::Runner *Framework::runner() @@ -73,13 +207,13 @@ libtest::Runner *Framework::runner() return _runner; } -void* Framework::create(test_return_t& arg) +test_return_t Framework::create() { - arg= TEST_SUCCESS; + test_return_t rc= TEST_SUCCESS; if (_create) { - return _creators_ptr= _create(_servers, arg); + _creators_ptr= _create(_servers, rc); } - return NULL; + return rc; } diff --git a/libtest/framework.h b/libtest/framework.h index 00959c18..45cd6533 100644 --- a/libtest/framework.h +++ b/libtest/framework.h @@ -36,12 +36,16 @@ #pragma once +#include + /** Framework is the structure which is passed to the test implementation to be filled. This must be implemented in order for the test framework to load the tests. We call get_world() in order to fill this structure. */ +#include + class Framework { public: collection_st *collections; @@ -51,7 +55,7 @@ public: test_callback_destroy_fn *_destroy; public: - void* create(test_return_t& arg); + test_return_t create(); /** If an error occurs during the test, this is called. @@ -93,17 +97,74 @@ public: libtest::Runner *runner(); + void exec(); - Framework(); + libtest::Collection& collection(); + + Framework(libtest::SignalThread&, const std::string&); virtual ~Framework(); - Framework(const Framework&); + Framework(libtest::SignalThread&, + const std::string&, + const std::string&); + + bool match(const char* arg); + + void *creators_ptr() + { + return _creators_ptr; + } + + libtest::SignalThread& signal() + { + return _signal; + } + + uint32_t sum_total(); + uint32_t sum_success(); + uint32_t sum_skipped(); + uint32_t sum_failed(); + + size_t size() + { + return _collection.size(); + } + + uint32_t total() const + { + return _total; + } + + uint32_t success() const + { + return _success; + } + + uint32_t skipped() const + { + return _skipped; + } + + uint32_t failed() const + { + return _failed; + } private: Framework& operator=(const Framework&); + + uint32_t _total; + uint32_t _success; + uint32_t _skipped; + uint32_t _failed; + libtest::server_startup_st _servers; bool _socket; void *_creators_ptr; unsigned long int _servers_to_run; + std::vector _collection; + libtest::SignalThread& _signal; + std::string _only_run; + std::string _wildcard; }; diff --git a/libtest/include.am b/libtest/include.am index 7b47fb11..7e9be22d 100644 --- a/libtest/include.am +++ b/libtest/include.am @@ -42,6 +42,7 @@ CLEANFILES+= \ distclean-libtest-check: -rm -rf tmp_chroot +noinst_HEADERS+= libtest/timer.hpp noinst_HEADERS+= \ libtest/binaries.h \ libtest/cpu.hpp \ @@ -73,7 +74,6 @@ noinst_HEADERS+= \ libtest/server_container.h \ libtest/signal.h \ libtest/socket.hpp \ - libtest/stats.h \ libtest/stream.h \ libtest/strerror.h \ libtest/string.hpp \ @@ -94,6 +94,7 @@ libtest_libtest_la_SOURCES= libtest_libtest_la_SOURCES+= libtest/binaries.cc libtest_libtest_la_SOURCES+= libtest/cmdline.cc libtest_libtest_la_SOURCES+= libtest/comparison.cc +libtest_libtest_la_SOURCES+= libtest/collection.cc libtest_libtest_la_SOURCES+= libtest/core.cc libtest_libtest_la_SOURCES+= libtest/cpu.cc libtest_libtest_la_SOURCES+= libtest/dream.cc @@ -112,7 +113,9 @@ libtest_libtest_la_SOURCES+= libtest/server.cc libtest_libtest_la_SOURCES+= libtest/server_container.cc libtest_libtest_la_SOURCES+= libtest/signal.cc libtest_libtest_la_SOURCES+= libtest/socket.cc +libtest_libtest_la_SOURCES+= libtest/stream.cc libtest_libtest_la_SOURCES+= libtest/strerror.cc +libtest_libtest_la_SOURCES+= libtest/timer.cc libtest_libtest_la_SOURCES+= libtest/tmpfile.cc libtest_libtest_la_SOURCES+= libtest/vchar.cc diff --git a/libtest/main.cc b/libtest/main.cc index 0926dc64..3ae8ff98 100644 --- a/libtest/main.cc +++ b/libtest/main.cc @@ -58,71 +58,23 @@ using namespace libtest; -static void stats_print(Stats *stats) +static void stats_print(Framework *frame) { - if (stats->collection_failed == 0 and stats->collection_success == 0) + if (frame->failed() == 0 and frame->success() == 0) { return; } - 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) -{ - long us, s; - - us = (long)(a.tv_usec - b.tv_usec); - us /= 1000; - s = (long)(a.tv_sec - b.tv_sec); - s *= 1000; - return s + us; -} - -static test_return_t runner_code(Framework* frame, - test_st* run, - void* creators_ptr, - long int& load_time) -{ // Runner Code - - struct timeval start_time, end_time; - - gettimeofday(&start_time, NULL); - assert(frame->runner()); - assert(run->test_fn); - - test_return_t return_code; - try - { - return_code= frame->runner()->run(run->test_fn, creators_ptr); - } - // Special case where check for the testing of the exception - // system. - catch (libtest::fatal &e) - { - if (fatal::is_disabled()) - { - fatal::increment_disabled_counter(); - return_code= TEST_SUCCESS; - } - else - { - throw; - } - } - - gettimeofday(&end_time, NULL); - load_time= timedif(end_time, start_time); - - return return_code; + Out << "Collections\t\t\t\t\t" << frame->total(); + Out << "\tFailed\t\t\t\t\t" << frame->failed(); + Out << "\tSkipped\t\t\t\t\t" << frame->skipped(); + Out << "\tSucceeded\t\t\t\t" << frame->success(); + Outn(); + Out << "Tests\t\t\t\t\t" << frame->sum_total(); + Out << "\tFailed\t\t\t\t" << frame->sum_failed(); + Out << "\tSkipped\t\t\t\t" << frame->sum_skipped(); + Out << "\tSucceeded\t\t\t" << frame->sum_success(); } #include @@ -134,6 +86,7 @@ int main(int argc, char *argv[]) unsigned long int opt_repeat= 1; // Run all tests once bool opt_quiet= false; std::string collection_to_run; + std::string wildcard; // Options parsing { @@ -142,6 +95,7 @@ int main(int argc, char *argv[]) OPT_LIBYATL_MATCH_COLLECTION, OPT_LIBYATL_MASSIVE, OPT_LIBYATL_QUIET, + OPT_LIBYATL_MATCH_WILDCARD, OPT_LIBYATL_REPEAT }; @@ -151,6 +105,7 @@ int main(int argc, char *argv[]) { "quiet", no_argument, NULL, OPT_LIBYATL_QUIET }, { "repeat", no_argument, NULL, OPT_LIBYATL_REPEAT }, { "collection", required_argument, NULL, OPT_LIBYATL_MATCH_COLLECTION }, + { "wildcard", required_argument, NULL, OPT_LIBYATL_MATCH_WILDCARD }, { "massive", no_argument, NULL, OPT_LIBYATL_MASSIVE }, { 0, 0, 0, 0 } }; @@ -181,6 +136,10 @@ int main(int argc, char *argv[]) collection_to_run= optarg; break; + case OPT_LIBYATL_MATCH_WILDCARD: + wildcard= optarg; + break; + case OPT_LIBYATL_MASSIVE: opt_massive= true; break; @@ -247,6 +206,24 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } + if (getenv("YATL_COLLECTION_TO_RUN")) + { + if (strlen(getenv("YATL_COLLECTION_TO_RUN"))) + { + collection_to_run= getenv("YATL_COLLECTION_TO_RUN"); + } + } + + if (collection_to_run.compare("none") == 0) + { + return EXIT_SUCCESS; + } + + if (collection_to_run.empty() == false) + { + Out << "Only testing " << collection_to_run; + } + int exit_code; try @@ -254,8 +231,6 @@ int main(int argc, char *argv[]) do { exit_code= EXIT_SUCCESS; - std::auto_ptr frame(new Framework); - fatal_assert(sigignore(SIGPIPE) == 0); libtest::SignalThread signal; @@ -265,182 +240,26 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - Stats stats; - - get_world(frame.get()); - - test_return_t error; - void *creators_ptr= frame->create(error); - - switch (error) - { - case TEST_SUCCESS: - break; - - case TEST_SKIPPED: - Out << "SKIP " << argv[0]; - return EXIT_SUCCESS; - - case TEST_FAILURE: - return EXIT_FAILURE; - } - - if (getenv("YATL_COLLECTION_TO_RUN")) - { - if (strlen(getenv("YATL_COLLECTION_TO_RUN"))) - { - collection_to_run= getenv("YATL_COLLECTION_TO_RUN"); - } - } - - if (collection_to_run.compare("none") == 0) - { - return EXIT_SUCCESS; - } - - if (collection_to_run.empty() == false) - { - Out << "Only testing " << collection_to_run; - } - - char *wildcard= NULL; - if (argc == 3) - { - wildcard= argv[2]; - } + std::auto_ptr frame(new Framework(signal, collection_to_run, wildcard)); - for (collection_st *next= frame->collections; next and next->name and (not signal.is_shutdown()); next++) + // Run create(), bail on error. { - if (collection_to_run.empty() == false and fnmatch(collection_to_run.c_str(), next->name, 0)) - { - continue; - } - - stats.collection_total++; - - bool failed= false; - bool skipped= false; - test_return_t collection_rc; - if (test_success(collection_rc= frame->runner()->pre(next->pre, creators_ptr))) - { - Out << "Collection: " << next->name; - - for (test_st *run= next->tests; run->name; run++) - { - long int load_time= 0; - - if (wildcard && fnmatch(wildcard, run->name, 0)) - { - continue; - } - - test_return_t return_code; - try - { - if (run->requires_flush) - { - if (test_failed(frame->runner()->flush(creators_ptr))) - { - Error << "frame->runner()->flush(creators_ptr)"; - continue; - } - } - - return_code= runner_code(frame.get(), run, creators_ptr, load_time); - - if (return_code == TEST_SKIPPED) - { } - else if (return_code == TEST_FAILURE) - { -#if 0 - Error << " frame->runner()->run(failure)"; - signal.set_shutdown(SHUTDOWN_GRACEFUL); -#endif - } - - } - catch (libtest::fatal &e) - { - Error << "Fatal exception was thrown: " << e.what(); - return_code= TEST_FAILURE; - throw; - } - catch (std::exception &e) - { - Error << "Exception was thrown: " << e.what(); - return_code= TEST_FAILURE; - throw; - } - catch (...) - { - Error << "Unknown exception occurred"; - return_code= TEST_FAILURE; - throw; - } - - stats.total++; - - switch (return_code) - { - case TEST_SUCCESS: - 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; - Out << "\tTesting " << run->name << "\t\t\t\t\t" << "[ " << test_strerror(return_code) << " ]"; - break; - - case TEST_SKIPPED: - stats.skipped++; - skipped= true; - Out << "\tTesting " << run->name << "\t\t\t\t\t" << "[ " << test_strerror(return_code) << " ]"; - break; - - default: - fatal_message("invalid return code"); - } -#if 0 - @TODO add code here to allow for a collection to define a method to reset to allow tests to continue. -#endif - } - - (void) frame->runner()->post(next->post, creators_ptr); - } - else if (collection_rc == TEST_FAILURE) - { - Out << next->name << " [ failed ]"; - failed= true; -#if 0 - signal.set_shutdown(SHUTDOWN_GRACEFUL); -#endif - } - else if (collection_rc == TEST_SKIPPED) + switch (frame->create()) { - Out << next->name << " [ skipping ]"; - skipped= true; - } - - if (failed == false and skipped == false) - { - stats.collection_success++; - } + case TEST_SUCCESS: + break; - if (failed) - { - stats.collection_failed++; - } + case TEST_SKIPPED: + Out << "SKIP " << argv[0]; + return EXIT_SUCCESS; - if (skipped) - { - stats.collection_skipped++; + case TEST_FAILURE: + return EXIT_FAILURE; } - - Outn(); } + frame->exec(); + if (signal.is_shutdown() == false) { signal.set_shutdown(SHUTDOWN_GRACEFUL); @@ -452,21 +271,21 @@ int main(int argc, char *argv[]) Out << "Tests were aborted."; exit_code= EXIT_FAILURE; } - else if (stats.collection_failed) + else if (frame->failed()) { Out << "Some test failed."; exit_code= EXIT_FAILURE; } - else if (stats.collection_skipped and stats.collection_failed and stats.collection_success) + else if (frame->skipped() and frame->failed() and frame->success()) { Out << "Some tests were skipped."; } - else if (stats.collection_success and (stats.collection_failed == 0)) + else if (frame->success() and (frame->failed() == 0)) { Out << "All tests completed successfully."; } - stats_print(&stats); + stats_print(frame.get()); Outn(); // Generate a blank to break up the messages if make check/test has been run } while (exit_code == EXIT_SUCCESS and --opt_repeat); @@ -474,18 +293,22 @@ int main(int argc, char *argv[]) catch (libtest::fatal& e) { std::cerr << e.what() << std::endl; + exit_code= EXIT_FAILURE; } catch (libtest::disconnected& e) { std::cerr << "Unhandled disconnection occurred:" << e.what() << std::endl; + exit_code= EXIT_FAILURE; } catch (std::exception& e) { std::cerr << e.what() << std::endl; + exit_code= EXIT_FAILURE; } catch (...) { std::cerr << "Unknown exception halted execution." << std::endl; + exit_code= EXIT_FAILURE; } return exit_code; diff --git a/libtest/port.cc b/libtest/port.cc index 3ef6bd70..9f9a5bfe 100644 --- a/libtest/port.cc +++ b/libtest/port.cc @@ -52,7 +52,6 @@ #include -#include #include #ifndef __INTEL_COMPILER diff --git a/libtest/server.cc b/libtest/server.cc index 726a01ba..31c58094 100644 --- a/libtest/server.cc +++ b/libtest/server.cc @@ -164,7 +164,9 @@ bool Server::start() // If we find that we already have a pid then kill it. if (has_pid() == true) { +#if 0 fatal_message("has_pid() failed, programer error"); +#endif } // This needs more work. @@ -262,28 +264,29 @@ bool Server::start() if (kill_file(pid_file()) == false) { throw libtest::fatal(LIBYATL_DEFAULT_PARAM, - "Failed to kill off server, waited: %u after startup occurred, when pinging failed: %s stderr:%s", + "Failed to kill off server, waited: %u after startup occurred, when pinging failed: %.*s stderr:%.*s", this_wait, - pid_file().c_str(), - _app.stderr_c_str()); + int(_running.size()), _running.c_str(), + int(_app.stderr_result_length()), _app.stderr_c_str()); } throw libtest::fatal(LIBYATL_DEFAULT_PARAM, - "Failed native ping(), pid: %d is alive: %s waited: %u server started, having pid_file. exec: %s stderr:%s", + "Failed native ping(), pid: %d is alive: %s waited: %u server started, having pid_file. exec: %.*s stderr:%.*s", int(_app.pid()), _app.check() ? "true" : "false", - this_wait, _running.c_str(), - _app.stderr_c_str()); + this_wait, + int(_running.size()), _running.c_str(), + int(_app.stderr_result_length()), _app.stderr_c_str()); } else { throw libtest::fatal(LIBYATL_DEFAULT_PARAM, - "Failed native ping(), pid: %d is alive: %s waited: %u server started. exec: %s stderr:%s", + "Failed native ping(), pid: %d is alive: %s waited: %u server started. exec: %.*s stderr:%.*s", int(_app.pid()), _app.check() ? "true" : "false", this_wait, - _running.c_str(), - _app.stderr_c_str()); + int(_running.size()), _running.c_str(), + int(_app.stderr_result_length()), _app.stderr_c_str()); } _running.clear(); return false; diff --git a/libtest/server_container.cc b/libtest/server_container.cc index 3315b3bb..f658e6ff 100644 --- a/libtest/server_container.cc +++ b/libtest/server_container.cc @@ -91,13 +91,14 @@ Server* server_startup_st::pop_server() return tmp; } -bool server_startup_st::shutdown(uint32_t number_of_host) +// host_to_shutdown => host number to shutdown in array +bool server_startup_st::shutdown(uint32_t host_to_shutdown) { - if (servers.size() > number_of_host) + if (servers.size() > host_to_shutdown) { - Server* tmp= servers[number_of_host]; + Server* tmp= servers[host_to_shutdown]; - if (tmp and tmp->has_pid() and tmp->kill() == false) + if (tmp and tmp->kill() == false) { } else { @@ -108,7 +109,7 @@ bool server_startup_st::shutdown(uint32_t number_of_host) return false; } -void server_startup_st::shutdown_and_remove() +void server_startup_st::clear() { for (std::vector::iterator iter= servers.begin(); iter != servers.end(); iter++) { @@ -166,7 +167,7 @@ server_startup_st::server_startup_st() : server_startup_st::~server_startup_st() { - shutdown_and_remove(); + clear(); } bool server_startup_st::validate() diff --git a/libtest/server_container.h b/libtest/server_container.h index 0a78c4f5..b358e28d 100644 --- a/libtest/server_container.h +++ b/libtest/server_container.h @@ -112,7 +112,9 @@ public: } - void shutdown_and_remove(); + // Just remove everything after shutdown + void clear(); + bool shutdown(); bool shutdown(uint32_t number_of_host); diff --git a/libtest/stream.cc b/libtest/stream.cc new file mode 100644 index 00000000..a9d769f8 --- /dev/null +++ b/libtest/stream.cc @@ -0,0 +1,64 @@ +/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab: + * + * Data Differential YATL (i.e. libtest) library + * + * Copyright (C) 2012 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. + * + */ + +#include +#include + +namespace libtest { +namespace stream { + +namespace detail { + +} // namespace detail + +make_cerr::make_cerr(const char* filename, int line_number, const char* func) : + log(std::cerr, filename, line_number, func) +{ } + +cerr::cerr(const char* filename, int line_number, const char* func) : + log(std::cout, filename, line_number, func) + { } + +clog::clog(const char* filename, int line_number, const char* func) : + log(std::clog, filename, line_number, func) + { } + +cout::cout(const char* filename, int line_number, const char* func) : + log(std::cout, filename, line_number, func) + { } + +} // namespace stream +} // namespace libtest diff --git a/libtest/stream.h b/libtest/stream.h index 1555d98d..9917b94d 100644 --- a/libtest/stream.h +++ b/libtest/stream.h @@ -48,58 +48,66 @@ namespace stream { namespace detail { template - class cerr { + class channel { private: public: typedef std::basic_ostringstream stream_buffer; public: - void operator()(const stream_buffer &s) + void operator()(const stream_buffer& s, std::ostream& _out, + const char* filename, int line_number, const char* func) { - std::cerr << s.str() << std::endl; - } - }; - -template - class make_cerr { - private: - - public: - typedef std::basic_ostringstream stream_buffer; - - public: - void operator()(const stream_buffer &s) - { - std::cerr << std::endl << s.str() << std::endl; - } - }; - -template - class cout { - private: - - public: - typedef std::basic_ostringstream stream_buffer; - - public: - void operator()(const stream_buffer &s) - { - std::cout << s.str() << std::endl; + if (filename) + { + _out + << filename + << ":" + << line_number + << ": in " + << func << "() " + << s.str() + << std::endl; + } + else + { + _out + << s.str() + << std::endl; + } } }; template - class clog { + class channelln { private: public: typedef std::basic_ostringstream stream_buffer; public: - void operator()(const stream_buffer &s) + void operator()(const stream_buffer& s, std::ostream& _out, + const char* filename, int line_number, const char* func) { - std::cerr<< s.str() << std::endl; + if (filename) + { + _out + << std::endl + << filename + << ":" + << line_number + << ": in " + << func << "() " + << s.str() + << std::endl; + } + else + { + _out + << std::endl + << s.str() + << std::endl; + } } }; @@ -107,37 +115,30 @@ template