diff options
| author | Robert Collins <robertc@robertcollins.net> | 2009-10-10 12:19:17 +1100 |
|---|---|---|
| committer | Robert Collins <robertc@robertcollins.net> | 2009-10-10 12:19:17 +1100 |
| commit | 6796be6ea3f0d8795fee7ab364a24f0e5678ffbb (patch) | |
| tree | 177d77c187285aa0748f191a0b26230241c312b0 | |
| parent | cc36797e0831ed019dbfb4b37b33636f5c25abfa (diff) | |
| parent | a3c2c3bff21e7db30002824843dc0bc954ad6d6d (diff) | |
| download | subunit-git-6796be6ea3f0d8795fee7ab364a24f0e5678ffbb.tar.gz | |
Merge trunk to resolve NEWS.
| -rw-r--r-- | .bzrignore | 2 | ||||
| -rw-r--r-- | Makefile.am | 19 | ||||
| -rw-r--r-- | NEWS | 5 | ||||
| -rw-r--r-- | README | 5 | ||||
| -rw-r--r-- | c++/README | 59 | ||||
| -rw-r--r-- | c++/SubunitTestProgressListener.cpp | 63 | ||||
| -rw-r--r-- | c++/SubunitTestProgressListener.h | 56 | ||||
| -rw-r--r-- | c++/cppunit-subunit-1.10.2.patch | 134 | ||||
| -rw-r--r-- | c/include/subunit/child.h | 12 | ||||
| -rw-r--r-- | c/lib/child.c | 50 | ||||
| -rw-r--r-- | c/tests/test_child.c | 19 | ||||
| -rw-r--r-- | configure.ac | 4 | ||||
| -rw-r--r-- | libcppunit_subunit.pc.in | 11 | ||||
| -rw-r--r-- | python/subunit/__init__.py | 1 |
14 files changed, 251 insertions, 189 deletions
@@ -21,10 +21,12 @@ py-compile .libs *.lo libsubunit.la +libcppunit_subunit.la subunit-0.0.1.tar.gz libtool stamp-h1 libsubunit.pc +libcppunit_subunit.pc config.log config.status Makefile diff --git a/Makefile.am b/Makefile.am index f6a4eff..d0080c7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,14 +8,10 @@ EXTRA_DIST = \ c/check-subunit-0.9.5.patch \ c/check-subunit-0.9.6.patch \ c++/README \ - c++/cppunit-subunit-1.10.2.patch \ perl/subunit-diff \ perl/Makefile.PL.in \ perl/lib/Subunit/Diff.pm \ perl/lib/Subunit.pm \ - python/subunit/__init__.py \ - python/subunit/progress_model.py \ - python/subunit/run.py \ python/subunit/tests/TestUtil.py \ python/subunit/tests/__init__.py \ python/subunit/tests/sample-script.py \ @@ -39,6 +35,9 @@ ACLOCAL_AMFLAGS = -I m4 SUBUNIT_CFLAGS = -Wall -Werror -Wextra -Wstrict-prototypes -Wmissing-prototypes \ -Wwrite-strings -Wno-variadic-macros -I$(top_srcdir)/c/include AM_CFLAGS = $(SUBUNIT_CFLAGS) +SUBUNIT_CXXFLAGS = -Wall -Werror -Wextra -Wwrite-strings -Wno-variadic-macros \ + -I$(top_srcdir)/c/include +AM_CXXFLAGS = $(SUBUNIT_CXXFLAGS) include_subunitdir = $(includedir)/subunit @@ -57,7 +56,9 @@ TESTS = runtests.py $(check_PROGRAMS) ## install libsubunit.pc pcdatadir = $(libdir)/pkgconfig -pcdata_DATA = libsubunit.pc +pcdata_DATA = \ + libsubunit.pc \ + libcppunit_subunit.pc pkgpython_PYTHON = \ python/subunit/__init__.py \ @@ -67,9 +68,11 @@ pkgpython_PYTHON = \ python/subunit/test_results.py lib_LTLIBRARIES = libsubunit.la +lib_LTLIBRARIES += libcppunit_subunit.la include_subunit_HEADERS = \ - c/include/subunit/child.h + c/include/subunit/child.h \ + c++/SubunitTestProgressListener.h check_PROGRAMS = \ c/tests/test_child @@ -81,6 +84,10 @@ libsubunit_la_SOURCES = \ c/lib/child.c \ c/include/subunit/child.h +libcppunit_subunit_la_SOURCES = \ + c++/SubunitTestProgressListener.cpp \ + c++/SubunitTestProgressListener.h + tests_LDADD = @CHECK_LIBS@ $(top_builddir)/libsubunit.la c_tests_test_child_CFLAGS = $(SUBUNIT_CFLAGS) @CHECK_CFLAGS@ c_tests_test_child_LDADD = $(tests_LDADD) @@ -13,6 +13,9 @@ subunit release notes IMPROVEMENTS: + * CPPUnit is now directly supported: subunit builds a cppunit listener + ``libcppunit-subunit``. + * In the python API ``addExpectedFailure`` and ``addUnexpectedSuccess`` from python 2.7/3.1 are now supported. ``addExpectedFailure`` is serialised as ``xfail``, and ``addUnexpectedSuccess`` as ``success``. @@ -24,6 +27,8 @@ subunit release notes for them, both serialiser and object is not yet finalised. Testers and early adopters are sought. + * The C library now has ``subunit_test_skip``. + BUG FIXES: * Install progress_model.py correctly. @@ -18,7 +18,6 @@ subunit reuses iso8601 by Michael Twomey, distributed under an MIT style licence - see python/iso8601/LICENSE for details. - Subunit ------- @@ -86,8 +85,8 @@ more details. C++ === -C++ uses the C bindings and includes a patch for cppunit. See 'c++/README' for -details. +The C library is includable and usable directly from C++. A TestListener for +CPPUnit is included in the Subunit distribution. See 'c++/README' for details. shell ===== @@ -18,32 +18,33 @@ # Currently there are no native C++ bindings for subunit. However the C library -can be used from C++ safely. There is also a patch for cppunit -(http://cppunit.sourceforge.net/) to enable reporting via subunit -(cppunit-subunit-1.10.2.patch). - -To use the patch, apply it and rebuild your cppunit. Then in your main do -{ - // Create the event manager and test controller - CPPUNIT_NS::TestResult controller; - - // Add a listener that collects test result - // so we can get the overall status. - // note this isn't needed for subunit... - CPPUNIT_NS::TestResultCollector result; - controller.addListener( &result ); - - // Add a listener that print test activity in subunit format. - CPPUNIT_NS::SubunitTestProgressListener progress; - controller.addListener( &progress ); - - // Add the top suite to the test runner - CPPUNIT_NS::TestRunner runner; - runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest() ); - runner.run( controller ); - - return result.wasSuccessful() ? 0 : 1; -} - - -See the c/README for documentation on the C bindings for subunit. +can be used from C++ safely. A CPPUnit listener is built as part of Subunit to +allow CPPUnit users to simply get Subunit output. + +To use the listener, use pkg-config (or your preferred replacement) to get the +cflags and link settings from libcppunit_subunit.pc. + +In your test driver main, use SubunitTestProgressListener, as shown in this +example main:: + + { + // Create the event manager and test controller + CPPUNIT_NS::TestResult controller; + + // Add a listener that collects test result + // so we can get the overall status. + // note this isn't needed for subunit... + CPPUNIT_NS::TestResultCollector result; + controller.addListener( &result ); + + // Add a listener that print test activity in subunit format. + CPPUNIT_NS::SubunitTestProgressListener progress; + controller.addListener( &progress ); + + // Add the top suite to the test runner + CPPUNIT_NS::TestRunner runner; + runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest() ); + runner.run( controller ); + + return result.wasSuccessful() ? 0 : 1; + } diff --git a/c++/SubunitTestProgressListener.cpp b/c++/SubunitTestProgressListener.cpp new file mode 100644 index 0000000..76cd9e1 --- /dev/null +++ b/c++/SubunitTestProgressListener.cpp @@ -0,0 +1,63 @@ +/* Subunit test listener for cppunit (http://cppunit.sourceforge.net). + * Copyright (C) 2006 Robert Collins <robertc@robertcollins.net> + * + * Licensed under either the Apache License, Version 2.0 or the BSD 3-clause + * license at the users choice. A copy of both licenses are available in the + * project source as Apache-2.0 and BSD. You may not use this file except in + * compliance with one of these two licences. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under these licenses is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license you chose for the specific language governing permissions + * and limitations under that license. + */ + +#include <cppunit/Exception.h> +#include <cppunit/Test.h> +#include <cppunit/TestFailure.h> +#include <cppunit/TextOutputter.h> +#include <iostream> + +// Have to be able to import the public interface without config.h. +#include "SubunitTestProgressListener.h" +#include "config.h" +#include "subunit/child.h" + + +CPPUNIT_NS_BEGIN + + +void +SubunitTestProgressListener::startTest( Test *test ) +{ + subunit_test_start(test->getName().c_str()); + last_test_failed = false; +} + +void +SubunitTestProgressListener::addFailure( const TestFailure &failure ) +{ + std::ostringstream capture_stream; + TextOutputter outputter(NULL, capture_stream); + outputter.printFailureLocation(failure.sourceLine()); + outputter.printFailureDetail(failure.thrownException()); + + if (failure.isError()) + subunit_test_error(failure.failedTestName().c_str(), + capture_stream.str().c_str()); + else + subunit_test_fail(failure.failedTestName().c_str(), + capture_stream.str().c_str()); + last_test_failed = true; +} + +void +SubunitTestProgressListener::endTest( Test *test) +{ + if (!last_test_failed) + subunit_test_pass(test->getName().c_str()); +} + + +CPPUNIT_NS_END diff --git a/c++/SubunitTestProgressListener.h b/c++/SubunitTestProgressListener.h new file mode 100644 index 0000000..5206d83 --- /dev/null +++ b/c++/SubunitTestProgressListener.h @@ -0,0 +1,56 @@ +/* Subunit test listener for cppunit (http://cppunit.sourceforge.net). + * Copyright (C) 2006 Robert Collins <robertc@robertcollins.net> + * + * Licensed under either the Apache License, Version 2.0 or the BSD 3-clause + * license at the users choice. A copy of both licenses are available in the + * project source as Apache-2.0 and BSD. You may not use this file except in + * compliance with one of these two licences. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under these licenses is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the license you chose for the specific language governing permissions + * and limitations under that license. + */ +#ifndef CPPUNIT_SUBUNITTESTPROGRESSLISTENER_H +#define CPPUNIT_SUBUNITTESTPROGRESSLISTENER_H + +#include <cppunit/TestListener.h> + + +CPPUNIT_NS_BEGIN + + +/*! + * \brief TestListener that outputs subunit + * (http://www.robertcollins.net/unittest/subunit) compatible output. + * \ingroup TrackingTestExecution + */ +class CPPUNIT_API SubunitTestProgressListener : public TestListener +{ +public: + + SubunitTestProgressListener() {} + + void startTest( Test *test ); + + void addFailure( const TestFailure &failure ); + + void endTest( Test *test ); + +private: + /// Prevents the use of the copy constructor. + SubunitTestProgressListener( const SubunitTestProgressListener © ); + + /// Prevents the use of the copy operator. + void operator =( const SubunitTestProgressListener © ); + +private: + int last_test_failed; +}; + + +CPPUNIT_NS_END + +#endif // CPPUNIT_SUBUNITTESTPROGRESSLISTENER_H + diff --git a/c++/cppunit-subunit-1.10.2.patch b/c++/cppunit-subunit-1.10.2.patch deleted file mode 100644 index b3c353b..0000000 --- a/c++/cppunit-subunit-1.10.2.patch +++ /dev/null @@ -1,134 +0,0 @@ -diff -u cppunit-1.10.2/src/cppunit/Makefile.am cppunit-1.10.2/src/cppunit/Makefile.am ---- cppunit-1.10.2/src/cppunit/Makefile.am -+++ cppunit-1.10.2/src/cppunit/Makefile.am -@@ -28,6 +28,7 @@ - ProtectorChain.cpp \ - SourceLine.cpp \ - StringTools.cpp \ -+ SubunitTestProgressListener.cpp \ - SynchronizedObject.cpp \ - Test.cpp \ - TestAssert.cpp \ -@@ -74,0 +76,2 @@ -+ -+LIBRARY_LIBADD = $(LIBS) ---- cppunit-1.10.2.orig/src/cppunit/SubunitTestProgressListener.cpp -+++ cppunit-1.10.2/src/cppunit/SubunitTestProgressListener.cpp -@@ -0,0 +1,50 @@ -+#include <cppunit/Exception.h> -+#include <cppunit/Test.h> -+#include <cppunit/TestFailure.h> -+#include <cppunit/SubunitTestProgressListener.h> -+#include <cppunit/TextOutputter.h> -+#include <iostream> -+ -+#include "config.h" -+#ifdef HAVE_LIBSUBUNIT -+#include <subunit/child.h> -+ -+ -+CPPUNIT_NS_BEGIN -+ -+ -+void -+SubunitTestProgressListener::startTest( Test *test ) -+{ -+ subunit_test_start(test->getName().c_str()); -+ last_test_failed = false; -+} -+ -+void -+SubunitTestProgressListener::addFailure( const TestFailure &failure ) -+{ -+ std::ostringstream capture_stream; -+ TextOutputter outputter(NULL, capture_stream); -+ outputter.printFailureLocation(failure.sourceLine()); -+ outputter.printFailureDetail(failure.thrownException()); -+ -+ if (failure.isError()) -+ subunit_test_error(failure.failedTestName().c_str(), -+ capture_stream.str().c_str()); -+ else -+ subunit_test_fail(failure.failedTestName().c_str(), -+ capture_stream.str().c_str()); -+ last_test_failed = true; -+} -+ -+void -+SubunitTestProgressListener::endTest( Test *test) -+{ -+ if (!last_test_failed) -+ subunit_test_pass(test->getName().c_str()); -+} -+ -+ -+CPPUNIT_NS_END -+ -+#endif ---- cppunit-1.10.2.orig/configure.in -+++ cppunit-1.10.2/configure.in -@@ -65,6 +65,8 @@ - # check for doxygen - BB_ENABLE_DOXYGEN - -+# check for subunit -+AC_CHECK_LIB(subunit, subunit_test_start) - - # Check for headers - # Note that the fourth argument to AC_CHECK_HEADERS is non-empty to force ---- cppunit-1.10.2.orig/include/cppunit/Makefile.am -+++ cppunit-1.10.2/include/cppunit/Makefile.am -@@ -15,6 +15,7 @@ - Portability.h \ - Protector.h \ - SourceLine.h \ -+ SubunitTestProgressListener.h \ - SynchronizedObject.h \ - Test.h \ - TestAssert.h \ -only in patch2: -unchanged: ---- cppunit-1.10.2.orig/include/cppunit/SubunitTestProgressListener.h -+++ cppunit-1.10.2/include/cppunit/SubunitTestProgressListener.h -@@ -0,0 +1,41 @@ -+#ifndef CPPUNIT_SUBUNITTESTPROGRESSLISTENER_H -+#define CPPUNIT_SUBUNITTESTPROGRESSLISTENER_H -+ -+#include <cppunit/TestListener.h> -+ -+ -+CPPUNIT_NS_BEGIN -+ -+ -+/*! -+ * \brief TestListener that outputs subunit -+ * (http://www.robertcollins.net/unittest/subunit) compatible output. -+ * \ingroup TrackingTestExecution -+ */ -+class CPPUNIT_API SubunitTestProgressListener : public TestListener -+{ -+public: -+ -+ SubunitTestProgressListener() {} -+ -+ void startTest( Test *test ); -+ -+ void addFailure( const TestFailure &failure ); -+ -+ void endTest( Test *test ); -+ -+private: -+ /// Prevents the use of the copy constructor. -+ SubunitTestProgressListener( const SubunitTestProgressListener © ); -+ -+ /// Prevents the use of the copy operator. -+ void operator =( const SubunitTestProgressListener © ); -+ -+private: -+ int last_test_failed; -+}; -+ -+ -+CPPUNIT_NS_END -+ -+#endif // CPPUNIT_SUBUNITTESTPROGRESSLISTENER_H diff --git a/c/include/subunit/child.h b/c/include/subunit/child.h index 7fab7b5..0a4e601 100644 --- a/c/include/subunit/child.h +++ b/c/include/subunit/child.h @@ -62,6 +62,18 @@ extern void subunit_test_error(char const * const name, char const * const error); +/** + * subunit_test_skip: + * + * Report that a test has been skipped. An skip is a test that has not run to + * conclusion but hasn't given an error either - its result is unknown. + * @name: test case name + * @reason: a string describing the reason for the skip. + */ +extern void subunit_test_skip(char const * const name, + char const * const reason); + + #ifdef __cplusplus } #endif diff --git a/c/lib/child.c b/c/lib/child.c index 872a868..2b59747 100644 --- a/c/lib/child.c +++ b/c/lib/child.c @@ -19,6 +19,28 @@ #include <string.h> #include "subunit/child.h" +/* Write details about a test event. It is the callers responsibility to ensure + * that details are only provided for events the protocol expects details on. + * @event: The event - e.g. 'skip' + * @name: The test name/id. + * @details: The details of the event, may be NULL if no details are present. + */ +static void +subunit_send_event(char const * const event, char const * const name, + char const * const details) +{ + if (NULL == details) { + fprintf(stdout, "%s: %s\n", event, name); + } else { + fprintf(stdout, "%s: %s [\n", event, name); + fprintf(stdout, "%s", details); + if (details[strlen(details) - 1] != '\n') + fprintf(stdout, "\n"); + fprintf(stdout, "]\n"); + } + fflush(stdout); +} + /* these functions all flush to ensure that the test runner knows the action * that has been taken even if the subsequent test etc takes a long time or * never completes (i.e. a segfault). @@ -27,38 +49,34 @@ void subunit_test_start(char const * const name) { - fprintf(stdout, "test: %s\n", name); - fflush(stdout); + subunit_send_event("test", name, NULL); } void subunit_test_pass(char const * const name) { - fprintf(stdout, "success: %s\n", name); - fflush(stdout); + /* TODO: add success details as an option */ + subunit_send_event("success", name, NULL); } void subunit_test_fail(char const * const name, char const * const error) { - fprintf(stdout, "failure: %s [\n", name); - fprintf(stdout, "%s", error); - if (error[strlen(error) - 1] != '\n') - fprintf(stdout, "\n"); - fprintf(stdout, "]\n"); - fflush(stdout); + subunit_send_event("failure", name, error); } void subunit_test_error(char const * const name, char const * const error) { - fprintf(stdout, "error: %s [\n", name); - fprintf(stdout, "%s", error); - if (error[strlen(error) - 1] != '\n') - fprintf(stdout, "\n"); - fprintf(stdout, "]\n"); - fflush(stdout); + subunit_send_event("error", name, error); +} + + +void +subunit_test_skip(char const * const name, char const * const reason) +{ + subunit_send_event("skip", name, reason); } diff --git a/c/tests/test_child.c b/c/tests/test_child.c index f2b2845..6399eeb 100644 --- a/c/tests/test_child.c +++ b/c/tests/test_child.c @@ -146,6 +146,24 @@ START_TEST (test_error) } END_TEST + +static void +call_test_skip(void) +{ + subunit_test_skip("test case", "Multiple lines\n of output\n"); +} + + +START_TEST (test_skip) +{ + test_stdout_function("skip: test case [\n" + "Multiple lines\n" + " of output\n" + "]\n", + call_test_skip); +} +END_TEST + static Suite * child_suite(void) { @@ -156,6 +174,7 @@ child_suite(void) tcase_add_test (tc_core, test_pass); tcase_add_test (tc_core, test_fail); tcase_add_test (tc_core, test_error); + tcase_add_test (tc_core, test_skip); return s; } diff --git a/configure.ac b/configure.ac index f950717..76a91a4 100644 --- a/configure.ac +++ b/configure.ac @@ -18,6 +18,7 @@ AC_SUBST([SUBUNIT_MICRO_VERSION]) AC_SUBST([SUBUNIT_VERSION]) AC_USE_SYSTEM_EXTENSIONS AC_PROG_CC +AC_PROG_CXX AM_PROG_CC_C_O AC_PROG_INSTALL AC_PROG_LN_S @@ -46,11 +47,14 @@ AC_FUNC_REALLOC # Easier memory management. # C unit testing. PKG_CHECK_MODULES([CHECK], [check >= 0.9.4]) +# C++ unit testing. +PKG_CHECK_MODULES([CPPUNIT], [cppunit]) # Output files AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([libsubunit.pc + libcppunit_subunit.pc Makefile perl/Makefile.PL ]) diff --git a/libcppunit_subunit.pc.in b/libcppunit_subunit.pc.in new file mode 100644 index 0000000..98982c7 --- /dev/null +++ b/libcppunit_subunit.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: cppunit subunit listener +Description: Subunit output listener for the CPPUnit test library. +URL: http://launchpad.net/subunit +Version: @VERSION@ +Libs: -L${libdir} -lsubunit +Cflags: -I${includedir} diff --git a/python/subunit/__init__.py b/python/subunit/__init__.py index 5b482e3..f06437c 100644 --- a/python/subunit/__init__.py +++ b/python/subunit/__init__.py @@ -1152,4 +1152,3 @@ class TestResultFilter(unittest.TestResult): if id.startswith("subunit.RemotedTestCase."): return id[len("subunit.RemotedTestCase."):] return id - |
