First commit for GitHub
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d3a1e13
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+Test/build
+*.pbxuser
+*.mode1v3
diff --git a/LICENSE_1_0.txt b/LICENSE_1_0.txt
new file mode 100644
index 0000000..1dad8e9
--- /dev/null
+++ b/LICENSE_1_0.txt
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/README b/README
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/README
diff --git a/Test/ClassTests.cpp b/Test/ClassTests.cpp
new file mode 100644
index 0000000..9dd7147
--- /dev/null
+++ b/Test/ClassTests.cpp
@@ -0,0 +1,37 @@
+/*
+ * ClassTests.cpp
+ * Catch - Test
+ *
+ * Created by Phil on 09/11/2010.
+ * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#include "catch.hpp"
+
+namespace
+{
+ class TestClass
+ {
+ std::string s;
+
+ public:
+ TestClass()
+ : s( "hello" )
+ {}
+
+ void succeedingCase()
+ {
+ EXPECT( s == "hello" );
+ }
+ void failingCase()
+ {
+ EXPECT( s == "world" );
+ }
+ };
+}
+METHOD_AS_TEST_CASE( TestClass::succeedingCase, "succeeding/TestClass/succeedingCase", "A method based test run that succeeds" );
+METHOD_AS_TEST_CASE( TestClass::failingCase, "failing/TestClass/failingCase", "A method based test run that fails" );
diff --git a/Test/ConditionTests.cpp b/Test/ConditionTests.cpp
new file mode 100644
index 0000000..b310681
--- /dev/null
+++ b/Test/ConditionTests.cpp
@@ -0,0 +1,185 @@
+/*
+ * ConditionTests.cpp
+ * Catch - Test
+ *
+ * Created by Phil on 08/11/2010.
+ * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#include "catch.hpp"
+
+#include <string>
+
+struct TestData
+{
+ TestData()
+ : int_seven( 7 ),
+ str_hello( "hello" ),
+ float_nine_point_one( 9.1f ),
+ double_pi( 3.1415926535 )
+ {}
+
+ int int_seven;
+ std::string str_hello;
+ float float_nine_point_one;
+ double double_pi;
+};
+
+// These tests all use the CHECK macro, which continues if the specific test fails.
+// This allows us to see all results, even if an earlier check fails - which is
+// particularly important for the "should fail" checks
+
+// Equality tests
+TEST_CASE( "succeeding/conditions/equality", "Equality checks that should succeed" )
+{
+ TestData data;
+
+ CHECK( data.int_seven == 7 );
+ CHECK( data.float_nine_point_one == Approx( 9.1f ) );
+ CHECK( data.double_pi == Approx( 3.1415926535 ) );
+ CHECK( data.str_hello == "hello" );
+ CHECK( data.str_hello.size() == 5 );
+
+ double x = 1.1 + 0.1 + 0.1;
+ CHECK( x == Approx( 1.3 ) );
+}
+
+TEST_CASE( "failing/conditions/equality", "Equality checks that should fail" )
+{
+ TestData data;
+
+ CHECK( data.int_seven == 6 );
+ CHECK( data.int_seven == 8 );
+ CHECK( data.int_seven == 0 );
+ CHECK( data.float_nine_point_one == Approx( 9.11f ) );
+ CHECK( data.float_nine_point_one == Approx( 9.0f ) );
+ CHECK( data.float_nine_point_one == 1 );
+ CHECK( data.float_nine_point_one == 0 );
+ CHECK( data.double_pi == Approx( 3.1415 ) );
+ CHECK( data.str_hello == "goodbye" );
+ CHECK( data.str_hello == "hell" );
+ CHECK( data.str_hello == "hello1" );
+ CHECK( data.str_hello.size() == 6 );
+
+ double x = 1.1 + 0.1 + 0.1;
+ CHECK( x == Approx( 1.301 ) );
+}
+
+TEST_CASE( "succeeding/conditions/inequality", "Inequality checks that should succeed" )
+{
+ TestData data;
+
+ CHECK( data.int_seven != 6 );
+ CHECK( data.int_seven != 8 );
+ CHECK( data.float_nine_point_one != Approx( 9.11f ) );
+ CHECK( data.float_nine_point_one != Approx( 9.0f ) );
+ CHECK( data.float_nine_point_one != 1 );
+ CHECK( data.float_nine_point_one != 0 );
+ CHECK( data.double_pi != Approx( 3.1415 ) );
+ CHECK( data.str_hello != "goodbye" );
+ CHECK( data.str_hello != "hell" );
+ CHECK( data.str_hello != "hello1" );
+ CHECK( data.str_hello.size() != 6 );
+}
+
+TEST_CASE( "failing/conditions/inequality", "Inequality checks that should fails" )
+{
+ TestData data;
+
+ CHECK( data.int_seven != 7 );
+ CHECK( data.float_nine_point_one != Approx( 9.1f ) );
+ CHECK( data.double_pi != Approx( 3.1415926535 ) );
+ CHECK( data.str_hello != "hello" );
+ CHECK( data.str_hello.size() != 5 );
+}
+
+// Ordering comparison tests
+TEST_CASE( "succeeding/conditions/ordered", "Ordering comparison checks that should succeed" )
+{
+ TestData data;
+
+ CHECK( data.int_seven < 8 );
+ CHECK( data.int_seven > 6 );
+ CHECK( data.int_seven > 0 );
+ CHECK( data.int_seven > -1 );
+
+ CHECK( data.int_seven >= 7 );
+ CHECK( data.int_seven >= 6 );
+ CHECK( data.int_seven <= 7 );
+ CHECK( data.int_seven <= 8 );
+
+ CHECK( data.float_nine_point_one > 9 );
+ CHECK( data.float_nine_point_one < 10 );
+ CHECK( data.float_nine_point_one < 9.2 );
+
+ CHECK( data.str_hello <= "hello" );
+ CHECK( data.str_hello >= "hello" );
+
+ CHECK( data.str_hello < "hellp" );
+ CHECK( data.str_hello < "z" );
+ CHECK( data.str_hello > "hellm" );
+ CHECK( data.str_hello > "a" );
+}
+
+TEST_CASE( "failing/conditions/ordered", "Ordering comparison checks that should fail" )
+{
+ TestData data;
+
+ CHECK( data.int_seven > 7 );
+ CHECK( data.int_seven < 7 );
+ CHECK( data.int_seven > 8 );
+ CHECK( data.int_seven < 6 );
+ CHECK( data.int_seven < 0 );
+ CHECK( data.int_seven < -1 );
+
+ CHECK( data.int_seven >= 8 );
+ CHECK( data.int_seven <= 6 );
+
+ CHECK( data.float_nine_point_one < 9 );
+ CHECK( data.float_nine_point_one > 10 );
+ CHECK( data.float_nine_point_one > 9.2 );
+
+ CHECK( data.str_hello > "hello" );
+ CHECK( data.str_hello < "hello" );
+ CHECK( data.str_hello > "hellp" );
+ CHECK( data.str_hello > "z" );
+ CHECK( data.str_hello < "hellm" );
+ CHECK( data.str_hello < "a" );
+
+ CHECK( data.str_hello >= "z" );
+ CHECK( data.str_hello <= "a" );
+}
+
+// Not (!) tests
+TEST_CASE( "succeeding/conditions/not", "'Not' checks that should succeed" )
+{
+ bool falseValue = false;
+
+ CHECK( !false );
+ CHECK_NOT( false );
+
+ CHECK( !falseValue );
+ CHECK_NOT( falseValue );
+
+ CHECK( !(1 == 2) );
+ CHECK_NOT( 1 == 2 );
+}
+
+TEST_CASE( "failing/conditions/not", "'Not' checks that should fail" )
+{
+ bool trueValue = true;
+
+ CHECK( !true );
+ CHECK_NOT( true );
+
+ CHECK( !trueValue );
+ CHECK_NOT( trueValue );
+
+ CHECK( !(1 == 1) );
+ CHECK_NOT( 1 == 1 );
+}
+
diff --git a/Test/ExceptionTests.cpp b/Test/ExceptionTests.cpp
new file mode 100644
index 0000000..3bb222e
--- /dev/null
+++ b/Test/ExceptionTests.cpp
@@ -0,0 +1,58 @@
+/*
+ * ExceptionTests.cpp
+ * Catch - Test
+ *
+ * Created by Phil on 09/11/2010.
+ * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#include "catch.hpp"
+
+#include <string>
+
+namespace
+{
+ int thisThrows()
+ {
+ throw std::domain_error( "expected exception" );
+ }
+
+ int thisDoesntThrow()
+ {
+ return 0;
+ }
+}
+
+TEST_CASE( "succeeding/exceptions/explicit", "When checked exceptions are thrown they can be expected or unexpected" )
+{
+ CHECK_THROWS_AS( thisThrows(), std::domain_error );
+ CHECK_NOTHROW( thisDoesntThrow() );
+ EXPECT_THROWS( thisThrows() );
+}
+
+TEST_CASE( "failing/exceptions/explicit", "When checked exceptions are thrown they can be expected or unexpected" )
+{
+ CHECK_THROWS_AS( thisThrows(), std::string );
+ CHECK_THROWS_AS( thisDoesntThrow(), std::domain_error );
+ CHECK_NOTHROW( thisThrows() );
+}
+
+TEST_CASE( "failing/exceptions/implicit", "When unchecked exceptions are thrown they are always failures" )
+{
+ throw std::domain_error( "unexpected exception" );
+}
+
+TEST_CASE( "succeeding/exceptions/implicit", "When unchecked exceptions are thrown, but caught, they do not affect the test" )
+{
+ try
+ {
+ throw std::domain_error( "unexpected exception" );
+ }
+ catch(...)
+ {
+ }
+}
diff --git a/Test/MessageTests.cpp b/Test/MessageTests.cpp
new file mode 100644
index 0000000..be62f05
--- /dev/null
+++ b/Test/MessageTests.cpp
@@ -0,0 +1,24 @@
+/*
+ * MessageTests.cpp
+ * Catch - Test
+ *
+ * Created by Phil on 09/11/2010.
+ * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#include "catch.hpp"
+
+TEST_CASE( "succeeding/message", "INFO and WARN do not abort tests" )
+{
+ INFO( "this is a message" ); // This should output the message but continue
+ WARN( "this is a warning" ); // This should output the message but continue
+}
+
+TEST_CASE( "failing/message", "FAIL aborts the test" )
+{
+ FAIL( "This is a failure" ); // This should output the message and abort
+}
\ No newline at end of file
diff --git a/Test/Test.1 b/Test/Test.1
new file mode 100644
index 0000000..69da656
--- /dev/null
+++ b/Test/Test.1
@@ -0,0 +1,79 @@
+.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples.
+.\"See Also:
+.\"man mdoc.samples for a complete listing of options
+.\"man mdoc for the short list of editing options
+.\"/usr/share/misc/mdoc.template
+.Dd 02/11/2010 \" DATE
+.Dt Test 1 \" Program name and manual section number
+.Os Darwin
+.Sh NAME \" Section Header - required - don't modify
+.Nm Test,
+.\" The following lines are read in generating the apropos(man -k) database. Use only key
+.\" words here as the database is built based on the words here and in the .ND line.
+.Nm Other_name_for_same_program(),
+.Nm Yet another name for the same program.
+.\" Use .Nm macro to designate other names for the documented program.
+.Nd This line parsed for whatis database.
+.Sh SYNOPSIS \" Section Header - required - don't modify
+.Nm
+.Op Fl abcd \" [-abcd]
+.Op Fl a Ar path \" [-a path]
+.Op Ar file \" [file]
+.Op Ar \" [file ...]
+.Ar arg0 \" Underlined argument - use .Ar anywhere to underline
+arg2 ... \" Arguments
+.Sh DESCRIPTION \" Section Header - required - don't modify
+Use the .Nm macro to refer to your program throughout the man page like such:
+.Nm
+Underlining is accomplished with the .Ar macro like this:
+.Ar underlined text .
+.Pp \" Inserts a space
+A list of items with descriptions:
+.Bl -tag -width -indent \" Begins a tagged list
+.It item a \" Each item preceded by .It macro
+Description of item a
+.It item b
+Description of item b
+.El \" Ends the list
+.Pp
+A list of flags and their descriptions:
+.Bl -tag -width -indent \" Differs from above in tag removed
+.It Fl a \"-a flag as a list item
+Description of -a flag
+.It Fl b
+Description of -b flag
+.El \" Ends the list
+.Pp
+.\" .Sh ENVIRONMENT \" May not be needed
+.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1
+.\" .It Ev ENV_VAR_1
+.\" Description of ENV_VAR_1
+.\" .It Ev ENV_VAR_2
+.\" Description of ENV_VAR_2
+.\" .El
+.Sh FILES \" File used or created by the topic of the man page
+.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact
+.It Pa /usr/share/file_name
+FILE_1 description
+.It Pa /Users/joeuser/Library/really_long_file_name
+FILE_2 description
+.El \" Ends the list
+.\" .Sh DIAGNOSTICS \" May not be needed
+.\" .Bl -diag
+.\" .It Diagnostic Tag
+.\" Diagnostic informtion here.
+.\" .It Diagnostic Tag
+.\" Diagnostic informtion here.
+.\" .El
+.Sh SEE ALSO
+.\" List links in ascending order by section, alphabetically within a section.
+.\" Please do not reference files that do not exist without filing a bug report
+.Xr a 1 ,
+.Xr b 1 ,
+.Xr c 1 ,
+.Xr a 2 ,
+.Xr b 2 ,
+.Xr a 3 ,
+.Xr b 3
+.\" .Sh BUGS \" Document known, unremedied bugs
+.\" .Sh HISTORY \" Document history if command behaves in a unique manner
\ No newline at end of file
diff --git a/Test/Test.xcodeproj/project.pbxproj b/Test/Test.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..1113be1
--- /dev/null
+++ b/Test/Test.xcodeproj/project.pbxproj
@@ -0,0 +1,271 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 4AFC340C128099F5003A0C29 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AFC340B128099F5003A0C29 /* main.cpp */; };
+ 4AFC38CD12887D80003A0C29 /* ConditionTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AFC38CC12887D80003A0C29 /* ConditionTests.cpp */; };
+ 4AFC3A9912893C56003A0C29 /* ExceptionTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AFC3A9812893C56003A0C29 /* ExceptionTests.cpp */; };
+ 4AFC3AA912893E54003A0C29 /* MessageTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AFC3AA812893E54003A0C29 /* MessageTests.cpp */; };
+ 4AFC3B0B12894114003A0C29 /* ClassTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AFC3B0A12894114003A0C29 /* ClassTests.cpp */; };
+ 4AFC3B671289C7E3003A0C29 /* TrickyTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4AFC3B661289C7E3003A0C29 /* TrickyTests.cpp */; };
+ 8DD76F6A0486A84900D96B5E /* Test.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6859E8B029090EE04C91782 /* Test.1 */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 8DD76F690486A84900D96B5E /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 8;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ 8DD76F6A0486A84900D96B5E /* Test.1 in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 4AFC340B128099F5003A0C29 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
+ 4AFC341512809A36003A0C29 /* catch_capture.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_capture.hpp; path = ../internal/catch_capture.hpp; sourceTree = SOURCE_ROOT; };
+ 4AFC341612809A36003A0C29 /* catch_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = catch_common.h; path = ../internal/catch_common.h; sourceTree = SOURCE_ROOT; };
+ 4AFC341712809A36003A0C29 /* catch_registry.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_registry.hpp; path = ../internal/catch_registry.hpp; sourceTree = SOURCE_ROOT; };
+ 4AFC341812809A36003A0C29 /* catch_reporter_registry.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_reporter_registry.hpp; path = ../internal/catch_reporter_registry.hpp; sourceTree = SOURCE_ROOT; };
+ 4AFC341912809A36003A0C29 /* catch_resultinfo.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_resultinfo.hpp; path = ../internal/catch_resultinfo.hpp; sourceTree = SOURCE_ROOT; };
+ 4AFC341A12809A36003A0C29 /* catch_runner_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_runner_impl.hpp; path = ../internal/catch_runner_impl.hpp; sourceTree = SOURCE_ROOT; };
+ 4AFC341B12809A36003A0C29 /* catch_testcaseinfo.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_testcaseinfo.hpp; path = ../internal/catch_testcaseinfo.hpp; sourceTree = SOURCE_ROOT; };
+ 4AFC341C12809A45003A0C29 /* catch_default_main.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_default_main.hpp; path = ../catch_default_main.hpp; sourceTree = SOURCE_ROOT; };
+ 4AFC341D12809A45003A0C29 /* catch_reporter_basic.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_reporter_basic.hpp; path = ../catch_reporter_basic.hpp; sourceTree = SOURCE_ROOT; };
+ 4AFC341E12809A45003A0C29 /* catch_reporter_xml.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_reporter_xml.hpp; path = ../catch_reporter_xml.hpp; sourceTree = SOURCE_ROOT; };
+ 4AFC341F12809A45003A0C29 /* catch_list.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_list.hpp; path = ../internal/catch_list.hpp; sourceTree = SOURCE_ROOT; };
+ 4AFC342012809A45003A0C29 /* catch.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch.hpp; path = ../catch.hpp; sourceTree = SOURCE_ROOT; };
+ 4AFC346412809D41003A0C29 /* catch_commandline.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_commandline.hpp; path = ../internal/catch_commandline.hpp; sourceTree = SOURCE_ROOT; };
+ 4AFC359B1281F00B003A0C29 /* catch_section.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_section.hpp; path = ../internal/catch_section.hpp; sourceTree = SOURCE_ROOT; };
+ 4AFC38161284B387003A0C29 /* catch_runner.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_runner.hpp; path = ../catch_runner.hpp; sourceTree = SOURCE_ROOT; };
+ 4AFC384F1287E33E003A0C29 /* catch_runnerconfig.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_runnerconfig.hpp; path = ../catch_runnerconfig.hpp; sourceTree = SOURCE_ROOT; };
+ 4AFC38CC12887D80003A0C29 /* ConditionTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConditionTests.cpp; sourceTree = "<group>"; };
+ 4AFC3A9812893C56003A0C29 /* ExceptionTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExceptionTests.cpp; sourceTree = "<group>"; };
+ 4AFC3AA812893E54003A0C29 /* MessageTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MessageTests.cpp; sourceTree = "<group>"; };
+ 4AFC3B0A12894114003A0C29 /* ClassTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClassTests.cpp; sourceTree = "<group>"; };
+ 4AFC3B661289C7E3003A0C29 /* TrickyTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrickyTests.cpp; sourceTree = "<group>"; };
+ 8DD76F6C0486A84900D96B5E /* Test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Test; sourceTree = BUILT_PRODUCTS_DIR; };
+ C6859E8B029090EE04C91782 /* Test.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = Test.1; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8DD76F660486A84900D96B5E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 08FB7794FE84155DC02AAC07 /* Test */ = {
+ isa = PBXGroup;
+ children = (
+ 08FB7795FE84155DC02AAC07 /* Source */,
+ C6859E8C029090F304C91782 /* Documentation */,
+ 1AB674ADFE9D54B511CA2CBB /* Products */,
+ );
+ name = Test;
+ sourceTree = "<group>";
+ };
+ 08FB7795FE84155DC02AAC07 /* Source */ = {
+ isa = PBXGroup;
+ children = (
+ 4AFC341312809A12003A0C29 /* Catch */,
+ 4AFC340B128099F5003A0C29 /* main.cpp */,
+ 4AFC38CC12887D80003A0C29 /* ConditionTests.cpp */,
+ 4AFC3A9812893C56003A0C29 /* ExceptionTests.cpp */,
+ 4AFC3AA812893E54003A0C29 /* MessageTests.cpp */,
+ 4AFC3B0A12894114003A0C29 /* ClassTests.cpp */,
+ 4AFC3B661289C7E3003A0C29 /* TrickyTests.cpp */,
+ );
+ name = Source;
+ sourceTree = "<group>";
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8DD76F6C0486A84900D96B5E /* Test */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 4AFC341312809A12003A0C29 /* Catch */ = {
+ isa = PBXGroup;
+ children = (
+ 4AFC342012809A45003A0C29 /* catch.hpp */,
+ 4AFC341C12809A45003A0C29 /* catch_default_main.hpp */,
+ 4AFC341D12809A45003A0C29 /* catch_reporter_basic.hpp */,
+ 4AFC341E12809A45003A0C29 /* catch_reporter_xml.hpp */,
+ 4AFC38161284B387003A0C29 /* catch_runner.hpp */,
+ 4AFC341412809A1B003A0C29 /* Internal */,
+ );
+ name = Catch;
+ sourceTree = "<group>";
+ };
+ 4AFC341412809A1B003A0C29 /* Internal */ = {
+ isa = PBXGroup;
+ children = (
+ 4AFC341F12809A45003A0C29 /* catch_list.hpp */,
+ 4AFC359B1281F00B003A0C29 /* catch_section.hpp */,
+ 4AFC346412809D41003A0C29 /* catch_commandline.hpp */,
+ 4AFC341512809A36003A0C29 /* catch_capture.hpp */,
+ 4AFC341612809A36003A0C29 /* catch_common.h */,
+ 4AFC341712809A36003A0C29 /* catch_registry.hpp */,
+ 4AFC341812809A36003A0C29 /* catch_reporter_registry.hpp */,
+ 4AFC341912809A36003A0C29 /* catch_resultinfo.hpp */,
+ 4AFC341A12809A36003A0C29 /* catch_runner_impl.hpp */,
+ 4AFC341B12809A36003A0C29 /* catch_testcaseinfo.hpp */,
+ 4AFC384F1287E33E003A0C29 /* catch_runnerconfig.hpp */,
+ );
+ name = Internal;
+ sourceTree = "<group>";
+ };
+ C6859E8C029090F304C91782 /* Documentation */ = {
+ isa = PBXGroup;
+ children = (
+ C6859E8B029090EE04C91782 /* Test.1 */,
+ );
+ name = Documentation;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 8DD76F620486A84900D96B5E /* Test */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "Test" */;
+ buildPhases = (
+ 8DD76F640486A84900D96B5E /* Sources */,
+ 8DD76F660486A84900D96B5E /* Frameworks */,
+ 8DD76F690486A84900D96B5E /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Test;
+ productInstallPath = "$(HOME)/bin";
+ productName = Test;
+ productReference = 8DD76F6C0486A84900D96B5E /* Test */;
+ productType = "com.apple.product-type.tool";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "Test" */;
+ compatibilityVersion = "Xcode 3.1";
+ hasScannedForEncodings = 1;
+ mainGroup = 08FB7794FE84155DC02AAC07 /* Test */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 8DD76F620486A84900D96B5E /* Test */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8DD76F640486A84900D96B5E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4AFC340C128099F5003A0C29 /* main.cpp in Sources */,
+ 4AFC38CD12887D80003A0C29 /* ConditionTests.cpp in Sources */,
+ 4AFC3A9912893C56003A0C29 /* ExceptionTests.cpp in Sources */,
+ 4AFC3AA912893E54003A0C29 /* MessageTests.cpp in Sources */,
+ 4AFC3B0B12894114003A0C29 /* ClassTests.cpp in Sources */,
+ 4AFC3B671289C7E3003A0C29 /* TrickyTests.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB923208733DC60010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ INSTALL_PATH = /usr/local/bin;
+ PRODUCT_NAME = Test;
+ };
+ name = Debug;
+ };
+ 1DEB923308733DC60010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PRODUCT_NAME = Test;
+ };
+ name = Release;
+ };
+ 1DEB923608733DC60010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ PREBINDING = NO;
+ SDKROOT = macosx10.6;
+ };
+ name = Debug;
+ };
+ 1DEB923708733DC60010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ PREBINDING = NO;
+ SDKROOT = macosx10.6;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "Test" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB923208733DC60010E9CD /* Debug */,
+ 1DEB923308733DC60010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "Test" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB923608733DC60010E9CD /* Debug */,
+ 1DEB923708733DC60010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/Test/TrickyTests.cpp b/Test/TrickyTests.cpp
new file mode 100644
index 0000000..51ee889
--- /dev/null
+++ b/Test/TrickyTests.cpp
@@ -0,0 +1,34 @@
+/*
+ * TrickyTests.cpp
+ * Catch - Test
+ *
+ * Created by Phil on 09/11/2010.
+ * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#include "catch.hpp"
+
+namespace Catch
+{
+ template<>
+ std::string toString<std::pair<int, int> >( const std::pair<int, int>& value )
+ {
+ std::ostringstream oss;
+ oss << "std::pair( " << value.first << ", " << value.second << " )";
+ return oss.str();
+
+ }
+}
+
+TEST_CASE( "succeeding/Tricky", "Some tricky to parse tests" )
+{
+ std::pair<int, int> aNicePair( 1, 2 );
+
+ // !TBD: would be nice if this could compile without the extra parentheses
+ EXPECT( (std::pair<int, int>( 1, 2 )) == aNicePair );
+
+}
\ No newline at end of file
diff --git a/Test/main.cpp b/Test/main.cpp
new file mode 100644
index 0000000..ee0806e
--- /dev/null
+++ b/Test/main.cpp
@@ -0,0 +1,53 @@
+/*
+ * main.cpp
+ * Catch - Test
+ *
+ * Created by Phil on 22/10/2010.
+ * Copyright 2010 Two Blue Cubes Ltd
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#include "catch.hpp"
+#include "catch_runner.hpp"
+
+// This code runs the meta tests and verifies that the failing ones failed and the successful ones succeeded
+int main (int argc, char * const argv[])
+{
+ using namespace Catch;
+
+ ReporterConfig reporterConfig( ReporterConfig::Include::SuccessfulResults );
+ BasicReporter reporter (reporterConfig );
+ Runner runner;
+ runner.setReporter( &reporter );
+
+ std::ostringstream ossSucceeding;
+ reporterConfig.setStreamBuf( ossSucceeding.rdbuf() );
+ runner.runMatching( "succeeding/*" );
+ std::string succeedingResults = ossSucceeding.str();
+
+ std::ostringstream ossFailing;
+ reporterConfig.setStreamBuf( ossFailing.rdbuf() );
+ runner.runMatching( "failing/*" );
+ std::string failingResults = ossFailing.str();
+
+ int result = 0;
+ if( succeedingResults.find( "failed" ) != std::string::npos )
+ {
+ std::cerr << "Some tests that should have succeeded failed:\n\n" << succeedingResults;
+ result = 1;
+ }
+ if( failingResults.find( "succeeded" ) != std::string::npos )
+ {
+ std::cerr << "Some tests that should have failed succeeded:\n\n" << failingResults;
+ result = 1;
+ }
+
+ if( result == 0 )
+ {
+ std::cout << "All tests completed successfully" << std::endl;
+ }
+ return result;
+}
diff --git a/catch.hpp b/catch.hpp
new file mode 100644
index 0000000..5bbd469
--- /dev/null
+++ b/catch.hpp
@@ -0,0 +1,65 @@
+/*
+ * catch.hpp
+ * Catch
+ *
+ * Created by Phil on 22/10/2010.
+ * Copyright 2010 Two Blue Cubes Ltd
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+/* TBD:
+
+ Next:
+
+ Later:
+ Finish command line parser (list as xml, specify FP tolerance)
+ INFO() stores messages until next result
+ Revisit Approx()
+ Extra reports
+ Tags?
+ Detect caught "Catch" exception, offer continuation based iteration instead
+ Finish macros, listed here, later (just CHECK_NOFAIL now)
+ */
+#ifndef TWOBLUECUBES_CATCH_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_HPP_INCLUDED
+
+#include "internal/catch_registry.hpp"
+#include "internal/catch_capture.hpp"
+#include "internal/catch_section.hpp"
+
+//////
+
+#define EXPECT( pred ) _CATCH_TEST( pred, false, true, "EXPECT" )
+#define EXPECT_NOT( pred ) _CATCH_TEST( pred, true, true, "EXPECT_NOT" )
+
+#define EXPECT_THROWS( expr ) _CATCH_THROWS( expr, ..., false, true, "EXPECT_THROWS" )
+#define EXPECT_THROWS_AS( expr, exceptionType ) _CATCH_THROWS_AS( expr, exceptionType, false, true, "EXPECT_THROWS_AS" )
+
+#define CHECK( pred ) _CATCH_TEST( pred, false, false, "CHECK" )
+#define CHECK_NOT( pred ) _CATCH_TEST( pred, true, false, "CHECK_NOT" )
+
+#define CHECK_THROWS( expr ) _CATCH_THROWS( expr, ..., false. false, "CHECK_THROWS" )
+#define CHECK_THROWS_AS( expr, exceptionType ) _CATCH_THROWS_AS( expr, exceptionType, false, false, "CHECK_THROWS_AS" )
+#define CHECK_NOTHROW( expr ) _CATCH_THROWS_AS( expr, Catch::DummyExceptionType_DontUse, true, false, "CHECK_NOTHROW" )
+
+#define INFO( reason ) _CATCH_MSG( reason, Catch::ResultWas::Info, false, "INFO" )
+#define WARN( reason ) _CATCH_MSG( reason, Catch::ResultWas::Warning, false, "WARN" )
+#define FAIL( reason ) _CATCH_MSG( reason, Catch::ResultWas::ExplicitFailure, true, "FAIL" )
+
+#define SECTION( name, description ) CATCH_SECTION( name, description )
+
+#define TEST_CASE( name, description ) CATCH_TEST_CASE( name, description )
+#define METHOD_AS_TEST_CASE( method, name, description ) CATCH_METHOD_AS_TEST_CASE( method, name, description )
+
+#define REGISTER_REPORTER( name, reporterType ) CATCH_REGISTER_REPORTER( name, reporterType )
+
+///////////////
+// Still to be implemented
+#define CHECK_NOFAIL( pred ) // !TBD - reports violation, but doesn't fail Test
+
+using Catch::Approx;
+
+#endif // TWOBLUECUBES_CATCH_HPP_INCLUDED
\ No newline at end of file
diff --git a/catch_default_main.hpp b/catch_default_main.hpp
new file mode 100644
index 0000000..a22ac97
--- /dev/null
+++ b/catch_default_main.hpp
@@ -0,0 +1,23 @@
+/*
+ * catch_default_main.hpp
+ * Catch
+ *
+ * Created by Phil on 01/11/2010.
+ * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+#ifndef TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
+
+#include "catch_runner.hpp"
+#include "catch.hpp"
+
+int main (int argc, char * const argv[])
+{
+ return Catch::Main( argc, argv );
+}
+
+#endif // TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
\ No newline at end of file
diff --git a/catch_reporter_basic.hpp b/catch_reporter_basic.hpp
new file mode 100644
index 0000000..bdd52ad
--- /dev/null
+++ b/catch_reporter_basic.hpp
@@ -0,0 +1,99 @@
+/*
+ * catch_reporter_basic.hpp
+ * Catch
+ *
+ * Created by Phil on 28/10/2010.
+ * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+#ifndef TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED
+
+#include "internal/catch_capture.hpp"
+#include "internal/catch_reporter_registry.hpp"
+
+namespace Catch
+{
+ class BasicReporter : public ITestReporter
+ {
+ public:
+ ///////////////////////////////////////////////////////////////////////////
+ BasicReporter( const ReporterConfig& config )
+ : m_config( config )
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ static std::string getDescription()
+ {
+ return "Reports test results as lines of text";
+ }
+
+ private: // ITestReporter
+
+ ///////////////////////////////////////////////////////////////////////////
+ virtual void StartTestCase( const TestCaseInfo& testInfo )
+ {
+ m_config.stream() << std::endl << "[Running: " << testInfo.getName() << "]" << std::endl;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ virtual void Result( const ResultInfo& resultInfo )
+ {
+ if( !m_config.includeSuccessfulResults() && resultInfo.ok() )
+ return;
+
+ if( !resultInfo.getFilename().empty() )
+ m_config.stream() << resultInfo.getFilename() << "(" << resultInfo.getLine() << "): ";
+
+ if( resultInfo.hasExpression() )
+ {
+ m_config.stream() << resultInfo.getExpression();
+ if( resultInfo.ok() )
+ m_config.stream() << " succeeded";
+ else
+ m_config.stream() << " failed";
+ }
+ switch( resultInfo.getResultType() )
+ {
+ case ResultWas::ThrewException:
+ if( resultInfo.hasExpression() )
+ m_config.stream() << " with unexpected";
+ else
+ m_config.stream() << "Unexpected";
+ m_config.stream() << " exception with message: '" << resultInfo.getMessage() << "'";
+ break;
+ case ResultWas::Info:
+ m_config.stream() << "info: '" << resultInfo.getMessage() << "'";
+ break;
+ case ResultWas::Warning:
+ m_config.stream() << "warning: '" << resultInfo.getMessage() << "'";
+ break;
+ case ResultWas::ExplicitFailure:
+ m_config.stream() << "failed with message: '" << resultInfo.getMessage() << "'";
+ break;
+ }
+
+ if( resultInfo.hasExpression() )
+ {
+ m_config.stream() << " for: " << resultInfo.getExpandedExpression();
+ }
+ m_config.stream() << std::endl;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ virtual void EndTestCase( const TestCaseInfo& testInfo )
+ {
+ m_config.stream() << "[Finished: " << testInfo.getName() << "]" << std::endl;
+ }
+
+ private:
+ const ReporterConfig& m_config;
+ };
+
+} // end namespace Catch
+
+#endif // TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED
\ No newline at end of file
diff --git a/catch_reporter_xml.hpp b/catch_reporter_xml.hpp
new file mode 100644
index 0000000..34dd863
--- /dev/null
+++ b/catch_reporter_xml.hpp
@@ -0,0 +1,98 @@
+/*
+ * catch_reporter_xml.hpp
+ * Catch
+ *
+ * Created by Phil on 28/10/2010.
+ * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+#ifndef TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
+
+#include "internal/catch_capture.hpp"
+#include "internal/catch_reporter_registry.hpp"
+#include <iostream>
+
+namespace Catch
+{
+ class XmlReporter : public Catch::ITestReporter
+ {
+ public:
+ ///////////////////////////////////////////////////////////////////////////
+ XmlReporter( const ReporterConfig& config = ReporterConfig() )
+ : m_config( config )
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ static std::string getDescription()
+ {
+ return "Reports test results as an XML document";
+ }
+
+ private: // ITestReporter
+
+ ///////////////////////////////////////////////////////////////////////////
+ virtual void StartTestCase( const Catch::TestCaseInfo& testInfo )
+ {
+ m_config.stream() << "<TestCase name='" << testInfo.getName() << "'>\n";
+ m_currentTestSuccess = true;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ virtual void Result( const Catch::ResultInfo& resultInfo )
+ {
+ if( !m_config.includeSuccessfulResults() && resultInfo.ok() )
+ return;
+
+ if( resultInfo.hasExpression() )
+ {
+ m_config.stream() << "\t<Expression success='" << (resultInfo.ok() ? "true" : "false") << "' "
+ << "filename='" << resultInfo.getFilename() << "' line='" << resultInfo.getLine() << "'>\n"
+ << "\t\t<Original>" << resultInfo.getExpression() << "</Original>\n"
+ << "\t\t<Expanded>" << resultInfo.getExpandedExpression() << "</Expanded>\n";
+ m_currentTestSuccess |= resultInfo.ok();
+ }
+ switch( resultInfo.getResultType() )
+ {
+ case ResultWas::ThrewException:
+ if( resultInfo.hasExpression() )
+ m_config.stream() << "\t";
+ m_config.stream() << "\t<Exception>" << resultInfo.getMessage() << "</Exception>\n";
+ m_currentTestSuccess = false;
+ break;
+ case ResultWas::Info:
+ m_config.stream() << "\t<Info>" << resultInfo.getMessage() << "</Info>\n";
+ break;
+ case ResultWas::Warning:
+ m_config.stream() << "\t<Warning>" << resultInfo.getMessage() << "</Warning>\n";
+ break;
+ case ResultWas::ExplicitFailure:
+ m_config.stream() << "\t<Failure>" << resultInfo.getMessage() << "</Failure>\n";
+ m_currentTestSuccess = false;
+ break;
+ }
+ if( resultInfo.hasExpression() )
+ {
+ m_config.stream() << "\t</Expression>\n";
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ virtual void EndTestCase( const Catch::TestCaseInfo& testInfo )
+ {
+ m_config.stream() << "\t<OverallResult success='" << (m_currentTestSuccess ? "true" : "false" ) << "/>\n";
+ m_config.stream() << "</TestCase>" << std::endl;
+ }
+
+ private:
+ const ReporterConfig& m_config;
+ bool m_currentTestSuccess;
+ };
+
+} // end namespace Catch
+
+#endif // TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
\ No newline at end of file
diff --git a/catch_runner.hpp b/catch_runner.hpp
new file mode 100644
index 0000000..cdf6653
--- /dev/null
+++ b/catch_runner.hpp
@@ -0,0 +1,82 @@
+/*
+ * catch_runner.hpp
+ * Catch
+ *
+ * Created by Phil on 31/10/2010.
+ * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#ifndef TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
+
+#include "internal/catch_commandline.hpp"
+#include "internal/catch_list.hpp"
+#include "catch_reporter_basic.hpp"
+#include "catch_reporter_xml.hpp"
+
+namespace Catch
+{
+ inline int Main( int argc, char * const argv[] )
+ {
+ ReporterRegistry::instance().registerReporter<BasicReporter>( "basic" );
+ ReporterRegistry::instance().registerReporter<XmlReporter>( "xml" );
+
+ RunnerConfig config;
+ ArgParser( argc, argv, config );
+
+ if( !config.m_message.empty() )
+ {
+ std::cerr << config.m_message << std::endl;
+ return std::numeric_limits<int>::max();
+ }
+
+ // Handle list request
+ if( config.listWhat() != RunnerConfig::listNone )
+ return List( config );
+
+ // Open output file, if specified
+ std::ofstream ofs;
+ if( !config.getFilename().empty() )
+ {
+ ofs.open( config.getFilename().c_str() );
+ if( ofs.fail() )
+ {
+ std::cerr << "Unable to open file: '" << config.getFilename() << "'" << std::endl;
+ return std::numeric_limits<int>::max();
+ }
+ config.getReporterConfig().setStreamBuf( ofs.rdbuf() );
+ }
+
+ Runner runner;
+ runner.setReporter( config.getReporter() );
+
+ // Run test specs specified on the command line - or default to all
+ if( config.m_testSpecs.size() == 0 )
+ {
+ runner.runAll();
+ }
+ else
+ {
+ // !TBD We should get all the testcases upfront, report any missing,
+ // then just run them
+ std::vector<std::string>::const_iterator it = config.m_testSpecs.begin();
+ std::vector<std::string>::const_iterator itEnd = config.m_testSpecs.end();
+ for(; it != itEnd; ++it )
+ {
+ if( runner.runMatching( *it ) == 0 )
+ {
+ // Use reporter?
+ std::cerr << "\n[Unable to match any test cases with: " << *it << "]" << std::endl;
+ }
+ }
+ }
+ return runner.getFailures();
+ }
+
+} // end namespace Catch
+
+#endif // TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
\ No newline at end of file
diff --git a/catch_runnerconfig.hpp b/catch_runnerconfig.hpp
new file mode 100644
index 0000000..19b4840
--- /dev/null
+++ b/catch_runnerconfig.hpp
@@ -0,0 +1,126 @@
+/*
+ * catch_runnerconfig.hpp
+ * Catch
+ *
+ * Created by Phil on 08/11/2010.
+ * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#ifndef TWOBLUECUBES_CATCH_RUNNERCONFIG_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_RUNNERCONFIG_HPP_INCLUDED
+
+#include "catch_reporter_registry.hpp"
+
+#include <vector>
+#include <string>
+
+namespace Catch
+{
+ class RunnerConfig
+ {
+ public:
+
+ enum ListInfo
+ {
+ listNone = 0,
+
+ listReports = 1,
+ listTests = 2,
+ listAll = 3,
+
+ listWhatMask = 0xf,
+
+ listAsText = 0x10,
+ listAsXml = 0x11,
+
+ listAsMask = 0xf0
+ };
+
+
+ RunnerConfig()
+ : m_listSpec( listNone ),
+ m_reporter( NULL )
+ {}
+
+ void setReporterInfo( const std::string& reporterName )
+ {
+ if( m_reporter.get() )
+ return setError( "Only one reporter may be specified" );
+ setReporter( ReporterRegistry::instance().create( reporterName, m_reporterConfig ) );
+ }
+
+ void addTestSpec( const std::string& testSpec )
+ {
+ m_testSpecs.push_back( testSpec );
+ }
+ void setListSpec( ListInfo listSpec )
+ {
+ m_listSpec = listSpec;
+ }
+
+ void setFilename( const std::string& filename )
+ {
+ m_filename = filename;
+ }
+
+ std::string getFilename()
+ {
+ return m_filename;
+ }
+
+ void setError( const std::string& errorMessage )
+ {
+ m_message = errorMessage + "\n\n" + "Usage: ...";
+ }
+
+ void setReporter( ITestReporter* reporter )
+ {
+ m_reporter = std::auto_ptr<ITestReporter>( reporter );
+ }
+
+ ITestReporter* getReporter()
+ {
+ if( !m_reporter.get() )
+ setReporter( ReporterRegistry::instance().create( "basic", m_reporterConfig ) );
+ return m_reporter.get();
+ }
+
+ const ITestReporter* getReporter() const
+ {
+ return const_cast<RunnerConfig*>( this )->getReporter();
+ }
+
+ ListInfo listWhat() const
+ {
+ return (ListInfo)( m_listSpec & listWhatMask );
+ }
+
+ ListInfo listAs() const
+ {
+ return (ListInfo)( m_listSpec & listAsMask );
+ }
+
+ ReporterConfig& getReporterConfig()
+ {
+ return m_reporterConfig;
+ }
+ void setIncludeAll( bool includeAll )
+ {
+ m_reporterConfig.setIncludeWhat( includeAll ? ReporterConfig::Include::SuccessfulResults : ReporterConfig::Include::FailedOnly );
+ }
+
+ std::auto_ptr<ITestReporter> m_reporter;
+ std::string m_filename;
+ ReporterConfig m_reporterConfig;
+ std::string m_message;
+ ListInfo m_listSpec;
+ std::vector<std::string> m_testSpecs;
+ };
+
+} // end namespace Catch
+
+#endif // TWOBLUECUBES_CATCH_RUNNERCONFIG_HPP_INCLUDED
\ No newline at end of file
diff --git a/internal/catch_capture.hpp b/internal/catch_capture.hpp
new file mode 100644
index 0000000..2a01eee
--- /dev/null
+++ b/internal/catch_capture.hpp
@@ -0,0 +1,279 @@
+/*
+ * catch_capture.hpp
+ * Catch
+ *
+ * Created by Phil on 18/10/2010.
+ * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+#ifndef TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
+
+#include "catch_resultinfo.hpp"
+#include <sstream>
+#include "math.h"
+
+namespace Catch
+{
+
+template<typename T>
+std::string toString( const T& value )
+{
+ std::ostringstream oss;
+ oss << value;
+ return oss.str();
+}
+
+class TestFailureException
+{
+};
+class DummyExceptionType_DontUse
+{
+};
+
+class MutableResultInfo : public ResultInfo
+{
+public:
+
+ MutableResultInfo()
+ {}
+
+ MutableResultInfo( const std::string& expr, bool isNot, const std::string& filename, size_t line, const std::string& macroName )
+ : ResultInfo( ( isNot ? "!" : "" ) + expr, ResultWas::Unknown, isNot, filename, line, macroName )
+ {
+ }
+ void setResultType( ResultWas::OfType result )
+ {
+ // Flip bool results if isNot is set
+ if( m_isNot && result == ResultWas::Ok )
+ m_result = ResultWas::ExpressionFailed;
+ else if( m_isNot && result == ResultWas::ExpressionFailed )
+ m_result = ResultWas::Ok;
+ else
+ m_result = result;
+ }
+ void setMessage( const std::string& message )
+ {
+ m_message = message;
+ }
+
+private:
+ friend class ResultBuilder;
+ void setLhs( const std::string& lhs )
+ {
+ m_lhs = lhs;
+ }
+ MutableResultInfo& setRhs( const std::string& op, const std::string& rhs )
+ {
+ m_op = op;
+ m_rhs = rhs;
+ return *this;
+ }
+};
+
+class ResultBuilder
+{
+public:
+ ResultBuilder( const char* expr, bool isNot, const std::string& filename, size_t line, const std::string& macroName )
+ : m_result( expr, isNot, filename, line, macroName )
+ {}
+
+ template<typename T>
+ ResultBuilder& operator->*(const T & operand)
+ {
+ m_result.setLhs( toString( operand ) );
+ return *this;
+ }
+
+ template<typename RhsT>
+ MutableResultInfo& operator == ( const RhsT& rhs )
+ {
+ return m_result.setRhs( "==", toString( rhs ) );
+ }
+ template<typename RhsT>
+ MutableResultInfo& operator != ( const RhsT& rhs )
+ {
+ return m_result.setRhs( "!=", toString( rhs ) );
+ }
+ template<typename RhsT>
+ MutableResultInfo& operator < ( const RhsT& rhs )
+ {
+ return m_result.setRhs( "<", toString( rhs ) );
+ }
+ template<typename RhsT>
+ MutableResultInfo& operator > ( const RhsT& rhs )
+ {
+ return m_result.setRhs( ">", toString( rhs ) );
+ }
+ template<typename RhsT>
+ MutableResultInfo& operator <= ( const RhsT& rhs )
+ {
+ return m_result.setRhs( "<=", toString( rhs ) );
+ }
+ template<typename RhsT>
+ MutableResultInfo& operator >= ( const RhsT& rhs )
+ {
+ return m_result.setRhs( ">=", toString( rhs ) );
+ }
+ operator MutableResultInfo&()
+ {
+ return m_result;
+ }
+
+private:
+ MutableResultInfo m_result;
+
+};
+
+class TestCaseInfo;
+
+struct IResultListener
+{
+ virtual ~IResultListener(){}
+ virtual void testEnded( const ResultInfo& result ) = 0;
+};
+
+class ResultsCapture
+{
+private:
+ ResultsCapture()
+ : m_listener( 0 )
+ {
+ }
+
+ static ResultsCapture& instance()
+ {
+ static ResultsCapture instance;
+ return instance;
+ }
+
+public:
+
+ static IResultListener* setListener( IResultListener* listener )
+ {
+ IResultListener* prevListener = instance().m_listener;
+ instance().m_listener = listener;
+ return prevListener;
+ }
+
+ static void acceptExpression( const MutableResultInfo& resultInfo )
+ {
+ instance().currentResult = resultInfo;
+ }
+
+ static void acceptResult( bool result, bool stopOnFail )
+ {
+ acceptResult( result ? ResultWas::Ok : ResultWas::ExpressionFailed, stopOnFail );
+ }
+
+ static void acceptResult( ResultWas::OfType result, bool stopOnFail )
+ {
+ if( !acceptResult( result ) && stopOnFail )
+ {
+ throw TestFailureException();
+ }
+ }
+
+ static bool acceptResult( ResultWas::OfType result )
+ {
+ MutableResultInfo& currentResult = instance().currentResult;
+ currentResult.setResultType( result );
+
+ if( instance().m_listener )
+ {
+ instance().m_listener->testEnded( currentResult );
+ }
+ bool ok = currentResult.ok();
+ instance().currentResult = MutableResultInfo();
+ return ok;
+ }
+
+ static bool acceptResult( bool expressionResult )
+ {
+ return acceptResult( expressionResult ? ResultWas::Ok : ResultWas::ExpressionFailed );
+ }
+
+ static void acceptMessage( const std::string& msg )
+ {
+ instance().currentResult.setMessage( msg );
+ }
+
+private:
+ MutableResultInfo currentResult;
+ IResultListener* m_listener;
+};
+
+// !TBD Need to clean this all up
+#define CATCH_absTol 1e-10
+#define CATCH_relTol 1e-10
+
+class Approx
+{
+public:
+ // !TBD more generic
+ Approx( double d )
+ : m_d( d )
+ {
+ }
+ template<typename T>
+ friend bool operator == ( const T& lhs, const Approx& rhs )
+ {
+ // !TBD Use proper tolerance
+ // From: http://realtimecollisiondetection.net/blog/?p=89
+ // see also: http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
+ return fabs( lhs - rhs.m_d ) <= std::max( CATCH_absTol, CATCH_relTol * std::max( fabs(lhs), fabs(rhs.m_d) ) );
+ }
+
+ template<typename T>
+ friend bool operator != ( const T& lhs, const Approx& rhs )
+ {
+ return ! operator==( lhs, rhs );
+ }
+
+ double m_d;
+};
+
+template<>
+inline std::string toString<Approx>( const Approx& value )
+{
+ std::ostringstream oss;
+ oss << "Approx( " << value.m_d << ")";
+ return oss.str();
+}
+
+
+} // end namespace Catch
+
+#define _CATCH_TEST( expr, isNot, stopOnFailure, macroName ) \
+ Catch::ResultsCapture::acceptExpression( Catch::ResultBuilder( #expr, isNot, __FILE__, __LINE__, macroName )->*expr ); \
+ Catch::ResultsCapture::acceptResult( expr, stopOnFailure );
+
+#define _CATCH_THROWS( expr, exceptionType, nothrow, stopOnFailure, macroName ) \
+ Catch::ResultsCapture::acceptExpression( Catch::ResultBuilder( #expr, false, __FILE__, __LINE__, macroName ) ); \
+ try \
+ { \
+ expr; \
+ Catch::ResultsCapture::acceptResult( nothrow, stopOnFailure ); \
+ } \
+ catch( exceptionType ) \
+ { \
+ Catch::ResultsCapture::acceptResult( !(nothrow), stopOnFailure ); \
+ }
+
+#define _CATCH_THROWS_AS( expr, exceptionType, nothrow, stopOnFailure, macroName ) \
+_CATCH_THROWS( expr, exceptionType, nothrow, stopOnFailure, macroName ) \
+catch( ... ) \
+{ \
+ Catch::ResultsCapture::acceptResult( false, stopOnFailure ); \
+}
+
+#define _CATCH_MSG( reason, resultType, stopOnFailure, macroName ) \
+ Catch::ResultsCapture::acceptExpression( Catch::MutableResultInfo( "", false, __FILE__, __LINE__, macroName ) ); \
+ Catch::ResultsCapture::acceptMessage( reason ); \
+ Catch::ResultsCapture::acceptResult( resultType, stopOnFailure );
+
+
+#endif // TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
diff --git a/internal/catch_commandline.hpp b/internal/catch_commandline.hpp
new file mode 100644
index 0000000..28daa27
--- /dev/null
+++ b/internal/catch_commandline.hpp
@@ -0,0 +1,174 @@
+/*
+ * catch_commandline.hpp
+ * Catch
+ *
+ * Created by Phil on 02/11/2010.
+ * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#ifndef TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
+
+#include "catch_runnerconfig.hpp"
+#include "catch_runner_impl.hpp"
+
+namespace Catch
+{
+ // -l --list:tests [xml] lists available tests (optionally in xml)
+ // -l --list:reports [xml] lists available reports (optionally in xml)
+ // -l --list:all [xml] lists available tests and reports (optionally in xml)
+ // -t --test "testspec" (any number)
+ // -r --report <type>
+ // -o --output filename to write to
+ // -s --success report successful cases too
+ class ArgParser
+ {
+ enum Mode
+ {
+ modeNone,
+ modeList,
+ modeTest,
+ modeReport,
+ modeOutput,
+ modeSuccess,
+
+ modeError
+ };
+
+ public:
+ ArgParser( int argc, char * const argv[], RunnerConfig& config )
+ : m_mode( modeNone ),
+ m_config( config )
+ {
+ for(size_t i=1; i < argc; ++i )
+ {
+ if( argv[i][0] == '-' )
+ {
+ std::string cmd = ( argv[i] );
+ if( cmd == "-l" || cmd == "--list" )
+ changeMode( cmd, modeList );
+ else if( cmd == "-t" || cmd == "--test" )
+ changeMode( cmd, modeTest );
+ else if( cmd == "-r" || cmd == "--report" )
+ changeMode( cmd, modeReport );
+ else if( cmd == "-o" || cmd == "--output" )
+ changeMode( cmd, modeOutput );
+ else if( cmd == "-s" || cmd == "--success" )
+ changeMode( cmd, modeSuccess );
+ }
+ else
+ {
+ m_args.push_back( argv[i] );
+ }
+ if( m_mode == modeError )
+ return;
+ }
+ changeMode( "", modeNone );
+ }
+
+ private:
+ std::string argsAsString()
+ {
+ std::ostringstream oss;
+ std::vector<std::string>::const_iterator it = m_args.begin();
+ std::vector<std::string>::const_iterator itEnd = m_args.end();
+ for( bool first = true; it != itEnd; ++it, first = false )
+ {
+ if( !first )
+ oss << " ";
+ oss << *it;
+ }
+ return oss.str();
+ }
+
+ void changeMode( const std::string& cmd, Mode mode )
+ {
+ m_command = cmd;
+ switch( m_mode )
+ {
+ case modeNone:
+ if( m_args.size() > 0 )
+ return setErrorMode( "Unexpected arguments before " + m_command + ": " + argsAsString() );
+ break;
+ case modeList:
+ if( m_args.size() > 2 )
+ {
+ return setErrorMode( m_command + " expected upto 2 arguments but recieved: " + argsAsString() );
+ }
+ else
+ {
+ RunnerConfig::ListInfo listSpec = RunnerConfig::listAll;
+ if( m_args.size() >= 1 )
+ {
+ if( m_args[0] == "tests" )
+ listSpec = RunnerConfig::listTests;
+ else if( m_args[0] == "reports" )
+ listSpec = RunnerConfig::listReports;
+ else
+ return setErrorMode( m_command + " expected [tests] or [reports] but recieved: [" + m_args[0] + "]" );
+ }
+ if( m_args.size() >= 2 )
+ {
+ if( m_args[1] == "xml" )
+ listSpec = (RunnerConfig::ListInfo)( listSpec | RunnerConfig::listAsXml );
+ else if( m_args[1] == "text" )
+ listSpec = (RunnerConfig::ListInfo)( listSpec | RunnerConfig::listAsText );
+ else
+ return setErrorMode( m_command + " expected [xml] or [text] but recieved: [" + m_args[1] + "]" );
+ }
+ m_config.m_listSpec = (RunnerConfig::ListInfo)( m_config.m_listSpec | listSpec );
+ }
+ break;
+ case modeTest:
+ if( m_args.size() == 0 )
+ return setErrorMode( m_command + " expected at least 1 argument but recieved none" );
+ {
+ std::vector<std::string>::const_iterator it = m_args.begin();
+ std::vector<std::string>::const_iterator itEnd = m_args.end();
+ for(; it != itEnd; ++it )
+ m_config.addTestSpec( *it );
+ }
+ break;
+ case modeReport:
+ if( m_args.size() != 1 )
+ return setErrorMode( m_command + " expected one argument, recieved: " + argsAsString() );
+ m_config.setReporterInfo( m_args[0] );
+ break;
+ case modeOutput:
+ if( m_args.size() == 0 )
+ return setErrorMode( m_command + " expected filename" );
+ m_config.setFilename( m_args[0] );
+ break;
+ case modeSuccess:
+ if( m_args.size() != 0 )
+ return setErrorMode( m_command + " does not accept arguments" );
+ m_config.setIncludeAll( true );
+ break;
+ }
+ m_args.clear();
+ m_mode = mode;
+ }
+
+ void setErrorMode( const std::string& errorMessage )
+ {
+ m_mode = modeError;
+ m_command = "";
+ m_config.setError( errorMessage );
+ }
+
+ private:
+
+ Mode m_mode;
+ std::string m_command;
+ std::vector<std::string> m_args;
+ RunnerConfig& m_config;
+ };
+
+
+} // end namespace Catch
+
+#endif // TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
\ No newline at end of file
diff --git a/internal/catch_common.h b/internal/catch_common.h
new file mode 100644
index 0000000..b4d8b16
--- /dev/null
+++ b/internal/catch_common.h
@@ -0,0 +1,20 @@
+/*
+ * catch_common.h
+ * Catch
+ *
+ * Created by Phil on 29/10/2010.
+ * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#ifndef TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
+#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
+
+#define _CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
+#define _CATCH_UNIQUE_NAME_LINE( name, line ) _CATCH_UNIQUE_NAME_LINE2( name, line )
+#define _CATCH_UNIQUE_NAME( name ) _CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
+
+#endif // TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
\ No newline at end of file
diff --git a/internal/catch_list.hpp b/internal/catch_list.hpp
new file mode 100644
index 0000000..82cc162
--- /dev/null
+++ b/internal/catch_list.hpp
@@ -0,0 +1,66 @@
+/*
+ * catch_list.hpp
+ * Catch
+ *
+ * Created by Phil on 5/11/2010.
+ * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#ifndef TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
+
+#include "catch_commandline.hpp"
+
+namespace Catch
+{
+ inline int List( const RunnerConfig& config )
+ {
+ if( config.listWhat() & RunnerConfig::listReports )
+ {
+ std::cout << "Available reports:\n";
+ ReporterRegistry::FactoryMap::const_iterator it = ReporterRegistry::instance().m_factories.begin();
+ ReporterRegistry::FactoryMap::const_iterator itEnd = ReporterRegistry::instance().m_factories.end();
+ for(; it != itEnd; ++it )
+ {
+ // !TBD: consider listAs()
+ std::cout << "\t" << it->first << " '" << it->second->getDescription() << "'\n";
+ }
+ std::cout << std::endl;
+ }
+ if( config.listWhat() & RunnerConfig::listTests )
+ {
+ std::cout << "Available tests:\n";
+ std::vector<TestCaseInfo>::const_iterator it = TestRegistry::instance().getAllTests().begin();
+ std::vector<TestCaseInfo>::const_iterator itEnd = TestRegistry::instance().getAllTests().end();
+ for(; it != itEnd; ++it )
+ {
+ // !TBD: consider listAs()
+ std::cout << "\t" << it->getName() << " '" << it->getDescription() << "'\n";
+ }
+ std::cout << std::endl;
+ }
+ if( ( config.listWhat() & RunnerConfig::listAll ) == 0 )
+ {
+ std::cerr << "Unknown list type" << std::endl;
+ return std::numeric_limits<int>::max();
+ }
+
+ if( config.getReporter() )
+ {
+ std::cerr << "Reporters ignored when listing" << std::endl;
+ }
+ if( config.m_testSpecs.size() == 0 )
+ {
+ std::cerr << "Test specs ignored when listing" << std::endl;
+ }
+ return 0;
+
+ }
+
+} // end namespace Catch
+
+#endif // TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
\ No newline at end of file
diff --git a/internal/catch_registry.hpp b/internal/catch_registry.hpp
new file mode 100644
index 0000000..b136be6
--- /dev/null
+++ b/internal/catch_registry.hpp
@@ -0,0 +1,116 @@
+/*
+ * catch_registry.hpp
+ * Catch
+ *
+ * Created by Phil on 18/10/2010.
+ * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+#ifndef TWOBLUECUBES_CATCH_REGISTRY_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_REGISTRY_HPP_INCLUDED
+
+#include "catch_testcaseinfo.hpp"
+#include "catch_common.h"
+
+#include <vector>
+#include <stdexcept>
+
+namespace Catch
+{
+class TestRegistry
+{
+public:
+
+ static TestRegistry& instance()
+ {
+ static TestRegistry reg;
+ return reg;
+ }
+
+ void registerTest( const TestCaseInfo& testInfo )
+ {
+ m_functions.push_back( testInfo );
+ }
+
+ std::vector<TestCaseInfo> getAllTests() const
+ {
+ return m_functions;
+ }
+
+private:
+
+ std::vector<TestCaseInfo> m_functions;
+};
+
+typedef void(*TestFunction)();
+
+struct FreeFunctionTestCase : TestCase
+{
+ FreeFunctionTestCase( TestFunction fun )
+ : fun( fun )
+ {}
+
+ virtual void invoke() const
+ {
+ fun();
+ }
+
+ virtual TestCase* clone() const
+ {
+ return new FreeFunctionTestCase( fun );
+ }
+
+private:
+ TestFunction fun;
+};
+
+template<typename C>
+struct MethodTestCase : TestCase
+{
+ MethodTestCase( void (C::*method)() )
+ : method( method )
+ {}
+
+ virtual void invoke() const
+ {
+ C obj;
+ (obj.*method)();
+ }
+
+ virtual TestCase* clone() const
+ {
+ return new MethodTestCase<C>( method );
+ }
+
+private:
+ void (C::*method)();
+};
+
+struct AutoReg
+{
+ AutoReg( TestFunction function, const std::string& name, const std::string& description )
+ {
+ TestRegistry::instance().registerTest( TestCaseInfo( new FreeFunctionTestCase( function ), name, description ) );
+ }
+
+ template<typename C>
+ AutoReg( void (C::*method)(), const std::string& name, const std::string& description )
+ {
+ TestRegistry::instance().registerTest( TestCaseInfo( new MethodTestCase<C>( method ), name, description ) );
+ }
+};
+
+} // end namespace Catch
+
+#define CATCH_TEST_CASE( Name, Desc ) \
+ static void _CATCH_UNIQUE_NAME( __catchTestFunction )(); \
+ namespace{ Catch::AutoReg _CATCH_UNIQUE_NAME( autoRegistrar )( &_CATCH_UNIQUE_NAME( __catchTestFunction ), Name, Desc ); }\
+ static void _CATCH_UNIQUE_NAME( __catchTestFunction )()
+
+#define CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
+ namespace{ Catch::AutoReg _CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, Name, Desc ); }
+
+#endif // TWOBLUECUBES_CATCH_REGISTRY_HPP_INCLUDED
diff --git a/internal/catch_reporter_registry.hpp b/internal/catch_reporter_registry.hpp
new file mode 100644
index 0000000..820703d
--- /dev/null
+++ b/internal/catch_reporter_registry.hpp
@@ -0,0 +1,166 @@
+/*
+ * catch_registry.hpp
+ * Catch
+ *
+ * Created by Phil on 29/10/2010.
+ * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+#ifndef TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
+
+#include "catch_testcaseinfo.hpp"
+#include "catch_resultinfo.hpp"
+#include "catch_common.h"
+
+#include <map>
+#include <iostream>
+#include <fstream>
+
+namespace Catch
+{
+ class ReporterConfig
+ {
+ private:
+ ReporterConfig( const ReporterConfig& other );
+ ReporterConfig& operator = ( const ReporterConfig& other );
+
+ public:
+
+ struct Include { enum What
+ {
+ FailedOnly,
+ SuccessfulResults
+ }; };
+
+ public:
+
+ ///////////////////////////////////////////////////////////////////////////
+ explicit ReporterConfig( Include::What includeWhat = Include::FailedOnly )
+ : m_includeWhat( includeWhat ),
+ m_os( std::cout.rdbuf() )
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ bool includeSuccessfulResults() const
+ {
+ return m_includeWhat == Include::SuccessfulResults;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ void setIncludeWhat(Include::What includeWhat )
+ {
+ m_includeWhat = includeWhat;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ std::ostream& stream() const
+ {
+ return m_os;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ void setStreamBuf( std::streambuf* buf )
+ {
+ m_os.rdbuf( buf );
+ }
+
+ private:
+ Include::What m_includeWhat;
+
+ mutable std::ostream m_os;
+ };
+
+ struct ITestReporter
+ {
+ virtual ~ITestReporter(){}
+
+ // !TBD
+ // StartTesting
+ // EndTesting
+ // StartGroup
+ // EndGroup
+ // StartSection
+ // EndSection
+ virtual void StartTestCase( const TestCaseInfo& testInfo ) = 0;
+ virtual void Result( const ResultInfo& result ) = 0;
+ virtual void EndTestCase( const TestCaseInfo& testInfo ) = 0;
+ };
+
+ struct IReporterFactory
+ {
+ virtual ~IReporterFactory(){}
+
+ virtual ITestReporter* create( const ReporterConfig& config ) = 0;
+ virtual std::string getDescription() const = 0;
+ };
+
+ template<typename T>
+ class ReporterFactory : public IReporterFactory
+ {
+ virtual ITestReporter* create( const ReporterConfig& config )
+ {
+ return new T( config );
+ }
+ virtual std::string getDescription() const
+ {
+ return T::getDescription();
+ }
+ };
+
+ class ReporterRegistry
+ {
+ public:
+
+ static ReporterRegistry& instance()
+ {
+ static ReporterRegistry instance;
+ return instance;
+ }
+
+ ~ReporterRegistry()
+ {
+ FactoryMap::const_iterator it = m_factories.begin();
+ FactoryMap::const_iterator itEnd = m_factories.end();
+ for(; it != itEnd; ++it )
+ {
+ delete it->second;
+ }
+ }
+
+ ITestReporter* create( const std::string& name, const ReporterConfig& config )
+ {
+ FactoryMap::const_iterator it = m_factories.find( name );
+ if( it == m_factories.end() )
+ return NULL;
+ return it->second->create( config );
+ }
+
+ template<typename T>
+ void registerReporter( const std::string& name )
+ {
+ m_factories.insert( std::make_pair( name, new ReporterFactory<T>() ) );
+ }
+
+// private: // !TBD
+ typedef std::map<std::string, IReporterFactory*> FactoryMap;
+ FactoryMap m_factories;
+ };
+
+ template<typename T>
+ struct ReporterRegistrar
+ {
+ ReporterRegistrar( const std::string& name )
+ {
+ ReporterRegistry::instance().registerReporter<T>( name );
+ }
+ };
+}
+
+#define CATCH_REGISTER_REPORTER( name, reporterType ) Catch::ReporterRegistrar<reporterType> _CATCH_UNIQUE_NAME( __catchReporterReg )( name );
+
+#endif // TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
\ No newline at end of file
diff --git a/internal/catch_resultinfo.hpp b/internal/catch_resultinfo.hpp
new file mode 100644
index 0000000..5eae176
--- /dev/null
+++ b/internal/catch_resultinfo.hpp
@@ -0,0 +1,122 @@
+/*
+ * catch_resultinfo.hpp
+ * Catch
+ *
+ * Created by Phil on 28/10/2010.
+ * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+#ifndef TWOBLUECUBES_CATCH_RESULT_INFO_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_RESULT_INFO_HPP_INCLUDED
+
+#include <string>
+
+namespace Catch
+{
+ struct ResultWas{ enum OfType
+ {
+ Unknown = -1,
+ Ok = 0,
+ ExpressionFailed = 1,
+
+ Info = 2,
+ Warning = 3,
+ ExplicitFailure = 4,
+
+ Exception = 0x100,
+
+ ThrewException = Exception | 1,
+ DidntThrowException = Exception | 2
+
+ }; };
+
+ class ResultInfo
+ {
+ public:
+
+ ResultInfo()
+ : m_result( ResultWas::Unknown ),
+ m_isNot( false ),
+ m_line( 0 )
+ {}
+
+ ResultInfo( const std::string& expr, ResultWas::OfType result, bool isNot, const std::string& filename, size_t line, const std::string& macroName )
+ : m_expr( expr ),
+ m_result( result ),
+ m_isNot( isNot ),
+ m_op( m_expr[0] == '!' ? "!" : "" ),
+ m_filename( filename ),
+ m_line( line ),
+ m_macroName( macroName )
+ {
+ }
+
+ bool ok() const
+ {
+ return m_result == ResultWas::Ok;
+ }
+
+ ResultWas::OfType getResultType() const
+ {
+ return m_result;
+ }
+
+ bool hasExpression() const
+ {
+ return !m_expr.empty();
+ }
+ bool hasMessage() const
+ {
+ return !m_message.empty();
+ }
+ std::string getExpression() const
+ {
+ return m_expr;
+ }
+ std::string getExpandedExpression() const
+ {
+ if( m_op == "" || m_isNot )
+ return m_lhs.empty() ? m_expr : m_op + m_lhs;
+ else if( m_op != "!" )
+ return m_lhs + " " + m_op + " " + m_rhs;
+ else
+ return "{can't expand - use " + m_macroName + "_NOT( " + m_expr.substr(1) + " ) instead of " + m_macroName + "( " + m_expr + " ) for better diagnostics}";
+ }
+
+ std::string getMessage() const
+ {
+ return m_message;
+ }
+
+ std::string getFilename() const
+ {
+ return m_filename;
+ }
+
+ size_t getLine() const
+ {
+ return m_line;
+ }
+
+ std::string getTestMacroName() const
+ {
+ return m_macroName;
+ }
+
+ protected:
+ std::string m_macroName;
+ std::string m_filename;
+ size_t m_line;
+ std::string m_expr, m_lhs, m_rhs, m_op;
+ std::string m_message;
+ ResultWas::OfType m_result;
+ bool m_isNot;
+ };
+
+} // end namespace Catch
+
+
+#endif // TWOBLUECUBES_CATCH_RESULT_INFO_HPP_INCLUDED
diff --git a/internal/catch_runner_impl.hpp b/internal/catch_runner_impl.hpp
new file mode 100644
index 0000000..14d8491
--- /dev/null
+++ b/internal/catch_runner_impl.hpp
@@ -0,0 +1,145 @@
+/*
+ * catch_runner.hpp
+ * Catch
+ *
+ * Created by Phil on 22/10/2010.
+ * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+#ifndef TWOBLUECUBES_INTERNAL_CATCH_RUNNER_HPP_INCLUDED
+#define TWOBLUECUBES_INTERNAL_CATCH_RUNNER_HPP_INCLUDED
+
+#include "catch_reporter_registry.hpp"
+#include "catch_registry.hpp"
+#include "catch_capture.hpp"
+
+namespace Catch
+{
+ class TestSpec
+ {
+ public:
+ TestSpec( const std::string& rawSpec )
+ : m_rawSpec( rawSpec ),
+ m_isWildcarded( false )
+ {
+ if( m_rawSpec[m_rawSpec.size()-1] == '*' )
+ {
+ m_rawSpec = m_rawSpec.substr( 0, m_rawSpec.size()-1 );
+ m_isWildcarded = true;
+ }
+ }
+
+ bool matches( const std::string& testName ) const
+ {
+ if( !m_isWildcarded )
+ return m_rawSpec == testName;
+ else
+ return testName.size() >= m_rawSpec.size() && testName.substr( 0, m_rawSpec.size() ) == m_rawSpec;
+ }
+
+ private:
+ std::string m_rawSpec;
+ bool m_isWildcarded;
+ };
+
+ class Runner : public IResultListener
+ {
+ public:
+ Runner()
+ : m_successes( 0 ),
+ m_failures( 0 ),
+ m_reporter( 0 )
+ {
+ }
+
+ void setReporter( ITestReporter* reporter )
+ {
+ m_reporter = reporter;
+ }
+
+ void runAll()
+ {
+ std::vector<TestCaseInfo> allTests = TestRegistry::instance().getAllTests();
+ for( size_t i=0; i < allTests.size(); ++i )
+ {
+ runTest( allTests[i] );
+ }
+ }
+
+ size_t runMatching( const std::string& rawTestSpec )
+ {
+ TestSpec testSpec( rawTestSpec );
+
+ std::vector<TestCaseInfo> allTests = TestRegistry::instance().getAllTests();
+ size_t testsRun = 0;
+ for( size_t i=0; i < allTests.size(); ++i )
+ {
+ if( testSpec.matches( allTests[i].getName() ) )
+ {
+ runTest( allTests[i] );
+ testsRun++;
+ }
+ }
+ return testsRun;
+ }
+
+ void runTest( const TestCaseInfo& testInfo )
+ {
+ IResultListener* prevListener = ResultsCapture::setListener( this );
+ m_reporter->StartTestCase( testInfo );
+
+ try
+ {
+ testInfo.invoke();
+ }
+ catch( TestFailureException& ex )
+ {
+ // This just means the test was aborted due to failure
+ }
+ catch( std::exception& ex )
+ {
+ ResultsCapture::acceptMessage( ex.what() );
+ ResultsCapture::acceptResult( ResultWas::ThrewException );
+ }
+ catch(...)
+ {
+ ResultsCapture::acceptMessage( "unknown exception" );
+ ResultsCapture::acceptResult( ResultWas::ThrewException );
+ }
+
+ m_reporter->EndTestCase( testInfo );
+ ResultsCapture::setListener( prevListener );
+ }
+
+ size_t getSuccessCount() const
+ {
+ return m_successes;
+ }
+ size_t getFailures() const
+ {
+ return m_failures;
+ }
+
+ private: // IResultListener
+
+ virtual void testEnded( const ResultInfo& result )
+ {
+ if( result.ok() )
+ m_successes++;
+ else
+ m_failures++;
+
+ m_reporter->Result( result );
+ }
+
+ private:
+ size_t m_successes;
+ size_t m_failures;
+ ITestReporter* m_reporter;
+ };
+}
+
+#endif // TWOBLUECUBES_INTERNAL_CATCH_RUNNER_HPP_INCLUDED
\ No newline at end of file
diff --git a/internal/catch_section.hpp b/internal/catch_section.hpp
new file mode 100644
index 0000000..c7df9e8
--- /dev/null
+++ b/internal/catch_section.hpp
@@ -0,0 +1,39 @@
+/*
+ * catch_section.hpp
+ * Catch
+ *
+ * Created by Phil on 03/11/2010.
+ * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#ifndef TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
+
+#include <string>
+
+namespace Catch
+{
+ class Section
+ {
+ public:
+ Section( const std::string& name, const std::string& description )
+ {
+ // !TBD notify the runner
+ }
+
+ operator bool()
+ {
+ // !TBD get this from runner
+ return true;
+ }
+ };
+
+} // end namespace Catch
+
+#define CATCH_SECTION( name, desc ) if( Catch::Section __catchSection = Catch::Section( name, desc ) )
+
+#endif // TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
diff --git a/internal/catch_testcaseinfo.hpp b/internal/catch_testcaseinfo.hpp
new file mode 100644
index 0000000..7a8185c
--- /dev/null
+++ b/internal/catch_testcaseinfo.hpp
@@ -0,0 +1,84 @@
+/*
+ * catch_testcaseinfo.hpp
+ * Catch
+ *
+ * Created by Phil on 29/10/2010.
+ * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ */
+
+#ifndef TWOBLUECUBES_CATCH_TESTCASEINFO_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_TESTCASEINFO_HPP_INCLUDED
+
+#include <map>
+#include <string>
+
+namespace Catch
+{
+ struct TestCase
+ {
+ virtual ~TestCase(){}
+ virtual void invoke() const = 0;
+ virtual TestCase* clone() const = 0;
+ };
+
+ class TestCaseInfo
+ {
+ public:
+ TestCaseInfo( TestCase* testCase, const std::string& name, const std::string& description )
+ : test( testCase ),
+ name( name ),
+ description( description )
+ {
+ }
+ TestCaseInfo()
+ : test( NULL )
+ {
+ }
+
+ TestCaseInfo( const TestCaseInfo& other )
+ : test( other.test->clone() ),
+ name( other.name ),
+ description( other.description )
+ {
+ }
+
+ TestCaseInfo& operator = ( const TestCaseInfo& other )
+ {
+ test = other.test->clone();
+ name = other.name;
+ description = description;
+ return *this;
+ }
+
+ ~TestCaseInfo()
+ {
+ delete test;
+ }
+
+ void invoke() const
+ {
+ test->invoke();
+ }
+
+ const std::string& getName() const
+ {
+ return name;
+ }
+ const std::string& getDescription() const
+ {
+ return description;
+ }
+
+ private:
+ TestCase* test;
+ std::string name;
+ std::string description;
+ };
+
+}
+
+#endif // TWOBLUECUBES_CATCH_TESTCASEINFO_HPP_INCLUDED
\ No newline at end of file