summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Collins <robertc@robertcollins.net>2009-10-10 12:19:17 +1100
committerRobert Collins <robertc@robertcollins.net>2009-10-10 12:19:17 +1100
commit6796be6ea3f0d8795fee7ab364a24f0e5678ffbb (patch)
tree177d77c187285aa0748f191a0b26230241c312b0
parentcc36797e0831ed019dbfb4b37b33636f5c25abfa (diff)
parenta3c2c3bff21e7db30002824843dc0bc954ad6d6d (diff)
downloadsubunit-git-6796be6ea3f0d8795fee7ab364a24f0e5678ffbb.tar.gz
Merge trunk to resolve NEWS.
-rw-r--r--.bzrignore2
-rw-r--r--Makefile.am19
-rw-r--r--NEWS5
-rw-r--r--README5
-rw-r--r--c++/README59
-rw-r--r--c++/SubunitTestProgressListener.cpp63
-rw-r--r--c++/SubunitTestProgressListener.h56
-rw-r--r--c++/cppunit-subunit-1.10.2.patch134
-rw-r--r--c/include/subunit/child.h12
-rw-r--r--c/lib/child.c50
-rw-r--r--c/tests/test_child.c19
-rw-r--r--configure.ac4
-rw-r--r--libcppunit_subunit.pc.in11
-rw-r--r--python/subunit/__init__.py1
14 files changed, 251 insertions, 189 deletions
diff --git a/.bzrignore b/.bzrignore
index 59334ac..ac34aa1 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -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)
diff --git a/NEWS b/NEWS
index ce6a3e3..1cef756 100644
--- a/NEWS
+++ b/NEWS
@@ -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.
diff --git a/README b/README
index 3f15c03..7dbc5a0 100644
--- a/README
+++ b/README
@@ -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
=====
diff --git a/c++/README b/c++/README
index 3fd085c..7b81844 100644
--- a/c++/README
+++ b/c++/README
@@ -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 &copy );
+
+ /// Prevents the use of the copy operator.
+ void operator =( const SubunitTestProgressListener &copy );
+
+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 &copy );
-+
-+ /// Prevents the use of the copy operator.
-+ void operator =( const SubunitTestProgressListener &copy );
-+
-+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
-