android: Update catch2 to v2.7.0
am: e9410dfbd9

Change-Id: I3bbca942737cdb9ad54a62bcd495396528d5eb08
diff --git a/.conan/build.py b/.conan/build.py
new file mode 100644
index 0000000..dfba264
--- /dev/null
+++ b/.conan/build.py
@@ -0,0 +1,94 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import os
+import re
+from cpt.packager import ConanMultiPackager
+from cpt.ci_manager import CIManager
+from cpt.printer import Printer
+
+
+class BuilderSettings(object):
+    @property
+    def username(self):
+        """ Set catchorg as package's owner
+        """
+        return os.getenv("CONAN_USERNAME", "catchorg")
+
+    @property
+    def login_username(self):
+        """ Set Bintray login username
+        """
+        return os.getenv("CONAN_LOGIN_USERNAME", "horenmar")
+
+    @property
+    def upload(self):
+        """ Set Catch2 repository to be used on upload.
+            The upload server address could be customized by env var
+            CONAN_UPLOAD. If not defined, the method will check the branch name.
+            Only master or CONAN_STABLE_BRANCH_PATTERN will be accepted.
+            The master branch will be pushed to testing channel, because it does
+            not match the stable pattern. Otherwise it will upload to stable
+            channel.
+        """
+        return os.getenv("CONAN_UPLOAD", "https://api.bintray.com/conan/catchorg/Catch2")
+
+    @property
+    def upload_only_when_stable(self):
+        """ Force to upload when running over tag branch
+        """
+        return os.getenv("CONAN_UPLOAD_ONLY_WHEN_STABLE", "True").lower() in ["true", "1", "yes"]
+
+    @property
+    def stable_branch_pattern(self):
+        """ Only upload the package the branch name is like a tag
+        """
+        return os.getenv("CONAN_STABLE_BRANCH_PATTERN", r"v\d+\.\d+\.\d+")
+
+    @property
+    def reference(self):
+        """ Read project version from branch create Conan referece
+        """
+        return os.getenv("CONAN_REFERENCE", "Catch2/{}".format(self._version))
+
+    @property
+    def channel(self):
+        """ Default Conan package channel when not stable
+        """
+        return os.getenv("CONAN_CHANNEL", "testing")
+
+    @property
+    def _version(self):
+        """ Get version name from cmake file
+        """
+        pattern = re.compile(r"project\(Catch2 LANGUAGES CXX VERSION (\d+\.\d+\.\d+)\)")
+        version = "latest"
+        with open("CMakeLists.txt") as file:
+            for line in file:
+                result = pattern.search(line)
+                if result:
+                    version = result.group(1)
+        return version
+
+    @property
+    def _branch(self):
+        """ Get branch name from CI manager
+        """
+        printer = Printer(None)
+        ci_manager = CIManager(printer)
+        return ci_manager.get_branch()
+
+
+if __name__ == "__main__":
+    settings = BuilderSettings()
+    builder = ConanMultiPackager(
+        reference=settings.reference,
+        channel=settings.channel,
+        upload=settings.upload,
+        upload_only_when_stable=settings.upload_only_when_stable,
+        stable_branch_pattern=settings.stable_branch_pattern,
+        login_username=settings.login_username,
+        username=settings.username,
+        test_folder=os.path.join(".conan", "test_package"))
+    builder.add()
+    builder.run()
diff --git a/.conan/test_package/CMakeLists.txt b/.conan/test_package/CMakeLists.txt
new file mode 100644
index 0000000..db05659
--- /dev/null
+++ b/.conan/test_package/CMakeLists.txt
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 3.2.0)
+project(test_package CXX)
+
+include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
+conan_basic_setup(TARGETS)
+
+find_package(Catch2 REQUIRED CONFIG)
+
+add_executable(${PROJECT_NAME} test_package.cpp)
+target_link_libraries(${PROJECT_NAME} CONAN_PKG::Catch2)
+set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 11)
diff --git a/.conan/test_package/conanfile.py b/.conan/test_package/conanfile.py
new file mode 100644
index 0000000..0a0da54
--- /dev/null
+++ b/.conan/test_package/conanfile.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+from conans import ConanFile, CMake
+import os
+
+
+class TestPackageConan(ConanFile):
+    settings = "os", "compiler", "build_type", "arch"
+    generators = "cmake"
+
+    def build(self):
+        cmake = CMake(self)
+        cmake.configure()
+        cmake.build()
+
+    def test(self):
+        assert os.path.isfile(os.path.join(self.deps_cpp_info["Catch2"].rootpath, "licenses", "LICENSE.txt"))
+        bin_path = os.path.join("bin", "test_package")
+        self.run("%s -s" % bin_path, run_environment=True)
diff --git a/.conan/test_package/test_package.cpp b/.conan/test_package/test_package.cpp
new file mode 100644
index 0000000..cff50de
--- /dev/null
+++ b/.conan/test_package/test_package.cpp
@@ -0,0 +1,15 @@
+#define CATCH_CONFIG_MAIN
+
+#include <catch2/catch.hpp>
+
+int Factorial( int number ) {
+    return number <= 1 ? 1 : Factorial( number - 1 ) * number;
+}
+
+TEST_CASE( "Factorial Tests", "[single-file]" ) {
+    REQUIRE( Factorial(0) == 1 );
+    REQUIRE( Factorial(1) == 1 );
+    REQUIRE( Factorial(2) == 2 );
+    REQUIRE( Factorial(3) == 6 );
+    REQUIRE( Factorial(10) == 3628800 );
+}
\ No newline at end of file
diff --git a/.gitattributes b/.gitattributes
index 9e88eb4..23f98ff 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -10,8 +10,13 @@
 # Windows specific files should retain windows line-endings
 *.sln text eol=crlf
 
+# Keep executable scripts with LFs so they can be run after being
+# checked out on Windows
+*.py text eol=lf
+
+
 # Keep the single include header with LFs to make sure it is uploaded,
 # hashed etc with LF
-single_include/*.hpp eol=lf
+single_include/**/*.hpp eol=lf
 # Also keep the LICENCE file with LFs for the same reason
 LICENCE.txt eol=lf
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..dbeff11
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,29 @@
+---
+name: Bug report
+about: Create an issue that documents a bug
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Reproduction steps**
+Steps to reproduce the bug.
+<!-- Usually this means a small and self-contained piece of code that uses Catch and specifying compiler flags if relevant. -->
+
+
+**Platform information:**
+<!-- Fill in any extra information that might be important for your issue. -->
+ - OS: **Windows NT**
+ - Compiler+version: **GCC v2.9.5**
+ - Catch version: **v1.2.3**
+
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..be9b9ee
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,14 @@
+---
+name: Feature request
+about: Create an issue that requests a feature or other improvement
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Description**
+Describe the feature/change you request and why do you want it.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/.github/issue_template.md b/.github/issue_template.md
deleted file mode 100644
index 051b5e5..0000000
--- a/.github/issue_template.md
+++ /dev/null
@@ -1,29 +0,0 @@
-## Description
-<!--
-If your issue is a bugreport, this means describing what you did,
-what did you want to happen and what actually did happen.
-
-If your issue is a feature request, describe the feature and why do you
-want it.
--->
-
-
-### Steps to reproduce
-<!--
-This is only relevant for bug reports, but if you do have one,
-please provide a minimal set of steps to reproduce the problem.
-
-Usually this means providing a small and self-contained code using Catch
-and specifying compiler flags/tools used if relevant.
--->
-
-
-### Extra information
-<!--
-Fill in any extra information that might be important for your issue.
-
-If your issue is a bugreport, definitely fill out at least the following.
--->
-* Catch version: **v42.42.42**
-* Operating System: **Joe's discount operating system**
-* Compiler+version: **Hidden Dragon v1.2.3**
diff --git a/.gitignore b/.gitignore
index ffce8e9..f017e9e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,3 +27,4 @@
 .vs
 cmake-build-*
 benchmark-dir
+.conan/test_package/build
diff --git a/.travis.yml b/.travis.yml
index 1da1c0f..345edfb 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,8 @@
 language: cpp
-sudo: false
+
+branches:
+  except:
+  - /dev-appveyor.*/
 
 common_sources: &all_sources
   - ubuntu-toolchain-r-test
@@ -7,6 +10,7 @@
   - llvm-toolchain-trusty-3.9
   - llvm-toolchain-trusty-4.0
   - llvm-toolchain-trusty-5.0
+  - llvm-toolchain-trusty-6.0
 
 matrix:
   include:
@@ -17,145 +21,169 @@
       addons:
         apt:
           sources: *all_sources
-          packages: ['valgrind', 'lcov', 'clang-3.5']
-      env: COMPILER='clang++-3.5' VALGRIND=1
+          packages: ['clang-3.5']
+      env: COMPILER='clang++-3.5'
 
     - os: linux
       compiler: clang
       addons:
         apt:
           sources: *all_sources
-          packages: ['valgrind', 'lcov', 'clang-3.6']
-      env: COMPILER='clang++-3.6' VALGRIND=1
+          packages: ['clang-3.6']
+      env: COMPILER='clang++-3.6'
 
-# Travis's containers do not seem to have Clang 3.7 in apt, no matter what sources I add.
-#    - os: linux
-#      compiler: clang
-#      addons:
-#        apt:
-#          sources: *all_sources
-#          packages: ['valgrind', 'clang-3.7']
-#      env: COMPILER='clang++-3.7' VALGRIND=1
+    # Clang 3.7 is intentionally skipped as we cannot get it easily on
+    # TravisCI container
 
     - os: linux
       compiler: clang
       addons:
         apt:
           sources: *all_sources
-          packages: ['valgrind', 'lcov', 'clang-3.8']
-      env: COMPILER='clang++-3.8' VALGRIND=1
+          packages: ['lcov', 'clang-3.8']
+      env: COMPILER='clang++-3.8'
 
     - os: linux
       compiler: clang
       addons:
           apt:
               sources: *all_sources
-              packages: ['clang-3.9', 'valgrind', 'lcov']
-      env: COMPILER='clang++-3.9' VALGRIND=1
+              packages: ['clang-3.9']
+      env: COMPILER='clang++-3.9'
 
     - os: linux
       compiler: clang
       addons:
           apt:
               sources: *all_sources
-              packages: ['clang-4.0', 'valgrind', 'lcov']
-      env: COMPILER='clang++-4.0' VALGRIND=1
+              packages: ['clang-4.0']
+      env: COMPILER='clang++-4.0'
 
     - os: linux
       compiler: clang
       addons:
           apt:
               sources: *all_sources
-              packages: ['clang-5.0', 'valgrind', 'lcov']
-      env: COMPILER='clang++-5.0' VALGRIND=1
+              packages: ['clang-5.0']
+      env: COMPILER='clang++-5.0'
+
+    - os: linux
+      compiler: clang
+      addons:
+          apt:
+              sources: *all_sources
+              packages: ['clang-6.0']
+      env: COMPILER='clang++-6.0'
 
     # 2/ Linux GCC Builds
     - os: linux
       compiler: gcc
       addons:
         apt:
-         sources: ['ubuntu-toolchain-r-test']
-         packages: ['valgrind', 'lcov', 'g++-4.8']
-      env: COMPILER='g++-4.8' VALGRIND=1
+         sources: *all_sources
+         packages: ['g++-4.8']
+      env: COMPILER='g++-4.8'
 
     - os: linux
       compiler: gcc
       addons:
         apt:
           sources: *all_sources
-          packages: ['valgrind', 'lcov', 'g++-4.9']
-      env: COMPILER='g++-4.9' VALGRIND=1
+          packages: ['g++-4.9']
+      env: COMPILER='g++-4.9'
 
     - os: linux
       compiler: gcc
       addons:
         apt:
           sources: *all_sources
-          packages: ['valgrind', 'lcov', 'g++-5']
-      env: COMPILER='g++-5' VALGRIND=1
+          packages: ['g++-5']
+      env: COMPILER='g++-5'
 
     - os: linux
       compiler: gcc
       addons: &gcc6
         apt:
           sources: *all_sources
-          packages: ['valgrind', 'lcov', 'g++-6']
-      env: COMPILER='g++-6' VALGRIND=1
+          packages: ['g++-6']
+      env: COMPILER='g++-6'
 
     - os: linux
       compiler: gcc
       addons: &gcc7
         apt:
           sources: *all_sources
-          packages: ['valgrind', 'lcov', 'g++-7']
-      env: COMPILER='g++-7' VALGRIND=1
+          packages: ['g++-7']
+      env: COMPILER='g++-7'
+
+    - os: linux
+      compiler: gcc
+      addons: &gcc8
+        apt:
+          sources: *all_sources
+          packages: ['g++-8']
+      env: COMPILER='g++-8'
 
     # 3b/ Linux C++14 Clang builds
+    # Note that we need newer libstdc++ for C++14 support
     - os: linux
       compiler: clang
       addons:
           apt:
-              packages: ['clang-3.8', 'valgrind', 'lcov', 'libstdc++-6-dev']
+              packages: ['clang-3.8', 'libstdc++-6-dev']
               sources:
                   - ubuntu-toolchain-r-test
                   - llvm-toolchain-trusty
-      env: COMPILER='clang++-3.8' CPP14=1 VALGRIND=1
+      env: COMPILER='clang++-3.8' CPP14=1
 
     - os: linux
       compiler: clang
       addons:
           apt:
               sources: *all_sources
-              packages: ['clang-3.9', 'valgrind', 'lcov', 'libstdc++-6-dev']
-      env: COMPILER='clang++-3.9' CPP14=1 VALGRIND=1
+              packages: ['clang-3.9', 'libstdc++-6-dev']
+      env: COMPILER='clang++-3.9' CPP14=1
 
     - os: linux
       compiler: clang
       addons:
           apt:
               sources: *all_sources
-              packages: ['clang-4.0', 'valgrind', 'lcov', 'libstdc++-6-dev']
-      env: COMPILER='clang++-4.0' CPP14=1 VALGRIND=1
+              packages: ['clang-4.0', 'libstdc++-6-dev']
+      env: COMPILER='clang++-4.0' CPP14=1
 
     - os: linux
       compiler: clang
       addons:
           apt:
               sources: *all_sources
-              packages: ['clang-5.0', 'valgrind', 'lcov', 'libstdc++-6-dev']
-      env: COMPILER='clang++-5.0' CPP14=1 VALGRIND=1
+              packages: ['clang-5.0', 'libstdc++-6-dev']
+      env: COMPILER='clang++-5.0' CPP14=1
+
+    - os: linux
+      compiler: clang
+      addons:
+          apt:
+              sources: *all_sources
+              packages: ['clang-6.0', 'libstdc++-6-dev']
+      env: COMPILER='clang++-6.0' CPP14=1
 
 
     # 4a/ Linux C++14 GCC builds
     - os: linux
       compiler: gcc
       addons: *gcc6
-      env: COMPILER='g++-6' CPP14=1 VALGRIND=1
+      env: COMPILER='g++-6' CPP14=1
 
     - os: linux
       compiler: gcc
       addons: *gcc7
-      env: COMPILER='g++-7' CPP14=1 VALGRIND=1
+      env: COMPILER='g++-7' CPP14=1
+
+    - os: linux
+      compiler: gcc
+      addons: *gcc8
+      env: COMPILER='g++-8' CPP14=1
 
     # 5/ OSX Clang Builds
     - os: osx
@@ -181,15 +209,86 @@
     - os: osx
       osx_image: xcode9.1
       compiler: clang
-      env: COMPILER='clang++' USE_CPP14=1
+      env: COMPILER='clang++' CPP14=1
 
+    # 6/ Special builds -- examples, coverage, valgrind, etc.
+    - os: linux
+      compiler: gcc
+      addons:
+        apt:
+          sources: *all_sources
+          packages: ['lcov', 'g++-7']
+      env: COMPILER='g++-7' CPP14=1 EXAMPLES=1 COVERAGE=1 EXTRAS=1
+
+    - os: linux
+      compiler: clang
+      addons:
+        apt:
+          packages: ['clang-3.8', 'lcov']
+          sources:
+            - ubuntu-toolchain-r-test
+            - llvm-toolchain-trusty
+      env: COMPILER='clang++-3.8' EXAMPLES=1 COVERAGE=1 EXTRAS=1
+
+    - os: linux
+      compiler: gcc
+      addons:
+        apt:
+          sources: *all_sources
+          packages: ['valgrind', 'lcov', 'g++-7']
+      env: COMPILER='g++-7' CPP14=1 VALGRIND=1
+
+    - os: osx
+      osx_image: xcode9.1
+      compiler: clang
+      env: COMPILER='clang++' CPP14=1 EXAMPLES=1 COVERAGE=1 EXTRAS=1
+
+    # 7/ C++17 builds
+    - os: linux
+      compiler: gcc
+      addons: *gcc7
+      env: COMPILER='g++-7' CPP17=1
+
+    - os: linux
+      compiler: gcc
+      addons: *gcc7
+      env: COMPILER='g++-7' EXAMPLES=1 COVERAGE=1 EXTRAS=1 CPP17=1
+
+    - os: linux
+      compiler: clang
+      addons:
+          apt:
+              sources: *all_sources
+              packages: ['clang-6.0', 'libstdc++-8-dev']
+      env: COMPILER='clang++-6.0' CPP17=1
+
+    - os: linux
+      compiler: clang
+      addons:
+          apt:
+              sources: *all_sources
+              packages: ['clang-6.0', 'libstdc++-8-dev']
+      env: COMPILER='clang++-6.0' CPP17=1 EXAMPLES=1 COVERAGE=1 EXTRAS=1
+
+    # 8/ Conan
+    - language: python
+      python:
+        - "3.7"
+      dist: xenial
+      install:
+        - pip install conan==1.10.2 conan-package-tools
+      env:
+        - CONAN_GCC_VERSIONS=8
+        - CONAN_DOCKER_IMAGE=conanio/gcc8
+      script:
+        - python .conan/build.py
 
 install:
   - DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
   - mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}
   - |
     if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
-      CMAKE_URL="http://www.cmake.org/files/v3.3/cmake-3.3.2-Linux-x86_64.tar.gz"
+      CMAKE_URL="http://cmake.org/files/v3.8/cmake-3.8.2-Linux-x86_64.tar.gz"
       mkdir cmake && travis_retry wget --no-check-certificate --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake
       export PATH=${DEPS_DIR}/cmake/bin:${PATH}
     elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
@@ -202,25 +301,24 @@
   # Regenerate single header file, so it is tested in the examples...
   - python scripts/generateSingleHeader.py
 
-  - |
     # Use Debug builds for running Valgrind and building examples
-    cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DCATCH_USE_VALGRIND=${VALGRIND} -DCATCH_BUILD_EXAMPLES=ON -DCATCH_ENABLE_COVERAGE=ON
+  - cmake -H. -BBuild-Debug -DCMAKE_BUILD_TYPE=Debug -Wdev -DUSE_CPP14=${CPP14} -DUSE_CPP17=${CPP17} -DCATCH_USE_VALGRIND=${VALGRIND} -DCATCH_BUILD_EXAMPLES=${EXAMPLES} -DCATCH_ENABLE_COVERAGE=${COVERAGE} -DCATCH_BUILD_EXTRA_TESTS=${EXTRAS}
     # Don't bother with release build for coverage build
-    cmake -H. -BBuild-Release -DCMAKE_BUILD_TYPE=Release -Wdev -DUSE_CPP14=${CPP14}
+  - cmake -H. -BBuild-Release -DCMAKE_BUILD_TYPE=Release -Wdev -DUSE_CPP14=${CPP14} -DUSE_CPP17=${CPP17}
 
 
 script:
-  - |
-    cd Build-Debug
-    make -j 2
-    CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
+  - cd Build-Debug
+  - make -j 2
+  - CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
     # Coverage collection does not work for OS X atm
-    if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
+  - |
+    if [[ "${TRAVIS_OS_NAME}" == "linux" ]] && [[ "${COVERAGE}" == "1" ]]; then
       make gcov
       make lcov
       bash <(curl -s https://codecov.io/bash) -X gcov || echo "Codecov did not collect coverage reports"
     fi
-    # Go to release build
-    cd ../Build-Release
-    make -j 2
-    CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
+  - # Go to release build
+  - cd ../Build-Release
+  - make -j 2
+  - CTEST_OUTPUT_ON_FAILURE=1 ctest -j 2
diff --git a/Android.bp b/Android.bp
index 42df9d6..4852cf0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -18,6 +18,7 @@
     local_include_dirs: ["include"],  // cc_test ignores export_include_dirs
     export_include_dirs: ["include"],
     srcs: ["include/**/*.cpp"],
+    exclude_srcs: ["include/catch_with_main.cpp"],
 }
 
 // !!! IMPORTANT: Use 'whole_static_libs' or the linker will dead-code-eliminate
@@ -33,9 +34,7 @@
         "libcatch2-defaults",
     ],
     srcs: [
-        // cannot use catch_with_main.hpp as main, soong errors with "has unknown extension"
-        // "include/catch_with_main.hpp",
-        "examples/000-CatchMain.cpp",
+        "include/catch_with_main.cpp",
     ],
 }
 
@@ -46,6 +45,7 @@
     defaults: [
         "libcatch2-defaults",
     ],
+    cflags: ["-DCATCH_CONFIG_DISABLE_EXCEPTIONS"],
 }
 
 // This rule can be used by other external/ projects that depend on catch2
@@ -55,7 +55,6 @@
     defaults: [
         "libcatch2-defaults",
     ],
-    rtti: true,
     cflags: ["-fexceptions"],
 }
 
@@ -74,7 +73,7 @@
     ],
 }
 
-// Upstream config: RTTI and exceptions are enabled.
+// Upstream config: Exceptions are enabled.
 // This should be validated first after an upstream merge.
 cc_test {
     name: "libcatch2-tests-upstream",
@@ -83,7 +82,6 @@
     ],
 
     gtest: false,
-    rtti: true,
     cflags: ["-fexceptions"],
 
     whole_static_libs: [
@@ -91,13 +89,17 @@
     ],
 }
 
-// Android config: RTTI and exceptions are disabled.
+// Android config: Exceptions are disabled.
 // This should be validated second after an upstream merge.
 cc_test {
     name: "libcatch2-tests",
     defaults: [
         "libcatch2-defaults-tests",
     ],
+    cflags: [
+        "-DCATCH_CONFIG_DISABLE_EXCEPTIONS",
+        "-Wno-unused-function",
+    ],
     gtest: false,
     whole_static_libs: [
         "libcatch2",
diff --git a/CMake/Catch2Config.cmake.in b/CMake/Catch2Config.cmake.in
new file mode 100644
index 0000000..c485219
--- /dev/null
+++ b/CMake/Catch2Config.cmake.in
@@ -0,0 +1,10 @@
+@PACKAGE_INIT@
+
+
+# Avoid repeatedly including the targets
+if(NOT TARGET Catch2::Catch2)
+    # Provide path for scripts
+    list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
+
+    include(${CMAKE_CURRENT_LIST_DIR}/Catch2Targets.cmake)
+endif()
diff --git a/CMake/MiscFunctions.cmake b/CMake/MiscFunctions.cmake
new file mode 100644
index 0000000..262f7cd
--- /dev/null
+++ b/CMake/MiscFunctions.cmake
@@ -0,0 +1,26 @@
+#checks that the given hard-coded list contains all headers + sources in the given folder
+function(CheckFileList LIST_VAR FOLDER)
+  set(MESSAGE " should be added to the variable ${LIST_VAR}")
+  set(MESSAGE "${MESSAGE} in ${CMAKE_CURRENT_LIST_FILE}\n")
+  file(GLOB GLOBBED_LIST "${FOLDER}/*.cpp"
+                         "${FOLDER}/*.hpp"
+                         "${FOLDER}/*.h")
+  list(REMOVE_ITEM GLOBBED_LIST ${${LIST_VAR}})
+  foreach(EXTRA_ITEM ${GLOBBED_LIST})
+    string(REPLACE "${CATCH_DIR}/" "" RELATIVE_FILE_NAME "${EXTRA_ITEM}")
+    message(AUTHOR_WARNING "The file \"${RELATIVE_FILE_NAME}\"${MESSAGE}")
+  endforeach()
+endfunction()
+
+function(CheckFileListRec LIST_VAR FOLDER)
+  set(MESSAGE " should be added to the variable ${LIST_VAR}")
+  set(MESSAGE "${MESSAGE} in ${CMAKE_CURRENT_LIST_FILE}\n")
+  file(GLOB_RECURSE GLOBBED_LIST "${FOLDER}/*.cpp"
+                                 "${FOLDER}/*.hpp"
+                                 "${FOLDER}/*.h")
+  list(REMOVE_ITEM GLOBBED_LIST ${${LIST_VAR}})
+  foreach(EXTRA_ITEM ${GLOBBED_LIST})
+    string(REPLACE "${CATCH_DIR}/" "" RELATIVE_FILE_NAME "${EXTRA_ITEM}")
+    message(AUTHOR_WARNING "The file \"${RELATIVE_FILE_NAME}\"${MESSAGE}")
+  endforeach()
+endfunction()
diff --git a/CMake/catch2.pc.in b/CMake/catch2.pc.in
new file mode 100644
index 0000000..3ac9fbd
--- /dev/null
+++ b/CMake/catch2.pc.in
@@ -0,0 +1,7 @@
+includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
+
+Name: Catch2
+Description: A modern, C++-native, header-only, test framework for C++11
+URL: https://github.com/catchorg/Catch2
+Version: @Catch2_VERSION@
+Cflags: -I${includedir}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 19472de..ea35d24 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.0)
+cmake_minimum_required(VERSION 3.5)
 
 # detect if Catch is being bundled,
 # disable testsuite in that case
@@ -6,14 +6,24 @@
   set(NOT_SUBPROJECT ON)
 endif()
 
-project(Catch2 LANGUAGES CXX VERSION 2.1.1)
+project(Catch2 LANGUAGES CXX VERSION 2.7.0)
+
+# Provide path for scripts
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
 
 include(GNUInstallDirs)
+include(CMakePackageConfigHelpers)
+include(CTest)
 
 option(CATCH_USE_VALGRIND "Perform SelfTests with Valgrind" OFF)
+option(CATCH_BUILD_TESTING "Build SelfTest project" ON)
 option(CATCH_BUILD_EXAMPLES "Build documentation examples" OFF)
+option(CATCH_BUILD_EXTRA_TESTS "Build extra tests" OFF)
 option(CATCH_ENABLE_COVERAGE "Generate coverage for codecov.io" OFF)
 option(CATCH_ENABLE_WERROR "Enable all warnings as errors" ON)
+option(CATCH_INSTALL_DOCS "Install documentation alongside library" ON)
+option(CATCH_INSTALL_HELPERS "Install contrib alongside library" ON)
+
 
 set_property(GLOBAL PROPERTY USE_FOLDERS ON)
 
@@ -27,381 +37,172 @@
     set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ENTRY:wmainCRTStartup")
 endif()
 
-#checks that the given hard-coded list contains all headers + sources in the given folder
-function(CheckFileList LIST_VAR FOLDER)
-  set(MESSAGE " should be added to the variable ${LIST_VAR}")
-  set(MESSAGE "${MESSAGE} in ${CMAKE_CURRENT_LIST_FILE}\n")
-  file(GLOB GLOBBED_LIST "${FOLDER}/*.cpp"
-                         "${FOLDER}/*.hpp"
-                         "${FOLDER}/*.h")
-  list(REMOVE_ITEM GLOBBED_LIST ${${LIST_VAR}})
-  foreach(EXTRA_ITEM ${GLOBBED_LIST})
-    string(REPLACE "${CATCH_DIR}/" "" RELATIVE_FILE_NAME "${EXTRA_ITEM}")
-    message(AUTHOR_WARNING "The file \"${RELATIVE_FILE_NAME}\"${MESSAGE}")
-  endforeach()
-endfunction()
-
-function(CheckFileListRec LIST_VAR FOLDER)
-  set(MESSAGE " should be added to the variable ${LIST_VAR}")
-  set(MESSAGE "${MESSAGE} in ${CMAKE_CURRENT_LIST_FILE}\n")
-  file(GLOB_RECURSE GLOBBED_LIST "${FOLDER}/*.cpp"
-                                 "${FOLDER}/*.hpp"
-                                 "${FOLDER}/*.h")
-  list(REMOVE_ITEM GLOBBED_LIST ${${LIST_VAR}})
-  foreach(EXTRA_ITEM ${GLOBBED_LIST})
-    string(REPLACE "${CATCH_DIR}/" "" RELATIVE_FILE_NAME "${EXTRA_ITEM}")
-    message(AUTHOR_WARNING "The file \"${RELATIVE_FILE_NAME}\"${MESSAGE}")
-  endforeach()
-endfunction()
-
-# define the sources of the self test
-# Please keep these ordered alphabetically
-set(TEST_SOURCES
-        ${SELF_TEST_DIR}/TestMain.cpp
-        ${SELF_TEST_DIR}/IntrospectiveTests/CmdLine.tests.cpp
-        ${SELF_TEST_DIR}/IntrospectiveTests/PartTracker.tests.cpp
-        ${SELF_TEST_DIR}/IntrospectiveTests/TagAlias.tests.cpp
-        ${SELF_TEST_DIR}/IntrospectiveTests/String.tests.cpp
-        ${SELF_TEST_DIR}/IntrospectiveTests/Xml.tests.cpp
-        ${SELF_TEST_DIR}/UsageTests/Approx.tests.cpp
-        ${SELF_TEST_DIR}/UsageTests/BDD.tests.cpp
-        ${SELF_TEST_DIR}/UsageTests/Benchmark.tests.cpp
-        ${SELF_TEST_DIR}/UsageTests/Class.tests.cpp
-        ${SELF_TEST_DIR}/UsageTests/Compilation.tests.cpp
-        ${SELF_TEST_DIR}/UsageTests/Condition.tests.cpp
-        ${SELF_TEST_DIR}/UsageTests/Decomposition.tests.cpp
-        ${SELF_TEST_DIR}/UsageTests/EnumToString.tests.cpp
-        ${SELF_TEST_DIR}/UsageTests/Exception.tests.cpp
-        ${SELF_TEST_DIR}/UsageTests/Message.tests.cpp
-        ${SELF_TEST_DIR}/UsageTests/Misc.tests.cpp
-        ${SELF_TEST_DIR}/UsageTests/ToStringChrono.tests.cpp
-        ${SELF_TEST_DIR}/UsageTests/ToStringGeneral.tests.cpp
-        ${SELF_TEST_DIR}/UsageTests/ToStringPair.tests.cpp
-        ${SELF_TEST_DIR}/UsageTests/ToStringTuple.tests.cpp
-        ${SELF_TEST_DIR}/UsageTests/ToStringVector.tests.cpp
-        ${SELF_TEST_DIR}/UsageTests/ToStringWhich.tests.cpp
-        ${SELF_TEST_DIR}/UsageTests/Tricky.tests.cpp
-        ${SELF_TEST_DIR}/UsageTests/VariadicMacros.tests.cpp
-        ${SELF_TEST_DIR}/UsageTests/Matchers.tests.cpp
-        )
-CheckFileList(TEST_SOURCES ${SELF_TEST_DIR})
-
-# A set of impl files that just #include a single header
-# Please keep these ordered alphabetically
-set(SURROGATE_SOURCES
-        ${SELF_TEST_DIR}/SurrogateCpps/catch_console_colour.cpp
-        ${SELF_TEST_DIR}/SurrogateCpps/catch_debugger.cpp
-        ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_reporter.cpp
-        ${SELF_TEST_DIR}/SurrogateCpps/catch_option.cpp
-        ${SELF_TEST_DIR}/SurrogateCpps/catch_stream.cpp
-        ${SELF_TEST_DIR}/SurrogateCpps/catch_test_case_tracker.cpp
-        ${SELF_TEST_DIR}/SurrogateCpps/catch_test_spec.cpp
-        ${SELF_TEST_DIR}/SurrogateCpps/catch_xmlwriter.cpp
-        )
-CheckFileList(SURROGATE_SOURCES ${SELF_TEST_DIR}/SurrogateCpps)
-
-
-# Please keep these ordered alphabetically
-set(TOP_LEVEL_HEADERS
-        ${HEADER_DIR}/catch.hpp
-        ${HEADER_DIR}/catch_with_main.hpp
-        )
-CheckFileList(TOP_LEVEL_HEADERS ${HEADER_DIR})
-
-# Please keep these ordered alphabetically
-set(EXTERNAL_HEADERS
-        ${HEADER_DIR}/external/clara.hpp
-        )
-CheckFileList(EXTERNAL_HEADERS ${HEADER_DIR}/external)
-
-
-# Please keep these ordered alphabetically
-set(INTERNAL_HEADERS
-        ${HEADER_DIR}/internal/catch_approx.h
-        ${HEADER_DIR}/internal/catch_assertionhandler.h
-        ${HEADER_DIR}/internal/catch_assertioninfo.h
-        ${HEADER_DIR}/internal/catch_assertionresult.h
-        ${HEADER_DIR}/internal/catch_capture.hpp
-        ${HEADER_DIR}/internal/catch_capture_matchers.h
-        ${HEADER_DIR}/internal/catch_clara.h
-        ${HEADER_DIR}/internal/catch_commandline.h
-        ${HEADER_DIR}/internal/catch_common.h
-        ${HEADER_DIR}/internal/catch_compiler_capabilities.h
-        ${HEADER_DIR}/internal/catch_config.hpp
-        ${HEADER_DIR}/internal/catch_console_colour.h
-        ${HEADER_DIR}/internal/catch_context.h
-        ${HEADER_DIR}/internal/catch_debug_console.h
-        ${HEADER_DIR}/internal/catch_debugger.h
-        ${HEADER_DIR}/internal/catch_decomposer.h
-        ${HEADER_DIR}/internal/catch_default_main.hpp
-        ${HEADER_DIR}/internal/catch_enforce.h
-        ${HEADER_DIR}/internal/catch_errno_guard.h
-        ${HEADER_DIR}/internal/catch_exception_translator_registry.h
-        ${HEADER_DIR}/internal/catch_external_interfaces.h
-        ${HEADER_DIR}/internal/catch_fatal_condition.h
-        ${HEADER_DIR}/internal/catch_impl.hpp
-        ${HEADER_DIR}/internal/catch_interfaces_capture.h
-        ${HEADER_DIR}/internal/catch_interfaces_config.h
-        ${HEADER_DIR}/internal/catch_interfaces_exception.h
-        ${HEADER_DIR}/internal/catch_interfaces_registry_hub.h
-        ${HEADER_DIR}/internal/catch_interfaces_reporter.h
-        ${HEADER_DIR}/internal/catch_interfaces_runner.h
-        ${HEADER_DIR}/internal/catch_interfaces_tag_alias_registry.h
-        ${HEADER_DIR}/internal/catch_interfaces_testcase.h
-        ${HEADER_DIR}/internal/catch_leak_detector.h
-        ${HEADER_DIR}/internal/catch_list.h
-        ${HEADER_DIR}/internal/catch_matchers.h
-        ${HEADER_DIR}/internal/catch_matchers_floating.h
-        ${HEADER_DIR}/internal/catch_matchers_string.h
-        ${HEADER_DIR}/internal/catch_matchers_vector.h
-        ${HEADER_DIR}/internal/catch_message.h
-        ${HEADER_DIR}/internal/catch_objc.hpp
-        ${HEADER_DIR}/internal/catch_objc_arc.hpp
-        ${HEADER_DIR}/internal/catch_option.hpp
-        ${HEADER_DIR}/internal/catch_platform.h
-        ${HEADER_DIR}/internal/catch_random_number_generator.h
-        ${HEADER_DIR}/internal/catch_reenable_warnings.h
-        ${HEADER_DIR}/internal/catch_reporter_registrars.hpp
-        ${HEADER_DIR}/internal/catch_reporter_registry.h
-        ${HEADER_DIR}/internal/catch_result_type.h
-        ${HEADER_DIR}/internal/catch_run_context.h
-        ${HEADER_DIR}/internal/catch_benchmark.h
-        ${HEADER_DIR}/internal/catch_section.h
-        ${HEADER_DIR}/internal/catch_section_info.h
-        ${HEADER_DIR}/internal/catch_session.h
-        ${HEADER_DIR}/internal/catch_startup_exception_registry.h
-        ${HEADER_DIR}/internal/catch_stream.h
-        ${HEADER_DIR}/internal/catch_stringref.h
-        ${HEADER_DIR}/internal/catch_string_manip.h
-        ${HEADER_DIR}/internal/catch_suppress_warnings.h
-        ${HEADER_DIR}/internal/catch_tag_alias.h
-        ${HEADER_DIR}/internal/catch_tag_alias_autoregistrar.h
-        ${HEADER_DIR}/internal/catch_tag_alias_registry.h
-        ${HEADER_DIR}/internal/catch_test_case_info.h
-        ${HEADER_DIR}/internal/catch_test_case_registry_impl.h
-        ${HEADER_DIR}/internal/catch_test_case_tracker.h
-        ${HEADER_DIR}/internal/catch_test_registry.h
-        ${HEADER_DIR}/internal/catch_test_spec.h
-        ${HEADER_DIR}/internal/catch_test_spec_parser.h
-        ${HEADER_DIR}/internal/catch_text.h
-        ${HEADER_DIR}/internal/catch_timer.h
-        ${HEADER_DIR}/internal/catch_tostring.h
-        ${HEADER_DIR}/internal/catch_totals.h
-        ${HEADER_DIR}/internal/catch_uncaught_exceptions.h
-        ${HEADER_DIR}/internal/catch_user_interfaces.h
-        ${HEADER_DIR}/internal/catch_version.h
-        ${HEADER_DIR}/internal/catch_wildcard_pattern.h
-        ${HEADER_DIR}/internal/catch_windows_h_proxy.h
-        ${HEADER_DIR}/internal/catch_xmlwriter.h
-        )
-set(IMPL_SOURCES
-        ${HEADER_DIR}/internal/catch_approx.cpp
-        ${HEADER_DIR}/internal/catch_assertionhandler.cpp
-        ${HEADER_DIR}/internal/catch_assertionresult.cpp
-        ${HEADER_DIR}/internal/catch_benchmark.cpp
-        ${HEADER_DIR}/internal/catch_capture_matchers.cpp
-        ${HEADER_DIR}/internal/catch_commandline.cpp
-        ${HEADER_DIR}/internal/catch_common.cpp
-        ${HEADER_DIR}/internal/catch_config.cpp
-        ${HEADER_DIR}/internal/catch_console_colour.cpp
-        ${HEADER_DIR}/internal/catch_context.cpp
-        ${HEADER_DIR}/internal/catch_debug_console.cpp
-        ${HEADER_DIR}/internal/catch_debugger.cpp
-        ${HEADER_DIR}/internal/catch_decomposer.cpp
-        ${HEADER_DIR}/internal/catch_errno_guard.cpp
-        ${HEADER_DIR}/internal/catch_exception_translator_registry.cpp
-        ${HEADER_DIR}/internal/catch_fatal_condition.cpp
-        ${HEADER_DIR}/internal/catch_interfaces_capture.cpp
-        ${HEADER_DIR}/internal/catch_interfaces_config.cpp
-        ${HEADER_DIR}/internal/catch_interfaces_exception.cpp
-        ${HEADER_DIR}/internal/catch_interfaces_registry_hub.cpp
-        ${HEADER_DIR}/internal/catch_interfaces_runner.cpp
-        ${HEADER_DIR}/internal/catch_interfaces_testcase.cpp
-        ${HEADER_DIR}/internal/catch_list.cpp
-        ${HEADER_DIR}/internal/catch_leak_detector.cpp
-        ${HEADER_DIR}/internal/catch_matchers.cpp
-        ${HEADER_DIR}/internal/catch_matchers_floating.cpp
-        ${HEADER_DIR}/internal/catch_matchers_string.cpp
-        ${HEADER_DIR}/internal/catch_message.cpp
-        ${HEADER_DIR}/internal/catch_registry_hub.cpp
-        ${HEADER_DIR}/internal/catch_interfaces_reporter.cpp
-        ${HEADER_DIR}/internal/catch_random_number_generator.cpp
-        ${HEADER_DIR}/internal/catch_reporter_registry.cpp
-        ${HEADER_DIR}/internal/catch_result_type.cpp
-        ${HEADER_DIR}/internal/catch_run_context.cpp
-        ${HEADER_DIR}/internal/catch_section.cpp
-        ${HEADER_DIR}/internal/catch_section_info.cpp
-        ${HEADER_DIR}/internal/catch_session.cpp
-        ${HEADER_DIR}/internal/catch_startup_exception_registry.cpp
-        ${HEADER_DIR}/internal/catch_stream.cpp
-        ${HEADER_DIR}/internal/catch_stringref.cpp
-        ${HEADER_DIR}/internal/catch_string_manip.cpp
-        ${HEADER_DIR}/internal/catch_tag_alias.cpp
-        ${HEADER_DIR}/internal/catch_tag_alias_autoregistrar.cpp
-        ${HEADER_DIR}/internal/catch_tag_alias_registry.cpp
-        ${HEADER_DIR}/internal/catch_test_case_info.cpp
-        ${HEADER_DIR}/internal/catch_test_case_registry_impl.cpp
-        ${HEADER_DIR}/internal/catch_test_case_tracker.cpp
-        ${HEADER_DIR}/internal/catch_test_registry.cpp
-        ${HEADER_DIR}/internal/catch_test_spec.cpp
-        ${HEADER_DIR}/internal/catch_test_spec_parser.cpp
-        ${HEADER_DIR}/internal/catch_timer.cpp
-        ${HEADER_DIR}/internal/catch_tostring.cpp
-        ${HEADER_DIR}/internal/catch_totals.cpp
-        ${HEADER_DIR}/internal/catch_uncaught_exceptions.cpp
-        ${HEADER_DIR}/internal/catch_version.cpp
-        ${HEADER_DIR}/internal/catch_wildcard_pattern.cpp
-        ${HEADER_DIR}/internal/catch_xmlwriter.cpp
-        )
-set(INTERNAL_FILES ${IMPL_SOURCES} ${INTERNAL_HEADERS})
-CheckFileList(INTERNAL_FILES ${HEADER_DIR}/internal)
-
-# Please keep these ordered alphabetically
-set(REPORTER_HEADERS
-        ${HEADER_DIR}/reporters/catch_reporter_automake.hpp
-        ${HEADER_DIR}/reporters/catch_reporter_bases.hpp
-        ${HEADER_DIR}/reporters/catch_reporter_compact.h
-        ${HEADER_DIR}/reporters/catch_reporter_console.h
-        ${HEADER_DIR}/reporters/catch_reporter_junit.h
-        ${HEADER_DIR}/reporters/catch_reporter_multi.h
-        ${HEADER_DIR}/reporters/catch_reporter_tap.hpp
-        ${HEADER_DIR}/reporters/catch_reporter_teamcity.hpp
-        ${HEADER_DIR}/reporters/catch_reporter_xml.h
-        )
-set(REPORTER_SOURCES
-        ${HEADER_DIR}/reporters/catch_reporter_bases.cpp
-        ${HEADER_DIR}/reporters/catch_reporter_compact.cpp
-        ${HEADER_DIR}/reporters/catch_reporter_console.cpp
-        ${HEADER_DIR}/reporters/catch_reporter_junit.cpp
-        ${HEADER_DIR}/reporters/catch_reporter_multi.cpp
-        ${HEADER_DIR}/reporters/catch_reporter_xml.cpp
-        )
-set(REPORTER_FILES ${REPORTER_HEADERS} ${REPORTER_SOURCES})
-CheckFileList(REPORTER_FILES ${HEADER_DIR}/reporters)
-
-# Specify the headers, too, so CLion recognises them as project files
-set(HEADERS
-        ${TOP_LEVEL_HEADERS}
-        ${EXTERNAL_HEADERS}
-        ${INTERNAL_HEADERS}
-        ${REPORTER_HEADERS}
-        )
-
-# Provide some groupings for IDEs
-SOURCE_GROUP("Tests" FILES ${TEST_SOURCES})
-SOURCE_GROUP("Surrogates" FILES ${SURROGATE_SOURCES})
-
-
-# Projects consuming Catch via ExternalProject_Add might want to use install step
-# without building all of our selftests.
-
-if(DEFINED NO_SELFTEST)
-    message(DEPRECATION "*** CMake option NO_SELFTEST is deprecated; use BUILD_TESTING instead")
-    if (NO_SELFTEST)
-        set(BUILD_TESTING OFF CACHE BOOL "Disable Catch2 internal testsuite" FORCE)
-    else()
-        set(BUILD_TESTING ON CACHE BOOL "Disable Catch2 internal testsuite" FORCE)
+if (BUILD_TESTING AND CATCH_BUILD_TESTING AND NOT_SUBPROJECT)
+    find_package(PythonInterp)
+    if (NOT PYTHONINTERP_FOUND)
+        message(FATAL_ERROR "Python not found, but required for tests")
     endif()
+    add_subdirectory(projects)
 endif()
 
-include(CTest)
-
-if (BUILD_TESTING AND NOT_SUBPROJECT)
-    add_executable(SelfTest ${TEST_SOURCES} ${IMPL_SOURCES} ${REPORTER_SOURCES} ${SURROGATE_SOURCES} ${HEADERS})
-    target_include_directories(SelfTest PRIVATE ${HEADER_DIR})
-
-    if(USE_CPP14)
-        message(STATUS "Enabling C++14")
-        set_property(TARGET SelfTest PROPERTY CXX_STANDARD 14)
-    else()
-        message(STATUS "Enabling C++11")
-        set_property(TARGET SelfTest PROPERTY CXX_STANDARD 11)
-    endif()
-
-    set_property(TARGET SelfTest PROPERTY CXX_STANDARD_REQUIRED ON)
-    set_property(TARGET SelfTest PROPERTY CXX_EXTENSIONS OFF)
-
-    if (CATCH_ENABLE_COVERAGE)
-        set(ENABLE_COVERAGE ON CACHE BOOL "Enable coverage build." FORCE)
-        list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
-        find_package(codecov)
-        add_coverage(SelfTest)
-        list(APPEND LCOV_REMOVE_PATTERNS "'/usr/*'")
-        coverage_evaluate()
-    endif()
-
-    # Add desired warnings
-    if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )
-        target_compile_options( SelfTest PRIVATE -Wall -Wextra -Wunreachable-code -Wpedantic)
-        if (CATCH_ENABLE_WERROR)
-            target_compile_options( SelfTest PRIVATE -Werror)
-        endif()
-    endif()
-    # Clang specific warning go here
-    if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
-        # Actually keep these
-        target_compile_options( SelfTest PRIVATE -Wweak-vtables -Wexit-time-destructors -Wglobal-constructors -Wmissing-noreturn )
-    endif()
-    if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" )
-		STRING(REGEX REPLACE "/W[0-9]" "/W4" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) # override default warning level
-        target_compile_options( SelfTest PRIVATE /w44265 /w44061 /w44062 )
-        if (CATCH_ENABLE_WERROR)
-            target_compile_options( SelfTest PRIVATE /WX)
-        endif()
-    endif()
-
-
-    # configure unit tests via CTest
-    include(CTest)
-    add_test(NAME RunTests COMMAND $<TARGET_FILE:SelfTest>)
-
-    add_test(NAME ListTests COMMAND $<TARGET_FILE:SelfTest> --list-tests --verbosity high)
-    set_tests_properties(ListTests PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ test cases")
-
-    add_test(NAME ListTags COMMAND $<TARGET_FILE:SelfTest> --list-tags)
-    set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags")
-
-    add_test(NAME ListReporters COMMAND $<TARGET_FILE:SelfTest> --list-reporters)
-    set_tests_properties(ListReporters PROPERTIES PASS_REGULAR_EXPRESSION "Available reporters:")
-
-    add_test(NAME ListTestNamesOnly COMMAND $<TARGET_FILE:SelfTest> --list-test-names-only)
-    set_tests_properties(ListTestNamesOnly PROPERTIES PASS_REGULAR_EXPRESSION "Regex string matcher")
-
-
-
-    # AppVeyor has a Python 2.7 in path, but doesn't have .py files as autorunnable
-    add_test(NAME ApprovalTests COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/scripts/approvalTests.py $<TARGET_FILE:SelfTest>)
-    set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed")
-
-    if (CATCH_USE_VALGRIND)
-        add_test(NAME ValgrindRunTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest>)
-        add_test(NAME ValgrindListTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tests --verbosity high)
-        set_tests_properties(ValgrindListTests PROPERTIES PASS_REGULAR_EXPRESSION "definitely lost: 0 bytes in 0 blocks")
-        add_test(NAME ValgrindListTags COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tags)
-        set_tests_properties(ValgrindListTags PROPERTIES PASS_REGULAR_EXPRESSION "definitely lost: 0 bytes in 0 blocks")
-    endif()
-
-endif() # !NO_SELFTEST
-
-
 if(CATCH_BUILD_EXAMPLES)
     add_subdirectory(examples)
 endif()
 
-install(DIRECTORY "single_include/" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/catch")
+if(CATCH_BUILD_EXTRA_TESTS)
+    add_subdirectory(projects/ExtraTests)
+endif()
 
-install(DIRECTORY docs/ DESTINATION "${CMAKE_INSTALL_DOCDIR}")
+# add catch as a 'linkable' target
+add_library(Catch2 INTERFACE)
 
-## Provide some pkg-config integration
-# Don't bother on Windows
-if(NOT WIN32 OR NOT CMAKE_HOST_SYSTEM_NAME MATCHES Windows)
 
-    set(PKGCONFIG_INSTALL_DIR
-        "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig"
-        CACHE PATH "Path where catch.pc is installed"
+
+# depend on some obvious c++11 features so the dependency is transitively added dependents
+target_compile_features(Catch2
+  INTERFACE
+    cxx_alignas
+    cxx_alignof
+    cxx_attributes
+    cxx_auto_type
+    cxx_constexpr
+    cxx_defaulted_functions
+    cxx_deleted_functions
+    cxx_final
+    cxx_lambdas
+    cxx_noexcept
+    cxx_override
+    cxx_range_for
+    cxx_rvalue_references
+    cxx_static_assert
+    cxx_strong_enums
+    cxx_trailing_return_types
+    cxx_unicode_literals
+    cxx_user_literals
+    cxx_variadic_macros
+)
+
+target_include_directories(Catch2
+  INTERFACE
+    $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/single_include>
+    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+)
+
+# provide a namespaced alias for clients to 'link' against if catch is included as a sub-project
+add_library(Catch2::Catch2 ALIAS Catch2)
+
+# Only perform the installation steps when Catch is not being used as
+# a subproject via `add_subdirectory`, or the destinations will break,
+# see https://github.com/catchorg/Catch2/issues/1373
+if (NOT_SUBPROJECT)
+    set(CATCH_CMAKE_CONFIG_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Catch2")
+
+    configure_package_config_file(
+        ${CMAKE_CURRENT_LIST_DIR}/CMake/Catch2Config.cmake.in
+        ${CMAKE_CURRENT_BINARY_DIR}/Catch2Config.cmake
+        INSTALL_DESTINATION
+          ${CATCH_CMAKE_CONFIG_DESTINATION}
     )
 
-    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/catch.pc.in ${CMAKE_CURRENT_BINARY_DIR}/catch.pc @ONLY)
-    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/catch.pc DESTINATION ${PKGCONFIG_INSTALL_DIR})
 
-endif()
+    # create and install an export set for catch target as Catch2::Catch
+    install(
+      TARGETS
+        Catch2
+      EXPORT
+        Catch2Targets
+      DESTINATION
+        ${CMAKE_INSTALL_LIBDIR}
+    )
+
+
+    install(
+      EXPORT
+        Catch2Targets
+      NAMESPACE
+        Catch2::
+      DESTINATION
+        ${CATCH_CMAKE_CONFIG_DESTINATION}
+    )
+
+    # By default, FooConfigVersion is tied to architecture that it was
+    # generated on. Because Catch2 is header-only, it is arch-independent
+    # and thus Catch2ConfigVersion should not be tied to the architecture
+    # it was generated on.
+    #
+    # CMake does not provide a direct customization point for this in
+    # `write_basic_package_version_file`, but it can be accomplished
+    # indirectly by temporarily undefining `CMAKE_SIZEOF_VOID_P`.
+    set(CATCH2_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})
+    unset(CMAKE_SIZEOF_VOID_P)
+    write_basic_package_version_file(
+      "${CMAKE_CURRENT_BINARY_DIR}/Catch2ConfigVersion.cmake"
+      COMPATIBILITY
+        SameMajorVersion
+    )
+    set(CMAKE_SIZEOF_VOID_P ${CATCH2_CMAKE_SIZEOF_VOID_P})
+
+    install(
+      DIRECTORY
+        "single_include/"
+      DESTINATION
+        "${CMAKE_INSTALL_INCLUDEDIR}"
+    )
+
+    install(
+      FILES
+        "${CMAKE_CURRENT_BINARY_DIR}/Catch2Config.cmake"
+        "${CMAKE_CURRENT_BINARY_DIR}/Catch2ConfigVersion.cmake"
+      DESTINATION
+        ${CATCH_CMAKE_CONFIG_DESTINATION}
+    )
+
+    # Install documentation
+    if(CATCH_INSTALL_DOCS)
+      install(
+        DIRECTORY
+          docs/
+        DESTINATION
+          "${CMAKE_INSTALL_DOCDIR}"
+      )
+    endif()
+
+    if(CATCH_INSTALL_HELPERS)
+    # Install CMake scripts
+    install(
+      FILES
+        "contrib/ParseAndAddCatchTests.cmake"
+        "contrib/Catch.cmake"
+        "contrib/CatchAddTests.cmake"
+      DESTINATION
+        ${CATCH_CMAKE_CONFIG_DESTINATION}
+    )
+
+    # Install debugger helpers
+    install(
+      FILES
+        "contrib/gdbinit"
+        "contrib/lldbinit"
+      DESTINATION
+        ${CMAKE_INSTALL_DATAROOTDIR}/Catch2
+    )
+    endif()
+
+    ## Provide some pkg-config integration
+    set(PKGCONFIG_INSTALL_DIR
+        "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig"
+        CACHE PATH "Path where catch2.pc is installed"
+    )
+    configure_file(
+      ${CMAKE_CURRENT_SOURCE_DIR}/CMake/catch2.pc.in
+      ${CMAKE_CURRENT_BINARY_DIR}/catch2.pc
+      @ONLY
+    )
+    install(
+      FILES
+        "${CMAKE_CURRENT_BINARY_DIR}/catch2.pc"
+      DESTINATION
+        ${PKGCONFIG_INSTALL_DIR}
+    )
+
+endif(NOT_SUBPROJECT)
diff --git a/METADATA b/METADATA
index 03fb27c..cf98e4a 100644
--- a/METADATA
+++ b/METADATA
@@ -13,7 +13,7 @@
     type: GIT
     value: "https://github.com/catchorg/Catch2.git"
   }
-  version: "62dae592c330ab74cea30c897255ee9518639c3f"
-  last_upgrade_date { year: 2018 month: 2 day: 6 }
+  version: "v2.7.0"
+  last_upgrade_date { year: 2019 month: 3 day: 7 }
   license_type: NOTICE
 }
diff --git a/README.md b/README.md
index 1c2c03b..08095f1 100644
--- a/README.md
+++ b/README.md
@@ -5,9 +5,11 @@
 [![Build Status](https://travis-ci.org/catchorg/Catch2.svg?branch=master)](https://travis-ci.org/catchorg/Catch2)
 [![Build status](https://ci.appveyor.com/api/projects/status/github/catchorg/Catch2?svg=true)](https://ci.appveyor.com/project/catchorg/catch2)
 [![codecov](https://codecov.io/gh/catchorg/Catch2/branch/master/graph/badge.svg)](https://codecov.io/gh/catchorg/Catch2)
-[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/TpIcJaLaH4WrKlhS)
+[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/byNJIivVphHo170P)
+[![Join the chat in Discord: https://discord.gg/4CWS9zD](https://img.shields.io/badge/Discord-Chat!-brightgreen.svg)](https://discord.gg/4CWS9zD)
 
-<a href="https://github.com/catchorg/Catch2/releases/download/v2.1.1/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
+
+<a href="https://github.com/catchorg/Catch2/releases/download/v2.7.0/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
 
 ## Catch2 is released!
 
@@ -32,5 +34,5 @@
 
 ## More
 * Issues and bugs can be raised on the [Issue tracker on GitHub](https://github.com/catchorg/Catch2/issues)
-* For discussion or questions please use [the dedicated Google Groups forum](https://groups.google.com/forum/?fromgroups#!forum/catch-forum)
+* For discussion or questions please use [the dedicated Google Groups forum](https://groups.google.com/forum/?fromgroups#!forum/catch-forum) or our [Discord](https://discord.gg/4CWS9zD)
 * See [who else is using Catch2](docs/opensource-users.md#top)
diff --git a/appveyor.yml b/appveyor.yml
index 2d68172..53f5b39 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -19,18 +19,51 @@
 
         - additional_flags: "/D_UNICODE /DUNICODE"
           wmain: 1
+          coverage: 0
+
+        # Have a coverage dimension
+        - additional_flags: ""
+          wmain: 0
+          coverage: 1
+
+        # Have an examples dimension
+        - additional_flags: ""
+          wmain: 0
+          examples: 1
+
 
 matrix:
     exclude:
         - os: Visual Studio 2015
           additional_flags: "/permissive- /std:c++latest"
 
-init:
-  - git config --global core.autocrlf input
+        - os: Visual Studio 2015
+          additional_flags: "/D_UNICODE /DUNICODE"
+
+        # Exclude unwanted coverage configurations
+        - coverage: 1
+          platform: Win32
+
+        - coverage: 1
+          os: Visual Studio 2015
+
+        - coverage: 1
+          configuration: Release
+
+        # Exclude unwanted examples configurations
+        - examples: 1
+          platform: Win32
+
+        - examples: 1
+          os: Visual Studio 2015
+
+        - examples: 1
+          configuration: Release
+
 
 install:
-  - ps: if (($env:CONFIGURATION) -eq "Debug" ) { python -m pip install codecov }
-  - ps: if (($env:CONFIGURATION) -eq "Debug" ) { .\misc\installOpenCppCoverage.ps1 }
+  - ps: if (($env:CONFIGURATION) -eq "Debug" -And ($env:coverage) -eq "1" ) { python -m pip --disable-pip-version-check install codecov }
+  - ps: if (($env:CONFIGURATION) -eq "Debug" -And ($env:coverage) -eq "1" ) { .\misc\installOpenCppCoverage.ps1 }
 
 # Win32 and x64 are CMake-compatible solution platform names.
 # This allows us to pass %PLATFORM% to CMake -A.
diff --git a/catch.pc.in b/catch.pc.in
deleted file mode 100644
index abd0b66..0000000
--- a/catch.pc.in
+++ /dev/null
@@ -1,6 +0,0 @@
-includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
-
-Name: Catch
-Description: Testing library for C++
-Version: @Catch2_VERSION@
-Cflags: -I${includedir}
diff --git a/codecov.yml b/codecov.yml
index 7fd12df..94d88d8 100644
--- a/codecov.yml
+++ b/codecov.yml
@@ -6,17 +6,19 @@
     project:
       default:
         threshold: 2%
-
-codecov:
-  branch: master
-
-comment:
-  layout: "diff"
-
-coverage:
+    patch:
+      default:
+        target: 80%
   ignore:
     - "projects/SelfTest"
     - "**/catch_reporter_tap.hpp"
     - "**/catch_reporter_automake.hpp"
     - "**/catch_reporter_teamcity.hpp"
     - "**/external/clara.hpp"
+
+
+codecov:
+  branch: master
+
+comment:
+  layout: "diff"
diff --git a/conanfile.py b/conanfile.py
index fa9fdce..a7cebb9 100644
--- a/conanfile.py
+++ b/conanfile.py
@@ -1,19 +1,27 @@
 #!/usr/bin/env python
-from conans import ConanFile
+from conans import ConanFile, CMake
 
 
 class CatchConan(ConanFile):
-    name = "Catch"
-    version = "2.1.1"
+    name = "Catch2"
     description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD"
-    author = "philsquared"
+    topics = ("conan", "catch2", "header-only", "unit-test", "tdd", "bdd")
+    url = "https://github.com/catchorg/Catch2"
+    homepage = url
+    license = "BSL-1.0"
+    exports = "LICENSE.txt"
+    exports_sources = ("single_include/*", "CMakeLists.txt", "CMake/*", "contrib/*")
     generators = "cmake"
-    exports_sources = "single_include/*"
-    url = "https://github.com/philsquared/Catch"
-    license = "Boost Software License - Version 1.0. http://www.boost.org/LICENSE_1_0.txt"
 
     def package(self):
-        self.copy(pattern="catch.hpp", src="single_include", dst="include")
+        cmake = CMake(self)
+        cmake.definitions["BUILD_TESTING"] = "OFF"
+        cmake.definitions["CATCH_INSTALL_DOCS"] = "OFF"
+        cmake.definitions["CATCH_INSTALL_HELPERS"] = "ON"
+        cmake.configure()
+        cmake.install()
+
+        self.copy(pattern="LICENSE.txt", dst="licenses")
 
     def package_id(self):
-            self.info.header_only()
+        self.info.header_only()
diff --git a/contrib/CatchAddTests.cmake b/contrib/CatchAddTests.cmake
index c68921e..2220ce3 100644
--- a/contrib/CatchAddTests.cmake
+++ b/contrib/CatchAddTests.cmake
@@ -50,14 +50,15 @@
 
 # Parse output
 foreach(line ${output})
-  # Test name; strip spaces to get just the name...
-  string(REGEX REPLACE " +" "" test "${line}")
+  set(test ${line})
+  # use escape commas to handle properly test cases with commans inside the name
+  string(REPLACE "," "\\," test_name ${test})
   # ...and add to script
   add_command(add_test
     "${prefix}${test}${suffix}"
     ${TEST_EXECUTOR}
     "${TEST_EXECUTABLE}"
-    "${test}"
+    "${test_name}"
     ${extra_args}
   )
   add_command(set_tests_properties
diff --git a/contrib/ParseAndAddCatchTests.cmake b/contrib/ParseAndAddCatchTests.cmake
index cb2846d..ff4fc66 100644
--- a/contrib/ParseAndAddCatchTests.cmake
+++ b/contrib/ParseAndAddCatchTests.cmake
@@ -39,6 +39,11 @@
 #    PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS (Default OFF)                                      #
 #    -- causes CMake to rerun when file with tests changes so that new tests will be discovered    #
 #                                                                                                  #
+# One can also set (locally) the optional variable OptionalCatchTestLauncher to precise the way    #
+# a test should be run. For instance to use test MPI, one can write                                #
+#     set(OptionalCatchTestLauncher ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${NUMPROC})                 #
+# just before calling this ParseAndAddCatchTests function                                          #
+#                                                                                                  #
 #==================================================================================================#
 
 cmake_minimum_required(VERSION 2.8.8)
@@ -104,7 +109,7 @@
         # Get test type and fixture if applicable
         string(REGEX MATCH "(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^,^\"]*" TestTypeAndFixture "${TestName}")
         string(REGEX MATCH "(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)" TestType "${TestTypeAndFixture}")
-        string(REPLACE "${TestType}(" "" TestFixture "${TestTypeAndFixture}")
+        string(REGEX REPLACE "${TestType}\\([ \t]*" "" TestFixture "${TestTypeAndFixture}")
 
         # Get string parts of test definition
         string(REGEX MATCHALL "\"+([^\\^\"]|\\\\\")+\"+" TestStrings "${TestName}")
@@ -143,6 +148,9 @@
             endif()
             string(REPLACE "]" ";" Tags "${Tags}")
             string(REPLACE "[" "" Tags "${Tags}")
+        else()
+          # unset tags variable from previous loop
+          unset(Tags)
         endif()
 
         list(APPEND Labels ${Tags})
@@ -156,7 +164,7 @@
                 break()
             endif(result)
         endforeach(label)
-        if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound})
+        if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_LESS "3.9")
             PrintDebugMessage("Skipping test \"${CTestName}\" as it has [!hide], [.] or [.foo] label")
         else()
             PrintDebugMessage("Adding test \"${CTestName}\"")
@@ -164,12 +172,22 @@
                 PrintDebugMessage("Setting labels to ${Labels}")
             endif()
 
+            # Escape commas in the test spec
+            string(REPLACE "," "\\," Name ${Name})
+
             # Add the test and set its properties
-            add_test(NAME "\"${CTestName}\"" COMMAND ${TestTarget} ${Name} ${AdditionalCatchParameters})
-            set_tests_properties("\"${CTestName}\"" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran"
-                                                    LABELS "${Labels}")
+            add_test(NAME "\"${CTestName}\"" COMMAND ${OptionalCatchTestLauncher} ${TestTarget} ${Name} ${AdditionalCatchParameters})
+            # Old CMake versions do not document VERSION_GREATER_EQUAL, so we use VERSION_GREATER with 3.8 instead
+            if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_GREATER "3.8")
+                PrintDebugMessage("Setting DISABLED test property")
+                set_tests_properties("\"${CTestName}\"" PROPERTIES DISABLED ON)
+            else()
+                set_tests_properties("\"${CTestName}\"" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran"
+                                                        LABELS "${Labels}")
+            endif()
         endif()
 
+
     endforeach()
 endfunction()
 
diff --git a/contrib/gdbinit b/contrib/gdbinit
new file mode 100644
index 0000000..fb3608a
--- /dev/null
+++ b/contrib/gdbinit
@@ -0,0 +1,16 @@
+#
+# This file provides a way to skip stepping into Catch code when debugging with gdb.
+#
+# With the gdb "skip" command you can tell gdb to skip files or functions during debugging.
+# see https://xaizek.github.io/2016-05-26/skipping-standard-library-in-gdb/ for an example
+#
+# Basically the following line tells gdb to skip all functions containing the
+# regexp "Catch", which matches the complete Catch namespace.
+# If you want to skip just some parts of the Catch code you can modify the
+# regexp accordingly.
+# 
+# If you want to permanently skip stepping into Catch code copy the following
+# line into your ~/.gdbinit file
+# 
+
+skip -rfu Catch
diff --git a/contrib/lldbinit b/contrib/lldbinit
new file mode 100644
index 0000000..4f13634
--- /dev/null
+++ b/contrib/lldbinit
@@ -0,0 +1,16 @@
+#
+# This file provides a way to skip stepping into Catch code when debugging with lldb.
+#
+# With the setting "target.process.thread.step-avoid-regexp" you can tell lldb
+# to skip functions matching the regexp
+#
+# Basically the following line tells lldb to skip all functions containing the
+# regexp "Catch", which matches the complete Catch namespace.
+# If you want to skip just some parts of the Catch code you can modify the
+# regexp accordingly.
+#
+# If you want to permanently skip stepping into Catch code copy the following
+# line into your ~/.lldbinit file
+#
+
+settings set target.process.thread.step-avoid-regexp Catch
\ No newline at end of file
diff --git a/docs/Readme.md b/docs/Readme.md
index be7d1cd..721880a 100644
--- a/docs/Readme.md
+++ b/docs/Readme.md
@@ -12,6 +12,8 @@
 * [Test fixtures](test-fixtures.md#top)
 * [Reporters](reporters.md#top)
 * [Event Listeners](event-listeners.md#top)
+* [Data Generators](generators.md#top)
+* [Other macros](other-macros.md#top)
 
 Fine tuning:
 * [Supplying your own main()](own-main.md#top)
@@ -20,7 +22,10 @@
 
 Running:
 * [Command line](command-line.md#top)
-* [CI and Build system integration](build-systems.md#top)
+
+Odds and ends:
+* [CMake integration](cmake-integration.md#top)
+* [CI and other miscellaneous pieces](ci-and-misc.md#top)
 
 FAQ:
 * [Why are my tests slow to compile?](slow-compiles.md#top)
@@ -31,3 +36,4 @@
 * [Open Source Projects using Catch](opensource-users.md#top)
 * [Contributing](contributing.md#top)
 * [Release Notes](release-notes.md#top)
+* [Deprecations and incoming changes](deprecations.md#top)
diff --git a/docs/assertions.md b/docs/assertions.md
index ece4e10..900fd52 100644
--- a/docs/assertions.md
+++ b/docs/assertions.md
@@ -6,10 +6,11 @@
 [Exceptions](#exceptions)<br>
 [Matcher expressions](#matcher-expressions)<br>
 [Thread Safety](#thread-safety)<br>
+[Expressions with commas](#expressions-with-commas)<br>
 
 Most test frameworks have a large collection of assertion macros to capture all possible conditional forms (```_EQUALS```, ```_NOTEQUALS```, ```_GREATER_THAN``` etc).
 
-Catch is different. Because it decomposes natural C-style conditional expressions most of these forms are reduced to one or two that you will use all the time. That said there are a rich set of auxilliary macros as well. We'll describe all of these here.
+Catch is different. Because it decomposes natural C-style conditional expressions most of these forms are reduced to one or two that you will use all the time. That said there are a rich set of auxiliary macros as well. We'll describe all of these here.
 
 Most of these macros come in two forms:
 
@@ -54,33 +55,45 @@
 
 When comparing floating point numbers - especially if at least one of them has been computed - great care must be taken to allow for rounding errors and inexact representations.
 
-Catch provides a way to perform tolerant comparisons of floating point values through use of a wrapper class called ```Approx```. ```Approx``` can be used on either side of a comparison expression. It overloads the comparisons operators to take a tolerance into account. Here's a simple example:
+Catch provides a way to perform tolerant comparisons of floating point values through use of a wrapper class called `Approx`. `Approx` can be used on either side of a comparison expression. It overloads the comparisons operators to take a tolerance into account. Here's a simple example:
 
-```
+```cpp
 REQUIRE( performComputation() == Approx( 2.1 ) );
 ```
 
-This way `Approx` is constructed with reasonable defaults, covering most simple cases of rounding errors. If these are insufficient, each `Approx` instance has 3 tuning knobs, that can be used to customize it for your computation.
+Catch also provides a UDL for `Approx`; `_a`. It resides in
+the `Catch::literals` namespace and can be used like so:
+```cpp
+using namespace Catch::literals;
+REQUIRE( performComputation() == 2.1_a );
+```
 
-* __epsilon__ - epsilon serves to set the percentage by which a result can be erroneous, before it is rejected. By default set to `std::numeric_limits<float>::epsilon()*100`.
-* __margin__ - margin serves to set the the absolute value by which a result can be erroneous before it is rejected. By default set to `0.0`.
-* __scale__ - scale serves to adjust the epsilon's multiplicator. By default set to `0.0`.
+`Approx` is constructed with defaults that should cover most simple cases.
+For the more complex cases, `Approx` provides 3 customization points:
+
+* __epsilon__ - epsilon serves to set the coefficient by which a result
+can differ from `Approx`'s value before it is rejected.
+_By default set to `std::numeric_limits<float>::epsilon()*100`._
+* __margin__ - margin serves to set the the absolute value by which
+a result can differ from `Approx`'s value before it is rejected.
+_By default set to `0.0`._
+* __scale__ - scale is used to change the magnitude of `Approx` for relative check.
+_By default set to `0.0`._
 
 #### epsilon example
 ```cpp
 Approx target = Approx(100).epsilon(0.01);
 100.0 == target; // Obviously true
 200.0 == target; // Obviously still false
-100.5 == target; // True, because we set target to allow up to 1% error
+100.5 == target; // True, because we set target to allow up to 1% difference
 ```
 
 #### margin example
-_Margin check is used only if the relative (epsilon and scale based) check fails._
 ```cpp
 Approx target = Approx(100).margin(5);
 100.0 == target; // Obviously true
 200.0 == target; // Obviously still false
-104.0 == target; // True, because we set target to allow absolute error up to 5
+104.0 == target; // True, because we set target to allow absolute difference of at most 5
 ```
 
 #### scale
@@ -155,6 +168,34 @@
 Currently assertions in Catch are not thread safe.
 For more details, along with workarounds, see the section on [the limitations page](limitations.md#thread-safe-assertions).
 
+## Expressions with commas
+
+Because the preprocessor parses code using different rules than the
+compiler, multiple-argument assertions (e.g. `REQUIRE_THROWS_AS`) have
+problems with commas inside the provided expressions. As an example
+`REQUIRE_THROWS_AS(std::pair<int, int>(1, 2), std::invalid_argument);`
+will fail to compile, because the preprocessor sees 3 arguments provided,
+but the macro accepts only 2. There are two possible workarounds.
+
+1) Use typedef:
+```cpp
+using int_pair = std::pair<int, int>;
+REQUIRE_THROWS_AS(int_pair(1, 2), std::invalid_argument);
+```
+
+This solution is always applicable, but makes the meaning of the code
+less clear.
+
+2) Parenthesize the expression:
+```cpp
+TEST_CASE_METHOD((Fixture<int, int>), "foo", "[bar]") {
+    SUCCEED();
+}
+```
+
+This solution is not always applicable, because it might require extra
+changes on the Catch's side to work.
+
 ---
 
 [Home](Readme.md#top)
diff --git a/docs/build-systems.md b/docs/build-systems.md
deleted file mode 100644
index 2873bc6..0000000
--- a/docs/build-systems.md
+++ /dev/null
@@ -1,175 +0,0 @@
-<a id="top"></a>
-# CI and build system integration
-
-Build Systems may refer to low-level tools, like CMake, or larger systems that run on servers, like Jenkins or TeamCity. This page will talk about both.
-
-## Continuous Integration systems
-
-Probably the most important aspect to using Catch with a build server is the use of different reporters. Catch comes bundled with three reporters that should cover the majority of build servers out there - although adding more for better integration with some is always a possibility (currently we also offer TeamCity, TAP and Automake reporters).
-
-Two of these reporters are built in (XML and JUnit) and the third (TeamCity) is included as a separate header. It's possible that the other two may be split out in the future too - as that would make the core of Catch smaller for those that don't need them.
-
-### XML Reporter
-```-r xml``` 
-
-The XML Reporter writes in an XML format that is specific to Catch. 
-
-The advantage of this format is that it corresponds well to the way Catch works (especially the more unusual features, such as nested sections) and is a fully streaming format - that is it writes output as it goes, without having to store up all its results before it can start writing.
-
-The disadvantage is that, being specific to Catch, no existing build servers understand the format natively. It can be used as input to an XSLT transformation that could convert it to, say, HTML - although this loses the streaming advantage, of course.
-
-### JUnit Reporter
-```-r junit```
-
-The JUnit Reporter writes in an XML format that mimics the JUnit ANT schema.
-
-The advantage of this format is that the JUnit Ant schema is widely understood by most build servers and so can usually be consumed with no additional work.
-
-The disadvantage is that this schema was designed to correspond to how JUnit works - and there is a significant mismatch with how Catch works. Additionally the format is not streamable (because opening elements hold counts of failed and passing tests as attributes) - so the whole test run must complete before it can be written.
-
-## Other reporters
-Other reporters are not part of the single-header distribution and need
-to be downloaded and included separately. All reporters are stored in
-`single_include` directory in the git repository, and are named
-`catch_reporter_*.hpp`. For example, to use the TeamCity reporter you
-need to download `single_include/catch_reporter_teamcity.hpp` and include
-it after Catch itself.
-
-```cpp
-#define CATCH_CONFIG_MAIN
-#include "catch.hpp"
-#include "catch_reporter_teamcity.hpp"
-```
-
-### TeamCity Reporter
-```-r teamcity```
-
-The TeamCity Reporter writes TeamCity service messages to stdout. In order to be able to use this reporter an additional header must also be included.
-
-Being specific to TeamCity this is the best reporter to use with it - but it is completely unsuitable for any other purpose. It is a streaming format (it writes as it goes) - although test results don't appear in the TeamCity interface until the completion of a suite (usually the whole test run).
-
-### Automake Reporter
-```-r automake```
-
-The Automake Reporter writes out the [meta tags](https://www.gnu.org/software/automake/manual/html_node/Log-files-generation-and-test-results-recording.html#Log-files-generation-and-test-results-recording) expected by automake via `make check`.
-
-### TAP (Test Anything Protocol) Reporter
-```-r tap```
-
-Because of the incremental nature of Catch's test suites and ability to run specific tests, our implementation of TAP reporter writes out the number of tests in a suite last.
-
-## Low-level tools
-
-### Precompiled headers (PCHs)
-
-Catch offers prototypal support for being included in precompiled headers, but because of its single-header nature it does need some actions by the user:
-* The precompiled header needs to define `CATCH_CONFIG_ALL_PARTS`
-* The implementation file needs to
-  * undefine `TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED`
-  * define `CATCH_CONFIG_IMPL_ONLY`
-  * define `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`
-  * include "catch.hpp" again
-
-
-### CMake
-
-In general we recommend "vendoring" Catch's single-include releases inside your own repository. If you do this, the following example shows a minimal CMake project:
-```CMake
-cmake_minimum_required(VERSION 3.0)
-
-project(cmake_test)
-
-# Prepare "Catch" library for other executables
-set(CATCH_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/catch)
-add_library(Catch INTERFACE)
-target_include_directories(Catch INTERFACE ${CATCH_INCLUDE_DIR})
-
-# Make test executable
-set(TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
-add_executable(tests ${TEST_SOURCES})
-target_link_libraries(tests Catch)
-```
-Note that it assumes that the path to the Catch's header is `catch/catch.hpp` from the `CMakeLists.txt` file.
-
-
-You can also use the following CMake snippet to automatically fetch the entire Catch repository from github and configure it as an external project:
-```CMake
-cmake_minimum_required(VERSION 2.8.8)
-project(catch_builder CXX)
-include(ExternalProject)
-find_package(Git REQUIRED)
-
-ExternalProject_Add(
-    catch
-    PREFIX ${CMAKE_BINARY_DIR}/catch
-    GIT_REPOSITORY https://github.com/philsquared/Catch.git
-    TIMEOUT 10
-    UPDATE_COMMAND ${GIT_EXECUTABLE} pull
-    CONFIGURE_COMMAND ""
-    BUILD_COMMAND ""
-    INSTALL_COMMAND ""
-    LOG_DOWNLOAD ON
-   )
-
-# Expose required variable (CATCH_INCLUDE_DIR) to parent scope
-ExternalProject_Get_Property(catch source_dir)
-set(CATCH_INCLUDE_DIR ${source_dir}/single_include CACHE INTERNAL "Path to include folder for Catch")
-```
-
-If you put it in, e.g., `${PROJECT_SRC_DIR}/${EXT_PROJECTS_DIR}/catch/`, you can use it in your project by adding the following to your root CMake file:
-
-```CMake
-# Includes Catch in the project:
-add_subdirectory(${EXT_PROJECTS_DIR}/catch)
-include_directories(${CATCH_INCLUDE_DIR} ${COMMON_INCLUDES})
-enable_testing(true)  # Enables unit-testing.
-```
-
-The advantage of this approach is that you can always automatically update Catch to the latest release. The disadvantage is that it means bringing in lot more than you need.
-
-
-### Automatic test registration
-We provide 2 CMake scripts that can automatically register Catch-based
-tests with CTest,
-  * `contrib/ParseAndAddCatchTests.cmake`
-  * `contrib/CatchAddTests.cmake`
-
-The first is based on parsing the test implementation files, and attempts
-to register all `TEST_CASE`s using their tags as labels. This means that
-these:
-
-```cpp
-TEST_CASE("Test1", "[unit]") {
-    int a = 1;
-    int b = 2;
-    REQUIRE(a == b);
-}
-
-TEST_CASE("Test2") {
-    int a = 1;
-    int b = 2;
-    REQUIRE(a == b);
-}
-
-TEST_CASE("Test3", "[a][b][c]") {
-    int a = 1;
-    int b = 2;
-    REQUIRE(a == b);
-}
-```
-would be registered as 3 tests, `Test1`, `Test2` and `Test3`,
-and 4 CTest labels would be created, `a`, `b`, `c` and `unit`.
-
-
-The second is based on parsing the output of a Catch binary given
-`--list-test-names-only`. This means that it deals with inactive
-(e.g. commented-out) tests better, but requires CMake 3.10 for full
-functionality.
-
-### CodeCoverage module (GCOV, LCOV...)
-
-If you are using GCOV tool to get testing coverage of your code, and are not sure how to integrate it with CMake and Catch, there should be an external example over at https://github.com/fkromer/catch_cmake_coverage
-
----
-
-[Home](Readme.md#top)
diff --git a/docs/ci-and-misc.md b/docs/ci-and-misc.md
new file mode 100644
index 0000000..8c33087
--- /dev/null
+++ b/docs/ci-and-misc.md
@@ -0,0 +1,108 @@
+<a id="top"></a>
+# CI and other odd pieces
+
+**Contents**<br>
+[Continuous Integration systems](#continuous-integration-systems)<br>
+[Other reporters](#other-reporters)<br>
+[Low-level tools](#low-level-tools)<br>
+[CMake](#cmake)<br>
+
+This page talks about how Catch integrates with Continuous Integration 
+Build Systems may refer to low-level tools, like CMake, or larger systems that run on servers, like Jenkins or TeamCity. This page will talk about both.
+
+## Continuous Integration systems
+
+Probably the most important aspect to using Catch with a build server is the use of different reporters. Catch comes bundled with three reporters that should cover the majority of build servers out there - although adding more for better integration with some is always a possibility (currently we also offer TeamCity, TAP and Automake reporters).
+
+Two of these reporters are built in (XML and JUnit) and the third (TeamCity) is included as a separate header. It's possible that the other two may be split out in the future too - as that would make the core of Catch smaller for those that don't need them.
+
+### XML Reporter
+```-r xml``` 
+
+The XML Reporter writes in an XML format that is specific to Catch. 
+
+The advantage of this format is that it corresponds well to the way Catch works (especially the more unusual features, such as nested sections) and is a fully streaming format - that is it writes output as it goes, without having to store up all its results before it can start writing.
+
+The disadvantage is that, being specific to Catch, no existing build servers understand the format natively. It can be used as input to an XSLT transformation that could convert it to, say, HTML - although this loses the streaming advantage, of course.
+
+### JUnit Reporter
+```-r junit```
+
+The JUnit Reporter writes in an XML format that mimics the JUnit ANT schema.
+
+The advantage of this format is that the JUnit Ant schema is widely understood by most build servers and so can usually be consumed with no additional work.
+
+The disadvantage is that this schema was designed to correspond to how JUnit works - and there is a significant mismatch with how Catch works. Additionally the format is not streamable (because opening elements hold counts of failed and passing tests as attributes) - so the whole test run must complete before it can be written.
+
+## Other reporters
+Other reporters are not part of the single-header distribution and need
+to be downloaded and included separately. All reporters are stored in
+`single_include` directory in the git repository, and are named
+`catch_reporter_*.hpp`. For example, to use the TeamCity reporter you
+need to download `single_include/catch_reporter_teamcity.hpp` and include
+it after Catch itself.
+
+```cpp
+#define CATCH_CONFIG_MAIN
+#include "catch.hpp"
+#include "catch_reporter_teamcity.hpp"
+```
+
+### TeamCity Reporter
+```-r teamcity```
+
+The TeamCity Reporter writes TeamCity service messages to stdout. In order to be able to use this reporter an additional header must also be included.
+
+Being specific to TeamCity this is the best reporter to use with it - but it is completely unsuitable for any other purpose. It is a streaming format (it writes as it goes) - although test results don't appear in the TeamCity interface until the completion of a suite (usually the whole test run).
+
+### Automake Reporter
+```-r automake```
+
+The Automake Reporter writes out the [meta tags](https://www.gnu.org/software/automake/manual/html_node/Log-files-generation-and-test-results-recording.html#Log-files-generation-and-test-results-recording) expected by automake via `make check`.
+
+### TAP (Test Anything Protocol) Reporter
+```-r tap```
+
+Because of the incremental nature of Catch's test suites and ability to run specific tests, our implementation of TAP reporter writes out the number of tests in a suite last.
+
+## Low-level tools
+
+### Precompiled headers (PCHs)
+
+Catch offers prototypal support for being included in precompiled headers, but because of its single-header nature it does need some actions by the user:
+* The precompiled header needs to define `CATCH_CONFIG_ALL_PARTS`
+* The implementation file needs to
+  * undefine `TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED`
+  * define `CATCH_CONFIG_IMPL_ONLY`
+  * define `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`
+  * include "catch.hpp" again
+
+
+### CodeCoverage module (GCOV, LCOV...)
+
+If you are using GCOV tool to get testing coverage of your code, and are not sure how to integrate it with CMake and Catch, there should be an external example over at https://github.com/fkromer/catch_cmake_coverage
+
+
+### pkg-config
+
+Catch2 provides a rudimentary pkg-config integration, by registering itself
+under the name `catch2`. This means that after Catch2 is installed, you
+can use `pkg-config` to get its include path: `pkg-config --cflags catch2`.
+
+### gdb and lldb scripts
+
+Catch2's `contrib` folder also contains two simple debugger scripts,
+`gdbinit` for `gdb` and `lldbinit` for `lldb`. If loaded into their
+respective debugger, these will tell it to step over Catch2's internals
+when stepping through code.
+
+
+## CMake
+
+[As it has been getting kinda long, the documentation of Catch2's
+integration with CMake has been moved to its own page.](cmake-integration.md#top)
+
+
+---
+
+[Home](Readme.md#top)
diff --git a/docs/cmake-integration.md b/docs/cmake-integration.md
new file mode 100644
index 0000000..246e7f0
--- /dev/null
+++ b/docs/cmake-integration.md
@@ -0,0 +1,226 @@
+<a id="top"></a>
+# CMake integration
+
+**Contents**<br>
+[CMake target](#cmake-target)<br>
+[Automatic test registration](#automatic-test-registration)<br>
+[CMake project options](#cmake-project-options)<br>
+[Installing Catch2 from git repository](#installing-catch2-from-git-repository)<br>
+
+Because we use CMake to build Catch2, we also provide a couple of
+integration points for our users.
+
+1) Catch2 exports a (namespaced) CMake target
+2) Catch2's repository contains CMake scripts for automatic registration
+of `TEST_CASE`s in CTest
+
+## CMake target
+
+Catch2's CMake build exports an interface target `Catch2::Catch2`. Linking
+against it will add the proper include path and all necessary capabilities
+to the resulting binary.
+
+This means that if Catch2 has been installed on the system, it should be
+enough to do:
+```cmake
+find_package(Catch2 REQUIRED)
+target_link_libraries(tests Catch2::Catch2)
+```
+
+
+This target is also provided when Catch2 is used as a subdirectory.
+Assuming that Catch2 has been cloned to `lib/Catch2`:
+```cmake
+add_subdirectory(lib/Catch2)
+target_link_libraries(tests Catch2::Catch2)
+```
+
+## Automatic test registration
+
+Catch2's repository also contains two CMake scripts that help users
+with automatically registering their `TEST_CASE`s with CTest. They
+can be found in the `contrib` folder, and are
+
+1) `Catch.cmake` (and its dependency `CatchAddTests.cmake`)
+2) `ParseAndAddCatchTests.cmake`
+
+If Catch2 has been installed in system, both of these can be used after
+doing `find_package(Catch2 REQUIRED)`. Otherwise you need to add them
+to your CMake module path.
+
+### `Catch.cmake` and `AddCatchTests.cmake`
+
+`Catch.cmake` provides function `catch_discover_tests` to get tests from
+a target. This function works by running the resulting executable with
+`--list-test-names-only` flag, and then parsing the output to find all
+existing tests.
+
+#### Usage
+```cmake
+cmake_minimum_required(VERSION 3.5)
+
+project(baz LANGUAGES CXX VERSION 0.0.1)
+
+find_package(Catch2 REQUIRED)
+add_executable(foo test.cpp)
+target_link_libraries(foo Catch2::Catch2)
+
+include(CTest)
+include(Catch)
+catch_discover_tests(foo)
+```
+
+
+#### Customization
+`catch_discover_tests` can be given several extra argumets:
+```cmake
+catch_discover_tests(target
+                     [TEST_SPEC arg1...]
+                     [EXTRA_ARGS arg1...]
+                     [WORKING_DIRECTORY dir]
+                     [TEST_PREFIX prefix]
+                     [TEST_SUFFIX suffix]
+                     [PROPERTIES name1 value1...]
+                     [TEST_LIST var]
+)
+```
+
+* `TEST_SPEC arg1...`
+
+Specifies test cases, wildcarded test cases, tags and tag expressions to
+pass to the Catch executable alongside the `--list-test-names-only` flag.
+
+
+* `EXTRA_ARGS arg1...`
+
+Any extra arguments to pass on the command line to each test case.
+
+
+* `WORKING_DIRECTORY dir`
+
+Specifies the directory in which to run the discovered test cases.  If this
+option is not provided, the current binary directory is used.
+
+
+* `TEST_PREFIX prefix`
+
+Specifies a _prefix_ to be added to the name of each discovered test case.
+This can be useful when the same test executable is being used in multiple
+calls to `catch_discover_tests()`, with different `TEST_SPEC` or `EXTRA_ARGS`.
+
+
+* `TEST_SUFFIX suffix`
+
+Same as `TEST_PREFIX`, except it specific the _suffix_ for the test names.
+Both `TEST_PREFIX` and `TEST_SUFFIX` can be specified at the same time.
+
+
+* `PROPERTIES name1 value1...`
+
+Specifies additional properties to be set on all tests discovered by this
+invocation of `catch_discover_tests`.
+
+
+* `TEST_LIST var`
+
+Make the list of tests available in the variable `var`, rather than the
+default `<target>_TESTS`.  This can be useful when the same test
+executable is being used in multiple calls to `catch_discover_tests()`.
+Note that this variable is only available in CTest.
+
+
+### `ParseAndAddCatchTests.cmake`
+
+`ParseAndAddCatchTests` works by parsing all implementation files
+associated with the provided target, and registering them via CTest's
+`add_test`. This approach has some limitations, such as the fact that
+commented-out tests will be registered anyway.
+
+
+#### Usage
+
+```cmake
+cmake_minimum_required(VERSION 3.5)
+
+project(baz LANGUAGES CXX VERSION 0.0.1)
+
+find_package(Catch2 REQUIRED)
+add_executable(foo test.cpp)
+target_link_libraries(foo Catch2::Catch2)
+
+include(CTest)
+include(ParseAndAddCatchTests)
+ParseAndAddCatchTests(foo)
+```
+
+
+#### Customization
+
+`ParseAndAddCatchTests` provides some customization points:
+* `PARSE_CATCH_TESTS_VERBOSE` -- When `ON`, the script prints debug
+messages. Defaults to `OFF`.
+* `PARSE_CATCH_TESTS_NO_HIDDEN_TESTS` -- When `ON`, hidden tests (tests
+tagged with any of `[!hide]`, `[.]` or `[.foo]`) will not be registered.
+Defaults to `OFF`.
+* `PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME` -- When `ON`, adds fixture
+class name to the test name in CTest. Defaults to `ON`.
+* `PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME` -- When `ON`, adds target
+name to the test name in CTest. Defaults to `ON`.
+* `PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS` -- When `ON`, adds test
+file to `CMAKE_CONFIGURE_DEPENDS`. This means that the CMake configuration
+step will be re-ran when the test files change, letting new tests be
+automatically discovered. Defaults to `OFF`.
+
+
+Optionally, one can specify a launching command to run tests by setting the
+variable `OptionalCatchTestLauncher` before calling `ParseAndAddCatchTests`. For
+instance to run some tests using `MPI` and other sequentially, one can write
+```cmake
+set(OptionalCatchTestLauncher ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${NUMPROC})
+ParseAndAddCatchTests(mpi_foo)
+unset(OptionalCatchTestLauncher)
+ParseAndAddCatchTests(bar)
+```
+
+## CMake project options
+
+Catch2's CMake project also provides some options for other projects
+that consume it. These are
+
+* `CATCH_BUILD_TESTING` -- When `ON`, Catch2's SelfTest project will be
+built. Defaults to `ON`. Note that Catch2 also obeys `BUILD_TESTING` CMake
+variable, so _both_ of them need to be `ON` for the SelfTest to be built,
+and either of them can be set to `OFF` to disable building SelfTest.
+* `CATCH_BUILD_EXAMPLES` -- When `ON`, Catch2's usage examples will be
+built. Defaults to `OFF`.
+* `CATCH_INSTALL_DOCS` -- When `ON`, Catch2's documentation will be
+included in the installation. Defaults to `ON`.
+* `CATCH_INSTALL_HELPERS` -- When `ON`, Catch2's contrib folder will be
+included in the installation. Defaults to `ON`.
+* `BUILD_TESTING` -- When `ON` and the project is not used as a subproject,
+Catch2's test binary will be built. Defaults to `ON`.
+
+
+## Installing Catch2 from git repository
+
+If you cannot install Catch2 from a package manager (e.g. Ubuntu 16.04
+provides catch only in version 1.2.0) you might want to install it from
+the repository instead. Assuming you have enough rights, you can just
+install it to the default location, like so:
+```
+$ git clone https://github.com/catchorg/Catch2.git
+$ cd Catch2
+$ cmake -Bbuild -H. -DBUILD_TESTING=OFF
+$ sudo cmake --build build/ --target install
+```
+
+If you do not have superuser rights, you will also need to specify
+[CMAKE_INSTALL_PREFIX](https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html)
+when configuring the build, and then modify your calls to
+[find_package](https://cmake.org/cmake/help/latest/command/find_package.html)
+accordingly.
+
+
+---
+
+[Home](Readme.md#top)
diff --git a/docs/command-line.md b/docs/command-line.md
index 8afcb7d..fc63fe8 100644
--- a/docs/command-line.md
+++ b/docs/command-line.md
@@ -24,6 +24,7 @@
 [Usage](#usage)<br>
 [Specify the section to run](#specify-the-section-to-run)<br>
 [Filenames as tags](#filenames-as-tags)<br>
+[Override output colouring](#override-output-colouring)<br>
 
 Catch works quite nicely without any command line options at all - but for those times when you want greater control the following options are available.
 Click one of the followings links to take you straight to that option - or scroll on to browse the available options.
@@ -57,6 +58,7 @@
 <a href="#libidentify">                                 `    --libidentify`</a><br />
 <a href="#wait-for-keypress">                           `    --wait-for-keypress`</a><br />
 <a href="#benchmark-resolution-multiple">               `    --benchmark-resolution-multiple`</a><br />
+<a href="#use-colour">                                  `    --use-colour`</a><br />
 
 </br>
 
@@ -78,7 +80,7 @@
 
 Test specs are case insensitive.
 
-If a spec is prefixed with `exclude:` or the `~` character then the pattern matches an exclusion. This means that tests matching the pattern are excluded from the set - even if a prior inclusion spec included them. Subsequent inclusion specs will take precendence, however.
+If a spec is prefixed with `exclude:` or the `~` character then the pattern matches an exclusion. This means that tests matching the pattern are excluded from the set - even if a prior inclusion spec included them. Subsequent inclusion specs will take precedence, however.
 Inclusions and exclusions are evaluated in left-to-right order.
 
 Test case examples:
@@ -94,7 +96,7 @@
 </pre>
 
 Names within square brackets are interpreted as tags.
-A series of tags form an AND expression wheras a comma-separated sequence forms an OR expression. e.g.:
+A series of tags form an AND expression whereas a comma-separated sequence forms an OR expression. e.g.:
 
 <pre>[one][two],[three]</pre>
 This matches all tests tagged `[one]` and `[two]`, as well as all tests tagged `[three]`
@@ -122,7 +124,9 @@
 ## Breaking into the debugger
 <pre>-b, --break</pre>
 
-In some IDEs (currently XCode and Visual Studio) it is possible for Catch to break into the debugger on a test failure. This can be very helpful during debug sessions - especially when there is more than one path through a particular test.
+Under most debuggers Catch2 is capable of automatically breaking on a test
+failure. This allows the user to see the current state of the test during
+failure.
 
 <a id="showing-results-for-successful-tests"></a>
 ## Showing results for successful tests
@@ -192,9 +196,16 @@
 ## Warnings
 <pre>-w, --warn &lt;warning name></pre>
 
-Enables reporting of warnings (only one, at time of this writing). If a warning is issued it fails the test.
+Enables reporting of suspicious test states. There are currently two
+available warnings
 
-The ony available warning, presently, is ```NoAssertions```. This warning fails a test case, or (leaf) section if no assertions (```REQUIRE```/ ```CHECK``` etc) are encountered.
+```
+    NoAssertions   // Fail test case / leaf section if no assertions
+                   // (e.g. `REQUIRE`) is encountered.
+    NoTests        // Return non-zero exit code when no test cases were run
+                   // Also calls reporter's noMatchingTestCases method
+```
+
 
 <a id="reporting-timings"></a>
 ## Reporting timings
@@ -262,7 +273,7 @@
 
 When running benchmarks the clock resolution is estimated. Benchmarks are then run for exponentially increasing
 numbers of iterations until some multiple of the estimated resolution is exceed. By default that multiple is 100, but 
-it can be overriden here.
+it can be overridden here.
 
 <a id="usage"></a>
 ## Usage
@@ -322,6 +333,16 @@
 
 So, for example,  tests within the file `~\Dev\MyProject\Ferrets.cpp` would be tagged `[#Ferrets]`.
 
+<a id="use-colour"></a>
+## Override output colouring
+<pre>--use-colour &lt;yes|no|auto&gt;</pre>
+
+Catch colours output for terminals, but omits colouring when it detects that
+output is being sent to a pipe. This is done to avoid interfering with automated
+processing of output.
+
+`--use-colour yes` forces coloured output, `--use-colour no` disables coloured
+output. The default behaviour is `--use-colour auto`.
 
 ---
 
diff --git a/docs/commercial-users.md b/docs/commercial-users.md
index e4d789f..4f98f75 100644
--- a/docs/commercial-users.md
+++ b/docs/commercial-users.md
@@ -13,5 +13,7 @@
 [issue](https://github.com/philsquared/Catch/issues), or on the [forums](https://groups.google.com/forum/?fromgroups#!forum/catch-forum).
  
  - Bloomberg
+ - [Bloomlife](https://bloomlife.com)
  - NASA
  - [Inscopix Inc.](https://www.inscopix.com/)
+ - [Makimo](https://makimo.pl/)
diff --git a/docs/configuration.md b/docs/configuration.md
index 3e59e76..1c94481 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -3,13 +3,19 @@
 
 **Contents**<br>
 [main()/ implementation](#main-implementation)<br>
+[Reporter / Listener interfaces](#reporter--listener-interfaces)<br>
 [Prefixing Catch macros](#prefixing-catch-macros)<br>
 [Terminal colour](#terminal-colour)<br>
 [Console width](#console-width)<br>
 [stdout](#stdout)<br>
+[Fallback stringifier](#fallback-stringifier)<br>
+[Default reporter](#default-reporter)<br>
+[C++11 toggles](#c11-toggles)<br>
+[C++17 toggles](#c17-toggles)<br>
 [Other toggles](#other-toggles)<br>
 [Windows header clutter](#windows-header-clutter)<br>
 [Enabling stringification](#enabling-stringification)<br>
+[Disabling exceptions](#disabling-exceptions)<br>
 
 Catch is designed to "just work" as much as possible. For most people the only configuration needed is telling Catch which source file should host all the implementation code (```CATCH_CONFIG_MAIN```).
 
@@ -17,14 +23,14 @@
 
 ## main()/ implementation
 
-	CATCH_CONFIG_MAIN	// Designates this as implementation file and defines main()
-	CATCH_CONFIG_RUNNER	// Designates this as implementation file
+    CATCH_CONFIG_MAIN      // Designates this as implementation file and defines main()
+    CATCH_CONFIG_RUNNER    // Designates this as implementation file
 
 Although Catch is header only it still, internally, maintains a distinction between interface headers and headers that contain implementation. Only one source file in your test project should compile the implementation headers and this is controlled through the use of one of these macros - one of these identifiers should be defined before including Catch in *exactly one implementation file in your project*.
 
-# Reporter / Listener interfaces
+## Reporter / Listener interfaces
 
-    CATCH_CONFIG_EXTERNAL_INTERFACES  // Brings in neccessary headers for Reporter/Listener implementation
+    CATCH_CONFIG_EXTERNAL_INTERFACES  // Brings in necessary headers for Reporter/Listener implementation
 
 Brings in various parts of Catch that are required for user defined Reporters and Listeners. This means that new Reporters and Listeners can be defined in this file as well as in the main file.
 
@@ -32,16 +38,16 @@
 
 ## Prefixing Catch macros
 
-	CATCH_CONFIG_PREFIX_ALL
+    CATCH_CONFIG_PREFIX_ALL
 
 To keep test code clean and uncluttered Catch uses short macro names (e.g. ```TEST_CASE``` and ```REQUIRE```). Occasionally these may conflict with identifiers from platform headers or the system under test. In this case the above identifier can be defined. This will cause all the Catch user macros to be prefixed with ```CATCH_``` (e.g. ```CATCH_TEST_CASE``` and ```CATCH_REQUIRE```).
 
 
 ## Terminal colour
 
-	CATCH_CONFIG_COLOUR_NONE	// completely disables all text colouring
-	CATCH_CONFIG_COLOUR_WINDOWS	// forces the Win32 console API to be used
-	CATCH_CONFIG_COLOUR_ANSI	// forces ANSI colour codes to be used
+    CATCH_CONFIG_COLOUR_NONE      // completely disables all text colouring
+    CATCH_CONFIG_COLOUR_WINDOWS   // forces the Win32 console API to be used
+    CATCH_CONFIG_COLOUR_ANSI      // forces ANSI colour codes to be used
 
 Yes, I am English, so I will continue to spell "colour" with a 'u'.
 
@@ -55,24 +61,81 @@
 
 ## Console width
 
-	CATCH_CONFIG_CONSOLE_WIDTH = x // where x is a number
+    CATCH_CONFIG_CONSOLE_WIDTH = x // where x is a number
 
 Catch formats output intended for the console to fit within a fixed number of characters. This is especially important as indentation is used extensively and uncontrolled line wraps break this.
 By default a console width of 80 is assumed but this can be controlled by defining the above identifier to be a different value.
 
 ## stdout
 
-	CATCH_CONFIG_NOSTDOUT
+    CATCH_CONFIG_NOSTDOUT
 
-Catch does not use ```std::cout```, ```std::cerr``` and ```std::clog``` directly but gets them from ```Catch::cout()```, ```Catch::cerr()``` and ```Catch::clog``` respectively. If the above identifier is defined these functions are left unimplemented and you must implement them yourself. Their signatures are:
+To support platforms that do not provide `std::cout`, `std::cerr` and
+`std::clog`, Catch does not usem the directly, but rather calls
+`Catch::cout`, `Catch::cerr` and `Catch::clog`. You can replace their
+implementation by defining `CATCH_CONFIG_NOSTDOUT` and implementing
+them yourself, their signatures are:
 
     std::ostream& cout();
     std::ostream& cerr();
     std::ostream& clog();
 
-This can be useful on certain platforms that do not provide the standard iostreams, such as certain embedded systems.
+[You can see an example of replacing these functions here.](
+../examples/231-Cfg-OutputStreams.cpp)
 
 
+## Fallback stringifier
+
+By default, when Catch's stringification machinery has to stringify
+a type that does not specialize `StringMaker`, does not overload `operator<<`,
+is not an enumeration and is not a range, it uses `"{?}"`. This can be
+overriden by defining `CATCH_CONFIG_FALLBACK_STRINGIFIER` to name of a
+function that should perform the stringification instead.
+
+All types that do not provide `StringMaker` specialization or `operator<<`
+overload will be sent to this function (this includes enums and ranges).
+The provided function must return `std::string` and must accept any type,
+e.g. via overloading.
+
+_Note that if the provided function does not handle a type and this type
+requires to be stringified, the compilation will fail._
+
+
+## Default reporter
+
+Catch's default reporter can be changed by defining macro
+`CATCH_CONFIG_DEFAULT_REPORTER` to string literal naming the desired
+default reporter.
+
+This means that defining `CATCH_CONFIG_DEFAULT_REPORTER` to `"console"`
+is equivalent with the out-of-the-box experience.
+
+
+## C++11 toggles
+
+    CATCH_CONFIG_CPP11_TO_STRING // Use `std::to_string`
+
+Because we support platforms whose standard library does not contain
+`std::to_string`, it is possible to force Catch to use a workaround
+based on `std::stringstream`. On platforms other than Android,
+the default is to use `std::to_string`. On Android, the default is to
+use the `stringstream` workaround. As always, it is possible to override
+Catch's selection, by defining either `CATCH_CONFIG_CPP11_TO_STRING` or
+`CATCH_CONFIG_NO_CPP11_TO_STRING`.
+
+
+## C++17 toggles
+
+    CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS  // Use std::uncaught_exceptions instead of std::uncaught_exception
+    CATCH_CONFIG_CPP17_STRING_VIEW          // Provide StringMaker specialization for std::string_view
+    CATCH_CONFIG_CPP17_VARIANT              // Override C++17 detection for CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
+
+Catch contains basic compiler/standard detection and attempts to use
+some C++17 features whenever appropriate. This automatic detection
+can be manually overridden in both directions, that is, a feature
+can be enabled by defining the macro in the table above, and disabled
+by using `_NO_` in the macro, e.g. `CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS`.
+
 
 ## Other toggles
 
@@ -84,6 +147,8 @@
     CATCH_CONFIG_WINDOWS_CRTDBG             // Enable leak checking using Windows's CRT Debug Heap
     CATCH_CONFIG_DISABLE_STRINGIFICATION    // Disable stringifying the original expression
     CATCH_CONFIG_DISABLE                    // Disables assertions and test case registration
+    CATCH_CONFIG_WCHAR                      // Enables use of wchart_t
+    CATCH_CONFIG_EXPERIMENTAL_REDIRECT      // Enables the new (experimental) way of capturing stdout/stderr
 
 Currently Catch enables `CATCH_CONFIG_WINDOWS_SEH` only when compiled with MSVC, because some versions of MinGW do not have the necessary Win32 API support.
 
@@ -91,14 +156,22 @@
 
 `CATCH_CONFIG_WINDOWS_CRTDBG` is off by default. If enabled, Windows's CRT is used to check for memory leaks, and displays them after the tests finish running.
 
-These toggles can be disabled by using `_NO_` form of the toggle, e.g. `CATCH_CONFIG_NO_WINDOWS_SEH`.
+`CATCH_CONFIG_WCHAR` is on by default, but can be disabled. Currently
+it is only used in support for DJGPP cross-compiler.
+
+With the exception of `CATCH_CONFIG_EXPERIMENTAL_REDIRECT`,
+these toggles can be disabled by using `_NO_` form of the toggle,
+e.g. `CATCH_CONFIG_NO_WINDOWS_SEH`.
 
 ### `CATCH_CONFIG_FAST_COMPILE`
-Defining this flag speeds up compilation of test files by ~20%, by making 2 changes:
-* The `-b` (`--break`) flag no longer makes Catch break into debugger in the same stack frame as the failed test, but rather in a stack frame *below*.
-* Non-exception family of macros ({`REQUIRE`,`CHECK`}{`_`,`_FALSE`, `_FALSE`}, no longer use local try-cache block. This disables exception translation, but should not lead to false negatives.
+This compile-time flag speeds up compilation of assertion macros by ~20%,
+by disabling the generation of assertion-local try-catch blocks for
+non-exception family of assertion macros ({`REQUIRE`,`CHECK`}{``,`_FALSE`, `_THAT`}).
+This disables translation of exceptions thrown under these assertions, but
+should not lead to false negatives.
 
-`CATCH_CONFIG_FAST_COMPILE` has to be either defined, or not defined, in all translation units that are linked into single test binary, or the behaviour of setting `-b` flag and throwing unexpected exceptions will be unpredictable.
+`CATCH_CONFIG_FAST_COMPILE` has to be either defined, or not defined,
+in all translation units that are linked into single test binary.
 
 ### `CATCH_CONFIG_DISABLE_MATCHERS`
 When `CATCH_CONFIG_DISABLE_MATCHERS` is defined, all mentions of Catch's Matchers are ifdef-ed away from the translation unit. Doing so will speed up compilation of that TU.
@@ -127,12 +200,48 @@
 
 By default, Catch does not stringify some types from the standard library. This is done to avoid dragging in various standard library headers by default. However, Catch does contain these and can be configured to provide them, using these macros:
 
-    CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER    // Provide StringMaker specialization for std::pair
-    CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER   // Provide StringMaker specialization for std::tuple
-    CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER  // Provide StringMaker specialization for std::chrono::duration, std::chrono::timepoint
-    CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS    // Defines all of the above
+    CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER     // Provide StringMaker specialization for std::pair
+    CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER    // Provide StringMaker specialization for std::tuple
+    CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER   // Provide StringMaker specialization for std::chrono::duration, std::chrono::timepoint
+    CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER  // Provide StringMaker specialization for std::variant, std::monostate (on C++17)
+    CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER // Provide StringMaker specialization for std::optional (on C++17)
+    CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS     // Defines all of the above
 
 
+## Disabling exceptions
+
+By default, Catch2 uses exceptions to signal errors and to abort tests
+when an assertion from the `REQUIRE` family of assertions fails. We also
+provide an experimental support for disabling exceptions. Catch2 should
+automatically detect when it is compiled with exceptions disabled, but
+it can be forced to compile without exceptions by defining
+
+    CATCH_CONFIG_DISABLE_EXCEPTIONS
+
+Note that when using Catch2 without exceptions, there are 2 major
+limitations:
+
+1) If there is an error that would normally be signalled by an exception,
+the exception's message will instead be written to `Catch::cerr` and
+`std::terminate` will be called.
+2) If an assertion from the `REQUIRE` family of macros fails,
+`std::terminate` will be called after the active reporter returns.
+
+
+There is also a customization point for the exact behaviour of what
+happens instead of exception being thrown. To use it, define
+
+    CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER
+
+and provide a definition for this function:
+
+```cpp
+namespace Catch {
+    [[noreturn]]
+    void throw_exception(std::exception const&);
+}
+```
+
 ---
 
 [Home](Readme.md#top)
diff --git a/docs/contributing.md b/docs/contributing.md
index b615037..21bbad1 100644
--- a/docs/contributing.md
+++ b/docs/contributing.md
@@ -1,8 +1,8 @@
 <a id="top"></a>
 # Contributing to Catch
 
-So you want to contribute something to Catch? That's great! Whether it's a bug fix, a new feature, support for 
-additional compilers - or just a fix to the documentation - all contributions are very welcome and very much appreciated. 
+So you want to contribute something to Catch? That's great! Whether it's a bug fix, a new feature, support for
+additional compilers - or just a fix to the documentation - all contributions are very welcome and very much appreciated.
 Of course so are bug reports and other comments and questions.
 
 If you are contributing to the code base there are a few simple guidelines to keep in mind. This also includes notes to
@@ -16,7 +16,7 @@
 
 ## Directory structure
 
-_Users_ of Catch primarily use the single header version. _Maintainers_ should work with the full source (which is still, 
+_Users_ of Catch primarily use the single header version. _Maintainers_ should work with the full source (which is still,
 primarily, in headers). This can be found in the `include` folder. There are a set of test files, currently under
 `projects/SelfTest`. The test app can be built via CMake from the `CMakeLists.txt` file in the root, or you can generate
 project files for Visual Studio, XCode, and others (instructions in the `projects` folder). If you have access to CLion,
@@ -37,20 +37,42 @@
 
 ## Testing your changes
 
-Obviously all changes to Catch's code should be tested. If you added new functionality, you should add tests covering and
-showcasing it. Even if you have only made changes to Catch internals (ie you implemented some performance improvements),
-you should still test your changes.
+Obviously all changes to Catch's code should be tested. If you added new
+functionality, you should add tests covering and showcasing it. Even if you have
+only made changes to Catch internals (i.e. you implemented some performance
+improvements), you should still test your changes.
 
-This means 3 things
+This means 2 things
 
-* Compiling Catch's SelfTest project -- code that does not compile is evidently incorrect. Obviously, you are not expected to
-have access to all compilers and platforms Catch supports, Catch's CI pipeline will compile your code using supported compilers
-once you open a PR.
-* Running the SelfTest binary. There should be no unexpected failures on simple run.
-* Running Catch's approval tests. Approval tests compare current output of the SelfTest binary in various configurations against
-known good output. Catch's repository provides utility scripts `approvalTests.py` to help you with this. It needs to be passed
-the SelfTest binary compiled with your changes, like so: `$ ./scripts/approvalTests.py clang-build/SelfTest`. The output should
-be fairly self-explanatory.
+* Compiling Catch's SelfTest project:
+```
+$ cd Catch2
+$ cmake -Bdebug-build -H. -DCMAKE_BUILD_TYPE=Debug
+$ cmake --build debug-build
+```
+because code that does not compile is evidently incorrect. Obviously,
+you are not expected to have access to all the compilers and platforms
+supported by Catch2, but you should at least smoke test your changes
+on your platform. Our CI pipeline will check your PR against most of
+the supported platforms, but it takes an hour to finish -- compiling
+locally takes just a few minutes.
+
+
+* Running the tests via CTest:
+```
+$ cd debug-build
+$ ctest -j 2 --output-on-failure
+```
+If you added new tests, approval tests are very likely to fail. If they
+do not, it means that your changes weren't run as part of them. This
+_might_ be intentional, but usually is not.
+
+The approval tests compare current output of the SelfTest binary in various
+configurations against known good outputs. The reason it fails is,
+_usually_, that you've added new tests but have not yet approved the changes
+they introduce. This is done with the `scripts/approve.py` script, but
+before you do so, you need to check that the introduced changes are indeed
+intentional.
 
 
 
diff --git a/docs/deprecations.md b/docs/deprecations.md
new file mode 100644
index 0000000..0489e1f
--- /dev/null
+++ b/docs/deprecations.md
@@ -0,0 +1,93 @@
+<a id="top"></a>
+# Deprecations and incoming changes
+
+This page documents current deprecations and upcoming planned changes
+inside Catch2. The difference between these is that a deprecated feature
+will be removed, while a planned change to a feature means that the
+feature will behave differently, but will still be present. Obviously,
+either of these is a breaking change, and thus will not happen until
+at least the next major release.
+
+
+## Deprecations
+
+### `--list-*` return values
+
+The return codes of the `--list-*` family of command line arguments
+will no longer be equal to the number of tests/tags/etc found, instead
+it will be 0 for success and non-zero for failure.
+
+
+### `--list-test-names-only`
+
+`--list-test-names-only` command line argument will be removed.
+
+
+### `ANON_TEST_CASE`
+
+`ANON_TEST_CASE` is scheduled for removal, as it can be fully replaced
+by a `TEST_CASE` with no arguments.
+
+
+### Secondary description amongst tags
+
+Currently, the tags part of `TEST_CASE` (and others) macro can also
+contain text that is not part of tags. This text is then separated into
+a "description" of the test case, but the description is then never used
+apart from writing it out for `--list-tests -v high`.
+
+Because it isn't actually used nor documented, and brings complications
+to Catch2's internals, description support will be removed.
+
+
+## Planned changes
+
+
+### Reporter verbosities
+
+The current implementation of verbosities, where the reporter is checked
+up-front whether it supports the requested verbosity, is fundamentally
+misguided and will be changed. The new implementation will no longer check
+whether the specified reporter supports the requested verbosity, instead
+it will be up to the reporters to deal with verbosities as they see fit
+(with an expectation that unsupported verbosities will be, at most,
+warnings, but not errors).
+
+
+### Output format of `--list-*` command line parameters
+
+The various list operations will be piped through reporters. This means
+that e.g. XML reporter will write the output as machine-parseable XML,
+while the Console reporter will keep the current, human-oriented output.
+
+
+### `CHECKED_IF` and `CHECKED_ELSE`
+
+To make the `CHECKED_IF` and `CHECKED_ELSE` macros more useful, they will
+be marked as "OK to fail" (`Catch::ResultDisposition::SuppressFail` flag
+will be added), which means that their failure will not fail the test,
+making the `else` actually useful.
+
+
+### Change semantics of `[.]` and tag exclusion
+
+Currently, given these 2 tests
+```cpp
+TEST_CASE("A", "[.][foo]") {}
+TEST_CASE("B", "[.][bar]") {}
+```
+specifying `[foo]` as the testspec will run test "A" and specifying
+`~[foo]` will run test "B", even though it is hidden. Also, specifying
+`~[baz]` will run both tests. This behaviour is often surprising and will
+be changed so that hidden tests are included in a run only if they
+positively match a testspec.
+
+
+### Console Colour API
+
+The API for Catch2's console colour will be changed to take an extra
+argument, the stream to which the colour code should be applied.
+
+---
+
+[Home](Readme.md#top)
diff --git a/docs/event-listeners.md b/docs/event-listeners.md
index 1ddef0f..c6625a2 100644
--- a/docs/event-listeners.md
+++ b/docs/event-listeners.md
@@ -44,7 +44,7 @@
 
 ## Events that can be hooked
 
-The following are the methods that can be overriden in the Listener:
+The following are the methods that can be overridden in the Listener:
 
 ```c++
 // The whole test run, starting and ending
diff --git a/docs/generators.md b/docs/generators.md
new file mode 100644
index 0000000..8ad47e3
--- /dev/null
+++ b/docs/generators.md
@@ -0,0 +1,133 @@
+<a id="top"></a>
+# Data Generators
+
+Data generators (also known as _data driven/parametrized test cases_)
+let you reuse the same set of assertions across different input values.
+In Catch2, this means that they respect the ordering and nesting
+of the `TEST_CASE` and `SECTION` macros, and their nested sections
+are run once per each value in a generator.
+
+This is best explained with an example:
+```cpp
+TEST_CASE("Generators") {
+    auto i = GENERATE(1, 2, 3);
+    SECTION("one") {
+        auto j = GENERATE( -3, -2, -1 );
+        REQUIRE(j < i);
+    }
+}
+```
+
+The assertion in this test case will be run 9 times, because there
+are 3 possible values for `i` (1, 2, and 3) and there are 3 possible
+values for `j` (-3, -2, and -1).
+
+
+There are 2 parts to generators in Catch2, the `GENERATE` macro together
+with the already provided generators, and the `IGenerator<T>` interface
+that allows users to implement their own generators.
+
+## Provided generators
+
+Catch2's provided generator functionality consists of three parts,
+
+* `GENERATE` macro,  that serves to integrate generator expression with
+a test case,
+* 2 fundamental generators
+  * `ValueGenerator<T>` -- contains only single element
+  * `ValuesGenerator<T>` -- contains multiple elements
+* 5 generic generators that modify other generators
+  * `FilterGenerator<T, Predicate>` -- filters out elements from a generator
+  for which the predicate returns "false"
+  * `TakeGenerator<T>` -- takes first `n` elements from a generator
+  * `RepeatGenerator<T>` -- repeats output from a generator `n` times
+  * `MapGenerator<T, U, Func>` -- returns the result of applying `Func`
+  on elements from a different generator
+  * `ChunkGenerator<T>` -- returns chunks (inside `std::vector`) of n elements from a generator
+* 3 specific purpose generators
+  * `RandomIntegerGenerator<Integral>` -- generates random Integrals from range
+  * `RandomFloatGenerator<Float>` -- generates random Floats from range
+  * `RangeGenerator<T>` -- generates all values inside a specific range
+
+The generators also have associated helper functions that infer their
+type, making their usage much nicer. These are
+
+* `value(T&&)` for `ValueGenerator<T>`
+* `values(std::initializer_list<T>)` for `ValuesGenerator<T>`
+* `filter(predicate, GeneratorWrapper<T>&&)` for `FilterGenerator<T, Predicate>`
+* `take(count, GeneratorWrapper<T>&&)` for `TakeGenerator<T>`
+* `repeat(repeats, GeneratorWrapper<T>&&)` for `RepeatGenerator<T>`
+* `map(func, GeneratorWrapper<T>&&)` for `MapGenerator<T, T, Func>` (map `T` to `T`)
+* `map<T>(func, GeneratorWrapper<U>&&)` for `MapGenerator<T, U, Func>` (map `U` to `T`)
+* `chunk(chunk-size, GeneratorWrapper<T>&&)` for `ChunkGenerator<T>`
+* `random(IntegerOrFloat a, IntegerOrFloat b)` for `RandomIntegerGenerator` or `RandomFloatGenerator`
+* `range(start, end)` for `RangeGenerator<T>` with a step size of `1` 
+* `range(start, end, step)` for `RangeGenerator<T>` with a custom step size
+
+
+And can be used as shown in the example below to create a generator
+that returns 100 odd random number:
+
+```cpp
+TEST_CASE("Generating random ints", "[example][generator]") {
+    SECTION("Deducing functions") {
+        auto i = GENERATE(take(100, filter([](int i) { return i % 2 == 1; }, random(-100, 100))));
+        REQUIRE(i > -100);
+        REQUIRE(i < 100);
+        REQUIRE(i % 2 == 1);
+    }
+}
+```
+
+
+Apart from registering generators with Catch2, the `GENERATE` macro has
+one more purpose, and that is to provide simple way of generating trivial
+generators, as seen in the first example on this page, where we used it
+as `auto i = GENERATE(1, 2, 3);`. This usage converted each of the three
+literals into a single `ValueGenerator<int>` and then placed them all in
+a special generator that concatenates other generators. It can also be
+used with other generators as arguments, such as `auto i = GENERATE(0, 2,
+take(100, random(300, 3000)));`. This is useful e.g. if you know that
+specific inputs are problematic and want to test them separately/first.
+
+**For safety reasons, you cannot use variables inside the `GENERATE` macro.**
+
+You can also override the inferred type by using `as<type>` as the first
+argument to the macro. This can be useful when dealing with string literals,
+if you want them to come out as `std::string`:
+
+```cpp
+TEST_CASE("type conversion", "[generators]") {
+    auto str = GENERATE(as<std::string>{}, "a", "bb", "ccc");`
+    REQUIRE(str.size() > 0);
+}
+```
+
+## Generator interface
+
+You can also implement your own generators, by deriving from the
+`IGenerator<T>` interface:
+
+```cpp
+template<typename T>
+struct IGenerator : GeneratorUntypedBase {
+    // via GeneratorUntypedBase:
+    // Attempts to move the generator to the next element.
+    // Returns true if successful (and thus has another element that can be read)
+    virtual bool next() = 0;
+
+    // Precondition:
+    // The generator is either freshly constructed or the last call to next() returned true
+    virtual T const& get() const = 0;
+};
+```
+
+However, to be able to use your custom generator inside `GENERATE`, it
+will need to be wrapped inside a `GeneratorWrapper<T>`.
+`GeneratorWrapper<T>` is a value wrapper around a
+`std::unique_ptr<IGenerator<T>>`.
+
+For full example of implementing your own generator, look into Catch2's
+examples, specifically
+[Generators: Create your own generator](../examples/300-Gen-OwnGenerator.cpp).
+
diff --git a/docs/limitations.md b/docs/limitations.md
index bcdbab0..b95cd87 100644
--- a/docs/limitations.md
+++ b/docs/limitations.md
@@ -1,12 +1,19 @@
 <a id="top"></a>
 # Known limitations
 
-Catch has some known limitations, that we are not planning to change. Some of these are caused by our desire to support C++98 compilers, some of these are caused by our desire to keep Catch crossplatform, some exist because their priority is seen as low compared to the development effort they would need and some other yet are compiler/runtime bugs.
+Over time, some limitations of Catch2 emerged. Some of these are due
+to implementation details that cannot be easily changed, some of these
+are due to lack of development resources on our part, and some of these
+are due to plain old 3rd party bugs.
+
 
 ## Implementation limits
 ### Sections nested in loops
 
-If you are using `SECTION`s inside loops, you have to create them with different name per loop's iteration. The recommended way to do so is to incorporate the loop's counter into section's name, like so
+If you are using `SECTION`s inside loops, you have to create them with
+different name per loop's iteration. The recommended way to do so is to
+incorporate the loop's counter into section's name, like so:
+
 ```cpp
 TEST_CASE( "Looped section" ) {
     for (char i = '0'; i < '5'; ++i) {
@@ -17,11 +24,34 @@
 }
 ```
 
+or with a `DYNAMIC_SECTION` macro (that was made for exactly this purpose):
+
+```cpp
+TEST_CASE( "Looped section" ) {
+    for (char i = '0'; i < '5'; ++i) {
+        DYNAMIC_SECTION( "Looped section " << i) {
+            SUCCEED( "Everything is OK" );
+        }
+    }
+}
+```
+
+### Tests might be run again if last section fails
+
+If the last section in a test fails, it might be run again. This is because
+Catch2 discovers `SECTION`s dynamically, as they are about to run, and
+if the last section in test case is aborted during execution (e.g. via
+the `REQUIRE` family of macros), Catch2 does not know that there are no
+more sections in that test case and must run the test case again.
+
+
 ## Features
 This section outlines some missing features, what is their status and their possible workarounds.
 
 ### Thread safe assertions
-Because threading support in standard C++98 is limited (well, non-existent), assertion macros in Catch are not thread safe. This does not mean that you cannot use threads inside Catch's test, but that only single thread can interact with Catch's assertions and other macros.
+Catch2's assertion macros are not thread safe. This does not mean that
+you cannot use threads inside Catch's test, but that only single thread
+can interact with Catch's assertions and other macros.
 
 This means that this is ok
 ```cpp
@@ -49,8 +79,8 @@
     REQUIRE(cnt == 16);
 ```
 
-
-_This limitation is highly unlikely to be lifted before Catch 2 is released._
+Because C++11 provides the necessary tools to do this, we are planning
+to remove this limitation in the future.
 
 ### Process isolation in a test
 Catch does not support running tests in isolated (forked) processes. While this might in the future, the fact that Windows does not support forking and only allows full-on process creation and the desire to keep code as similar as possible across platforms, mean that this is likely to take significant development time, that is not currently available.
@@ -96,6 +126,14 @@
   ""\" == ""\"
 ```
 
+### Visual Studio 2015 -- Alignment compilation error (C2718)
+
+VS 2015 has a known bug, where `declval<T>` can cause compilation error
+if `T` has alignment requirements that it cannot meet.
+
+
+A workaround is to explicitly specialize `Catch::is_range` for given
+type (this avoids code path that uses `declval<T>` in a SFINAE context).
 
 
 ### Visual Studio 2015 -- Wrong line number reported in debug mode
@@ -127,3 +165,14 @@
 This is a bug in `libstdc++-4.8`, where all matching methods from `<regex>` return false. Since `Matches` uses `<regex>` internally, if the underlying implementation does not work, it doesn't work either.
 
 Workaround: Use newer version of `libstdc++`.
+
+
+### libstdc++, `_GLIBCXX_DEBUG` macro and random ordering of tests
+
+Running a Catch2 binary compiled against libstdc++ with `_GLIBCXX_DEBUG`
+macro defined with `--order rand` will cause a debug check to trigger and
+abort the run due to self-assignment.
+[This is a known bug inside libstdc++](https://stackoverflow.com/questions/22915325/avoiding-self-assignment-in-stdshuffle/23691322)
+
+Workaround: Don't use `--order rand` when compiling against debug-enabled
+libstdc++.
diff --git a/docs/list-of-examples.md b/docs/list-of-examples.md
index 6517d5d..677dec1 100644
--- a/docs/list-of-examples.md
+++ b/docs/list-of-examples.md
@@ -1,18 +1,32 @@
 <a id="top"></a>
 # List of examples
 
+## Already available
+
+- Catch main: [Catch-provided main](../examples/000-CatchMain.cpp)
 - Test Case: [Single-file](../examples/010-TestCase.cpp)
-- Test Case: [Multiple-file 1](../examples/020-TestCase-1.cpp), [2](../examples/020-TestCase-1.cpp)
+- Test Case: [Multiple-file 1](../examples/020-TestCase-1.cpp), [2](../examples/020-TestCase-2.cpp)
 - Assertion: [REQUIRE, CHECK](../examples/030-Asn-Require-Check.cpp)
+- Fixture: [Sections](../examples/100-Fix-Section.cpp)
+- Fixture: [Class-based fixtures](../examples/110-Fix-ClassFixture.cpp)
+- BDD: [SCENARIO, GIVEN, WHEN, THEN](../examples/120-Bdd-ScenarioGivenWhenThen.cpp)
+- Report: [Catch-provided main](../examples/200-Rpt-CatchMain.cpp)
+- Report: [TeamCity reporter](../examples/207-Rpt-TeamCityReporter.cpp)
+- Listener: [Listeners](../examples/210-Evt-EventListeners.cpp)
+- Configuration: [Provide your own output streams](../examples/231-Cfg-OutputStreams.cpp)
+- Generators: [Create your own generator](../examples/300-Gen-OwnGenerator.cpp)
+- Generators: [Use map to convert types in GENERATE expression](../examples/301-Gen-MapTypeConversion.cpp)
+- Generators: [Use variables in generator expressions](../examples/310-Gen-VariablesInGenerators.cpp)
+
+
+## Planned
+
 - Assertion: [REQUIRE_THAT and Matchers](../examples/040-Asn-RequireThat.cpp)
 - Assertion: [REQUIRE_NO_THROW](../examples/050-Asn-RequireNoThrow.cpp)
 - Assertion: [REQUIRE_THROWS](../examples/050-Asn-RequireThrows.cpp)
 - Assertion: [REQUIRE_THROWS_AS](../examples/070-Asn-RequireThrowsAs.cpp)
 - Assertion: [REQUIRE_THROWS_WITH](../examples/080-Asn-RequireThrowsWith.cpp)
 - Assertion: [REQUIRE_THROWS_MATCHES](../examples/090-Asn-RequireThrowsMatches.cpp)
-- Fixture: [Sections](../examples/100-Fix-Section.cpp)
-- Fixture: [Class-based fixtures](../examples/110-Fix-ClassFixture.cpp)
-- BDD: [SCENARIO, GIVEN, WHEN, THEN](../examples/120-Bdd-ScenarioGivenWhenThen.cpp)
 - Floating point: [Approx - Comparisons](../examples/130-Fpt-Approx.cpp)
 - Logging: [CAPTURE - Capture expression](../examples/140-Log-Capture.cpp)
 - Logging: [INFO - Provide information with failure](../examples/150-Log-Info.cpp)
@@ -20,8 +34,10 @@
 - Logging: [FAIL, FAIL_CHECK - Issue message and force failure/continue](../examples/170-Log-Fail.cpp)
 - Logging: [SUCCEED - Issue message and continue](../examples/180-Log-Succeed.cpp)
 - Report: [User-defined type](../examples/190-Rpt-ReportUserDefinedType.cpp)
-- Report: [Reporter](../examples/200-Rpt-UserDefinedReporter.cpp)
-- Listener: [Listeners](../examples/210-Evt-EventListeners.cpp)
+- Report: [User-defined reporter](../examples/202-Rpt-UserDefinedReporter.cpp)
+- Report: [Automake reporter](../examples/205-Rpt-AutomakeReporter.cpp)
+- Report: [TAP reporter](../examples/206-Rpt-TapReporter.cpp)
+- Report: [Multiple reporter](../examples/208-Rpt-MultipleReporters.cpp)
 - Configuration: [Provide your own main()](../examples/220-Cfg-OwnMain.cpp)
 - Configuration: [Compile-time configuration](../examples/230-Cfg-CompileTimeConfiguration.cpp)
 - Configuration: [Run-time configuration](../examples/240-Cfg-RunTimeConfiguration.cpp)
diff --git a/docs/logging.md b/docs/logging.md
index 7ae54aa..e896a57 100644
--- a/docs/logging.md
+++ b/docs/logging.md
@@ -1,7 +1,7 @@
 <a id="top"></a>
 # Logging macros
 
-Additional messages can be logged during a test case. Note that the messages are scoped and thus will not be reported if failure occurs in scope preceding the message declaration. An example:
+Additional messages can be logged during a test case. Note that the messages logged with `INFO` are scoped and thus will not be reported if failure occurs in scope preceding the message declaration. An example:
 
 ```cpp
 TEST_CASE("Foo") {
@@ -28,6 +28,60 @@
 ```
 When the last `CHECK` fails in the "Bar" test case, then only one message will be printed: `Test case start`.
 
+## Logging without local scope
+
+`UNSCOPED_INFO` is similar to `INFO` with two key differences:
+
+- Lifetime of an unscoped message is not tied to its own scope.
+- An unscoped message can be reported by the first following assertion only, regardless of the result of that assertion.
+
+In other words, lifetime of `UNSCOPED_INFO` is limited by the following assertion (or by the end of test case/section, whichever comes first) whereas lifetime of `INFO` is limited by its own scope.
+
+These differences make this macro useful for reporting information from helper functions or inner scopes. An example:
+
+```cpp
+void print_some_info() {
+    UNSCOPED_INFO("Info from helper");
+}
+
+TEST_CASE("Baz") {
+    print_some_info();
+    for (int i = 0; i < 2; ++i) {
+        UNSCOPED_INFO("The number is " << i);
+    }
+    CHECK(false);
+}
+
+TEST_CASE("Qux") {
+    INFO("First info");
+    UNSCOPED_INFO("First unscoped info");
+    CHECK(false);
+
+    INFO("Second info");
+    UNSCOPED_INFO("Second unscoped info");
+    CHECK(false);
+}
+```
+
+"Baz" test case prints:
+```
+Info from helper
+The number is 0
+The number is 1
+```
+
+With "Qux" test case, two messages will be printed when the first `CHECK` fails:
+```
+First info
+First unscoped info
+```
+
+"First unscoped info" message will be cleared after the first `CHECK`, while "First info" message will persist until the end of the test case. Therefore, when the second `CHECK` fails, three messages will be printed:
+```
+First info
+Second info
+Second unscoped info
+```
 
 ## Streaming macros
 
@@ -43,7 +97,14 @@
 
 **INFO(** _message expression_ **)**
 
-The message is logged to a buffer, but only reported with the next assertion that is logged. This allows you to log contextual information in case of failures which is not shown during a successful test run (for the console reporter, without -s). Messages are removed from the buffer at the end of their scope, so may be used, for example, in loops.
+The message is logged to a buffer, but only reported with next assertions that are logged. This allows you to log contextual information in case of failures which is not shown during a successful test run (for the console reporter, without -s). Messages are removed from the buffer at the end of their scope, so may be used, for example, in loops.
+
+_Note that in Catch2 2.x.x `INFO` can be used without a trailing semicolon as there is a trailing semicolon inside macro.
+This semicolon will be removed with next major version. It is highly advised to use a trailing semicolon after `INFO` macro._
+
+**UNSCOPED_INFO(** _message expression_ **)**
+
+Similar to `INFO`, but messages are not limited to their own scope: They are removed from the buffer after each assertion, section or test case, whichever comes first.
 
 **WARN(** _message expression_ **)**
 
@@ -57,26 +118,37 @@
 
 AS `FAIL`, but does not abort the test
 
-## Quickly capture a variable value
+## Quickly capture value of variables or expressions
 
-**CAPTURE(** _expression_ **)**
+**CAPTURE(** _expression1_, _expression2_, ... **)**
 
-Sometimes you just want to log the name and value of a variable. While you can easily do this with the INFO macro, above, as a convenience the CAPTURE macro handles the stringising of the variable name for you (actually it works with any expression, not just variables).
+Sometimes you just want to log a value of variable, or expression. For
+convenience, we provide the `CAPTURE` macro, that can take a variable,
+or an expression, and prints out that variable/expression and its value
+at the time of capture.
 
-E.g.
-```c++
-CAPTURE( theAnswer );
+e.g. `CAPTURE( theAnswer );` will log message "theAnswer := 42", while
+```cpp
+int a = 1, b = 2, c = 3;
+CAPTURE( a, b, c, a + b, c > b, a == 1);
+```
+will log a total of 6 messages:
+```
+a := 1
+b := 2
+c := 3
+a + b := 3
+c > b := true
+a == 1 := true
 ```
 
-This would log something like:
+You can also capture expressions that use commas inside parentheses
+(e.g. function calls), brackets, or braces (e.g. initializers). To
+properly capture expression that contains template parameters list
+(in other words, it contains commas between angle brackets), you need
+to enclose the expression inside parentheses:
+`CAPTURE( (std::pair<int, int>{1, 2}) );`
 
-<pre>"theAnswer := 42"</pre>
-
-## Deprecated macros
-
-**SCOPED_INFO and SCOPED_CAPTURE**
-
-These macros are now deprecated and are just aliases for INFO and CAPTURE (which were not previously scoped).
 
 ---
 
diff --git a/docs/matchers.md b/docs/matchers.md
index fb95ce2..adbd4ce 100644
--- a/docs/matchers.md
+++ b/docs/matchers.md
@@ -53,6 +53,25 @@
 Do note that ULP-based checks only make sense when both compared numbers are of the same type and `WithinULP` will use type of its argument as the target type. This means that `WithinULP(1.f, 1)` will expect to compare `float`s, but `WithinULP(1., 1)` will expect to compare `double`s.
 
 
+### Generic matchers
+Catch also aims to provide a set of generic matchers. Currently this set
+contains only a matcher that takes arbitrary callable predicate and applies
+it onto the provided object.
+
+Because of type inference limitations, the argument type of the predicate
+has to be provided explicitly. Example:
+```cpp
+REQUIRE_THAT("Hello olleH",
+             Predicate<std::string>(
+                 [] (std::string const& str) -> bool { return str.front() == str.back(); },
+                 "First and last character should be equal")
+);
+```
+
+The second argument is an optional description of the predicate, and is
+used only during reporting of the result.
+
+
 ## Custom matchers
 It's easy to provide your own matchers to extend Catch or just to work with your own types.
 
diff --git a/docs/opensource-users.md b/docs/opensource-users.md
index 43596cc..d71b425 100644
--- a/docs/opensource-users.md
+++ b/docs/opensource-users.md
@@ -1,42 +1,45 @@
 <a id="top"></a>
 # Open Source projects using Catch
 
-Catch is great for open source. With its [liberal license](../LICENSE.txt) and single-header, dependency-free, distribution 
+Catch is great for open source. With its [liberal license](../LICENSE.txt) and single-header, dependency-free, distribution
 it's easy to just drop the header into your project and start writing tests - what's not to like?
 
 As a result Catch is now being used in many Open Source projects, including some quite well known ones.
 This page is an attempt to track those projects. Obviously it can never be complete.
 This effort largely relies on the maintainers of the projects themselves updating this page and submitting a PR
-(or, if you prefer contact one of the maintainers of Catch directly, use the 
+(or, if you prefer contact one of the maintainers of Catch directly, use the
 [forums](https://groups.google.com/forum/?fromgroups#!forum/catch-forum)), or raise an [issue](https://github.com/philsquared/Catch/issues) to let us know).
 Of course users of those projects might want to update this page too. That's fine - as long you're confident the project maintainers won't mind.
-If you're an Open Source project maintainer and see your project listed here but would rather it wasn't - 
+If you're an Open Source project maintainer and see your project listed here but would rather it wasn't -
 just let us know via any of the previously mentioned means - although I'm sure there won't be many who feel that way.
- 
+
 Listing a project here does not imply endorsement and the plan is to keep these ordered alphabetically to avoid an implication of relative importance.
 
 ## Libraries & Frameworks
 
 ### [Azmq](https://github.com/zeromq/azmq)
-Boost Asio style bindings for ZeroMQ
+Boost Asio style bindings for ZeroMQ.
 
 ### [ChakraCore](https://github.com/Microsoft/ChakraCore)
-The core part of the Chakra Javascript engine that powers Microsoft Edge
+The core part of the Chakra JavaScript engine that powers Microsoft Edge.
 
 ### [ChaiScript](https://github.com/ChaiScript/ChaiScript)
-A, header-only, embedded scripting language designed from the ground up to directly target C++ and take advantage of modern C++ development techniques
+A, header-only, embedded scripting language designed from the ground up to directly target C++ and take advantage of modern C++ development techniques.
 
 ### [Clara](https://github.com/philsquared/Clara)
 A, single-header-only, type-safe, command line parser - which also prints formatted usage strings.
 
 ### [Couchbase-lite-core](https://github.com/couchbase/couchbase-lite-core)
-The next-generation core storage and query engine for Couchbase Lite
+The next-generation core storage and query engine for Couchbase Lite.
+
+### [cppcodec](https://github.com/tplgy/cppcodec)
+Header-only C++11 library to encode/decode base64, base64url, base32, base32hex and hex (a.k.a. base16) as specified in RFC 4648, plus Crockford's base32.
 
 ### [DtCraft](https://github.com/twhuang-uiuc/DtCraft)
-A High-performance Cluster Computing Engine
+A High-performance Cluster Computing Engine.
 
 ### [forest](https://github.com/xorz57/forest)
-Forest is an open-source, template library of tree data structures written in C++11.
+Template Library of Tree Data Structures.
 
 ### [Fuxedo](https://github.com/fuxedo/fuxedo)
 Open source Oracle Tuxedo-like XATMI middleware for C and C++.
@@ -47,6 +50,9 @@
 ### [JSON for Modern C++](https://github.com/nlohmann/json)
 A, single-header, JSON parsing library that takes advantage of what C++ has to offer.
 
+### [libcluon](https://github.com/chrberger/libcluon)
+A single-header-only library written in C++14 to glue distributed software components (UDP, TCP, shared memory) supporting natively Protobuf, LCM/ZCM, MsgPack, and JSON for dynamic message transformations in-between. 
+
 ### [MNMLSTC Core](https://github.com/mnmlstc/core)
 A small and easy to use C++11 library that adds a functionality set that will be available in C++14 and later, as well as some useful additions.
 
@@ -57,22 +63,25 @@
 A header-only framework for benchmarking small snippets of C++ code.
 
 ### [SOCI](https://github.com/SOCI/soci)
-The C++ Database Access Library
+The C++ Database Access Library.
 
 ### [polymorphic_value](https://github.com/jbcoe/polymorphic_value)
-A polymorphic value-type for C++
+A polymorphic value-type for C++.
 
 ### [Ppconsul](https://github.com/oliora/ppconsul)
-A C++ client library for Consul. Consul is a distributed tool for discovering and configuring services in your infrastructure
+A C++ client library for Consul. Consul is a distributed tool for discovering and configuring services in your infrastructure.
 
 ### [Reactive-Extensions/ RxCpp](https://github.com/Reactive-Extensions/RxCpp)
-A library of algorithms for values-distributed-in-time
+A library of algorithms for values-distributed-in-time.
+
+### [thor](https://github.com/xorz57/thor)
+Wrapper Library for CUDA.
 
 ### [TextFlowCpp](https://github.com/philsquared/textflowcpp)
-A small, single-header-only, library for wrapping and composing columns of text
+A small, single-header-only, library for wrapping and composing columns of text.
 
 ### [Trompeloeil](https://github.com/rollbear/trompeloeil)
-A thread safe header only mocking framework for C++14
+A thread-safe header-only mocking framework for C++14.
 
 ### [args](https://github.com/Taywee/args)
 A simple header-only C++ argument parser library.
@@ -86,13 +95,16 @@
 Minimal, open-source and cross-platform audio tool for live music production.
 
 ### [MAME](https://github.com/mamedev/mame)
-MAME originally stood for Multiple Arcade Machine Emulator
+MAME originally stood for Multiple Arcade Machine Emulator.
 
 ### [Newsbeuter](https://github.com/akrennmair/newsbeuter)
 Newsbeuter is an open-source RSS/Atom feed reader for text terminals.
 
+### [SpECTRE](https://github.com/sxs-collaboration/spectre)
+SpECTRE is a code for multi-scale, multi-physics problems in astrophysics and gravitational physics.
+
 ### [Standardese](https://github.com/foonathan/standardese)
-Standardese aims to be a nextgen Doxygen
+Standardese aims to be a nextgen Doxygen.
 
 ---
 
diff --git a/docs/other-macros.md b/docs/other-macros.md
new file mode 100644
index 0000000..6f5fac7
--- /dev/null
+++ b/docs/other-macros.md
@@ -0,0 +1,150 @@
+<a id="top"></a>
+# Other macros
+
+This page serves as a reference for macros that are not documented
+elsewhere. For now, these macros are separated into 2 rough categories,
+"assertion related macros" and "test case related macros".
+
+## Assertion related macros
+
+* `CHECKED_IF` and `CHECKED_ELSE`
+
+`CHECKED_IF( expr )` is an `if` replacement, that also applies Catch2's
+stringification machinery to the _expr_ and records the result. As with
+`if`, the block after a `CHECKED_IF` is entered only if the expression
+evaluates to `true`. `CHECKED_ELSE( expr )` work similarly, but the block
+is entered only if the _expr_ evaluated to `false`.
+
+Example:
+```cpp
+int a = ...;
+int b = ...;
+CHECKED_IF( a == b ) {
+    // This block is entered when a == b
+} CHECKED_ELSE ( a == b ) {
+    // This block is entered when a != b
+}
+```
+
+* `CHECK_NOFAIL`
+
+`CHECK_NOFAIL( expr )` is a variant of `CHECK` that does not fail the test
+case if _expr_ evaluates to `false`. This can be useful for checking some
+assumption, that might be violated without the test neccessarily failing.
+
+Example output:
+```
+main.cpp:6:
+FAILED - but was ok:
+  CHECK_NOFAIL( 1 == 2 )
+
+main.cpp:7:
+PASSED:
+  CHECK( 2 == 2 )
+```
+
+* `SUCCEED`
+
+`SUCCEED( msg )` is mostly equivalent with `INFO( msg ); REQUIRE( true );`.
+In other words, `SUCCEED` is for cases where just reaching a certain line
+means that the test has been a success.
+
+Example usage:
+```cpp
+TEST_CASE( "SUCCEED showcase" ) {
+    int I = 1;
+    SUCCEED( "I is " << I );
+}
+```
+
+* `STATIC_REQUIRE`
+
+`STATIC_REQUIRE( expr )` is a macro that can be used the same way as a
+`static_assert`, but also registers the success with Catch2, so it is
+reported as a success at runtime. The whole check can also be deferred
+to the runtime, by defining `CATCH_CONFIG_RUNTIME_STATIC_REQUIRE` before
+including the Catch2 header.
+
+Example:
+```cpp
+TEST_CASE("STATIC_REQUIRE showcase", "[traits]") {
+    STATIC_REQUIRE( std::is_void<void>::value );
+    STATIC_REQUIRE_FALSE( std::is_void<int>::value );
+}
+```
+
+## Test case related macros
+
+* `METHOD_AS_TEST_CASE`
+
+`METHOD_AS_TEST_CASE( member-function-pointer, description )` lets you
+register a member function of a class as a Catch2 test case. The class
+will be separately instantiated for each method registered in this way.
+
+```cpp
+class TestClass {
+    std::string s;
+
+public:
+    TestClass()
+        :s( "hello" )
+    {}
+
+    void testCase() {
+        REQUIRE( s == "hello" );
+    }
+};
+
+
+METHOD_AS_TEST_CASE( TestClass::testCase, "Use class's method as a test case", "[class]" )
+```
+
+* `REGISTER_TEST_CASE`
+
+`REGISTER_TEST_CASE( function, description )` let's you register
+a `function` as a test case. The function has to have `void()` signature,
+the description can contain both name and tags.
+
+Example:
+```cpp
+REGISTER_TEST_CASE( someFunction, "ManuallyRegistered", "[tags]" );
+```
+
+_Note that the registration still has to happen before Catch2's session
+is initiated. This means that it either needs to be done in a global
+constructor, or before Catch2's session is created in user's own main._
+
+
+* `ANON_TEST_CASE`
+
+`ANON_TEST_CASE` is a `TEST_CASE` replacement that will autogenerate
+unique name. The advantage of this is that you do not have to think
+of a name for the test case,`the disadvantage is that the name doesn't
+neccessarily remain stable across different links, and thus it might be
+hard to run directly.
+
+Example:
+```cpp
+ANON_TEST_CASE() {
+    SUCCEED("Hello from anonymous test case");
+}
+```
+
+* `DYNAMIC_SECTION`
+
+`DYNAMIC_SECTION` is a `SECTION` where the user can use `operator<<` to
+create the final name for that section. This can be useful with e.g.
+generators, or when creating a `SECTION` dynamically, within a loop.
+
+Example:
+```cpp
+TEST_CASE( "looped SECTION tests" ) {
+    int a = 1;
+
+    for( int b = 0; b < 10; ++b ) {
+        DYNAMIC_SECTION( "b is currently: " << b ) {
+            CHECK( b > a );
+        }
+    }
+}
+```
diff --git a/docs/own-main.md b/docs/own-main.md
index 18d1b7d..6a9b1aa 100644
--- a/docs/own-main.md
+++ b/docs/own-main.md
@@ -1,6 +1,12 @@
 <a id="top"></a>
 # Supplying main() yourself
 
+**Contents**<br>
+[Let Catch take full control of args and config](#let-catch-take-full-control-of-args-and-config)<br>
+[Amending the config](#amending-the-config)<br>
+[Adding your own command line options](#adding-your-own-command-line-options)<br>
+[Version detection](#version-detection)<br>
+
 The easiest way to use Catch is to let it supply ```main()``` for you and handle configuring itself from the command line.
 
 This is achieved by writing ```#define CATCH_CONFIG_MAIN``` before the ```#include "catch.hpp"``` in *exactly one* source file.
@@ -30,7 +36,7 @@
 
 ## Amending the config
 
-If you still want Catch to process the command line, but you want to programatically tweak the config, you can do so in one of two ways:
+If you still want Catch to process the command line, but you want to programmatically tweak the config, you can do so in one of two ways:
 
 ```c++
 #define CATCH_CONFIG_RUNNER
@@ -45,7 +51,7 @@
     
   int returnCode = session.applyCommandLine( argc, argv );
   if( returnCode != 0 ) // Indicates a command line error
-  	  return returnCode;
+        return returnCode;
  
   // writing to session.configData() or session.Config() here 
   // overrides command line args
@@ -94,7 +100,7 @@
   // Let Catch (using Clara) parse the command line
   int returnCode = session.applyCommandLine( argc, argv );
   if( returnCode != 0 ) // Indicates a command line error
-  	return returnCode;
+      return returnCode;
 
   // if set on the command line then 'height' is now set at this point
   if( height > 0 )
diff --git a/docs/release-notes.md b/docs/release-notes.md
index 565d6cd..34278c3 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -1,20 +1,360 @@
 <a id="top"></a>
 
-# 2.1.1
+# Release notes
+**Contents**<br>
+[2.7.0](#270)<br>
+[2.6.1](#261)<br>
+[2.6.0](#260)<br>
+[2.5.0](#250)<br>
+[2.4.2](#242)<br>
+[2.4.1](#241)<br>
+[2.4.0](#240)<br>
+[2.3.0](#230)<br>
+[2.2.3](#223)<br>
+[2.2.2](#222)<br>
+[2.2.1](#221)<br>
+[2.2.0](#220)<br>
+[2.1.2](#212)<br>
+[2.1.1](#211)<br>
+[2.1.0](#210)<br>
+[2.0.1](#201)<br>
+[Older versions](#older-versions)<br>
+[Even Older versions](#even-older-versions)<br>
 
-## Improvements
+## 2.7.0
+
+### Improvements
+* `TEMPLATE_PRODUCT_TEST_CASE` now uses the resulting type in the name, instead of the serial number (#1544)
+* Catch2's single header is now strictly ASCII (#1542)
+* Added generator for random integral/floating point types
+  * The types are inferred within the `random` helper
+* Added back RangeGenerator (#1526)
+  * RangeGenerator returns elements within a certain range
+* Added ChunkGenerator generic transform (#1538)
+  * A ChunkGenerator returns the elements from different generator in chunks of n elements
+* Added `UNSCOPED_INFO` (#415, #983, #1522)
+  * This is a variant of `INFO` that lives until next assertion/end of the test case.
+
+
+### Fixes
+* All calls to C stdlib functions are now `std::` qualified (#1541)
+  * Code brought in from Clara was also updated.
+* Running tests will no longer open the specified output file twice (#1545)
+  * This would cause trouble when the file was not a file, but rather a named pipe
+  * Fixes the CLion/Resharper integration with Catch
+* Fixed `-Wunreachable-code` occuring with (old) ccache+cmake+clang combination (#1540)
+* Fixed `-Wdefaulted-function-deleted` warning with Clang 8 (#1537)
+* Catch2's type traits and helpers are now properly namespaced inside `Catch::` (#1548)
+* Fixed std{out,err} redirection for failing test (#1514, #1525)
+  * Somehow, this bug has been present for well over a year before it was reported
+
+
+### Contrib
+* `ParseAndAddCatchTests` now properly escapes commas in the test name
+
+
+
+## 2.6.1
+
+### Improvements
+* The JUnit reporter now also reports random seed (#1520, #1521)
+
+### Fixes
+* The TAP reporter now formats comments with test name properly (#1529)
+* `CATCH_REQUIRE_THROWS`'s internals were unified with `REQUIRE_THROWS` (#1536)
+  * This fixes a potential `-Wunused-value` warning when used
+* Fixed a potential segfault when using any of the `--list-*` options (#1533, #1534)
+
+
+## 2.6.0
+
+**With this release the data generator feature is now fully supported.**
+
+
+### Improvements
+* Added `TEMPLATE_PRODUCT_TEST_CASE` (#1454, #1468)
+  * This allows you to easily test various type combinations, see documentation for details
+* The error message for `&&` and `||` inside assertions has been improved (#1273, #1480)
+* The error message for chained comparisons inside assertions has been improved (#1481)
+* Added `StringMaker` specialization for `std::optional` (#1510)
+* The generator interface has been redone once again (#1516)
+  * It is no longer considered experimental and is fully supported
+  * The new interface supports "Input" generators
+  * The generator documentation has been fully updated
+  * We also added 2 generator examples
+
+
+### Fixes
+* Fixed `-Wredundant-move` on newer Clang (#1474)
+* Removed unreachable mentions `std::current_exception`, `std::rethrow_exception` in no-exceptions mode (#1462)
+  * This should fix compilation with IAR
+* Fixed missing `<type_traits>` include (#1494)
+* Fixed various static analysis warnings
+  * Unrestored stream state in `XmlWriter` (#1489)
+  * Potential division by zero in `estimateClockResolution` (#1490)
+  * Uninitialized member in `RunContext` (#1491)
+  * `SourceLineInfo` move ops are now marked `noexcept`
+  * `CATCH_BREAK_INTO_DEBUGGER` is now always a function
+* Fix double run of a test case if user asks for a specific section (#1394, #1492)
+* ANSI colour code output now respects `-o` flag and writes to the file as well (#1502)
+* Fixed detection of `std::variant` support for compilers other than Clang (#1511)
+
+
+### Contrib
+* `ParseAndAddCatchTests` has learned how to use `DISABLED` CTest property (#1452)
+* `ParseAndAddCatchTests` now works when there is a whitspace before the test name (#1493)
+
+
+### Miscellaneous
+* We added new issue templates for reporting issues on GitHub
+* `contributing.md` has been updated to reflect the current test status (#1484)
+
+
+
+## 2.5.0
+
+### Improvements
+* Added support for templated tests via `TEMPLATE_TEST_CASE` (#1437)
+
+
+### Fixes
+* Fixed compilation of `PredicateMatcher<const char*>` by removing partial specialization of `MatcherMethod<T*>`
+* Listeners now implicitly support any verbosity (#1426)
+* Fixed compilation with Embarcadero builder by introducing `Catch::isnan` polyfill (#1438)
+* Fixed `CAPTURE` asserting for non-trivial captures (#1436, #1448)
+
+
+### Miscellaneous
+* We should now be providing first party Conan support via https://bintray.com/catchorg/Catch2 (#1443)
+* Added new section "deprecations and planned changes" to the documentation
+  * It contains summary of what is deprecated and might change with next major version
+* From this release forward, the released headers should be pgp signed (#430)
+  * KeyID `E29C 46F3 B8A7 5028 6079 3B7D ECC9 C20E 314B 2360`
+  * or https://codingnest.com/files/horenmar-publickey.asc
+
+
+## 2.4.2
+
+### Improvements
+* XmlReporter now also outputs the RNG seed that was used in a run (#1404)
+* `Catch::Session::applyCommandLine` now also accepts `wchar_t` arguments.
+  * However, Catch2 still does not support unicode.
+* Added `STATIC_REQUIRE` macro (#1356, #1362)
+* Catch2's singleton's are now cleaned up even if tests are run (#1411)
+  * This is mostly useful as a FP prevention for users who define their own main.
+* Specifying an invalid reporter via `-r` is now reported sooner (#1351, #1422)
+
+
+### Fixes
+* Stringification no longer assumes that `char` is signed (#1399, #1407)
+  * This caused a `Wtautological-compare` warning.
+* SFINAE for `operator<<` no longer sees different overload set than the actual insertion (#1403)
+
+
+### Contrib
+* `catch_discover_tests` correctly adds tests with comma in name (#1327, #1409)
+* Added a new customization point in how the tests are launched to `catch_discover_tests`
+
+
+## 2.4.1
+
+### Improvements
+* Added a StringMaker for `std::(w)string_view` (#1375, #1376)
+* Added a StringMaker for `std::variant` (#1380)
+  * This one is disabled by default to avoid increased compile-time drag
+* Added detection for cygwin environment without `std::to_string` (#1396, #1397)
+
+### Fixes
+* `UnorderedEqualsMatcher` will no longer accept erroneously accept
+vectors that share suffix, but are not permutation of the desired vector
+* Abort after (`-x N`) can no longer be overshot by nested `REQUIRES` and
+subsequently ignored (#1391, #1392)
+
+
+## 2.4.0
+
+**This release brings two new experimental features, generator support
+and a `-fno-exceptions` support. Being experimental means that they
+will not be subject to the usual stability guarantees provided by semver.**
+
+### Improvements
+* Various small runtime performance improvements
+* `CAPTURE` macro is now variadic
+* Added `AND_GIVEN` macro (#1360)
+* Added experimental support for data generators
+  * See [their documentation](generators.md) for details
+* Added support for compiling and running Catch without exceptions
+  * Doing so limits the functionality somewhat
+  * Look [into the documentation](configuration.md#disablingexceptions) for details
+
+### Fixes
+* Suppressed `-Wnon-virtual-dtor` warnings in Matchers (#1357)
+* Suppressed `-Wunreachable-code` warnings in floating point matchers (#1350)
+
+### CMake
+* It is now possible to override which Python is used to run Catch's tests (#1365)
+* Catch now provides infrastructure for adding tests that check compile-time configuration
+* Catch no longer tries to install itself when used as a subproject (#1373)
+* Catch2ConfigVersion.cmake is now generated as arch-independent (#1368)
+  * This means that installing Catch from 32-bit machine and copying it to 64-bit one works
+  * This fixes conan installation of Catch
+
+
+## 2.3.0
+
+**This release changes the include paths provided by our CMake and
+pkg-config integration. The proper include path for the single-header
+when using one of the above is now `<catch2/catch.hpp>`. This change
+also necessitated changes to paths inside the repository, so that the
+single-header version is now at `single_include/catch2/catch.hpp`, rather
+than `single_include/catch.hpp`.**
+
+
+
+### Fixes
+* Fixed Objective-C++ build
+* `-Wunused-variable` suppression no longer leaks from Catch's header under Clang
+* Implementation of the experimental new output capture can now be disabled (#1335)
+  * This allows building Catch2 on platforms that do not provide things like `dup` or `tmpfile`.
+* The JUnit and XML reporters will no longer skip over successful tests when running without `-s`  (#1264, #1267, #1310)
+  * See improvements for more details
+
+### Improvements
+* pkg-config and CMake integration has been rewritten
+  * If you use them, the new include path is `#include <catch2/catch.hpp>`
+  * CMake installation now also installs scripts from `contrib/`
+  * For details see the [new documentation](cmake-integration.md#top)
+* Reporters now have a new customization point, `ReporterPreferences::shouldReportAllAssertions`
+  * When this is set to `false` and the tests are run without `-s`, passing assertions are not sent to the reporter.
+  * Defaults to `false`.
+* Added `DYNAMIC_SECTION`, a section variant that constructs its name using stream
+  * This means that you can do `DYNAMIC_SECTION("For X := " << x)`.
+
+
+## 2.2.3
+
+**To fix some of the bugs, some behavior had to change in potentially breaking manner.**
+**This means that even though this is a patch release, it might not be a drop-in replacement.**
+
+### Fixes
+* Listeners are now called before reporter
+  * This was always documented to be the case, now it actually works that way
+* Catch's commandline will no longer accept multiple reporters
+  * This was done because multiple reporters never worked properly and broke things in non-obvious ways
+  * **This has potential to be a breaking change**
+* MinGW is now detected as Windows platform w/o SEH support (#1257)
+  * This means that Catch2 no longer tries to use POSIX signal handling when compiled with MinGW
+* Fixed potential UB in parsing tags using non-ASCII characters (#1266)
+  * Note that Catch2 still supports only ASCII test names/tags/etc
+* `TEST_CASE_METHOD` can now be used on classnames containing commas (#1245)
+  * You have to enclose the classname in extra set of parentheses
+* Fixed insufficient alt stack size for POSIX signal handling (#1225)
+* Fixed compilation error on Android due to missing `std::to_string` in C++11 mode (#1280)
+* Fixed the order of user-provided `FALLBACK_STRINGIFIER` in stringification machinery (#1024)
+  * It was intended to be replacement for built-in fallbacks, but it was used _after_ them.
+  * **This has potential to be a breaking change**
+* Fixed compilation error when a type has an `operator<<` with templated lhs (#1285, #1306)
+
+### Improvements
+* Added a new, experimental, output capture (#1243)
+  * This capture can also redirect output written via C apis, e.g. `printf`
+  * To opt-in, define `CATCH_CONFIG_EXPERIMENTAL_REDIRECT` in the implementation file
+* Added a new fallback stringifier for classes derived from `std::exception`
+  * Both `StringMaker` specialization and `operator<<` overload are given priority
+
+### Miscellaneous
+* `contrib/` now contains dbg scripts that skip over Catch's internals (#904, #1283)
+  * `gdbinit` for gdb `lldbinit` for lldb
+* `CatchAddTests.cmake` no longer strips whitespace from tests (#1265, #1281)
+* Online documentation now describes `--use-colour` option (#1263)
+
+
+## 2.2.2
+
+### Fixes
+* Fixed bug in `WithinAbs::match()` failing spuriously (#1228)
+* Fixed clang-tidy diagnostic about virtual call in destructor (#1226)
+* Reduced the number of GCC warnings suppression leaking out of the header (#1090, #1091)
+  * Only `-Wparentheses` should be leaking now
+* Added upper bound on the time benchmark timer calibration is allowed to take (#1237)
+  * On platforms where `std::chrono::high_resolution_clock`'s resolution is low, the calibration would appear stuck
+* Fixed compilation error when stringifying static arrays of `unsigned char`s (#1238)
+
+### Improvements
+* XML encoder now hex-encodes invalid UTF-8 sequences (#1207)
+  * This affects xml and junit reporters
+  * Some invalid UTF-8 parts are left as is, e.g. surrogate pairs. This is because certain extensions of UTF-8 allow them, such as WTF-8.
+* CLR objects (`T^`) can now be stringified (#1216)
+  * This affects code compiled as C++/CLI
+* Added `PredicateMatcher`, a matcher that takes an arbitrary predicate function (#1236)
+  * See [documentation for details](https://github.com/catchorg/Catch2/blob/master/docs/matchers.md)
+
+### Others
+* Modified CMake-installed pkg-config to allow `#include <catch.hpp>`(#1239)
+  * The plans to standardize on `#include <catch2/catch.hpp>` are still in effect
+
+
+## 2.2.1
+
+### Fixes
+* Fixed compilation error when compiling Catch2 with `std=c++17` against libc++ (#1214)
+  * Clara (Catch2's CLI parsing library) used `std::optional` without including it explicitly
+* Fixed Catch2 return code always being 0 (#1215)
+  * In the words of STL, "We feel superbad about letting this in"
+
+
+## 2.2.0
+
+### Fixes
+* Hidden tests are not listed by default when listing tests (#1175)
+  * This makes `catch_discover_tests` CMake script work better
+* Fixed regression that meant `<windows.h>` could potentially not be included properly (#1197)
+* Fixed installing `Catch2ConfigVersion.cmake` when Catch2 is a subproject.
+
+### Improvements
+* Added an option to warn (+ exit with error) when no tests were ran (#1158)
+  * Use as `-w NoTests`
+* Added provisional support for Emscripten (#1114)
+* [Added a way to override the fallback stringifier](https://github.com/catchorg/Catch2/blob/master/docs/configuration.md#fallback-stringifier) (#1024)
+  * This allows project's own stringification machinery to be easily reused for Catch
+* `Catch::Session::run()` now accepts `char const * const *`, allowing it to accept array of string literals (#1031, #1178)
+  * The embedded version of Clara was bumped to v1.1.3
+* Various minor performance improvements
+* Added support for DJGPP DOS crosscompiler (#1206)
+
+
+## 2.1.2
+
+### Fixes
+* Fixed compilation error with `-fno-rtti` (#1165)
+* Fixed NoAssertion warnings
+* `operator<<` is used before range-based stringification (#1172)
+* Fixed `-Wpedantic` warnings (extra semicolons and binary literals) (#1173)
+
+
+### Improvements
+* Added `CATCH_VERSION_{MAJOR,MINOR,PATCH}` macros (#1131)
+* Added `BrightYellow` colour for use in reporters (#979)
+  * It is also used by ConsoleReporter for reconstructed expressions
+
+### Other changes
+* Catch is now exported as a CMake package and linkable target (#1170)
+
+## 2.1.1
+
+### Improvements
 * Static arrays are now properly stringified like ranges across MSVC/GCC/Clang
 * Embedded newer version of Clara -- v1.1.1
   * This should fix some warnings dragged in from Clara
 * MSVC's CLR exceptions are supported
 
 
-## Fixes
+### Fixes
 * Fixed compilation when comparison operators do not return bool (#1147)
 * Fixed CLR exceptions blowing up the executable during translation (#1138)
 
 
-## Other changes
+### Other changes
 * Many CMake changes
   * `NO_SELFTEST` option is deprecated, use `BUILD_TESTING` instead.
   * Catch specific CMake options were prefixed with `CATCH_` for namespacing purposes
@@ -22,9 +362,9 @@
 
 
 
-# 2.1.0
+## 2.1.0
 
-## Improvements
+### Improvements
 * Various performance improvements
   * On top of the performance regression fixes
 * Experimental support for PCH was added (#1061)
@@ -34,7 +374,7 @@
   * Bugs in g++ 4.x and 5.x mean that some of them have to be left in
 
 
-## Fixes
+### Fixes
 * Fixed performance regression from Catch classic
   * One of the performance improvement patches for Catch classic was not applied to Catch2
 * Fixed platform detection for iOS (#1084)
@@ -47,7 +387,7 @@
 * Fixed `std::uncaught_exception` deprecation warning (#1124)
 
 
-## New features
+### New features
 * New Matchers
   * Regex matcher for strings, `Matches`.
   * Set-equal matcher for vectors, `UnorderedEquals`
@@ -56,15 +396,15 @@
   * Containers are objects that respond to ADL `begin(T)` and `end(T)`.
 
 
-## Other changes
+### Other changes
 * Reporters will now be versioned in the `single_include` folder to ensure their compatibility with the last released version
 
 
 
 
-# 2.0.1
+## 2.0.1
 
-## Breaking changes
+### Breaking changes
 * Removed C++98 support
 * Removed legacy reporter support
 * Removed legacy generator support
@@ -94,7 +434,7 @@
   * `INFINITY == Approx(INFINITY)` returns true
 
 
-## Improvements
+### Improvements
 * Reporters and Listeners can be defined in files different from the main file
   * The file has to define `CATCH_CONFIG_EXTERNAL_INTERFACES` before including catch.hpp.
 * Errors that happen during set up before main are now caught and properly reported once main is entered
@@ -128,7 +468,7 @@
 * Add `pkg-config` support to CMake install command
 
 
-## Fixes
+### Fixes
 * Don't use console colour if running in XCode
 * Explicit constructor in reporter base class
 * Swept out `-Wweak-vtables`, `-Wexit-time-destructors`, `-Wglobal-constructors` warnings
@@ -140,7 +480,7 @@
 * Suppressed C4061 warning under MSVC
 
 
-## Internal changes
+### Internal changes
 * The development version now uses .cpp files instead of header files containing implementation.
   * This makes partial rebuilds much faster during development
 * The expression decomposition layer has been rewritten
@@ -148,13 +488,33 @@
 * New library (TextFlow) is used for formatting text to output
 
 
-# Older versions
+## Older versions
 
-## 1.11.x
+### 1.12.x
 
-### 1.11.0
+#### 1.12.2
+##### Fixes
+* Fixed missing <cassert> include
 
-#### Fixes
+#### 1.12.1
+
+##### Fixes
+* Fixed deprecation warning in `ScopedMessage::~ScopedMessage`
+* All uses of `min` or `max` identifiers are now wrapped in parentheses
+  * This avoids problems when Windows headers define `min` and `max` macros
+
+#### 1.12.0
+
+##### Fixes
+* Fixed compilation for strict C++98 mode (ie not gnu++98) and older compilers (#1103)
+* `INFO` messages are included in the `xml` reporter output even without `-s` specified.
+
+
+### 1.11.x
+
+#### 1.11.0
+
+##### Fixes
 * The original expression in `REQUIRE_FALSE( expr )` is now reporter properly as `!( expr )` (#1051)
   * Previously the parentheses were missing and `x != y` would be expanded as `!x != x`
 * `Approx::Margin` is now inclusive (#952)
@@ -162,7 +522,7 @@
   * This means that `REQUIRE( 0.25f == Approx( 0.0f ).margin( 0.25f ) )` passes, instead of fails
 * `RandomNumberGenerator::result_type` is now unsigned (#1050)
 
-#### Improvements
+##### Improvements
 * `__JETBRAINS_IDE__` macro handling is now CLion version specific (#1017)
   * When CLion 2017.3 or newer is detected, `__COUNTER__` is used instead of
 * TeamCity reporter now explicitly flushes output stream after each report (#1057)
@@ -170,35 +530,35 @@
 * `ParseAndAddCatchTests` now can add test files as dependency to CMake configuration
   * This means you do not have to manually rerun CMake configuration step to detect new tests
 
-## 1.10.x
+### 1.10.x
 
-### 1.10.0
+#### 1.10.0
 
-#### Fixes
+##### Fixes
 * Evaluation layer has been rewritten (backported from Catch 2)
   * The new layer is much simpler and fixes some issues (#981)
 * Implemented workaround for VS 2017 raw string literal stringification bug (#995)
 * Fixed interaction between `[!shouldfail]` and `[!mayfail]` tags and sections
   * Previously sections with failing assertions would be marked as failed, not failed-but-ok
 
-#### Improvements
+##### Improvements
 * Added [libidentify](https://github.com/janwilmans/LibIdentify) support
 * Added "wait-for-keypress" option
 
-## 1.9.x
+### 1.9.x
 
-### 1.9.6
+#### 1.9.6
 
-#### Improvements
+##### Improvements
 * Catch's runtime overhead has been significantly decreased (#937, #939)
 * Added `--list-extra-info` cli option (#934).
   * It lists all tests together with extra information, ie filename, line number and description.
 
 
 
-### 1.9.5
+#### 1.9.5
 
-#### Fixes
+##### Fixes
 * Truthy expressions are now reconstructed properly, not as booleans (#914)
 * Various warnings are no longer erroneously suppressed in test files (files that include `catch.hpp`, but do not define `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`) (#871)
 * Catch no longer fails to link when main is compiled as C++, but linked against Objective-C (#855)
@@ -206,35 +566,35 @@
   * Previously any GCC with minor version less than 3 would be incorrectly classified as not supporting `__COUNTER__`.
 * Suppressed C4996 warning caused by upcoming updated to MSVC 2017, marking `std::uncaught_exception` as deprecated. (#927)
 
-#### Improvements
+##### Improvements
 * CMake integration script now incorporates debug messages and registers tests in an improved way (#911)
 * Various documentation improvements
 
 
 
-### 1.9.4
+#### 1.9.4
 
-#### Fixes
+##### Fixes
 * `CATCH_FAIL` macro no longer causes compilation error without variadic macro support
 * `INFO` messages are no longer cleared after being reported once
 
-#### Improvements and minor changes
+##### Improvements and minor changes
 * Catch now uses `wmain` when compiled under Windows and `UNICODE` is defined.
   * Note that Catch still officially supports only ASCII
 
-### 1.9.3
+#### 1.9.3
 
-#### Fixes
+##### Fixes
 * Completed the fix for (lack of) uint64_t in earlier Visual Studios
 
-### 1.9.2
+#### 1.9.2
 
-#### Improvements and minor changes
+##### Improvements and minor changes
 * All of `Approx`'s member functions now accept strong typedefs in C++11 mode (#888)
   * Previously `Approx::scale`, `Approx::epsilon`, `Approx::margin` and `Approx::operator()` didn't.
 
 
-#### Fixes
+##### Fixes
 * POSIX signals are now disabled by default under QNX (#889)
   * QNX does not support current enough (2001) POSIX specification
 * JUnit no longer counts exceptions as failures if given test case is marked as ok to fail.
@@ -242,22 +602,22 @@
 * Catch no longer attempts to define `uint64_t` on windows (#862)
   * This was causing trouble when compiled under Cygwin
 
-#### Other
+##### Other
 * Catch is now compiled under MSVC 2017 using `std:c++latest` (C++17 mode) in CI
 * We now provide cmake script that autoregisters Catch tests into ctest.
   * See `contrib` folder.
 
 
-### 1.9.1
+#### 1.9.1
 
-#### Fixes
+##### Fixes
 * Unexpected exceptions are no longer ignored by default (#885, #887)
 
 
-### 1.9.0
+#### 1.9.0
 
 
-#### Improvements and minor changes
+##### Improvements and minor changes
 * Catch no longer attempts to ensure the exception type passed by user in `REQUIRE_THROWS_AS` is a constant reference.
   * It was causing trouble when `REQUIRE_THROWS_AS` was used inside templated functions
   * This actually reverts changes made in v1.7.2
@@ -271,7 +631,7 @@
 * When Catch is compiled using C++11, `Approx` is now constructible with anything that can be explicitly converted to `double`.
 * Captured messages are now printed on unexpected exceptions
 
-#### Fixes:
+##### Fixes:
 * Clang's `-Wexit-time-destructors` should be suppressed for Catch's internals
 * GCC's `-Wparentheses` is now suppressed for all TU's that include `catch.hpp`.
   * This is functionally a revert of changes made in 1.8.0, where we tried using `_Pragma` based suppression. This should have kept the suppression local to Catch's assertions, but bugs in GCC's handling of `_Pragma`s in C++ mode meant that it did not always work.
@@ -280,18 +640,18 @@
   * [Details can be found in documentation](configuration.md#catch_config_cpp11_stream_insertable_check)
 
 
-#### Other notes:
+##### Other notes:
 * We have added VS 2017 to our CI
 * Work on Catch 2 should start soon
 
 
 
-## 1.8.x
+### 1.8.x
 
-### 1.8.2
+#### 1.8.2
 
 
-#### Improvements and minor changes
+##### Improvements and minor changes
 * TAP reporter now behaves as if `-s` was always set
   * This should be more consistent with the protocol desired behaviour.
 * Compact reporter now obeys `-d yes` argument (#780)
@@ -305,7 +665,7 @@
   * Listeners provide a way to hook into events generated by running your tests, including start and end of run, every test case, every section and every assertion.
 
 
-#### Fixes:
+##### Fixes:
 * Catch no longer attempts to reconstruct expression that led to a fatal error  (#810)
   * This fixes possible signal/SEH loop when processing expressions, where the signal was triggered by expression decomposition.
 * Fixed (C4265) missing virtual destructor warning in Matchers (#844)
@@ -322,21 +682,21 @@
 * Regression in Objective-C bindings (Matchers) fixed (#854)
 
 
-#### Other notes:
+##### Other notes:
 * We have added VS 2013 and 2015 to our CI
 * Catch Classic (1.x.x) now contains its own, forked, version of Clara (the argument parser).
 
 
 
-### 1.8.1
+#### 1.8.1
 
-#### Fixes
+##### Fixes
 
 Cygwin issue with `gettimeofday` - `#define` was not early enough
 
-### 1.8.0
+#### 1.8.0
 
-#### New features/ minor changes
+##### New features/ minor changes
 
 * Matchers have new, simpler (and documented) interface.
   * Catch provides string and vector matchers.
@@ -356,33 +716,33 @@
 * `Approx` now supports an optional margin of absolute error
   * It has also received [new documentation](assertions.md#top).
 
-#### Fixes
+##### Fixes
 * Silenced C4312 ("conversion from int to 'ClassName *") warnings in the evaluate layer.
 * Fixed C4512 ("assignment operator could not be generated") warnings under VS2013.
 * Cygwin compatibility fixes
   * Signal handling is no longer compiled by default.
   * Usage of `gettimeofday` inside Catch should no longer cause compilation errors.
-* Improved `-Wparentheses` supression for gcc (#674)
-  * When compiled with gcc 4.8 or newer, the supression is localized to assertions only
+* Improved `-Wparentheses` suppression for gcc (#674)
+  * When compiled with gcc 4.8 or newer, the suppression is localized to assertions only
   * Otherwise it is supressed for the whole TU
 * Fixed test spec parser issue (with escapes in multiple names)
 
-#### Other
+##### Other
 * Various documentation fixes and improvements
 
 
-## 1.7.x
+### 1.7.x
 
-### 1.7.2
+#### 1.7.2
 
-#### Fixes and minor improvements
+##### Fixes and minor improvements
 Xml:
 
 (technically the first two are breaking changes but are also fixes and arguably break few if any people)
 * C-escape control characters instead of XML encoding them (which requires XML 1.1)
 * Revert XML output to XML 1.0
 * Can provide stylesheet references by extending the XML reporter
-* Added description and tags attribites to XML Reporter
+* Added description and tags attributes to XML Reporter
 * Tags are closed and the stream flushed more eagerly to avoid stdout interpolation
 
 
@@ -394,9 +754,9 @@
 * Silenced a few more warnings in different circumstances
 * Travis improvements
 
-### 1.7.1
+#### 1.7.1
 
-#### Fixes:
+##### Fixes:
 * Fixed inconsistency in defining `NOMINMAX` and `WIN32_LEAN_AND_MEAN` inside `catch.hpp`.
 * Fixed SEH-related compilation error under older MinGW compilers, by making Windows SEH handling opt-in for compilers other than MSVC.
   * For specifics, look into the [documentation](configuration.md#top).
@@ -406,9 +766,9 @@
 * Fixed possible infinite recursion in Windows SEH.
 * Fixed possible compilation error caused by Catch's operator overloads being ambiguous in regards to user-defined templated operators.
 
-### 1.7.0
+#### 1.7.0
 
-#### Features/ Changes:
+##### Features/ Changes:
 * Catch now runs significantly faster for passing tests
   * Microbenchmark focused on Catch's overhead went from ~3.4s to ~0.7s.
   * Real world test using [JSON for Modern C++](https://github.com/nlohmann/json)'s test suite went from ~6m 25s to ~4m 14s.
@@ -422,30 +782,30 @@
 * Certain characters (space, tab, etc) are now pretty printed.
   * This means that a `char c = ' '; REQUIRE(c == '\t');` would be printed as `' ' == '\t'`, instead of ` == 9`.
 
-#### Fixes:
+##### Fixes:
 * Text formatting no longer attempts to access out-of-bounds characters under certain conditions.
 * THROW family of assertions no longer trigger `-Wunused-value` on expressions containing explicit cast.
 * Breaking into debugger under OS X works again and no longer required `DEBUG` to be defined.
 * Compilation no longer breaks under certain compiler if a lambda is used inside assertion macro.
 
-#### Other:
+##### Other:
 * Catch's CMakeLists now defines install command.
 * Catch's CMakeLists now generates projects with warnings enabled.
 
 
-## 1.6.x
+### 1.6.x
 
-### 1.6.1
+#### 1.6.1
 
-#### Features/ Changes:
+##### Features/ Changes:
 * Catch now supports breaking into debugger on Linux
 
-#### Fixes:
+##### Fixes:
 * Generators no longer leak memory (generators are still unsupported in general)
 * JUnit reporter now reports UTC timestamps, instead of "tbd"
 * `CHECK_THAT` macro is now properly defined as `CATCH_CHECK_THAT` when using `CATCH_` prefixed macros
 
-#### Other:
+##### Other:
 * Types with overloaded `&&` operator are no longer evaluated twice when used in an assertion macro.
 * The use of `__COUNTER__` is supressed when Catch is parsed by CLion
   * This change is not active when compiling a binary
@@ -455,28 +815,28 @@
   * This can be disabled if needed, see [documentation](configuration.md#top) for details.
 
 
-### 1.6.0
+#### 1.6.0
 
-#### Cmake/ projects:
+##### Cmake/ projects:
 * Moved CMakeLists.txt to root, made it friendlier for CLion and generating XCode and VS projects, and removed the manually maintained XCode and VS projects.
 
-#### Features/ Changes:
+##### Features/ Changes:
 * Approx now supports `>=` and `<=`
 * Can now use `\` to escape chars in test names on command line
 * Standardize C++11 feature toggles
 
-#### Fixes:
+##### Fixes:
 * Blue shell colour
 * Missing argument to `CATCH_CHECK_THROWS`
 * Don't encode extended ASCII in XML
 * use `std::shuffle` on more compilers (fixes deprecation warning/error)
 * Use `__COUNTER__` more consistently (where available)
 
-#### Other:
+##### Other:
 * Tweaks and changes to scripts - particularly for Approval test - to make them more portable
 
 
-# Even Older versions
+## Even Older versions
 Release notes were not maintained prior to v1.6.0, but you should be able to work them out from the Git history
 
 ---
diff --git a/docs/release-process.md b/docs/release-process.md
index 433777b..412cf2d 100644
--- a/docs/release-process.md
+++ b/docs/release-process.md
@@ -1,18 +1,18 @@
 <a id="top"></a>
 # How to release
 
-When enough changes have accumulated, it is time to release new version of Catch. This document describes the proces in doing so, that no steps are forgotten. Note that all referenced scripts can be found in the `scripts/` directory.
+When enough changes have accumulated, it is time to release new version of Catch. This document describes the process in doing so, that no steps are forgotten. Note that all referenced scripts can be found in the `scripts/` directory.
 
-## Neccessary steps
+## Necessary steps
 
-These steps are neccessary and have to be performed before each new release. They serve to make sure that the new release is correct and linked-to from the standard places.
+These steps are necessary and have to be performed before each new release. They serve to make sure that the new release is correct and linked-to from the standard places.
 
 
-### Approval testing
+### Testing
 
-Catch's releases are primarily validated against output from previous release, stored in `projects/SelfTest/Baselines`. To validate current sources, build the SelfTest binary and pass it to the `approvalTests.py` script: `approvalTests.py <path/to/SelfTest>`.
-
-There should be no differences, as Approval tests should be updated when changes to Catch are made, but if there are, then they need to be manually reviewed and either approved (using `approve.py`) or Catch requires other fixes.
+All of the tests are currently run in our CI setup based on TravisCI and
+AppVeyor. As long as the last commit tested green, the release can
+proceed.
 
 
 ### Incrementing version number
@@ -27,7 +27,7 @@
 
 ### Release notes
 
-Once a release is ready, release notes need to be written. They should summarize changes done since last release. For rough idea of expected notes see previous releases. Once written, release notes should be placed in `docs/release-notes.md`.
+Once a release is ready, release notes need to be written. They should summarize changes done since last release. For rough idea of expected notes see previous releases. Once written, release notes should be added to `docs/release-notes.md`.
 
 
 ### Commit and push update to GitHub
@@ -43,23 +43,30 @@
 Single header version of `catch.hpp` *needs* to be attached as a binary,
 as that is where the official download link links to. Preferably
 it should use linux line endings. All non-bundled reporters (Automake,
-TAP, TeamCity) should also be attached as binaries, as they are dependent
-on a specific version of the single-include header.
+TAP, TeamCity) should also be attached as binaries, as they might be
+dependent on a specific version of the single-include header.
 
+Since 2.5.0, the release tag and the "binaries" (headers) should be PGP
+signed.
 
-## Optional steps
+#### Signing a tag
 
-The following steps are optional, and do not have to be performed when releasing new version of Catch. However, they *should* happen, but they can happen the next day without losing anything significant.
+To create a signed tag, use `git tag -s <VERSION>`, where `<VERSION>`
+is the version being released, e.g. `git tag -s v2.6.0`.
 
+Use the version name as the short message and the release notes as
+the body (long) message.
 
-### vcpkg update
+#### Signing the headers
 
-Catch is maintaining its own port in Microsoft's package manager [vcpkg](https://github.com/Microsoft/vcpkg). This means that when new version of Catch is released, it should be posted there as well. `updateVcpkgPackage.py` can do a lot of neccessary work for you, it creates a branch and commits neccessary changes. You should review these changes, push and open a PR against vcpkg's upstream.
+This will create ASCII-armored signatures for the headers that are
+uploaded to the GitHub release:
 
-Note that the script assumes you have your fork of vcpkg checked out in a directory next to the directory where you have checked out Catch, like so:
 ```
-GitHub
-    Catch
-    vcpkg
+$ gpg2 --armor --output catch.hpp.asc --detach-sig catch.hpp
+$ gpg2 --armor --output catch_reporter_automake.hpp.asc --detach-sig catch_reporter_automake.hpp
+$ gpg2 --armor --output catch_reporter_teamcity.hpp.asc --detach-sig catch_reporter_teamcity.hpp
+$ gpg2 --armor --output catch_reporter_tap.hpp.asc --detach-sig catch_reporter_tap.hpp
 ```
 
+_GPG does not support signing multiple files in single invocation._
diff --git a/docs/reporters.md b/docs/reporters.md
index 78e78ee..32b3419 100644
--- a/docs/reporters.md
+++ b/docs/reporters.md
@@ -25,8 +25,8 @@
 There are a few additional reporters, for specific build systems, in the Catch repository (in `include\reporters`) which you can `#include` in your project if you would like to make use of them.
 Do this in one source file - the same one you have `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`.
 
-* `teamcity` writes the native, streaming, format that [TeamCity](https://www.jetbrains.com/teamcity/) understands.
-Use this when building as part of a TeamCity build to see results as they happen.
+* `teamcity` writes the native, streaming, format that [TeamCity](https://www.jetbrains.com/teamcity/) understands. 
+Use this when building as part of a TeamCity build to see results as they happen ([code example](../examples/207-Rpt-TeamCityReporter.cpp)).
 * `tap` writes in the TAP ([Test Anything Protocol](https://en.wikipedia.org/wiki/Test_Anything_Protocol)) format.
 * `automake` writes in a format that correspond to [automake  .trs](https://www.gnu.org/software/automake/manual/html_node/Log-files-generation-and-test-results-recording.html) files
 
diff --git a/docs/test-cases-and-sections.md b/docs/test-cases-and-sections.md
index 68944f5..62a805f 100644
--- a/docs/test-cases-and-sections.md
+++ b/docs/test-cases-and-sections.md
@@ -1,6 +1,12 @@
 <a id="top"></a>
 # Test cases and sections
 
+**Contents**<br>
+[Tags](#tags)<br>
+[Tag aliases](#tag-aliases)<br>
+[BDD-style test cases](#bdd-style-test-cases)<br>
+[Type parametrised test cases](#type-parametrised-test-cases)<br>
+
 While Catch fully supports the traditional, xUnit, style of class-based fixtures containing test case methods this is not the preferred style.
 
 Instead Catch provides a powerful mechanism for nesting test case sections within a test case. For a more detailed discussion see the [tutorial](tutorial.md#test-cases-and-sections).
@@ -20,10 +26,10 @@
 
 As an example - given the following test cases:
 
-	TEST_CASE( "A", "[widget]" ) { /* ... */ }
-	TEST_CASE( "B", "[widget]" ) { /* ... */ }
-	TEST_CASE( "C", "[gadget]" ) { /* ... */ }
-	TEST_CASE( "D", "[widget][gadget]" ) { /* ... */ }
+    TEST_CASE( "A", "[widget]" ) { /* ... */ }
+    TEST_CASE( "B", "[widget]" ) { /* ... */ }
+    TEST_CASE( "C", "[gadget]" ) { /* ... */ }
+    TEST_CASE( "D", "[widget][gadget]" ) { /* ... */ }
 
 The tag expression, ```"[widget]"``` selects A, B & D. ```"[gadget]"``` selects C & D. ```"[widget][gadget]"``` selects just D and ```"[widget],[gadget]"``` selects all four test cases.
 
@@ -37,7 +43,7 @@
 
 * `[!hide]` or `[.]` - causes test cases to be skipped from the default list (i.e. when no test cases have been explicitly selected through tag expressions or name wildcards). The hide tag is often combined with another, user, tag (for example `[.][integration]` - so all integration tests are excluded from the default run but can be run by passing `[integration]` on the command line). As a short-cut you can combine these by simply prefixing your user tag with a `.` - e.g. `[.integration]`. Because the hide tag has evolved to have several forms, all forms are added as tags if you use one of them.
 
-* `[!throws]`	- lets Catch know that this test is likely to throw an exception even if successful. This causes the test to be excluded when running with `-e` or `--nothrow`.
+* `[!throws]` - lets Catch know that this test is likely to throw an exception even if successful. This causes the test to be excluded when running with `-e` or `--nothrow`.
 
 * `[!mayfail]` - doesn't fail the test if any given assertion fails (but still reports it). This can be useful to flag a work-in-progress, or a known issue that you don't want to immediately fix but still want to track in your tests.
 
@@ -55,11 +61,11 @@
 
 Between tag expressions and wildcarded test names (as well as combinations of the two) quite complex patterns can be constructed to direct which test cases are run. If a complex pattern is used often it is convenient to be able to create an alias for the expression. This can be done, in code, using the following form:
 
-	CATCH_REGISTER_TAG_ALIAS( <alias string>, <tag expression> )
+    CATCH_REGISTER_TAG_ALIAS( <alias string>, <tag expression> )
 
 Aliases must begin with the `@` character. An example of a tag alias is:
 
-	CATCH_REGISTER_TAG_ALIAS( "[@nhf]", "[failing]~[.]" )
+    CATCH_REGISTER_TAG_ALIAS( "[@nhf]", "[failing]~[.]" )
 
 Now when `[@nhf]` is used on the command line this matches all tests that are tagged `[failing]`, but which are not also hidden.
 
@@ -86,6 +92,105 @@
 
 Other than the additional prefixes and the formatting in the console reporter these macros behave exactly as ```TEST_CASE```s and ```SECTION```s. As such there is nothing enforcing the correct sequencing of these macros - that's up to the programmer!
 
+## Type parametrised test cases
+
+In addition to `TEST_CASE`s, Catch2 also supports test cases parametrised
+by types, in the form of `TEMPLATE_TEST_CASE` and
+`TEMPLATE_PRODUCT_TEST_CASE`.
+
+* **TEMPLATE_TEST_CASE(** _test name_ , _tags_,  _type1_, _type2_, ..., _typen_ **)**
+
+_test name_ and _tag_ are exactly the same as they are in `TEST_CASE`,
+with the difference that the tag string must be provided (however, it
+can be empty). _type1_ through _typen_ is the list of types for which
+this test case should run, and, inside the test code, the current type
+is available as the `TestType` type.
+
+Because of limitations of the C++ preprocessor, if you want to specify
+a type with multiple template parameters, you need to enclose it in
+parentheses, e.g. `std::map<int, std::string>` needs to be passed as
+`(std::map<int, std::string>)`.
+
+Example:
+```cpp
+TEMPLATE_TEST_CASE( "vectors can be sized and resized", "[vector][template]", int, std::string, (std::tuple<int,float>) ) {
+
+    std::vector<TestType> v( 5 );
+
+    REQUIRE( v.size() == 5 );
+    REQUIRE( v.capacity() >= 5 );
+
+    SECTION( "resizing bigger changes size and capacity" ) {
+        v.resize( 10 );
+
+        REQUIRE( v.size() == 10 );
+        REQUIRE( v.capacity() >= 10 );
+    }
+    SECTION( "resizing smaller changes size but not capacity" ) {
+        v.resize( 0 );
+
+        REQUIRE( v.size() == 0 );
+        REQUIRE( v.capacity() >= 5 );
+
+        SECTION( "We can use the 'swap trick' to reset the capacity" ) {
+            std::vector<TestType> empty;
+            empty.swap( v );
+
+            REQUIRE( v.capacity() == 0 );
+        }
+    }
+    SECTION( "reserving smaller does not change size or capacity" ) {
+        v.reserve( 0 );
+
+        REQUIRE( v.size() == 5 );
+        REQUIRE( v.capacity() >= 5 );
+    }
+}
+```
+
+* **TEMPLATE_PRODUCT_TEST_CASE(** _test name_ , _tags_, (_template-type1_, _template-type2_, ..., _template-typen_), (_template-arg1_, _template-arg2_, ..., _template-argm_) **)**
+
+_template-type1_ through _template-typen_ is list of template template
+types which should be combined with each of _template-arg1_ through
+ _template-argm_, resulting in _n * m_ test cases. Inside the test case,
+the resulting type is available under the name of `TestType`.
+
+To specify more than 1 type as a single _template-type_ or _template-arg_,
+you must enclose the types in an additional set of parentheses, e.g.
+`((int, float), (char, double))` specifies 2 template-args, each
+consisting of 2 concrete types (`int`, `float` and `char`, `double`
+respectively). You can also omit the outer set of parentheses if you
+specify only one type as the full set of either the _template-types_,
+or the _template-args_.
+
+
+Example:
+```cpp
+template< typename T>
+struct Foo {
+    size_t size() {
+        return 0;
+    }
+};
+
+TEMPLATE_PRODUCT_TEST_CASE("A Template product test case", "[template][product]", (std::vector, Foo), (int, float)) {
+    TestType x;
+    REQUIRE(x.size() == 0);
+}
+```
+
+You can also have different arities in the _template-arg_ packs:
+```cpp
+TEMPLATE_PRODUCT_TEST_CASE("Product with differing arities", "[template][product]", std::tuple, (int, (int, double), (int, double, float))) {
+    TestType x;
+    REQUIRE(std::tuple_size<TestType>::value >= 1);
+}
+```
+
+_While there is an upper limit on the number of types you can specify
+in single `TEMPLATE_TEST_CASE` or `TEMPLATE_PRODUCT_TEST_CASE`, the limit
+is very high and should not be encountered in practice._
+
 ---
 
 [Home](Readme.md#top)
diff --git a/docs/test-fixtures.md b/docs/test-fixtures.md
index 1dc7bab..6b29ce6 100644
--- a/docs/test-fixtures.md
+++ b/docs/test-fixtures.md
@@ -30,6 +30,60 @@
 
 The two test cases here will create uniquely-named derived classes of UniqueTestsFixture and thus can access the `getID()` protected method and `conn` member variables. This ensures that both the test cases are able to create a DBConnection using the same method (DRY principle) and that any ID's created are unique such that the order that tests are executed does not matter.
 
+
+Catch2 also provides `TEMPLATE_TEST_CASE_METHOD` and
+`TEMPLATE_PRODUCT_TEST_CASE_METHOD` that can be used together
+with templated fixtures and templated template fixtures to perform
+tests for multiple different types. Unlike `TEST_CASE_METHOD`,
+`TEMPLATE_TEST_CASE_METHOD` and `TEMPLATE_PRODUCT_TEST_CASE_METHOD` do
+require the tag specification to be non-empty, as it is followed by
+further macro arguments.
+
+Also note that, because of limitations of the C++ preprocessor, if you
+want to specify a type with multiple template parameters, you need to
+enclose it in parentheses, e.g. `std::map<int, std::string>` needs to be
+passed as `(std::map<int, std::string>)`.
+In the case of `TEMPLATE_PRODUCT_TEST_CASE_METHOD`, if a member of the
+type list should consist of more than single type, it needs to be enclosed
+in another pair of parentheses, e.g. `(std::map, std::pair)` and
+`((int, float), (char, double))`.
+
+Example:
+```cpp
+template< typename T >
+struct Template_Fixture {
+    Template_Fixture(): m_a(1) {}
+
+    T m_a;
+};
+
+TEMPLATE_TEST_CASE_METHOD(Template_Fixture,"A TEMPLATE_TEST_CASE_METHOD based test run that succeeds", "[class][template]", int, float, double) {
+    REQUIRE( Template_Fixture<TestType>::m_a == 1 );
+}
+
+template<typename T>
+struct Template_Template_Fixture {
+    Template_Template_Fixture() {}
+
+    T m_a;
+};
+
+template<typename T>
+struct Foo_class {
+    size_t size() {
+        return 0;
+    }
+};
+
+TEMPLATE_PRODUCT_TEST_CASE_METHOD(Template_Template_Fixture, "A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test succeeds", "[class][template]", (Foo_class, std::vector), int) {
+    REQUIRE( Template_Template_Fixture<TestType>::m_a.size() == 0 );
+}
+```
+
+_While there is an upper limit on the number of types you can specify
+in single `TEMPLATE_TEST_CASE_METHOD` or `TEMPLATE_PRODUCT_TEST_CASE_METHOD`,
+the limit is very high and should not be encountered in practice._
+
 ---
 
 [Home](Readme.md#top)
diff --git a/docs/tostring.md b/docs/tostring.md
index 568c1c2..933f2e6 100644
--- a/docs/tostring.md
+++ b/docs/tostring.md
@@ -1,6 +1,12 @@
 <a id="top"></a>
 # String conversions
 
+**Contents**<br>
+[operator << overload for std::ostream](#operator--overload-for-stdostream)<br>
+[Catch::StringMaker specialisation](#catchstringmaker-specialisation)<br>
+[Catch::is_range specialisation](#catchis_range-specialisation)<br>
+[Exceptions](#exceptions)<br>
+
 Catch needs to be able to convert types you use in assertions and logging expressions into strings (for logging and reporting purposes).
 Most built-in or std types are supported out of the box but there are two ways that you can tell Catch how to convert your own types (or other, third-party types) into strings.
 
@@ -10,30 +16,30 @@
 
 ```
 std::ostream& operator << ( std::ostream& os, T const& value ) {
-	os << convertMyTypeToString( value );
-	return os;
+    os << convertMyTypeToString( value );
+    return os;
 }
 ```
 
 (where ```T``` is your type and ```convertMyTypeToString``` is where you'll write whatever code is necessary to make your type printable - it doesn't have to be in another function).
 
-You should put this function in the same namespace as your type and have it declared before including Catch's header.
+You should put this function in the same namespace as your type, or the global namespace, and have it declared before including Catch's header.
 
-## Catch::StringMaker<T> specialisation
+## Catch::StringMaker specialisation
 If you don't want to provide an ```operator <<``` overload, or you want to convert your type differently for testing purposes, you can provide a specialization for `Catch::StringMaker<T>`:
 
 ```
 namespace Catch {
-	template<>
+    template<>
     struct StringMaker<T> {
-    	static std::string convert( T const& value ) {
-        	return convertMyTypeToString( value );
+        static std::string convert( T const& value ) {
+            return convertMyTypeToString( value );
         }
     };
 }
 ```
 
-## Catch::is_range<T> specialisation
+## Catch::is_range specialisation
 As a fallback, Catch attempts to detect if the type can be iterated
 (`begin(T)` and `end(T)` are valid) and if it can be, it is stringified
 as a range. For certain types this can lead to infinite recursion, so
@@ -56,7 +62,7 @@
 
 ```
 CATCH_TRANSLATE_EXCEPTION( MyType& ex ) {
-	return ex.message();
+    return ex.message();
 }
 ```
 
diff --git a/docs/tutorial.md b/docs/tutorial.md
index d55355c..7c0f814 100644
--- a/docs/tutorial.md
+++ b/docs/tutorial.md
@@ -8,24 +8,31 @@
 [Test cases and sections](#test-cases-and-sections)<br>
 [BDD-Style](#bdd-style)<br>
 [Scaling up](#scaling-up)<br>
+[Type parametrised test cases](#type-parametrised-test-cases)<br>
 [Next steps](#next-steps)<br>
 
 ## Getting Catch2
 
-The simplest way to get Catch2 is to download the latest [single header version](https://raw.githubusercontent.com/CatchOrg/Catch2/master/single_include/catch.hpp). The single header is generated by merging a set of individual headers but it is still just normal source code in a header file.
+The simplest way to get Catch2 is to download the latest [single header version](https://raw.githubusercontent.com/catchorg/Catch2/master/single_include/catch2/catch.hpp). The single header is generated by merging a set of individual headers but it is still just normal source code in a header file.
+
+Alternative ways of getting Catch2 include using your system package
+manager, or installing it using [its CMake package](cmake-integration.md#installing-catch2-from-git-repository).
 
 The full source for Catch2, including test projects, documentation, and other things, is hosted on GitHub. [http://catch-lib.net](http://catch-lib.net) will redirect you there.
 
 
 ## Where to put it?
 
-Catch2 is header only. All you need to do is drop the file somewhere reachable from your project - either in some central location you can set your header search path to find, or directly into your project tree itself! This is a particularly good option for other Open-Source projects that want to use Catch for their test suite. See [this blog entry for more on that](http://www.levelofindirection.com/journal/2011/5/27/unit-testing-in-c-and-objective-c-just-got-ridiculously-easi.html). 
+Catch2 is header only. All you need to do is drop the file somewhere reachable from your project - either in some central location you can set your header search path to find, or directly into your project tree itself! This is a particularly good option for other Open-Source projects that want to use Catch for their test suite. See [this blog entry for more on that](http://www.levelofindirection.com/journal/2011/5/27/unit-testing-in-c-and-objective-c-just-got-ridiculously-easi.html).
 
 The rest of this tutorial will assume that the Catch2 single-include header (or the include folder) is available unqualified - but you may need to prefix it with a folder name if necessary.
 
+_If you have installed Catch2 from system package manager, or CMake
+package, you need to include the header as `#include <catch2/catch.hpp>`_
+
 ## Writing tests
 
-Let's start with a really simple example ([code](../examples/010-TestCase.cpp)). Say you have written a function to calculate factorials and now you want to test it (let's leave aside TDD for now). 
+Let's start with a really simple example ([code](../examples/010-TestCase.cpp)). Say you have written a function to calculate factorials and now you want to test it (let's leave aside TDD for now).
 
 ```c++
 unsigned int Factorial( unsigned int number ) {
@@ -116,31 +123,31 @@
 TEST_CASE( "vectors can be sized and resized", "[vector]" ) {
 
     std::vector<int> v( 5 );
-    
+
     REQUIRE( v.size() == 5 );
     REQUIRE( v.capacity() >= 5 );
-    
+
     SECTION( "resizing bigger changes size and capacity" ) {
         v.resize( 10 );
-        
+
         REQUIRE( v.size() == 10 );
         REQUIRE( v.capacity() >= 10 );
     }
     SECTION( "resizing smaller changes size but not capacity" ) {
         v.resize( 0 );
-        
+
         REQUIRE( v.size() == 0 );
         REQUIRE( v.capacity() >= 5 );
     }
     SECTION( "reserving bigger changes capacity but not size" ) {
         v.reserve( 10 );
-        
+
         REQUIRE( v.size() == 5 );
         REQUIRE( v.capacity() >= 10 );
     }
     SECTION( "reserving smaller does not change size or capacity" ) {
         v.reserve( 0 );
-        
+
         REQUIRE( v.size() == 5 );
         REQUIRE( v.capacity() >= 5 );
     }
@@ -157,13 +164,13 @@
 ```c++
     SECTION( "reserving bigger changes capacity but not size" ) {
         v.reserve( 10 );
-        
+
         REQUIRE( v.size() == 5 );
         REQUIRE( v.capacity() >= 10 );
-    
+
         SECTION( "reserving smaller again does not change capacity" ) {
             v.reserve( 7 );
-            
+
             REQUIRE( v.capacity() >= 10 );
         }
     }
@@ -182,13 +189,13 @@
 
     GIVEN( "A vector with some items" ) {
         std::vector<int> v( 5 );
-        
+
         REQUIRE( v.size() == 5 );
         REQUIRE( v.capacity() >= 5 );
-        
+
         WHEN( "the size is increased" ) {
             v.resize( 10 );
-            
+
             THEN( "the size and capacity change" ) {
                 REQUIRE( v.size() == 10 );
                 REQUIRE( v.capacity() >= 10 );
@@ -196,7 +203,7 @@
         }
         WHEN( "the size is reduced" ) {
             v.resize( 0 );
-            
+
             THEN( "the size changes but not capacity" ) {
                 REQUIRE( v.size() == 0 );
                 REQUIRE( v.capacity() >= 5 );
@@ -204,7 +211,7 @@
         }
         WHEN( "more capacity is reserved" ) {
             v.reserve( 10 );
-            
+
             THEN( "the capacity changes but not the size" ) {
                 REQUIRE( v.size() == 5 );
                 REQUIRE( v.capacity() >= 10 );
@@ -212,7 +219,7 @@
         }
         WHEN( "less capacity is reserved" ) {
             v.reserve( 0 );
-            
+
             THEN( "neither size nor capacity are changed" ) {
                 REQUIRE( v.size() == 5 );
                 REQUIRE( v.capacity() >= 5 );
@@ -250,6 +257,17 @@
 Do not write your tests in header files!
 
 
+## Type parametrised test cases
+
+Test cases in Catch2 can be also parametrised by type, via the
+`TEMPLATE_TEST_CASE` and `TEMPLATE_PRODUCT_TEST_CASE` macros,
+which behave in the same way the `TEST_CASE` macro, but are run for
+every type or type combination.
+
+For more details, see our documentation on [test cases and
+sections](test-cases-and-sections.md#type-parametrised-test-cases).
+
+
 ## Next steps
 
 This has been a brief introduction to get you up and running with Catch, and to point out some of the key differences between Catch and other frameworks you may already be familiar with. This will get you going quite far already and you are now in a position to dive in and write some tests.
diff --git a/docs/why-catch.md b/docs/why-catch.md
index 45f58a6..86cc55b 100644
--- a/docs/why-catch.md
+++ b/docs/why-catch.md
@@ -6,7 +6,7 @@
 [Google Test](http://code.google.com/p/googletest/),
 [Boost.Test](http://www.boost.org/doc/libs/1_49_0/libs/test/doc/html/index.html),
 [CppUnit](http://sourceforge.net/apps/mediawiki/cppunit/index.php?title=Main_Page),
-[Cute](http://r2.ifs.hsr.ch/cute),
+[Cute](http://www.cute-test.com),
 [many, many more](http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C.2B.2B).
 
 So what does Catch bring to the party that differentiates it from these? Apart from a Catchy name, of course.
diff --git a/examples/000-CatchMain.cpp b/examples/000-CatchMain.cpp
index c8bf91e..2894d42 100644
--- a/examples/000-CatchMain.cpp
+++ b/examples/000-CatchMain.cpp
@@ -6,7 +6,7 @@
 // Let Catch provide main():
 #define CATCH_CONFIG_MAIN
 
-#include "catch.hpp"
+#include <catch2/catch.hpp>
 
 // That's it
 
diff --git a/examples/010-TestCase.cpp b/examples/010-TestCase.cpp
index 16a212a..c00b8a8 100644
--- a/examples/010-TestCase.cpp
+++ b/examples/010-TestCase.cpp
@@ -3,7 +3,7 @@
 // Let Catch provide main():
 #define CATCH_CONFIG_MAIN
 
-#include "catch.hpp"
+#include <catch2/catch.hpp>
 
 int Factorial( int number ) {
    return number <= 1 ? number : Factorial( number - 1 ) * number;  // fail
diff --git a/examples/020-TestCase-1.cpp b/examples/020-TestCase-1.cpp
index 0d10276..ab0249e 100644
--- a/examples/020-TestCase-1.cpp
+++ b/examples/020-TestCase-1.cpp
@@ -6,7 +6,7 @@
 // Let Catch provide main():
 #define CATCH_CONFIG_MAIN
 
-#include "catch.hpp"
+#include <catch2/catch.hpp>
 
 TEST_CASE( "1: All test cases reside in other .cpp files (empty)", "[multi-file:1]" ) {
 }
diff --git a/examples/020-TestCase-2.cpp b/examples/020-TestCase-2.cpp
index 2cca362..08b313e 100644
--- a/examples/020-TestCase-2.cpp
+++ b/examples/020-TestCase-2.cpp
@@ -2,7 +2,7 @@
 
 // main() provided by Catch in file 020-TestCase-1.cpp.
 
-#include "catch.hpp"
+#include <catch2/catch.hpp>
 
 int Factorial( int number ) {
    return number <= 1 ? number : Factorial( number - 1 ) * number;  // fail
diff --git a/examples/030-Asn-Require-Check.cpp b/examples/030-Asn-Require-Check.cpp
index 35f2ff7..f814a1b 100644
--- a/examples/030-Asn-Require-Check.cpp
+++ b/examples/030-Asn-Require-Check.cpp
@@ -10,7 +10,7 @@
 
 // main() provided in 000-CatchMain.cpp
 
-#include "catch.hpp"
+#include <catch2/catch.hpp>
 
 std::string one() {
     return "1";
diff --git a/examples/100-Fix-Section.cpp b/examples/100-Fix-Section.cpp
index 8cb94bf..d0b9f2d 100644
--- a/examples/100-Fix-Section.cpp
+++ b/examples/100-Fix-Section.cpp
@@ -6,7 +6,7 @@
 
 // main() provided in 000-CatchMain.cpp
 
-#include "catch.hpp"
+#include <catch2/catch.hpp>
 
 TEST_CASE( "vectors can be sized and resized", "[vector]" ) {
 
diff --git a/examples/110-Fix-ClassFixture.cpp b/examples/110-Fix-ClassFixture.cpp
index 06c2cf3..e42fd17 100644
--- a/examples/110-Fix-ClassFixture.cpp
+++ b/examples/110-Fix-ClassFixture.cpp
@@ -6,7 +6,7 @@
 
 // main() provided in 000-CatchMain.cpp
 
-#include "catch.hpp"
+#include <catch2/catch.hpp>
 
 class DBConnection
 {
diff --git a/examples/120-Bdd-ScenarioGivenWhenThen.cpp b/examples/120-Bdd-ScenarioGivenWhenThen.cpp
index c45f1f2..d1b9ce5 100644
--- a/examples/120-Bdd-ScenarioGivenWhenThen.cpp
+++ b/examples/120-Bdd-ScenarioGivenWhenThen.cpp
@@ -2,7 +2,7 @@
 
 // main() provided in 000-CatchMain.cpp
 
-#include "catch.hpp"
+#include <catch2/catch.hpp>
 
 SCENARIO( "vectors can be sized and resized", "[vector]" ) {
 
diff --git a/examples/200-Rpt-CatchMain.cpp b/examples/200-Rpt-CatchMain.cpp
new file mode 100644
index 0000000..b84c804
--- /dev/null
+++ b/examples/200-Rpt-CatchMain.cpp
@@ -0,0 +1,27 @@
+// 200-Rpt-CatchMain.cpp
+
+// In a Catch project with multiple files, dedicate one file to compile the
+// source code of Catch itself and reuse the resulting object file for linking.
+
+// Let Catch provide main():
+#define CATCH_CONFIG_MAIN
+
+#include <catch2/catch.hpp>
+
+#ifdef   CATCH_EXAMPLE_RPT_1
+#include CATCH_EXAMPLE_RPT_1
+#endif
+
+#ifdef   CATCH_EXAMPLE_RPT_2
+#include CATCH_EXAMPLE_RPT_2
+#endif
+
+#ifdef   CATCH_EXAMPLE_RPT_3
+#include CATCH_EXAMPLE_RPT_3
+#endif
+
+// That's it
+
+// Compile implementation of Catch for use with files that do contain tests:
+// - g++ -std=c++11 -Wall -I$(CATCH_ROOT) -DCATCH_EXAMPLE_RPT_1=\"include/reporters/catch_reporter_teamcity.hpp\" -o 200-Rpt-CatchMainTeamCity.o -c 200-Rpt-CatchMain.cpp
+// cl -EHsc -I%CATCH_ROOT% -DCATCH_EXAMPLE_RPT_1=\"include/reporters/catch_reporter_teamcity.hpp\" -Fo200-Rpt-CatchMainTeamCity.obj -c 200-Rpt-CatchMain.cpp
diff --git a/examples/207-Rpt-TeamCityReporter.cpp b/examples/207-Rpt-TeamCityReporter.cpp
new file mode 100644
index 0000000..d28460f
--- /dev/null
+++ b/examples/207-Rpt-TeamCityReporter.cpp
@@ -0,0 +1,171 @@
+// 207-Rpt-TeamCityReporter.cpp
+
+// Catch has built-in and external reporters:
+// Built-in:
+// - compact
+// - console
+// - junit
+// - xml
+// External:
+// - automake
+// - tap
+// - teamcity (this example)
+
+// main() and reporter code provided in 200-Rpt-CatchMain.cpp
+
+#include <catch2/catch.hpp>
+
+#ifdef _MSC_VER
+# pragma warning (disable : 4702) // Disable warning: unreachable code
+#endif
+
+TEST_CASE( "TeamCity passes unconditionally succeeding assertion", "[teamcity]" ) {
+
+    SUCCEED();
+}
+
+TEST_CASE( "TeamCity reports unconditionally failing assertion", "[teamcity]" ) {
+
+    FAIL();
+}
+
+TEST_CASE( "TeamCity reports failing check", "[teamcity]" ) {
+
+    REQUIRE( 3 == 7 );
+}
+
+TEST_CASE( "TeamCity reports failing check-false", "[teamcity]" ) {
+
+    REQUIRE_FALSE( 3 == 3 );
+}
+
+TEST_CASE( "TeamCity reports failing check-that", "[teamcity]" ) {
+
+    using namespace Catch;
+
+    REQUIRE_THAT( "hello", Contains( "world" ) );
+}
+
+TEST_CASE( "TeamCity reports unexpected exception", "[teamcity]" ) {
+
+    REQUIRE( (throw std::runtime_error("surprise!"), true) );
+}
+
+TEST_CASE( "TeamCity reports undesired exception", "[teamcity]" ) {
+
+    REQUIRE_NOTHROW( (throw std::runtime_error("surprise!"), true) );
+}
+
+TEST_CASE( "TeamCity reports missing expected exception", "[teamcity]" ) {
+
+    REQUIRE_THROWS( true );
+}
+
+TEST_CASE( "TeamCity reports missing specific expected exception", "[teamcity]" ) {
+
+    REQUIRE_THROWS_AS( throw std::bad_alloc(), std::runtime_error );
+}
+
+TEST_CASE( "TeamCity reports unexpected message in expected exception", "[teamcity]" ) {
+
+    using namespace Catch;
+
+    CHECK_THROWS_WITH( throw std::runtime_error("hello"), "world" );
+    CHECK_THROWS_WITH( throw std::runtime_error("hello"), Contains("world") );
+}
+
+struct MyException: public std::runtime_error
+{
+    MyException( char const * text )
+    : std::runtime_error( text ) {}
+    
+    ~MyException() override;
+};
+
+// prevent -Wweak-vtables:
+MyException::~MyException() = default;
+
+struct MyExceptionMatcher : Catch::MatcherBase< std::runtime_error >
+{
+    std::string m_text;
+
+    MyExceptionMatcher( char const * text )
+    : m_text( text )
+    {}
+
+    ~MyExceptionMatcher() override;
+    
+    bool match( std::runtime_error const & arg ) const override
+    { 
+        return m_text == arg.what() ; 
+    }
+    
+    std::string describe() const override 
+    { 
+        return "it's me";
+    }
+};
+
+// prevent -Wweak-vtables:
+MyExceptionMatcher::~MyExceptionMatcher() = default;
+
+TEST_CASE( "TeamCity failing check-throws-matches", "[teamcity]" ) {
+
+    CHECK_THROWS_MATCHES( throw MyException("hello"), MyException, MyExceptionMatcher("world") );
+}
+
+// [!throws] - lets Catch know that this test is likely to throw an exception even if successful. 
+// This causes the test to be excluded when running with -e or --nothrow.
+
+// No special effects for the reporter.
+
+TEST_CASE( "TeamCity throwing exception with tag [!throws]", "[teamcity][!throws]" ) {
+
+    REQUIRE_THROWS( throw std::runtime_error("unsurprisingly") );
+}
+
+// [!mayfail] - doesn't fail the test if any given assertion fails (but still reports it). This can be useful to flag a work-in-progress, or a known issue that you don't want to immediately fix but still want to track in your tests.
+
+TEST_CASE( "TeamCity failing assertion with tag [!mayfail]", "[teamcity][!mayfail] " ) {
+
+    REQUIRE( 3 == 7 );  // doesn't fail test case this time, reports: testIgnored
+    REQUIRE( 3 == 3 );
+}
+
+// [!shouldfail] - like [!mayfail] but fails the test if it passes. 
+// This can be useful if you want to be notified of accidental, or third-party, fixes.
+
+TEST_CASE( "TeamCity succeeding assertion with tag [!shouldfail]", "[teamcity][!shouldfail]" ) {
+
+    SUCCEED( "Marked [!shouldfail]" );
+}
+
+// Compile & run:
+// - g++ -std=c++11 -Wall -I$(CATCH_ROOT) -DCATCH_EXAMPLE_RPT_1=\"include/reporters/catch_reporter_teamcity.hpp\" -o 200-Rpt-CatchMainTeamCity.o -c 200-Rpt-CatchMain.cpp
+// - g++ -std=c++11 -Wall -I$(CATCH_ROOT) -o 207-Rpt-TeamCityReporter 207-Rpt-TeamCityReporter.cpp 200-Rpt-CatchMainTeamCity.o && 207-Rpt-TeamCityReporter --list-reporters
+//
+// - cl -EHsc -I%CATCH_ROOT% -DCATCH_EXAMPLE_RPT_1=\"include/reporters/catch_reporter_teamcity.hpp\" -Fo200-Rpt-CatchMainTeamCity.obj -c 200-Rpt-CatchMain.cpp
+// - cl -EHsc -I%CATCH_ROOT% 207-Rpt-TeamCityReporter.cpp 200-Rpt-CatchMainTeamCity.o && 207-Rpt-TeamCityReporter --list-reporters
+
+// Compilation output (--list-reporters):
+// Available reporters:
+//   compact:   Reports test results on a single line, suitable for IDEs
+//   console:   Reports test results as plain lines of text
+//   junit:     Reports test results in an XML format that looks like Ant's
+//                junitreport target
+//   teamcity:  Reports test results as TeamCity service messages
+//   xml:       Reports test results as an XML document
+
+// Expected output (abbreviated and broken into shorter lines):
+//
+// prompt> 207-Rpt-TeamCityReporter.exe --reporter teamcity
+// ##teamcity[testSuiteStarted name='207-Rpt-TeamCityReporter.exe']
+// ##teamcity[testStarted name='TeamCity passes unconditionally succeeding assertion']
+// ##teamcity[testFinished name='TeamCity passes unconditionally succeeding assertion' duration='1']
+// ##teamcity[testStarted name='TeamCity reports unconditionally failing assertion']
+// ##teamcity[testFailed name='TeamCity reports unconditionally failing assertion' /
+// message='.../examples/207-Rpt-TeamCityReporter.cpp:23|n/
+// ...............................................................................|n|n/
+// .../examples/207-Rpt-TeamCityReporter.cpp:25|nexplicit failure']
+// ##teamcity[testFinished name='TeamCity reports unconditionally failing assertion' duration='3']
+// ...
diff --git a/examples/210-Evt-EventListeners.cpp b/examples/210-Evt-EventListeners.cpp
index 8ba360f..fde51c7 100644
--- a/examples/210-Evt-EventListeners.cpp
+++ b/examples/210-Evt-EventListeners.cpp
@@ -10,7 +10,7 @@
 // Let Catch provide the required interfaces:
 #define CATCH_CONFIG_EXTERNAL_INTERFACES
 
-#include "catch.hpp"
+#include <catch2/catch.hpp>
 #include <iostream>
 
 // -----------------------------------------------------------------------
@@ -187,8 +187,7 @@
 
 void print( std::ostream& os, int const level, std::string const& title, Catch::SectionInfo const& info ) {
     os << ws(level  ) << title << ":\n"
-       << ws(level+1) << "- name: "         << info.name << "\n"
-       << ws(level+1) << "- description: '" << info.description << "'\n";
+       << ws(level+1) << "- name: "         << info.name << "\n";
     print( os, level+1 , "- lineInfo", info.lineInfo );
 }
 
@@ -388,16 +387,16 @@
     REQUIRE( i == 42 );
 
     SECTION("Section 1") {
-        INFO("Section 1")
+        INFO("Section 1");
         i = 7;
         SECTION("Section 1.1") {
-            INFO("Section 1.1")
+            INFO("Section 1.1");
             REQUIRE( i == 42 );
         }
     }
 
     SECTION("Section 2") {
-        INFO("Section 2")
+        INFO("Section 2");
         REQUIRE( i == 42 );
     }
     WARN("At end of test case");
diff --git a/examples/231-Cfg-OutputStreams.cpp b/examples/231-Cfg-OutputStreams.cpp
new file mode 100644
index 0000000..efa9997
--- /dev/null
+++ b/examples/231-Cfg-OutputStreams.cpp
@@ -0,0 +1,49 @@
+// 231-Cfg-OutputStreams.cpp
+// Show how to replace the streams with a simple custom made streambuf.
+
+// Note that this reimplementation _does not_ follow `std::cerr`
+// semantic, because it buffers the output. For most uses however,
+// there is no important difference between having `std::cerr` buffered
+// or unbuffered.
+
+#define CATCH_CONFIG_NOSTDOUT
+#define CATCH_CONFIG_MAIN
+#include <catch2/catch.hpp>
+
+class out_buff : public std::stringbuf {
+    std::FILE* m_stream;
+public:
+    out_buff(std::FILE* stream) :m_stream(stream) {}
+    ~out_buff() { pubsync(); }
+    int sync() {
+        int ret = 0;
+        for (unsigned char c : str()) {
+            if (putc(c, m_stream) == EOF) {
+                ret = -1;
+                break;
+            }
+        }
+        // Reset the buffer to avoid printing it multiple times
+        str("");
+        return ret;
+    }
+};
+
+namespace Catch {
+    std::ostream& cout() {
+        static std::ostream ret(new out_buff(stdout));
+        return ret;
+    }
+    std::ostream& clog() {
+        static std::ostream ret(new out_buff(stderr));
+        return ret;
+    }
+    std::ostream& cerr() {
+        return clog();
+    }
+}
+
+
+TEST_CASE("This binary uses putc to write out output", "[compilation-only]") {
+    SUCCEED("Nothing to test.");
+}
diff --git a/examples/300-Gen-OwnGenerator.cpp b/examples/300-Gen-OwnGenerator.cpp
new file mode 100644
index 0000000..c8b6a65
--- /dev/null
+++ b/examples/300-Gen-OwnGenerator.cpp
@@ -0,0 +1,59 @@
+// 300-Gen-OwnGenerator.cpp
+// Shows how to define a custom generator.
+
+// Specifically we will implement a random number generator for integers
+// It will have infinite capacity and settable lower/upper bound
+
+#include <catch2/catch.hpp>
+
+#include <random>
+
+// This class shows how to implement a simple generator for Catch tests
+class RandomIntGenerator : public Catch::Generators::IGenerator<int> {
+    std::minstd_rand m_rand;
+    std::uniform_int_distribution<> m_dist;
+    int current_number;
+public:
+
+    RandomIntGenerator(int low, int high):
+        m_rand(std::random_device{}()),
+        m_dist(low, high)
+    {
+        static_cast<void>(next());
+    }
+
+    int const& get() const override;
+    bool next() override {
+        current_number = m_dist(m_rand);
+        return true;
+    }
+};
+
+// Avoids -Wweak-vtables
+int const& RandomIntGenerator::get() const {
+    return current_number;
+}
+
+// This helper function provides a nicer UX when instantiating the generator
+// Notice that it returns an instance of GeneratorWrapper<int>, which
+// is a value-wrapper around std::unique_ptr<IGenerator<int>>.
+Catch::Generators::GeneratorWrapper<int> random(int low, int high) {
+    return Catch::Generators::GeneratorWrapper<int>(std::unique_ptr<Catch::Generators::IGenerator<int>>(new RandomIntGenerator(low, high)));
+}
+
+// The two sections in this test case are equivalent, but the first one
+// is much more readable/nicer to use
+TEST_CASE("Generating random ints", "[example][generator]") {
+    SECTION("Nice UX") {
+        auto i = GENERATE(take(100, random(-100, 100)));
+        REQUIRE(i >= -100);
+        REQUIRE(i <= 100);
+    }
+    SECTION("Creating the random generator directly") {
+        auto i = GENERATE(take(100, GeneratorWrapper<int>(std::unique_ptr<IGenerator<int>>(new RandomIntGenerator(-100, 100)))));
+        REQUIRE(i >= -100);
+        REQUIRE(i <= 100);
+    }
+}
+
+// Compiling and running this file will result in 400 successful assertions
diff --git a/examples/301-Gen-MapTypeConversion.cpp b/examples/301-Gen-MapTypeConversion.cpp
new file mode 100644
index 0000000..b6377e9
--- /dev/null
+++ b/examples/301-Gen-MapTypeConversion.cpp
@@ -0,0 +1,54 @@
+// 301-Gen-MapTypeConversion.cpp
+// Shows how to use map to modify generator's return type.
+
+// TODO
+
+#include <catch2/catch.hpp>
+
+#include <string>
+#include <sstream>
+
+// Returns a line from a stream. You could have it e.g. read lines from
+// a file, but to avoid problems with paths in examples, we will use
+// a fixed stringstream.
+class LineGenerator : public Catch::Generators::IGenerator<std::string> {
+    std::string m_line;
+    std::stringstream m_stream;
+public:
+    LineGenerator() {
+        m_stream.str("1\n2\n3\n4\n");
+        if (!next()) {
+            throw Catch::GeneratorException("Couldn't read a single line");
+        }
+    }
+
+    std::string const& get() const override {
+        return m_line;
+    }
+    
+    bool next() override {
+        return !!std::getline(m_stream, m_line);
+    }
+};
+
+// This helper function provides a nicer UX when instantiating the generator
+// Notice that it returns an instance of GeneratorWrapper<std::string>, which
+// is a value-wrapper around std::unique_ptr<IGenerator<std::string>>.
+Catch::Generators::GeneratorWrapper<std::string> lines(std::string /* ignored for example */) {
+    return Catch::Generators::GeneratorWrapper<std::string>(
+        std::unique_ptr<Catch::Generators::IGenerator<std::string>>(
+            new LineGenerator()
+        )
+    );
+}
+
+
+
+TEST_CASE("filter can convert types inside the generator expression", "[example][generator]") {
+    auto num = GENERATE(map<int>([](std::string const& line) { return std::stoi(line); },
+                                 lines("fake-file")));
+                                 
+    REQUIRE(num > 0);
+}
+
+// Compiling and running this file will result in 4 successful assertions
diff --git a/examples/310-Gen-VariablesInGenerators.cpp b/examples/310-Gen-VariablesInGenerators.cpp
new file mode 100644
index 0000000..96840bb
--- /dev/null
+++ b/examples/310-Gen-VariablesInGenerators.cpp
@@ -0,0 +1,72 @@
+// 310-Gen-VariablesInGenerator.cpp
+// Shows how to use variables when creating generators.
+
+// Note that using variables inside generators is dangerous and should
+// be done only if you know what you are doing, because the generators
+// _WILL_ outlive the variables -- thus they should be either captured
+// by value directly, or copied by the generators during construction.
+
+#include <catch2/catch.hpp>
+
+#include <random>
+
+// Lets start by implementing a parametrizable double generator
+class RandomDoubleGenerator : public Catch::Generators::IGenerator<double> {
+    std::minstd_rand m_rand;
+    std::uniform_real_distribution<> m_dist;
+    double current_number;
+public:
+
+    RandomDoubleGenerator(double low, double high):
+        m_rand(std::random_device{}()),
+        m_dist(low, high)
+    {
+        static_cast<void>(next());
+    }
+
+    double const& get() const override;
+    bool next() override {
+        current_number = m_dist(m_rand);
+        return true;
+    }
+};
+
+// Avoids -Wweak-vtables
+double const& RandomDoubleGenerator::get() const {
+    return current_number;
+}
+
+
+// Also provide a nice shortcut for creating the generator
+Catch::Generators::GeneratorWrapper<double> random(double low, double high) {
+    return Catch::Generators::GeneratorWrapper<double>(std::unique_ptr<Catch::Generators::IGenerator<double>>(new RandomDoubleGenerator(low, high)));
+}
+
+
+TEST_CASE("Generate random doubles across different ranges",
+          "[generator][example][advanced]") {
+    // Workaround for old libstdc++
+    using record = std::tuple<double, double>;
+    // Set up 3 ranges to generate numbers from
+    auto r = GENERATE(table<double, double>({
+        record{3, 4},
+        record{-4, -3},
+        record{10, 1000}
+    }));
+
+    // This will not compile (intentionally), because it accesses a variable
+    // auto number = GENERATE(take(50, random(r.first, r.second)));
+    
+    // We have to manually register the generators instead
+    // Notice that we are using value capture in the lambda, to avoid lifetime issues
+    auto number = Catch::Generators::generate( CATCH_INTERNAL_LINEINFO,
+        [=]{
+            using namespace Catch::Generators;
+            return makeGenerators(take(50, random(std::get<0>(r), std::get<1>(r))));
+        }
+    );
+    REQUIRE(std::abs(number) > 0);
+}
+
+// Compiling and running this file will result in 150 successful assertions
+
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 7270e93..dff5c74 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -8,15 +8,19 @@
 
 project( CatchExamples CXX )
 
+message( STATUS "Examples included" )
+
 # define folders used:
 
 set( EXAMPLES_DIR ${CATCH_DIR}/examples )
 set( HEADER_DIR   ${CATCH_DIR}/single_include )
+set( REPORTER_HEADER_DIR ${CATCH_DIR}/include/reporters )
 
 # single-file sources:
 
 set( SOURCES_SINGLE_FILE
     010-TestCase.cpp
+    231-Cfg-OutputStreams.cpp
 )
 
 # multiple-file modules:
@@ -40,6 +44,29 @@
     110-Fix-ClassFixture.cpp
     120-Bdd-ScenarioGivenWhenThen.cpp
     210-Evt-EventListeners.cpp
+    300-Gen-OwnGenerator.cpp
+    301-Gen-MapTypeConversion.cpp
+    310-Gen-VariablesInGenerators.cpp
+)
+
+# main-s for reporter-specific test sources:
+
+set( SOURCES_REPORTERS_MAIN
+    200-Rpt-CatchMain.cpp
+)
+
+string( REPLACE ".cpp" "" BASENAMES_REPORTERS_MAIN 200-Rpt-CatchMain.cpp )
+
+set( NAMES_REPORTERS TeamCity )
+
+foreach( reporter ${NAMES_REPORTERS} )
+    list( APPEND SOURCES_SPECIFIC_REPORTERS_MAIN ${BASENAMES_REPORTERS_MAIN}${reporter}.cpp )
+endforeach()
+
+# sources to combine with 200-Rpt-CatchMain{Reporter}.cpp:
+
+set( SOURCES_REPORTERS_TESTS
+    207-Rpt-TeamCityReporter.cpp
 )
 
 # check if all sources are listed, warn if not:
@@ -49,6 +76,8 @@
     ${SOURCES_SINGLE_FILE}
     ${SOURCES_IDIOMATIC_MAIN}
     ${SOURCES_IDIOMATIC_TESTS}
+    ${SOURCES_REPORTERS_MAIN}
+    ${SOURCES_REPORTERS_TESTS}
 )
 
 foreach( name ${SOURCES_ALL} )
@@ -61,29 +90,55 @@
 
 string( REPLACE ".cpp" "" BASENAMES_SINGLE_FILE     "${SOURCES_SINGLE_FILE}" )
 string( REPLACE ".cpp" "" BASENAMES_IDIOMATIC_TESTS "${SOURCES_IDIOMATIC_TESTS}" )
+string( REPLACE ".cpp" "" BASENAMES_REPORTERS_TESTS "${SOURCES_REPORTERS_TESTS}" )
+string( REPLACE ".cpp" "" BASENAMES_REPORTERS_MAIN  "${SOURCES_REPORTERS_MAIN}" )
 
 set( TARGETS_SINGLE_FILE     ${BASENAMES_SINGLE_FILE} )
 set( TARGETS_IDIOMATIC_TESTS ${BASENAMES_IDIOMATIC_TESTS} )
-set( TARGETS_ALL             ${TARGETS_SINGLE_FILE} ${TARGETS_IDIOMATIC_TESTS} 020-TestCase CatchMain )
+set( TARGETS_REPORTERS_TESTS ${BASENAMES_REPORTERS_TESTS} )
+set( TARGETS_REPORTERS_MAIN  ${BASENAMES_REPORTERS_MAIN} )
+
+set( TARGETS_ALL
+    ${TARGETS_SINGLE_FILE}
+    020-TestCase
+    ${TARGETS_IDIOMATIC_TESTS} CatchMain
+    ${TARGETS_REPORTERS_TESTS} CatchMainTeamCity
+)
 
 # define program targets:
 
-add_library( CatchMain OBJECT ${EXAMPLES_DIR}/${SOURCES_IDIOMATIC_MAIN} ${HEADER_DIR}/catch.hpp )
+add_library( CatchMain         OBJECT ${EXAMPLES_DIR}/${SOURCES_IDIOMATIC_MAIN} ${HEADER_DIR}/catch2/catch.hpp )
+#add_library( CatchMainAutomake OBJECT ${EXAMPLES_DIR}/200-Rpt-CatchMain.cpp ${HEADER_DIR}/catch2/catch.hpp )
+#add_library( CatchMainTap      OBJECT ${EXAMPLES_DIR}/200-Rpt-CatchMain.cpp ${HEADER_DIR}/catch2/catch.hpp )
+add_library( CatchMainTeamCity OBJECT ${EXAMPLES_DIR}/200-Rpt-CatchMain.cpp ${HEADER_DIR}/catch2/catch.hpp )
 
-add_executable( 020-TestCase ${EXAMPLES_DIR}/020-TestCase-1.cpp ${EXAMPLES_DIR}/020-TestCase-2.cpp ${HEADER_DIR}/catch.hpp )
+#target_compile_definitions( CatchMainAutomake PRIVATE CATCH_EXAMPLE_RPT_1=\"include/reporters/catch_reporter_automake.hpp\" )
+#target_compile_definitions( CatchMainTap      PRIVATE CATCH_EXAMPLE_RPT_1=\"include/reporters/catch_reporter_tap.hpp\" )
+target_compile_definitions( CatchMainTeamCity PRIVATE CATCH_EXAMPLE_RPT_1=\"include/reporters/catch_reporter_teamcity.hpp\" )
 
 foreach( name ${TARGETS_SINGLE_FILE} )
-    add_executable( ${name} ${EXAMPLES_DIR}/${name}.cpp ${HEADER_DIR}/catch.hpp )
+    add_executable( ${name} ${EXAMPLES_DIR}/${name}.cpp ${HEADER_DIR}/catch2/catch.hpp )
 endforeach()
 
 foreach( name ${TARGETS_IDIOMATIC_TESTS} )
-    add_executable( ${name} ${EXAMPLES_DIR}/${name}.cpp $<TARGET_OBJECTS:CatchMain> ${HEADER_DIR}/catch.hpp )
+    add_executable( ${name} ${EXAMPLES_DIR}/${name}.cpp $<TARGET_OBJECTS:CatchMain> ${HEADER_DIR}/catch2/catch.hpp )
 endforeach()
 
+add_executable( 020-TestCase ${EXAMPLES_DIR}/020-TestCase-1.cpp ${EXAMPLES_DIR}/020-TestCase-2.cpp ${HEADER_DIR}/catch2/catch.hpp )
+
+#add_executable( 207-Rpt-AutomakeReporter ${EXAMPLES_DIR}/207-Rpt-AutomakeReporter.cpp $<TARGET_OBJECTS:CatchMainAutomake> ${HEADER_DIR}/catch2/catch.hpp )
+#add_executable( 207-Rpt-TapReporter      ${EXAMPLES_DIR}/207-Rpt-TapReporter.cpp      $<TARGET_OBJECTS:CatchMainTap>      ${HEADER_DIR}/catch2/catch.hpp )
+add_executable( 207-Rpt-TeamCityReporter ${EXAMPLES_DIR}/207-Rpt-TeamCityReporter.cpp $<TARGET_OBJECTS:CatchMainTeamCity> ${HEADER_DIR}/catch2/catch.hpp )
+
+#foreach( name ${TARGETS_REPORTERS_TESTS} )
+#    add_executable( ${name} ${EXAMPLES_DIR}/${name}.cpp $<TARGET_OBJECTS:CatchMain> ${HEADER_DIR}/catch2/catch.hpp )
+#endforeach()
+
 foreach( name ${TARGETS_ALL} )
-    target_include_directories( ${name} PRIVATE ${HEADER_DIR} )
+    target_include_directories( ${name} PRIVATE ${HEADER_DIR} ${CATCH_DIR} )
 
     set_property(TARGET ${name} PROPERTY CXX_STANDARD 11)
+    set_property(TARGET ${name} PROPERTY CXX_EXTENSIONS OFF)
 
     # Add desired warnings
     if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )
@@ -98,3 +153,4 @@
         target_compile_options( ${name}  PRIVATE /W4 /w44265 /WX )
     endif()
 endforeach()
+
diff --git a/include/catch.hpp b/include/catch.hpp
index 0a4711b..e15588f 100644
--- a/include/catch.hpp
+++ b/include/catch.hpp
@@ -10,8 +10,8 @@
 #define TWOBLUECUBES_CATCH_HPP_INCLUDED
 
 #define CATCH_VERSION_MAJOR 2
-#define CATCH_VERSION_MINOR 1
-#define CATCH_VERSION_PATCH 1
+#define CATCH_VERSION_MINOR 7
+#define CATCH_VERSION_PATCH 0
 
 #ifdef __clang__
 #    pragma clang system_header
@@ -33,7 +33,9 @@
 #  if defined(CATCH_CONFIG_DISABLE_MATCHERS)
 #    undef CATCH_CONFIG_DISABLE_MATCHERS
 #  endif
-#  define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
+#  if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
+#    define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
+#  endif
 #endif
 
 #if !defined(CATCH_CONFIG_IMPL_ONLY)
@@ -60,6 +62,9 @@
 #ifndef CATCH_CONFIG_DISABLE_MATCHERS
 #include "internal/catch_capture_matchers.h"
 #endif
+#include "internal/catch_generators.hpp"
+#include "internal/catch_generators_generic.hpp"
+#include "internal/catch_generators_specific.hpp"
 
 // These files are included here so the single_include script doesn't put them
 // in the conditionally compiled sections
@@ -98,7 +103,7 @@
 #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
 #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
 
-#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ )
+#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
@@ -112,7 +117,7 @@
 #define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
 #define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
 
-#define CATCH_CHECK_THROWS( ... )  INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ )
+#define CATCH_CHECK_THROWS( ... )  INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
@@ -128,27 +133,51 @@
 
 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
-#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) )
+#define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE",__VA_ARGS__ )
 
 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
+#define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
 #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
 
 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
 
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
+#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
+#else
+#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
+#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
+#endif
+
+
+#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
+#define CATCH_STATIC_REQUIRE( ... )       static_assert(   __VA_ARGS__ ,      #__VA_ARGS__ );     CATCH_SUCCEED( #__VA_ARGS__ )
+#define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ )
+#else
+#define CATCH_STATIC_REQUIRE( ... )       CATCH_REQUIRE( __VA_ARGS__ )
+#define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ )
+#endif
+
+
 // "BDD-style" convenience wrappers
 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
-#define CATCH_GIVEN( desc )    CATCH_SECTION( std::string( "Given: ") + desc )
-#define CATCH_WHEN( desc )     CATCH_SECTION( std::string( " When: ") + desc )
-#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( "  And: ") + desc )
-#define CATCH_THEN( desc )     CATCH_SECTION( std::string( " Then: ") + desc )
-#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( "  And: ") + desc )
+#define CATCH_GIVEN( desc )     INTERNAL_CATCH_DYNAMIC_SECTION( "    Given: " << desc )
+#define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
+#define CATCH_WHEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     When: " << desc )
+#define CATCH_AND_WHEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
+#define CATCH_THEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     Then: " << desc )
+#define CATCH_AND_THEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( "      And: " << desc )
 
 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
 #else
@@ -186,19 +215,42 @@
 #endif // CATCH_CONFIG_DISABLE_MATCHERS
 
 #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
+#define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg )
 #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
-#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) )
+#define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ )
 
 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
+#define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
 #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
 #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
 
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
+#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
+#define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
+#else
+#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
+#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
+#define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
+#endif
+
+
+#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
+#define STATIC_REQUIRE( ... )       static_assert(   __VA_ARGS__,  #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ )
+#define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" )
+#else
+#define STATIC_REQUIRE( ... )       REQUIRE( __VA_ARGS__ )
+#define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ )
+#endif
+
 #endif
 
 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
@@ -207,15 +259,17 @@
 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
 
-#define GIVEN( desc )    SECTION( std::string("   Given: ") + desc )
-#define WHEN( desc )     SECTION( std::string("    When: ") + desc )
-#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc )
-#define THEN( desc )     SECTION( std::string("    Then: ") + desc )
-#define AND_THEN( desc ) SECTION( std::string("     And: ") + desc )
+#define GIVEN( desc )     INTERNAL_CATCH_DYNAMIC_SECTION( "    Given: " << desc )
+#define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
+#define WHEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     When: " << desc )
+#define AND_WHEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
+#define THEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     Then: " << desc )
+#define AND_THEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( "      And: " << desc )
 
 using Catch::Detail::Approx;
 
-#else
+#else // CATCH_CONFIG_DISABLE
+
 //////
 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_
 #ifdef CATCH_CONFIG_PREFIX_ALL
@@ -260,21 +314,38 @@
 #define CATCH_METHOD_AS_TEST_CASE( method, ... )
 #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
 #define CATCH_SECTION( ... )
+#define CATCH_DYNAMIC_SECTION( ... )
 #define CATCH_FAIL( ... ) (void)(0)
 #define CATCH_FAIL_CHECK( ... ) (void)(0)
 #define CATCH_SUCCEED( ... ) (void)(0)
 
 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
 
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) )
+#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className )
+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
+#else
+#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) )
+#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) )
+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
+#endif
+
 // "BDD-style" convenience wrappers
 #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
 #define CATCH_GIVEN( desc )
+#define CATCH_AND_GIVEN( desc )
 #define CATCH_WHEN( desc )
 #define CATCH_AND_WHEN( desc )
 #define CATCH_THEN( desc )
 #define CATCH_AND_THEN( desc )
 
+#define CATCH_STATIC_REQUIRE( ... )       (void)(0)
+#define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0)
+
 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
 #else
 
@@ -319,11 +390,27 @@
 #define METHOD_AS_TEST_CASE( method, ... )
 #define REGISTER_TEST_CASE( Function, ... ) (void)(0)
 #define SECTION( ... )
+#define DYNAMIC_SECTION( ... )
 #define FAIL( ... ) (void)(0)
 #define FAIL_CHECK( ... ) (void)(0)
 #define SUCCEED( ... ) (void)(0)
 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
 
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) )
+#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className )
+#define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
+#else
+#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) )
+#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) )
+#define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
+#endif
+
+#define STATIC_REQUIRE( ... )       (void)(0)
+#define STATIC_REQUIRE_FALSE( ... ) (void)(0)
+
 #endif
 
 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
@@ -333,6 +420,7 @@
 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
 
 #define GIVEN( desc )
+#define AND_GIVEN( desc )
 #define WHEN( desc )
 #define AND_WHEN( desc )
 #define THEN( desc )
diff --git a/include/catch_with_main.cpp b/include/catch_with_main.cpp
new file mode 120000
index 0000000..273da6b
--- /dev/null
+++ b/include/catch_with_main.cpp
@@ -0,0 +1 @@
+catch_with_main.hpp
\ No newline at end of file
diff --git a/include/external/clara.hpp b/include/external/clara.hpp
index 31dea24..20c6da7 100644
--- a/include/external/clara.hpp
+++ b/include/external/clara.hpp
@@ -5,7 +5,7 @@
 //
 // See https://github.com/philsquared/Clara for more details
 
-// Clara v1.1.1
+// Clara v1.1.5
 
 #ifndef CATCH_CLARA_HPP_INCLUDED
 #define CATCH_CLARA_HPP_INCLUDED
@@ -18,14 +18,24 @@
 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH
 #endif
 
+#ifndef CLARA_CONFIG_OPTIONAL_TYPE
+#ifdef __has_include
+#if __has_include(<optional>) && __cplusplus >= 201703L
+#include <optional>
+#define CLARA_CONFIG_OPTIONAL_TYPE std::optional
+#endif
+#endif
+#endif
+
+
 // ----------- #included from clara_textflow.hpp -----------
 
 // TextFlowCpp
 //
 // A single-header library for wrapping and laying out basic text, by Phil Nash
 //
-// This work is licensed under the BSD 2-Clause license.
-// See the accompanying LICENSE file, or the one at https://opensource.org/licenses/BSD-2-Clause
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 //
 // This project is hosted at https://github.com/philsquared/textflowcpp
 
@@ -41,324 +51,327 @@
 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80
 #endif
 
-#if CATCH_CONFIG_USE_EXCEPTIONS == 0
-// std::cerr + std::terminate instead of 'throw'
-#include <iostream>
-#include <exception>
-#endif
 
+namespace Catch {
+namespace clara {
+namespace TextFlow {
 
-namespace Catch { namespace clara { namespace TextFlow {
+inline auto isWhitespace(char c) -> bool {
+	static std::string chars = " \t\n\r";
+	return chars.find(c) != std::string::npos;
+}
+inline auto isBreakableBefore(char c) -> bool {
+	static std::string chars = "[({<|";
+	return chars.find(c) != std::string::npos;
+}
+inline auto isBreakableAfter(char c) -> bool {
+	static std::string chars = "])}>.,:;*+-=&/\\";
+	return chars.find(c) != std::string::npos;
+}
 
-    inline auto isWhitespace( char c ) -> bool {
-        static std::string chars = " \t\n\r";
-        return chars.find( c ) != std::string::npos;
-    }
-    inline auto isBreakableBefore( char c ) -> bool {
-        static std::string chars = "[({<|";
-        return chars.find( c ) != std::string::npos;
-    }
-    inline auto isBreakableAfter( char c ) -> bool {
-        static std::string chars = "])}>.,:;*+-=&/\\";
-        return chars.find( c ) != std::string::npos;
-    }
+class Columns;
 
-    class Columns;
+class Column {
+	std::vector<std::string> m_strings;
+	size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH;
+	size_t m_indent = 0;
+	size_t m_initialIndent = std::string::npos;
 
-    class Column {
-        std::vector<std::string> m_strings;
-        size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH;
-        size_t m_indent = 0;
-        size_t m_initialIndent = std::string::npos;
+public:
+	class iterator {
+		friend Column;
 
-    public:
-        class iterator {
-            friend Column;
+		Column const& m_column;
+		size_t m_stringIndex = 0;
+		size_t m_pos = 0;
 
-            Column const& m_column;
-            size_t m_stringIndex = 0;
-            size_t m_pos = 0;
+		size_t m_len = 0;
+		size_t m_end = 0;
+		bool m_suffix = false;
 
-            size_t m_len = 0;
-            size_t m_end = 0;
-            bool m_suffix = false;
+		iterator(Column const& column, size_t stringIndex)
+			: m_column(column),
+			m_stringIndex(stringIndex) {}
 
-            iterator( Column const& column, size_t stringIndex )
-            :   m_column( column ),
-                m_stringIndex( stringIndex )
-            {}
+		auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; }
 
-            auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; }
+		auto isBoundary(size_t at) const -> bool {
+			assert(at > 0);
+			assert(at <= line().size());
 
-            auto isBoundary( size_t at ) const -> bool {
-                assert( at > 0 );
-                assert( at <= line().size() );
+			return at == line().size() ||
+				(isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) ||
+				isBreakableBefore(line()[at]) ||
+				isBreakableAfter(line()[at - 1]);
+		}
 
-                return at == line().size() ||
-                       ( isWhitespace( line()[at] ) && !isWhitespace( line()[at-1] ) ) ||
-                       isBreakableBefore( line()[at] ) ||
-                       isBreakableAfter( line()[at-1] );
-            }
+		void calcLength() {
+			assert(m_stringIndex < m_column.m_strings.size());
 
-            void calcLength() {
-                assert( m_stringIndex < m_column.m_strings.size() );
+			m_suffix = false;
+			auto width = m_column.m_width - indent();
+			m_end = m_pos;
+			while (m_end < line().size() && line()[m_end] != '\n')
+				++m_end;
 
-                m_suffix = false;
-                auto width = m_column.m_width-indent();
-                m_end = m_pos;
-                while( m_end < line().size() && line()[m_end] != '\n' )
-                    ++m_end;
+			if (m_end < m_pos + width) {
+				m_len = m_end - m_pos;
+			} else {
+				size_t len = width;
+				while (len > 0 && !isBoundary(m_pos + len))
+					--len;
+				while (len > 0 && isWhitespace(line()[m_pos + len - 1]))
+					--len;
 
-                if( m_end < m_pos + width ) {
-                    m_len = m_end - m_pos;
-                }
-                else {
-                    size_t len = width;
-                    while (len > 0 && !isBoundary(m_pos + len))
-                        --len;
-                    while (len > 0 && isWhitespace( line()[m_pos + len - 1] ))
-                        --len;
+				if (len > 0) {
+					m_len = len;
+				} else {
+					m_suffix = true;
+					m_len = width - 1;
+				}
+			}
+		}
 
-                    if (len > 0) {
-                        m_len = len;
-                    } else {
-                        m_suffix = true;
-                        m_len = width - 1;
-                    }
-                }
-            }
+		auto indent() const -> size_t {
+			auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;
+			return initial == std::string::npos ? m_column.m_indent : initial;
+		}
 
-            auto indent() const -> size_t {
-                auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;
-                return initial == std::string::npos ? m_column.m_indent : initial;
-            }
+		auto addIndentAndSuffix(std::string const &plain) const -> std::string {
+			return std::string(indent(), ' ') + (m_suffix ? plain + "-" : plain);
+		}
 
-            auto addIndentAndSuffix(std::string const &plain) const -> std::string {
-                return std::string( indent(), ' ' ) + (m_suffix ? plain + "-" : plain);
-            }
+	public:
+		using difference_type = std::ptrdiff_t;
+		using value_type = std::string;
+		using pointer = value_type * ;
+		using reference = value_type & ;
+		using iterator_category = std::forward_iterator_tag;
 
-        public:
-            explicit iterator( Column const& column ) : m_column( column ) {
-                assert( m_column.m_width > m_column.m_indent );
-                assert( m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent );
-                calcLength();
-                if( m_len == 0 )
-                    m_stringIndex++; // Empty string
-            }
+		explicit iterator(Column const& column) : m_column(column) {
+			assert(m_column.m_width > m_column.m_indent);
+			assert(m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent);
+			calcLength();
+			if (m_len == 0)
+				m_stringIndex++; // Empty string
+		}
 
-            auto operator *() const -> std::string {
-                assert( m_stringIndex < m_column.m_strings.size() );
-                assert( m_pos <= m_end );
-                if( m_pos + m_column.m_width < m_end )
-                    return addIndentAndSuffix(line().substr(m_pos, m_len));
-                else
-                    return addIndentAndSuffix(line().substr(m_pos, m_end - m_pos));
-            }
+		auto operator *() const -> std::string {
+			assert(m_stringIndex < m_column.m_strings.size());
+			assert(m_pos <= m_end);
+			return addIndentAndSuffix(line().substr(m_pos, m_len));
+		}
 
-            auto operator ++() -> iterator& {
-                m_pos += m_len;
-                if( m_pos < line().size() && line()[m_pos] == '\n' )
-                    m_pos += 1;
-                else
-                    while( m_pos < line().size() && isWhitespace( line()[m_pos] ) )
-                        ++m_pos;
+		auto operator ++() -> iterator& {
+			m_pos += m_len;
+			if (m_pos < line().size() && line()[m_pos] == '\n')
+				m_pos += 1;
+			else
+				while (m_pos < line().size() && isWhitespace(line()[m_pos]))
+					++m_pos;
 
-                if( m_pos == line().size() ) {
-                    m_pos = 0;
-                    ++m_stringIndex;
-                }
-                if( m_stringIndex < m_column.m_strings.size() )
-                    calcLength();
-                return *this;
-            }
-            auto operator ++(int) -> iterator {
-                iterator prev( *this );
-                operator++();
-                return prev;
-            }
+			if (m_pos == line().size()) {
+				m_pos = 0;
+				++m_stringIndex;
+			}
+			if (m_stringIndex < m_column.m_strings.size())
+				calcLength();
+			return *this;
+		}
+		auto operator ++(int) -> iterator {
+			iterator prev(*this);
+			operator++();
+			return prev;
+		}
 
-            auto operator ==( iterator const& other ) const -> bool {
-                return
-                    m_pos == other.m_pos &&
-                    m_stringIndex == other.m_stringIndex &&
-                    &m_column == &other.m_column;
-            }
-            auto operator !=( iterator const& other ) const -> bool {
-                return !operator==( other );
-            }
-        };
-        using const_iterator = iterator;
+		auto operator ==(iterator const& other) const -> bool {
+			return
+				m_pos == other.m_pos &&
+				m_stringIndex == other.m_stringIndex &&
+				&m_column == &other.m_column;
+		}
+		auto operator !=(iterator const& other) const -> bool {
+			return !operator==(other);
+		}
+	};
+	using const_iterator = iterator;
 
-        explicit Column( std::string const& text ) { m_strings.push_back( text ); }
+	explicit Column(std::string const& text) { m_strings.push_back(text); }
 
-        auto width( size_t newWidth ) -> Column& {
-            assert( newWidth > 0 );
-            m_width = newWidth;
-            return *this;
-        }
-        auto indent( size_t newIndent ) -> Column& {
-            m_indent = newIndent;
-            return *this;
-        }
-        auto initialIndent( size_t newIndent ) -> Column& {
-            m_initialIndent = newIndent;
-            return *this;
-        }
+	auto width(size_t newWidth) -> Column& {
+		assert(newWidth > 0);
+		m_width = newWidth;
+		return *this;
+	}
+	auto indent(size_t newIndent) -> Column& {
+		m_indent = newIndent;
+		return *this;
+	}
+	auto initialIndent(size_t newIndent) -> Column& {
+		m_initialIndent = newIndent;
+		return *this;
+	}
 
-        auto width() const -> size_t { return m_width; }
-        auto begin() const -> iterator { return iterator( *this ); }
-        auto end() const -> iterator { return { *this, m_strings.size() }; }
+	auto width() const -> size_t { return m_width; }
+	auto begin() const -> iterator { return iterator(*this); }
+	auto end() const -> iterator { return { *this, m_strings.size() }; }
 
-        inline friend std::ostream& operator << ( std::ostream& os, Column const& col ) {
-            bool first = true;
-            for( auto line : col ) {
-                if( first )
-                    first = false;
-                else
-                    os << "\n";
-                os <<  line;
-            }
-            return os;
-        }
+	inline friend std::ostream& operator << (std::ostream& os, Column const& col) {
+		bool first = true;
+		for (auto line : col) {
+			if (first)
+				first = false;
+			else
+				os << "\n";
+			os << line;
+		}
+		return os;
+	}
 
-        auto operator + ( Column const& other ) -> Columns;
+	auto operator + (Column const& other)->Columns;
 
-        auto toString() const -> std::string {
-            std::ostringstream oss;
-            oss << *this;
-            return oss.str();
-        }
-    };
+	auto toString() const -> std::string {
+		std::ostringstream oss;
+		oss << *this;
+		return oss.str();
+	}
+};
 
-    class Spacer : public Column {
+class Spacer : public Column {
 
-    public:
-        explicit Spacer( size_t spaceWidth ) : Column( "" ) {
-            width( spaceWidth );
-        }
-    };
+public:
+	explicit Spacer(size_t spaceWidth) : Column("") {
+		width(spaceWidth);
+	}
+};
 
-    class Columns {
-        std::vector<Column> m_columns;
+class Columns {
+	std::vector<Column> m_columns;
 
-    public:
+public:
 
-        class iterator {
-            friend Columns;
-            struct EndTag {};
+	class iterator {
+		friend Columns;
+		struct EndTag {};
 
-            std::vector<Column> const& m_columns;
-            std::vector<Column::iterator> m_iterators;
-            size_t m_activeIterators;
+		std::vector<Column> const& m_columns;
+		std::vector<Column::iterator> m_iterators;
+		size_t m_activeIterators;
 
-            iterator( Columns const& columns, EndTag )
-            :   m_columns( columns.m_columns ),
-                m_activeIterators( 0 )
-            {
-                m_iterators.reserve( m_columns.size() );
+		iterator(Columns const& columns, EndTag)
+			: m_columns(columns.m_columns),
+			m_activeIterators(0) {
+			m_iterators.reserve(m_columns.size());
 
-                for( auto const& col : m_columns )
-                    m_iterators.push_back( col.end() );
-            }
+			for (auto const& col : m_columns)
+				m_iterators.push_back(col.end());
+		}
 
-        public:
-            explicit iterator( Columns const& columns )
-            :   m_columns( columns.m_columns ),
-                m_activeIterators( m_columns.size() )
-            {
-                m_iterators.reserve( m_columns.size() );
+	public:
+		using difference_type = std::ptrdiff_t;
+		using value_type = std::string;
+		using pointer = value_type * ;
+		using reference = value_type & ;
+		using iterator_category = std::forward_iterator_tag;
 
-                for( auto const& col : m_columns )
-                    m_iterators.push_back( col.begin() );
-            }
+		explicit iterator(Columns const& columns)
+			: m_columns(columns.m_columns),
+			m_activeIterators(m_columns.size()) {
+			m_iterators.reserve(m_columns.size());
 
-            auto operator ==( iterator const& other ) const -> bool {
-                return m_iterators == other.m_iterators;
-            }
-            auto operator !=( iterator const& other ) const -> bool {
-                return m_iterators != other.m_iterators;
-            }
-            auto operator *() const -> std::string {
-                std::string row, padding;
+			for (auto const& col : m_columns)
+				m_iterators.push_back(col.begin());
+		}
 
-                for( size_t i = 0; i < m_columns.size(); ++i ) {
-                    auto width = m_columns[i].width();
-                    if( m_iterators[i] != m_columns[i].end() ) {
-                        std::string col = *m_iterators[i];
-                        row += padding + col;
-                        if( col.size() < width )
-                            padding = std::string( width - col.size(), ' ' );
-                        else
-                            padding = "";
-                    }
-                    else {
-                        padding += std::string( width, ' ' );
-                    }
-                }
-                return row;
-            }
-            auto operator ++() -> iterator& {
-                for( size_t i = 0; i < m_columns.size(); ++i ) {
-                    if (m_iterators[i] != m_columns[i].end())
-                        ++m_iterators[i];
-                }
-                return *this;
-            }
-            auto operator ++(int) -> iterator {
-                iterator prev( *this );
-                operator++();
-                return prev;
-            }
-        };
-        using const_iterator = iterator;
+		auto operator ==(iterator const& other) const -> bool {
+			return m_iterators == other.m_iterators;
+		}
+		auto operator !=(iterator const& other) const -> bool {
+			return m_iterators != other.m_iterators;
+		}
+		auto operator *() const -> std::string {
+			std::string row, padding;
 
-        auto begin() const -> iterator { return iterator( *this ); }
-        auto end() const -> iterator { return { *this, iterator::EndTag() }; }
+			for (size_t i = 0; i < m_columns.size(); ++i) {
+				auto width = m_columns[i].width();
+				if (m_iterators[i] != m_columns[i].end()) {
+					std::string col = *m_iterators[i];
+					row += padding + col;
+					if (col.size() < width)
+						padding = std::string(width - col.size(), ' ');
+					else
+						padding = "";
+				} else {
+					padding += std::string(width, ' ');
+				}
+			}
+			return row;
+		}
+		auto operator ++() -> iterator& {
+			for (size_t i = 0; i < m_columns.size(); ++i) {
+				if (m_iterators[i] != m_columns[i].end())
+					++m_iterators[i];
+			}
+			return *this;
+		}
+		auto operator ++(int) -> iterator {
+			iterator prev(*this);
+			operator++();
+			return prev;
+		}
+	};
+	using const_iterator = iterator;
 
-        auto operator += ( Column const& col ) -> Columns& {
-            m_columns.push_back( col );
-            return *this;
-        }
-        auto operator + ( Column const& col ) -> Columns {
-            Columns combined = *this;
-            combined += col;
-            return combined;
-        }
+	auto begin() const -> iterator { return iterator(*this); }
+	auto end() const -> iterator { return { *this, iterator::EndTag() }; }
 
-        inline friend std::ostream& operator << ( std::ostream& os, Columns const& cols ) {
+	auto operator += (Column const& col) -> Columns& {
+		m_columns.push_back(col);
+		return *this;
+	}
+	auto operator + (Column const& col) -> Columns {
+		Columns combined = *this;
+		combined += col;
+		return combined;
+	}
 
-            bool first = true;
-            for( auto line : cols ) {
-                if( first )
-                    first = false;
-                else
-                    os << "\n";
-                os << line;
-            }
-            return os;
-        }
+	inline friend std::ostream& operator << (std::ostream& os, Columns const& cols) {
 
-        auto toString() const -> std::string {
-            std::ostringstream oss;
-            oss << *this;
-            return oss.str();
-        }
-    };
+		bool first = true;
+		for (auto line : cols) {
+			if (first)
+				first = false;
+			else
+				os << "\n";
+			os << line;
+		}
+		return os;
+	}
 
-    inline auto Column::operator + ( Column const& other ) -> Columns {
-        Columns cols;
-        cols += *this;
-        cols += other;
-        return cols;
-    }
-}}} // namespace Catch::clara::TextFlow
+	auto toString() const -> std::string {
+		std::ostringstream oss;
+		oss << *this;
+		return oss.str();
+	}
+};
 
+inline auto Column::operator + (Column const& other) -> Columns {
+	Columns cols;
+	cols += *this;
+	cols += other;
+	return cols;
+}
+}
+
+}
+}
 #endif // CATCH_CLARA_TEXTFLOW_HPP_INCLUDED
 
 // ----------- end of #include from clara_textflow.hpp -----------
 // ........... back in clara.hpp
 
-
+#include <cctype>
+#include <string>
 #include <memory>
 #include <set>
 #include <algorithm>
@@ -395,11 +408,9 @@
         std::vector<std::string> m_args;
 
     public:
-        Args( int argc, char *argv[] ) {
-            m_exeName = argv[0];
-            for( int i = 1; i < argc; ++i )
-                m_args.push_back( argv[i] );
-        }
+        Args( int argc, char const* const* argv )
+            : m_exeName(argv[0]),
+              m_args(argv + 1, argv + argc) {}
 
         Args( std::initializer_list<std::string> args )
         :   m_exeName( *args.begin() ),
@@ -586,14 +597,13 @@
 
     protected:
         void enforceOk() const override {
-            switch( m_type ) {
-                case ResultBase::LogicError:
-                    Exception::doThrow( std::logic_error( m_errorMessage ) );
-                case ResultBase::RuntimeError:
-                    Exception::doThrow( std::runtime_error( m_errorMessage ) );
-                case ResultBase::Ok:
-                    break;
-            }
+
+            // Errors shouldn't reach this point, but if they do
+            // the actual error message will be in m_errorMessage
+            assert( m_type != ResultBase::LogicError );
+            assert( m_type != ResultBase::RuntimeError );
+            if( m_type != ResultBase::Ok )
+                std::abort();
         }
 
         std::string m_errorMessage; // Only populated if resultType is an error
@@ -654,7 +664,7 @@
     }
     inline auto convertInto( std::string const &source, bool &target ) -> ParserResult {
         std::string srcLC = source;
-        std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( ::tolower(c) ); } );
+        std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( std::tolower(c) ); } );
         if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on")
             target = true;
         else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off")
@@ -663,6 +673,16 @@
             return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" );
         return ParserResult::ok( ParseResultType::Matched );
     }
+#ifdef CLARA_CONFIG_OPTIONAL_TYPE
+    template<typename T>
+    inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult {
+        T temp;
+        auto result = convertInto( source, temp );
+        if( result )
+            target = std::move(temp);
+        return result;
+    }
+#endif // CLARA_CONFIG_OPTIONAL_TYPE
 
     struct NonCopyable {
         NonCopyable() = default;
@@ -672,20 +692,17 @@
         NonCopyable &operator=( NonCopyable && ) = delete;
     };
 
-    struct BoundValueRefBase;
-
     struct BoundRef : NonCopyable {
         virtual ~BoundRef() = default;
         virtual auto isContainer() const -> bool { return false; }
-        virtual auto isValueRefBase() const -> bool = 0;  // Support for compiling without rtti.
+        virtual auto isFlag() const -> bool { return false; }
     };
     struct BoundValueRefBase : BoundRef {
         virtual auto setValue( std::string const &arg ) -> ParserResult = 0;
-        virtual auto isValueRefBase() const -> bool { return true; }
     };
     struct BoundFlagRefBase : BoundRef {
         virtual auto setFlag( bool flag ) -> ParserResult = 0;
-        virtual auto isValueRefBase() const -> bool { return false; }
+        virtual auto isFlag() const -> bool { return true; }
     };
 
     template<typename T>
@@ -917,7 +934,7 @@
             if( token.type != TokenType::Argument )
                 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
 
-            assert( m_ref.get()->isValueRefBase() );
+            assert( !m_ref->isFlag() );
             auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
 
             auto result = valueRef->setValue( remainingTokens->token );
@@ -993,20 +1010,14 @@
             if( remainingTokens && remainingTokens->type == TokenType::Option ) {
                 auto const &token = *remainingTokens;
                 if( isMatch(token.token ) ) {
-                    if ( !m_ref.get()->isValueRefBase() ) {
-                        detail::BoundFlagRefBase* flagRef = static_cast<detail::BoundFlagRefBase*>( m_ref.get() );
-#if CATCH_CONFIG_USE_RTTI
-                        assert( dynamic_cast<detail::BoundFlagRefBase*>( m_ref.get() ) );
-#endif
+                    if( m_ref->isFlag() ) {
+                        auto flagRef = static_cast<detail::BoundFlagRefBase*>( m_ref.get() );
                         auto result = flagRef->setFlag( true );
                         if( !result )
                             return InternalParseResult( result );
                         if( result.value() == ParseResultType::ShortCircuitAll )
                             return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
                     } else {
-#if CATCH_CONFIG_USE_RTTI
-                        assert( dynamic_cast<detail::BoundValueRefBase*>( m_ref.get() ) );
-#endif
                         auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
                         ++remainingTokens;
                         if( !remainingTokens )
diff --git a/include/internal/catch_approx.cpp b/include/internal/catch_approx.cpp
index 20f7b16..a7d7111 100644
--- a/include/internal/catch_approx.cpp
+++ b/include/internal/catch_approx.cpp
@@ -7,6 +7,7 @@
  */
 
 #include "catch_approx.h"
+#include "catch_enforce.h"
 
 #include <cmath>
 #include <limits>
@@ -35,6 +36,13 @@
         return Approx( 0 );
     }
 
+    Approx Approx::operator-() const {
+        auto temp(*this);
+        temp.m_value = -temp.m_value;
+        return temp;
+    }
+
+
     std::string Approx::toString() const {
         ReusableStringStream rss;
         rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )";
@@ -47,8 +55,31 @@
         return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value)));
     }
 
+    void Approx::setMargin(double margin) {
+        CATCH_ENFORCE(margin >= 0,
+            "Invalid Approx::margin: " << margin << '.'
+            << " Approx::Margin has to be non-negative.");
+        m_margin = margin;
+    }
+
+    void Approx::setEpsilon(double epsilon) {
+        CATCH_ENFORCE(epsilon >= 0 && epsilon <= 1.0,
+            "Invalid Approx::epsilon: " << epsilon << '.'
+            << " Approx::epsilon has to be in [0, 1]");
+        m_epsilon = epsilon;
+    }
+
 } // end namespace Detail
 
+namespace literals {
+    Detail::Approx operator "" _a(long double val) {
+        return Detail::Approx(val);
+    }
+    Detail::Approx operator "" _a(unsigned long long val) {
+        return Detail::Approx(val);
+    }
+} // end namespace literals
+
 std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value) {
     return value.toString();
 }
diff --git a/include/internal/catch_approx.h b/include/internal/catch_approx.h
index 4b58f46..4522e5a 100644
--- a/include/internal/catch_approx.h
+++ b/include/internal/catch_approx.h
@@ -8,11 +8,9 @@
 #ifndef TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
 #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
 
-#include "catch_common.h"
 #include "catch_tostring.h"
 
 #include <type_traits>
-#include <stdexcept>
 
 namespace Catch {
 namespace Detail {
@@ -20,18 +18,26 @@
     class Approx {
     private:
         bool equalityComparisonImpl(double other) const;
+        // Validates the new margin (margin >= 0)
+        // out-of-line to avoid including stdexcept in the header
+        void setMargin(double margin);
+        // Validates the new epsilon (0 < epsilon < 1)
+        // out-of-line to avoid including stdexcept in the header
+        void setEpsilon(double epsilon);
 
     public:
         explicit Approx ( double value );
 
         static Approx custom();
 
+        Approx operator-() const;
+
         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
         Approx operator()( T const& value ) {
             Approx approx( static_cast<double>(value) );
-            approx.epsilon( m_epsilon );
-            approx.margin( m_margin );
-            approx.scale( m_scale );
+            approx.m_epsilon = m_epsilon;
+            approx.m_margin = m_margin;
+            approx.m_scale = m_scale;
             return approx;
         }
 
@@ -84,27 +90,14 @@
         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
         Approx& epsilon( T const& newEpsilon ) {
             double epsilonAsDouble = static_cast<double>(newEpsilon);
-            if( epsilonAsDouble < 0 || epsilonAsDouble > 1.0 ) {
-              Exception::doThrow( std::domain_error
-                    (   "Invalid Approx::epsilon: " +
-                        Catch::Detail::stringify( epsilonAsDouble ) +
-                        ", Approx::epsilon has to be between 0 and 1" ) );
-            }
-            m_epsilon = epsilonAsDouble;
+            setEpsilon(epsilonAsDouble);
             return *this;
         }
 
         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
         Approx& margin( T const& newMargin ) {
             double marginAsDouble = static_cast<double>(newMargin);
-            if( marginAsDouble < 0 ) {
-                Exception::doThrow( std::domain_error
-                    (   "Invalid Approx::margin: " +
-                         Catch::Detail::stringify( marginAsDouble ) +
-                         ", Approx::Margin has to be non-negative." ) );
-
-            }
-            m_margin = marginAsDouble;
+            setMargin(marginAsDouble);
             return *this;
         }
 
@@ -122,7 +115,12 @@
         double m_scale;
         double m_value;
     };
-}
+} // end namespace Detail
+
+namespace literals {
+    Detail::Approx operator "" _a(long double val);
+    Detail::Approx operator "" _a(unsigned long long val);
+} // end namespace literals
 
 template<>
 struct StringMaker<Catch::Detail::Approx> {
diff --git a/include/internal/catch_assertionhandler.cpp b/include/internal/catch_assertionhandler.cpp
index e4a107e..fd14c85 100644
--- a/include/internal/catch_assertionhandler.cpp
+++ b/include/internal/catch_assertionhandler.cpp
@@ -15,12 +15,15 @@
 #include "catch_interfaces_registry_hub.h"
 #include "catch_capture_matchers.h"
 #include "catch_run_context.h"
+#include "catch_enforce.h"
 
 namespace Catch {
 
-    auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& {
-        expr.streamReconstructedExpression( os );
-        return os;
+    namespace {
+        auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& {
+            expr.streamReconstructedExpression( os );
+            return os;
+        }
     }
 
     LazyExpression::LazyExpression( bool isNegated )
@@ -50,7 +53,7 @@
     }
 
     AssertionHandler::AssertionHandler
-        (   StringRef macroName,
+        (   StringRef const& macroName,
             SourceLineInfo const& lineInfo,
             StringRef capturedExpression,
             ResultDisposition::Flags resultDisposition )
@@ -79,8 +82,13 @@
             // (To go back to the test and change execution, jump over the throw, next)
             CATCH_BREAK_INTO_DEBUGGER();
         }
-        if( m_reaction.shouldThrow )
-            Exception::doThrow( Catch::TestFailureException() );
+        if (m_reaction.shouldThrow) {
+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
+            throw Catch::TestFailureException();
+#else
+            CATCH_ERROR( "Test failure requires aborting test!" );
+#endif
+        }
     }
     void AssertionHandler::setCompleted() {
         m_completed = true;
@@ -107,7 +115,7 @@
 
     // This is the overload that takes a string and infers the Equals matcher from it
     // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp
-    void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString  ) {
+    void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString  ) {
         handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString );
     }
 
diff --git a/include/internal/catch_assertionhandler.h b/include/internal/catch_assertionhandler.h
index cadc78f..3089e66 100644
--- a/include/internal/catch_assertionhandler.h
+++ b/include/internal/catch_assertionhandler.h
@@ -49,7 +49,7 @@
 
     public:
         AssertionHandler
-            (   StringRef macroName,
+            (   StringRef const& macroName,
                 SourceLineInfo const& lineInfo,
                 StringRef capturedExpression,
                 ResultDisposition::Flags resultDisposition );
@@ -81,7 +81,7 @@
         auto allowThrows() const -> bool;
     };
 
-    void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString );
+    void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString );
 
 } // namespace Catch
 
diff --git a/include/internal/catch_assertionresult.cpp b/include/internal/catch_assertionresult.cpp
index ec32c66..4ce0718 100644
--- a/include/internal/catch_assertionresult.cpp
+++ b/include/internal/catch_assertionresult.cpp
@@ -65,9 +65,9 @@
             expr = m_info.capturedExpression;
         else {
             expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
-            expr += m_info.macroName.c_str();
+            expr += m_info.macroName;
             expr += "( ";
-            expr += m_info.capturedExpression.c_str();
+            expr += m_info.capturedExpression;
             expr += " )";
         }
         return expr;
diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp
index 29ad326..51fa035 100644
--- a/include/internal/catch_capture.hpp
+++ b/include/internal/catch_capture.hpp
@@ -9,8 +9,9 @@
 #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
 
 #include "catch_assertionhandler.h"
-#include "catch_message.h"
 #include "catch_interfaces_capture.h"
+#include "catch_message.h"
+#include "catch_stringref.h"
 
 #if !defined(CATCH_CONFIG_DISABLE)
 
@@ -20,14 +21,7 @@
   #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
 #endif
 
-#if defined(CATCH_CONFIG_FAST_COMPILE)
-
-struct ConvertToAny {
-  template <typename T>
-  operator T() {
-    return T{};
-  }
-};
+#if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
 
 ///////////////////////////////////////////////////////////////////////////////
 // Another way to speed-up compilation is to omit local try-catch for REQUIRE*
@@ -37,8 +31,8 @@
 
 #else // CATCH_CONFIG_FAST_COMPILE
 
-#define INTERNAL_CATCH_TRY CATCH_INTERNAL_TRY
-#define INTERNAL_CATCH_CATCH( handler ) CATCH_INTERNAL_CATCH_ALL() { handler.handleUnexpectedInflightException(); }
+#define INTERNAL_CATCH_TRY try
+#define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); }
 
 #endif
 
@@ -47,14 +41,14 @@
 ///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
     do { \
-        Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
         INTERNAL_CATCH_TRY { \
             CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
             catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \
             CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
         } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
-    } while( (void)0, false && static_cast<bool>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look
+    } while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look
     // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -67,15 +61,23 @@
     INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
     if( !Catch::getResultCapture().lastAssertionPassed() )
 
+#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
+
+#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... )
+#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... )
+#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr )
+
+#else
+
 ///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
     do { \
-        Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
-        CATCH_INTERNAL_TRY { \
+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
+        try { \
             static_cast<void>(__VA_ARGS__); \
             catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
         } \
-        CATCH_INTERNAL_CATCH_ALL() { \
+        catch( ... ) { \
             catchAssertionHandler.handleUnexpectedInflightException(); \
         } \
         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
@@ -84,7 +86,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
     do { \
-        Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
         if( catchAssertionHandler.allowThrows() ) \
             try { \
                 static_cast<void>(__VA_ARGS__); \
@@ -101,7 +103,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
     do { \
-        Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
         if( catchAssertionHandler.allowThrows() ) \
             try { \
                 static_cast<void>(expr); \
@@ -118,31 +120,41 @@
         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
     } while( false )
 
+#endif  // CATCH_CONFIG_DISABLE_EXCEPTIONS
 
 ///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
     do { \
-        Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \
         catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
     } while( false )
 
 ///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \
+    auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \
+    varName.captureValues( 0, __VA_ARGS__ )
+
+///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CATCH_INFO( macroName, log ) \
-    Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );
+    Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \
+    Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
 
 ///////////////////////////////////////////////////////////////////////////////
 // Although this is matcher-based, it can be used with just a string
 #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
     do { \
-        Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
         if( catchAssertionHandler.allowThrows() ) \
             try { \
                 static_cast<void>(__VA_ARGS__); \
                 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
             } \
             catch( ... ) { \
-                Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher ); \
+                Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \
             } \
         else \
             catchAssertionHandler.handleThrowingCallSkipped(); \
diff --git a/include/internal/catch_capture_matchers.cpp b/include/internal/catch_capture_matchers.cpp
index 7ef1597..6f32044 100644
--- a/include/internal/catch_capture_matchers.cpp
+++ b/include/internal/catch_capture_matchers.cpp
@@ -13,9 +13,9 @@
     using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
 
     // This is the general overload that takes a any string matcher
-    // There is another overload, in catch_assertinhandler.h/.cpp, that only takes a string and infers
+    // There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers
     // the Equals matcher (so the header does not mention matchers)
-    void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString  ) {
+    void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString  ) {
         std::string exceptionMessage = Catch::translateActiveException();
         MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString );
         handler.handleExpr( expr );
diff --git a/include/internal/catch_capture_matchers.h b/include/internal/catch_capture_matchers.h
index 3aeb276..0ced01d 100644
--- a/include/internal/catch_capture_matchers.h
+++ b/include/internal/catch_capture_matchers.h
@@ -11,8 +11,10 @@
 #include "catch_capture.hpp"
 #include "catch_matchers.h"
 #include "catch_matchers_floating.h"
+#include "catch_matchers_generic.hpp"
 #include "catch_matchers_string.h"
 #include "catch_matchers_vector.h"
+#include "catch_stringref.h"
 
 namespace Catch {
 
@@ -22,7 +24,7 @@
         MatcherT m_matcher;
         StringRef m_matcherString;
     public:
-        MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString )
+        MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString )
         :   ITransientExpression{ true, matcher.match( arg ) },
             m_arg( arg ),
             m_matcher( matcher ),
@@ -41,10 +43,10 @@
 
     using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
 
-    void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString  );
+    void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString  );
 
     template<typename ArgT, typename MatcherT>
-    auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString  ) -> MatchExpr<ArgT, MatcherT> {
+    auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString  ) -> MatchExpr<ArgT, MatcherT> {
         return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString );
     }
 
@@ -54,9 +56,9 @@
 ///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
     do { \
-        Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
-        CATCH_INTERNAL_TRY { \
-            catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \
+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
+        INTERNAL_CATCH_TRY { \
+            catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \
         } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
     } while( false )
@@ -65,14 +67,14 @@
 ///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \
     do { \
-        Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
         if( catchAssertionHandler.allowThrows() ) \
             try { \
                 static_cast<void>(__VA_ARGS__ ); \
                 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
             } \
             catch( exceptionType const& ex ) { \
-                catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher ) ); \
+                catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \
             } \
             catch( ... ) { \
                 catchAssertionHandler.handleUnexpectedInflightException(); \
diff --git a/include/internal/catch_commandline.cpp b/include/internal/catch_commandline.cpp
index c0231d1..66759eb 100644
--- a/include/internal/catch_commandline.cpp
+++ b/include/internal/catch_commandline.cpp
@@ -10,6 +10,9 @@
 
 #include "catch_string_manip.h"
 
+#include "catch_interfaces_registry_hub.h"
+#include "catch_interfaces_reporter.h"
+
 #include <fstream>
 #include <ctime>
 
@@ -20,9 +23,19 @@
         using namespace clara;
 
         auto const setWarning = [&]( std::string const& warning ) {
-                if( warning != "NoAssertions" )
+                auto warningSet = [&]() {
+                    if( warning == "NoAssertions" )
+                        return WarnAbout::NoAssertions;
+
+                    if ( warning == "NoTests" )
+                        return WarnAbout::NoTests;
+
+                    return WarnAbout::Nothing;
+                }();
+
+                if (warningSet == WarnAbout::Nothing)
                     return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" );
-                config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
+                config.warnings = static_cast<WarnAbout::What>( config.warnings | warningSet );
                 return ParserResult::ok( ParseResultType::Matched );
             };
         auto const loadTestNamesFromFile = [&]( std::string const& filename ) {
@@ -95,6 +108,18 @@
                 return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" );
             return ParserResult::ok( ParseResultType::Matched );
         };
+        auto const setReporter = [&]( std::string const& reporter ) {
+            IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
+
+            auto lcReporter = toLower( reporter );
+            auto result = factories.find( lcReporter );
+
+            if( factories.end() != result )
+                config.reporterName = lcReporter;
+            else
+                return ParserResult::runtimeError( "Unrecognized reporter, '" + reporter + "'. Check available with --list-reporters" );
+            return ParserResult::ok( ParseResultType::Matched );
+        };
 
         auto cli
             = ExeName( config.processName )
@@ -120,7 +145,7 @@
             | Opt( config.outputFilename, "filename" )
                 ["-o"]["--out"]
                 ( "output filename" )
-            | Opt( config.reporterNames, "name" )
+            | Opt( setReporter, "name" )
                 ["-r"]["--reporter"]
                 ( "reporter to use (defaults to console)" )
             | Opt( config.name, "name" )
diff --git a/include/internal/catch_common.cpp b/include/internal/catch_common.cpp
index c271146..b2fca4c 100644
--- a/include/internal/catch_common.cpp
+++ b/include/internal/catch_common.cpp
@@ -22,7 +22,9 @@
         return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
     }
     bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept {
-        return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0));
+        // We can assume that the same file will usually have the same pointer.
+        // Thus, if the pointers are the same, there is no point in calling the strcmp
+        return line < other.line || ( line == other.line && file != other.file && (std::strcmp(file, other.file) < 0));
     }
 
     std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h
index 8294a86..e474562 100644
--- a/include/internal/catch_common.h
+++ b/include/internal/catch_common.h
@@ -22,6 +22,10 @@
 #include <string>
 #include <cstdint>
 
+// We need a dummy global operator<< so we can bring it into Catch namespace later
+struct Catch_global_namespace_dummy {};
+std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy);
+
 namespace Catch {
 
     struct CaseSensitive { enum Choice {
@@ -48,10 +52,10 @@
             line( _line )
         {}
 
-        SourceLineInfo( SourceLineInfo const& other )        = default;
-        SourceLineInfo( SourceLineInfo && )                  = default;
-        SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
-        SourceLineInfo& operator = ( SourceLineInfo && )     = default;
+        SourceLineInfo( SourceLineInfo const& other )            = default;
+        SourceLineInfo& operator = ( SourceLineInfo const& )     = default;
+        SourceLineInfo( SourceLineInfo&& )              noexcept = default;
+        SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default;
 
         bool empty() const noexcept;
         bool operator == ( SourceLineInfo const& other ) const noexcept;
@@ -63,6 +67,11 @@
 
     std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
 
+    // Bring in operator<< from global namespace into Catch namespace
+    // This is necessary because the overload of operator<< above makes
+    // lookup stop at namespace Catch
+    using ::operator<<;
+
     // Use this in variadic streaming macros to allow
     //    >> +StreamEndStop
     // as well as
@@ -74,40 +83,10 @@
     T const& operator + ( T const& value, StreamEndStop ) {
         return value;
     }
-
-
-    // A replacement for the "throw" keyword which is illegal when
-    // exceptions are disabled with -fno-exceptions.
-    struct Exception {
-        template <typename E>
-        [[noreturn]] static void doThrow(E&& e) {
-#if CATCH_CONFIG_USE_EXCEPTIONS
-            throw std::forward<E>(e);
-#else
-            // "throw" keyword is unsupported when exceptions are disabled.
-            // Immediately terminate instead.
-            (void)e;  // error: unused parameter 'e' [-Werror,-Wunused-parameter]
-            std::terminate();
-#endif
-        }
-    };
 }
 
 #define CATCH_INTERNAL_LINEINFO \
     ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
 
-#if CATCH_CONFIG_USE_EXCEPTIONS
-#  define CATCH_INTERNAL_TRY try
-#  define CATCH_INTERNAL_CATCH( type, var) catch( type var )
-#  define CATCH_INTERNAL_CATCH_UNNAMED( type ) catch( type )
-#  define CATCH_INTERNAL_CATCH_ALL() catch( ... )
-#else
-// 'try' and 'catch' (and 'throw') keywords are illegal with -fno-exceptions.
-#  define CATCH_INTERNAL_TRY if ((true))
-#  define CATCH_INTERNAL_CATCH( typ, var ) while ((false)) for ( typename std::remove_reference<typ>::type var ; ; )
-#  define CATCH_INTERNAL_CATCH_UNNAMED( type ) while ((false))
-#  define CATCH_INTERNAL_CATCH_ALL() while ((false))
-#endif
-
 #endif // TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
 
diff --git a/include/internal/catch_compiler_capabilities.h b/include/internal/catch_compiler_capabilities.h
index 0ee2f49..012bf46 100644
--- a/include/internal/catch_compiler_capabilities.h
+++ b/include/internal/catch_compiler_capabilities.h
@@ -14,6 +14,7 @@
 // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
 // CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
 // CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
+// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled?
 // ****************
 // Note to maintainers: if new toggles are added please document them
 // in configuration.md, too
@@ -24,14 +25,15 @@
 // Many features, at point of detection, define an _INTERNAL_ macro, so they
 // can be combined, en-mass, with the _NO_ forms later.
 
+#include "catch_platform.h"
 
 #ifdef __cplusplus
 
-#  if __cplusplus >= 201402L
+#  if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
 #    define CATCH_CPP14_OR_GREATER
 #  endif
 
-#  if __cplusplus >= 201703L
+#  if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
 #    define CATCH_CPP17_OR_GREATER
 #  endif
 
@@ -56,25 +58,25 @@
 #       define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
             _Pragma( "clang diagnostic pop" )
 
-#if  !__has_feature(cxx_rtti)
-#    define CATCH_CONFIG_USE_RTTI 0
-#endif
-
-#if !__has_feature(cxx_exceptions)
-#    define CATCH_CONFIG_USE_EXCEPTIONS 0
-#endif
+#       define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
+            _Pragma( "clang diagnostic push" ) \
+            _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" )
+#       define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS \
+            _Pragma( "clang diagnostic pop" )
 
 #endif // __clang__
 
 
 ////////////////////////////////////////////////////////////////////////////////
+// Assume that non-Windows platforms support posix signals by default
+#if !defined(CATCH_PLATFORM_WINDOWS)
+    #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
 // We know some environments not to support full POSIX signals
-#if defined(__CYGWIN__) || defined(__QNX__)
-
-#   if !defined(CATCH_CONFIG_POSIX_SIGNALS)
-#       define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
-#   endif
-
+#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__)
+    #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
 #endif
 
 #ifdef __OS400__
@@ -83,13 +85,38 @@
 #endif
 
 ////////////////////////////////////////////////////////////////////////////////
+// Android somehow still does not support std::to_string
+#if defined(__ANDROID__)
+#    define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// Not all Windows environments support SEH properly
+#if defined(__MINGW32__)
+#    define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// PS4
+#if defined(__ORBIS__)
+#    define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
 // Cygwin
 #ifdef __CYGWIN__
 
 // Required for some versions of Cygwin to declare gettimeofday
 // see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
 #   define _BSD_SOURCE
+// some versions of cygwin (most) do not support std::to_string. Use the libstd check. 
+// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813
+# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
+	       && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
 
+#	define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
+
+# endif
 #endif // __CYGWIN__
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -109,9 +136,34 @@
 #    define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
 #  endif
 
+// MSVC traditional preprocessor needs some workaround for __VA_ARGS__
+// _MSVC_TRADITIONAL == 0 means new conformant preprocessor
+// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor
+#  if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
+#    define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#  endif
+
 #endif // _MSC_VER
 
 ////////////////////////////////////////////////////////////////////////////////
+// Check if we are compiled with -fno-exceptions or equivalent
+#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND)
+#  define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// DJGPP
+#ifdef __DJGPP__
+#  define CATCH_INTERNAL_CONFIG_NO_WCHAR
+#endif // __DJGPP__
+
+////////////////////////////////////////////////////////////////////////////////
+// Embarcadero C++Build
+#if defined(__BORLANDC__)
+    #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
 
 // Use of __COUNTER__ is suppressed during code analysis in
 // CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly
@@ -122,21 +174,93 @@
     #define CATCH_INTERNAL_CONFIG_COUNTER
 #endif
 
+////////////////////////////////////////////////////////////////////////////////
+// Check if string_view is available and usable
+// The check is split apart to work around v140 (VS2015) preprocessor issue...
+#if defined(__has_include)
+#if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER)
+#    define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW
+#endif
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// Check if optional is available and usable
+#if defined(__has_include)
+#  if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
+#    define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
+#  endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
+#endif // __has_include
+
+////////////////////////////////////////////////////////////////////////////////
+// Check if variant is available and usable
+#if defined(__has_include)
+#  if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
+#    if defined(__clang__) && (__clang_major__ < 8)
+       // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852
+       // fix should be in clang 8, workaround in libstdc++ 8.2
+#      include <ciso646>
+#      if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
+#        define CATCH_CONFIG_NO_CPP17_VARIANT
+#      else
+#        define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
+#      endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
+#    else
+#      define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
+#    endif // defined(__clang__) && (__clang_major__ < 8)
+#  endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
+#endif // __has_include
+
+
 #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
 #   define CATCH_CONFIG_COUNTER
 #endif
-#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH)
+#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH)
 #   define CATCH_CONFIG_WINDOWS_SEH
 #endif
 // This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
-#if !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
+#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
 #   define CATCH_CONFIG_POSIX_SIGNALS
 #endif
+// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions.
+#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR)
+#   define CATCH_CONFIG_WCHAR
+#endif
 
-#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_INTERNAL_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
+#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING)
+#    define CATCH_CONFIG_CPP11_TO_STRING
+#endif
+
+#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL)
+#  define CATCH_CONFIG_CPP17_OPTIONAL
+#endif
+
+#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
 #  define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
 #endif
 
+#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW)
+#  define CATCH_CONFIG_CPP17_STRING_VIEW
+#endif
+
+#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT)
+#  define CATCH_CONFIG_CPP17_VARIANT
+#endif
+
+#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
+#  define CATCH_INTERNAL_CONFIG_NEW_CAPTURE
+#endif
+
+#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE)
+#  define CATCH_CONFIG_NEW_CAPTURE
+#endif
+
+#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
+#  define CATCH_CONFIG_DISABLE_EXCEPTIONS
+#endif
+
+#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN)
+#  define CATCH_CONFIG_POLYFILL_ISNAN
+#endif
 
 #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
 #   define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
@@ -146,13 +270,23 @@
 #   define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
 #   define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
 #endif
-
-#if !defined(CATCH_CONFIG_USE_RTTI)
-#  define CATCH_CONFIG_USE_RTTI 1
+#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS)
+#   define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS
+#   define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
 #endif
 
-#if !defined(CATCH_CONFIG_USE_EXCEPTIONS)
-#  define CATCH_CONFIG_USE_EXCEPTIONS 1
+#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
+#define CATCH_TRY if ((true))
+#define CATCH_CATCH_ALL if ((false))
+#define CATCH_CATCH_ANON(type) if ((false))
+#else
+#define CATCH_TRY try
+#define CATCH_CATCH_ALL catch (...)
+#define CATCH_CATCH_ANON(type) catch (type)
+#endif
+
+#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR)
+#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
 #endif
 
 #endif // TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
diff --git a/include/internal/catch_config.cpp b/include/internal/catch_config.cpp
index 67d2b27..e8ad2a8 100644
--- a/include/internal/catch_config.cpp
+++ b/include/internal/catch_config.cpp
@@ -15,12 +15,16 @@
     :   m_data( data ),
         m_stream( openStream() )
     {
-        if( !data.testsOrTags.empty() ) {
-            TestSpecParser parser( ITagAliasRegistry::get() );
+        TestSpecParser parser(ITagAliasRegistry::get());
+        if (data.testsOrTags.empty()) {
+            parser.parse("~[.]"); // All not hidden tests
+        }
+        else {
+            m_hasTestFilters = true;
             for( auto const& testOrTags : data.testsOrTags )
                 parser.parse( testOrTags );
-            m_testSpec = parser.testSpec();
         }
+        m_testSpec = parser.testSpec();
     }
 
     std::string const& Config::getFilename() const {
@@ -33,11 +37,13 @@
     bool Config::listReporters() const      { return m_data.listReporters; }
 
     std::string Config::getProcessName() const { return m_data.processName; }
+    std::string const& Config::getReporterName() const { return m_data.reporterName; }
 
-    std::vector<std::string> const& Config::getReporterNames() const { return m_data.reporterNames; }
+    std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; }
     std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }
 
     TestSpec const& Config::testSpec() const { return m_testSpec; }
+    bool Config::hasTestFilters() const { return m_hasTestFilters; }
 
     bool Config::showHelp() const { return m_data.showHelp; }
 
@@ -46,7 +52,8 @@
     std::ostream& Config::stream() const               { return m_stream->stream(); }
     std::string Config::name() const                   { return m_data.name.empty() ? m_data.processName : m_data.name; }
     bool Config::includeSuccessfulResults() const      { return m_data.showSuccessfulTests; }
-    bool Config::warnAboutMissingAssertions() const    { return m_data.warnings & WarnAbout::NoAssertions; }
+    bool Config::warnAboutMissingAssertions() const    { return !!(m_data.warnings & WarnAbout::NoAssertions); }
+    bool Config::warnAboutNoTests() const              { return !!(m_data.warnings & WarnAbout::NoTests); }
     ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; }
     RunTests::InWhatOrder Config::runOrder() const     { return m_data.runOrder; }
     unsigned int Config::rngSeed() const               { return m_data.rngSeed; }
diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp
index fcaa050..7bafc9c 100644
--- a/include/internal/catch_config.hpp
+++ b/include/internal/catch_config.hpp
@@ -54,8 +54,12 @@
         std::string outputFilename;
         std::string name;
         std::string processName;
+#ifndef CATCH_CONFIG_DEFAULT_REPORTER
+#define CATCH_CONFIG_DEFAULT_REPORTER "console"
+#endif
+        std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER;
+#undef CATCH_CONFIG_DEFAULT_REPORTER
 
-        std::vector<std::string> reporterNames;
         std::vector<std::string> testsOrTags;
         std::vector<std::string> sectionsToRun;
     };
@@ -76,11 +80,13 @@
         bool listReporters() const;
 
         std::string getProcessName() const;
+        std::string const& getReporterName() const;
 
-        std::vector<std::string> const& getReporterNames() const;
+        std::vector<std::string> const& getTestsOrTags() const;
         std::vector<std::string> const& getSectionsToRun() const override;
 
         virtual TestSpec const& testSpec() const override;
+        bool hasTestFilters() const override;
 
         bool showHelp() const;
 
@@ -90,6 +96,7 @@
         std::string name() const override;
         bool includeSuccessfulResults() const override;
         bool warnAboutMissingAssertions() const override;
+        bool warnAboutNoTests() const override;
         ShowDurations::OrNot showDurations() const override;
         RunTests::InWhatOrder runOrder() const override;
         unsigned int rngSeed() const override;
@@ -107,6 +114,7 @@
 
         std::unique_ptr<IStream const> m_stream;
         TestSpec m_testSpec;
+        bool m_hasTestFilters = false;
     };
 
 } // end namespace Catch
diff --git a/include/internal/catch_console_colour.cpp b/include/internal/catch_console_colour.cpp
index f692b5c..07072db 100644
--- a/include/internal/catch_console_colour.cpp
+++ b/include/internal/catch_console_colour.cpp
@@ -160,7 +160,8 @@
 
     private:
         void setColour( const char* _escapeCode ) {
-            Catch::cout() << '\033' << _escapeCode;
+            getCurrentContext().getConfig()->stream()
+                << '\033' << _escapeCode;
         }
     };
 
@@ -169,7 +170,12 @@
 #ifdef CATCH_PLATFORM_MAC
             !isDebuggerActive() &&
 #endif
-            isatty(STDOUT_FILENO);
+#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
+            isatty(STDOUT_FILENO)
+#else
+            false
+#endif
+            ;
     }
     IColourImpl* platformColourInstance() {
         ErrnoGuard guard;
diff --git a/include/internal/catch_debug_console.cpp b/include/internal/catch_debug_console.cpp
index d817c56..5d25f65 100644
--- a/include/internal/catch_debug_console.cpp
+++ b/include/internal/catch_debug_console.cpp
@@ -9,21 +9,23 @@
 #include "catch_debug_console.h"
 #include "catch_stream.h"
 #include "catch_platform.h"
+#include "catch_windows_h_proxy.h"
 
 #ifdef CATCH_PLATFORM_WINDOWS
 
-#include "catch_windows_h_proxy.h"
-
     namespace Catch {
         void writeToDebugConsole( std::string const& text ) {
             ::OutputDebugStringA( text.c_str() );
         }
     }
+
 #else
+
     namespace Catch {
         void writeToDebugConsole( std::string const& text ) {
             // !TBD: Need a version for Mac/ XCode and other IDEs
             Catch::cout() << text;
         }
     }
+
 #endif // Platform
diff --git a/include/internal/catch_debugger.h b/include/internal/catch_debugger.h
index 7541984..db3ff68 100644
--- a/include/internal/catch_debugger.h
+++ b/include/internal/catch_debugger.h
@@ -38,12 +38,9 @@
 #endif
 
 #ifdef CATCH_TRAP
-    #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
+    #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }()
 #else
-    namespace Catch {
-        inline void doNothing() {}
-    }
-    #define CATCH_BREAK_INTO_DEBUGGER() Catch::doNothing()
+    #define CATCH_BREAK_INTO_DEBUGGER() []{}()
 #endif
 
 #endif // TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
diff --git a/include/internal/catch_decomposer.h b/include/internal/catch_decomposer.h
index 618a250..08075f0 100644
--- a/include/internal/catch_decomposer.h
+++ b/include/internal/catch_decomposer.h
@@ -10,6 +10,7 @@
 
 #include "catch_tostring.h"
 #include "catch_stringref.h"
+#include "catch_meta.hpp"
 
 #include <iosfwd>
 
@@ -19,6 +20,7 @@
 #pragma warning(disable:4018) // more "signed/unsigned mismatch"
 #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
 #pragma warning(disable:4180) // qualifier applied to function type has no meaning
+#pragma warning(disable:4800) // Forcing result to true or false
 #endif
 
 namespace Catch {
@@ -62,6 +64,62 @@
             m_op( op ),
             m_rhs( rhs )
         {}
+
+        template<typename T>
+        auto operator && ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
+            static_assert(always_false<T>::value,
+            "chained comparisons are not supported inside assertions, "
+            "wrap the expression inside parentheses, or decompose it");
+        }
+
+        template<typename T>
+        auto operator || ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
+            static_assert(always_false<T>::value,
+            "chained comparisons are not supported inside assertions, "
+            "wrap the expression inside parentheses, or decompose it");
+        }
+
+        template<typename T>
+        auto operator == ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
+            static_assert(always_false<T>::value,
+            "chained comparisons are not supported inside assertions, "
+            "wrap the expression inside parentheses, or decompose it");
+        }
+
+        template<typename T>
+        auto operator != ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
+            static_assert(always_false<T>::value,
+            "chained comparisons are not supported inside assertions, "
+            "wrap the expression inside parentheses, or decompose it");
+        }
+
+        template<typename T>
+        auto operator > ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
+            static_assert(always_false<T>::value,
+            "chained comparisons are not supported inside assertions, "
+            "wrap the expression inside parentheses, or decompose it");
+        }
+
+        template<typename T>
+        auto operator < ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
+            static_assert(always_false<T>::value,
+            "chained comparisons are not supported inside assertions, "
+            "wrap the expression inside parentheses, or decompose it");
+        }
+
+        template<typename T>
+        auto operator >= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
+            static_assert(always_false<T>::value,
+            "chained comparisons are not supported inside assertions, "
+            "wrap the expression inside parentheses, or decompose it");
+        }
+
+        template<typename T>
+        auto operator <= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
+            static_assert(always_false<T>::value,
+            "chained comparisons are not supported inside assertions, "
+            "wrap the expression inside parentheses, or decompose it");
+        }
     };
 
     template<typename LhsT>
@@ -74,7 +132,7 @@
 
     public:
         explicit UnaryExpr( LhsT lhs )
-        :   ITransientExpression{ false, lhs ? true : false },
+        :   ITransientExpression{ false, static_cast<bool>(lhs) },
             m_lhs( lhs )
         {}
     };
@@ -143,6 +201,20 @@
             return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };
         }
 
+        template<typename RhsT>
+        auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {
+            static_assert(always_false<RhsT>::value,
+            "operator&& is not supported inside assertions, "
+            "wrap the expression inside parentheses, or decompose it");
+        }
+
+        template<typename RhsT>
+        auto operator || ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {
+            static_assert(always_false<RhsT>::value,
+            "operator|| is not supported inside assertions, "
+            "wrap the expression inside parentheses, or decompose it");
+        }
+
         auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
             return UnaryExpr<LhsT>{ m_lhs };
         }
diff --git a/include/internal/catch_default_main.hpp b/include/internal/catch_default_main.hpp
index 4372e9c..17ad090 100644
--- a/include/internal/catch_default_main.hpp
+++ b/include/internal/catch_default_main.hpp
@@ -12,7 +12,7 @@
 
 #ifndef __OBJC__
 
-#if defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
+#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
 // Standard C/C++ Win32 Unicode wmain entry point
 extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {
 #else
diff --git a/include/internal/catch_enforce.cpp b/include/internal/catch_enforce.cpp
new file mode 100644
index 0000000..f4db1c1
--- /dev/null
+++ b/include/internal/catch_enforce.cpp
@@ -0,0 +1,19 @@
+/*
+ *  Created by Martin on 03/09/2018.
+ *
+ *  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_enforce.h"
+
+namespace Catch {
+#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER)
+    [[noreturn]]
+    void throw_exception(std::exception const& e) {
+        Catch::cerr() << "Catch will terminate because it needed to throw an exception.\n"
+                      << "The message was: " << e.what() << '\n';
+        std::terminate();
+    }
+#endif
+} // namespace Catch;
diff --git a/include/internal/catch_enforce.h b/include/internal/catch_enforce.h
index cd4202a..0069402 100644
--- a/include/internal/catch_enforce.h
+++ b/include/internal/catch_enforce.h
@@ -8,18 +8,35 @@
 #define TWOBLUECUBES_CATCH_ENFORCE_H_INCLUDED
 
 #include "catch_common.h"
+#include "catch_compiler_capabilities.h"
 #include "catch_stream.h"
 
+
 #include <stdexcept>
-#include <iosfwd>
+
+namespace Catch {
+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
+    template <typename Ex>
+    [[noreturn]]
+    void throw_exception(Ex const& e) {
+        throw e;
+    }
+#else // ^^ Exceptions are enabled //  Exceptions are disabled vv
+    [[noreturn]]
+    void throw_exception(std::exception const& e);
+#endif
+} // namespace Catch;
 
 #define CATCH_PREPARE_EXCEPTION( type, msg ) \
-    type( static_cast<std::ostringstream&&>( Catch::ReusableStringStream().get() << msg ).str() )
+    type( ( Catch::ReusableStringStream() << msg ).str() )
 #define CATCH_INTERNAL_ERROR( msg ) \
-    Exception::doThrow( CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg) );
+    Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg))
 #define CATCH_ERROR( msg ) \
-    Exception::doThrow( CATCH_PREPARE_EXCEPTION( std::domain_error, msg ) )
+    Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::domain_error, msg ))
+#define CATCH_RUNTIME_ERROR( msg ) \
+    Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::runtime_error, msg ))
 #define CATCH_ENFORCE( condition, msg ) \
     do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false)
 
+
 #endif // TWOBLUECUBES_CATCH_ENFORCE_H_INCLUDED
diff --git a/include/internal/catch_exception_translator_registry.cpp b/include/internal/catch_exception_translator_registry.cpp
index f048f67..cef36e5 100644
--- a/include/internal/catch_exception_translator_registry.cpp
+++ b/include/internal/catch_exception_translator_registry.cpp
@@ -6,8 +6,10 @@
  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  */
 
-#include "catch_assertionhandler.h"
 #include "catch_exception_translator_registry.h"
+#include "catch_assertionhandler.h"
+#include "catch_compiler_capabilities.h"
+#include "catch_enforce.h"
 
 #ifdef __OBJC__
 #import "Foundation/Foundation.h"
@@ -22,8 +24,9 @@
         m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) );
     }
 
+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
     std::string ExceptionTranslatorRegistry::translateActiveException() const {
-        CATCH_INTERNAL_TRY {
+        try {
 #ifdef __OBJC__
             // In Objective-C try objective-c exceptions first
             @try {
@@ -47,27 +50,40 @@
             return tryTranslators();
 #endif
         }
-        CATCH_INTERNAL_CATCH_UNNAMED( TestFailureException& ) {
+        catch( TestFailureException& ) {
             std::rethrow_exception(std::current_exception());
         }
-        CATCH_INTERNAL_CATCH( std::exception&, ex ) {
+        catch( std::exception& ex ) {
             return ex.what();
         }
-        CATCH_INTERNAL_CATCH( std::string&, msg ) {
+        catch( std::string& msg ) {
             return msg;
         }
-        CATCH_INTERNAL_CATCH( const char*, msg ) {
+        catch( const char* msg ) {
             return msg;
         }
-        CATCH_INTERNAL_CATCH_ALL() {
+        catch(...) {
             return "Unknown exception";
         }
     }
 
     std::string ExceptionTranslatorRegistry::tryTranslators() const {
-        if( m_translators.empty() )
+        if (m_translators.empty()) {
             std::rethrow_exception(std::current_exception());
-        else
-            return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
+        } else {
+            return m_translators[0]->translate(m_translators.begin() + 1, m_translators.end());
+        }
     }
+
+#else // ^^ Exceptions are enabled // Exceptions are disabled vv
+    std::string ExceptionTranslatorRegistry::translateActiveException() const {
+        CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
+    }
+
+    std::string ExceptionTranslatorRegistry::tryTranslators() const {
+        CATCH_INTERNAL_ERROR("Attempted to use exception translators under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
+    }
+#endif
+
+
 }
diff --git a/include/internal/catch_fatal_condition.cpp b/include/internal/catch_fatal_condition.cpp
index 55ee539..24e16d3 100644
--- a/include/internal/catch_fatal_condition.cpp
+++ b/include/internal/catch_fatal_condition.cpp
@@ -17,24 +17,18 @@
 #    pragma GCC diagnostic ignored "-Wmissing-field-initializers"
 #endif
 
-#if (defined(CATCH_PLATFORM_WINDOWS) && defined(CATCH_CONFIG_WINDOWS_SEH)) || defined(CATCH_CONFIG_POSIX_SIGNALS)
+#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
+
 namespace {
     // Report the error condition
     void reportFatal( char const * const message ) {
         Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
     }
 }
-#endif
 
-#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
+#endif // signals/SEH handling
 
-#  if !defined ( CATCH_CONFIG_WINDOWS_SEH )
-
-namespace Catch {
-    void FatalConditionHandler::reset() {}
-}
-
-#  else // CATCH_CONFIG_WINDOWS_SEH is defined
+#if defined( CATCH_CONFIG_WINDOWS_SEH )
 
 namespace Catch {
     struct SignalDefs { DWORD id; const char* name; };
@@ -74,7 +68,6 @@
 
     void FatalConditionHandler::reset() {
         if (isSet) {
-            // Unregister handler and restore the old guarantee
             RemoveVectoredExceptionHandler(exceptionHandlerHandle);
             SetThreadStackGuarantee(&guaranteeSize);
             exceptionHandlerHandle = nullptr;
@@ -93,20 +86,7 @@
 
 } // namespace Catch
 
-#  endif // CATCH_CONFIG_WINDOWS_SEH
-
-#else // Not Windows - assumed to be POSIX compatible //////////////////////////
-
-#  if !defined(CATCH_CONFIG_POSIX_SIGNALS)
-
-namespace Catch {
-    void FatalConditionHandler::reset() {}
-}
-
-
-#  else // CATCH_CONFIG_POSIX_SIGNALS is defined
-
-#include <signal.h>
+#elif defined( CATCH_CONFIG_POSIX_SIGNALS )
 
 namespace Catch {
 
@@ -114,6 +94,11 @@
         int id;
         const char* name;
     };
+    
+    // 32kb for the alternate stack seems to be sufficient. However, this value
+    // is experimentally determined, so that's not guaranteed.
+    constexpr static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
+
     static SignalDefs signalDefs[] = {
         { SIGINT,  "SIGINT - Terminal interrupt signal" },
         { SIGILL,  "SIGILL - Illegal instruction signal" },
@@ -141,7 +126,7 @@
         isSet = true;
         stack_t sigStack;
         sigStack.ss_sp = altStackMem;
-        sigStack.ss_size = SIGSTKSZ;
+        sigStack.ss_size = sigStackSize;
         sigStack.ss_flags = 0;
         sigaltstack(&sigStack, &oldSigStack);
         struct sigaction sa = { };
@@ -173,14 +158,18 @@
     bool FatalConditionHandler::isSet = false;
     struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
     stack_t FatalConditionHandler::oldSigStack = {};
-    char FatalConditionHandler::altStackMem[SIGSTKSZ] = {};
+    char FatalConditionHandler::altStackMem[sigStackSize] = {};
 
 
 } // namespace Catch
 
-#  endif // CATCH_CONFIG_POSIX_SIGNALS
+#else
 
-#endif // not Windows
+namespace Catch {
+    void FatalConditionHandler::reset() {}
+}
+
+#endif // signals/SEH handling
 
 #if defined(__GNUC__)
 #    pragma GCC diagnostic pop
diff --git a/include/internal/catch_fatal_condition.h b/include/internal/catch_fatal_condition.h
index 9977702..a64fa62 100644
--- a/include/internal/catch_fatal_condition.h
+++ b/include/internal/catch_fatal_condition.h
@@ -9,23 +9,12 @@
 #ifndef TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
 #define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
 
-#include <string>
 #include "catch_platform.h"
 #include "catch_compiler_capabilities.h"
-
-
-#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
 #include "catch_windows_h_proxy.h"
 
-#  if !defined ( CATCH_CONFIG_WINDOWS_SEH )
 
-namespace Catch {
-    struct FatalConditionHandler {
-        void reset();
-    };
-}
-
-#  else // CATCH_CONFIG_WINDOWS_SEH is defined
+#if defined( CATCH_CONFIG_WINDOWS_SEH )
 
 namespace Catch {
 
@@ -44,20 +33,7 @@
 
 } // namespace Catch
 
-#  endif // CATCH_CONFIG_WINDOWS_SEH
-
-#else // Not Windows - assumed to be POSIX compatible //////////////////////////
-
-#  if !defined(CATCH_CONFIG_POSIX_SIGNALS)
-
-namespace Catch {
-    struct FatalConditionHandler {
-        void reset();
-    };
-}
-
-
-#  else // CATCH_CONFIG_POSIX_SIGNALS is defined
+#elif defined ( CATCH_CONFIG_POSIX_SIGNALS )
 
 #include <signal.h>
 
@@ -66,7 +42,7 @@
     struct FatalConditionHandler {
 
         static bool isSet;
-        static struct sigaction oldSigActions[];// [sizeof(signalDefs) / sizeof(SignalDefs)];
+        static struct sigaction oldSigActions[];
         static stack_t oldSigStack;
         static char altStackMem[];
 
@@ -79,8 +55,15 @@
 
 } // namespace Catch
 
-#  endif // CATCH_CONFIG_POSIX_SIGNALS
 
-#endif // not Windows
+#else
+
+namespace Catch {
+    struct FatalConditionHandler {
+        void reset();
+    };
+}
+
+#endif
 
 #endif // TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
diff --git a/include/internal/catch_generators.cpp b/include/internal/catch_generators.cpp
new file mode 100644
index 0000000..5fbe2d2
--- /dev/null
+++ b/include/internal/catch_generators.cpp
@@ -0,0 +1,32 @@
+/*
+ *  Created by Phil Nash on 15/6/2018.
+ *
+ *  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_generators.hpp"
+#include "catch_random_number_generator.h"
+#include "catch_interfaces_capture.h"
+
+#include <limits>
+#include <set>
+
+namespace Catch {
+
+IGeneratorTracker::~IGeneratorTracker() {}
+
+const char* GeneratorException::what() const noexcept {
+    return m_msg;
+}
+
+namespace Generators {
+
+    GeneratorUntypedBase::~GeneratorUntypedBase() {}
+
+    auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
+        return getResultCapture().acquireGeneratorTracker( lineInfo );
+    }
+
+} // namespace Generators
+} // namespace Catch
diff --git a/include/internal/catch_generators.hpp b/include/internal/catch_generators.hpp
new file mode 100644
index 0000000..40e434e
--- /dev/null
+++ b/include/internal/catch_generators.hpp
@@ -0,0 +1,207 @@
+/*
+ *  Created by Phil Nash on 15/6/2018.
+ *
+ *  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_GENERATORS_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
+
+#include "catch_interfaces_generatortracker.h"
+#include "catch_common.h"
+#include "catch_enforce.h"
+
+#include <memory>
+#include <vector>
+#include <cassert>
+
+#include <utility>
+#include <exception>
+
+namespace Catch {
+
+class GeneratorException : public std::exception {
+    const char* const m_msg = "";
+
+public:
+    GeneratorException(const char* msg):
+        m_msg(msg)
+    {}
+
+    const char* what() const noexcept override final;
+};
+
+namespace Generators {
+
+    // !TBD move this into its own location?
+    namespace pf{
+        template<typename T, typename... Args>
+        std::unique_ptr<T> make_unique( Args&&... args ) {
+            return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+        }
+    }
+
+    template<typename T>
+    struct IGenerator : GeneratorUntypedBase {
+        virtual ~IGenerator() = default;
+
+        // Returns the current element of the generator
+        //
+        // \Precondition The generator is either freshly constructed,
+        // or the last call to `next()` returned true
+        virtual T const& get() const = 0;
+        using type = T;
+    };
+
+    template<typename T>
+    class SingleValueGenerator final : public IGenerator<T> {
+        T m_value;
+    public:
+        SingleValueGenerator(T const& value) : m_value( value ) {}
+        SingleValueGenerator(T&& value) : m_value(std::move(value)) {}
+
+        T const& get() const override {
+            return m_value;
+        }
+        bool next() override {
+            return false;
+        }
+    };
+
+    template<typename T>
+    class FixedValuesGenerator final : public IGenerator<T> {
+        std::vector<T> m_values;
+        size_t m_idx = 0;
+    public:
+        FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {}
+
+        T const& get() const override {
+            return m_values[m_idx];
+        }
+        bool next() override {
+            ++m_idx;
+            return m_idx < m_values.size();
+        }
+    };
+
+    template <typename T>
+    class GeneratorWrapper final {
+        std::unique_ptr<IGenerator<T>> m_generator;
+    public:
+        GeneratorWrapper(std::unique_ptr<IGenerator<T>> generator):
+            m_generator(std::move(generator))
+        {}
+        T const& get() const {
+            return m_generator->get();
+        }
+        bool next() {
+            return m_generator->next();
+        }
+    };
+
+    template <typename T>
+    GeneratorWrapper<T> value(T&& value) {
+        return GeneratorWrapper<T>(pf::make_unique<SingleValueGenerator<T>>(std::forward<T>(value)));
+    }
+    template <typename T>
+    GeneratorWrapper<T> values(std::initializer_list<T> values) {
+        return GeneratorWrapper<T>(pf::make_unique<FixedValuesGenerator<T>>(values));
+    }
+
+    template<typename T>
+    class Generators : public IGenerator<T> {
+        std::vector<GeneratorWrapper<T>> m_generators;
+        size_t m_current = 0;
+
+        void populate(GeneratorWrapper<T>&& generator) {
+            m_generators.emplace_back(std::move(generator));
+        }
+        void populate(T&& val) {
+            m_generators.emplace_back(value(std::move(val)));
+        }
+        template<typename U>
+        void populate(U&& val) {
+            populate(T(std::move(val)));
+        }
+        template<typename U, typename... Gs>
+        void populate(U&& valueOrGenerator, Gs... moreGenerators) {
+            populate(std::forward<U>(valueOrGenerator));
+            populate(std::forward<Gs>(moreGenerators)...);
+        }
+
+    public:
+        template <typename... Gs>
+        Generators(Gs... moreGenerators) {
+            m_generators.reserve(sizeof...(Gs));
+            populate(std::forward<Gs>(moreGenerators)...);
+        }
+
+        T const& get() const override {
+            return m_generators[m_current].get();
+        }
+
+        bool next() override {
+            if (m_current >= m_generators.size()) {
+                return false;
+            }
+            const bool current_status = m_generators[m_current].next();
+            if (!current_status) {
+                ++m_current;
+            }
+            return m_current < m_generators.size();
+        }
+    };
+
+
+    template<typename... Ts>
+    GeneratorWrapper<std::tuple<Ts...>> table( std::initializer_list<std::tuple<typename std::decay<Ts>::type...>> tuples ) {
+        return values<std::tuple<Ts...>>( tuples );
+    }
+
+    // Tag type to signal that a generator sequence should convert arguments to a specific type
+    template <typename T>
+    struct as {};
+
+    template<typename T, typename... Gs>
+    auto makeGenerators( GeneratorWrapper<T>&& generator, Gs... moreGenerators ) -> Generators<T> {
+        return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...);
+    }
+    template<typename T>
+    auto makeGenerators( GeneratorWrapper<T>&& generator ) -> Generators<T> {
+        return Generators<T>(std::move(generator));
+    }
+    template<typename T, typename... Gs>
+    auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators<T> {
+        return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
+    }
+    template<typename T, typename U, typename... Gs>
+    auto makeGenerators( as<T>, U&& val, Gs... moreGenerators ) -> Generators<T> {
+        return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
+    }
+
+    auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&;
+
+    template<typename L>
+    // Note: The type after -> is weird, because VS2015 cannot parse
+    //       the expression used in the typedef inside, when it is in
+    //       return type. Yeah.
+    auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) {
+        using UnderlyingType = typename decltype(generatorExpression())::type;
+
+        IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo );
+        if (!tracker.hasGenerator()) {
+            tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression()));
+        }
+
+        auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker.getGenerator() );
+        return generator.get();
+    }
+
+} // namespace Generators
+} // namespace Catch
+
+#define GENERATE( ... ) \
+    Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, []{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
+
+
+#endif // TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
diff --git a/include/internal/catch_generators_generic.hpp b/include/internal/catch_generators_generic.hpp
new file mode 100644
index 0000000..2226dbc
--- /dev/null
+++ b/include/internal/catch_generators_generic.hpp
@@ -0,0 +1,230 @@
+/*
+ *  Created by Martin on 23/2/2019.
+ *
+ *  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_GENERATORS_GENERIC_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_GENERATORS_GENERIC_HPP_INCLUDED
+
+#include "catch_generators.hpp"
+
+namespace Catch {
+namespace Generators {
+
+    template <typename T>
+    class TakeGenerator : public IGenerator<T> {
+        GeneratorWrapper<T> m_generator;
+        size_t m_returned = 0;
+        size_t m_target;
+    public:
+        TakeGenerator(size_t target, GeneratorWrapper<T>&& generator):
+            m_generator(std::move(generator)),
+            m_target(target)
+        {
+            assert(target != 0 && "Empty generators are not allowed");
+        }
+        T const& get() const override {
+            return m_generator.get();
+        }
+        bool next() override {
+            ++m_returned;
+            if (m_returned >= m_target) {
+                return false;
+            }
+
+            const auto success = m_generator.next();
+            // If the underlying generator does not contain enough values
+            // then we cut short as well
+            if (!success) {
+                m_returned = m_target;
+            }
+            return success;
+        }
+    };
+
+    template <typename T>
+    GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator) {
+        return GeneratorWrapper<T>(pf::make_unique<TakeGenerator<T>>(target, std::move(generator)));
+    }
+
+
+    template <typename T, typename Predicate>
+    class FilterGenerator : public IGenerator<T> {
+        GeneratorWrapper<T> m_generator;
+        Predicate m_predicate;
+    public:
+        template <typename P = Predicate>
+        FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator):
+            m_generator(std::move(generator)),
+            m_predicate(std::forward<P>(pred))
+        {
+            if (!m_predicate(m_generator.get())) {
+                // It might happen that there are no values that pass the
+                // filter. In that case we throw an exception.
+                auto has_initial_value = next();
+                if (!has_initial_value) {
+                    Catch::throw_exception(GeneratorException("No valid value found in filtered generator"));
+                }
+            }
+        }
+
+        T const& get() const override {
+            return m_generator.get();
+        }
+
+        bool next() override {
+            bool success = m_generator.next();
+            if (!success) {
+                return false;
+            }
+            while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true);
+            return success;
+        }
+    };
+
+
+    template <typename T, typename Predicate>
+    GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) {
+        return GeneratorWrapper<T>(std::unique_ptr<IGenerator<T>>(pf::make_unique<FilterGenerator<T, Predicate>>(std::forward<Predicate>(pred), std::move(generator))));
+    }
+
+    template <typename T>
+    class RepeatGenerator : public IGenerator<T> {
+        GeneratorWrapper<T> m_generator;
+        mutable std::vector<T> m_returned;
+        size_t m_target_repeats;
+        size_t m_current_repeat = 0;
+        size_t m_repeat_index = 0;
+    public:
+        RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator):
+            m_generator(std::move(generator)),
+            m_target_repeats(repeats)
+        {
+            assert(m_target_repeats > 0 && "Repeat generator must repeat at least once");
+        }
+
+        T const& get() const override {
+            if (m_current_repeat == 0) {
+                m_returned.push_back(m_generator.get());
+                return m_returned.back();
+            }
+            return m_returned[m_repeat_index];
+        }
+
+        bool next() override {
+            // There are 2 basic cases:
+            // 1) We are still reading the generator
+            // 2) We are reading our own cache
+
+            // In the first case, we need to poke the underlying generator.
+            // If it happily moves, we are left in that state, otherwise it is time to start reading from our cache
+            if (m_current_repeat == 0) {
+                const auto success = m_generator.next();
+                if (!success) {
+                    ++m_current_repeat;
+                }
+                return m_current_repeat < m_target_repeats;
+            }
+
+            // In the second case, we need to move indices forward and check that we haven't run up against the end
+            ++m_repeat_index;
+            if (m_repeat_index == m_returned.size()) {
+                m_repeat_index = 0;
+                ++m_current_repeat;
+            }
+            return m_current_repeat < m_target_repeats;
+        }
+    };
+
+    template <typename T>
+    GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) {
+        return GeneratorWrapper<T>(pf::make_unique<RepeatGenerator<T>>(repeats, std::move(generator)));
+    }
+
+    template <typename T, typename U, typename Func>
+    class MapGenerator : public IGenerator<T> {
+        // TBD: provide static assert for mapping function, for friendly error message
+        GeneratorWrapper<U> m_generator;
+        Func m_function;
+        // To avoid returning dangling reference, we have to save the values
+        T m_cache;
+    public:
+        template <typename F2 = Func>
+        MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) :
+            m_generator(std::move(generator)),
+            m_function(std::forward<F2>(function)),
+            m_cache(m_function(m_generator.get()))
+        {}
+
+        T const& get() const override {
+            return m_cache;
+        }
+        bool next() override {
+            const auto success = m_generator.next();
+            if (success) {
+                m_cache = m_function(m_generator.get());
+            }
+            return success;
+        }
+    };
+
+    template <typename T, typename U, typename Func>
+    GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
+        return GeneratorWrapper<T>(
+            pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))
+        );
+    }
+    template <typename T, typename Func>
+    GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<T>&& generator) {
+        return GeneratorWrapper<T>(
+            pf::make_unique<MapGenerator<T, T, Func>>(std::forward<Func>(function), std::move(generator))
+        );
+    }
+
+    template <typename T>
+    class ChunkGenerator final : public IGenerator<std::vector<T>> {
+        std::vector<T> m_chunk;
+        size_t m_chunk_size;
+        GeneratorWrapper<T> m_generator;
+        bool m_used_up = false;
+    public:
+        ChunkGenerator(size_t size, GeneratorWrapper<T> generator) :
+            m_chunk_size(size), m_generator(std::move(generator))
+        {
+            m_chunk.reserve(m_chunk_size);
+            m_chunk.push_back(m_generator.get());
+            for (size_t i = 1; i < m_chunk_size; ++i) {
+                if (!m_generator.next()) {
+                    Catch::throw_exception(GeneratorException("Not enough values to initialize the first chunk"));
+                }
+                m_chunk.push_back(m_generator.get());
+            }
+        }
+        std::vector<T> const& get() const override {
+            return m_chunk;
+        }
+        bool next() override {
+            m_chunk.clear();
+            for (size_t idx = 0; idx < m_chunk_size; ++idx) {
+                if (!m_generator.next()) {
+                    return false;
+                }
+                m_chunk.push_back(m_generator.get());
+            }
+            return true;
+        }
+    };
+
+    template <typename T>
+    GeneratorWrapper<std::vector<T>> chunk(size_t size, GeneratorWrapper<T>&& generator) {
+        return GeneratorWrapper<std::vector<T>>(
+            pf::make_unique<ChunkGenerator<T>>(size, std::move(generator))
+        );
+    }
+
+} // namespace Generators
+} // namespace Catch
+
+
+#endif // TWOBLUECUBES_CATCH_GENERATORS_GENERIC_HPP_INCLUDED
diff --git a/include/internal/catch_generators_specific.hpp b/include/internal/catch_generators_specific.hpp
new file mode 100644
index 0000000..7aae06b
--- /dev/null
+++ b/include/internal/catch_generators_specific.hpp
@@ -0,0 +1,135 @@
+/*
+ *  Created by Martin on 15/6/2018.
+ *
+ *  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_GENERATORS_SPECIFIC_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_GENERATORS_SPECIFIC_HPP_INCLUDED
+
+#include "catch_context.h"
+#include "catch_generators.hpp"
+#include "catch_interfaces_config.h"
+
+#include <random>
+
+namespace Catch {
+namespace Generators {
+
+template <typename Float>
+class RandomFloatingGenerator final : public IGenerator<Float> {
+    // FIXME: What is the right seed?
+    std::minstd_rand m_rand;
+    std::uniform_real_distribution<Float> m_dist;
+    Float m_current_number;
+public:
+
+    RandomFloatingGenerator(Float a, Float b):
+        m_rand(getCurrentContext().getConfig()->rngSeed()),
+        m_dist(a, b) {
+        static_cast<void>(next());
+    }
+
+    Float const& get() const override {
+        return m_current_number;
+    }
+    bool next() override {
+        m_current_number = m_dist(m_rand);
+        return true;
+    }
+};
+
+template <typename Integer>
+class RandomIntegerGenerator final : public IGenerator<Integer> {
+    std::minstd_rand m_rand;
+    std::uniform_int_distribution<Integer> m_dist;
+    Integer m_current_number;
+public:
+
+    RandomIntegerGenerator(Integer a, Integer b):
+        m_rand(getCurrentContext().getConfig()->rngSeed()),
+        m_dist(a, b) {
+        static_cast<void>(next());
+    }
+
+    Integer const& get() const override {
+        return m_current_number;
+    }
+    bool next() override {
+        m_current_number = m_dist(m_rand);
+        return true;
+    }
+};
+
+// TODO: Ideally this would be also constrained against the various char types,
+//       but I don't expect users to run into that in practice.
+template <typename T>
+typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value,
+GeneratorWrapper<T>>::type
+random(T a, T b) {
+    return GeneratorWrapper<T>(
+        pf::make_unique<RandomIntegerGenerator<T>>(a, b)
+    );
+}
+
+template <typename T>
+typename std::enable_if<std::is_floating_point<T>::value,
+GeneratorWrapper<T>>::type
+random(T a, T b) {
+    return GeneratorWrapper<T>(
+        pf::make_unique<RandomFloatingGenerator<T>>(a, b)
+    );
+}
+
+
+template <typename T>
+class RangeGenerator final : public IGenerator<T> {
+    T m_current;
+    T m_end;
+    T m_step;
+    bool m_positive;
+
+public:
+    RangeGenerator(T const& start, T const& end, T const& step):
+        m_current(start),
+        m_end(end),
+        m_step(step),
+        m_positive(m_step > T(0))
+    {
+        assert(m_current != m_end && "Range start and end cannot be equal");
+        assert(m_step != T(0) && "Step size cannot be zero");
+        assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && "Step moves away from end");
+    }
+
+    RangeGenerator(T const& start, T const& end):
+        RangeGenerator(start, end, (start < end) ? T(1) : T(-1))
+    {}
+
+    T const& get() const override {
+        return m_current;
+    }
+
+    bool next() override {
+        m_current += m_step;
+        return (m_positive) ? (m_current < m_end) : (m_current > m_end);
+    }
+};
+
+template <typename T>
+GeneratorWrapper<T> range(T const& start, T const& end, T const& step) {
+    static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer");
+    return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end, step));
+}
+
+template <typename T>
+GeneratorWrapper<T> range(T const& start, T const& end) {
+    static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer");
+    return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end));
+}
+
+
+} // namespace Generators
+} // namespace Catch
+
+
+#endif // TWOBLUECUBES_CATCH_GENERATORS_SPECIFIC_HPP_INCLUDED
diff --git a/include/internal/catch_interfaces_capture.h b/include/internal/catch_interfaces_capture.h
index 4d091f8..36f27a3 100644
--- a/include/internal/catch_interfaces_capture.h
+++ b/include/internal/catch_interfaces_capture.h
@@ -20,12 +20,15 @@
     struct SectionInfo;
     struct SectionEndInfo;
     struct MessageInfo;
+    struct MessageBuilder;
     struct Counts;
     struct BenchmarkInfo;
     struct BenchmarkStats;
     struct AssertionReaction;
+    struct SourceLineInfo;
 
     struct ITransientExpression;
+    struct IGeneratorTracker;
 
     struct IResultCapture {
 
@@ -36,12 +39,16 @@
         virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
         virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
 
+        virtual auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0;
+
         virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0;
         virtual void benchmarkEnded( BenchmarkStats const& stats ) = 0;
 
         virtual void pushScopedMessage( MessageInfo const& message ) = 0;
         virtual void popScopedMessage( MessageInfo const& message ) = 0;
 
+        virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0;
+
         virtual void handleFatalErrorCondition( StringRef message ) = 0;
 
         virtual void handleExpr
diff --git a/include/internal/catch_interfaces_config.h b/include/internal/catch_interfaces_config.h
index 2584ccc..f509c7e 100644
--- a/include/internal/catch_interfaces_config.h
+++ b/include/internal/catch_interfaces_config.h
@@ -25,7 +25,8 @@
 
     struct WarnAbout { enum What {
         Nothing = 0x00,
-        NoAssertions = 0x01
+        NoAssertions = 0x01,
+        NoTests = 0x02
     }; };
 
     struct ShowDurations { enum OrNot {
@@ -62,10 +63,12 @@
         virtual bool includeSuccessfulResults() const = 0;
         virtual bool shouldDebugBreak() const = 0;
         virtual bool warnAboutMissingAssertions() const = 0;
+        virtual bool warnAboutNoTests() const = 0;
         virtual int abortAfter() const = 0;
         virtual bool showInvisibles() const = 0;
         virtual ShowDurations::OrNot showDurations() const = 0;
         virtual TestSpec const& testSpec() const = 0;
+        virtual bool hasTestFilters() const = 0;
         virtual RunTests::InWhatOrder runOrder() const = 0;
         virtual unsigned int rngSeed() const = 0;
         virtual int benchmarkResolutionMultiple() const = 0;
diff --git a/include/internal/catch_interfaces_exception.h b/include/internal/catch_interfaces_exception.h
index c803156..73ef990 100644
--- a/include/internal/catch_interfaces_exception.h
+++ b/include/internal/catch_interfaces_exception.h
@@ -8,7 +8,6 @@
 #ifndef TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
 #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
 
-#include "catch_capture.hpp"  // for CATCH_INTERNAL_TRY
 #include "catch_interfaces_registry_hub.h"
 
 #if defined(CATCH_CONFIG_DISABLE)
@@ -47,15 +46,17 @@
             {}
 
             std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {
-                CATCH_INTERNAL_TRY {
+                CATCH_TRY {
                     if( it == itEnd )
                         std::rethrow_exception(std::current_exception());
                     else
                         return (*it)->translate( it+1, itEnd );
                 }
-                CATCH_INTERNAL_CATCH ( T&, ex ) {
+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
+                catch( T& ex ) {
                     return m_translateFunction( ex );
                 }
+#endif
             }
 
         protected:
diff --git a/include/internal/catch_interfaces_generatortracker.h b/include/internal/catch_interfaces_generatortracker.h
new file mode 100644
index 0000000..c1b1391
--- /dev/null
+++ b/include/internal/catch_interfaces_generatortracker.h
@@ -0,0 +1,39 @@
+/*
+ *  Created by Phil Nash on 26/6/2018.
+ *
+ *  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_INTERFACES_GENERATORTRACKER_INCLUDED
+#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORTRACKER_INCLUDED
+
+#include <memory>
+
+namespace Catch {
+
+    namespace Generators {
+        class GeneratorUntypedBase {
+        public:
+            GeneratorUntypedBase() = default;
+            virtual ~GeneratorUntypedBase();
+            // Attempts to move the generator to the next element
+             //
+             // Returns true iff the move succeeded (and a valid element
+             // can be retrieved).
+            virtual bool next() = 0;
+        };
+        using GeneratorBasePtr = std::unique_ptr<GeneratorUntypedBase>;
+
+    } // namespace Generators
+
+    struct IGeneratorTracker {
+        virtual ~IGeneratorTracker();
+        virtual auto hasGenerator() const -> bool = 0;
+        virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;
+        virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0;
+    };
+
+} // namespace Catch
+
+#endif //TWOBLUECUBES_CATCH_INTERFACES_GENERATORTRACKER_INCLUDED
diff --git a/include/internal/catch_interfaces_registry_hub.h b/include/internal/catch_interfaces_registry_hub.h
index 1afbbec..8e1da61 100644
--- a/include/internal/catch_interfaces_registry_hub.h
+++ b/include/internal/catch_interfaces_registry_hub.h
@@ -33,7 +33,7 @@
         virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
         virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
 
-        virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
+        virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0;
 
 
         virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
@@ -49,7 +49,7 @@
         virtual void registerStartupException() noexcept = 0;
     };
 
-    IRegistryHub& getRegistryHub();
+    IRegistryHub const& getRegistryHub();
     IMutableRegistryHub& getMutableRegistryHub();
     void cleanUp();
     std::string translateActiveException();
diff --git a/include/internal/catch_interfaces_reporter.cpp b/include/internal/catch_interfaces_reporter.cpp
index 129a5f4..0c367c5 100644
--- a/include/internal/catch_interfaces_reporter.cpp
+++ b/include/internal/catch_interfaces_reporter.cpp
@@ -6,7 +6,7 @@
  */
 
 #include "catch_interfaces_reporter.h"
-#include "../reporters/catch_reporter_multi.h"
+#include "../reporters/catch_reporter_listening.h"
 
 namespace Catch {
 
@@ -111,25 +111,4 @@
     IReporterFactory::~IReporterFactory() = default;
     IReporterRegistry::~IReporterRegistry() = default;
 
-    void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ) {
-
-        if( !existingReporter ) {
-            existingReporter = std::move( additionalReporter );
-            return;
-        }
-
-        MultipleReporters* multi = nullptr;
-
-        if( existingReporter->isMulti() ) {
-            multi = static_cast<MultipleReporters*>( existingReporter.get() );
-        }
-        else {
-            auto newMulti = std::unique_ptr<MultipleReporters>( new MultipleReporters );
-            newMulti->add( std::move( existingReporter ) );
-            multi = newMulti.get();
-            existingReporter = std::move( newMulti );
-        }
-        multi->add( std::move( additionalReporter ) );
-    }
-
 } // end namespace Catch
diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h
index b620abb..e5fbf8b 100644
--- a/include/internal/catch_interfaces_reporter.h
+++ b/include/internal/catch_interfaces_reporter.h
@@ -42,6 +42,7 @@
 
     struct ReporterPreferences {
         bool shouldRedirectStdOut = false;
+        bool shouldReportAllAssertions = false;
     };
 
     template<typename T>
@@ -79,8 +80,8 @@
 
         AssertionStats( AssertionStats const& )              = default;
         AssertionStats( AssertionStats && )                  = default;
-        AssertionStats& operator = ( AssertionStats const& ) = default;
-        AssertionStats& operator = ( AssertionStats && )     = default;
+        AssertionStats& operator = ( AssertionStats const& ) = delete;
+        AssertionStats& operator = ( AssertionStats && )     = delete;
         virtual ~AssertionStats();
 
         AssertionResult assertionResult;
@@ -226,8 +227,6 @@
         virtual Listeners const& getListeners() const = 0;
     };
 
-    void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter );
-
 } // end namespace Catch
 
 #endif // TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
diff --git a/include/internal/catch_interfaces_testcase.h b/include/internal/catch_interfaces_testcase.h
index 9e02b14..f57cc8f 100644
--- a/include/internal/catch_interfaces_testcase.h
+++ b/include/internal/catch_interfaces_testcase.h
@@ -9,7 +9,6 @@
 #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
 
 #include <vector>
-#include <memory>
 
 namespace Catch {
 
@@ -20,8 +19,6 @@
         virtual ~ITestInvoker();
     };
 
-    using ITestCasePtr = std::shared_ptr<ITestInvoker>;
-
     class TestCase;
     struct IConfig;
 
diff --git a/include/internal/catch_leak_detector.cpp b/include/internal/catch_leak_detector.cpp
index 36aba6a..7a30e8a 100644
--- a/include/internal/catch_leak_detector.cpp
+++ b/include/internal/catch_leak_detector.cpp
@@ -6,6 +6,7 @@
  */
 
  #include "catch_leak_detector.h"
+ #include "catch_interfaces_registry_hub.h"
 
 
 #ifdef CATCH_CONFIG_WINDOWS_CRTDBG
@@ -13,16 +14,16 @@
 
 namespace Catch {
 
-	LeakDetector::LeakDetector() {
-		int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
-		flag |= _CRTDBG_LEAK_CHECK_DF;
-		flag |= _CRTDBG_ALLOC_MEM_DF;
-		_CrtSetDbgFlag(flag);
-		_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
-		_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
-		// Change this to leaking allocation's number to break there
-		_CrtSetBreakAlloc(-1);
-	}
+    LeakDetector::LeakDetector() {
+        int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
+        flag |= _CRTDBG_LEAK_CHECK_DF;
+        flag |= _CRTDBG_ALLOC_MEM_DF;
+        _CrtSetDbgFlag(flag);
+        _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+        _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
+        // Change this to leaking allocation's number to break there
+        _CrtSetBreakAlloc(-1);
+    }
 }
 
 #else
@@ -30,3 +31,7 @@
     Catch::LeakDetector::LeakDetector() {}
 
 #endif
+
+Catch::LeakDetector::~LeakDetector() {
+    Catch::cleanUp();
+}
diff --git a/include/internal/catch_leak_detector.h b/include/internal/catch_leak_detector.h
index bfb0b42..633457a 100644
--- a/include/internal/catch_leak_detector.h
+++ b/include/internal/catch_leak_detector.h
@@ -11,6 +11,7 @@
 
     struct LeakDetector {
         LeakDetector();
+        ~LeakDetector();
     };
 
 }
diff --git a/include/internal/catch_list.cpp b/include/internal/catch_list.cpp
index 3efad0b..e1d9922 100644
--- a/include/internal/catch_list.cpp
+++ b/include/internal/catch_list.cpp
@@ -12,6 +12,7 @@
 #include "catch_interfaces_reporter.h"
 #include "catch_interfaces_testcase.h"
 
+#include "catch_context.h"
 #include "catch_stream.h"
 #include "catch_text.h"
 
@@ -28,11 +29,10 @@
 
     std::size_t listTests( Config const& config ) {
         TestSpec testSpec = config.testSpec();
-        if( config.testSpec().hasFilters() )
+        if( config.hasTestFilters() )
             Catch::cout() << "Matching test cases:\n";
         else {
             Catch::cout() << "All available test cases:\n";
-            testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
         }
 
         auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
@@ -54,7 +54,7 @@
                 Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n";
         }
 
-        if( !config.testSpec().hasFilters() )
+        if( !config.hasTestFilters() )
             Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl;
         else
             Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl;
@@ -63,8 +63,6 @@
 
     std::size_t listTestsNamesOnly( Config const& config ) {
         TestSpec testSpec = config.testSpec();
-        if( !config.testSpec().hasFilters() )
-            testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
         std::size_t matchedTests = 0;
         std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
         for( auto const& testCaseInfo : matchedTestCases ) {
@@ -94,11 +92,10 @@
 
     std::size_t listTags( Config const& config ) {
         TestSpec testSpec = config.testSpec();
-        if( config.testSpec().hasFilters() )
+        if( config.hasTestFilters() )
             Catch::cout() << "Tags for matching test cases:\n";
         else {
             Catch::cout() << "All available tags:\n";
-            testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
         }
 
         std::map<std::string, TagInfo> tagCounts;
@@ -128,7 +125,7 @@
         return tagCounts.size();
     }
 
-    std::size_t listReporters( Config const& /*config*/ ) {
+    std::size_t listReporters() {
         Catch::cout() << "Available reporters:\n";
         IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
         std::size_t maxNameLen = 0;
@@ -150,16 +147,17 @@
         return factories.size();
     }
 
-    Option<std::size_t> list( Config const& config ) {
+    Option<std::size_t> list( std::shared_ptr<Config> const& config ) {
         Option<std::size_t> listedCount;
-        if( config.listTests() )
-            listedCount = listedCount.valueOr(0) + listTests( config );
-        if( config.listTestNamesOnly() )
-            listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
-        if( config.listTags() )
-            listedCount = listedCount.valueOr(0) + listTags( config );
-        if( config.listReporters() )
-            listedCount = listedCount.valueOr(0) + listReporters( config );
+        getCurrentMutableContext().setConfig( config );
+        if( config->listTests() )
+            listedCount = listedCount.valueOr(0) + listTests( *config );
+        if( config->listTestNamesOnly() )
+            listedCount = listedCount.valueOr(0) + listTestsNamesOnly( *config );
+        if( config->listTags() )
+            listedCount = listedCount.valueOr(0) + listTags( *config );
+        if( config->listReporters() )
+            listedCount = listedCount.valueOr(0) + listReporters();
         return listedCount;
     }
 
diff --git a/include/internal/catch_list.h b/include/internal/catch_list.h
index 4bc96ec..cea7bba 100644
--- a/include/internal/catch_list.h
+++ b/include/internal/catch_list.h
@@ -29,9 +29,9 @@
 
     std::size_t listTags( Config const& config );
 
-    std::size_t listReporters( Config const& /*config*/ );
+    std::size_t listReporters();
     
-    Option<std::size_t> list( Config const& config );
+    Option<std::size_t> list( std::shared_ptr<Config> const& config );
 
 } // end namespace Catch
 
diff --git a/include/internal/catch_matchers.h b/include/internal/catch_matchers.h
index cacdeb3..aebd4c2 100644
--- a/include/internal/catch_matchers.h
+++ b/include/internal/catch_matchers.h
@@ -38,18 +38,11 @@
 #    pragma clang diagnostic push
 #    pragma clang diagnostic ignored "-Wnon-virtual-dtor"
 #endif
-/*
- * include/internal/catch_matchers.h:38:16: error: 'Catch::Matchers::Impl::MatcherMethod<std::__1::basic_string<char> >' has virtual functions but non-virtual destructor [-Werror,-Wnon-virtual-dtor]
- */
 
         template<typename ObjectT>
         struct MatcherMethod {
             virtual bool match( ObjectT const& arg ) const = 0;
         };
-        template<typename PtrT>
-        struct MatcherMethod<PtrT*> {
-            virtual bool match( PtrT* arg ) const = 0;
-        };
 
 #ifdef __clang__
 #    pragma clang diagnostic pop
diff --git a/include/internal/catch_matchers_floating.cpp b/include/internal/catch_matchers_floating.cpp
index e9abeb9..9bc082e 100644
--- a/include/internal/catch_matchers_floating.cpp
+++ b/include/internal/catch_matchers_floating.cpp
@@ -6,12 +6,14 @@
  */
 
 #include "catch_matchers_floating.h"
+#include "catch_enforce.h"
+#include "catch_polyfills.hpp"
+#include "catch_to_string.hpp"
 #include "catch_tostring.h"
 
 #include <cstdlib>
 #include <cstdint>
 #include <cstring>
-#include <stdexcept>
 
 namespace Catch {
 namespace Matchers {
@@ -56,7 +58,7 @@
 bool almostEqualUlps(FP lhs, FP rhs, int maxUlpDiff) {
     // Comparison with NaN should always be false.
     // This way we can rule it out before getting into the ugly details
-    if (std::isnan(lhs) || std::isnan(rhs)) {
+    if (Catch::isnan(lhs) || Catch::isnan(rhs)) {
         return false;
     }
 
@@ -80,15 +82,14 @@
 namespace Floating {
     WithinAbsMatcher::WithinAbsMatcher(double target, double margin)
         :m_target{ target }, m_margin{ margin } {
-        if (m_margin < 0) {
-          Exception::doThrow( std::domain_error("Allowed margin difference has to be >= 0") );
-        }
+        CATCH_ENFORCE(margin >= 0, "Invalid margin: " << margin << '.'
+            << " Margin has to be non-negative.");
     }
 
     // Performs equivalent check of std::fabs(lhs - rhs) <= margin
     // But without the subtraction to allow for INFINITY in comparison
     bool WithinAbsMatcher::match(double const& matchee) const {
-        return (matchee + m_margin >= m_target) && (m_target + m_margin >= m_margin);
+        return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);
     }
 
     std::string WithinAbsMatcher::describe() const {
@@ -98,11 +99,16 @@
 
     WithinUlpsMatcher::WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType)
         :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
-        if (m_ulps < 0) {
-          Exception::doThrow( std::domain_error("Allowed ulp difference has to be >= 0") );
-        }
+        CATCH_ENFORCE(ulps >= 0, "Invalid ULP setting: " << ulps << '.'
+            << " ULPs have to be non-negative.");
     }
 
+#if defined(__clang__)
+#pragma clang diagnostic push
+// Clang <3.5 reports on the default branch in the switch below
+#pragma clang diagnostic ignored "-Wunreachable-code"
+#endif
+
     bool WithinUlpsMatcher::match(double const& matchee) const {
         switch (m_type) {
         case FloatingPointKind::Float:
@@ -110,12 +116,16 @@
         case FloatingPointKind::Double:
             return almostEqualUlps<double>(matchee, m_target, m_ulps);
         default:
-            Exception::doThrow( std::domain_error("Unknown FloatingPointKind value") );
+            CATCH_INTERNAL_ERROR( "Unknown FloatingPointKind value" );
         }
     }
 
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
     std::string WithinUlpsMatcher::describe() const {
-        return "is within " + std::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : "");
+        return "is within " + Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : "");
     }
 
 }// namespace Floating
diff --git a/include/internal/catch_matchers_generic.cpp b/include/internal/catch_matchers_generic.cpp
new file mode 100644
index 0000000..300102e
--- /dev/null
+++ b/include/internal/catch_matchers_generic.cpp
@@ -0,0 +1,9 @@
+#include "catch_matchers_generic.hpp"
+
+std::string Catch::Matchers::Generic::Detail::finalizeDescription(const std::string& desc) {
+    if (desc.empty()) {
+        return "matches undescribed predicate";
+    } else {
+        return "matches predicate: \"" + desc + '"';
+    }
+}
diff --git a/include/internal/catch_matchers_generic.hpp b/include/internal/catch_matchers_generic.hpp
new file mode 100644
index 0000000..7c4f9f1
--- /dev/null
+++ b/include/internal/catch_matchers_generic.hpp
@@ -0,0 +1,58 @@
+/*
+ *  Created by Martin Hořeňovský on 03/04/2017.
+ *
+ * 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_MATCHERS_GENERIC_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_MATCHERS_GENERIC_HPP_INCLUDED
+
+#include "catch_common.h"
+#include "catch_matchers.h"
+
+#include <functional>
+#include <string>
+
+namespace Catch {
+namespace Matchers {
+namespace Generic {
+
+namespace Detail {
+    std::string finalizeDescription(const std::string& desc);
+}
+
+template <typename T>
+class PredicateMatcher : public MatcherBase<T> {
+    std::function<bool(T const&)> m_predicate;
+    std::string m_description;
+public:
+
+    PredicateMatcher(std::function<bool(T const&)> const& elem, std::string const& descr)
+        :m_predicate(std::move(elem)),
+        m_description(Detail::finalizeDescription(descr))
+    {}
+
+    bool match( T const& item ) const override {
+        return m_predicate(item);
+    }
+
+    std::string describe() const override {
+        return m_description;
+    }
+};
+
+} // namespace Generic
+
+    // The following functions create the actual matcher objects.
+    // The user has to explicitly specify type to the function, because
+    // infering std::function<bool(T const&)> is hard (but possible) and
+    // requires a lot of TMP.
+    template<typename T>
+    Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = "") {
+        return Generic::PredicateMatcher<T>(predicate, description);
+    }
+
+} // namespace Matchers
+} // namespace Catch
+
+#endif // TWOBLUECUBES_CATCH_MATCHERS_GENERIC_HPP_INCLUDED
diff --git a/include/internal/catch_matchers_vector.h b/include/internal/catch_matchers_vector.h
index 833d7dc..1e29cc9 100644
--- a/include/internal/catch_matchers_vector.h
+++ b/include/internal/catch_matchers_vector.h
@@ -124,7 +124,7 @@
                 auto lfirst = m_target.begin(), llast = m_target.end();
                 auto rfirst = vec.begin(), rlast = vec.end();
                 // Cut common prefix to optimize checking of permuted parts
-                while (lfirst != llast && *lfirst != *rfirst) {
+                while (lfirst != llast && *lfirst == *rfirst) {
                     ++lfirst; ++rfirst;
                 }
                 if (lfirst == llast) {
diff --git a/include/internal/catch_message.cpp b/include/internal/catch_message.cpp
index 8684970..fa7e874 100644
--- a/include/internal/catch_message.cpp
+++ b/include/internal/catch_message.cpp
@@ -10,9 +10,12 @@
 #include "catch_interfaces_capture.h"
 #include "catch_uncaught_exceptions.h"
 
+#include <cassert>
+#include <stack>
+
 namespace Catch {
 
-    MessageInfo::MessageInfo(   std::string const& _macroName,
+    MessageInfo::MessageInfo(   StringRef const& _macroName,
                                 SourceLineInfo const& _lineInfo,
                                 ResultWas::OfType _type )
     :   macroName( _macroName ),
@@ -35,7 +38,7 @@
 
     ////////////////////////////////////////////////////////////////////////////
 
-    Catch::MessageBuilder::MessageBuilder( std::string const& macroName,
+    Catch::MessageBuilder::MessageBuilder( StringRef const& macroName,
                                            SourceLineInfo const& lineInfo,
                                            ResultWas::OfType type )
         :m_info(macroName, lineInfo, type) {}
@@ -44,15 +47,82 @@
 
 
     ScopedMessage::ScopedMessage( MessageBuilder const& builder )
-    : m_info( builder.m_info )
+    : m_info( builder.m_info ), m_moved()
     {
         m_info.message = builder.m_stream.str();
         getResultCapture().pushScopedMessage( m_info );
     }
 
+    ScopedMessage::ScopedMessage( ScopedMessage&& old )
+    : m_info( old.m_info ), m_moved()
+    {
+        old.m_moved = true;
+    }
+
     ScopedMessage::~ScopedMessage() {
-        if ( !uncaught_exceptions() ){
+        if ( !uncaught_exceptions() && !m_moved ){
             getResultCapture().popScopedMessage(m_info);
         }
     }
+
+
+    Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) {
+        auto trimmed = [&] (size_t start, size_t end) {
+            while (names[start] == ',' || isspace(names[start])) {
+                ++start;
+            }
+            while (names[end] == ',' || isspace(names[end])) {
+                --end;
+            }
+            return names.substr(start, end - start + 1);
+        };
+
+        size_t start = 0;
+        std::stack<char> openings;
+        for (size_t pos = 0; pos < names.size(); ++pos) {
+            char c = names[pos];
+            switch (c) {
+            case '[':
+            case '{':
+            case '(':
+            // It is basically impossible to disambiguate between
+            // comparison and start of template args in this context
+//            case '<':
+                openings.push(c);
+                break;
+            case ']':
+            case '}':
+            case ')':
+//           case '>':
+                openings.pop();
+                break;
+            case ',':
+                if (start != pos && openings.size() == 0) {
+                    m_messages.emplace_back(macroName, lineInfo, resultType);
+                    m_messages.back().message = trimmed(start, pos);
+                    m_messages.back().message += " := ";
+                    start = pos;
+                }
+            }
+        }
+        assert(openings.size() == 0 && "Mismatched openings");
+        m_messages.emplace_back(macroName, lineInfo, resultType);
+        m_messages.back().message = trimmed(start, names.size() - 1);
+        m_messages.back().message += " := ";
+    }
+    Capturer::~Capturer() {
+        if ( !uncaught_exceptions() ){
+            assert( m_captured == m_messages.size() );
+            for( size_t i = 0; i < m_captured; ++i  )
+                m_resultCapture.popScopedMessage( m_messages[i] );
+        }
+    }
+
+    void Capturer::captureValue( size_t index, std::string const& value ) {
+        assert( index < m_messages.size() );
+        m_messages[index].message += value;
+        m_resultCapture.pushScopedMessage( m_messages[index] );
+        m_captured++;
+    }
+
 } // end namespace Catch
diff --git a/include/internal/catch_message.h b/include/internal/catch_message.h
index 0a512ed..748f5ac 100644
--- a/include/internal/catch_message.h
+++ b/include/internal/catch_message.h
@@ -8,19 +8,23 @@
 #ifndef TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
 #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
 
-#include <string>
 #include "catch_result_type.h"
 #include "catch_common.h"
 #include "catch_stream.h"
+#include "catch_interfaces_capture.h"
+#include "catch_tostring.h"
+
+#include <string>
+#include <vector>
 
 namespace Catch {
 
     struct MessageInfo {
-        MessageInfo(    std::string const& _macroName,
+        MessageInfo(    StringRef const& _macroName,
                         SourceLineInfo const& _lineInfo,
                         ResultWas::OfType _type );
 
-        std::string macroName;
+        StringRef macroName;
         std::string message;
         SourceLineInfo lineInfo;
         ResultWas::OfType type;
@@ -44,7 +48,7 @@
     };
 
     struct MessageBuilder : MessageStream {
-        MessageBuilder( std::string const& macroName,
+        MessageBuilder( StringRef const& macroName,
                         SourceLineInfo const& lineInfo,
                         ResultWas::OfType type );
 
@@ -60,9 +64,34 @@
     class ScopedMessage {
     public:
         explicit ScopedMessage( MessageBuilder const& builder );
+        ScopedMessage( ScopedMessage& duplicate ) = delete;
+        ScopedMessage( ScopedMessage&& old );
         ~ScopedMessage();
 
         MessageInfo m_info;
+        bool m_moved;
+    };
+
+    class Capturer {
+        std::vector<MessageInfo> m_messages;
+        IResultCapture& m_resultCapture = getResultCapture();
+        size_t m_captured = 0;
+    public:
+        Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names );
+        ~Capturer();
+
+        void captureValue( size_t index, std::string const& value );
+
+        template<typename T>
+        void captureValues( size_t index, T const& value ) {
+            captureValue( index, Catch::Detail::stringify( value ) );
+        }
+
+        template<typename T, typename... Ts>
+        void captureValues( size_t index, T const& value, Ts const&... values ) {
+            captureValue( index, Catch::Detail::stringify(value) );
+            captureValues( index+1, values... );
+        }
     };
 
 } // end namespace Catch
diff --git a/include/internal/catch_meta.hpp b/include/internal/catch_meta.hpp
new file mode 100644
index 0000000..3508a46
--- /dev/null
+++ b/include/internal/catch_meta.hpp
@@ -0,0 +1,77 @@
+/*
+ *  Created by Jozef on 02/12/2018.
+ *  Copyright 2018 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_META_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_META_HPP_INCLUDED
+
+#include <type_traits>
+
+namespace Catch {
+template< typename... >
+struct TypeList {};
+
+template< typename... >
+struct append;
+
+template< template<typename...> class L1
+    , typename...E1
+    , template<typename...> class L2
+    , typename...E2
+>
+struct append< L1<E1...>, L2<E2...> > {
+    using type = L1<E1..., E2...>;
+};
+
+template< template<typename...> class L1
+    , typename...E1
+    , template<typename...> class L2
+    , typename...E2
+    , typename...Rest
+>
+struct append< L1<E1...>, L2<E2...>, Rest...> {
+    using type = typename append< L1<E1..., E2...>, Rest... >::type;
+};
+
+template< template<typename...> class
+    , typename...
+>
+struct rewrap;
+
+template< template<typename...> class Container
+    , template<typename...> class List
+    , typename...elems
+>
+struct rewrap<Container, List<elems...>> {
+    using type = TypeList< Container< elems... > >;
+};
+
+template< template<typename...> class Container
+    , template<typename...> class List
+    , class...Elems
+    , typename...Elements>
+    struct rewrap<Container, List<Elems...>, Elements...> {
+    using type = typename append<TypeList<Container<Elems...>>, typename rewrap<Container, Elements...>::type>::type;
+};
+
+template< template<typename...> class...Containers >
+struct combine {
+    template< typename...Types >
+    struct with_types {
+        template< template <typename...> class Final >
+        struct into {
+            using type = typename append<Final<>, typename rewrap<Containers, Types...>::type...>::type;
+        };
+    };
+};
+
+template<typename T>
+struct always_false : std::false_type {};
+
+} // namespace Catch
+
+#endif // TWOBLUECUBES_CATCH_META_HPP_INCLUDED
diff --git a/include/internal/catch_objc.hpp b/include/internal/catch_objc.hpp
index b43f335..39cbb1f 100644
--- a/include/internal/catch_objc.hpp
+++ b/include/internal/catch_objc.hpp
@@ -93,7 +93,7 @@
                         std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
                         const char* className = class_getName( cls );
 
-                        getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo("",0) ) );
+                        getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, NameAndTags( name.c_str(), desc.c_str() ), SourceLineInfo("",0) ) );
                         noTestMethods++;
                     }
                 }
diff --git a/include/internal/catch_output_redirect.cpp b/include/internal/catch_output_redirect.cpp
new file mode 100644
index 0000000..a0a9aff
--- /dev/null
+++ b/include/internal/catch_output_redirect.cpp
@@ -0,0 +1,147 @@
+/*
+ *  Created by Martin on 28/04/2018.
+ *
+ *  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_output_redirect.h"
+#include "catch_enforce.h"
+
+#include <cstdio>
+#include <cstring>
+#include <fstream>
+#include <sstream>
+#include <stdexcept>
+
+#if defined(CATCH_CONFIG_NEW_CAPTURE)
+    #if defined(_MSC_VER)
+    #include <io.h>      //_dup and _dup2
+    #define dup _dup
+    #define dup2 _dup2
+    #define fileno _fileno
+    #else
+    #include <unistd.h>  // dup and dup2
+    #endif
+#endif
+
+
+namespace Catch {
+
+    RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
+    :   m_originalStream( originalStream ),
+        m_redirectionStream( redirectionStream ),
+        m_prevBuf( m_originalStream.rdbuf() )
+    {
+        m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
+    }
+
+    RedirectedStream::~RedirectedStream() {
+        m_originalStream.rdbuf( m_prevBuf );
+    }
+
+    RedirectedStdOut::RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {}
+    auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); }
+
+    RedirectedStdErr::RedirectedStdErr()
+    :   m_cerr( Catch::cerr(), m_rss.get() ),
+        m_clog( Catch::clog(), m_rss.get() )
+    {}
+    auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); }
+
+    RedirectedStreams::RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr)
+    :   m_redirectedCout(redirectedCout),
+        m_redirectedCerr(redirectedCerr)
+    {}
+
+    RedirectedStreams::~RedirectedStreams() {
+        m_redirectedCout += m_redirectedStdOut.str();
+        m_redirectedCerr += m_redirectedStdErr.str();
+    }
+
+#if defined(CATCH_CONFIG_NEW_CAPTURE)
+
+#if defined(_MSC_VER)
+    TempFile::TempFile() {
+        if (tmpnam_s(m_buffer)) {
+            CATCH_RUNTIME_ERROR("Could not get a temp filename");
+        }
+        if (fopen_s(&m_file, m_buffer, "w")) {
+            char buffer[100];
+            if (strerror_s(buffer, errno)) {
+                CATCH_RUNTIME_ERROR("Could not translate errno to a string");
+            }
+            CATCH_RUNTIME_ERROR("Coul dnot open the temp file: '" << m_buffer << "' because: " << buffer);
+        }
+    }
+#else
+    TempFile::TempFile() {
+        m_file = std::tmpfile();
+        if (!m_file) {
+            CATCH_RUNTIME_ERROR("Could not create a temp file.");
+        }
+    }
+
+#endif
+
+    TempFile::~TempFile() {
+         // TBD: What to do about errors here?
+         std::fclose(m_file);
+         // We manually create the file on Windows only, on Linux
+         // it will be autodeleted
+#if defined(_MSC_VER)
+         std::remove(m_buffer);
+#endif
+    }
+
+
+    FILE* TempFile::getFile() {
+        return m_file;
+    }
+
+    std::string TempFile::getContents() {
+        std::stringstream sstr;
+        char buffer[100] = {};
+        std::rewind(m_file);
+        while (std::fgets(buffer, sizeof(buffer), m_file)) {
+            sstr << buffer;
+        }
+        return sstr.str();
+    }
+
+    OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) :
+        m_originalStdout(dup(1)),
+        m_originalStderr(dup(2)),
+        m_stdoutDest(stdout_dest),
+        m_stderrDest(stderr_dest) {
+        dup2(fileno(m_stdoutFile.getFile()), 1);
+        dup2(fileno(m_stderrFile.getFile()), 2);
+    }
+
+    OutputRedirect::~OutputRedirect() {
+        Catch::cout() << std::flush;
+        fflush(stdout);
+        // Since we support overriding these streams, we flush cerr
+        // even though std::cerr is unbuffered
+        Catch::cerr() << std::flush;
+        Catch::clog() << std::flush;
+        fflush(stderr);
+
+        dup2(m_originalStdout, 1);
+        dup2(m_originalStderr, 2);
+
+        m_stdoutDest += m_stdoutFile.getContents();
+        m_stderrDest += m_stderrFile.getContents();
+    }
+
+#endif // CATCH_CONFIG_NEW_CAPTURE
+
+} // namespace Catch
+
+#if defined(CATCH_CONFIG_NEW_CAPTURE)
+    #if defined(_MSC_VER)
+    #undef dup
+    #undef dup2
+    #undef fileno
+    #endif
+#endif
diff --git a/include/internal/catch_output_redirect.h b/include/internal/catch_output_redirect.h
new file mode 100644
index 0000000..3d1c2d4
--- /dev/null
+++ b/include/internal/catch_output_redirect.h
@@ -0,0 +1,116 @@
+/*
+ *  Created by Martin on 28/04/2018.
+ *
+ *  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_OUTPUT_REDIRECT_H
+#define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
+
+#include "catch_platform.h"
+#include "catch_stream.h"
+
+#include <cstdio>
+#include <iosfwd>
+#include <string>
+
+namespace Catch {
+
+    class RedirectedStream {
+        std::ostream& m_originalStream;
+        std::ostream& m_redirectionStream;
+        std::streambuf* m_prevBuf;
+
+    public:
+        RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream );
+        ~RedirectedStream();
+    };
+
+    class RedirectedStdOut {
+        ReusableStringStream m_rss;
+        RedirectedStream m_cout;
+    public:
+        RedirectedStdOut();
+        auto str() const -> std::string;
+    };
+
+    // StdErr has two constituent streams in C++, std::cerr and std::clog
+    // This means that we need to redirect 2 streams into 1 to keep proper
+    // order of writes
+    class RedirectedStdErr {
+        ReusableStringStream m_rss;
+        RedirectedStream m_cerr;
+        RedirectedStream m_clog;
+    public:
+        RedirectedStdErr();
+        auto str() const -> std::string;
+    };
+
+    class RedirectedStreams {
+    public:
+        RedirectedStreams(RedirectedStreams const&) = delete;
+        RedirectedStreams& operator=(RedirectedStreams const&) = delete;
+        RedirectedStreams(RedirectedStreams&&) = delete;
+        RedirectedStreams& operator=(RedirectedStreams&&) = delete;
+
+        RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr);
+        ~RedirectedStreams();
+    private:
+        std::string& m_redirectedCout;
+        std::string& m_redirectedCerr;
+        RedirectedStdOut m_redirectedStdOut;
+        RedirectedStdErr m_redirectedStdErr;
+    };
+
+#if defined(CATCH_CONFIG_NEW_CAPTURE)
+
+    // Windows's implementation of std::tmpfile is terrible (it tries
+    // to create a file inside system folder, thus requiring elevated
+    // privileges for the binary), so we have to use tmpnam(_s) and
+    // create the file ourselves there.
+    class TempFile {
+    public:
+        TempFile(TempFile const&) = delete;
+        TempFile& operator=(TempFile const&) = delete;
+        TempFile(TempFile&&) = delete;
+        TempFile& operator=(TempFile&&) = delete;
+
+        TempFile();
+        ~TempFile();
+
+        std::FILE* getFile();
+        std::string getContents();
+
+    private:
+        std::FILE* m_file = nullptr;
+    #if defined(_MSC_VER)
+        char m_buffer[L_tmpnam] = { 0 };
+    #endif
+    };
+
+
+    class OutputRedirect {
+    public:
+        OutputRedirect(OutputRedirect const&) = delete;
+        OutputRedirect& operator=(OutputRedirect const&) = delete;
+        OutputRedirect(OutputRedirect&&) = delete;
+        OutputRedirect& operator=(OutputRedirect&&) = delete;
+
+
+        OutputRedirect(std::string& stdout_dest, std::string& stderr_dest);
+        ~OutputRedirect();
+
+    private:
+        int m_originalStdout = -1;
+        int m_originalStderr = -1;
+        TempFile m_stdoutFile;
+        TempFile m_stderrFile;
+        std::string& m_stdoutDest;
+        std::string& m_stderrDest;
+    };
+
+#endif
+
+} // end namespace Catch
+
+#endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
diff --git a/include/internal/catch_platform.h b/include/internal/catch_platform.h
index cbf1792..e14cd33 100644
--- a/include/internal/catch_platform.h
+++ b/include/internal/catch_platform.h
@@ -20,7 +20,7 @@
 #elif defined(linux) || defined(__linux) || defined(__linux__)
 #  define CATCH_PLATFORM_LINUX
 
-#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
+#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__)
 #  define CATCH_PLATFORM_WINDOWS
 #endif
 
diff --git a/include/internal/catch_polyfills.cpp b/include/internal/catch_polyfills.cpp
new file mode 100644
index 0000000..68a2c82
--- /dev/null
+++ b/include/internal/catch_polyfills.cpp
@@ -0,0 +1,31 @@
+/*
+ *  Created by Martin on 17/11/2017.
+ *
+ *  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_polyfills.hpp"
+
+#include <cmath>
+
+namespace Catch {
+
+#if !defined(CATCH_CONFIG_POLYFILL_ISNAN)
+    bool isnan(float f) {
+        return std::isnan(f);
+    }
+    bool isnan(double d) {
+        return std::isnan(d);
+    }
+#else
+    // For now we only use this for embarcadero
+    bool isnan(float f) {
+        return std::_isnan(f);
+    }
+    bool isnan(double d) {
+        return std::_isnan(d);
+    }
+#endif
+
+} // end namespace Catch
diff --git a/include/internal/catch_polyfills.hpp b/include/internal/catch_polyfills.hpp
new file mode 100644
index 0000000..ba4189e
--- /dev/null
+++ b/include/internal/catch_polyfills.hpp
@@ -0,0 +1,15 @@
+/*
+ *  Created by Martin on 17/11/2017.
+ *
+ *  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_POLYFILLS_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_POLYFILLS_HPP_INCLUDED
+
+namespace Catch {
+    bool isnan(float f);
+    bool isnan(double d);
+}
+
+#endif // TWOBLUECUBES_CATCH_POLYFILLS_HPP_INCLUDED
diff --git a/include/internal/catch_preprocessor.hpp b/include/internal/catch_preprocessor.hpp
new file mode 100644
index 0000000..faf41e6
--- /dev/null
+++ b/include/internal/catch_preprocessor.hpp
@@ -0,0 +1,89 @@
+/*
+ *  Created by Jozef on 12/11/2018.
+ *  Copyright 2017 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_PREPROCESSOR_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_PREPROCESSOR_HPP_INCLUDED
+
+#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__
+#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__)))
+#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__)))
+#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__)))
+#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__)))
+#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__)))
+
+#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__
+// MSVC needs more evaluations
+#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__)))
+#define CATCH_RECURSE(...)  CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__))
+#else
+#define CATCH_RECURSE(...)  CATCH_RECURSION_LEVEL5(__VA_ARGS__)
+#endif
+
+#define CATCH_REC_END(...)
+#define CATCH_REC_OUT
+
+#define CATCH_EMPTY()
+#define CATCH_DEFER(id) id CATCH_EMPTY()
+
+#define CATCH_REC_GET_END2() 0, CATCH_REC_END
+#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2
+#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1
+#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT
+#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0)
+#define CATCH_REC_NEXT(test, next)  CATCH_REC_NEXT1(CATCH_REC_GET_END test, next)
+
+#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
+#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ )
+#define CATCH_REC_LIST2(f, x, peek, ...)   f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
+
+#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )
+#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ )
+#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...)   f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )
+
+// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results,
+// and passes userdata as the first parameter to each invocation,
+// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c)
+#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
+
+#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
+
+#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param)
+#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__
+#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
+#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
+#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__)
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__
+#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param))
+#else
+// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
+#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__)
+#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__
+#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1)
+#endif
+
+#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__)
+
+#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name, __VA_ARGS__)
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name,...) Name " - " #__VA_ARGS__
+#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name,...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))
+#else
+// MSVC is adding extra space and needs more calls to properly remove ()
+#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name,...) Name " -" #__VA_ARGS__
+#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, __VA_ARGS__)
+#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
+#endif
+
+#define INTERNAL_CATCH_MAKE_TYPE_LIST(types) Catch::TypeList<INTERNAL_CATCH_REMOVE_PARENS(types)>
+
+#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(types)\
+    CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,INTERNAL_CATCH_REMOVE_PARENS(types))
+
+#endif // TWOBLUECUBES_CATCH_PREPROCESSOR_HPP_INCLUDED
diff --git a/include/internal/catch_random_number_generator.cpp b/include/internal/catch_random_number_generator.cpp
index 412faeb..ec8a5eb 100644
--- a/include/internal/catch_random_number_generator.cpp
+++ b/include/internal/catch_random_number_generator.cpp
@@ -9,23 +9,21 @@
 #include "catch_context.h"
 #include "catch_interfaces_config.h"
 
-#include <cstdlib>
-
 namespace Catch {
 
-    void seedRng( IConfig const& config ) {
-        if( config.rngSeed() != 0 )
-            std::srand( config.rngSeed() );
+    std::mt19937& rng() {
+        static std::mt19937 s_rng;
+        return s_rng;
     }
+
+    void seedRng( IConfig const& config ) {
+        if( config.rngSeed() != 0 ) {
+            std::srand( config.rngSeed() );
+            rng().seed( config.rngSeed() );
+        }
+    }
+
     unsigned int rngSeed() {
         return getCurrentContext().getConfig()->rngSeed();
     }
-
-    RandomNumberGenerator::result_type RandomNumberGenerator::operator()( result_type n ) const {
-        return std::rand() % n;
-    }
-    RandomNumberGenerator::result_type RandomNumberGenerator::operator()() const {
-        return std::rand() % (max)();
-    }
-
 }
diff --git a/include/internal/catch_random_number_generator.h b/include/internal/catch_random_number_generator.h
index d18cffd..817b784 100644
--- a/include/internal/catch_random_number_generator.h
+++ b/include/internal/catch_random_number_generator.h
@@ -8,31 +8,16 @@
 #define TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED
 
 #include <algorithm>
+#include <random>
 
 namespace Catch {
 
     struct IConfig;
 
+    std::mt19937& rng();
     void seedRng( IConfig const& config );
-
     unsigned int rngSeed();
 
-    struct RandomNumberGenerator {
-        using result_type = unsigned int;
-
-        static constexpr result_type (min)() { return 0; }
-        static constexpr result_type (max)() { return 1000000; }
-
-        result_type operator()( result_type n ) const;
-        result_type operator()() const;
-
-        template<typename V>
-        static void shuffle( V& vector ) {
-            RandomNumberGenerator rng;
-            std::shuffle( vector.begin(), vector.end(), rng );
-        }
-    };
-
 }
 
 #endif // TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED
diff --git a/include/internal/catch_registry_hub.cpp b/include/internal/catch_registry_hub.cpp
index d98708c..a506239 100644
--- a/include/internal/catch_registry_hub.cpp
+++ b/include/internal/catch_registry_hub.cpp
@@ -14,6 +14,7 @@
 #include "catch_exception_translator_registry.h"
 #include "catch_tag_alias_registry.h"
 #include "catch_startup_exception_registry.h"
+#include "catch_singletons.hpp"
 
 namespace Catch {
 
@@ -30,7 +31,7 @@
             ITestCaseRegistry const& getTestCaseRegistry() const override {
                 return m_testCaseRegistry;
             }
-            IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() override {
+            IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const override {
                 return m_exceptionTranslatorRegistry;
             }
             ITagAliasRegistry const& getTagAliasRegistry() const override {
@@ -67,27 +68,19 @@
             TagAliasRegistry m_tagAliasRegistry;
             StartupExceptionRegistry m_exceptionRegistry;
         };
-
-        // Single, global, instance
-        RegistryHub*& getTheRegistryHub() {
-            static RegistryHub* theRegistryHub = nullptr;
-            if( !theRegistryHub )
-                theRegistryHub = new RegistryHub();
-            return theRegistryHub;
-        }
     }
 
-    IRegistryHub& getRegistryHub() {
-        return *getTheRegistryHub();
+    using RegistryHubSingleton = Singleton<RegistryHub, IRegistryHub, IMutableRegistryHub>;
+
+    IRegistryHub const& getRegistryHub() {
+        return RegistryHubSingleton::get();
     }
     IMutableRegistryHub& getMutableRegistryHub() {
-        return *getTheRegistryHub();
+        return RegistryHubSingleton::getMutable();
     }
     void cleanUp() {
-        delete getTheRegistryHub();
-        getTheRegistryHub() = nullptr;
+        cleanupSingletons();
         cleanUpContext();
-        ReusableStringStream::cleanup();
     }
     std::string translateActiveException() {
         return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp
index 83de539..bc3a515 100644
--- a/include/internal/catch_run_context.cpp
+++ b/include/internal/catch_run_context.cpp
@@ -1,8 +1,10 @@
 #include "catch_run_context.h"
+#include "catch_compiler_capabilities.h"
 #include "catch_context.h"
 #include "catch_enforce.h"
 #include "catch_random_number_generator.h"
 #include "catch_stream.h"
+#include "catch_output_redirect.h"
 
 #include <cassert>
 #include <algorithm>
@@ -10,55 +12,68 @@
 
 namespace Catch {
 
-    class RedirectedStream {
-        std::ostream& m_originalStream;
-        std::ostream& m_redirectionStream;
-        std::streambuf* m_prevBuf;
+    namespace Generators {
+        struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
+            GeneratorBasePtr m_generator;
 
-    public:
-        RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
-        :   m_originalStream( originalStream ),
-            m_redirectionStream( redirectionStream ),
-            m_prevBuf( m_originalStream.rdbuf() )
-        {
-            m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
-        }
-        ~RedirectedStream() {
-            m_originalStream.rdbuf( m_prevBuf );
-        }
-    };
+            GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
+            :   TrackerBase( nameAndLocation, ctx, parent )
+            {}
+            ~GeneratorTracker();
 
-    class RedirectedStdOut {
-        ReusableStringStream m_rss;
-        RedirectedStream m_cout;
-    public:
-        RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {}
-        auto str() const -> std::string { return m_rss.str(); }
-    };
+            static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) {
+                std::shared_ptr<GeneratorTracker> tracker;
 
-    // StdErr has two constituent streams in C++, std::cerr and std::clog
-    // This means that we need to redirect 2 streams into 1 to keep proper
-    // order of writes
-    class RedirectedStdErr {
-        ReusableStringStream m_rss;
-        RedirectedStream m_cerr;
-        RedirectedStream m_clog;
-    public:
-        RedirectedStdErr()
-        :   m_cerr( Catch::cerr(), m_rss.get() ),
-            m_clog( Catch::clog(), m_rss.get() )
-        {}
-        auto str() const -> std::string { return m_rss.str(); }
-    };
+                ITracker& currentTracker = ctx.currentTracker();
+                if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
+                    assert( childTracker );
+                    assert( childTracker->isGeneratorTracker() );
+                    tracker = std::static_pointer_cast<GeneratorTracker>( childTracker );
+                }
+                else {
+                    tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, &currentTracker );
+                    currentTracker.addChild( tracker );
+                }
 
+                if( !ctx.completedCycle() && !tracker->isComplete() ) {
+                    tracker->open();
+                }
+
+                return *tracker;
+            }
+
+            // TrackerBase interface
+            bool isGeneratorTracker() const override { return true; }
+            auto hasGenerator() const -> bool override {
+                return !!m_generator;
+            }
+            void close() override {
+                TrackerBase::close();
+                // Generator interface only finds out if it has another item on atual move
+                if (m_runState == CompletedSuccessfully && m_generator->next()) {
+                    m_children.clear();
+                    m_runState = Executing;
+                }
+            }
+
+            // IGeneratorTracker interface
+            auto getGenerator() const -> GeneratorBasePtr const& override {
+                return m_generator;
+            }
+            void setGenerator( GeneratorBasePtr&& generator ) override {
+                m_generator = std::move( generator );
+            }
+        };
+        GeneratorTracker::~GeneratorTracker() {}
+    }
 
     RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter)
     :   m_runInfo(_config->name()),
         m_context(getCurrentMutableContext()),
         m_config(_config),
         m_reporter(std::move(reporter)),
-        m_lastAssertionInfo{ "", SourceLineInfo("",0), "", ResultDisposition::Normal },
-        m_includeSuccessfulResults( m_config->includeSuccessfulResults() )
+        m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal },
+        m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions )
     {
         m_context.setRunner(this);
         m_context.setConfig(m_config);
@@ -84,7 +99,7 @@
         std::string redirectedCout;
         std::string redirectedCerr;
 
-        TestCaseInfo testInfo = testCase.getTestCaseInfo();
+        auto const& testInfo = testCase.getTestCaseInfo();
 
         m_reporter->testCaseStarting(testInfo);
 
@@ -146,6 +161,9 @@
         // and should be let to clear themselves out.
         static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
 
+        if (result.getResultType() != ResultWas::Warning)
+            m_messageScopes.clear();
+
         // Reset working state
         resetAssertionInfo();
         m_lastResult = result;
@@ -169,6 +187,13 @@
 
         return true;
     }
+    auto RunContext::acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
+        using namespace Generators;
+        GeneratorTracker& tracker = GeneratorTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( "generator", lineInfo ) );
+        assert( tracker.isOpen() );
+        m_lastAssertionInfo.lineInfo = lineInfo;
+        return tracker;
+    }
 
     bool RunContext::testForMissingAssertions(Counts& assertions) {
         if (assertions.total() != 0)
@@ -193,6 +218,7 @@
 
         m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
         m_messages.clear();
+        m_messageScopes.clear();
     }
 
     void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) {
@@ -219,6 +245,10 @@
         m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
     }
 
+    void RunContext::emplaceUnscopedMessage( MessageBuilder const& builder ) {
+        m_messageScopes.emplace_back( builder );
+    }
+
     std::string RunContext::getCurrentTestName() const {
         return m_activeTestCase
             ? m_activeTestCase->getTestCaseInfo().name
@@ -249,7 +279,7 @@
 
         // Recreate section for test case (as we will lose the one that was in scope)
         auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
-        SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
+        SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
 
         Counts assertions;
         assertions.failed = 1;
@@ -279,41 +309,45 @@
         m_lastAssertionPassed = true;
         ++m_totals.assertions.passed;
         resetAssertionInfo();
+        m_messageScopes.clear();
     }
 
     bool RunContext::aborting() const {
-        return m_totals.assertions.failed == static_cast<std::size_t>(m_config->abortAfter());
+        return m_totals.assertions.failed >= static_cast<std::size_t>(m_config->abortAfter());
     }
 
     void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) {
         auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
-        SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
+        SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
         m_reporter->sectionStarting(testCaseSection);
         Counts prevAssertions = m_totals.assertions;
         double duration = 0;
         m_shouldReportUnexpected = true;
-        m_lastAssertionInfo = { "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal };
+        m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal };
 
         seedRng(*m_config);
 
         Timer timer;
-        CATCH_INTERNAL_TRY {
+        CATCH_TRY {
             if (m_reporter->getPreferences().shouldRedirectStdOut) {
-                RedirectedStdOut redirectedStdOut;
-                RedirectedStdErr redirectedStdErr;
+#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
+                RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr);
+
                 timer.start();
                 invokeActiveTestCase();
-                redirectedCout += redirectedStdOut.str();
-                redirectedCerr += redirectedStdErr.str();
-
+#else
+                OutputRedirect r(redirectedCout, redirectedCerr);
+                timer.start();
+                invokeActiveTestCase();
+#endif
             } else {
                 timer.start();
                 invokeActiveTestCase();
             }
             duration = timer.getElapsedSeconds();
-        } CATCH_INTERNAL_CATCH_UNNAMED (TestFailureException&) {
+        } CATCH_CATCH_ANON (TestFailureException&) {
             // This just means the test was aborted due to failure
-        } CATCH_INTERNAL_CATCH_ALL() {
+        } CATCH_CATCH_ALL {
             // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
             // are reported without translation at the point of origin.
             if( m_shouldReportUnexpected ) {
@@ -327,6 +361,7 @@
         m_testCaseTracker->close();
         handleUnfinishedSections();
         m_messages.clear();
+        m_messageScopes.clear();
 
         SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
         m_reporter->sectionEnded(testCaseSectionStats);
diff --git a/include/internal/catch_run_context.h b/include/internal/catch_run_context.h
index d0007a3..c530a7b 100644
--- a/include/internal/catch_run_context.h
+++ b/include/internal/catch_run_context.h
@@ -8,6 +8,7 @@
 #ifndef TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
 #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
 
+#include "catch_interfaces_generatortracker.h"
 #include "catch_interfaces_runner.h"
 #include "catch_interfaces_reporter.h"
 #include "catch_interfaces_exception.h"
@@ -79,12 +80,16 @@
         void sectionEnded( SectionEndInfo const& endInfo ) override;
         void sectionEndedEarly( SectionEndInfo const& endInfo ) override;
 
+        auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override;
+
         void benchmarkStarting( BenchmarkInfo const& info ) override;
         void benchmarkEnded( BenchmarkStats const& stats ) override;
 
         void pushScopedMessage( MessageInfo const& message ) override;
         void popScopedMessage( MessageInfo const& message ) override;
 
+        void emplaceUnscopedMessage( MessageBuilder const& builder ) override;
+
         std::string getCurrentTestName() const override;
 
         const AssertionResult* getLastResult() const override;
@@ -99,7 +104,7 @@
 
     public:
         // !TBD We need to do this another way!
-        bool aborting() const override;
+        bool aborting() const final;
 
     private:
 
@@ -125,13 +130,14 @@
         TestRunInfo m_runInfo;
         IMutableContext& m_context;
         TestCase const* m_activeTestCase = nullptr;
-        ITracker* m_testCaseTracker;
+        ITracker* m_testCaseTracker = nullptr;
         Option<AssertionResult> m_lastResult;
 
         IConfigPtr m_config;
         Totals m_totals;
         IStreamingReporterPtr m_reporter;
         std::vector<MessageInfo> m_messages;
+        std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */
         AssertionInfo m_lastAssertionInfo;
         std::vector<SectionEndInfo> m_unfinishedSections;
         std::vector<ITracker*> m_activeSections;
diff --git a/include/internal/catch_section.cpp b/include/internal/catch_section.cpp
index 72a57d5..0646d36 100644
--- a/include/internal/catch_section.cpp
+++ b/include/internal/catch_section.cpp
@@ -21,7 +21,7 @@
 
     Section::~Section() {
         if( m_sectionIncluded ) {
-            SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
+            SectionEndInfo endInfo{ m_info, m_assertions, m_timer.getElapsedSeconds() };
             if( uncaught_exceptions() )
                 getResultCapture().sectionEndedEarly( endInfo );
             else
diff --git a/include/internal/catch_section.h b/include/internal/catch_section.h
index 1e5b1c3..00c254b 100644
--- a/include/internal/catch_section.h
+++ b/include/internal/catch_section.h
@@ -8,6 +8,7 @@
 #ifndef TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
 #define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
 
+#include "catch_compiler_capabilities.h"
 #include "catch_section_info.h"
 #include "catch_totals.h"
 #include "catch_timer.h"
@@ -35,7 +36,14 @@
 
 } // end namespace Catch
 
-    #define INTERNAL_CATCH_SECTION( ... ) \
-        if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
+#define INTERNAL_CATCH_SECTION( ... ) \
+    CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
+    if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
+    CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
+
+#define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
+    CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
+    if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \
+    CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
 
 #endif // TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
diff --git a/include/internal/catch_section_info.cpp b/include/internal/catch_section_info.cpp
index e2846b8..89714e3 100644
--- a/include/internal/catch_section_info.cpp
+++ b/include/internal/catch_section_info.cpp
@@ -11,15 +11,9 @@
 
     SectionInfo::SectionInfo
         (   SourceLineInfo const& _lineInfo,
-            std::string const& _name,
-            std::string const& _description )
+            std::string const& _name )
     :   name( _name ),
-        description( _description ),
         lineInfo( _lineInfo )
     {}
 
-    SectionEndInfo::SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds )
-    : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
-    {}
-
 } // end namespace Catch
diff --git a/include/internal/catch_section_info.h b/include/internal/catch_section_info.h
index 86681ba..9cf792e 100644
--- a/include/internal/catch_section_info.h
+++ b/include/internal/catch_section_info.h
@@ -18,17 +18,20 @@
     struct SectionInfo {
         SectionInfo
             (   SourceLineInfo const& _lineInfo,
+                std::string const& _name );
+
+        // Deprecated
+        SectionInfo
+            (   SourceLineInfo const& _lineInfo,
                 std::string const& _name,
-                std::string const& _description = std::string() );
+                std::string const& ) : SectionInfo( _lineInfo, _name ) {}
 
         std::string name;
-        std::string description;
+        std::string description; // !Deprecated: this will always be empty
         SourceLineInfo lineInfo;
     };
 
     struct SectionEndInfo {
-        SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds );
-
         SectionInfo sectionInfo;
         Counts prevAssertions;
         double durationInSeconds;
diff --git a/include/internal/catch_session.cpp b/include/internal/catch_session.cpp
index 34ac571..a5907e9 100644
--- a/include/internal/catch_session.cpp
+++ b/include/internal/catch_session.cpp
@@ -5,12 +5,12 @@
  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  */
 
-#include "catch_common.h"
 #include "catch_session.h"
 #include "catch_commandline.h"
 #include "catch_console_colour.h"
 #include "catch_enforce.h"
 #include "catch_list.h"
+#include "catch_context.h"
 #include "catch_run_context.h"
 #include "catch_stream.h"
 #include "catch_test_spec.h"
@@ -19,6 +19,9 @@
 #include "catch_random_number_generator.h"
 #include "catch_startup_exception_registry.h"
 #include "catch_text.h"
+#include "catch_stream.h"
+#include "catch_windows_h_proxy.h"
+#include "../reporters/catch_reporter_listening.h"
 
 #include <cstdlib>
 #include <iomanip>
@@ -35,33 +38,29 @@
             return reporter;
         }
 
-#ifndef CATCH_CONFIG_DEFAULT_REPORTER
-#define CATCH_CONFIG_DEFAULT_REPORTER "console"
-#endif
-
         IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) {
-            auto const& reporterNames = config->getReporterNames();
-            if (reporterNames.empty())
-                return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config);
+            if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) {
+                return createReporter(config->getReporterName(), config);
+            }
 
-            IStreamingReporterPtr reporter;
-            for (auto const& name : reporterNames)
-                addReporter(reporter, createReporter(name, config));
-            return reporter;
-        }
-
-#undef CATCH_CONFIG_DEFAULT_REPORTER
-
-        void addListeners(IStreamingReporterPtr& reporters, IConfigPtr const& config) {
+            // On older platforms, returning std::unique_ptr<ListeningReporter>
+            // when the return type is std::unique_ptr<IStreamingReporter>
+            // doesn't compile without a std::move call. However, this causes
+            // a warning on newer platforms. Thus, we have to work around
+            // it a bit and downcast the pointer manually.
+            auto ret = std::unique_ptr<IStreamingReporter>(new ListeningReporter);
+            auto& multi = static_cast<ListeningReporter&>(*ret);
             auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
-            for (auto const& listener : listeners)
-                addReporter(reporters, listener->create(Catch::ReporterConfig(config)));
+            for (auto const& listener : listeners) {
+                multi.addListener(listener->create(Catch::ReporterConfig(config)));
+            }
+            multi.addReporter(createReporter(config->getReporterName(), config));
+            return ret;
         }
 
 
         Catch::Totals runTests(std::shared_ptr<Config> const& config) {
-            IStreamingReporterPtr reporter = makeReporter(config);
-            addListeners(reporter, config);
+            auto reporter = makeReporter(config);
 
             RunContext context(config, std::move(reporter));
 
@@ -70,8 +69,6 @@
             context.testGroupStarting(config->name(), 1, 1);
 
             TestSpec testSpec = config->testSpec();
-            if (!testSpec.hasFilters())
-                testSpec = TestSpecParser(ITagAliasRegistry::get()).parse("~[.]").testSpec(); // All not hidden tests
 
             auto const& allTestCases = getAllTestCasesSorted(*config);
             for (auto const& testCase : allTestCases) {
@@ -81,6 +78,20 @@
                     context.reporter().skipTest(testCase);
             }
 
+            if (config->warnAboutNoTests() && totals.testCases.total() == 0) {
+                ReusableStringStream testConfig;
+
+                bool first = true;
+                for (const auto& input : config->getTestsOrTags()) {
+                    if (!first) { testConfig << ' '; }
+                    first = false;
+                    testConfig << input;
+                }
+
+                context.reporter().noMatchingTestCases(testConfig.str());
+                totals.error = -1;
+            }
+
             context.testGroupEnded(config->name(), totals, 1, 1);
             return totals;
         }
@@ -112,26 +123,27 @@
     Session::Session() {
         static bool alreadyInstantiated = false;
         if( alreadyInstantiated ) {
-            CATCH_INTERNAL_TRY {
-                CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" );
-            }
-            CATCH_INTERNAL_CATCH_ALL() { getMutableRegistryHub().registerStartupException(); }
+            CATCH_TRY { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); }
+            CATCH_CATCH_ALL { getMutableRegistryHub().registerStartupException(); }
         }
 
+        // There cannot be exceptions at startup in no-exception mode.
+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
         const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();
         if ( !exceptions.empty() ) {
             m_startupExceptions = true;
             Colour colourGuard( Colour::Red );
-            Catch::cerr() << "Errors occured during startup!" << '\n';
+            Catch::cerr() << "Errors occurred during startup!" << '\n';
             // iterate over all exceptions and notify user
             for ( const auto& ex_ptr : exceptions ) {
-                CATCH_INTERNAL_TRY {
+                try {
                     std::rethrow_exception(ex_ptr);
-                } CATCH_INTERNAL_CATCH ( std::exception const&, ex ) {
+                } catch ( std::exception const& ex ) {
                     Catch::cerr() << Column( ex.what() ).indent(2) << '\n';
                 }
             }
         }
+#endif
 
         alreadyInstantiated = true;
         m_cli = makeCommandLineParser( m_configData );
@@ -154,12 +166,14 @@
                 << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
     }
 
-    int Session::applyCommandLine( int argc, char* argv[] ) {
+    int Session::applyCommandLine( int argc, char const * const * argv ) {
         if( m_startupExceptions )
             return 1;
 
         auto result = m_cli.parse( clara::Args( argc, argv ) );
         if( !result ) {
+            config();
+            getCurrentMutableContext().setConfig(m_config);
             Catch::cerr()
                 << Colour( Colour::Red )
                 << "\nError(s) in input:\n"
@@ -177,22 +191,8 @@
         return 0;
     }
 
-    void Session::useConfigData( ConfigData const& configData ) {
-        m_configData = configData;
-        m_config.reset();
-    }
-
-    int Session::run( int argc, char* argv[] ) {
-        if( m_startupExceptions )
-            return 1;
-        int returnCode = applyCommandLine( argc, argv );
-        if( returnCode == 0 )
-            returnCode = run();
-        return returnCode;
-    }
-
-#if defined(WIN32) && defined(UNICODE)
-    int Session::run( int argc, wchar_t* const argv[] ) {
+#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
+    int Session::applyCommandLine( int argc, wchar_t const * const * argv ) {
 
         char **utf8Argv = new char *[ argc ];
 
@@ -204,7 +204,7 @@
             WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
         }
 
-        int returnCode = run( argc, utf8Argv );
+        int returnCode = applyCommandLine( argc, utf8Argv );
 
         for ( int i = 0; i < argc; ++i )
             delete [] utf8Argv[ i ];
@@ -214,6 +214,12 @@
         return returnCode;
     }
 #endif
+
+    void Session::useConfigData( ConfigData const& configData ) {
+        m_configData = configData;
+        m_config.reset();
+    }
+
     int Session::run() {
         if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
             Catch::cout() << "...waiting for enter/ return before starting" << std::endl;
@@ -246,11 +252,11 @@
         if( m_startupExceptions )
             return 1;
 
-        if( m_configData.showHelp || m_configData.libIdentify )
+        if (m_configData.showHelp || m_configData.libIdentify) {
             return 0;
+        }
 
-        CATCH_INTERNAL_TRY
-        {
+        CATCH_TRY {
             config(); // Force config to be constructed
 
             seedRng( *m_config );
@@ -259,18 +265,21 @@
                 applyFilenamesAsTags( *m_config );
 
             // Handle list request
-            if( Option<std::size_t> listed = list( config() ) )
+            if( Option<std::size_t> listed = list( m_config ) )
                 return static_cast<int>( *listed );
 
+            auto totals = runTests( m_config );
             // Note that on unices only the lower 8 bits are usually used, clamping
             // the return value to 255 prevents false negative when some multiple
             // of 256 tests has failed
-            return (std::min)( MaxExitCode, static_cast<int>( runTests( m_config ).assertions.failed ) );
+            return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed)));
         }
-        CATCH_INTERNAL_CATCH ( std::exception&, ex ) {
+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
+        catch( std::exception& ex ) {
             Catch::cerr() << ex.what() << std::endl;
             return MaxExitCode;
         }
+#endif
     }
 
 } // end namespace Catch
diff --git a/include/internal/catch_session.h b/include/internal/catch_session.h
index b814aa6..af820da 100644
--- a/include/internal/catch_session.h
+++ b/include/internal/catch_session.h
@@ -25,14 +25,23 @@
         void showHelp() const;
         void libIdentify();
 
-        int applyCommandLine( int argc, char* argv[] );
+        int applyCommandLine( int argc, char const * const * argv );
+    #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
+        int applyCommandLine( int argc, wchar_t const * const * argv );
+    #endif
 
         void useConfigData( ConfigData const& configData );
 
-        int run( int argc, char* argv[] );
-    #if defined(WIN32) && defined(UNICODE)
-        int run( int argc, wchar_t* const argv[] );
-    #endif
+        template<typename CharT>
+        int run(int argc, CharT const * const argv[]) {
+            if (m_startupExceptions)
+                return 1;
+            int returnCode = applyCommandLine(argc, argv);
+            if (returnCode == 0)
+                returnCode = run();
+            return returnCode;
+        }
+    
         int run();
 
         clara::Parser const& cli() const;
diff --git a/include/internal/catch_singletons.cpp b/include/internal/catch_singletons.cpp
new file mode 100644
index 0000000..e5367ca
--- /dev/null
+++ b/include/internal/catch_singletons.cpp
@@ -0,0 +1,36 @@
+/*
+ *  Created by Phil Nash on 15/6/2018.
+ *
+ *  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_singletons.hpp"
+
+#include <vector>
+
+namespace Catch {
+
+    namespace {
+        static auto getSingletons() -> std::vector<ISingleton*>*& {
+            static std::vector<ISingleton*>* g_singletons = nullptr;
+            if( !g_singletons )
+                g_singletons = new std::vector<ISingleton*>();
+            return g_singletons;
+        }
+    }
+
+    ISingleton::~ISingleton() {}
+
+    void addSingleton(ISingleton* singleton ) {
+        getSingletons()->push_back( singleton );
+    }
+    void cleanupSingletons() {
+        auto& singletons = getSingletons();
+        for( auto singleton : *singletons )
+            delete singleton;
+        delete singletons;
+        singletons = nullptr;
+    }
+
+} // namespace Catch
diff --git a/include/internal/catch_singletons.hpp b/include/internal/catch_singletons.hpp
new file mode 100644
index 0000000..fbc4b32
--- /dev/null
+++ b/include/internal/catch_singletons.hpp
@@ -0,0 +1,44 @@
+/*
+ *  Created by Phil Nash on 15/6/2018.
+ *
+ *  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_SINGLETONS_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_SINGLETONS_HPP_INCLUDED
+
+namespace Catch {
+
+    struct ISingleton {
+        virtual ~ISingleton();
+    };
+
+
+    void addSingleton( ISingleton* singleton );
+    void cleanupSingletons();
+
+
+    template<typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT>
+    class Singleton : SingletonImplT, public ISingleton {
+
+        static auto getInternal() -> Singleton* {
+            static Singleton* s_instance = nullptr;
+            if( !s_instance ) {
+                s_instance = new Singleton;
+                addSingleton( s_instance );
+            }
+            return s_instance;
+        }
+
+    public:
+        static auto get() -> InterfaceT const& {
+            return *getInternal();
+        }
+        static auto getMutable() -> MutableInterfaceT& {
+            return *getInternal();
+        }
+    };
+
+} // namespace Catch
+
+#endif // TWOBLUECUBES_CATCH_SINGLETONS_HPP_INCLUDED
diff --git a/include/internal/catch_startup_exception_registry.cpp b/include/internal/catch_startup_exception_registry.cpp
index 7eae84f..3c5bd22 100644
--- a/include/internal/catch_startup_exception_registry.cpp
+++ b/include/internal/catch_startup_exception_registry.cpp
@@ -7,14 +7,13 @@
  */
 
 #include "catch_startup_exception_registry.h"
-#include "catch_common.h"
+#include "catch_compiler_capabilities.h"
 
 namespace Catch {
-    void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept {
-        CATCH_INTERNAL_TRY {
+void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept {
+        CATCH_TRY {
             m_exceptions.push_back(exception);
-        }
-        CATCH_INTERNAL_CATCH_ALL() {
+        } CATCH_CATCH_ALL {
             // If we run out of memory during start-up there's really not a lot more we can do about it
             std::terminate();
         }
diff --git a/include/internal/catch_stream.cpp b/include/internal/catch_stream.cpp
index 125fd47..ba2d2be 100644
--- a/include/internal/catch_stream.cpp
+++ b/include/internal/catch_stream.cpp
@@ -12,6 +12,7 @@
 #include "catch_stream.h"
 #include "catch_debug_console.h"
 #include "catch_stringref.h"
+#include "catch_singletons.hpp"
 
 #include <cstdio>
 #include <iostream>
@@ -20,11 +21,6 @@
 #include <vector>
 #include <memory>
 
-#if defined(__clang__)
-#    pragma clang diagnostic push
-#    pragma clang diagnostic ignored "-Wexit-time-destructors"
-#endif
-
 namespace Catch {
 
     Catch::IStream::~IStream() = default;
@@ -145,7 +141,6 @@
         std::vector<std::unique_ptr<std::ostringstream>> m_streams;
         std::vector<std::size_t> m_unused;
         std::ostringstream m_referenceStream; // Used for copy state/ flags from
-        static StringStreams* s_instance;
 
         auto add() -> std::size_t {
             if( m_unused.empty() ) {
@@ -163,34 +158,17 @@
             m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state
             m_unused.push_back(index);
         }
-
-        // !TBD: put in TLS
-        static auto instance() -> StringStreams& {
-            if( !s_instance )
-                s_instance = new StringStreams();
-            return *s_instance;
-        }
-        static void cleanup() {
-            delete s_instance;
-            s_instance = nullptr;
-        }
     };
 
-    StringStreams* StringStreams::s_instance = nullptr;
-
-    void ReusableStringStream::cleanup() {
-        StringStreams::cleanup();
-    }
-
     ReusableStringStream::ReusableStringStream()
-    :   m_index( StringStreams::instance().add() ),
-        m_oss( StringStreams::instance().m_streams[m_index].get() )
+    :   m_index( Singleton<StringStreams>::getMutable().add() ),
+        m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].get() )
     {}
 
     ReusableStringStream::~ReusableStringStream() {
         static_cast<std::ostringstream*>( m_oss )->str("");
         m_oss->clear();
-        StringStreams::instance().release( m_index );
+        Singleton<StringStreams>::getMutable().release( m_index );
     }
 
     auto ReusableStringStream::str() const -> std::string {
@@ -207,7 +185,3 @@
     std::ostream& clog() { return std::clog; }
 #endif
 }
-
-#if defined(__clang__)
-#    pragma clang diagnostic pop
-#endif
diff --git a/include/internal/catch_stream.h b/include/internal/catch_stream.h
index c5e78b2..2b41adb 100644
--- a/include/internal/catch_stream.h
+++ b/include/internal/catch_stream.h
@@ -43,8 +43,6 @@
             return *this;
         }
         auto get() -> std::ostream& { return *m_oss; }
-
-        static void cleanup();
     };
 }
 
diff --git a/include/internal/catch_string_manip.cpp b/include/internal/catch_string_manip.cpp
index 8476204..904d101 100644
--- a/include/internal/catch_string_manip.cpp
+++ b/include/internal/catch_string_manip.cpp
@@ -14,6 +14,12 @@
 
 namespace Catch {
 
+    namespace {
+        char toLowerCh(char c) {
+            return static_cast<char>( std::tolower( c ) );
+        }
+    }
+
     bool startsWith( std::string const& s, std::string const& prefix ) {
         return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
     }
@@ -29,9 +35,6 @@
     bool contains( std::string const& s, std::string const& infix ) {
         return s.find( infix ) != std::string::npos;
     }
-    char toLowerCh(char c) {
-        return static_cast<char>( std::tolower( c ) );
-    }
     void toLowerInPlace( std::string& s ) {
         std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
     }
diff --git a/include/internal/catch_stringref.cpp b/include/internal/catch_stringref.cpp
index b0b2f8e..9e9095e 100644
--- a/include/internal/catch_stringref.cpp
+++ b/include/internal/catch_stringref.cpp
@@ -43,7 +43,7 @@
            const_cast<StringRef*>( this )->takeOwnership();
         return m_start;
     }
-    auto StringRef::data() const noexcept -> char const* {
+    auto StringRef::currentData() const noexcept -> char const* {
         return m_start;
     }
 
@@ -112,7 +112,12 @@
     }
 
     auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& {
-        return os << str.c_str();
+        return os.write(str.currentData(), str.size());
+    }
+
+    auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& {
+        lhs.append(rhs.currentData(), rhs.size());
+        return lhs;
     }
 
 } // namespace Catch
diff --git a/include/internal/catch_stringref.h b/include/internal/catch_stringref.h
index 0f9e780..64f595b 100644
--- a/include/internal/catch_stringref.h
+++ b/include/internal/catch_stringref.h
@@ -12,8 +12,6 @@
 #include <iosfwd>
 
 namespace Catch {
-    
-    class StringData;
 
     /// A non-owning string class (similar to the forthcoming std::string_view)
     /// Note that, because a StringRef may be a substring of another string,
@@ -31,13 +29,13 @@
 
         char const* m_start;
         size_type m_size;
-        
+
         char* m_data = nullptr;
-        
+
         void takeOwnership();
 
         static constexpr char const* const s_empty = "";
-        
+
     public: // construction/ assignment
         StringRef() noexcept
         :   StringRef( s_empty, 0 )
@@ -83,13 +81,13 @@
         operator std::string() const;
 
         void swap( StringRef& other ) noexcept;
-        
+
     public: // operators
         auto operator == ( StringRef const& other ) const noexcept -> bool;
         auto operator != ( StringRef const& other ) const noexcept -> bool;
-        
+
         auto operator[] ( size_type index ) const noexcept -> char;
-        
+
     public: // named queries
         auto empty() const noexcept -> bool {
             return m_size == 0;
@@ -100,26 +98,35 @@
 
         auto numberOfCharacters() const noexcept -> size_type;
         auto c_str() const -> char const*;
-        
+
     public: // substrings and searches
         auto substr( size_type start, size_type size ) const noexcept -> StringRef;
 
+        // Returns the current start pointer.
+        // Note that the pointer can change when if the StringRef is a substring
+        auto currentData() const noexcept -> char const*;
+
     private: // ownership queries - may not be consistent between calls
         auto isOwned() const noexcept -> bool;
         auto isSubstring() const noexcept -> bool;
-        auto data() const noexcept -> char const*;
     };
 
     auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string;
     auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string;
     auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string;
 
+    auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&;
     auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&;
 
+
     inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {
         return StringRef( rawChars, size );
     }
 
 } // namespace Catch
 
+inline auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef {
+    return Catch::StringRef( rawChars, size );
+}
+
 #endif // CATCH_STRINGREF_H_INCLUDED
diff --git a/include/internal/catch_suppress_warnings.h b/include/internal/catch_suppress_warnings.h
index 9280114..dc8c1da 100644
--- a/include/internal/catch_suppress_warnings.h
+++ b/include/internal/catch_suppress_warnings.h
@@ -10,15 +10,18 @@
 #       pragma warning(push)
 #       pragma warning(disable: 161 1682)
 #   else // __ICC
-#       pragma clang diagnostic ignored "-Wunused-variable"
 #       pragma clang diagnostic push
 #       pragma clang diagnostic ignored "-Wpadded"
 #       pragma clang diagnostic ignored "-Wswitch-enum"
 #       pragma clang diagnostic ignored "-Wcovered-switch-default"
 #    endif
 #elif defined __GNUC__
-#    pragma GCC diagnostic ignored "-Wunused-variable"
-#    pragma GCC diagnostic ignored "-Wparentheses"
+     // Because REQUIREs trigger GCC's -Wparentheses, and because still
+     // supported version of g++ have only buggy support for _Pragmas,
+     // Wparentheses have to be suppressed globally.
+#    pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details
+
 #    pragma GCC diagnostic push
+#    pragma GCC diagnostic ignored "-Wunused-variable"
 #    pragma GCC diagnostic ignored "-Wpadded"
 #endif
diff --git a/include/internal/catch_tag_alias_autoregistrar.cpp b/include/internal/catch_tag_alias_autoregistrar.cpp
index b5c6ce9..6a292ed 100644
--- a/include/internal/catch_tag_alias_autoregistrar.cpp
+++ b/include/internal/catch_tag_alias_autoregistrar.cpp
@@ -1,12 +1,13 @@
 #include "catch_tag_alias_autoregistrar.h"
+#include "catch_compiler_capabilities.h"
 #include "catch_interfaces_registry_hub.h"
 
 namespace Catch {
-    
+
     RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) {
-        CATCH_INTERNAL_TRY {
+        CATCH_TRY {
             getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo);
-        } CATCH_INTERNAL_CATCH_ALL() {
+        } CATCH_CATCH_ALL {
             // Do not throw when constructing global objects, instead register the exception to be processed later
             getMutableRegistryHub().registerStartupException();
         }
diff --git a/include/internal/catch_test_case_info.cpp b/include/internal/catch_test_case_info.cpp
index 4ab9775..536462d 100644
--- a/include/internal/catch_test_case_info.cpp
+++ b/include/internal/catch_test_case_info.cpp
@@ -19,37 +19,38 @@
 
 namespace Catch {
 
-    TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
-        if( startsWith( tag, '.' ) ||
-            tag == "!hide" )
-            return TestCaseInfo::IsHidden;
-        else if( tag == "!throws" )
-            return TestCaseInfo::Throws;
-        else if( tag == "!shouldfail" )
-            return TestCaseInfo::ShouldFail;
-        else if( tag == "!mayfail" )
-            return TestCaseInfo::MayFail;
-        else if( tag == "!nonportable" )
-            return TestCaseInfo::NonPortable;
-        else if( tag == "!benchmark" )
-            return static_cast<TestCaseInfo::SpecialProperties>( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden );
-        else
-            return TestCaseInfo::None;
-    }
-    bool isReservedTag( std::string const& tag ) {
-        return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] );
-    }
-    void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
-        CATCH_ENFORCE( !isReservedTag(tag),
-                      "Tag name: [" << tag << "] is not allowed.\n"
-                      << "Tag names starting with non alpha-numeric characters are reserved\n"
-                      << _lineInfo );
+    namespace {
+        TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
+            if( startsWith( tag, '.' ) ||
+                tag == "!hide" )
+                return TestCaseInfo::IsHidden;
+            else if( tag == "!throws" )
+                return TestCaseInfo::Throws;
+            else if( tag == "!shouldfail" )
+                return TestCaseInfo::ShouldFail;
+            else if( tag == "!mayfail" )
+                return TestCaseInfo::MayFail;
+            else if( tag == "!nonportable" )
+                return TestCaseInfo::NonPortable;
+            else if( tag == "!benchmark" )
+                return static_cast<TestCaseInfo::SpecialProperties>( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden );
+            else
+                return TestCaseInfo::None;
+        }
+        bool isReservedTag( std::string const& tag ) {
+            return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( static_cast<unsigned char>(tag[0]) );
+        }
+        void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
+            CATCH_ENFORCE( !isReservedTag(tag),
+                          "Tag name: [" << tag << "] is not allowed.\n"
+                          << "Tag names starting with non alpha-numeric characters are reserved\n"
+                          << _lineInfo );
+        }
     }
 
     TestCase makeTestCase(  ITestInvoker* _testCase,
                             std::string const& _className,
-                            std::string const& _name,
-                            std::string const& _descOrTags,
+                            NameAndTags const& nameAndTags,
                             SourceLineInfo const& _lineInfo )
     {
         bool isHidden = false;
@@ -58,6 +59,7 @@
         std::vector<std::string> tags;
         std::string desc, tag;
         bool inTag = false;
+        std::string _descOrTags = nameAndTags.tags;
         for (char c : _descOrTags) {
             if( !inTag ) {
                 if( c == '[' )
@@ -85,8 +87,8 @@
             tags.push_back( "." );
         }
 
-        TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
-        return TestCase( _testCase, info );
+        TestCaseInfo info( nameAndTags.name, _className, desc, tags, _lineInfo );
+        return TestCase( _testCase, std::move(info) );
     }
 
     void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) {
@@ -147,7 +149,7 @@
     }
 
 
-    TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
+    TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo( std::move(info) ), test( testCase ) {}
 
 
     TestCase TestCase::withName( std::string const& _newName ) const {
diff --git a/include/internal/catch_test_case_info.h b/include/internal/catch_test_case_info.h
index 2a911b0..809c974 100644
--- a/include/internal/catch_test_case_info.h
+++ b/include/internal/catch_test_case_info.h
@@ -9,6 +9,7 @@
 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
 
 #include "catch_common.h"
+#include "catch_test_registry.h"
 
 #include <string>
 #include <vector>
@@ -61,7 +62,7 @@
     class TestCase : public TestCaseInfo {
     public:
 
-        TestCase( ITestInvoker* testCase, TestCaseInfo const& info );
+        TestCase( ITestInvoker* testCase, TestCaseInfo&& info );
 
         TestCase withName( std::string const& _newName ) const;
 
@@ -78,8 +79,7 @@
 
     TestCase makeTestCase(  ITestInvoker* testCase,
                             std::string const& className,
-                            std::string const& name,
-                            std::string const& description,
+                            NameAndTags const& nameAndTags,
                             SourceLineInfo const& lineInfo );
 }
 
diff --git a/include/internal/catch_test_case_registry_impl.cpp b/include/internal/catch_test_case_registry_impl.cpp
index 89c7239..a6b7f57 100644
--- a/include/internal/catch_test_case_registry_impl.cpp
+++ b/include/internal/catch_test_case_registry_impl.cpp
@@ -28,7 +28,7 @@
                 break;
             case RunTests::InRandomOrder:
                 seedRng( config );
-                RandomNumberGenerator::shuffle( sorted );
+                std::shuffle( sorted.begin(), sorted.end(), rng() );
                 break;
             case RunTests::InDeclarationOrder:
                 // already in declaration order
@@ -96,7 +96,7 @@
         m_testAsFunction();
     }
 
-    std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
+    std::string extractClassName( StringRef const& classOrQualifiedMethodName ) {
         std::string className = classOrQualifiedMethodName;
         if( startsWith( className, '&' ) )
         {
diff --git a/include/internal/catch_test_case_registry_impl.h b/include/internal/catch_test_case_registry_impl.h
index ad45e5a..8dc5b0f 100644
--- a/include/internal/catch_test_case_registry_impl.h
+++ b/include/internal/catch_test_case_registry_impl.h
@@ -22,7 +22,7 @@
     class TestCase;
     struct IConfig;
 
-    std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ); 
+    std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases );
     bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
 
     void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions );
@@ -58,7 +58,7 @@
     };
 
 
-    std::string extractClassName( std::string const& classOrQualifiedMethodName );
+    std::string extractClassName( StringRef const& classOrQualifiedMethodName );
 
     ///////////////////////////////////////////////////////////////////////////
 
diff --git a/include/internal/catch_test_case_tracker.cpp b/include/internal/catch_test_case_tracker.cpp
index 66da89e..210f273 100644
--- a/include/internal/catch_test_case_tracker.cpp
+++ b/include/internal/catch_test_case_tracker.cpp
@@ -10,7 +10,7 @@
 #include "catch_enforce.h"
 
 #include <algorithm>
-#include <assert.h>
+#include <cassert>
 #include <stdexcept>
 #include <memory>
 #include <sstream>
@@ -69,14 +69,6 @@
     }
 
 
-
-    TrackerBase::TrackerHasName::TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {}
-    bool TrackerBase::TrackerHasName::operator ()( ITrackerPtr const& tracker ) const {
-        return
-            tracker->nameAndLocation().name == m_nameAndLocation.name &&
-            tracker->nameAndLocation().location == m_nameAndLocation.location;
-    }
-
     TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
     :   m_nameAndLocation( nameAndLocation ),
         m_ctx( ctx ),
@@ -105,7 +97,12 @@
     }
 
     ITrackerPtr TrackerBase::findChild( NameAndLocation const& nameAndLocation ) {
-        auto it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) );
+        auto it = std::find_if( m_children.begin(), m_children.end(),
+            [&nameAndLocation]( ITrackerPtr const& tracker ){
+                return
+                    tracker->nameAndLocation().location == nameAndLocation.location &&
+                    tracker->nameAndLocation().name == nameAndLocation.name;
+            } );
         return( it != m_children.end() )
             ? *it
             : nullptr;
@@ -124,7 +121,7 @@
     }
 
     bool TrackerBase::isSectionTracker() const { return false; }
-    bool TrackerBase::isIndexTracker() const { return false; }
+    bool TrackerBase::isGeneratorTracker() const { return false; }
 
     void TrackerBase::open() {
         m_runState = Executing;
@@ -193,6 +190,17 @@
         }
     }
 
+    bool SectionTracker::isComplete() const {
+        bool complete = true;
+
+        if ((m_filters.empty() || m_filters[0] == "") ||
+             std::find(m_filters.begin(), m_filters.end(),
+                       m_nameAndLocation.name) != m_filters.end())
+            complete = TrackerBase::isComplete();
+        return complete;
+
+    }
+
     bool SectionTracker::isSectionTracker() const { return true; }
 
     SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
@@ -230,55 +238,11 @@
             m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() );
     }
 
-    IndexTracker::IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size )
-    :   TrackerBase( nameAndLocation, ctx, parent ),
-        m_size( size )
-    {}
-
-    bool IndexTracker::isIndexTracker() const { return true; }
-
-    IndexTracker& IndexTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) {
-        std::shared_ptr<IndexTracker> tracker;
-
-        ITracker& currentTracker = ctx.currentTracker();
-        if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
-            assert( childTracker );
-            assert( childTracker->isIndexTracker() );
-            tracker = std::static_pointer_cast<IndexTracker>( childTracker );
-        }
-        else {
-            tracker = std::make_shared<IndexTracker>( nameAndLocation, ctx, &currentTracker, size );
-            currentTracker.addChild( tracker );
-        }
-
-        if( !ctx.completedCycle() && !tracker->isComplete() ) {
-            if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
-                tracker->moveNext();
-            tracker->open();
-        }
-
-        return *tracker;
-    }
-
-    int IndexTracker::index() const { return m_index; }
-
-    void IndexTracker::moveNext() {
-        m_index++;
-        m_children.clear();
-    }
-
-    void IndexTracker::close() {
-        TrackerBase::close();
-        if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
-            m_runState = Executing;
-    }
-
 } // namespace TestCaseTracking
 
 using TestCaseTracking::ITracker;
 using TestCaseTracking::TrackerContext;
 using TestCaseTracking::SectionTracker;
-using TestCaseTracking::IndexTracker;
 
 } // namespace Catch
 
diff --git a/include/internal/catch_test_case_tracker.h b/include/internal/catch_test_case_tracker.h
index a4b0440..1727600 100644
--- a/include/internal/catch_test_case_tracker.h
+++ b/include/internal/catch_test_case_tracker.h
@@ -54,7 +54,7 @@
 
         // Debug/ checking
         virtual bool isSectionTracker() const = 0;
-        virtual bool isIndexTracker() const = 0;
+        virtual bool isGeneratorTracker() const = 0;
     };
 
     class TrackerContext {
@@ -95,13 +95,6 @@
             Failed
         };
 
-        class TrackerHasName {
-            NameAndLocation m_nameAndLocation;
-        public:
-            TrackerHasName( NameAndLocation const& nameAndLocation );
-            bool operator ()( ITrackerPtr const& tracker ) const;
-        };
-
         using Children = std::vector<ITrackerPtr>;
         NameAndLocation m_nameAndLocation;
         TrackerContext& m_ctx;
@@ -127,7 +120,7 @@
         void openChild() override;
 
         bool isSectionTracker() const override;
-        bool isIndexTracker() const override;
+        bool isGeneratorTracker() const override;
 
         void open();
 
@@ -147,6 +140,8 @@
 
         bool isSectionTracker() const override;
 
+        bool isComplete() const override;
+
         static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation );
 
         void tryOpen();
@@ -155,28 +150,11 @@
         void addNextFilters( std::vector<std::string> const& filters );
     };
 
-    class IndexTracker : public TrackerBase {
-        int m_size;
-        int m_index = -1;
-    public:
-        IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size );
-
-        bool isIndexTracker() const override;
-        void close() override;
-
-        static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size );
-
-        int index() const;
-
-        void moveNext();
-    };
-
 } // namespace TestCaseTracking
 
 using TestCaseTracking::ITracker;
 using TestCaseTracking::TrackerContext;
 using TestCaseTracking::SectionTracker;
-using TestCaseTracking::IndexTracker;
 
 } // namespace Catch
 
diff --git a/include/internal/catch_test_registry.cpp b/include/internal/catch_test_registry.cpp
index 0f6c83e..248bee4 100644
--- a/include/internal/catch_test_registry.cpp
+++ b/include/internal/catch_test_registry.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "catch_test_registry.h"
+#include "catch_compiler_capabilities.h"
 #include "catch_test_case_registry_impl.h"
 #include "catch_interfaces_registry_hub.h"
 
@@ -15,23 +16,22 @@
         return new(std::nothrow) TestInvokerAsFunction( testAsFunction );
     }
 
-    NameAndTags::NameAndTags( StringRef name_ , StringRef tags_ ) noexcept : name( name_ ), tags( tags_ ) {}
+    NameAndTags::NameAndTags( StringRef const& name_ , StringRef const& tags_ ) noexcept : name( name_ ), tags( tags_ ) {}
 
-    AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept {
-        CATCH_INTERNAL_TRY {
+    AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept {
+        CATCH_TRY {
             getMutableRegistryHub()
                     .registerTest(
                         makeTestCase(
                             invoker,
                             extractClassName( classOrMethod ),
-                            nameAndTags.name,
-                            nameAndTags.tags,
+                            nameAndTags,
                             lineInfo));
-        } CATCH_INTERNAL_CATCH_ALL() {
+        } CATCH_CATCH_ALL {
             // Do not throw when constructing global objects, instead register the exception to be processed later
             getMutableRegistryHub().registerStartupException();
         }
     }
-    
+
     AutoReg::~AutoReg() = default;
 }
diff --git a/include/internal/catch_test_registry.h b/include/internal/catch_test_registry.h
index 8400101..0e7b53d 100644
--- a/include/internal/catch_test_registry.h
+++ b/include/internal/catch_test_registry.h
@@ -12,6 +12,9 @@
 #include "catch_interfaces_testcase.h"
 #include "catch_compiler_capabilities.h"
 #include "catch_stringref.h"
+#include "catch_type_traits.hpp"
+#include "catch_preprocessor.hpp"
+#include "catch_meta.hpp"
 
 namespace Catch {
 
@@ -35,13 +38,13 @@
 }
 
 struct NameAndTags {
-    NameAndTags( StringRef name_ = StringRef(), StringRef tags_ = StringRef() ) noexcept;
+    NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept;
     StringRef name;
     StringRef tags;
 };
 
 struct AutoReg : NonCopyable {
-    AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept;
+    AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept;
     ~AutoReg();
 };
 
@@ -52,19 +55,30 @@
         static void TestName()
     #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
         namespace{                        \
-            struct TestName : ClassName { \
+            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
                 void test();              \
             };                            \
         }                                 \
         void TestName::test()
-
+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION( TestName, ... )  \
+        template<typename TestType>                                             \
+        static void TestName()
+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... )    \
+        namespace{                                                                                  \
+            template<typename TestType>                                                             \
+            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) {     \
+                void test();                                                                        \
+            };                                                                                      \
+        }                                                                                           \
+        template<typename TestType>                                                                 \
+        void TestName::test()
 #endif
 
     ///////////////////////////////////////////////////////////////////////////////
     #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
         static void TestName(); \
         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
-        namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
+        namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
         CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
         static void TestName()
     #define INTERNAL_CATCH_TESTCASE( ... ) \
@@ -80,7 +94,7 @@
     #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
         namespace{ \
-            struct TestName : ClassName{ \
+            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
                 void test(); \
             }; \
             Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
@@ -93,8 +107,151 @@
     ///////////////////////////////////////////////////////////////////////////////
     #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
-        Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
+        Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
         CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
 
+    ///////////////////////////////////////////////////////////////////////////////
+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, ... )\
+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+        template<typename TestType> \
+        static void TestFunc();\
+        namespace {\
+            template<typename...Types> \
+            struct TestName{\
+                template<typename...Ts> \
+                TestName(Ts...names){\
+                    CATCH_INTERNAL_CHECK_UNIQUE_TYPES(CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \
+                    using expander = int[];\
+                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ names, Tags } ), 0)... };/* NOLINT */ \
+                }\
+            };\
+            INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, __VA_ARGS__) \
+        }\
+        CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
+        template<typename TestType> \
+        static void TestFunc()
+
+#if defined(CATCH_CPP17_OR_GREATER)
+#define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) static_assert(Catch::is_unique<__VA_ARGS__>,"Duplicate type detected in declaration of template test case");
+#else
+#define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) static_assert(Catch::is_unique<__VA_ARGS__>::value,"Duplicate type detected in declaration of template test case");
+#endif
+
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
+        INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ )
+#else
+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ ) )
+#endif
+
+    #define INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, ...)\
+        static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
+            TestName<CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)>(CATCH_REC_LIST_UD(INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME,Name, __VA_ARGS__));\
+            return 0;\
+        }();
+
+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, TmplTypes, TypesList) \
+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS                      \
+        template<typename TestType> static void TestFuncName();       \
+        namespace {                                                   \
+            template<typename... Types>                               \
+            struct TestName {                                         \
+                TestName() {                                          \
+                    CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...)       \
+                    int index = 0;                                    \
+                    using expander = int[];                           \
+                    constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
+                    constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
+                    constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
+                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */\
+                }                                                     \
+            };                                                        \
+            static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
+                using TestInit = Catch::combine<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)> \
+                            ::with_types<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(TypesList)>::into<TestName>::type; \
+                TestInit();                                           \
+                return 0;                                             \
+            }();                                                      \
+        }                                                             \
+        CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS                    \
+        template<typename TestType>                                   \
+        static void TestFuncName()
+
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
+        INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ),Name,Tags,__VA_ARGS__)
+#else
+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ ) )
+#endif
+
+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, ... ) \
+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+        namespace{ \
+            template<typename TestType> \
+            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
+                void test();\
+            };\
+            template<typename...Types> \
+            struct TestNameClass{\
+                template<typename...Ts> \
+                TestNameClass(Ts...names){\
+                    CATCH_INTERNAL_CHECK_UNIQUE_TYPES(CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \
+                    using expander = int[];\
+                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ names, Tags } ), 0)... };/* NOLINT */ \
+                }\
+            };\
+            INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestNameClass, Name, __VA_ARGS__)\
+        }\
+        CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS\
+        template<typename TestType> \
+        void TestName<TestType>::test()
+
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
+        INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, __VA_ARGS__ )
+#else
+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, __VA_ARGS__ ) )
+#endif
+
+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, TmplTypes, TypesList)\
+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+        template<typename TestType> \
+            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
+                void test();\
+            };\
+        namespace {\
+            template<typename...Types>\
+            struct TestNameClass{\
+                TestNameClass(){\
+                    CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...)\
+                    int index = 0;\
+                    using expander = int[];\
+                    constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
+                    constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
+                    constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
+                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */ \
+                }\
+            };\
+            static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
+                using TestInit = Catch::combine<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>\
+                            ::with_types<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(TypesList)>::into<TestNameClass>::type;\
+                TestInit();\
+                return 0;\
+            }(); \
+        }\
+        CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
+        template<typename TestType> \
+        void TestName<TestType>::test()
+
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
+        INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, __VA_ARGS__ )
+#else
+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, __VA_ARGS__ ) )
+#endif
 
 #endif // TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
diff --git a/include/internal/catch_timer.cpp b/include/internal/catch_timer.cpp
index b9ae688..ca383a2 100644
--- a/include/internal/catch_timer.cpp
+++ b/include/internal/catch_timer.cpp
@@ -10,32 +10,44 @@
 
 #include <chrono>
 
+static const uint64_t nanosecondsInSecond = 1000000000;
+
 namespace Catch {
 
     auto getCurrentNanosecondsSinceEpoch() -> uint64_t {
         return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count();
     }
 
-    auto estimateClockResolution() -> uint64_t {
-        uint64_t sum = 0;
-        static const uint64_t iterations = 1000000;
+    namespace {
+        auto estimateClockResolution() -> uint64_t {
+            uint64_t sum = 0;
+            static const uint64_t iterations = 1000000;
 
-        for( std::size_t i = 0; i < iterations; ++i ) {
+            auto startTime = getCurrentNanosecondsSinceEpoch();
 
-            uint64_t ticks;
-            uint64_t baseTicks = getCurrentNanosecondsSinceEpoch();
-            do {
-                ticks = getCurrentNanosecondsSinceEpoch();
+            for( std::size_t i = 0; i < iterations; ++i ) {
+
+                uint64_t ticks;
+                uint64_t baseTicks = getCurrentNanosecondsSinceEpoch();
+                do {
+                    ticks = getCurrentNanosecondsSinceEpoch();
+                } while( ticks == baseTicks );
+
+                auto delta = ticks - baseTicks;
+                sum += delta;
+
+                // If we have been calibrating for over 3 seconds -- the clock
+                // is terrible and we should move on.
+                // TBD: How to signal that the measured resolution is probably wrong?
+                if (ticks > startTime + 3 * nanosecondsInSecond) {
+                    return sum / ( i + 1u );
+                }
             }
-            while( ticks == baseTicks );
 
-            auto delta = ticks - baseTicks;
-            sum += delta;
+            // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers
+            // - and potentially do more iterations if there's a high variance.
+            return sum/iterations;
         }
-
-        // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers
-        // - and potentially do more iterations if there's a high variance.
-        return sum/iterations;
     }
     auto getEstimatedClockResolution() -> uint64_t {
         static auto s_resolution = estimateClockResolution();
diff --git a/include/internal/catch_to_string.hpp b/include/internal/catch_to_string.hpp
new file mode 100644
index 0000000..3e2b587
--- /dev/null
+++ b/include/internal/catch_to_string.hpp
@@ -0,0 +1,28 @@
+/*
+ *  Created by Martin on 9/5/2018.
+ *
+ *  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_TO_STRING_H_INCLUDED
+#define TWOBLUECUBES_CATCH_TO_STRING_H_INCLUDED
+
+#include <string>
+
+#include "catch_compiler_capabilities.h"
+#include "catch_stream.h"
+
+namespace Catch {
+    template <typename T>
+    std::string to_string(T const& t) {
+#if defined(CATCH_CONFIG_CPP11_TO_STRING)
+        return std::to_string(t);
+#else
+        ReusableStringStream rss;
+        rss << t;
+        return rss.str();
+#endif
+    }
+} // end namespace Catch
+
+#endif // TWOBLUECUBES_CATCH_TO_STRING_H_INCLUDED
diff --git a/include/internal/catch_tostring.cpp b/include/internal/catch_tostring.cpp
index a9f7735..b857d3f 100644
--- a/include/internal/catch_tostring.cpp
+++ b/include/internal/catch_tostring.cpp
@@ -20,6 +20,7 @@
 #include "catch_tostring.h"
 #include "catch_interfaces_config.h"
 #include "catch_context.h"
+#include "catch_polyfills.hpp"
 
 #include <cmath>
 #include <iomanip>
@@ -68,7 +69,7 @@
 
 template<typename T>
 std::string fpToString( T value, int precision ) {
-    if (std::isnan(value)) {
+    if (Catch::isnan(value)) {
         return "nan";
     }
 
@@ -116,14 +117,11 @@
     return s;
 }
 
-std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) {
-    std::string s;
-    s.reserve(wstr.size());
-    for (auto c : wstr) {
-        s += (c <= 0xff) ? static_cast<char>(c) : '?';
-    }
-    return ::Catch::Detail::stringify(s);
+#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
+std::string StringMaker<std::string_view>::convert(std::string_view str) {
+    return ::Catch::Detail::stringify(std::string{ str });
 }
+#endif
 
 std::string StringMaker<char const*>::convert(char const* str) {
     if (str) {
@@ -139,6 +137,23 @@
         return{ "{null string}" };
     }
 }
+
+#ifdef CATCH_CONFIG_WCHAR
+std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) {
+    std::string s;
+    s.reserve(wstr.size());
+    for (auto c : wstr) {
+        s += (c <= 0xff) ? static_cast<char>(c) : '?';
+    }
+    return ::Catch::Detail::stringify(s);
+}
+
+# ifdef CATCH_CONFIG_CPP17_STRING_VIEW
+std::string StringMaker<std::wstring_view>::convert(std::wstring_view str) {
+    return StringMaker<std::wstring>::convert(std::wstring(str));
+}
+# endif
+
 std::string StringMaker<wchar_t const*>::convert(wchar_t const * str) {
     if (str) {
         return ::Catch::Detail::stringify(std::wstring{ str });
@@ -153,6 +168,7 @@
         return{ "{null string}" };
     }
 }
+#endif
 
 
 std::string StringMaker<int>::convert(int value) {
@@ -190,7 +206,7 @@
     return b ? "true" : "false";
 }
 
-std::string StringMaker<char>::convert(char value) {
+std::string StringMaker<signed char>::convert(signed char value) {
     if (value == '\r') {
         return "'\\r'";
     } else if (value == '\f') {
@@ -207,8 +223,8 @@
         return chstr;
     }
 }
-std::string StringMaker<signed char>::convert(signed char c) {
-    return ::Catch::Detail::stringify(static_cast<char>(c));
+std::string StringMaker<char>::convert(char c) {
+    return ::Catch::Detail::stringify(static_cast<signed char>(c));
 }
 std::string StringMaker<unsigned char>::convert(unsigned char c) {
     return ::Catch::Detail::stringify(static_cast<char>(c));
@@ -227,12 +243,11 @@
 
 std::string ratio_string<std::atto>::symbol() { return "a"; }
 std::string ratio_string<std::femto>::symbol() { return "f"; }
-std::string  ratio_string<std::pico>::symbol() { return "p"; }
-std::string  ratio_string<std::nano>::symbol() { return "n"; }
+std::string ratio_string<std::pico>::symbol() { return "p"; }
+std::string ratio_string<std::nano>::symbol() { return "n"; }
 std::string ratio_string<std::micro>::symbol() { return "u"; }
 std::string ratio_string<std::milli>::symbol() { return "m"; }
 
-
 } // end namespace Catch
 
 #if defined(__clang__)
diff --git a/include/internal/catch_tostring.h b/include/internal/catch_tostring.h
index 1e644a9..13a43b0 100644
--- a/include/internal/catch_tostring.h
+++ b/include/internal/catch_tostring.h
@@ -13,8 +13,13 @@
 #include <cstddef>
 #include <type_traits>
 #include <string>
+#include "catch_compiler_capabilities.h"
 #include "catch_stream.h"
 
+#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
+#include <string_view>
+#endif
+
 #ifdef __OBJC__
 #include "catch_objc_arc.hpp"
 #endif
@@ -24,15 +29,7 @@
 #pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless
 #endif
 
-
-// We need a dummy global operator<< so we can bring it into Catch namespace later
-struct Catch_global_namespace_dummy {};
-std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy);
-
 namespace Catch {
-    // Bring in operator<< from global namespace into Catch namespace
-    using ::operator<<;
-
     namespace Detail {
 
         extern const std::string unprintableString;
@@ -61,14 +58,38 @@
         std::string convertUnknownEnumToString( E e );
 
         template<typename T>
-        typename std::enable_if<!std::is_enum<T>::value, std::string>::type convertUnstreamable( T const& ) {
+        typename std::enable_if<
+            !std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value,
+        std::string>::type convertUnstreamable( T const& ) {
             return Detail::unprintableString;
         }
         template<typename T>
-        typename std::enable_if<std::is_enum<T>::value, std::string>::type convertUnstreamable( T const& value ) {
+        typename std::enable_if<
+            !std::is_enum<T>::value && std::is_base_of<std::exception, T>::value,
+         std::string>::type convertUnstreamable(T const& ex) {
+            return ex.what();
+        }
+
+
+        template<typename T>
+        typename std::enable_if<
+            std::is_enum<T>::value
+        , std::string>::type convertUnstreamable( T const& value ) {
             return convertUnknownEnumToString( value );
         }
 
+#if defined(_MANAGED)
+        //! Convert a CLR string to a utf8 std::string
+        template<typename T>
+        std::string clrReferenceToString( T^ ref ) {
+            if (ref == nullptr)
+                return std::string("null");
+            auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());
+            cli::pin_ptr<System::Byte> p = &bytes[0];
+            return std::string(reinterpret_cast<char const *>(p), bytes->Length);
+        }
+#endif
+
     } // namespace Detail
 
 
@@ -80,7 +101,9 @@
         typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
             convert(const Fake& value) {
                 ReusableStringStream rss;
-                rss << value;
+                // NB: call using the function-like syntax to avoid ambiguity with
+                // user-defined templated operator<< under clang.
+                rss.operator<<(value);
                 return rss.str();
         }
 
@@ -88,7 +111,11 @@
         static
         typename std::enable_if<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
             convert( const Fake& value ) {
-                return Detail::convertUnstreamable( value );
+#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
+            return Detail::convertUnstreamable(value);
+#else
+            return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);
+#endif
         }
     };
 
@@ -106,6 +133,13 @@
             return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<E>::type>(e));
         }
 
+#if defined(_MANAGED)
+        template <typename T>
+        std::string stringify( T^ e ) {
+            return ::Catch::StringMaker<T^>::convert(e);
+        }
+#endif
+
     } // namespace Detail
 
     // Some predefined specializations
@@ -114,10 +148,13 @@
     struct StringMaker<std::string> {
         static std::string convert(const std::string& str);
     };
+
+#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
     template<>
-    struct StringMaker<std::wstring> {
-        static std::string convert(const std::wstring& wstr);
+    struct StringMaker<std::string_view> {
+        static std::string convert(std::string_view str);
     };
+#endif
 
     template<>
     struct StringMaker<char const *> {
@@ -127,6 +164,20 @@
     struct StringMaker<char *> {
         static std::string convert(char * str);
     };
+
+#ifdef CATCH_CONFIG_WCHAR
+    template<>
+    struct StringMaker<std::wstring> {
+        static std::string convert(const std::wstring& wstr);
+    };
+
+# ifdef CATCH_CONFIG_CPP17_STRING_VIEW
+    template<>
+    struct StringMaker<std::wstring_view> {
+        static std::string convert(std::wstring_view str);
+    };
+# endif
+
     template<>
     struct StringMaker<wchar_t const *> {
         static std::string convert(wchar_t const * str);
@@ -135,23 +186,26 @@
     struct StringMaker<wchar_t *> {
         static std::string convert(wchar_t * str);
     };
+#endif
 
+    // TBD: Should we use `strnlen` to ensure that we don't go out of the buffer,
+    //      while keeping string semantics?
     template<int SZ>
     struct StringMaker<char[SZ]> {
-        static std::string convert(const char* str) {
+        static std::string convert(char const* str) {
             return ::Catch::Detail::stringify(std::string{ str });
         }
     };
     template<int SZ>
     struct StringMaker<signed char[SZ]> {
-        static std::string convert(const char* str) {
-            return ::Catch::Detail::stringify(std::string{ str });
+        static std::string convert(signed char const* str) {
+            return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) });
         }
     };
     template<int SZ>
     struct StringMaker<unsigned char[SZ]> {
-        static std::string convert(const char* str) {
-            return ::Catch::Detail::stringify(std::string{ str });
+        static std::string convert(unsigned char const* str) {
+            return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) });
         }
     };
 
@@ -235,6 +289,15 @@
         }
     };
 
+#if defined(_MANAGED)
+    template <typename T>
+    struct StringMaker<T^> {
+        static std::string convert( T^ ref ) {
+            return ::Catch::Detail::clrReferenceToString(ref);
+        }
+    };
+#endif
+
     namespace Detail {
         template<typename InputIterator>
         std::string rangeToString(InputIterator first, InputIterator last) {
@@ -283,7 +346,9 @@
 #if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)
 #  define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
 #  define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
+#  define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
 #  define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
+#  define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
 #endif
 
 // Separate std::pair specialization
@@ -305,6 +370,24 @@
 }
 #endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
 
+#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL)
+#include <optional>
+namespace Catch {
+    template<typename T>
+    struct StringMaker<std::optional<T> > {
+        static std::string convert(const std::optional<T>& optional) {
+            ReusableStringStream rss;
+            if (optional.has_value()) {
+                rss << ::Catch::Detail::stringify(*optional);
+            } else {
+                rss << "{ }";
+            }
+            return rss.str();
+        }
+    };
+}
+#endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
+
 // Separate std::tuple specialization
 #if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
 #include <tuple>
@@ -347,6 +430,34 @@
 }
 #endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
 
+#if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT)
+#include <variant>
+namespace Catch {
+    template<>
+    struct StringMaker<std::monostate> {
+        static std::string convert(const std::monostate&) {
+            return "{ }";
+        }
+    };
+
+    template<typename... Elements>
+    struct StringMaker<std::variant<Elements...>> {
+        static std::string convert(const std::variant<Elements...>& variant) {
+            if (variant.valueless_by_exception()) {
+                return "{valueless variant}";
+            } else {
+                return std::visit(
+                    [](const auto& value) {
+                        return ::Catch::Detail::stringify(value);
+                    },
+                    variant
+                );
+            }
+        }
+    };
+}
+#endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
+
 namespace Catch {
     struct not_this_one {}; // Tag type for detecting which begin/ end are being selected
 
@@ -364,6 +475,13 @@
             !std::is_same<decltype(end(std::declval<T>())), not_this_one>::value;
     };
 
+#if defined(_MANAGED) // Managed types are never ranges
+    template <typename T>
+    struct is_range<T^> {
+        static const bool value = false;
+    };
+#endif
+
     template<typename Range>
     std::string rangeToString( Range const& range ) {
         return ::Catch::Detail::rangeToString( begin( range ), end( range ) );
diff --git a/include/internal/catch_totals.h b/include/internal/catch_totals.h
index 9507582..5692728 100644
--- a/include/internal/catch_totals.h
+++ b/include/internal/catch_totals.h
@@ -32,7 +32,7 @@
 
         Totals delta( Totals const& prevTotals ) const;
 
-
+        int error = 0;
         Counts assertions;
         Counts testCases;
     };
diff --git a/include/internal/catch_type_traits.hpp b/include/internal/catch_type_traits.hpp
new file mode 100644
index 0000000..8edb1ec
--- /dev/null
+++ b/include/internal/catch_type_traits.hpp
@@ -0,0 +1,40 @@
+/*
+ *  Created by Jozef on 12/11/2018.
+ *  Copyright 2017 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_TYPE_TRAITS_HPP_INCLUDED
+#define TWOBLUECUBES_CATCH_TYPE_TRAITS_HPP_INCLUDED
+
+#include <type_traits>
+
+namespace Catch{
+
+#ifdef CATCH_CPP17_OR_GREATER
+	template <typename...>
+	inline constexpr auto is_unique = std::true_type{};
+
+	template <typename T, typename... Rest>
+	inline constexpr auto is_unique<T, Rest...> = std::bool_constant<
+		(!std::is_same_v<T, Rest> && ...) && is_unique<Rest...>
+	>{};
+#else
+
+template <typename...>
+struct is_unique : std::true_type{};
+
+template <typename T0, typename T1, typename... Rest>
+struct is_unique<T0, T1, Rest...> : std::integral_constant
+<bool,
+     !std::is_same<T0, T1>::value 
+     && is_unique<T0, Rest...>::value 
+     && is_unique<T1, Rest...>::value
+>{};
+
+#endif
+}
+
+#endif // TWOBLUECUBES_CATCH_TYPE_TRAITS_HPP_INCLUDED
diff --git a/include/internal/catch_uncaught_exceptions.cpp b/include/internal/catch_uncaught_exceptions.cpp
index 0e47a04..b990ccd 100644
--- a/include/internal/catch_uncaught_exceptions.cpp
+++ b/include/internal/catch_uncaught_exceptions.cpp
@@ -12,7 +12,6 @@
 
 namespace Catch {
     bool uncaught_exceptions() {
-// https://github.com/catchorg/Catch2/issues/1162
 #if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
         return std::uncaught_exceptions() > 0;
 #else
diff --git a/include/internal/catch_version.cpp b/include/internal/catch_version.cpp
index fc196d9..a1d08b2 100644
--- a/include/internal/catch_version.cpp
+++ b/include/internal/catch_version.cpp
@@ -37,7 +37,7 @@
     }
 
     Version const& libraryVersion() {
-        static Version version( 2, 1, 1, "", 0 );
+        static Version version( 2, 7, 0, "", 0 );
         return version;
     }
 
diff --git a/include/internal/catch_xmlwriter.cpp b/include/internal/catch_xmlwriter.cpp
index a3316f4..5354efa 100644
--- a/include/internal/catch_xmlwriter.cpp
+++ b/include/internal/catch_xmlwriter.cpp
@@ -7,51 +7,147 @@
 
 #include "catch_xmlwriter.h"
 
+#include "catch_enforce.h"
+
 #include <iomanip>
 
+using uchar = unsigned char;
+
 namespace Catch {
 
+namespace {
+
+    size_t trailingBytes(unsigned char c) {
+        if ((c & 0xE0) == 0xC0) {
+            return 2;
+        }
+        if ((c & 0xF0) == 0xE0) {
+            return 3;
+        }
+        if ((c & 0xF8) == 0xF0) {
+            return 4;
+        }
+        CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
+    }
+
+    uint32_t headerValue(unsigned char c) {
+        if ((c & 0xE0) == 0xC0) {
+            return c & 0x1F;
+        }
+        if ((c & 0xF0) == 0xE0) {
+            return c & 0x0F;
+        }
+        if ((c & 0xF8) == 0xF0) {
+            return c & 0x07;
+        }
+        CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
+    }
+
+    void hexEscapeChar(std::ostream& os, unsigned char c) {
+        std::ios_base::fmtflags f(os.flags());
+        os << "\\x"
+            << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
+            << static_cast<int>(c);
+        os.flags(f);
+    }
+
+} // anonymous namespace
+
     XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat )
     :   m_str( str ),
         m_forWhat( forWhat )
     {}
 
     void XmlEncode::encodeTo( std::ostream& os ) const {
-
         // Apostrophe escaping not necessary if we always use " to write attributes
         // (see: http://www.w3.org/TR/xml/#syntax)
 
-        for( std::size_t i = 0; i < m_str.size(); ++ i ) {
-            char c = m_str[i];
-            switch( c ) {
-                case '<':   os << "&lt;"; break;
-                case '&':   os << "&amp;"; break;
+        for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
+            uchar c = m_str[idx];
+            switch (c) {
+            case '<':   os << "&lt;"; break;
+            case '&':   os << "&amp;"; break;
 
-                case '>':
-                    // See: http://www.w3.org/TR/xml/#syntax
-                    if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' )
-                        os << "&gt;";
-                    else
-                        os << c;
+            case '>':
+                // See: http://www.w3.org/TR/xml/#syntax
+                if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']')
+                    os << "&gt;";
+                else
+                    os << c;
+                break;
+
+            case '\"':
+                if (m_forWhat == ForAttributes)
+                    os << "&quot;";
+                else
+                    os << c;
+                break;
+
+            default:
+                // Check for control characters and invalid utf-8
+
+                // Escape control characters in standard ascii
+                // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
+                if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
+                    hexEscapeChar(os, c);
                     break;
+                }
 
-                case '\"':
-                    if( m_forWhat == ForAttributes )
-                        os << "&quot;";
-                    else
-                        os << c;
+                // Plain ASCII: Write it to stream
+                if (c < 0x7F) {
+                    os << c;
                     break;
+                }
 
-                default:
-                    // Escape control chars - based on contribution by @espenalb in PR #465 and
-                    // by @mrpi PR #588
-                    if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) {
-                        // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
-                        os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
-                           << static_cast<int>( c );
-                    }
-                    else
-                        os << c;
+                // UTF-8 territory
+                // Check if the encoding is valid and if it is not, hex escape bytes.
+                // Important: We do not check the exact decoded values for validity, only the encoding format
+                // First check that this bytes is a valid lead byte:
+                // This means that it is not encoded as 1111 1XXX
+                // Or as 10XX XXXX
+                if (c <  0xC0 ||
+                    c >= 0xF8) {
+                    hexEscapeChar(os, c);
+                    break;
+                }
+
+                auto encBytes = trailingBytes(c);
+                // Are there enough bytes left to avoid accessing out-of-bounds memory?
+                if (idx + encBytes - 1 >= m_str.size()) {
+                    hexEscapeChar(os, c);
+                    break;
+                }
+                // The header is valid, check data
+                // The next encBytes bytes must together be a valid utf-8
+                // This means: bitpattern 10XX XXXX and the extracted value is sane (ish)
+                bool valid = true;
+                uint32_t value = headerValue(c);
+                for (std::size_t n = 1; n < encBytes; ++n) {
+                    uchar nc = m_str[idx + n];
+                    valid &= ((nc & 0xC0) == 0x80);
+                    value = (value << 6) | (nc & 0x3F);
+                }
+
+                if (
+                    // Wrong bit pattern of following bytes
+                    (!valid) ||
+                    // Overlong encodings
+                    (value < 0x80) ||
+                    (0x80 <= value && value < 0x800   && encBytes > 2) ||
+                    (0x800 < value && value < 0x10000 && encBytes > 3) ||
+                    // Encoded value out of range
+                    (value >= 0x110000)
+                    ) {
+                    hexEscapeChar(os, c);
+                    break;
+                }
+
+                // If we got here, this is in fact a valid(ish) utf-8 sequence
+                for (std::size_t n = 0; n < encBytes; ++n) {
+                    os << m_str[idx + n];
+                }
+                idx += encBytes - 1;
+                break;
             }
         }
     }
diff --git a/include/internal/catch_xmlwriter.h b/include/internal/catch_xmlwriter.h
index 76456f9..c4b1c03 100644
--- a/include/internal/catch_xmlwriter.h
+++ b/include/internal/catch_xmlwriter.h
@@ -56,7 +56,7 @@
 
         XmlWriter( std::ostream& os = Catch::cout() );
         ~XmlWriter();
-        
+
         XmlWriter( XmlWriter const& ) = delete;
         XmlWriter& operator=( XmlWriter const& ) = delete;
 
diff --git a/include/reporters/catch_reporter_bases.cpp b/include/reporters/catch_reporter_bases.cpp
index c2059b5..ce3553e 100644
--- a/include/reporters/catch_reporter_bases.cpp
+++ b/include/reporters/catch_reporter_bases.cpp
@@ -13,7 +13,7 @@
 #include <cstring>
 #include <cfloat>
 #include <cstdio>
-#include <assert.h>
+#include <cassert>
 #include <memory>
 
 namespace Catch {
@@ -30,13 +30,13 @@
         // + 1 for null terminator
         const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
         char buffer[maxDoubleSize];
- 
+
         // Save previous errno, to prevent sprintf from overwriting it
         ErrnoGuard guard;
 #ifdef _MSC_VER
         sprintf_s(buffer, "%.3f", duration);
 #else
-        sprintf(buffer, "%.3f", duration);
+        std::sprintf(buffer, "%.3f", duration);
 #endif
         return std::string(buffer);
     }
@@ -45,6 +45,10 @@
     TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config)
         :StreamingReporterBase(_config) {}
 
+    std::set<Verbosity> TestEventListenerBase::getSupportedVerbosities() {
+        return { Verbosity::Quiet, Verbosity::Normal, Verbosity::High };
+    }
+
     void TestEventListenerBase::assertionStarting(AssertionInfo const &) {}
 
     bool TestEventListenerBase::assertionEnded(AssertionStats const &) {
diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp
index 4c03d0e..4a27db6 100644
--- a/include/reporters/catch_reporter_bases.hpp
+++ b/include/reporters/catch_reporter_bases.hpp
@@ -8,13 +8,14 @@
 #ifndef TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
 #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
 
+#include "../internal/catch_enforce.h"
 #include "../internal/catch_interfaces_reporter.h"
 
 #include <algorithm>
 #include <cstring>
 #include <cfloat>
 #include <cstdio>
-#include <assert.h>
+#include <cassert>
 #include <memory>
 #include <ostream>
 
@@ -33,7 +34,7 @@
         {
             m_reporterPrefs.shouldRedirectStdOut = false;
             if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
-                Exception::doThrow( std::domain_error( "Verbosity level not supported by this reporter" ) );
+                CATCH_ERROR( "Verbosity level not supported by this reporter" );
         }
 
         ReporterPreferences getPreferences() const override {
@@ -148,7 +149,7 @@
         {
             m_reporterPrefs.shouldRedirectStdOut = false;
             if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
-                Exception::doThrow( std::domain_error( "Verbosity level not supported by this reporter" ) );
+                CATCH_ERROR( "Verbosity level not supported by this reporter" );
         }
         ~CumulativeReporterBase() override = default;
 
@@ -216,7 +217,7 @@
             node->children.push_back(m_rootSection);
             m_testCases.push_back(node);
             m_rootSection.reset();
-        
+
             assert(m_deepestSection);
             m_deepestSection->stdOut = testCaseStats.stdOut;
             m_deepestSection->stdErr = testCaseStats.stdErr;
@@ -265,6 +266,8 @@
     struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> {
         TestEventListenerBase( ReporterConfig const& _config );
 
+        static std::set<Verbosity> getSupportedVerbosities();
+
         void assertionStarting(AssertionInfo const&) override;
         bool assertionEnded(AssertionStats const&) override;
     };
diff --git a/include/reporters/catch_reporter_compact.cpp b/include/reporters/catch_reporter_compact.cpp
index caf4d3f..65f7026 100644
--- a/include/reporters/catch_reporter_compact.cpp
+++ b/include/reporters/catch_reporter_compact.cpp
@@ -245,9 +245,7 @@
         }
 
         ReporterPreferences CompactReporter::getPreferences() const {
-            ReporterPreferences prefs;
-            prefs.shouldRedirectStdOut = false;
-            return prefs;
+            return m_reporterPrefs;
         }
 
         void CompactReporter::noMatchingTestCases( std::string const& spec ) {
diff --git a/include/reporters/catch_reporter_console.cpp b/include/reporters/catch_reporter_console.cpp
index 54b62cd..76dc9ec 100644
--- a/include/reporters/catch_reporter_console.cpp
+++ b/include/reporters/catch_reporter_console.cpp
@@ -111,8 +111,6 @@
     void print() const {
         printSourceInfo();
         if (stats.totals.assertions.total() > 0) {
-            if (result.isOk())
-                stream << '\n';
             printResultType();
             printOriginalExpression();
             printReconstructedExpression();
@@ -247,7 +245,7 @@
         case Unit::Nanoseconds:
             return "ns";
         case Unit::Microseconds:
-            return "µs";
+            return "us";
         case Unit::Milliseconds:
             return "ms";
         case Unit::Seconds:
diff --git a/include/reporters/catch_reporter_junit.cpp b/include/reporters/catch_reporter_junit.cpp
index d133b70..7e97ee3 100644
--- a/include/reporters/catch_reporter_junit.cpp
+++ b/include/reporters/catch_reporter_junit.cpp
@@ -13,7 +13,7 @@
 #include "../internal/catch_tostring.h"
 #include "../internal/catch_reporter_registrars.hpp"
 
-#include <assert.h>
+#include <cassert>
 #include <sstream>
 #include <ctime>
 #include <algorithm>
@@ -62,6 +62,7 @@
             xml( _config.stream() )
         {
             m_reporterPrefs.shouldRedirectStdOut = true;
+            m_reporterPrefs.shouldReportAllAssertions = true;
         }
 
     JunitReporter::~JunitReporter() {}
@@ -75,6 +76,13 @@
     void JunitReporter::testRunStarting( TestRunInfo const& runInfo )  {
         CumulativeReporterBase::testRunStarting( runInfo );
         xml.startElement( "testsuites" );
+        if( m_config->rngSeed() != 0 ) {
+            xml.startElement( "properties" );
+            xml.scopedElement( "property" )
+                .writeAttribute( "name", "random-seed" )
+                .writeAttribute( "value", m_config->rngSeed() );
+            xml.endElement();
+        }
     }
 
     void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) {
diff --git a/include/reporters/catch_reporter_listening.cpp b/include/reporters/catch_reporter_listening.cpp
new file mode 100644
index 0000000..9ddae2f
--- /dev/null
+++ b/include/reporters/catch_reporter_listening.cpp
@@ -0,0 +1,142 @@
+/*
+ *  Created by Phil on 5/08/2015.
+ *  Copyright 2015 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_reporter_listening.h"
+#include <cassert>
+
+namespace Catch {
+
+    ListeningReporter::ListeningReporter() {
+        // We will assume that listeners will always want all assertions
+        m_preferences.shouldReportAllAssertions = true;
+    }
+
+    void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) {
+        m_listeners.push_back( std::move( listener ) );
+    }
+
+    void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) {
+        assert(!m_reporter && "Listening reporter can wrap only 1 real reporter");
+        m_reporter = std::move( reporter );
+        m_preferences.shouldRedirectStdOut = m_reporter->getPreferences().shouldRedirectStdOut;
+    }
+
+    ReporterPreferences ListeningReporter::getPreferences() const {
+        return m_preferences;
+    }
+
+    std::set<Verbosity> ListeningReporter::getSupportedVerbosities() {
+        return std::set<Verbosity>{ };
+    }
+
+
+    void ListeningReporter::noMatchingTestCases( std::string const& spec ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->noMatchingTestCases( spec );
+        }
+        m_reporter->noMatchingTestCases( spec );
+    }
+
+    void ListeningReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->benchmarkStarting( benchmarkInfo );
+        }
+        m_reporter->benchmarkStarting( benchmarkInfo );
+    }
+    void ListeningReporter::benchmarkEnded( BenchmarkStats const& benchmarkStats ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->benchmarkEnded( benchmarkStats );
+        }
+        m_reporter->benchmarkEnded( benchmarkStats );
+    }
+
+    void ListeningReporter::testRunStarting( TestRunInfo const& testRunInfo ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->testRunStarting( testRunInfo );
+        }
+        m_reporter->testRunStarting( testRunInfo );
+    }
+
+    void ListeningReporter::testGroupStarting( GroupInfo const& groupInfo ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->testGroupStarting( groupInfo );
+        }
+        m_reporter->testGroupStarting( groupInfo );
+    }
+
+
+    void ListeningReporter::testCaseStarting( TestCaseInfo const& testInfo ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->testCaseStarting( testInfo );
+        }
+        m_reporter->testCaseStarting( testInfo );
+    }
+
+    void ListeningReporter::sectionStarting( SectionInfo const& sectionInfo ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->sectionStarting( sectionInfo );
+        }
+        m_reporter->sectionStarting( sectionInfo );
+    }
+
+    void ListeningReporter::assertionStarting( AssertionInfo const& assertionInfo ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->assertionStarting( assertionInfo );
+        }
+        m_reporter->assertionStarting( assertionInfo );
+    }
+
+    // The return value indicates if the messages buffer should be cleared:
+    bool ListeningReporter::assertionEnded( AssertionStats const& assertionStats ) {
+        for( auto const& listener : m_listeners ) {
+            static_cast<void>( listener->assertionEnded( assertionStats ) );
+        }
+        return m_reporter->assertionEnded( assertionStats );
+    }
+
+    void ListeningReporter::sectionEnded( SectionStats const& sectionStats ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->sectionEnded( sectionStats );
+        }
+        m_reporter->sectionEnded( sectionStats );
+    }
+
+    void ListeningReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->testCaseEnded( testCaseStats );
+        }
+        m_reporter->testCaseEnded( testCaseStats );
+    }
+
+    void ListeningReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->testGroupEnded( testGroupStats );
+        }
+        m_reporter->testGroupEnded( testGroupStats );
+    }
+
+    void ListeningReporter::testRunEnded( TestRunStats const& testRunStats ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->testRunEnded( testRunStats );
+        }
+        m_reporter->testRunEnded( testRunStats );
+    }
+
+
+    void ListeningReporter::skipTest( TestCaseInfo const& testInfo ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->skipTest( testInfo );
+        }
+        m_reporter->skipTest( testInfo );
+    }
+
+    bool ListeningReporter::isMulti() const {
+        return true;
+    }
+
+} // end namespace Catch
diff --git a/include/reporters/catch_reporter_multi.h b/include/reporters/catch_reporter_listening.h
similarity index 84%
rename from include/reporters/catch_reporter_multi.h
rename to include/reporters/catch_reporter_listening.h
index 985d442..dddd7a5 100644
--- a/include/reporters/catch_reporter_multi.h
+++ b/include/reporters/catch_reporter_listening.h
@@ -11,12 +11,17 @@
 
 namespace Catch {
 
-    class MultipleReporters : public IStreamingReporter {
+    class ListeningReporter : public IStreamingReporter {
         using Reporters = std::vector<IStreamingReporterPtr>;
-        Reporters m_reporters;
+        Reporters m_listeners;
+        IStreamingReporterPtr m_reporter = nullptr;
+        ReporterPreferences m_preferences;
 
     public:
-        void add( IStreamingReporterPtr&& reporter );
+        ListeningReporter();
+
+        void addListener( IStreamingReporterPtr&& listener );
+        void addReporter( IStreamingReporterPtr&& reporter );
 
     public: // IStreamingReporter
 
diff --git a/include/reporters/catch_reporter_multi.cpp b/include/reporters/catch_reporter_multi.cpp
deleted file mode 100644
index 23bb160..0000000
--- a/include/reporters/catch_reporter_multi.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- *  Created by Phil on 5/08/2015.
- *  Copyright 2015 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_reporter_multi.h"
-
-namespace Catch {
-
-    void MultipleReporters::add( IStreamingReporterPtr&& reporter ) {
-        m_reporters.push_back( std::move( reporter ) );
-    }
-
-    ReporterPreferences MultipleReporters::getPreferences() const {
-        return m_reporters[0]->getPreferences();
-    }
-
-    std::set<Verbosity> MultipleReporters::getSupportedVerbosities() {
-        return std::set<Verbosity>{ };
-    }
-
-
-    void MultipleReporters::noMatchingTestCases( std::string const& spec ) {
-        for( auto const& reporter : m_reporters )
-            reporter->noMatchingTestCases( spec );
-    }
-
-    void MultipleReporters::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) {
-        for( auto const& reporter : m_reporters )
-            reporter->benchmarkStarting( benchmarkInfo );
-    }
-    void MultipleReporters::benchmarkEnded( BenchmarkStats const& benchmarkStats ) {
-        for( auto const& reporter : m_reporters )
-            reporter->benchmarkEnded( benchmarkStats );
-    }
-
-    void MultipleReporters::testRunStarting( TestRunInfo const& testRunInfo ) {
-        for( auto const& reporter : m_reporters )
-            reporter->testRunStarting( testRunInfo );
-    }
-
-    void MultipleReporters::testGroupStarting( GroupInfo const& groupInfo ) {
-        for( auto const& reporter : m_reporters )
-            reporter->testGroupStarting( groupInfo );
-    }
-
-
-    void MultipleReporters::testCaseStarting( TestCaseInfo const& testInfo ) {
-        for( auto const& reporter : m_reporters )
-            reporter->testCaseStarting( testInfo );
-    }
-
-    void MultipleReporters::sectionStarting( SectionInfo const& sectionInfo ) {
-        for( auto const& reporter : m_reporters )
-            reporter->sectionStarting( sectionInfo );
-    }
-
-    void MultipleReporters::assertionStarting( AssertionInfo const& assertionInfo ) {
-        for( auto const& reporter : m_reporters )
-            reporter->assertionStarting( assertionInfo );
-    }
-
-    // The return value indicates if the messages buffer should be cleared:
-    bool MultipleReporters::assertionEnded( AssertionStats const& assertionStats ) {
-        bool clearBuffer = false;
-        for( auto const& reporter : m_reporters )
-            clearBuffer |= reporter->assertionEnded( assertionStats );
-        return clearBuffer;
-    }
-
-    void MultipleReporters::sectionEnded( SectionStats const& sectionStats ) {
-        for( auto const& reporter : m_reporters )
-            reporter->sectionEnded( sectionStats );
-    }
-
-    void MultipleReporters::testCaseEnded( TestCaseStats const& testCaseStats ) {
-        for( auto const& reporter : m_reporters )
-            reporter->testCaseEnded( testCaseStats );
-    }
-
-    void MultipleReporters::testGroupEnded( TestGroupStats const& testGroupStats ) {
-        for( auto const& reporter : m_reporters )
-            reporter->testGroupEnded( testGroupStats );
-    }
-
-    void MultipleReporters::testRunEnded( TestRunStats const& testRunStats ) {
-        for( auto const& reporter : m_reporters )
-            reporter->testRunEnded( testRunStats );
-    }
-
-
-    void MultipleReporters::skipTest( TestCaseInfo const& testInfo ) {
-        for( auto const& reporter : m_reporters )
-            reporter->skipTest( testInfo );
-    }
-
-    bool MultipleReporters::isMulti() const {
-        return true;
-    }
-
-} // end namespace Catch
diff --git a/include/reporters/catch_reporter_tap.hpp b/include/reporters/catch_reporter_tap.hpp
index edb75b5..1bfe4f5 100644
--- a/include/reporters/catch_reporter_tap.hpp
+++ b/include/reporters/catch_reporter_tap.hpp
@@ -26,13 +26,11 @@
         ~TAPReporter() override;
 
         static std::string getDescription() {
-            return "Reports test results in TAP format, suitable for test harneses";
+            return "Reports test results in TAP format, suitable for test harnesses";
         }
 
         ReporterPreferences getPreferences() const override {
-            ReporterPreferences prefs;
-            prefs.shouldRedirectStdOut = false;
-            return prefs;
+            return m_reporterPrefs;
         }
 
         void noMatchingTestCases( std::string const& spec ) override {
@@ -44,9 +42,9 @@
         bool assertionEnded( AssertionStats const& _assertionStats ) override {
             ++counter;
 
+            stream << "# " << currentTestCaseInfo->name << std::endl;
             AssertionPrinter printer( stream, _assertionStats, counter );
             printer.print();
-            stream << " # " << currentTestCaseInfo->name ;
 
             stream << std::endl;
             return true;
diff --git a/include/reporters/catch_reporter_teamcity.hpp b/include/reporters/catch_reporter_teamcity.hpp
index ddd0d92..eca2885 100644
--- a/include/reporters/catch_reporter_teamcity.hpp
+++ b/include/reporters/catch_reporter_teamcity.hpp
@@ -97,12 +97,12 @@
                     case ResultWas::Ok:
                     case ResultWas::Info:
                     case ResultWas::Warning:
-                        Exception::doThrow( std::domain_error( "Internal error in TeamCity reporter" ) );
+                        CATCH_ERROR( "Internal error in TeamCity reporter" );
                     // These cases are here to prevent compiler warnings
                     case ResultWas::Unknown:
                     case ResultWas::FailureBit:
                     case ResultWas::Exception:
-                        Exception::doThrow( std::domain_error( "Not implemented" ) );
+                        CATCH_ERROR( "Not implemented" );
                 }
                 if( assertionStats.infoMessages.size() == 1 )
                     msg << " with message:";
diff --git a/include/reporters/catch_reporter_xml.cpp b/include/reporters/catch_reporter_xml.cpp
index b721d44..902014c 100644
--- a/include/reporters/catch_reporter_xml.cpp
+++ b/include/reporters/catch_reporter_xml.cpp
@@ -24,6 +24,7 @@
         m_xml(_config.stream())
     {
         m_reporterPrefs.shouldRedirectStdOut = true;
+        m_reporterPrefs.shouldReportAllAssertions = true;
     }
 
     XmlReporter::~XmlReporter() = default;
@@ -54,6 +55,9 @@
         m_xml.startElement( "Catch" );
         if( !m_config->name().empty() )
             m_xml.writeAttribute( "name", m_config->name() );
+        if( m_config->rngSeed() != 0 )
+            m_xml.scopedElement( "Randomness" )
+                .writeAttribute( "seed", m_config->rngSeed() );
     }
 
     void XmlReporter::testGroupStarting( GroupInfo const& groupInfo ) {
@@ -80,8 +84,7 @@
         StreamingReporterBase::sectionStarting( sectionInfo );
         if( m_sectionDepth++ > 0 ) {
             m_xml.startElement( "Section" )
-                .writeAttribute( "name", trim( sectionInfo.name ) )
-                .writeAttribute( "description", sectionInfo.description );
+                .writeAttribute( "name", trim( sectionInfo.name ) );
             writeSourceInfo( sectionInfo.lineInfo );
             m_xml.ensureTagClosed();
         }
diff --git a/misc/SelfTest.vcxproj.user b/misc/SelfTest.vcxproj.user
new file mode 100644
index 0000000..ffffc57
--- /dev/null
+++ b/misc/SelfTest.vcxproj.user
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <UseFullPaths>false</UseFullPaths>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <UseFullPaths>false</UseFullPaths>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <UseFullPaths>false</UseFullPaths>
+    </ClCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <UseFullPaths>false</UseFullPaths>
+    </ClCompile>
+  </ItemDefinitionGroup>
+</Project>
diff --git a/misc/appveyorBuildConfigurationScript.bat b/misc/appveyorBuildConfigurationScript.bat
index 27efcd1..f07bb70 100644
--- a/misc/appveyorBuildConfigurationScript.bat
+++ b/misc/appveyorBuildConfigurationScript.bat
@@ -1,13 +1,22 @@
-@REM  # In debug build, we want to
-@REM  # 1) Prebuild memcheck redirecter
-@REM  # 2) Regenerate single header include for examples
-@REM  # 3) Enable building examples
+SETLOCAL EnableDelayedExpansion
+
+@REM  # Possibilities:
+@REM  # Debug build + coverage
+@REM  # Debug build + examples
+@REM  # Debug build +   ---
+@REM  # Release build
 if "%CONFIGURATION%"=="Debug" (
-  python scripts\generateSingleHeader.py
-  cmake -Hmisc -Bbuild-misc -A%PLATFORM%
-  cmake --build build-misc
-  cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain% -DCATCH_BUILD_EXAMPLES=ON -DMEMORYCHECK_COMMAND=build-misc\Debug\CoverageHelper.exe -DMEMORYCHECK_COMMAND_OPTIONS=--sep-- -DMEMORYCHECK_TYPE=Valgrind
+  if "%coverage%"=="1" (
+    @REM # coverage needs to build the special helper as well as the main
+    cmake -Hmisc -Bbuild-misc -A%PLATFORM% || exit /b !ERRORLEVEL!
+    cmake --build build-misc || exit /b !ERRORLEVEL!
+    cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain% -DMEMORYCHECK_COMMAND=build-misc\Debug\CoverageHelper.exe -DMEMORYCHECK_COMMAND_OPTIONS=--sep-- -DMEMORYCHECK_TYPE=Valgrind || exit /b !ERRORLEVEL! || exit /b !ERRORLEVEL!
+  ) else (
+    @REM # We know that coverage is 0
+    python scripts\generateSingleHeader.py || exit /b !ERRORLEVEL!
+    cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain% -DCATCH_BUILD_EXAMPLES=%examples% -DCATCH_BUILD_EXTRA_TESTS=%examples% || exit /b !ERRORLEVEL!
+  )
 )
 if "%CONFIGURATION%"=="Release" (
-  cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain%
+  cmake -H. -BBuild -A%PLATFORM% -DUSE_WMAIN=%wmain% || exit /b !ERRORLEVEL!
 )
diff --git a/misc/appveyorTestRunScript.bat b/misc/appveyorTestRunScript.bat
index fdcc2ce..c129d99 100644
--- a/misc/appveyorTestRunScript.bat
+++ b/misc/appveyorTestRunScript.bat
@@ -1,9 +1,15 @@
+SETLOCAL EnableDelayedExpansion
+
 cd Build
 if "%CONFIGURATION%"=="Debug" (
-  ctest -j 2 -C %CONFIGURATION% -D ExperimentalMemCheck
-  python ..\misc\appveyorMergeCoverageScript.py
-  codecov --root .. --no-color --disable gcov -f cobertura.xml -t %CODECOV_TOKEN%
+  if "%coverage%"=="1" (
+    ctest -j 2 -C %CONFIGURATION% -D ExperimentalMemCheck || exit /b !ERRORLEVEL!
+    python ..\misc\appveyorMergeCoverageScript.py || exit /b !ERRORLEVEL!
+    codecov --root .. --no-color --disable gcov -f cobertura.xml -t %CODECOV_TOKEN% || exit /b !ERRORLEVEL!
+  ) else (
+    ctest -j 2 -C %CONFIGURATION% || exit /b !ERRORLEVEL!
+  )
 )
 if "%CONFIGURATION%"=="Release" (
-  ctest -j 2 -C %CONFIGURATION%
+  ctest -j 2 -C %CONFIGURATION% || exit /b !ERRORLEVEL!
 )
diff --git a/misc/coverage-helper.cpp b/misc/coverage-helper.cpp
index 9783d69..a664383 100644
--- a/misc/coverage-helper.cpp
+++ b/misc/coverage-helper.cpp
@@ -9,6 +9,38 @@
 #include <string>
 #include <vector>
 
+std::string escape_arg(const std::string& arg) {
+    if (arg.empty() == false &&
+        arg.find_first_of(" \t\n\v\"") == arg.npos) {
+        return arg;
+    }
+
+    std::string escaped;
+    escaped.push_back('"');
+    for (auto it = arg.begin(); ; ++it) {
+        int num_backslashes = 0;
+
+        while (it != arg.end() && *it == '\\') {
+            ++it;
+            ++num_backslashes;
+        }
+
+        if (it == arg.end()) {
+            escaped.append(num_backslashes * 2, '\\');
+            break;
+        } else if (*it == '"') {
+            escaped.append(num_backslashes * 2 + 1, '\\');
+            escaped.push_back(*it);
+        } else {
+            escaped.append(num_backslashes, '\\');
+            escaped.push_back(*it);
+        }
+    }
+    escaped.push_back('"');
+
+    return escaped;
+}
+
 
 void create_empty_file(std::string const& path) {
     std::ofstream ofs(path);
@@ -60,8 +92,9 @@
 void exec_cmd(std::string const& cmd, int log_num, std::string const& path) {
     std::array<char, 128> buffer;
 #if defined(_WIN32)
+    // cmd has already been escaped outside this function.
     auto real_cmd = "OpenCppCoverage --export_type binary:cov-report" + std::to_string(log_num)
-        + ".bin --quiet " + "--sources " + path + " --cover_children -- " + cmd;
+        + ".bin --quiet " + "--sources " + escape_arg(path) + " --cover_children -- " + cmd;
     std::cout << "=== Marker ===: Cmd: " << real_cmd << '\n';
     std::shared_ptr<FILE> pipe(_popen(real_cmd.c_str(), "r"), _pclose);
 #else // Just for testing, in the real world we will always work under WIN32
@@ -91,10 +124,15 @@
     assert(sep - begin(args) == 2 && "Structure differs from expected!");
 
     auto num = parse_log_file_arg(args[1]);
-
+    
     auto cmdline = std::accumulate(++sep, end(args), std::string{}, [] (const std::string& lhs, const std::string& rhs) {
-        return lhs + ' ' + rhs;
+        return lhs + ' ' + escape_arg(rhs);
     });
 
-    exec_cmd(cmdline, num, windowsify_path(catch_path(args[0])));
+    try {
+        return exec_cmd(cmdline, num, windowsify_path(catch_path(args[0])));
+    } catch (std::exception const& ex) {
+        std::cerr << "Helper failed with: '" << ex.what() << "'\n";
+        return 12;
+    }
 }
diff --git a/misc/installOpenCppCoverage.ps1 b/misc/installOpenCppCoverage.ps1
index 9dbffca..d277a55 100644
--- a/misc/installOpenCppCoverage.ps1
+++ b/misc/installOpenCppCoverage.ps1
@@ -1,5 +1,5 @@
-# Downloads are done from the oficial github release page links
-$downloadUrl = "https://github.com/OpenCppCoverage/OpenCppCoverage/releases/download/release-0.9.6.1/OpenCppCoverageSetup-x64-0.9.6.1.exe"
+# Downloads are done from the official github release page links
+$downloadUrl = "https://github.com/OpenCppCoverage/OpenCppCoverage/releases/download/release-0.9.7.0/OpenCppCoverageSetup-x64-0.9.7.0.exe"
 $installerPath = [System.IO.Path]::Combine($Env:USERPROFILE, "Downloads", "OpenCppCoverageSetup.exe")
 
 if(-Not (Test-Path $installerPath)) {
diff --git a/projects/Benchmark/BenchMain.cpp b/projects/Benchmark/BenchMain.cpp
deleted file mode 100644
index 32ef4ed..0000000
--- a/projects/Benchmark/BenchMain.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- *  Created by Martin on 16/01/2017.
- *
- *  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)
- */
-
-#define CATCH_CONFIG_MAIN
-#include "catch.hpp"
diff --git a/projects/Benchmark/StringificationBench.cpp b/projects/Benchmark/StringificationBench.cpp
deleted file mode 100644
index 765b4e9..0000000
--- a/projects/Benchmark/StringificationBench.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *  Created by Martin on 16/01/2017.
- *
- *  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 <vector>
-
-///////////////////////////////////////////////////////////////////////////////
-TEST_CASE("Successful tests -- REQUIRE", "[Success]") {
-    const std::size_t sz = 1 * 1024 * 1024;
-
-
-    std::vector<std::size_t> vec; vec.reserve(sz);
-    for (std::size_t i = 0; i < sz; ++i){
-        vec.push_back(i);
-        REQUIRE(vec.back() == i);
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-TEST_CASE("Successful tests -- CHECK", "[Success]") {
-    const std::size_t sz = 1 * 1024 * 1024;
-
-
-    std::vector<std::size_t> vec; vec.reserve(sz);
-    for (std::size_t i = 0; i < sz; ++i){
-        vec.push_back(i);
-        CHECK(vec.back() == i);
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-TEST_CASE("Unsuccessful tests -- CHECK", "[Failure]") {
-    const std::size_t sz = 1024 * 1024;
-
-
-    std::vector<std::size_t> vec; vec.reserve(sz);
-    for (std::size_t i = 0; i < sz; ++i){
-        vec.push_back(i);
-        CHECK(vec.size() == i);
-    }
-}
diff --git a/projects/Benchmark/readme.txt b/projects/Benchmark/readme.txt
deleted file mode 100644
index c4d2fab..0000000
--- a/projects/Benchmark/readme.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is very much a work in progress.
-The past results are standardized to a developer's machine,
-the benchmarking script is basic and there are only 3 benchmarks,
-but this should get better in time. For now, at least there is something to go by.
diff --git a/projects/Benchmark/results/2017-01-14T21-53-49-e3659cdddd43ba4df9e4846630be6a6a7bd85a07.result b/projects/Benchmark/results/2017-01-14T21-53-49-e3659cdddd43ba4df9e4846630be6a6a7bd85a07.result
deleted file mode 100644
index 4b6fc65..0000000
--- a/projects/Benchmark/results/2017-01-14T21-53-49-e3659cdddd43ba4df9e4846630be6a6a7bd85a07.result
+++ /dev/null
@@ -1,3 +0,0 @@
-Successful tests -- CHECK: median: 3.38116 (s), stddev: 0.11567366292001534 (s)
-Successful tests -- REQUIRE: median: 3.479955 (s), stddev: 0.16295972890734556 (s)
-Unsuccessful tests -- CHECK: median: 1.966895 (s), stddev: 0.06323488524716572 (s)
diff --git a/projects/Benchmark/results/2017-01-14T21-59-08-a1e9b841ff500b2f39ccfd4193ae450cb653da05.result b/projects/Benchmark/results/2017-01-14T21-59-08-a1e9b841ff500b2f39ccfd4193ae450cb653da05.result
deleted file mode 100644
index 98c8460..0000000
--- a/projects/Benchmark/results/2017-01-14T21-59-08-a1e9b841ff500b2f39ccfd4193ae450cb653da05.result
+++ /dev/null
@@ -1,3 +0,0 @@
-Successful tests -- CHECK: median: 1.30312 (s), stddev: 0.08759818557862176 (s)
-Successful tests -- REQUIRE: median: 1.341535 (s), stddev: 0.1479193390143576 (s)
-Unsuccessful tests -- CHECK: median: 1.967755 (s), stddev: 0.07921104121269959 (s)
diff --git a/projects/Benchmark/results/2017-01-15T09-35-14-3b98a0166f7b7196eba2ad518174d1a77165166d.result b/projects/Benchmark/results/2017-01-15T09-35-14-3b98a0166f7b7196eba2ad518174d1a77165166d.result
deleted file mode 100644
index fe6366b..0000000
--- a/projects/Benchmark/results/2017-01-15T09-35-14-3b98a0166f7b7196eba2ad518174d1a77165166d.result
+++ /dev/null
@@ -1,3 +0,0 @@
-Successful tests -- CHECK: median: 1.2982 (s), stddev: 0.019540648829214084 (s)
-Successful tests -- REQUIRE: median: 1.30102 (s), stddev: 0.014758430547392974 (s)
-Unsuccessful tests -- CHECK: median: 15.520199999999999 (s), stddev: 0.09536359426485094 (s)
diff --git a/projects/Benchmark/results/2017-01-29T22-08-36-60f8ebec49c5bc58d3604bf1a72cd3f7d129bf2e.result b/projects/Benchmark/results/2017-01-29T22-08-36-60f8ebec49c5bc58d3604bf1a72cd3f7d129bf2e.result
deleted file mode 100644
index c9b4d64..0000000
--- a/projects/Benchmark/results/2017-01-29T22-08-36-60f8ebec49c5bc58d3604bf1a72cd3f7d129bf2e.result
+++ /dev/null
@@ -1,3 +0,0 @@
-Successful tests -- CHECK: median: 0.7689014999999999 (s), stddev: 0.02127512078801068 (s)
-Successful tests -- REQUIRE: median: 0.772845 (s), stddev: 0.03011638381365052 (s)
-Unsuccessful tests -- CHECK: median: 15.49 (s), stddev: 0.536088571143903 (s)
diff --git a/projects/Benchmark/results/2017-01-29T23-13-35-bcaa2f9646c5ce50758f8582307c99501a932e1a.result b/projects/Benchmark/results/2017-01-29T23-13-35-bcaa2f9646c5ce50758f8582307c99501a932e1a.result
deleted file mode 100644
index 5b82330..0000000
--- a/projects/Benchmark/results/2017-01-29T23-13-35-bcaa2f9646c5ce50758f8582307c99501a932e1a.result
+++ /dev/null
@@ -1,3 +0,0 @@
-Successful tests -- CHECK: median: 0.775769 (s), stddev: 0.014802129132136525 (s)
-Successful tests -- REQUIRE: median: 0.785235 (s), stddev: 0.03532672836834896 (s)
-Unsuccessful tests -- CHECK: median: 15.156600000000001 (s), stddev: 0.2832375673450742 (s)
diff --git a/projects/CMakeLists.txt b/projects/CMakeLists.txt
new file mode 100644
index 0000000..b3caa82
--- /dev/null
+++ b/projects/CMakeLists.txt
@@ -0,0 +1,367 @@
+include(MiscFunctions)
+
+####
+# Temporary workaround for VS toolset changes in 2017
+# We need to disable <UseFullPaths> property, but CMake doesn't support it
+# until 3.13 (not yet released)
+####
+if (MSVC)
+configure_file(${CATCH_DIR}/misc/SelfTest.vcxproj.user
+               ${CMAKE_BINARY_DIR}/projects
+               COPYONLY)
+endif(MSVC) #Temporary workaround
+
+
+# define the sources of the self test
+# Please keep these ordered alphabetically
+set(TEST_SOURCES
+        ${SELF_TEST_DIR}/TestMain.cpp
+        ${SELF_TEST_DIR}/IntrospectiveTests/CmdLine.tests.cpp
+        ${SELF_TEST_DIR}/IntrospectiveTests/GeneratorsImpl.tests.cpp
+        ${SELF_TEST_DIR}/IntrospectiveTests/PartTracker.tests.cpp
+        ${SELF_TEST_DIR}/IntrospectiveTests/TagAlias.tests.cpp
+        ${SELF_TEST_DIR}/IntrospectiveTests/String.tests.cpp
+        ${SELF_TEST_DIR}/IntrospectiveTests/Xml.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/Approx.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/BDD.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/Benchmark.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/Class.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/Compilation.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/Condition.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/Decomposition.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/EnumToString.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/Exception.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/Generators.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/Message.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/Misc.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/ToStringChrono.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/ToStringGeneral.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/ToStringOptional.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/ToStringPair.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/ToStringTuple.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/ToStringVariant.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/ToStringVector.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/ToStringWhich.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/Tricky.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/VariadicMacros.tests.cpp
+        ${SELF_TEST_DIR}/UsageTests/Matchers.tests.cpp
+        )
+CheckFileList(TEST_SOURCES ${SELF_TEST_DIR})
+
+# A set of impl files that just #include a single header
+# Please keep these ordered alphabetically
+set(SURROGATE_SOURCES
+        ${SELF_TEST_DIR}/SurrogateCpps/catch_console_colour.cpp
+        ${SELF_TEST_DIR}/SurrogateCpps/catch_debugger.cpp
+        ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_reporter.cpp
+        ${SELF_TEST_DIR}/SurrogateCpps/catch_option.cpp
+        ${SELF_TEST_DIR}/SurrogateCpps/catch_stream.cpp
+        ${SELF_TEST_DIR}/SurrogateCpps/catch_test_case_tracker.cpp
+        ${SELF_TEST_DIR}/SurrogateCpps/catch_test_spec.cpp
+        ${SELF_TEST_DIR}/SurrogateCpps/catch_xmlwriter.cpp
+        )
+CheckFileList(SURROGATE_SOURCES ${SELF_TEST_DIR}/SurrogateCpps)
+
+
+# Please keep these ordered alphabetically
+set(TOP_LEVEL_HEADERS
+        ${HEADER_DIR}/catch.hpp
+        ${HEADER_DIR}/catch_with_main.hpp
+        )
+CheckFileList(TOP_LEVEL_HEADERS ${HEADER_DIR})
+
+# Please keep these ordered alphabetically
+set(EXTERNAL_HEADERS
+        ${HEADER_DIR}/external/clara.hpp
+        )
+CheckFileList(EXTERNAL_HEADERS ${HEADER_DIR}/external)
+
+
+# Please keep these ordered alphabetically
+set(INTERNAL_HEADERS
+        ${HEADER_DIR}/internal/catch_approx.h
+        ${HEADER_DIR}/internal/catch_assertionhandler.h
+        ${HEADER_DIR}/internal/catch_assertioninfo.h
+        ${HEADER_DIR}/internal/catch_assertionresult.h
+        ${HEADER_DIR}/internal/catch_capture.hpp
+        ${HEADER_DIR}/internal/catch_capture_matchers.h
+        ${HEADER_DIR}/internal/catch_clara.h
+        ${HEADER_DIR}/internal/catch_commandline.h
+        ${HEADER_DIR}/internal/catch_common.h
+        ${HEADER_DIR}/internal/catch_compiler_capabilities.h
+        ${HEADER_DIR}/internal/catch_config.hpp
+        ${HEADER_DIR}/internal/catch_console_colour.h
+        ${HEADER_DIR}/internal/catch_context.h
+        ${HEADER_DIR}/internal/catch_debug_console.h
+        ${HEADER_DIR}/internal/catch_debugger.h
+        ${HEADER_DIR}/internal/catch_decomposer.h
+        ${HEADER_DIR}/internal/catch_default_main.hpp
+        ${HEADER_DIR}/internal/catch_enforce.h
+        ${HEADER_DIR}/internal/catch_errno_guard.h
+        ${HEADER_DIR}/internal/catch_exception_translator_registry.h
+        ${HEADER_DIR}/internal/catch_external_interfaces.h
+        ${HEADER_DIR}/internal/catch_fatal_condition.h
+        ${HEADER_DIR}/internal/catch_generators.hpp
+        ${HEADER_DIR}/internal/catch_generators_generic.hpp
+        ${HEADER_DIR}/internal/catch_generators_specific.hpp
+        ${HEADER_DIR}/internal/catch_impl.hpp
+        ${HEADER_DIR}/internal/catch_interfaces_capture.h
+        ${HEADER_DIR}/internal/catch_interfaces_config.h
+        ${HEADER_DIR}/internal/catch_interfaces_exception.h
+        ${HEADER_DIR}/internal/catch_interfaces_registry_hub.h
+        ${HEADER_DIR}/internal/catch_interfaces_reporter.h
+        ${HEADER_DIR}/internal/catch_interfaces_runner.h
+        ${HEADER_DIR}/internal/catch_interfaces_tag_alias_registry.h
+        ${HEADER_DIR}/internal/catch_interfaces_testcase.h
+        ${HEADER_DIR}/internal/catch_leak_detector.h
+        ${HEADER_DIR}/internal/catch_list.h
+        ${HEADER_DIR}/internal/catch_matchers.h
+        ${HEADER_DIR}/internal/catch_matchers_floating.h
+        ${HEADER_DIR}/internal/catch_matchers_generic.hpp
+        ${HEADER_DIR}/internal/catch_matchers_string.h
+        ${HEADER_DIR}/internal/catch_matchers_vector.h
+        ${HEADER_DIR}/internal/catch_message.h
+        ${HEADER_DIR}/internal/catch_meta.hpp
+        ${HEADER_DIR}/internal/catch_objc.hpp
+        ${HEADER_DIR}/internal/catch_objc_arc.hpp
+        ${HEADER_DIR}/internal/catch_option.hpp
+        ${HEADER_DIR}/internal/catch_output_redirect.h
+        ${HEADER_DIR}/internal/catch_platform.h
+        ${HEADER_DIR}/internal/catch_polyfills.hpp
+        ${HEADER_DIR}/internal/catch_preprocessor.hpp
+        ${HEADER_DIR}/internal/catch_random_number_generator.h
+        ${HEADER_DIR}/internal/catch_reenable_warnings.h
+        ${HEADER_DIR}/internal/catch_reporter_registrars.hpp
+        ${HEADER_DIR}/internal/catch_reporter_registry.h
+        ${HEADER_DIR}/internal/catch_result_type.h
+        ${HEADER_DIR}/internal/catch_run_context.h
+        ${HEADER_DIR}/internal/catch_benchmark.h
+        ${HEADER_DIR}/internal/catch_section.h
+        ${HEADER_DIR}/internal/catch_section_info.h
+        ${HEADER_DIR}/internal/catch_session.h
+        ${HEADER_DIR}/internal/catch_singletons.hpp
+        ${HEADER_DIR}/internal/catch_startup_exception_registry.h
+        ${HEADER_DIR}/internal/catch_stream.h
+        ${HEADER_DIR}/internal/catch_stringref.h
+        ${HEADER_DIR}/internal/catch_string_manip.h
+        ${HEADER_DIR}/internal/catch_suppress_warnings.h
+        ${HEADER_DIR}/internal/catch_tag_alias.h
+        ${HEADER_DIR}/internal/catch_tag_alias_autoregistrar.h
+        ${HEADER_DIR}/internal/catch_tag_alias_registry.h
+        ${HEADER_DIR}/internal/catch_test_case_info.h
+        ${HEADER_DIR}/internal/catch_test_case_registry_impl.h
+        ${HEADER_DIR}/internal/catch_test_case_tracker.h
+        ${HEADER_DIR}/internal/catch_test_registry.h
+        ${HEADER_DIR}/internal/catch_test_spec.h
+        ${HEADER_DIR}/internal/catch_test_spec_parser.h
+        ${HEADER_DIR}/internal/catch_text.h
+        ${HEADER_DIR}/internal/catch_timer.h
+        ${HEADER_DIR}/internal/catch_to_string.hpp
+        ${HEADER_DIR}/internal/catch_tostring.h
+        ${HEADER_DIR}/internal/catch_totals.h
+        ${HEADER_DIR}/internal/catch_type_traits.hpp
+        ${HEADER_DIR}/internal/catch_uncaught_exceptions.h
+        ${HEADER_DIR}/internal/catch_user_interfaces.h
+        ${HEADER_DIR}/internal/catch_version.h
+        ${HEADER_DIR}/internal/catch_wildcard_pattern.h
+        ${HEADER_DIR}/internal/catch_windows_h_proxy.h
+        ${HEADER_DIR}/internal/catch_xmlwriter.h
+        )
+set(IMPL_SOURCES
+        ${HEADER_DIR}/internal/catch_approx.cpp
+        ${HEADER_DIR}/internal/catch_assertionhandler.cpp
+        ${HEADER_DIR}/internal/catch_assertionresult.cpp
+        ${HEADER_DIR}/internal/catch_benchmark.cpp
+        ${HEADER_DIR}/internal/catch_capture_matchers.cpp
+        ${HEADER_DIR}/internal/catch_commandline.cpp
+        ${HEADER_DIR}/internal/catch_common.cpp
+        ${HEADER_DIR}/internal/catch_config.cpp
+        ${HEADER_DIR}/internal/catch_console_colour.cpp
+        ${HEADER_DIR}/internal/catch_context.cpp
+        ${HEADER_DIR}/internal/catch_debug_console.cpp
+        ${HEADER_DIR}/internal/catch_debugger.cpp
+        ${HEADER_DIR}/internal/catch_decomposer.cpp
+        ${HEADER_DIR}/internal/catch_enforce.cpp
+        ${HEADER_DIR}/internal/catch_errno_guard.cpp
+        ${HEADER_DIR}/internal/catch_exception_translator_registry.cpp
+        ${HEADER_DIR}/internal/catch_fatal_condition.cpp
+        ${HEADER_DIR}/internal/catch_generators.cpp
+        ${HEADER_DIR}/internal/catch_interfaces_capture.cpp
+        ${HEADER_DIR}/internal/catch_interfaces_config.cpp
+        ${HEADER_DIR}/internal/catch_interfaces_exception.cpp
+        ${HEADER_DIR}/internal/catch_interfaces_generatortracker.h
+        ${HEADER_DIR}/internal/catch_interfaces_registry_hub.cpp
+        ${HEADER_DIR}/internal/catch_interfaces_runner.cpp
+        ${HEADER_DIR}/internal/catch_interfaces_testcase.cpp
+        ${HEADER_DIR}/internal/catch_list.cpp
+        ${HEADER_DIR}/internal/catch_leak_detector.cpp
+        ${HEADER_DIR}/internal/catch_matchers.cpp
+        ${HEADER_DIR}/internal/catch_matchers_floating.cpp
+        ${HEADER_DIR}/internal/catch_matchers_generic.cpp
+        ${HEADER_DIR}/internal/catch_matchers_string.cpp
+        ${HEADER_DIR}/internal/catch_message.cpp
+        ${HEADER_DIR}/internal/catch_output_redirect.cpp
+        ${HEADER_DIR}/internal/catch_registry_hub.cpp
+        ${HEADER_DIR}/internal/catch_interfaces_reporter.cpp
+        ${HEADER_DIR}/internal/catch_polyfills.cpp
+        ${HEADER_DIR}/internal/catch_random_number_generator.cpp
+        ${HEADER_DIR}/internal/catch_reporter_registry.cpp
+        ${HEADER_DIR}/internal/catch_result_type.cpp
+        ${HEADER_DIR}/internal/catch_run_context.cpp
+        ${HEADER_DIR}/internal/catch_section.cpp
+        ${HEADER_DIR}/internal/catch_section_info.cpp
+        ${HEADER_DIR}/internal/catch_session.cpp
+        ${HEADER_DIR}/internal/catch_singletons.cpp
+        ${HEADER_DIR}/internal/catch_startup_exception_registry.cpp
+        ${HEADER_DIR}/internal/catch_stream.cpp
+        ${HEADER_DIR}/internal/catch_stringref.cpp
+        ${HEADER_DIR}/internal/catch_string_manip.cpp
+        ${HEADER_DIR}/internal/catch_tag_alias.cpp
+        ${HEADER_DIR}/internal/catch_tag_alias_autoregistrar.cpp
+        ${HEADER_DIR}/internal/catch_tag_alias_registry.cpp
+        ${HEADER_DIR}/internal/catch_test_case_info.cpp
+        ${HEADER_DIR}/internal/catch_test_case_registry_impl.cpp
+        ${HEADER_DIR}/internal/catch_test_case_tracker.cpp
+        ${HEADER_DIR}/internal/catch_test_registry.cpp
+        ${HEADER_DIR}/internal/catch_test_spec.cpp
+        ${HEADER_DIR}/internal/catch_test_spec_parser.cpp
+        ${HEADER_DIR}/internal/catch_timer.cpp
+        ${HEADER_DIR}/internal/catch_tostring.cpp
+        ${HEADER_DIR}/internal/catch_totals.cpp
+        ${HEADER_DIR}/internal/catch_uncaught_exceptions.cpp
+        ${HEADER_DIR}/internal/catch_version.cpp
+        ${HEADER_DIR}/internal/catch_wildcard_pattern.cpp
+        ${HEADER_DIR}/internal/catch_xmlwriter.cpp
+        )
+set(INTERNAL_FILES ${IMPL_SOURCES} ${INTERNAL_HEADERS})
+CheckFileList(INTERNAL_FILES ${HEADER_DIR}/internal)
+
+# Please keep these ordered alphabetically
+set(REPORTER_HEADERS
+        ${HEADER_DIR}/reporters/catch_reporter_automake.hpp
+        ${HEADER_DIR}/reporters/catch_reporter_bases.hpp
+        ${HEADER_DIR}/reporters/catch_reporter_compact.h
+        ${HEADER_DIR}/reporters/catch_reporter_console.h
+        ${HEADER_DIR}/reporters/catch_reporter_junit.h
+        ${HEADER_DIR}/reporters/catch_reporter_listening.h
+        ${HEADER_DIR}/reporters/catch_reporter_tap.hpp
+        ${HEADER_DIR}/reporters/catch_reporter_teamcity.hpp
+        ${HEADER_DIR}/reporters/catch_reporter_xml.h
+        )
+set(REPORTER_SOURCES
+        ${HEADER_DIR}/reporters/catch_reporter_bases.cpp
+        ${HEADER_DIR}/reporters/catch_reporter_compact.cpp
+        ${HEADER_DIR}/reporters/catch_reporter_console.cpp
+        ${HEADER_DIR}/reporters/catch_reporter_junit.cpp
+        ${HEADER_DIR}/reporters/catch_reporter_listening.cpp
+        ${HEADER_DIR}/reporters/catch_reporter_xml.cpp
+        )
+set(REPORTER_FILES ${REPORTER_HEADERS} ${REPORTER_SOURCES})
+CheckFileList(REPORTER_FILES ${HEADER_DIR}/reporters)
+
+# Specify the headers, too, so CLion recognises them as project files
+set(HEADERS
+        ${TOP_LEVEL_HEADERS}
+        ${EXTERNAL_HEADERS}
+        ${INTERNAL_HEADERS}
+        ${REPORTER_HEADERS}
+        )
+
+# Provide some groupings for IDEs
+SOURCE_GROUP("Tests" FILES ${TEST_SOURCES})
+SOURCE_GROUP("Surrogates" FILES ${SURROGATE_SOURCES})
+
+include(CTest)
+
+add_executable(SelfTest ${TEST_SOURCES} ${IMPL_SOURCES} ${REPORTER_SOURCES} ${SURROGATE_SOURCES} ${HEADERS})
+target_include_directories(SelfTest PRIVATE ${HEADER_DIR})
+
+if(USE_CPP17)
+    message(STATUS "Enabling C++17")
+    set_property(TARGET SelfTest PROPERTY CXX_STANDARD 17)
+elseif(USE_CPP14)
+    message(STATUS "Enabling C++14")
+    set_property(TARGET SelfTest PROPERTY CXX_STANDARD 14)
+else()
+    message(STATUS "Enabling C++11")
+    set_property(TARGET SelfTest PROPERTY CXX_STANDARD 11)
+endif()
+
+set_property(TARGET SelfTest PROPERTY CXX_STANDARD_REQUIRED ON)
+set_property(TARGET SelfTest PROPERTY CXX_EXTENSIONS OFF)
+
+if (CATCH_ENABLE_COVERAGE)
+    set(ENABLE_COVERAGE ON CACHE BOOL "Enable coverage build." FORCE)
+    find_package(codecov)
+    add_coverage(SelfTest)
+    list(APPEND LCOV_REMOVE_PATTERNS "'/usr/*'")
+    coverage_evaluate()
+endif()
+
+# Add per compiler options
+if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" )
+    target_compile_options( SelfTest PRIVATE -Wall -Wextra -Wunreachable-code -Wpedantic -Wmissing-declarations )
+    if (CATCH_ENABLE_WERROR)
+        target_compile_options( SelfTest PRIVATE -Werror)
+    endif()
+endif()
+# Clang specific options go here
+if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
+    target_compile_options( SelfTest PRIVATE -Wweak-vtables -Wexit-time-destructors -Wglobal-constructors -Wmissing-noreturn )
+endif()
+if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" )
+    STRING(REGEX REPLACE "/W[0-9]" "/W4" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) # override default warning level
+    target_compile_options( SelfTest PRIVATE /w44265 /w44061 /w44062 /w45038 )
+    if (CATCH_ENABLE_WERROR)
+        target_compile_options( SelfTest PRIVATE /WX)
+    endif()
+    # Force MSVC to consider everything as encoded in utf-8
+    target_compile_options( SelfTest PRIVATE /utf-8 )
+endif()
+
+
+# configure unit tests via CTest
+add_test(NAME RunTests COMMAND $<TARGET_FILE:SelfTest>)
+
+add_test(NAME ListTests COMMAND $<TARGET_FILE:SelfTest> --list-tests --verbosity high)
+set_tests_properties(ListTests PROPERTIES 
+    PASS_REGULAR_EXPRESSION "[0-9]+ test cases"
+    FAIL_REGULAR_EXPRESSION "Hidden Test"
+)
+
+add_test(NAME ListTags COMMAND $<TARGET_FILE:SelfTest> --list-tags)
+set_tests_properties(ListTags PROPERTIES 
+    PASS_REGULAR_EXPRESSION "[0-9]+ tags" 
+    FAIL_REGULAR_EXPRESSION "\\[\\.\\]")
+
+add_test(NAME ListReporters COMMAND $<TARGET_FILE:SelfTest> --list-reporters)
+set_tests_properties(ListReporters PROPERTIES PASS_REGULAR_EXPRESSION "Available reporters:")
+
+add_test(NAME ListTestNamesOnly COMMAND $<TARGET_FILE:SelfTest> --list-test-names-only)
+set_tests_properties(ListTestNamesOnly PROPERTIES 
+    PASS_REGULAR_EXPRESSION "Regex string matcher"
+    FAIL_REGULAR_EXPRESSION "Hidden Test")
+
+add_test(NAME NoAssertions COMMAND $<TARGET_FILE:SelfTest> -w NoAssertions)
+set_tests_properties(NoAssertions PROPERTIES PASS_REGULAR_EXPRESSION "No assertions in test case")
+
+add_test(NAME NoTest COMMAND $<TARGET_FILE:SelfTest> -w NoTests "___nonexistent_test___")
+set_tests_properties(NoTest PROPERTIES PASS_REGULAR_EXPRESSION "No test cases matched")
+
+add_test(NAME FilteredSection-1 COMMAND $<TARGET_FILE:SelfTest> \#1394 -c RunSection)
+set_tests_properties(FilteredSection-1 PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran")
+add_test(NAME FilteredSection-2 COMMAND $<TARGET_FILE:SelfTest> \#1394\ nested -c NestedRunSection -c s1)
+set_tests_properties(FilteredSection-2 PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran")
+
+# AppVeyor has a Python 2.7 in path, but doesn't have .py files as autorunnable
+add_test(NAME ApprovalTests COMMAND ${PYTHON_EXECUTABLE} ${CATCH_DIR}/scripts/approvalTests.py $<TARGET_FILE:SelfTest>)
+set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed")
+
+
+if (CATCH_USE_VALGRIND)
+    add_test(NAME ValgrindRunTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest>)
+    add_test(NAME ValgrindListTests COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tests --verbosity high)
+    set_tests_properties(ValgrindListTests PROPERTIES PASS_REGULAR_EXPRESSION "definitely lost: 0 bytes in 0 blocks")
+    add_test(NAME ValgrindListTags COMMAND valgrind --leak-check=full --error-exitcode=1 $<TARGET_FILE:SelfTest> --list-tags)
+    set_tests_properties(ValgrindListTags PROPERTIES PASS_REGULAR_EXPRESSION "definitely lost: 0 bytes in 0 blocks")
+endif()
diff --git a/projects/ExtraTests/CMakeLists.txt b/projects/ExtraTests/CMakeLists.txt
new file mode 100644
index 0000000..c0dd82d
--- /dev/null
+++ b/projects/ExtraTests/CMakeLists.txt
@@ -0,0 +1,135 @@
+#
+# Build extra tests.
+#
+# Requires CATCH_BUILD_EXTRA_TESTS to be defined 'true', see ../CMakeLists.txt.
+#
+
+cmake_minimum_required( VERSION 3.5 )
+
+project( Catch2ExtraTests LANGUAGES CXX )
+
+message( STATUS "Extra tests included" )
+
+# define folders used:
+
+set( TESTS_DIR   ${CATCH_DIR}/projects/ExtraTests )
+set( SINGLE_INCLUDE_PATH ${CATCH_DIR}/single_include )
+
+
+add_executable(PrefixedMacros ${TESTS_DIR}/X01-PrefixedMacros.cpp)
+target_compile_definitions( PrefixedMacros PRIVATE CATCH_CONFIG_PREFIX_ALL )
+
+add_test(NAME CATCH_CONFIG_PREFIX_ALL COMMAND PrefixedMacros -s)
+set_tests_properties(
+    CATCH_CONFIG_PREFIX_ALL
+  PROPERTIES
+    PASS_REGULAR_EXPRESSION "CATCH_"
+    FAIL_REGULAR_EXPRESSION
+    # The spaces are important -> They disambiguate between CATCH_REQUIRE
+    # and REQUIRE without prefix.
+    " REQUIRE; REQUIRE_FALSE; REQUIRE_THROWS; REQUIRE_THROWS_AS; REQUIRE_THROWS_WITH; REQUIRE_THROWS_MATCHES; REQUIRE_NOTHROW; CHECK; CHECK_FALSE; CHECKED_IF; CHECKED_ELSE; CHECK_NOFAIL; CHECK_THROWS; CHECK_THROWS_AS; CHECK_THROWS_WITH; CHECK_THROWS_MATCHES; CHECK_NOTHROW; REQUIRE_THAT; CHECK_THAT"
+)
+
+add_executable(DisabledMacros ${TESTS_DIR}/X02-DisabledMacros.cpp)
+target_compile_definitions( DisabledMacros PRIVATE CATCH_CONFIG_DISABLE )
+
+add_test(NAME CATCH_CONFIG_DISABLE-1 COMMAND DisabledMacros -s)
+set_tests_properties(
+    CATCH_CONFIG_DISABLE-1
+  PROPERTIES
+    PASS_REGULAR_EXPRESSION "No tests ran"
+    FAIL_REGULAR_EXPRESSION "This should not happen"
+)
+add_test(NAME CATCH_CONFIG_DISABLE-2 COMMAND DisabledMacros --list-tests)
+set_tests_properties(
+    CATCH_CONFIG_DISABLE-2
+  PROPERTIES
+    PASS_REGULAR_EXPRESSION "0 test cases"
+)
+
+
+add_executable( DisabledExceptions-DefaultHandler ${TESTS_DIR}/X03-DisabledExceptions-DefaultHandler.cpp )
+add_executable( DisabledExceptions-CustomHandler ${TESTS_DIR}/X04-DisabledExceptions-CustomHandler.cpp )
+
+foreach(target DisabledExceptions-DefaultHandler DisabledExceptions-CustomHandler)
+target_compile_options( ${target}
+  PRIVATE
+    $<$<CXX_COMPILER_ID:MSVC>:/EHs-c-;/D_HAS_EXCEPTIONS=0>
+    $<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:AppleClang>>:-fno-exceptions>
+#    $<$<CXX_COMPILER_ID:Clang>:-fno-exceptions>
+#    $<$<CXX_COMPILER_ID:GNU>:-fno-exceptions>
+)
+endforeach()
+
+
+add_test(NAME CATCH_CONFIG_DISABLE_EXCEPTIONS-1 COMMAND DisabledExceptions-DefaultHandler "Tests that run")
+set_tests_properties(
+    CATCH_CONFIG_DISABLE_EXCEPTIONS-1
+  PROPERTIES
+    PASS_REGULAR_EXPRESSION "assertions: 4 \| 2 passed \| 2 failed"
+    FAIL_REGULAR_EXPRESSION "abort;terminate;fatal"
+)
+
+add_test(NAME CATCH_CONFIG_DISABLE_EXCEPTIONS-2 COMMAND DisabledExceptions-DefaultHandler "Tests that abort")
+set_tests_properties(
+    CATCH_CONFIG_DISABLE_EXCEPTIONS-2
+  PROPERTIES
+    PASS_REGULAR_EXPRESSION "Catch will terminate"
+)
+
+add_test(NAME CATCH_CONFIG_DISABLE_EXCEPTIONS-3 COMMAND DisabledExceptions-CustomHandler "Tests that run")
+set_tests_properties(
+    CATCH_CONFIG_DISABLE_EXCEPTIONS-3
+  PROPERTIES
+    PASS_REGULAR_EXPRESSION "assertions: 4 \| 2 passed \| 2 failed"
+    FAIL_REGULAR_EXPRESSION "====== CUSTOM HANDLER ======"
+)
+
+add_test(NAME CATCH_CONFIG_DISABLE_EXCEPTIONS-4 COMMAND DisabledExceptions-CustomHandler "Tests that abort")
+set_tests_properties(
+    CATCH_CONFIG_DISABLE_EXCEPTIONS-4
+  PROPERTIES
+    PASS_REGULAR_EXPRESSION "====== CUSTOM HANDLER ======"
+)
+
+
+
+add_executable(FallbackStringifier ${TESTS_DIR}/X10-FallbackStringifier.cpp)
+target_compile_definitions( FallbackStringifier PRIVATE CATCH_CONFIG_FALLBACK_STRINGIFIER=fallbackStringifier )
+
+add_test(NAME FallbackStringifier COMMAND FallbackStringifier -r compact -s)
+set_tests_properties(
+    FallbackStringifier
+  PROPERTIES
+    PASS_REGULAR_EXPRESSION "foo{} for: { !!! }"
+)
+
+
+add_executable(DisableStringification ${TESTS_DIR}/X11-DisableStringification.cpp)
+target_compile_definitions( DisableStringification PRIVATE CATCH_CONFIG_DISABLE_STRINGIFICATION )
+add_test(NAME CATCH_CONFIG_DISABLE_STRINGIFICATION COMMAND DisableStringification -r compact -s)
+set_tests_properties(
+    CATCH_CONFIG_DISABLE_STRINGIFICATION
+  PROPERTIES
+    PASS_REGULAR_EXPRESSION "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
+    FAIL_REGULAR_EXPRESSION  "Hidden{} == Hidden{}"
+)
+
+
+set( EXTRA_TEST_BINARIES
+    PrefixedMacros
+    DisabledMacros
+    DisabledExceptions-DefaultHandler
+    DisabledExceptions-CustomHandler
+    FallbackStringifier
+    DisableStringification
+)
+
+# Shared config
+foreach( test ${EXTRA_TEST_BINARIES} )
+    set_property( TARGET ${test} PROPERTY CXX_STANDARD 11 )
+    set_property( TARGET ${test} PROPERTY CXX_STANDARD_REQUIRED ON )
+    set_property( TARGET ${test} PROPERTY CXX_EXTENSIONS OFF )
+    target_include_directories( ${test} PRIVATE ${SINGLE_INCLUDE_PATH} )
+endforeach()
+
diff --git a/projects/ExtraTests/ToDo.txt b/projects/ExtraTests/ToDo.txt
new file mode 100644
index 0000000..ab68bd3
--- /dev/null
+++ b/projects/ExtraTests/ToDo.txt
@@ -0,0 +1,11 @@
+Configuration options that are left default and thus are not properly tested
+yet:
+
+    CATCH_CONFIG_COUNTER                    // Use __COUNTER__ to generate unique names for test cases
+    CATCH_CONFIG_WINDOWS_SEH                // Enable SEH handling on Windows
+    CATCH_CONFIG_FAST_COMPILE               // Sacrifices some (rather minor) features for compilation speed
+    CATCH_CONFIG_DISABLE_MATCHERS           // Do not compile Matchers in this compilation unit
+    CATCH_CONFIG_POSIX_SIGNALS              // Enable handling POSIX signals
+    CATCH_CONFIG_WINDOWS_CRTDBG             // Enable leak checking using Windows's CRT Debug Heap
+    CATCH_CONFIG_DEFAULT_REPORTER
+    CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS
diff --git a/projects/ExtraTests/X01-PrefixedMacros.cpp b/projects/ExtraTests/X01-PrefixedMacros.cpp
new file mode 100644
index 0000000..7671cbc
--- /dev/null
+++ b/projects/ExtraTests/X01-PrefixedMacros.cpp
@@ -0,0 +1,83 @@
+// X11-DisableStringification.cpp
+// Test that Catch's prefixed macros compile and run properly.
+
+#define CATCH_CONFIG_MAIN
+// This won't provide full coverage, but it might be worth checking
+// the other branch as well
+#define CATCH_CONFIG_RUNTIME_STATIC_REQUIRE
+#include <catch2/catch.hpp>
+
+#include <type_traits>
+#include <stdexcept>
+
+[[noreturn]]
+void this_throws() {
+    throw std::runtime_error("Some msg");
+}
+void this_doesnt_throw() {}
+
+CATCH_TEST_CASE("PrefixedMacros") {
+    using namespace Catch::Matchers;
+
+    CATCH_REQUIRE( 1 == 1 );
+    CATCH_REQUIRE_FALSE( 1 != 1 );
+
+    CATCH_REQUIRE_THROWS(this_throws());
+    CATCH_REQUIRE_THROWS_AS(this_throws(), std::runtime_error);
+    CATCH_REQUIRE_THROWS_WITH(this_throws(), "Some msg");
+    CATCH_REQUIRE_THROWS_MATCHES(this_throws(), std::runtime_error, Predicate<std::runtime_error>([](std::runtime_error const&) { return true; }));
+    CATCH_REQUIRE_NOTHROW(this_doesnt_throw());
+
+    CATCH_CHECK( 1 == 1 );
+    CATCH_CHECK_FALSE( 1 != 1 );
+    CATCH_CHECKED_IF( 1 == 1 ) {
+        CATCH_SUCCEED("don't care");
+    } CATCH_CHECKED_ELSE ( 1 == 1 ) {
+        CATCH_SUCCEED("don't care");
+    }
+
+    CATCH_CHECK_NOFAIL(1 == 2);
+
+    CATCH_CHECK_THROWS(this_throws());
+    CATCH_CHECK_THROWS_AS(this_throws(), std::runtime_error);
+    CATCH_CHECK_THROWS_WITH(this_throws(), "Some msg");
+    CATCH_CHECK_THROWS_MATCHES(this_throws(), std::runtime_error, Predicate<std::runtime_error>([](std::runtime_error const&) { return true; }));
+    CATCH_CHECK_NOTHROW(this_doesnt_throw());
+
+    CATCH_REQUIRE_THAT("abcd", Equals("abcd"));
+    CATCH_CHECK_THAT("bdef", Equals("bdef"));
+
+    CATCH_INFO( "some info" );
+    CATCH_WARN( "some warn" );
+    CATCH_SECTION("some section") {
+        int i = 1;
+        CATCH_CAPTURE( i );
+        CATCH_DYNAMIC_SECTION("Dynamic section: " << i) {
+            CATCH_FAIL_CHECK( "failure" );
+        }
+    }
+
+    CATCH_STATIC_REQUIRE( std::is_void<void>::value );
+    CATCH_STATIC_REQUIRE_FALSE( std::is_void<int>::value );
+}
+
+CATCH_ANON_TEST_CASE() {
+    CATCH_FAIL("");
+}
+
+// Missing:
+
+//
+// #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
+// #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
+// #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
+//
+// // "BDD-style" convenience wrappers
+// #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
+// #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
+// #define CATCH_GIVEN( desc )    INTERNAL_CATCH_DYNAMIC_SECTION( "   Given: " << desc )
+// #define CATCH_WHEN( desc )     INTERNAL_CATCH_DYNAMIC_SECTION( "    When: " << desc )
+// #define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And when: " << desc )
+// #define CATCH_THEN( desc )     INTERNAL_CATCH_DYNAMIC_SECTION( "    Then: " << desc )
+// #define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "     And: " << desc )
+//
diff --git a/projects/ExtraTests/X02-DisabledMacros.cpp b/projects/ExtraTests/X02-DisabledMacros.cpp
new file mode 100644
index 0000000..3a969d7
--- /dev/null
+++ b/projects/ExtraTests/X02-DisabledMacros.cpp
@@ -0,0 +1,31 @@
+// X02-DisabledMacros.cpp
+// Test that CATCH_CONFIG_DISABLE turns off TEST_CASE autoregistration
+// and expressions in assertion macros are not run.
+
+#define CATCH_CONFIG_MAIN
+#include <catch2/catch.hpp>
+
+
+// CATCH_CONFIG_DISABLE also prevents reporter registration.
+// We need to manually register at least one reporter for our tests
+static Catch::ReporterRegistrar<Catch::ConsoleReporter> temporary( "console" );
+
+#include <iostream>
+
+struct foo {
+    foo(){
+        REQUIRE_NOTHROW( print() );
+    }
+    void print() const {
+        std::cout << "This should not happen\n";
+    }
+};
+
+// Construct foo, but `foo::print` should not be run
+foo f;
+
+// This test should not be run, because it won't be registered
+TEST_CASE( "Disabled Macros" ) {
+    std::cout << "This should not happen\n";
+    FAIL();
+}
diff --git a/projects/ExtraTests/X03-DisabledExceptions-DefaultHandler.cpp b/projects/ExtraTests/X03-DisabledExceptions-DefaultHandler.cpp
new file mode 100644
index 0000000..846c9b0
--- /dev/null
+++ b/projects/ExtraTests/X03-DisabledExceptions-DefaultHandler.cpp
@@ -0,0 +1,23 @@
+#define CATCH_CONFIG_MAIN
+#include <catch2/catch.hpp>
+
+TEST_CASE("Tests that run") {
+    // All of these should be run and be reported
+    CHECK(1 == 2);
+    CHECK(1 == 1);
+    CHECK(1 != 3);
+    CHECK(1 == 4);
+}
+
+
+
+TEST_CASE("Tests that abort") {
+    // Avoid abort and other exceptional exits -- there is no way
+    // to tell CMake that abort is the desired outcome of a test.
+    std::set_terminate([](){exit(1);});
+    REQUIRE(1 == 1);
+    REQUIRE(1 != 2);
+    REQUIRE(1 == 3);
+    // We should not get here, because the test above aborts
+    REQUIRE(1 != 4);
+}
diff --git a/projects/ExtraTests/X04-DisabledExceptions-CustomHandler.cpp b/projects/ExtraTests/X04-DisabledExceptions-CustomHandler.cpp
new file mode 100644
index 0000000..96f3ceb
--- /dev/null
+++ b/projects/ExtraTests/X04-DisabledExceptions-CustomHandler.cpp
@@ -0,0 +1,33 @@
+#define CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER
+
+#define CATCH_CONFIG_MAIN
+#include <catch2/catch.hpp>
+
+namespace Catch {
+    [[noreturn]]
+    void throw_exception(std::exception const& e) {
+        Catch::cerr() << "====== CUSTOM HANDLER ====== run terminates because an exception was thrown.\n"
+                      << "The message was: " << e.what() << '\n';
+        // Avoid abort and other exceptional exits -- there is no way
+        // to tell CMake that abort is the desired outcome of a test.
+        exit(1);
+    }
+}
+
+TEST_CASE("Tests that run") {
+    // All of these should be run and be reported
+    CHECK(1 == 2);
+    CHECK(1 == 1);
+    CHECK(1 != 3);
+    CHECK(1 == 4);
+}
+
+
+
+TEST_CASE("Tests that abort") {
+    REQUIRE(1 == 1);
+    REQUIRE(1 != 2);
+    REQUIRE(1 == 3);
+    // We should not get here, because the test above aborts
+    REQUIRE(1 != 4);
+}
diff --git a/projects/ExtraTests/X10-FallbackStringifier.cpp b/projects/ExtraTests/X10-FallbackStringifier.cpp
new file mode 100644
index 0000000..0522d1a
--- /dev/null
+++ b/projects/ExtraTests/X10-FallbackStringifier.cpp
@@ -0,0 +1,23 @@
+// X10-FallbackStringifier.cpp
+// Test that defining fallbackStringifier compiles
+
+#include <string>
+
+// A catch-all stringifier
+template <typename T>
+std::string fallbackStringifier(T const&) {
+    return "{ !!! }";
+}
+
+#define CATCH_CONFIG_MAIN
+#include <catch2/catch.hpp>
+
+struct foo {
+    explicit operator bool() const {
+        return true;
+    }
+};
+
+TEST_CASE("aa") {
+    REQUIRE(foo{});
+}
diff --git a/projects/ExtraTests/X11-DisableStringification.cpp b/projects/ExtraTests/X11-DisableStringification.cpp
new file mode 100644
index 0000000..7a93f6e
--- /dev/null
+++ b/projects/ExtraTests/X11-DisableStringification.cpp
@@ -0,0 +1,16 @@
+// X11-DisableStringification.cpp
+// Test that stringification of original expression can be disabled
+// this is a workaround for VS 2017 issue with Raw String literal
+// and preprocessor token pasting. In other words, hopefully this test
+// will be deleted soon :-)
+
+#define CATCH_CONFIG_MAIN
+#include <catch2/catch.hpp>
+
+struct Hidden {};
+
+bool operator==(Hidden, Hidden) { return true; }
+
+TEST_CASE("DisableStringification") {
+    REQUIRE( Hidden{} == Hidden{} );
+}
diff --git a/projects/SelfTest/Baselines/automake.std.approved.txt b/projects/SelfTest/Baselines/automake.std.approved.txt
index 85299f7..057be06 100644
--- a/projects/SelfTest/Baselines/automake.std.approved.txt
+++ b/projects/SelfTest/Baselines/automake.std.approved.txt
@@ -53,7 +53,7 @@
 :test-result: PASS Inequality checks that should succeed
 :test-result: PASS Less-than inequalities with different epsilons
 :test-result: PASS Long strings can be wrapped
-:test-result: PASS Long text is truncted
+:test-result: PASS Long text is truncated
 :test-result: PASS ManuallyRegistered
 :test-result: PASS Matchers can be (AllOf) composed with the && operator
 :test-result: PASS Matchers can be (AnyOf) composed with the || operator
diff --git a/projects/SelfTest/Baselines/compact.sw.approved.txt b/projects/SelfTest/Baselines/compact.sw.approved.txt
index 947ef42..2fcdd86 100644
--- a/projects/SelfTest/Baselines/compact.sw.approved.txt
+++ b/projects/SelfTest/Baselines/compact.sw.approved.txt
@@ -9,6 +9,15 @@
 Compilation.tests.cpp:<line number>: passed: t1 > t2 for: {?} > {?}
 Compilation.tests.cpp:<line number>: passed: t1 <= t2 for: {?} <= {?}
 Compilation.tests.cpp:<line number>: passed: t1 >= t2 for: {?} >= {?}
+Misc.tests.cpp:<line number>: passed:
+Compilation.tests.cpp:<line number>: passed: std::memcmp(uarr, "123", sizeof(uarr)) == 0 for: 0 == 0 with 2 messages: 'uarr := "123"' and 'sarr := "456"'
+Compilation.tests.cpp:<line number>: passed: std::memcmp(sarr, "456", sizeof(sarr)) == 0 for: 0 == 0 with 2 messages: 'uarr := "123"' and 'sarr := "456"'
+Compilation.tests.cpp:<line number>: passed:
+Compilation.tests.cpp:<line number>: passed: h1 == h2 for: [1403 helper] == [1403 helper]
+This would not be caught previously
+Nor would this
+Tricky.tests.cpp:<line number>: failed: explicitly with 1 message: '1514'
+Compilation.tests.cpp:<line number>: passed: std::is_same<TypeList<int>, TypeList<int>>::value for: true
 Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42' with 1 message: 'expected exception'
 Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'answer := 42'; expression was: thisThrows() with 1 message: 'expected exception'
 Exception.tests.cpp:<line number>: passed: thisThrows() with 1 message: 'answer := 42'
@@ -52,10 +61,115 @@
 Tricky.tests.cpp:<line number>: passed: !!is_true<true>::value for: true
 Tricky.tests.cpp:<line number>: passed: is_true<true>::value for: true
 Tricky.tests.cpp:<line number>: passed: !(is_true<false>::value) for: !false
+Generators.tests.cpp:<line number>: passed: x < y for: 1 < 4
+Generators.tests.cpp:<line number>: passed: y < z for: 4 < 7
+Generators.tests.cpp:<line number>: passed: x < z for: 1 < 7
+Generators.tests.cpp:<line number>: passed: x < y for: 1 < 4
+Generators.tests.cpp:<line number>: passed: y < z for: 4 < 8
+Generators.tests.cpp:<line number>: passed: x < z for: 1 < 8
+Generators.tests.cpp:<line number>: passed: x < y for: 1 < 4
+Generators.tests.cpp:<line number>: passed: y < z for: 4 < 9
+Generators.tests.cpp:<line number>: passed: x < z for: 1 < 9
+Generators.tests.cpp:<line number>: passed: x < y for: 1 < 5
+Generators.tests.cpp:<line number>: passed: y < z for: 5 < 7
+Generators.tests.cpp:<line number>: passed: x < z for: 1 < 7
+Generators.tests.cpp:<line number>: passed: x < y for: 1 < 5
+Generators.tests.cpp:<line number>: passed: y < z for: 5 < 8
+Generators.tests.cpp:<line number>: passed: x < z for: 1 < 8
+Generators.tests.cpp:<line number>: passed: x < y for: 1 < 5
+Generators.tests.cpp:<line number>: passed: y < z for: 5 < 9
+Generators.tests.cpp:<line number>: passed: x < z for: 1 < 9
+Generators.tests.cpp:<line number>: passed: x < y for: 1 < 6
+Generators.tests.cpp:<line number>: passed: y < z for: 6 < 7
+Generators.tests.cpp:<line number>: passed: x < z for: 1 < 7
+Generators.tests.cpp:<line number>: passed: x < y for: 1 < 6
+Generators.tests.cpp:<line number>: passed: y < z for: 6 < 8
+Generators.tests.cpp:<line number>: passed: x < z for: 1 < 8
+Generators.tests.cpp:<line number>: passed: x < y for: 1 < 6
+Generators.tests.cpp:<line number>: passed: y < z for: 6 < 9
+Generators.tests.cpp:<line number>: passed: x < z for: 1 < 9
+Generators.tests.cpp:<line number>: passed: x < y for: 2 < 4
+Generators.tests.cpp:<line number>: passed: y < z for: 4 < 7
+Generators.tests.cpp:<line number>: passed: x < z for: 2 < 7
+Generators.tests.cpp:<line number>: passed: x < y for: 2 < 4
+Generators.tests.cpp:<line number>: passed: y < z for: 4 < 8
+Generators.tests.cpp:<line number>: passed: x < z for: 2 < 8
+Generators.tests.cpp:<line number>: passed: x < y for: 2 < 4
+Generators.tests.cpp:<line number>: passed: y < z for: 4 < 9
+Generators.tests.cpp:<line number>: passed: x < z for: 2 < 9
+Generators.tests.cpp:<line number>: passed: x < y for: 2 < 5
+Generators.tests.cpp:<line number>: passed: y < z for: 5 < 7
+Generators.tests.cpp:<line number>: passed: x < z for: 2 < 7
+Generators.tests.cpp:<line number>: passed: x < y for: 2 < 5
+Generators.tests.cpp:<line number>: passed: y < z for: 5 < 8
+Generators.tests.cpp:<line number>: passed: x < z for: 2 < 8
+Generators.tests.cpp:<line number>: passed: x < y for: 2 < 5
+Generators.tests.cpp:<line number>: passed: y < z for: 5 < 9
+Generators.tests.cpp:<line number>: passed: x < z for: 2 < 9
+Generators.tests.cpp:<line number>: passed: x < y for: 2 < 6
+Generators.tests.cpp:<line number>: passed: y < z for: 6 < 7
+Generators.tests.cpp:<line number>: passed: x < z for: 2 < 7
+Generators.tests.cpp:<line number>: passed: x < y for: 2 < 6
+Generators.tests.cpp:<line number>: passed: y < z for: 6 < 8
+Generators.tests.cpp:<line number>: passed: x < z for: 2 < 8
+Generators.tests.cpp:<line number>: passed: x < y for: 2 < 6
+Generators.tests.cpp:<line number>: passed: y < z for: 6 < 9
+Generators.tests.cpp:<line number>: passed: x < z for: 2 < 9
+Generators.tests.cpp:<line number>: passed: x < y for: 3 < 4
+Generators.tests.cpp:<line number>: passed: y < z for: 4 < 7
+Generators.tests.cpp:<line number>: passed: x < z for: 3 < 7
+Generators.tests.cpp:<line number>: passed: x < y for: 3 < 4
+Generators.tests.cpp:<line number>: passed: y < z for: 4 < 8
+Generators.tests.cpp:<line number>: passed: x < z for: 3 < 8
+Generators.tests.cpp:<line number>: passed: x < y for: 3 < 4
+Generators.tests.cpp:<line number>: passed: y < z for: 4 < 9
+Generators.tests.cpp:<line number>: passed: x < z for: 3 < 9
+Generators.tests.cpp:<line number>: passed: x < y for: 3 < 5
+Generators.tests.cpp:<line number>: passed: y < z for: 5 < 7
+Generators.tests.cpp:<line number>: passed: x < z for: 3 < 7
+Generators.tests.cpp:<line number>: passed: x < y for: 3 < 5
+Generators.tests.cpp:<line number>: passed: y < z for: 5 < 8
+Generators.tests.cpp:<line number>: passed: x < z for: 3 < 8
+Generators.tests.cpp:<line number>: passed: x < y for: 3 < 5
+Generators.tests.cpp:<line number>: passed: y < z for: 5 < 9
+Generators.tests.cpp:<line number>: passed: x < z for: 3 < 9
+Generators.tests.cpp:<line number>: passed: x < y for: 3 < 6
+Generators.tests.cpp:<line number>: passed: y < z for: 6 < 7
+Generators.tests.cpp:<line number>: passed: x < z for: 3 < 7
+Generators.tests.cpp:<line number>: passed: x < y for: 3 < 6
+Generators.tests.cpp:<line number>: passed: y < z for: 6 < 8
+Generators.tests.cpp:<line number>: passed: x < z for: 3 < 8
+Generators.tests.cpp:<line number>: passed: x < y for: 3 < 6
+Generators.tests.cpp:<line number>: passed: y < z for: 6 < 9
+Generators.tests.cpp:<line number>: passed: x < z for: 3 < 9
 Class.tests.cpp:<line number>: failed: s == "world" for: "hello" == "world"
 Class.tests.cpp:<line number>: passed: s == "hello" for: "hello" == "hello"
+Class.tests.cpp:<line number>: failed: Template_Fixture_2<TestType>::m_a.size() == 1 for: 0 == 1
+Class.tests.cpp:<line number>: failed: Template_Fixture_2<TestType>::m_a.size() == 1 for: 0 == 1
+Class.tests.cpp:<line number>: failed: Template_Fixture_2<TestType>::m_a.size() == 1 for: 0 == 1
+Class.tests.cpp:<line number>: failed: Template_Fixture_2<TestType>::m_a.size() == 1 for: 0 == 1
+Class.tests.cpp:<line number>: passed: Template_Fixture_2<TestType>::m_a.size() == 0 for: 0 == 0
+Class.tests.cpp:<line number>: passed: Template_Fixture_2<TestType>::m_a.size() == 0 for: 0 == 0
+Class.tests.cpp:<line number>: passed: Template_Fixture_2<TestType>::m_a.size() == 0 for: 0 == 0
+Class.tests.cpp:<line number>: passed: Template_Fixture_2<TestType>::m_a.size() == 0 for: 0 == 0
+Class.tests.cpp:<line number>: failed: Template_Fixture<TestType>::m_a == 2 for: 1.0 == 2
+Class.tests.cpp:<line number>: failed: Template_Fixture<TestType>::m_a == 2 for: 1.0f == 2
+Class.tests.cpp:<line number>: failed: Template_Fixture<TestType>::m_a == 2 for: 1 == 2
+Class.tests.cpp:<line number>: passed: Template_Fixture<TestType>::m_a == 1 for: 1.0 == 1
+Class.tests.cpp:<line number>: passed: Template_Fixture<TestType>::m_a == 1 for: 1.0f == 1
+Class.tests.cpp:<line number>: passed: Template_Fixture<TestType>::m_a == 1 for: 1 == 1
 Class.tests.cpp:<line number>: failed: m_a == 2 for: 1 == 2
 Class.tests.cpp:<line number>: passed: m_a == 1 for: 1 == 1
+Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0
+Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0
+Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0
+Misc.tests.cpp:<line number>: passed: x.size() == 0 for: 0 == 0
+Approx.tests.cpp:<line number>: passed: d == 1.23_a for: 1.23 == Approx( 1.23 )
+Approx.tests.cpp:<line number>: passed: d != 1.22_a for: 1.23 != Approx( 1.22 )
+Approx.tests.cpp:<line number>: passed: -d == -1.23_a for: -1.23 == Approx( -1.23 )
+Approx.tests.cpp:<line number>: passed: d == 1.2_a .epsilon(.1) for: 1.23 == Approx( 1.2 )
+Approx.tests.cpp:<line number>: passed: d != 1.2_a .epsilon(.001) for: 1.23 != Approx( 1.2 )
+Approx.tests.cpp:<line number>: passed: d == 1_a .epsilon(.3) for: 1.23 == Approx( 1.0 )
 Misc.tests.cpp:<line number>: passed: with 1 message: 'that's not flying - that's failing in style'
 Misc.tests.cpp:<line number>: failed: explicitly with 1 message: 'to infinity and beyond'
 Tricky.tests.cpp:<line number>: failed: &o1 == &o2 for: 0x<hex digits> == 0x<hex digits>
@@ -96,6 +210,10 @@
 Approx.tests.cpp:<line number>: passed: 0 == Approx( dSmall ).margin( 0.001 ) for: 0 == Approx( 0.00001 )
 Approx.tests.cpp:<line number>: passed: 1.234f == Approx( dMedium ) for: 1.234f == Approx( 1.234 )
 Approx.tests.cpp:<line number>: passed: dMedium == Approx( 1.234f ) for: 1.234 == Approx( 1.2339999676 )
+Matchers.tests.cpp:<line number>: passed: 1, Predicate<int>(alwaysTrue, "always true") for: 1 matches predicate: "always true"
+Matchers.tests.cpp:<line number>: passed: 1, !Predicate<int>(alwaysFalse, "always false") for: 1 not matches predicate: "always false"
+Matchers.tests.cpp:<line number>: passed: "Hello olleH", Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); }, "First and last character should be equal") for: "Hello olleH" matches predicate: "First and last character should be equal"
+Matchers.tests.cpp:<line number>: passed: "This wouldn't pass", !Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); } ) for: "This wouldn't pass" not matches undescribed predicate
 Tricky.tests.cpp:<line number>: passed: true
 Tricky.tests.cpp:<line number>: passed: true
 Tricky.tests.cpp:<line number>: passed: true
@@ -107,18 +225,20 @@
 Approx.tests.cpp:<line number>: passed: !(NAN == Approx(NAN)) for: !(nanf == Approx( nan ))
 Tricky.tests.cpp:<line number>: passed: y.v == 0 for: 0 == 0
 Tricky.tests.cpp:<line number>: passed: 0 == y.v for: 0 == 0
+Message.tests.cpp:<line number>: passed: with 7 messages: 'a := 1' and 'b := 2' and 'c := 3' and 'a + b := 3' and 'a+b := 3' and 'c > b := true' and 'a == 1 := true'
+Message.tests.cpp:<line number>: passed: with 7 messages: 'std::vector<int>{1, 2, 3}[0, 1, 2] := 3' and 'std::vector<int>{1, 2, 3}[(0, 1)] := 2' and 'std::vector<int>{1, 2, 3}[0] := 1' and '(helper_1436<int, int>{12, -12}) := { 12, -12 }' and '(helper_1436<int, int>(-12, 12)) := { -12, 12 }' and '(1, 2) := 2' and '(2, 3) := 3'
 ToStringGeneral.tests.cpp:<line number>: passed: true with 1 message: 'i := 2'
 ToStringGeneral.tests.cpp:<line number>: passed: true with 1 message: '3'
-ToStringGeneral.tests.cpp:<line number>: passed: tab == '/t' for: '/t' == '/t'
-ToStringGeneral.tests.cpp:<line number>: passed: newline == '/n' for: '/n' == '/n'
-ToStringGeneral.tests.cpp:<line number>: passed: carr_return == '/r' for: '/r' == '/r'
-ToStringGeneral.tests.cpp:<line number>: passed: form_feed == '/f' for: '/f' == '/f'
+ToStringGeneral.tests.cpp:<line number>: passed: tab == '\t' for: '\t' == '\t'
+ToStringGeneral.tests.cpp:<line number>: passed: newline == '\n' for: '\n' == '\n'
+ToStringGeneral.tests.cpp:<line number>: passed: carr_return == '\r' for: '\r' == '\r'
+ToStringGeneral.tests.cpp:<line number>: passed: form_feed == '\f' for: '\f' == '\f'
 ToStringGeneral.tests.cpp:<line number>: passed: space == ' ' for: ' ' == ' '
 ToStringGeneral.tests.cpp:<line number>: passed: c == chars[i] for: 'a' == 'a'
 ToStringGeneral.tests.cpp:<line number>: passed: c == chars[i] for: 'z' == 'z'
 ToStringGeneral.tests.cpp:<line number>: passed: c == chars[i] for: 'A' == 'A'
 ToStringGeneral.tests.cpp:<line number>: passed: c == chars[i] for: 'Z' == 'Z'
-ToStringGeneral.tests.cpp:<line number>: passed: null_terminator == '/0' for: 0 == 0
+ToStringGeneral.tests.cpp:<line number>: passed: null_terminator == '\0' for: 0 == 0
 ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 2 == 2
 ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 3 == 3
 ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 4 == 4
@@ -203,14 +323,21 @@
 Matchers.tests.cpp:<line number>: passed: testStringForMatching(), Equals("this string contains 'ABC' as a substring", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" equals: "this string contains 'abc' as a substring" (case insensitive)
 Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Equals("this string contains 'ABC' as a substring") for: "this string contains 'abc' as a substring" equals: "this string contains 'ABC' as a substring"
 Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Equals("something else", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" equals: "something else" (case insensitive)
+ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(WhatException{}) == "This exception has overriden what() method" for: "This exception has overriden what() method"
+==
+"This exception has overriden what() method"
+ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(OperatorException{}) == "OperatorException" for: "OperatorException" == "OperatorException"
+ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(StringMakerException{}) == "StringMakerException" for: "StringMakerException"
+==
+"StringMakerException"
 Matchers.tests.cpp:<line number>: failed: expected exception, got none; expression was: doesNotThrow(), SpecialException, ExceptionMatcher{1}
 Matchers.tests.cpp:<line number>: failed: expected exception, got none; expression was: doesNotThrow(), SpecialException, ExceptionMatcher{1}
 Matchers.tests.cpp:<line number>: failed: unexpected exception with message: 'Unknown exception'; expression was: throwsAsInt(1), SpecialException, ExceptionMatcher{1}
 Matchers.tests.cpp:<line number>: failed: unexpected exception with message: 'Unknown exception'; expression was: throwsAsInt(1), SpecialException, ExceptionMatcher{1}
-Matchers.tests.cpp:<line number>: failed: throws(3), SpecialException, ExceptionMatcher{1} for: {?} special exception has value of 1
-Matchers.tests.cpp:<line number>: failed: throws(4), SpecialException, ExceptionMatcher{1} for: {?} special exception has value of 1
-Matchers.tests.cpp:<line number>: passed: throws(1), SpecialException, ExceptionMatcher{1} for: {?} special exception has value of 1
-Matchers.tests.cpp:<line number>: passed: throws(2), SpecialException, ExceptionMatcher{2} for: {?} special exception has value of 2
+Matchers.tests.cpp:<line number>: failed: throws(3), SpecialException, ExceptionMatcher{1} for: SpecialException::what special exception has value of 1
+Matchers.tests.cpp:<line number>: failed: throws(4), SpecialException, ExceptionMatcher{1} for: SpecialException::what special exception has value of 1
+Matchers.tests.cpp:<line number>: passed: throws(1), SpecialException, ExceptionMatcher{1} for: SpecialException::what special exception has value of 1
+Matchers.tests.cpp:<line number>: passed: throws(2), SpecialException, ExceptionMatcher{2} for: SpecialException::what special exception has value of 2
 Exception.tests.cpp:<line number>: passed: thisThrows(), "expected exception" for: "expected exception" equals: "expected exception"
 Exception.tests.cpp:<line number>: passed: thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) for: "expected exception" equals: "expected exception" (case insensitive)
 Exception.tests.cpp:<line number>: passed: thisThrows(), StartsWith( "expected" ) for: "expected exception" starts with: "expected"
@@ -234,10 +361,14 @@
 Matchers.tests.cpp:<line number>: passed: 0., !WithinAbs(1., 0.99) for: 0.0 not is within 0.99 of 1.0
 Matchers.tests.cpp:<line number>: passed: 0., !WithinAbs(1., 0.99) for: 0.0 not is within 0.99 of 1.0
 Matchers.tests.cpp:<line number>: passed: NAN, !WithinAbs(NAN, 0) for: nanf not is within 0.0 of nan
+Matchers.tests.cpp:<line number>: passed: 11., !WithinAbs(10., 0.5) for: 11.0 not is within 0.5 of 10.0
+Matchers.tests.cpp:<line number>: passed: 10., !WithinAbs(11., 0.5) for: 10.0 not is within 0.5 of 11.0
+Matchers.tests.cpp:<line number>: passed: -10., WithinAbs(-10., 0.5) for: -10.0 is within 0.5 of -10.0
+Matchers.tests.cpp:<line number>: passed: -10., WithinAbs(-9.6, 0.5) for: -10.0 is within 0.5 of -9.6
 Matchers.tests.cpp:<line number>: passed: 1., WithinULP(1., 0) for: 1.0 is within 0 ULPs of 1.0
-Matchers.tests.cpp:<line number>: passed: std::nextafter(1., 2.), WithinULP(1., 1) for: 1.0 is within 1 ULPs of 1.0
-Matchers.tests.cpp:<line number>: passed: std::nextafter(1., 0.), WithinULP(1., 1) for: 1.0 is within 1 ULPs of 1.0
-Matchers.tests.cpp:<line number>: passed: std::nextafter(1., 2.), !WithinULP(1., 0) for: 1.0 not is within 0 ULPs of 1.0
+Matchers.tests.cpp:<line number>: passed: nextafter(1., 2.), WithinULP(1., 1) for: 1.0 is within 1 ULPs of 1.0
+Matchers.tests.cpp:<line number>: passed: nextafter(1., 0.), WithinULP(1., 1) for: 1.0 is within 1 ULPs of 1.0
+Matchers.tests.cpp:<line number>: passed: nextafter(1., 2.), !WithinULP(1., 0) for: 1.0 not is within 0 ULPs of 1.0
 Matchers.tests.cpp:<line number>: passed: 1., WithinULP(1., 0) for: 1.0 is within 0 ULPs of 1.0
 Matchers.tests.cpp:<line number>: passed: -0., WithinULP(0., 0) for: -0.0 is within 0 ULPs of 0.0
 Matchers.tests.cpp:<line number>: passed: NAN, !WithinULP(NAN, 123) for: nanf not is within 123 ULPs of nanf
@@ -254,10 +385,14 @@
 Matchers.tests.cpp:<line number>: passed: 0.f, !WithinAbs(1.f, 0.99f) for: 0.0f not is within 0.9900000095 of 1.0
 Matchers.tests.cpp:<line number>: passed: 0.f, WithinAbs(-0.f, 0) for: 0.0f is within 0.0 of -0.0
 Matchers.tests.cpp:<line number>: passed: NAN, !WithinAbs(NAN, 0) for: nanf not is within 0.0 of nan
+Matchers.tests.cpp:<line number>: passed: 11.f, !WithinAbs(10.f, 0.5f) for: 11.0f not is within 0.5 of 10.0
+Matchers.tests.cpp:<line number>: passed: 10.f, !WithinAbs(11.f, 0.5f) for: 10.0f not is within 0.5 of 11.0
+Matchers.tests.cpp:<line number>: passed: -10.f, WithinAbs(-10.f, 0.5f) for: -10.0f is within 0.5 of -10.0
+Matchers.tests.cpp:<line number>: passed: -10.f, WithinAbs(-9.6f, 0.5f) for: -10.0f is within 0.5 of -9.6000003815
 Matchers.tests.cpp:<line number>: passed: 1.f, WithinULP(1.f, 0) for: 1.0f is within 0 ULPs of 1.0f
-Matchers.tests.cpp:<line number>: passed: std::nextafter(1.f, 2.f), WithinULP(1.f, 1) for: 1.0f is within 1 ULPs of 1.0f
-Matchers.tests.cpp:<line number>: passed: std::nextafter(1.f, 0.f), WithinULP(1.f, 1) for: 1.0f is within 1 ULPs of 1.0f
-Matchers.tests.cpp:<line number>: passed: std::nextafter(1.f, 2.f), !WithinULP(1.f, 0) for: 1.0f not is within 0 ULPs of 1.0f
+Matchers.tests.cpp:<line number>: passed: nextafter(1.f, 2.f), WithinULP(1.f, 1) for: 1.0f is within 1 ULPs of 1.0f
+Matchers.tests.cpp:<line number>: passed: nextafter(1.f, 0.f), WithinULP(1.f, 1) for: 1.0f is within 1 ULPs of 1.0f
+Matchers.tests.cpp:<line number>: passed: nextafter(1.f, 2.f), !WithinULP(1.f, 0) for: 1.0f not is within 0 ULPs of 1.0f
 Matchers.tests.cpp:<line number>: passed: 1.f, WithinULP(1.f, 0) for: 1.0f is within 0 ULPs of 1.0f
 Matchers.tests.cpp:<line number>: passed: -0.f, WithinULP(0.f, 0) for: -0.0f is within 0 ULPs of 0.0f
 Matchers.tests.cpp:<line number>: passed: NAN, !WithinULP(NAN, 123) for: nanf not is within 123 ULPs of nanf
@@ -268,6 +403,180 @@
 Matchers.tests.cpp:<line number>: passed: WithinAbs(1.f, -1.f), std::domain_error
 Matchers.tests.cpp:<line number>: passed: WithinULP(1.f, 0)
 Matchers.tests.cpp:<line number>: passed: WithinULP(1.f, -1), std::domain_error
+Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
+Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
+Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
+Generators.tests.cpp:<line number>: passed: filter([] (int) {return false; }, value(1)), Catch::GeneratorException
+Generators.tests.cpp:<line number>: passed: i < 4 for: 1 < 4
+Generators.tests.cpp:<line number>: passed: i < 4 for: 2 < 4
+Generators.tests.cpp:<line number>: passed: i < 4 for: 3 < 4
+Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
+Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
+Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
+Generators.tests.cpp:<line number>: passed: i.size() == 1 for: 1 == 1
+Generators.tests.cpp:<line number>: passed: i.size() == 1 for: 1 == 1
+Generators.tests.cpp:<line number>: passed: i.size() == 1 for: 1 == 1
+Generators.tests.cpp:<line number>: passed: j > 0 for: 1 > 0
+Generators.tests.cpp:<line number>: passed: j > 0 for: 2 > 0
+Generators.tests.cpp:<line number>: passed: j > 0 for: 3 > 0
+Generators.tests.cpp:<line number>: passed: j > 0 for: 1 > 0
+Generators.tests.cpp:<line number>: passed: j > 0 for: 2 > 0
+Generators.tests.cpp:<line number>: passed: j > 0 for: 3 > 0
+Generators.tests.cpp:<line number>: passed: chunk2.size() == 2 for: 2 == 2
+Generators.tests.cpp:<line number>: passed: chunk2.front() == chunk2.back() for: 1 == 1
+Generators.tests.cpp:<line number>: passed: chunk2.size() == 2 for: 2 == 2
+Generators.tests.cpp:<line number>: passed: chunk2.front() == chunk2.back() for: 2 == 2
+Generators.tests.cpp:<line number>: passed: chunk2.size() == 2 for: 2 == 2
+Generators.tests.cpp:<line number>: passed: chunk2.front() == chunk2.back() for: 3 == 3
+Generators.tests.cpp:<line number>: passed: chunk2.size() == 2 for: 2 == 2
+Generators.tests.cpp:<line number>: passed: chunk2.front() == chunk2.back() for: 1 == 1
+Generators.tests.cpp:<line number>: passed: chunk2.front() < 3 for: 1 < 3
+Generators.tests.cpp:<line number>: passed: chunk2.size() == 2 for: 2 == 2
+Generators.tests.cpp:<line number>: passed: chunk2.front() == chunk2.back() for: 2 == 2
+Generators.tests.cpp:<line number>: passed: chunk2.front() < 3 for: 2 < 3
+Generators.tests.cpp:<line number>: passed: chunk(2, value(1)), Catch::GeneratorException
+Generators.tests.cpp:<line number>: passed: j < i for: -3 < 1
+Generators.tests.cpp:<line number>: passed: j < i for: -2 < 1
+Generators.tests.cpp:<line number>: passed: j < i for: -1 < 1
+Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 4 > 1
+Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 4 > 2
+Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 4 > 3
+Generators.tests.cpp:<line number>: passed: j < i for: -3 < 2
+Generators.tests.cpp:<line number>: passed: j < i for: -2 < 2
+Generators.tests.cpp:<line number>: passed: j < i for: -1 < 2
+Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 8 > 1
+Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 8 > 2
+Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 8 > 3
+Generators.tests.cpp:<line number>: passed: j < i for: -3 < 3
+Generators.tests.cpp:<line number>: passed: j < i for: -2 < 3
+Generators.tests.cpp:<line number>: passed: j < i for: -1 < 3
+Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 12 > 1
+Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 12 > 2
+Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 12 > 3
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 123 for: 123 == 123
+GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 5 for: 5 == 5
+GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 5 for: 5 == 5
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 4 for: 4 == 4
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 0 for: 0 == 0
+GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get().size() == 2 for: 2 == 2
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == "aa" for: "aa" == "aa"
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == "bb" for: "bb" == "bb"
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == "cc" for: "cc" == "cc"
+GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
+GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
+GeneratorsImpl.tests.cpp:<line number>: passed: filter([] (int) { return false; }, value(1)), Catch::GeneratorException
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
+GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
+GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2.0 for: 2.0 == 2.0
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 4.0 for: 4.0 == 4.0
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 6.0 for: 6.0 == 6.0
+GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
+GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
+GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -2 for: -2 == -2
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -1 for: -1 == -1
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 0 for: 0 == 0
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
+GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 0 for: 0 == 0
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -1 for: -1 == -1
+GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -7 for: -7 == -7
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -4 for: -4 == -4
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -1 for: -1 == -1
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
+GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -7 for: -7 == -7
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -4 for: -4 == -4
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -1 for: -1 == -1
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
+GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -7 for: -7 == -7
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -4 for: -4 == -4
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -1 for: -1 == -1
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 5 for: 5 == 5
+GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 5 for: 5 == 5
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -1 for: -1 == -1
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -4 for: -4 == -4
+GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 5 for: 5 == 5
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -1 for: -1 == -1
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -4 for: -4 == -4
+GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 5 for: 5 == 5
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2 for: 2 == 2
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -1 for: -1 == -1
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -4 for: -4 == -4
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
+GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == -7 for: -7 == -7
+GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
 Approx.tests.cpp:<line number>: passed: d >= Approx( 1.22 ) for: 1.23 >= Approx( 1.22 )
 Approx.tests.cpp:<line number>: passed: d >= Approx( 1.23 ) for: 1.23 >= Approx( 1.23 )
 Approx.tests.cpp:<line number>: passed: !(d >= Approx( 1.24 )) for: !(1.23 >= Approx( 1.24 ))
@@ -324,6 +633,8 @@
 Tricky.tests.cpp:<line number>: passed: True for: {?}
 Tricky.tests.cpp:<line number>: passed: !False for: true
 Tricky.tests.cpp:<line number>: passed: !(False) for: !{?}
+Compilation.tests.cpp:<line number>: passed: with 1 message: 'std::is_void<void>::value'
+Compilation.tests.cpp:<line number>: passed: with 1 message: '!(std::is_void<int>::value)'
 Condition.tests.cpp:<line number>: failed: data.int_seven > 7 for: 7 > 7
 Condition.tests.cpp:<line number>: failed: data.int_seven < 7 for: 7 < 7
 Condition.tests.cpp:<line number>: failed: data.int_seven > 8 for: 7 > 8
@@ -497,7 +808,6 @@
 CmdLine.tests.cpp:<line number>: passed: spec.matches( tcB ) == false for: false == false
 CmdLine.tests.cpp:<line number>: passed: spec.matches( tcC ) == false for: false == false
 CmdLine.tests.cpp:<line number>: passed: spec.matches( tcD ) == true for: true == true
-Tricky.tests.cpp:<line number>: passed: (std::pair<int, int>( 1, 2 )) == aNicePair for: {?} == {?}
 Condition.tests.cpp:<line number>: passed: p == 0 for: 0 == 0
 Condition.tests.cpp:<line number>: passed: p == pNULL for: 0 == 0
 Condition.tests.cpp:<line number>: passed: p != 0 for: 0x<hex digits> != 0
@@ -506,6 +816,7 @@
 Condition.tests.cpp:<line number>: passed: returnsNull() == 0 for: {null string} == 0
 Condition.tests.cpp:<line number>: passed: returnsConstNull() == 0 for: {null string} == 0
 Condition.tests.cpp:<line number>: passed: 0 != p for: 0 != 0x<hex digits>
+Matchers.tests.cpp:<line number>: passed: "foo", Predicate<const char*>([] (const char* const&) { return true; }) for: "foo" matches undescribed predicate
 CmdLine.tests.cpp:<line number>: passed: result for: {?}
 CmdLine.tests.cpp:<line number>: passed: config.processName == "" for: "" == ""
 CmdLine.tests.cpp:<line number>: passed: result for: {?}
@@ -513,26 +824,29 @@
 CmdLine.tests.cpp:<line number>: passed: config.shouldDebugBreak == false for: false == false
 CmdLine.tests.cpp:<line number>: passed: config.abortAfter == -1 for: -1 == -1
 CmdLine.tests.cpp:<line number>: passed: config.noThrow == false for: false == false
-CmdLine.tests.cpp:<line number>: passed: config.reporterNames.empty() for: true
+CmdLine.tests.cpp:<line number>: passed: config.reporterName == "console" for: "console" == "console"
+CmdLine.tests.cpp:<line number>: passed: !(cfg.hasTestFilters()) for: !false
 CmdLine.tests.cpp:<line number>: passed: result for: {?}
+CmdLine.tests.cpp:<line number>: passed: cfg.hasTestFilters() for: true
 CmdLine.tests.cpp:<line number>: passed: cfg.testSpec().matches(fakeTestCase("notIncluded")) == false for: false == false
 CmdLine.tests.cpp:<line number>: passed: cfg.testSpec().matches(fakeTestCase("test1")) for: true
 CmdLine.tests.cpp:<line number>: passed: result for: {?}
+CmdLine.tests.cpp:<line number>: passed: cfg.hasTestFilters() for: true
 CmdLine.tests.cpp:<line number>: passed: cfg.testSpec().matches(fakeTestCase("test1")) == false for: false == false
 CmdLine.tests.cpp:<line number>: passed: cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) for: true
 CmdLine.tests.cpp:<line number>: passed: result for: {?}
+CmdLine.tests.cpp:<line number>: passed: cfg.hasTestFilters() for: true
 CmdLine.tests.cpp:<line number>: passed: cfg.testSpec().matches(fakeTestCase("test1")) == false for: false == false
 CmdLine.tests.cpp:<line number>: passed: cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) for: true
 CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "-r", "console"}) for: {?}
-CmdLine.tests.cpp:<line number>: passed: config.reporterNames[0] == "console" for: "console" == "console"
+CmdLine.tests.cpp:<line number>: passed: config.reporterName == "console" for: "console" == "console"
 CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "-r", "xml"}) for: {?}
-CmdLine.tests.cpp:<line number>: passed: config.reporterNames[0] == "xml" for: "xml" == "xml"
-CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "-r", "xml", "-r", "junit"}) for: {?}
-CmdLine.tests.cpp:<line number>: passed: config.reporterNames.size() == 2 for: 2 == 2
-CmdLine.tests.cpp:<line number>: passed: config.reporterNames[0] == "xml" for: "xml" == "xml"
-CmdLine.tests.cpp:<line number>: passed: config.reporterNames[1] == "junit" for: "junit" == "junit"
+CmdLine.tests.cpp:<line number>: passed: config.reporterName == "xml" for: "xml" == "xml"
 CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--reporter", "junit"}) for: {?}
-CmdLine.tests.cpp:<line number>: passed: config.reporterNames[0] == "junit" for: "junit" == "junit"
+CmdLine.tests.cpp:<line number>: passed: config.reporterName == "junit" for: "junit" == "junit"
+CmdLine.tests.cpp:<line number>: passed: !(cli.parse({ "test", "-r", "xml", "-r", "junit" })) for: !{?}
+CmdLine.tests.cpp:<line number>: passed: !result for: true
+CmdLine.tests.cpp:<line number>: passed: result.errorMessage(), Contains("Unrecognized reporter") for: "Unrecognized reporter, 'unsupported'. Check available with --list-reporters" contains: "Unrecognized reporter"
 CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "-b"}) for: {?}
 CmdLine.tests.cpp:<line number>: passed: config.shouldDebugBreak == true for: true == true
 CmdLine.tests.cpp:<line number>: passed: cli.parse({"test", "--break"}) for: {?}
@@ -565,10 +879,14 @@
 CmdLine.tests.cpp:<line number>: passed: config.useColour == UseColour::No for: 2 == 2
 CmdLine.tests.cpp:<line number>: passed: !result for: true
 CmdLine.tests.cpp:<line number>: passed: result.errorMessage(), Contains( "colour mode must be one of" ) for: "colour mode must be one of: auto, yes or no. 'wrong' not recognised" contains: "colour mode must be one of"
+Misc.tests.cpp:<line number>: passed: std::tuple_size<TestType>::value >= 1 for: 3 >= 1
+Misc.tests.cpp:<line number>: passed: std::tuple_size<TestType>::value >= 1 for: 2 >= 1
+Misc.tests.cpp:<line number>: passed: std::tuple_size<TestType>::value >= 1 for: 1 >= 1
 Decomposition.tests.cpp:<line number>: failed: truthy(false) for: Hey, its truthy!
 Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("this STRING contains 'abc' as a substring") for: "this string contains 'abc' as a substring" matches "this STRING contains 'abc' as a substring" case sensitively
 Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("contains 'abc' as a substring") for: "this string contains 'abc' as a substring" matches "contains 'abc' as a substring" case sensitively
 Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Matches("this string contains 'abc' as a") for: "this string contains 'abc' as a substring" matches "this string contains 'abc' as a" case sensitively
+Matchers.tests.cpp:<line number>: passed: actual, !UnorderedEquals(expected) for: { 'a', 'b' } not UnorderedEquals: { 'c', 'b' }
 Message.tests.cpp:<line number>: passed: with 1 message: 'this is a success'
 Message.tests.cpp:<line number>: passed:
 BDD.tests.cpp:<line number>: passed: before == 0 for: 0 == 0
@@ -590,6 +908,8 @@
 Approx.tests.cpp:<line number>: passed: d == Approx( 1.23 ) for: 1.23 == Approx( 1.23 )
 Approx.tests.cpp:<line number>: passed: d != Approx( 1.22 ) for: 1.23 != Approx( 1.22 )
 Approx.tests.cpp:<line number>: passed: d != Approx( 1.24 ) for: 1.23 != Approx( 1.24 )
+Approx.tests.cpp:<line number>: passed: d == 1.23_a for: 1.23 == Approx( 1.23 )
+Approx.tests.cpp:<line number>: passed: d != 1.22_a for: 1.23 != Approx( 1.22 )
 Approx.tests.cpp:<line number>: passed: Approx( d ) == 1.23 for: Approx( 1.23 ) == 1.23
 Approx.tests.cpp:<line number>: passed: Approx( d ) != 1.22 for: Approx( 1.23 ) != 1.22
 Approx.tests.cpp:<line number>: passed: Approx( d ) != 1.24 for: Approx( 1.23 ) != 1.24
@@ -622,18 +942,21 @@
 String.tests.cpp:<line number>: passed: s.c_str() == rawChars for: "hello" == "hello"
 String.tests.cpp:<line number>: passed: isOwned( s ) == false for: false == false
 String.tests.cpp:<line number>: passed: original == "original"
-String.tests.cpp:<line number>: failed: isSubstring( original ) for: false
+String.tests.cpp:<line number>: passed: isSubstring( original ) for: true
+String.tests.cpp:<line number>: passed: isOwned( original ) == false for: false == false
+String.tests.cpp:<line number>: passed: isSubstring( original ) == false for: false == false
+String.tests.cpp:<line number>: passed: isOwned( original ) for: true
 String.tests.cpp:<line number>: passed: ss.empty() == false for: false == false
 String.tests.cpp:<line number>: passed: ss.size() == 5 for: 5 == 5
 String.tests.cpp:<line number>: passed: std::strcmp( ss.c_str(), "hello" ) == 0 for: 0 == 0
 String.tests.cpp:<line number>: passed: ss == "hello" for: hello == "hello"
 String.tests.cpp:<line number>: passed: isSubstring( ss ) for: true
 String.tests.cpp:<line number>: passed: isOwned( ss ) == false for: false == false
-String.tests.cpp:<line number>: passed: rawChars == data( s ) for: "hello world!" == "hello world!"
+String.tests.cpp:<line number>: passed: rawChars == s.currentData() for: "hello world!" == "hello world!"
 String.tests.cpp:<line number>: passed: ss.c_str() != rawChars for: "hello" != "hello world!"
 String.tests.cpp:<line number>: passed: isSubstring( ss ) == false for: false == false
 String.tests.cpp:<line number>: passed: isOwned( ss ) for: true
-String.tests.cpp:<line number>: passed: data( ss ) != data( s ) for: "hello" != "hello world!"
+String.tests.cpp:<line number>: passed: ss.currentData() != s.currentData() for: "hello" != "hello world!"
 String.tests.cpp:<line number>: passed: ss.size() == 6 for: 6 == 6
 String.tests.cpp:<line number>: passed: std::strcmp( ss.c_str(), "world!" ) == 0 for: 0 == 0
 String.tests.cpp:<line number>: passed: s.c_str() == s2.c_str() for: "hello world!" == "hello world!"
@@ -652,6 +975,9 @@
 String.tests.cpp:<line number>: passed: stdStr.size() == sr.size() for: 11 == 11
 String.tests.cpp:<line number>: passed: stdStr == "a stringref" for: "a stringref" == "a stringref"
 String.tests.cpp:<line number>: passed: stdStr.size() == sr.size() for: 11 == 11
+String.tests.cpp:<line number>: passed: ascii.numberOfCharacters() == ascii.size() for: 39 == 39
+String.tests.cpp:<line number>: passed: simpleu8.numberOfCharacters() == 30 for: 30 == 30
+String.tests.cpp:<line number>: passed: emojis.numberOfCharacters() == 9 for: 9 == 9
 ToStringChrono.tests.cpp:<line number>: passed: minute == seconds for: 1 m == 60 s
 ToStringChrono.tests.cpp:<line number>: passed: hour != seconds for: 1 h != 60 s
 ToStringChrono.tests.cpp:<line number>: passed: micro != milli for: 1 us != 1 ms
@@ -685,10 +1011,79 @@
 TagAlias.tests.cpp:<line number>: passed: registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) )
 TagAlias.tests.cpp:<line number>: passed: registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) )
 TagAlias.tests.cpp:<line number>: passed: registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) )
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.size() == 10 for: 10 == 10
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 10 for: 10 >= 10
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.size() == 0 for: 0 == 0
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.capacity() == 0 for: 0 == 0
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 10 for: 10 >= 10
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.size() == 10 for: 10 == 10
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 10 for: 10 >= 10
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.size() == 0 for: 0 == 0
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.capacity() == 0 for: 0 == 0
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 10 for: 10 >= 10
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.size() == 10 for: 10 == 10
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 10 for: 10 >= 10
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.size() == 0 for: 0 == 0
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.capacity() == 0 for: 0 == 0
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 10 for: 10 >= 10
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.size() == 10 for: 10 == 10
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 10 for: 10 >= 10
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.size() == 0 for: 0 == 0
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.capacity() == 0 for: 0 == 0
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 10 for: 10 >= 10
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
+Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
+Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
 VariadicMacros.tests.cpp:<line number>: passed: with 1 message: 'no assertions'
 Tricky.tests.cpp:<line number>: passed: 0x<hex digits> == bit30and31 for: 3221225472 (0x<hex digits>) == 3221225472
 Message.tests.cpp:<line number>: failed - but was ok: 1 == 2
 Misc.tests.cpp:<line number>: passed: with 1 message: 'oops!'
+Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'For some reason someone is throwing a string literal!'
 PartTracker.tests.cpp:<line number>: passed: testCase.isOpen() for: true
 PartTracker.tests.cpp:<line number>: passed: s1.isOpen() for: true
 PartTracker.tests.cpp:<line number>: passed: s1.isSuccessfullyCompleted() for: true
@@ -756,69 +1151,6 @@
 PartTracker.tests.cpp:<line number>: passed: s1.isComplete() for: true
 PartTracker.tests.cpp:<line number>: passed: testCase.isComplete() == false for: false == false
 PartTracker.tests.cpp:<line number>: passed: testCase.isComplete() for: true
-PartTracker.tests.cpp:<line number>: passed: testCase.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: s1.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: g1.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: g1.index() == 0 for: 0 == 0
-PartTracker.tests.cpp:<line number>: passed: g1.isComplete() == false for: false == false
-PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false == false
-PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false == false
-PartTracker.tests.cpp:<line number>: passed: testCase.isSuccessfullyCompleted() == false for: false == false
-PartTracker.tests.cpp:<line number>: passed: testCase2.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: s1b.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: g1b.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: g1b.index() == 1 for: 1 == 1
-PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false == false
-PartTracker.tests.cpp:<line number>: passed: s1b.isComplete() for: true
-PartTracker.tests.cpp:<line number>: passed: g1b.isComplete() for: true
-PartTracker.tests.cpp:<line number>: passed: testCase2.isComplete() for: true
-PartTracker.tests.cpp:<line number>: passed: testCase.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: s1.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: g1.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: g1.index() == 0 for: 0 == 0
-PartTracker.tests.cpp:<line number>: passed: g1.isComplete() == false for: false == false
-PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false == false
-PartTracker.tests.cpp:<line number>: passed: s2.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: s2.isComplete() for: true
-PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false == false
-PartTracker.tests.cpp:<line number>: passed: testCase.isComplete() == false for: false == false
-PartTracker.tests.cpp:<line number>: passed: testCase2.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: s1b.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: g1b.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: g1b.index() == 1 for: 1 == 1
-PartTracker.tests.cpp:<line number>: passed: s2b.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: s2b.isComplete() for: true
-PartTracker.tests.cpp:<line number>: passed: g1b.isComplete() for: true
-PartTracker.tests.cpp:<line number>: passed: s1b.isComplete() for: true
-PartTracker.tests.cpp:<line number>: passed: testCase2.isComplete() for: true
-PartTracker.tests.cpp:<line number>: passed: testCase.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: s1.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: g1.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: g1.index() == 0 for: 0 == 0
-PartTracker.tests.cpp:<line number>: passed: g1.isComplete() == false for: false == false
-PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false == false
-PartTracker.tests.cpp:<line number>: passed: s2.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: s2.isComplete() for: true
-PartTracker.tests.cpp:<line number>: passed: s2.isSuccessfullyCompleted() == false for: false == false
-PartTracker.tests.cpp:<line number>: passed: s1.isComplete() == false for: false == false
-PartTracker.tests.cpp:<line number>: passed: testCase.isComplete() == false for: false == false
-PartTracker.tests.cpp:<line number>: passed: testCase2.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: s1b.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: g1b.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: g1b.index() == 0 for: 0 == 0
-PartTracker.tests.cpp:<line number>: passed: s2b.isOpen() == false for: false == false
-PartTracker.tests.cpp:<line number>: passed: g1b.isComplete() == false for: false == false
-PartTracker.tests.cpp:<line number>: passed: s1b.isComplete() == false for: false == false
-PartTracker.tests.cpp:<line number>: passed: testCase2.isComplete() == false for: false == false
-PartTracker.tests.cpp:<line number>: passed: testCase3.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: s1c.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: g1c.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: g1c.index() == 1 for: 1 == 1
-PartTracker.tests.cpp:<line number>: passed: s2c.isOpen() for: true
-PartTracker.tests.cpp:<line number>: passed: s2c.isComplete() for: true
-PartTracker.tests.cpp:<line number>: passed: g1c.isComplete() for: true
-PartTracker.tests.cpp:<line number>: passed: s1c.isComplete() for: true
-PartTracker.tests.cpp:<line number>: passed: testCase3.isComplete() for: true
 Exception.tests.cpp:<line number>: failed: unexpected exception with message: '3.14'
 Approx.tests.cpp:<line number>: passed: d == approx( 1.23 ) for: 1.23 == Approx( 1.23 )
 Approx.tests.cpp:<line number>: passed: d == approx( 1.22 ) for: 1.23 == Approx( 1.22 )
@@ -883,8 +1215,50 @@
 Xml.tests.cpp:<line number>: passed: encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't &quot;quote&quot; me on that" for: "don't &quot;quote&quot; me on that"
 ==
 "don't &quot;quote&quot; me on that"
-Xml.tests.cpp:<line number>: passed: encode( "[/x01]" ) == "[//x01]" for: "[/x01]" == "[/x01]"
-Xml.tests.cpp:<line number>: passed: encode( "[/x7F]" ) == "[//x7F]" for: "[/x7F]" == "[/x7F]"
+Xml.tests.cpp:<line number>: passed: encode( "[\x01]" ) == "[\\x01]" for: "[\x01]" == "[\x01]"
+Xml.tests.cpp:<line number>: passed: encode( "[\x7F]" ) == "[\\x7F]" for: "[\x7F]" == "[\x7F]"
+Xml.tests.cpp:<line number>: passed: encode(u8"Here be 👾") == u8"Here be 👾" for: "Here be 👾" == "Here be 👾"
+Xml.tests.cpp:<line number>: passed: encode(u8"šš") == u8"šš" for: "šš" == "šš"
+Xml.tests.cpp:<line number>: passed: encode("\xDF\xBF") == "\xDF\xBF" for: "߿" == "߿"
+Xml.tests.cpp:<line number>: passed: encode("\xE0\xA0\x80") == "\xE0\xA0\x80" for: "ࠀ" == "ࠀ"
+Xml.tests.cpp:<line number>: passed: encode("\xED\x9F\xBF") == "\xED\x9F\xBF" for: "퟿" == "퟿"
+Xml.tests.cpp:<line number>: passed: encode("\xEE\x80\x80") == "\xEE\x80\x80" for: "" == ""
+Xml.tests.cpp:<line number>: passed: encode("\xEF\xBF\xBF") == "\xEF\xBF\xBF" for: "￿" == "￿"
+Xml.tests.cpp:<line number>: passed: encode("\xF0\x90\x80\x80") == "\xF0\x90\x80\x80" for: "𐀀" == "𐀀"
+Xml.tests.cpp:<line number>: passed: encode("\xF4\x8F\xBF\xBF") == "\xF4\x8F\xBF\xBF" for: "􏿿" == "􏿿"
+Xml.tests.cpp:<line number>: passed: encode("Here \xFF be 👾") == u8"Here \\xFF be 👾" for: "Here \xFF be 👾" == "Here \xFF be 👾"
+Xml.tests.cpp:<line number>: passed: encode("\xFF") == "\\xFF" for: "\xFF" == "\xFF"
+Xml.tests.cpp:<line number>: passed: encode("\xC5\xC5\xA0") == u8"\\xC5Š" for: "\xC5Š" == "\xC5Š"
+Xml.tests.cpp:<line number>: passed: encode("\xF4\x90\x80\x80") == u8"\\xF4\\x90\\x80\\x80" for: "\xF4\x90\x80\x80" == "\xF4\x90\x80\x80"
+Xml.tests.cpp:<line number>: passed: encode("\xC0\x80") == u8"\\xC0\\x80" for: "\xC0\x80" == "\xC0\x80"
+Xml.tests.cpp:<line number>: passed: encode("\xF0\x80\x80\x80") == u8"\\xF0\\x80\\x80\\x80" for: "\xF0\x80\x80\x80" == "\xF0\x80\x80\x80"
+Xml.tests.cpp:<line number>: passed: encode("\xC1\xBF") == u8"\\xC1\\xBF" for: "\xC1\xBF" == "\xC1\xBF"
+Xml.tests.cpp:<line number>: passed: encode("\xE0\x9F\xBF") == u8"\\xE0\\x9F\\xBF" for: "\xE0\x9F\xBF" == "\xE0\x9F\xBF"
+Xml.tests.cpp:<line number>: passed: encode("\xF0\x8F\xBF\xBF") == u8"\\xF0\\x8F\\xBF\\xBF" for: "\xF0\x8F\xBF\xBF" == "\xF0\x8F\xBF\xBF"
+Xml.tests.cpp:<line number>: passed: encode("\xED\xA0\x80") == "\xED\xA0\x80" for: "í €" == "í €"
+Xml.tests.cpp:<line number>: passed: encode("\xED\xAF\xBF") == "\xED\xAF\xBF" for: "í¯¿" == "í¯¿"
+Xml.tests.cpp:<line number>: passed: encode("\xED\xB0\x80") == "\xED\xB0\x80" for: "í°€" == "í°€"
+Xml.tests.cpp:<line number>: passed: encode("\xED\xBF\xBF") == "\xED\xBF\xBF" for: "í¿¿" == "í¿¿"
+Xml.tests.cpp:<line number>: passed: encode("\x80") == u8"\\x80" for: "\x80" == "\x80"
+Xml.tests.cpp:<line number>: passed: encode("\x81") == u8"\\x81" for: "\x81" == "\x81"
+Xml.tests.cpp:<line number>: passed: encode("\xBC") == u8"\\xBC" for: "\xBC" == "\xBC"
+Xml.tests.cpp:<line number>: passed: encode("\xBF") == u8"\\xBF" for: "\xBF" == "\xBF"
+Xml.tests.cpp:<line number>: passed: encode("\xF5\x80\x80\x80") == u8"\\xF5\\x80\\x80\\x80" for: "\xF5\x80\x80\x80" == "\xF5\x80\x80\x80"
+Xml.tests.cpp:<line number>: passed: encode("\xF6\x80\x80\x80") == u8"\\xF6\\x80\\x80\\x80" for: "\xF6\x80\x80\x80" == "\xF6\x80\x80\x80"
+Xml.tests.cpp:<line number>: passed: encode("\xF7\x80\x80\x80") == u8"\\xF7\\x80\\x80\\x80" for: "\xF7\x80\x80\x80" == "\xF7\x80\x80\x80"
+Xml.tests.cpp:<line number>: passed: encode("\xDE") == u8"\\xDE" for: "\xDE" == "\xDE"
+Xml.tests.cpp:<line number>: passed: encode("\xDF") == u8"\\xDF" for: "\xDF" == "\xDF"
+Xml.tests.cpp:<line number>: passed: encode("\xE0") == u8"\\xE0" for: "\xE0" == "\xE0"
+Xml.tests.cpp:<line number>: passed: encode("\xEF") == u8"\\xEF" for: "\xEF" == "\xEF"
+Xml.tests.cpp:<line number>: passed: encode("\xF0") == u8"\\xF0" for: "\xF0" == "\xF0"
+Xml.tests.cpp:<line number>: passed: encode("\xF4") == u8"\\xF4" for: "\xF4" == "\xF4"
+Xml.tests.cpp:<line number>: passed: encode("\xE0\x80") == u8"\\xE0\\x80" for: "\xE0\x80" == "\xE0\x80"
+Xml.tests.cpp:<line number>: passed: encode("\xE0\xBF") == u8"\\xE0\\xBF" for: "\xE0\xBF" == "\xE0\xBF"
+Xml.tests.cpp:<line number>: passed: encode("\xE1\x80") == u8"\\xE1\\x80" for: "\xE1\x80" == "\xE1\x80"
+Xml.tests.cpp:<line number>: passed: encode("\xF0\x80") == u8"\\xF0\\x80" for: "\xF0\x80" == "\xF0\x80"
+Xml.tests.cpp:<line number>: passed: encode("\xF4\x80") == u8"\\xF4\\x80" for: "\xF4\x80" == "\xF4\x80"
+Xml.tests.cpp:<line number>: passed: encode("\xF0\x80\x80") == u8"\\xF0\\x80\\x80" for: "\xF0\x80\x80" == "\xF0\x80\x80"
+Xml.tests.cpp:<line number>: passed: encode("\xF4\x80\x80") == u8"\\xF4\\x80\\x80" for: "\xF4\x80\x80" == "\xF4\x80\x80"
 ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( empty ) == "{  }" for: "{  }" == "{  }"
 ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( oneValue ) == "{ 42 }" for: "{ 42 }" == "{ 42 }"
 ToStringVector.tests.cpp:<line number>: passed: Catch::Detail::stringify( twoValues ) == "{ 42, 250 }" for: "{ 42, 250 }" == "{ 42, 250 }"
@@ -911,10 +1285,20 @@
 Misc.tests.cpp:<line number>: passed:
 loose text artifact
 Message.tests.cpp:<line number>: failed: explicitly with 1 message: 'Previous info should not be seen'
+Message.tests.cpp:<line number>: failed: explicitly with 1 message: 'previous unscoped info SHOULD not be seen'
 Misc.tests.cpp:<line number>: passed: l == std::numeric_limits<long long>::max() for: 9223372036854775807 (0x<hex digits>)
 ==
 9223372036854775807 (0x<hex digits>)
 Misc.tests.cpp:<line number>: failed: b > a for: 0 > 1
+Misc.tests.cpp:<line number>: failed: b > a for: 1 > 1
+Misc.tests.cpp:<line number>: passed: b > a for: 2 > 1
+Misc.tests.cpp:<line number>: passed: b > a for: 3 > 1
+Misc.tests.cpp:<line number>: passed: b > a for: 4 > 1
+Misc.tests.cpp:<line number>: passed: b > a for: 5 > 1
+Misc.tests.cpp:<line number>: passed: b > a for: 6 > 1
+Misc.tests.cpp:<line number>: passed: b > a for: 7 > 1
+Misc.tests.cpp:<line number>: passed: b > a for: 8 > 1
+Misc.tests.cpp:<line number>: passed: b > a for: 9 > 1
 Misc.tests.cpp:<line number>: failed: ( fib[i] % 2 ) == 0 for: 1 == 0 with 1 message: 'Testing if fib[0] (1) is even'
 Misc.tests.cpp:<line number>: failed: ( fib[i] % 2 ) == 0 for: 1 == 0 with 1 message: 'Testing if fib[1] (1) is even'
 Misc.tests.cpp:<line number>: passed: ( fib[i] % 2 ) == 0 for: 0 == 0 with 1 message: 'Testing if fib[2] (2) is even'
@@ -923,6 +1307,8 @@
 Misc.tests.cpp:<line number>: passed: ( fib[i] % 2 ) == 0 for: 0 == 0 with 1 message: 'Testing if fib[5] (8) is even'
 Misc.tests.cpp:<line number>: failed: ( fib[i] % 2 ) == 0 for: 1 == 0 with 1 message: 'Testing if fib[6] (13) is even'
 Misc.tests.cpp:<line number>: failed: ( fib[i] % 2 ) == 0 for: 1 == 0 with 1 message: 'Testing if fib[7] (21) is even'
+Message.tests.cpp:<line number>: warning: 'info' with 2 messages: 'unscoped info' and 'and warn may mix'
+Message.tests.cpp:<line number>: warning: 'info' with 2 messages: 'unscoped info' and 'they are not cleared after warnings'
 Misc.tests.cpp:<line number>: failed: a == b for: 1 == 2
 Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2
 Misc.tests.cpp:<line number>: passed: a < b for: 1 < 2
@@ -932,13 +1318,22 @@
 Tricky.tests.cpp:<line number>: passed: s == "7" for: "7" == "7"
 Tricky.tests.cpp:<line number>: passed: ti == typeid(int) for: {?} == {?}
 Misc.tests.cpp:<line number>: passed:
+Message.tests.cpp:<line number>: passed: true with 1 message: 'this MAY be seen only for the FIRST assertion IF info is printed for passing assertions'
+Message.tests.cpp:<line number>: passed: true with 1 message: 'this MAY be seen only for the SECOND assertion IF info is printed for passing assertions'
+Message.tests.cpp:<line number>: failed: false with 1 message: 'this SHOULD be seen'
 Misc.tests.cpp:<line number>: passed: makeString( false ) != static_cast<char*>(0) for: "valid string" != {null string}
 Misc.tests.cpp:<line number>: passed: makeString( true ) == static_cast<char*>(0) for: {null string} == {null string}
 Tricky.tests.cpp:<line number>: passed: ptr.get() == 0 for: 0 == 0
-ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( pair ) == "{ { 42, /"Arthur/" }, { /"Ford/", 24 } }" for: "{ { 42, "Arthur" }, { "Ford", 24 } }"
+ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" for: "{ { 42, "Arthur" }, { "Ford", 24 } }"
 ==
 "{ { 42, "Arthur" }, { "Ford", 24 } }"
 Tricky.tests.cpp:<line number>: passed: p == 0 for: 0 == 0
+Message.tests.cpp:<line number>: passed: true with 1 message: 'this MAY be seen IF info is printed for passing assertions'
+Message.tests.cpp:<line number>: failed: false with 2 messages: 'this SHOULD be seen' and 'this SHOULD also be seen'
+Message.tests.cpp:<line number>: failed: false with 1 message: 'this SHOULD be seen only ONCE'
+Message.tests.cpp:<line number>: passed: true
+Message.tests.cpp:<line number>: passed: true with 1 message: 'this MAY also be seen only ONCE IF info is printed for passing assertions'
+Message.tests.cpp:<line number>: passed: true
 Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2
 Misc.tests.cpp:<line number>: passed: b != a for: 2 != 1
 Misc.tests.cpp:<line number>: passed: a != b for: 1 != 2
@@ -958,35 +1353,24 @@
 String.tests.cpp:<line number>: passed: s == "didn|'t" for: "didn|'t" == "didn|'t"
 Misc.tests.cpp:<line number>: failed: false with 1 message: '3'
 Message.tests.cpp:<line number>: failed: false with 2 messages: 'hi' and 'i := 7'
+Message.tests.cpp:<line number>: failed: false with 4 messages: 'Count 1 to 3...' and '1' and '2' and '3'
+Message.tests.cpp:<line number>: failed: false with 4 messages: 'Count 4 to 6...' and '4' and '5' and '6'
 ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( emptyMap ) == "{  }" for: "{  }" == "{  }"
-ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( map ) == "{ { /"one/", 1 } }" for: "{ { "one", 1 } }" == "{ { "one", 1 } }"
-ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( map ) == "{ { /"abc/", 1 }, { /"def/", 2 }, { /"ghi/", 3 } }" for: "{ { "abc", 1 }, { "def", 2 }, { "ghi", 3 } }"
+ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( map ) == "{ { \"one\", 1 } }" for: "{ { "one", 1 } }" == "{ { "one", 1 } }"
+ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( map ) == "{ { \"abc\", 1 }, { \"def\", 2 }, { \"ghi\", 3 } }" for: "{ { "abc", 1 }, { "def", 2 }, { "ghi", 3 } }"
 ==
 "{ { "abc", 1 }, { "def", 2 }, { "ghi", 3 } }"
-ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(value) == "{ 34, /"xyzzy/" }" for: "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }"
-ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( value ) == "{ 34, /"xyzzy/" }" for: "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }"
+ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(value) == "{ 34, \"xyzzy\" }" for: "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }"
+ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( value ) == "{ 34, \"xyzzy\" }" for: "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }"
 ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( emptySet ) == "{  }" for: "{  }" == "{  }"
-ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( set ) == "{ /"one/" }" for: "{ "one" }" == "{ "one" }"
-ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( set ) == "{ /"abc/", /"def/", /"ghi/" }" for: "{ "abc", "def", "ghi" }"
+ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( set ) == "{ \"one\" }" for: "{ "one" }" == "{ "one" }"
+ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( set ) == "{ \"abc\", \"def\", \"ghi\" }" for: "{ "abc", "def", "ghi" }"
 ==
 "{ "abc", "def", "ghi" }"
-ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( pr ) == "{ { /"green/", 55 } }" for: "{ { "green", 55 } }"
+ToStringPair.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( pr ) == "{ { \"green\", 55 } }" for: "{ { "green", 55 } }"
 ==
 "{ { "green", 55 } }"
 Tricky.tests.cpp:<line number>: failed: std::string( "first" ) == "second" for: "first" == "second"
-ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( item ) == "StringMaker<has_maker>" for: "StringMaker<has_maker>"
-==
-"StringMaker<has_maker>"
-ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( item ) == "StringMaker<has_maker_and_operator>" for: "StringMaker<has_maker_and_operator>"
-==
-"StringMaker<has_maker_and_operator>"
-ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( item ) == "operator<<( has_operator )" for: "operator<<( has_operator )"
-==
-"operator<<( has_operator )"
-Misc.tests.cpp:<line number>: passed: result == "/"wide load/"" for: ""wide load"" == ""wide load""
-Misc.tests.cpp:<line number>: passed: result == "/"wide load/"" for: ""wide load"" == ""wide load""
-Misc.tests.cpp:<line number>: passed: result == "/"wide load/"" for: ""wide load"" == ""wide load""
-Misc.tests.cpp:<line number>: passed: result == "/"wide load/"" for: ""wide load"" == ""wide load""
 ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(streamable_range{}) == "op<<(streamable_range)" for: "op<<(streamable_range)"
 ==
 "op<<(streamable_range)"
@@ -994,7 +1378,20 @@
 ==
 "stringmaker(streamable_range)"
 ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(just_range{}) == "{ 1, 2, 3, 4 }" for: "{ 1, 2, 3, 4 }" == "{ 1, 2, 3, 4 }"
-ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(disabled_range{}) == "{?}" for: "{?}" == "{?}"
+ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(disabled_range{}) == "{ !!! }" for: "{ !!! }" == "{ !!! }"
+ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( item ) == "StringMaker<has_maker>" for: "StringMaker<has_maker>"
+==
+"StringMaker<has_maker>"
+ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( item ) == "StringMaker<has_maker_and_operator>" for: "StringMaker<has_maker_and_operator>"
+==
+"StringMaker<has_maker_and_operator>"
+ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(item) == "{ !!! }" for: "{ !!! }" == "{ !!! }"
+ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( item ) == "operator<<( has_operator )" for: "operator<<( has_operator )"
+==
+"operator<<( has_operator )"
+ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( item ) == "operator<<( has_template_operator )" for: "operator<<( has_template_operator )"
+==
+"operator<<( has_template_operator )"
 ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker> }" for: "{ StringMaker<has_maker> }"
 ==
 "{ StringMaker<has_maker> }"
@@ -1004,6 +1401,19 @@
 ToStringWhich.tests.cpp:<line number>: passed: ::Catch::Detail::stringify( v ) == "{ operator<<( has_operator ) }" for: "{ operator<<( has_operator ) }"
 ==
 "{ operator<<( has_operator ) }"
+Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 3 == 3
+Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 3 == 3
+Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 5 == 5
+Generators.tests.cpp:<line number>: passed: data.str.size() == data.len for: 4 == 4
+Generators.tests.cpp:<line number>: passed: strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)) for: 5 == 5
+Generators.tests.cpp:<line number>: passed: strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)) for: 6 == 6
+Generators.tests.cpp:<line number>: passed: strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)) for: 5 == 5
+Generators.tests.cpp:<line number>: passed: strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)) for: 6 == 6
+Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'Why would you throw a std::string?'
+Misc.tests.cpp:<line number>: passed: result == "\"wide load\"" for: ""wide load"" == ""wide load""
+Misc.tests.cpp:<line number>: passed: result == "\"wide load\"" for: ""wide load"" == ""wide load""
+Misc.tests.cpp:<line number>: passed: result == "\"wide load\"" for: ""wide load"" == ""wide load""
+Misc.tests.cpp:<line number>: passed: result == "\"wide load\"" for: ""wide load"" == ""wide load""
 EnumToString.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(e0) == "E2/V0" for: "E2/V0" == "E2/V0"
 EnumToString.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(e1) == "E2/V1" for: "E2/V1" == "E2/V1"
 EnumToString.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(e3) == "Unknown enum value 10" for: "Unknown enum value 10"
@@ -1020,17 +1430,17 @@
 ToStringTuple.tests.cpp:<line number>: passed: "1.2f" == ::Catch::Detail::stringify(float(1.2)) for: "1.2f" == "1.2f"
 ToStringTuple.tests.cpp:<line number>: passed: "{ 1.2f, 0 }" == ::Catch::Detail::stringify(type{1.2f,0}) for: "{ 1.2f, 0 }" == "{ 1.2f, 0 }"
 ToStringTuple.tests.cpp:<line number>: passed: "{ 0 }" == ::Catch::Detail::stringify(type{0}) for: "{ 0 }" == "{ 0 }"
-ToStringTuple.tests.cpp:<line number>: passed: "{ 0, 42, /"Catch me/" }" == ::Catch::Detail::stringify(value) for: "{ 0, 42, "Catch me" }"
+ToStringTuple.tests.cpp:<line number>: passed: "{ 0, 42, \"Catch me\" }" == ::Catch::Detail::stringify(value) for: "{ 0, 42, "Catch me" }"
 ==
 "{ 0, 42, "Catch me" }"
-ToStringTuple.tests.cpp:<line number>: passed: "{ /"hello/", /"world/" }" == ::Catch::Detail::stringify(type{"hello","world"}) for: "{ "hello", "world" }"
+ToStringTuple.tests.cpp:<line number>: passed: "{ \"hello\", \"world\" }" == ::Catch::Detail::stringify(type{"hello","world"}) for: "{ "hello", "world" }"
 ==
 "{ "hello", "world" }"
 ToStringTuple.tests.cpp:<line number>: passed: "{ { 42 }, { }, 1.2f }" == ::Catch::Detail::stringify(value) for: "{ { 42 }, { }, 1.2f }"
 ==
 "{ { 42 }, { }, 1.2f }"
 ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(v) == "{  }" for: "{  }" == "{  }"
-ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(v) == "{ { /"hello/" }, { /"world/" } }" for: "{ { "hello" }, { "world" } }"
+ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(v) == "{ { \"hello\" }, { \"world\" } }" for: "{ { "hello" }, { "world" } }"
 ==
 "{ { "hello" }, { "world" } }"
 ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(bools) == "{  }" for: "{  }" == "{  }"
@@ -1043,8 +1453,8 @@
 ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(vv) == "{ 42 }" for: "{ 42 }" == "{ 42 }"
 ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(vv) == "{ 42, 250 }" for: "{ 42, 250 }" == "{ 42, 250 }"
 ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(vv) == "{  }" for: "{  }" == "{  }"
-ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(vv) == "{ /"hello/" }" for: "{ "hello" }" == "{ "hello" }"
-ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(vv) == "{ /"hello/", /"world/" }" for: "{ "hello", "world" }"
+ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(vv) == "{ \"hello\" }" for: "{ "hello" }" == "{ "hello" }"
+ToStringVector.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(vv) == "{ \"hello\", \"world\" }" for: "{ "hello", "world" }"
 ==
 "{ "hello", "world" }"
 Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
@@ -1066,5 +1476,5 @@
 Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
 Misc.tests.cpp:<line number>: passed:
 Misc.tests.cpp:<line number>: passed:
-Failed 61 test cases, failed 120 assertions.
+Failed 77 test cases, failed 138 assertions.
 
diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt
index a94cc4f..3c50437 100644
--- a/projects/SelfTest/Baselines/console.std.approved.txt
+++ b/projects/SelfTest/Baselines/console.std.approved.txt
@@ -1,8 +1,22 @@
+This would not be caught previously
+Nor would this
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 <exe-name> is a <version> host application.
 Run with -? for options
 
+Randomness seeded to: 1
+
+-------------------------------------------------------------------------------
+#1514: stderr/stdout is not captured in tests aborted by an exception
+-------------------------------------------------------------------------------
+Tricky.tests.cpp:<line number>
+...............................................................................
+
+Tricky.tests.cpp:<line number>: FAILED:
+explicitly with message:
+  1514
+
 -------------------------------------------------------------------------------
 #748 - captures with unexpected exceptions
   outside assertions
@@ -91,6 +105,87 @@
   "hello" == "world"
 
 -------------------------------------------------------------------------------
+A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - Template_Foo
+<float>
+-------------------------------------------------------------------------------
+Class.tests.cpp:<line number>
+...............................................................................
+
+Class.tests.cpp:<line number>: FAILED:
+  REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 1 )
+with expansion:
+  0 == 1
+
+-------------------------------------------------------------------------------
+A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - Template_Foo
+<int>
+-------------------------------------------------------------------------------
+Class.tests.cpp:<line number>
+...............................................................................
+
+Class.tests.cpp:<line number>: FAILED:
+  REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 1 )
+with expansion:
+  0 == 1
+
+-------------------------------------------------------------------------------
+A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - std::vector
+<float>
+-------------------------------------------------------------------------------
+Class.tests.cpp:<line number>
+...............................................................................
+
+Class.tests.cpp:<line number>: FAILED:
+  REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 1 )
+with expansion:
+  0 == 1
+
+-------------------------------------------------------------------------------
+A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - std::vector
+<int>
+-------------------------------------------------------------------------------
+Class.tests.cpp:<line number>
+...............................................................................
+
+Class.tests.cpp:<line number>: FAILED:
+  REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 1 )
+with expansion:
+  0 == 1
+
+-------------------------------------------------------------------------------
+A TEMPLATE_TEST_CASE_METHOD based test run that fails - double
+-------------------------------------------------------------------------------
+Class.tests.cpp:<line number>
+...............................................................................
+
+Class.tests.cpp:<line number>: FAILED:
+  REQUIRE( Template_Fixture<TestType>::m_a == 2 )
+with expansion:
+  1.0 == 2
+
+-------------------------------------------------------------------------------
+A TEMPLATE_TEST_CASE_METHOD based test run that fails - float
+-------------------------------------------------------------------------------
+Class.tests.cpp:<line number>
+...............................................................................
+
+Class.tests.cpp:<line number>: FAILED:
+  REQUIRE( Template_Fixture<TestType>::m_a == 2 )
+with expansion:
+  1.0f == 2
+
+-------------------------------------------------------------------------------
+A TEMPLATE_TEST_CASE_METHOD based test run that fails - int
+-------------------------------------------------------------------------------
+Class.tests.cpp:<line number>
+...............................................................................
+
+Class.tests.cpp:<line number>: FAILED:
+  REQUIRE( Template_Fixture<TestType>::m_a == 2 )
+with expansion:
+  1 == 2
+
+-------------------------------------------------------------------------------
 A TEST_CASE_METHOD based test run that fails
 -------------------------------------------------------------------------------
 Class.tests.cpp:<line number>
@@ -335,12 +430,12 @@
 Matchers.tests.cpp:<line number>: FAILED:
   CHECK_THROWS_MATCHES( throws(3), SpecialException, ExceptionMatcher{1} )
 with expansion:
-  {?} special exception has value of 1
+  SpecialException::what special exception has value of 1
 
 Matchers.tests.cpp:<line number>: FAILED:
   REQUIRE_THROWS_MATCHES( throws(4), SpecialException, ExceptionMatcher{1} )
 with expansion:
-  {?} special exception has value of 1
+  SpecialException::what special exception has value of 1
 
 -------------------------------------------------------------------------------
 Expected exceptions that don't throw or unexpected exceptions fail the test
@@ -390,8 +485,7 @@
 explicitly with message:
   This is a failure
 
-Message.tests.cpp:<line number>:
-warning:
+Message.tests.cpp:<line number>: warning:
   This message appears in the output
 
 -------------------------------------------------------------------------------
@@ -400,8 +494,7 @@
 Message.tests.cpp:<line number>
 ...............................................................................
 
-Message.tests.cpp:<line number>:
-warning:
+Message.tests.cpp:<line number>: warning:
   this is a warning
 
 -------------------------------------------------------------------------------
@@ -526,8 +619,7 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-warning:
+Misc.tests.cpp:<line number>: warning:
   This one ran
 
 -------------------------------------------------------------------------------
@@ -739,6 +831,16 @@
   "
 
 -------------------------------------------------------------------------------
+Thrown string literals are translated
+-------------------------------------------------------------------------------
+Exception.tests.cpp:<line number>
+...............................................................................
+
+Exception.tests.cpp:<line number>: FAILED:
+due to unexpected exception with message:
+  For some reason someone is throwing a string literal!
+
+-------------------------------------------------------------------------------
 Unexpected exceptions can be translated
 -------------------------------------------------------------------------------
 Exception.tests.cpp:<line number>
@@ -897,8 +999,7 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-warning:
+Tricky.tests.cpp:<line number>: warning:
   Uncomment the code in this test to check that it gives a sensible compiler
   error
 
@@ -908,8 +1009,7 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-warning:
+Tricky.tests.cpp:<line number>: warning:
   Uncomment the code in this test to check that it gives a sensible compiler
   error
 
@@ -957,8 +1057,18 @@
   Previous info should not be seen
 
 -------------------------------------------------------------------------------
+just failure after unscoped info
+-------------------------------------------------------------------------------
+Message.tests.cpp:<line number>
+...............................................................................
+
+Message.tests.cpp:<line number>: FAILED:
+explicitly with message:
+  previous unscoped info SHOULD not be seen
+
+-------------------------------------------------------------------------------
 looped SECTION tests
-  s1
+  b is currently: 0
 -------------------------------------------------------------------------------
 Misc.tests.cpp:<line number>
 ...............................................................................
@@ -969,6 +1079,18 @@
   0 > 1
 
 -------------------------------------------------------------------------------
+looped SECTION tests
+  b is currently: 1
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: FAILED:
+  CHECK( b > a )
+with expansion:
+  1 > 1
+
+-------------------------------------------------------------------------------
 looped tests
 -------------------------------------------------------------------------------
 Misc.tests.cpp:<line number>
@@ -1017,9 +1139,21 @@
   Testing if fib[7] (21) is even
 
 -------------------------------------------------------------------------------
+mix info, unscoped info and warning
+-------------------------------------------------------------------------------
+Message.tests.cpp:<line number>
+...............................................................................
+
+Message.tests.cpp:<line number>: warning:
+  and warn may mix
+
+Message.tests.cpp:<line number>: warning:
+  they are not cleared after warnings
+
+-------------------------------------------------------------------------------
 more nested SECTION tests
-  s1
-  s2
+  doesn't equal
+  equal
 -------------------------------------------------------------------------------
 Misc.tests.cpp:<line number>
 ...............................................................................
@@ -1030,6 +1164,40 @@
   1 == 2
 
 -------------------------------------------------------------------------------
+not prints unscoped info from previous failures
+-------------------------------------------------------------------------------
+Message.tests.cpp:<line number>
+...............................................................................
+
+Message.tests.cpp:<line number>: FAILED:
+  REQUIRE( false )
+with message:
+  this SHOULD be seen
+
+-------------------------------------------------------------------------------
+prints unscoped info on failure
+-------------------------------------------------------------------------------
+Message.tests.cpp:<line number>
+...............................................................................
+
+Message.tests.cpp:<line number>: FAILED:
+  REQUIRE( false )
+with messages:
+  this SHOULD be seen
+  this SHOULD also be seen
+
+-------------------------------------------------------------------------------
+prints unscoped info only for the first assertion
+-------------------------------------------------------------------------------
+Message.tests.cpp:<line number>
+...............................................................................
+
+Message.tests.cpp:<line number>: FAILED:
+  CHECK( false )
+with message:
+  this SHOULD be seen only ONCE
+
+-------------------------------------------------------------------------------
 send a single char to INFO
 -------------------------------------------------------------------------------
 Misc.tests.cpp:<line number>
@@ -1053,6 +1221,28 @@
   i := 7
 
 -------------------------------------------------------------------------------
+stacks unscoped info in loops
+-------------------------------------------------------------------------------
+Message.tests.cpp:<line number>
+...............................................................................
+
+Message.tests.cpp:<line number>: FAILED:
+  CHECK( false )
+with messages:
+  Count 1 to 3...
+  1
+  2
+  3
+
+Message.tests.cpp:<line number>: FAILED:
+  CHECK( false )
+with messages:
+  Count 4 to 6...
+  4
+  5
+  6
+
+-------------------------------------------------------------------------------
 string literals of different sizes can be compared
 -------------------------------------------------------------------------------
 Tricky.tests.cpp:<line number>
@@ -1063,7 +1253,17 @@
 with expansion:
   "first" == "second"
 
+-------------------------------------------------------------------------------
+thrown std::strings are translated
+-------------------------------------------------------------------------------
+Exception.tests.cpp:<line number>
+...............................................................................
+
+Exception.tests.cpp:<line number>: FAILED:
+due to unexpected exception with message:
+  Why would you throw a std::string?
+
 ===============================================================================
-test cases: 198 | 147 passed |  47 failed |  4 failed as expected
-assertions: 996 | 870 passed | 105 failed | 21 failed as expected
+test cases:  255 |  189 passed |  62 failed |  4 failed as expected
+assertions: 1393 | 1250 passed | 122 failed | 21 failed as expected
 
diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt
index 2b7159e..5b54ace 100644
--- a/projects/SelfTest/Baselines/console.sw.approved.txt
+++ b/projects/SelfTest/Baselines/console.sw.approved.txt
@@ -3,14 +3,15 @@
 <exe-name> is a <version> host application.
 Run with -? for options
 
+Randomness seeded to: 1
+
 -------------------------------------------------------------------------------
 # A test name that starts with a #
 -------------------------------------------------------------------------------
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
 with message:
   yay
 
@@ -21,14 +22,12 @@
 Decomposition.tests.cpp:<line number>
 ...............................................................................
 
-Decomposition.tests.cpp:<line number>:
-PASSED:
+Decomposition.tests.cpp:<line number>: PASSED:
   REQUIRE( fptr == 0 )
 with expansion:
   0 == 0
 
-Decomposition.tests.cpp:<line number>:
-PASSED:
+Decomposition.tests.cpp:<line number>: PASSED:
   REQUIRE( fptr == 0l )
 with expansion:
   0 == 0
@@ -39,14 +38,12 @@
 Compilation.tests.cpp:<line number>
 ...............................................................................
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( y.v == 0 )
 with expansion:
   0 == 0
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( 0 == y.v )
 with expansion:
   0 == 0
@@ -57,43 +54,109 @@
 Compilation.tests.cpp:<line number>
 ...............................................................................
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( t1 == t2 )
 with expansion:
   {?} == {?}
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( t1 != t2 )
 with expansion:
   {?} != {?}
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( t1 < t2 )
 with expansion:
   {?} < {?}
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( t1 > t2 )
 with expansion:
   {?} > {?}
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( t1 <= t2 )
 with expansion:
   {?} <= {?}
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( t1 >= t2 )
 with expansion:
   {?} >= {?}
 
 -------------------------------------------------------------------------------
+#1175 - Hidden Test
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+
+-------------------------------------------------------------------------------
+#1238
+-------------------------------------------------------------------------------
+Compilation.tests.cpp:<line number>
+...............................................................................
+
+Compilation.tests.cpp:<line number>: PASSED:
+  REQUIRE( std::memcmp(uarr, "123", sizeof(uarr)) == 0 )
+with expansion:
+  0 == 0
+with messages:
+  uarr := "123"
+  sarr := "456"
+
+Compilation.tests.cpp:<line number>: PASSED:
+  REQUIRE( std::memcmp(sarr, "456", sizeof(sarr)) == 0 )
+with expansion:
+  0 == 0
+with messages:
+  uarr := "123"
+  sarr := "456"
+
+-------------------------------------------------------------------------------
+#1245
+-------------------------------------------------------------------------------
+Compilation.tests.cpp:<line number>
+...............................................................................
+
+Compilation.tests.cpp:<line number>: PASSED:
+
+-------------------------------------------------------------------------------
+#1403
+-------------------------------------------------------------------------------
+Compilation.tests.cpp:<line number>
+...............................................................................
+
+Compilation.tests.cpp:<line number>: PASSED:
+  REQUIRE( h1 == h2 )
+with expansion:
+  [1403 helper] == [1403 helper]
+
+This would not be caught previously
+Nor would this
+-------------------------------------------------------------------------------
+#1514: stderr/stdout is not captured in tests aborted by an exception
+-------------------------------------------------------------------------------
+Tricky.tests.cpp:<line number>
+...............................................................................
+
+Tricky.tests.cpp:<line number>: FAILED:
+explicitly with message:
+  1514
+
+-------------------------------------------------------------------------------
+#1548
+-------------------------------------------------------------------------------
+Compilation.tests.cpp:<line number>
+...............................................................................
+
+Compilation.tests.cpp:<line number>: PASSED:
+  REQUIRE( std::is_same<TypeList<int>, TypeList<int>>::value )
+with expansion:
+  true
+
+-------------------------------------------------------------------------------
 #748 - captures with unexpected exceptions
   outside assertions
 -------------------------------------------------------------------------------
@@ -125,8 +188,7 @@
 Exception.tests.cpp:<line number>
 ...............................................................................
 
-Exception.tests.cpp:<line number>:
-PASSED:
+Exception.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS( thisThrows() )
 with message:
   answer := 42
@@ -137,8 +199,7 @@
 Compilation.tests.cpp:<line number>
 ...............................................................................
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( 42 == f )
 with expansion:
   42 == {?}
@@ -149,38 +210,31 @@
 Compilation.tests.cpp:<line number>
 ...............................................................................
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( a == t )
 with expansion:
   3 == 3
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   CHECK( a == t )
 with expansion:
   3 == 3
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS( throws_int(true) )
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   CHECK_THROWS_AS( throws_int(true), int )
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE_NOTHROW( throws_int(false) )
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( "aaa", Catch::EndsWith("aaa") )
 with expansion:
   "aaa" ends with: "aaa"
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( templated_tests<int>(3) )
 with expansion:
   true
@@ -196,8 +250,7 @@
 with expansion:
   1 == 0
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( errno == 1 )
 with expansion:
   1 == 1
@@ -208,8 +261,7 @@
 Compilation.tests.cpp:<line number>
 ...............................................................................
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( x == 4 )
 with expansion:
   {?} == 4
@@ -223,8 +275,7 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
 with message:
   Everything is OK
 
@@ -235,8 +286,7 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
 with message:
   Everything is OK
 
@@ -247,8 +297,7 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
 with message:
   Everything is OK
 
@@ -259,8 +308,7 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
 with message:
   Everything is OK
 
@@ -271,8 +319,7 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
 with message:
   Everything is OK
 
@@ -322,46 +369,38 @@
 Condition.tests.cpp:<line number>
 ...............................................................................
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( false == false )
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( true == true )
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( !false )
 with expansion:
   true
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE_FALSE( false )
 with expansion:
   !false
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( !falseValue )
 with expansion:
   true
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE_FALSE( falseValue )
 with expansion:
   !false
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( !(1 == 2) )
 with expansion:
   true
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE_FALSE( 1 == 2 )
 
 -------------------------------------------------------------------------------
@@ -371,14 +410,12 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( is_true<true>::value == true )
 with expansion:
   true == true
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( true == is_true<true>::value )
 with expansion:
   true == true
@@ -390,14 +427,12 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( is_true<false>::value == false )
 with expansion:
   false == false
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( false == is_true<false>::value )
 with expansion:
   false == false
@@ -409,8 +444,7 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( !is_true<false>::value )
 with expansion:
   true
@@ -422,8 +456,7 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( !!is_true<true>::value )
 with expansion:
   true
@@ -435,19 +468,584 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( is_true<true>::value )
 with expansion:
   true
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE_FALSE( is_true<false>::value )
 with expansion:
   !false
 
 -------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  1 < 4
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  4 < 7
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  1 < 7
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  1 < 4
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  4 < 8
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  1 < 8
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  1 < 4
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  4 < 9
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  1 < 9
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  1 < 5
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  5 < 7
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  1 < 7
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  1 < 5
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  5 < 8
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  1 < 8
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  1 < 5
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  5 < 9
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  1 < 9
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  1 < 6
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  6 < 7
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  1 < 7
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  1 < 6
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  6 < 8
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  1 < 8
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  1 < 6
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  6 < 9
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  1 < 9
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  2 < 4
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  4 < 7
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  2 < 7
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  2 < 4
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  4 < 8
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  2 < 8
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  2 < 4
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  4 < 9
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  2 < 9
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  2 < 5
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  5 < 7
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  2 < 7
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  2 < 5
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  5 < 8
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  2 < 8
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  2 < 5
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  5 < 9
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  2 < 9
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  2 < 6
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  6 < 7
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  2 < 7
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  2 < 6
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  6 < 8
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  2 < 8
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  2 < 6
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  6 < 9
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  2 < 9
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  3 < 4
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  4 < 7
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  3 < 7
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  3 < 4
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  4 < 8
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  3 < 8
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  3 < 4
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  4 < 9
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  3 < 9
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  3 < 5
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  5 < 7
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  3 < 7
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  3 < 5
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  5 < 8
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  3 < 8
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  3 < 5
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  5 < 9
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  3 < 9
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  3 < 6
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  6 < 7
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  3 < 7
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  3 < 6
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  6 < 8
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  3 < 8
+
+-------------------------------------------------------------------------------
+3x3x3 ints
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( x < y )
+with expansion:
+  3 < 6
+
+Generators.tests.cpp:<line number>: PASSED:
+  CHECK( y < z )
+with expansion:
+  6 < 9
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( x < z )
+with expansion:
+  3 < 9
+
+-------------------------------------------------------------------------------
 A METHOD_AS_TEST_CASE based test run that fails
 -------------------------------------------------------------------------------
 Class.tests.cpp:<line number>
@@ -464,13 +1062,174 @@
 Class.tests.cpp:<line number>
 ...............................................................................
 
-Class.tests.cpp:<line number>:
-PASSED:
+Class.tests.cpp:<line number>: PASSED:
   REQUIRE( s == "hello" )
 with expansion:
   "hello" == "hello"
 
 -------------------------------------------------------------------------------
+A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - Template_Foo
+<float>
+-------------------------------------------------------------------------------
+Class.tests.cpp:<line number>
+...............................................................................
+
+Class.tests.cpp:<line number>: FAILED:
+  REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 1 )
+with expansion:
+  0 == 1
+
+-------------------------------------------------------------------------------
+A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - Template_Foo
+<int>
+-------------------------------------------------------------------------------
+Class.tests.cpp:<line number>
+...............................................................................
+
+Class.tests.cpp:<line number>: FAILED:
+  REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 1 )
+with expansion:
+  0 == 1
+
+-------------------------------------------------------------------------------
+A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - std::vector
+<float>
+-------------------------------------------------------------------------------
+Class.tests.cpp:<line number>
+...............................................................................
+
+Class.tests.cpp:<line number>: FAILED:
+  REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 1 )
+with expansion:
+  0 == 1
+
+-------------------------------------------------------------------------------
+A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - std::vector
+<int>
+-------------------------------------------------------------------------------
+Class.tests.cpp:<line number>
+...............................................................................
+
+Class.tests.cpp:<line number>: FAILED:
+  REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 1 )
+with expansion:
+  0 == 1
+
+-------------------------------------------------------------------------------
+A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds - Template_Foo
+<float>
+-------------------------------------------------------------------------------
+Class.tests.cpp:<line number>
+...............................................................................
+
+Class.tests.cpp:<line number>: PASSED:
+  REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 0 )
+with expansion:
+  0 == 0
+
+-------------------------------------------------------------------------------
+A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds - Template_Foo
+<int>
+-------------------------------------------------------------------------------
+Class.tests.cpp:<line number>
+...............................................................................
+
+Class.tests.cpp:<line number>: PASSED:
+  REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 0 )
+with expansion:
+  0 == 0
+
+-------------------------------------------------------------------------------
+A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds - std::vector
+<float>
+-------------------------------------------------------------------------------
+Class.tests.cpp:<line number>
+...............................................................................
+
+Class.tests.cpp:<line number>: PASSED:
+  REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 0 )
+with expansion:
+  0 == 0
+
+-------------------------------------------------------------------------------
+A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds - std::vector
+<int>
+-------------------------------------------------------------------------------
+Class.tests.cpp:<line number>
+...............................................................................
+
+Class.tests.cpp:<line number>: PASSED:
+  REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 0 )
+with expansion:
+  0 == 0
+
+-------------------------------------------------------------------------------
+A TEMPLATE_TEST_CASE_METHOD based test run that fails - double
+-------------------------------------------------------------------------------
+Class.tests.cpp:<line number>
+...............................................................................
+
+Class.tests.cpp:<line number>: FAILED:
+  REQUIRE( Template_Fixture<TestType>::m_a == 2 )
+with expansion:
+  1.0 == 2
+
+-------------------------------------------------------------------------------
+A TEMPLATE_TEST_CASE_METHOD based test run that fails - float
+-------------------------------------------------------------------------------
+Class.tests.cpp:<line number>
+...............................................................................
+
+Class.tests.cpp:<line number>: FAILED:
+  REQUIRE( Template_Fixture<TestType>::m_a == 2 )
+with expansion:
+  1.0f == 2
+
+-------------------------------------------------------------------------------
+A TEMPLATE_TEST_CASE_METHOD based test run that fails - int
+-------------------------------------------------------------------------------
+Class.tests.cpp:<line number>
+...............................................................................
+
+Class.tests.cpp:<line number>: FAILED:
+  REQUIRE( Template_Fixture<TestType>::m_a == 2 )
+with expansion:
+  1 == 2
+
+-------------------------------------------------------------------------------
+A TEMPLATE_TEST_CASE_METHOD based test run that succeeds - double
+-------------------------------------------------------------------------------
+Class.tests.cpp:<line number>
+...............................................................................
+
+Class.tests.cpp:<line number>: PASSED:
+  REQUIRE( Template_Fixture<TestType>::m_a == 1 )
+with expansion:
+  1.0 == 1
+
+-------------------------------------------------------------------------------
+A TEMPLATE_TEST_CASE_METHOD based test run that succeeds - float
+-------------------------------------------------------------------------------
+Class.tests.cpp:<line number>
+...............................................................................
+
+Class.tests.cpp:<line number>: PASSED:
+  REQUIRE( Template_Fixture<TestType>::m_a == 1 )
+with expansion:
+  1.0f == 1
+
+-------------------------------------------------------------------------------
+A TEMPLATE_TEST_CASE_METHOD based test run that succeeds - int
+-------------------------------------------------------------------------------
+Class.tests.cpp:<line number>
+...............................................................................
+
+Class.tests.cpp:<line number>: PASSED:
+  REQUIRE( Template_Fixture<TestType>::m_a == 1 )
+with expansion:
+  1 == 1
+
+-------------------------------------------------------------------------------
 A TEST_CASE_METHOD based test run that fails
 -------------------------------------------------------------------------------
 Class.tests.cpp:<line number>
@@ -487,13 +1246,92 @@
 Class.tests.cpp:<line number>
 ...............................................................................
 
-Class.tests.cpp:<line number>:
-PASSED:
+Class.tests.cpp:<line number>: PASSED:
   REQUIRE( m_a == 1 )
 with expansion:
   1 == 1
 
 -------------------------------------------------------------------------------
+A Template product test case - Foo<float>
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( x.size() == 0 )
+with expansion:
+  0 == 0
+
+-------------------------------------------------------------------------------
+A Template product test case - Foo<int>
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( x.size() == 0 )
+with expansion:
+  0 == 0
+
+-------------------------------------------------------------------------------
+A Template product test case - std::vector<float>
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( x.size() == 0 )
+with expansion:
+  0 == 0
+
+-------------------------------------------------------------------------------
+A Template product test case - std::vector<int>
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( x.size() == 0 )
+with expansion:
+  0 == 0
+
+-------------------------------------------------------------------------------
+A comparison that uses literals instead of the normal constructor
+-------------------------------------------------------------------------------
+Approx.tests.cpp:<line number>
+...............................................................................
+
+Approx.tests.cpp:<line number>: PASSED:
+  REQUIRE( d == 1.23_a )
+with expansion:
+  1.23 == Approx( 1.23 )
+
+Approx.tests.cpp:<line number>: PASSED:
+  REQUIRE( d != 1.22_a )
+with expansion:
+  1.23 != Approx( 1.22 )
+
+Approx.tests.cpp:<line number>: PASSED:
+  REQUIRE( -d == -1.23_a )
+with expansion:
+  -1.23 == Approx( -1.23 )
+
+Approx.tests.cpp:<line number>: PASSED:
+  REQUIRE( d == 1.2_a .epsilon(.1) )
+with expansion:
+  1.23 == Approx( 1.2 )
+
+Approx.tests.cpp:<line number>: PASSED:
+  REQUIRE( d != 1.2_a .epsilon(.001) )
+with expansion:
+  1.23 != Approx( 1.2 )
+
+Approx.tests.cpp:<line number>: PASSED:
+  REQUIRE( d == 1_a .epsilon(.3) )
+with expansion:
+  1.23 == Approx( 1.0 )
+
+-------------------------------------------------------------------------------
 A couple of nested sections followed by a failure
   Outer
   Inner
@@ -501,8 +1339,7 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
 with message:
   that's not flying - that's failing in style
 
@@ -538,38 +1375,32 @@
 Approx.tests.cpp:<line number>
 ...............................................................................
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( 104.0 != Approx(100.0) )
 with expansion:
   104.0 != Approx( 100.0 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( 104.0 == Approx(100.0).margin(5) )
 with expansion:
   104.0 == Approx( 100.0 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( 104.0 == Approx(100.0).margin(4) )
 with expansion:
   104.0 == Approx( 100.0 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( 104.0 != Approx(100.0).margin(3) )
 with expansion:
   104.0 != Approx( 100.0 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( 100.3 != Approx(100.0) )
 with expansion:
   100.3 != Approx( 100.0 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( 100.3 == Approx(100.0).margin(0.5) )
 with expansion:
   100.3 == Approx( 100.0 )
@@ -589,14 +1420,12 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( i++ == 7 )
 with expansion:
   7 == 7
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( i++ == 8 )
 with expansion:
   8 == 8
@@ -607,8 +1436,7 @@
 Exception.tests.cpp:<line number>
 ...............................................................................
 
-Exception.tests.cpp:<line number>:
-PASSED:
+Exception.tests.cpp:<line number>: PASSED:
   CHECK( 1 == 1 )
 
 Exception.tests.cpp:<line number>: FAILED:
@@ -622,8 +1450,7 @@
 VariadicMacros.tests.cpp:<line number>
 ...............................................................................
 
-VariadicMacros.tests.cpp:<line number>:
-PASSED:
+VariadicMacros.tests.cpp:<line number>: PASSED:
 with message:
   anonymous test case
 
@@ -633,32 +1460,25 @@
 Approx.tests.cpp:<line number>
 ...............................................................................
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE_NOTHROW( Approx(0).margin(0) )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE_NOTHROW( Approx(0).margin(1234656) )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS_AS( Approx(0).margin(-2), std::domain_error )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE_NOTHROW( Approx(0).epsilon(0) )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE_NOTHROW( Approx(0).epsilon(1) )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS_AS( Approx(0).epsilon(-0.001), std::domain_error )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS_AS( Approx(0).epsilon(1.0001), std::domain_error )
 
 -------------------------------------------------------------------------------
@@ -667,32 +1487,27 @@
 Approx.tests.cpp:<line number>
 ...............................................................................
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   CHECK( 0.25f == Approx(0.0f).margin(0.25f) )
 with expansion:
   0.25f == Approx( 0.0 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   CHECK( 0.0f == Approx(0.25f).margin(0.25f) )
 with expansion:
   0.0f == Approx( 0.25 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   CHECK( 0.5f == Approx(0.25f).margin(0.25f) )
 with expansion:
   0.5f == Approx( 0.25 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   CHECK( 245.0f == Approx(245.25f).margin(0.25f) )
 with expansion:
   245.0f == Approx( 245.25 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   CHECK( 245.5f == Approx(245.25f).margin(0.25f) )
 with expansion:
   245.5f == Approx( 245.25 )
@@ -703,14 +1518,12 @@
 Approx.tests.cpp:<line number>
 ...............................................................................
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) )
 with expansion:
   3.1428571429 == Approx( 3.141 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) )
 with expansion:
   3.1428571429 != Approx( 3.141 )
@@ -721,14 +1534,12 @@
 Approx.tests.cpp:<line number>
 ...............................................................................
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( d != Approx( 1.231 ) )
 with expansion:
   1.23 != Approx( 1.231 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( d == Approx( 1.231 ).epsilon( 0.1 ) )
 with expansion:
   1.23 == Approx( 1.231 )
@@ -739,14 +1550,12 @@
 Approx.tests.cpp:<line number>
 ...............................................................................
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( 1.23f == Approx( 1.23f ) )
 with expansion:
   1.23f == Approx( 1.2300000191 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( 0.0f == Approx( 0.0f ) )
 with expansion:
   0.0f == Approx( 0.0 )
@@ -757,14 +1566,12 @@
 Approx.tests.cpp:<line number>
 ...............................................................................
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( 1 == Approx( 1 ) )
 with expansion:
   1 == Approx( 1.0 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( 0 == Approx( 0 ) )
 with expansion:
   0 == Approx( 0.0 )
@@ -775,44 +1582,72 @@
 Approx.tests.cpp:<line number>
 ...............................................................................
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( 1.0f == Approx( 1 ) )
 with expansion:
   1.0f == Approx( 1.0 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( 0 == Approx( dZero) )
 with expansion:
   0 == Approx( 0.0 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( 0 == Approx( dSmall ).margin( 0.001 ) )
 with expansion:
   0 == Approx( 0.00001 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( 1.234f == Approx( dMedium ) )
 with expansion:
   1.234f == Approx( 1.234 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( dMedium == Approx( 1.234f ) )
 with expansion:
   1.234 == Approx( 1.2339999676 )
 
 -------------------------------------------------------------------------------
+Arbitrary predicate matcher
+  Function pointer
+-------------------------------------------------------------------------------
+Matchers.tests.cpp:<line number>
+...............................................................................
+
+Matchers.tests.cpp:<line number>: PASSED:
+  REQUIRE_THAT( 1, Predicate<int>(alwaysTrue, "always true") )
+with expansion:
+  1 matches predicate: "always true"
+
+Matchers.tests.cpp:<line number>: PASSED:
+  REQUIRE_THAT( 1, !Predicate<int>(alwaysFalse, "always false") )
+with expansion:
+  1 not matches predicate: "always false"
+
+-------------------------------------------------------------------------------
+Arbitrary predicate matcher
+  Lambdas + different type
+-------------------------------------------------------------------------------
+Matchers.tests.cpp:<line number>
+...............................................................................
+
+Matchers.tests.cpp:<line number>: PASSED:
+  REQUIRE_THAT( "Hello olleH", Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); }, "First and last character should be equal") )
+with expansion:
+  "Hello olleH" matches predicate: "First and last character should be equal"
+
+Matchers.tests.cpp:<line number>: PASSED:
+  REQUIRE_THAT( "This wouldn't pass", !Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); } ) )
+with expansion:
+  "This wouldn't pass" not matches undescribed predicate
+
+-------------------------------------------------------------------------------
 Assertions then sections
 -------------------------------------------------------------------------------
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( true )
 
 -------------------------------------------------------------------------------
@@ -822,8 +1657,7 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( true )
 
 -------------------------------------------------------------------------------
@@ -834,8 +1668,7 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( true )
 
 -------------------------------------------------------------------------------
@@ -844,8 +1677,7 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( true )
 
 -------------------------------------------------------------------------------
@@ -855,8 +1687,7 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( true )
 
 -------------------------------------------------------------------------------
@@ -867,8 +1698,7 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( true )
 
 -------------------------------------------------------------------------------
@@ -877,20 +1707,17 @@
 Approx.tests.cpp:<line number>
 ...............................................................................
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( INFINITY == Approx(INFINITY) )
 with expansion:
   inff == Approx( inf )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( NAN != Approx(NAN) )
 with expansion:
   nanf != Approx( nan )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE_FALSE( NAN == Approx(NAN) )
 with expansion:
   !(nanf == Approx( nan ))
@@ -901,27 +1728,56 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( y.v == 0 )
 with expansion:
   0 == 0
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( 0 == y.v )
 with expansion:
   0 == 0
 
 -------------------------------------------------------------------------------
+CAPTURE can deal with complex expressions
+-------------------------------------------------------------------------------
+Message.tests.cpp:<line number>
+...............................................................................
+
+Message.tests.cpp:<line number>: PASSED:
+with messages:
+  a := 1
+  b := 2
+  c := 3
+  a + b := 3
+  a+b := 3
+  c > b := true
+  a == 1 := true
+
+-------------------------------------------------------------------------------
+CAPTURE can deal with complex expressions involving commas
+-------------------------------------------------------------------------------
+Message.tests.cpp:<line number>
+...............................................................................
+
+Message.tests.cpp:<line number>: PASSED:
+with messages:
+  std::vector<int>{1, 2, 3}[0, 1, 2] := 3
+  std::vector<int>{1, 2, 3}[(0, 1)] := 2
+  std::vector<int>{1, 2, 3}[0] := 1
+  (helper_1436<int, int>{12, -12}) := { 12, -12 }
+  (helper_1436<int, int>(-12, 12)) := { -12, 12 }
+  (1, 2) := 2
+  (2, 3) := 3
+
+-------------------------------------------------------------------------------
 Capture and info messages
   Capture should stringify like assertions
 -------------------------------------------------------------------------------
 ToStringGeneral.tests.cpp:<line number>
 ...............................................................................
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   REQUIRE( true )
 with message:
   i := 2
@@ -933,8 +1789,7 @@
 ToStringGeneral.tests.cpp:<line number>
 ...............................................................................
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   REQUIRE( true )
 with message:
   3
@@ -946,26 +1801,22 @@
 ToStringGeneral.tests.cpp:<line number>
 ...............................................................................
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   CHECK( tab == '\t' )
 with expansion:
   '\t' == '\t'
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   CHECK( newline == '\n' )
 with expansion:
   '\n' == '\n'
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   CHECK( carr_return == '\r' )
 with expansion:
   '\r' == '\r'
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   CHECK( form_feed == '\f' )
 with expansion:
   '\f' == '\f'
@@ -977,32 +1828,27 @@
 ToStringGeneral.tests.cpp:<line number>
 ...............................................................................
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   CHECK( space == ' ' )
 with expansion:
   ' ' == ' '
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   REQUIRE( c == chars[i] )
 with expansion:
   'a' == 'a'
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   REQUIRE( c == chars[i] )
 with expansion:
   'z' == 'z'
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   REQUIRE( c == chars[i] )
 with expansion:
   'A' == 'A'
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   REQUIRE( c == chars[i] )
 with expansion:
   'Z' == 'Z'
@@ -1014,32 +1860,27 @@
 ToStringGeneral.tests.cpp:<line number>
 ...............................................................................
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   CHECK( null_terminator == '\0' )
 with expansion:
   0 == 0
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   REQUIRE( c == i )
 with expansion:
   2 == 2
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   REQUIRE( c == i )
 with expansion:
   3 == 3
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   REQUIRE( c == i )
 with expansion:
   4 == 4
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   REQUIRE( c == i )
 with expansion:
   5 == 5
@@ -1050,64 +1891,52 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS( std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} )
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   CHECK_THROWS( std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} )
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE_NOTHROW( std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} )
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   CHECK_NOTHROW( std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} )
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( std::vector<int>{1, 2} == std::vector<int>{1, 2} )
 with expansion:
   { 1, 2 } == { 1, 2 }
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   CHECK( std::vector<int>{1, 2} == std::vector<int>{1, 2} )
 with expansion:
   { 1, 2 } == { 1, 2 }
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE_FALSE( std::vector<int>{1, 2} == std::vector<int>{1, 2, 3} )
 with expansion:
   !({ 1, 2 } == { 1, 2, 3 })
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   CHECK_FALSE( std::vector<int>{1, 2} == std::vector<int>{1, 2, 3} )
 with expansion:
   !({ 1, 2 } == { 1, 2, 3 })
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   CHECK_NOFAIL( std::vector<int>{1, 2} == std::vector<int>{1, 2} )
 with expansion:
   { 1, 2 } == { 1, 2 }
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   CHECKED_IF( std::vector<int>{1, 2} == std::vector<int>{1, 2} )
 with expansion:
   { 1, 2 } == { 1, 2 }
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( true )
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   CHECKED_ELSE( std::vector<int>{1, 2} == std::vector<int>{1, 2} )
 with expansion:
   { 1, 2 } == { 1, 2 }
@@ -1118,14 +1947,12 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( a )
 with expansion:
   0x<hex digits>
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( a == &foo )
 with expansion:
   0x<hex digits> == 0x<hex digits>
@@ -1136,74 +1963,62 @@
 Approx.tests.cpp:<line number>
 ...............................................................................
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( td == Approx(10.0) )
 with expansion:
   StrongDoubleTypedef(10) == Approx( 10.0 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( Approx(10.0) == td )
 with expansion:
   Approx( 10.0 ) == StrongDoubleTypedef(10)
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( td != Approx(11.0) )
 with expansion:
   StrongDoubleTypedef(10) != Approx( 11.0 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( Approx(11.0) != td )
 with expansion:
   Approx( 11.0 ) != StrongDoubleTypedef(10)
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( td <= Approx(10.0) )
 with expansion:
   StrongDoubleTypedef(10) <= Approx( 10.0 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( td <= Approx(11.0) )
 with expansion:
   StrongDoubleTypedef(10) <= Approx( 11.0 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( Approx(10.0) <= td )
 with expansion:
   Approx( 10.0 ) <= StrongDoubleTypedef(10)
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( Approx(9.0) <= td )
 with expansion:
   Approx( 9.0 ) <= StrongDoubleTypedef(10)
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( td >= Approx(9.0) )
 with expansion:
   StrongDoubleTypedef(10) >= Approx( 9.0 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( td >= Approx(td) )
 with expansion:
   StrongDoubleTypedef(10) >= Approx( 10.0 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( Approx(td) >= td )
 with expansion:
   Approx( 10.0 ) >= StrongDoubleTypedef(10)
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( Approx(11.0) >= td )
 with expansion:
   Approx( 11.0 ) >= StrongDoubleTypedef(10)
@@ -1214,8 +2029,7 @@
 Condition.tests.cpp:<line number>
 ...............................................................................
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   CHECK( 54 == 6*9 )
 with expansion:
   54 == 54
@@ -1227,38 +2041,32 @@
 Condition.tests.cpp:<line number>
 ...............................................................................
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   CHECK( ( -1 > 2u ) )
 with expansion:
   true
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   CHECK( -1 > 2u )
 with expansion:
   -1 > 2
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   CHECK( ( 2u < -1 ) )
 with expansion:
   true
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   CHECK( 2u < -1 )
 with expansion:
   2 < -1
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   CHECK( ( minInt > 2u ) )
 with expansion:
   true
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   CHECK( minInt > 2u )
 with expansion:
   -2147483648 > 2
@@ -1269,80 +2077,67 @@
 Condition.tests.cpp:<line number>
 ...............................................................................
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( i == 1 )
 with expansion:
   1 == 1
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( ui == 2 )
 with expansion:
   2 == 2
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( l == 3 )
 with expansion:
   3 == 3
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( ul == 4 )
 with expansion:
   4 == 4
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( c == 5 )
 with expansion:
   5 == 5
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( uc == 6 )
 with expansion:
   6 == 6
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( 1 == i )
 with expansion:
   1 == 1
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( 2 == ui )
 with expansion:
   2 == 2
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( 3 == l )
 with expansion:
   3 == 3
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( 4 == ul )
 with expansion:
   4 == 4
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( 5 == c )
 with expansion:
   5 == 5
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( 6 == uc )
 with expansion:
   6 == 6
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( (std::numeric_limits<uint32_t>::max)() > ul )
 with expansion:
   4294967295 (0x<hex digits>) > 4
@@ -1402,14 +2197,12 @@
 Approx.tests.cpp:<line number>
 ...............................................................................
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( 101.000001 != Approx(100).epsilon(0.01) )
 with expansion:
   101.000001 != Approx( 100.0 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( std::pow(10, -5) != Approx(std::pow(10, -7)) )
 with expansion:
   0.00001 != Approx( 0.0000001 )
@@ -1437,8 +2230,7 @@
 Approx.tests.cpp:<line number>
 ...............................................................................
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( 101.01 != Approx(100).epsilon(0.01) )
 with expansion:
   101.01 != Approx( 100.0 )
@@ -1520,44 +2312,37 @@
 Condition.tests.cpp:<line number>
 ...............................................................................
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.int_seven == 7 )
 with expansion:
   7 == 7
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.float_nine_point_one == Approx( 9.1f ) )
 with expansion:
   9.1f == Approx( 9.1000003815 )
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.double_pi == Approx( 3.1415926535 ) )
 with expansion:
   3.1415926535 == Approx( 3.1415926535 )
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.str_hello == "hello" )
 with expansion:
   "hello" == "hello"
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( "hello" == data.str_hello )
 with expansion:
   "hello" == "hello"
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.str_hello.size() == 5 )
 with expansion:
   5 == 5
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( x == Approx( 1.3 ) )
 with expansion:
   1.3 == Approx( 1.3 )
@@ -1568,15 +2353,13 @@
 Matchers.tests.cpp:<line number>
 ...............................................................................
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( testStringForMatching(), Equals("this string contains 'abc' as a substring") )
 with expansion:
   "this string contains 'abc' as a substring" equals: "this string contains
   'abc' as a substring"
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( testStringForMatching(), Equals("this string contains 'ABC' as a substring", Catch::CaseSensitive::No) )
 with expansion:
   "this string contains 'abc' as a substring" equals: "this string contains
@@ -1601,6 +2384,31 @@
   insensitive)
 
 -------------------------------------------------------------------------------
+Exception as a value (e.g. in REQUIRE_THROWS_MATCHES) can be stringified
+-------------------------------------------------------------------------------
+ToStringGeneral.tests.cpp:<line number>
+...............................................................................
+
+ToStringGeneral.tests.cpp:<line number>: PASSED:
+  REQUIRE( ::Catch::Detail::stringify(WhatException{}) == "This exception has overriden what() method" )
+with expansion:
+  "This exception has overriden what() method"
+  ==
+  "This exception has overriden what() method"
+
+ToStringGeneral.tests.cpp:<line number>: PASSED:
+  REQUIRE( ::Catch::Detail::stringify(OperatorException{}) == "OperatorException" )
+with expansion:
+  "OperatorException" == "OperatorException"
+
+ToStringGeneral.tests.cpp:<line number>: PASSED:
+  REQUIRE( ::Catch::Detail::stringify(StringMakerException{}) == "StringMakerException" )
+with expansion:
+  "StringMakerException"
+  ==
+  "StringMakerException"
+
+-------------------------------------------------------------------------------
 Exception matchers that fail
   No exception
 -------------------------------------------------------------------------------
@@ -1642,12 +2450,12 @@
 Matchers.tests.cpp:<line number>: FAILED:
   CHECK_THROWS_MATCHES( throws(3), SpecialException, ExceptionMatcher{1} )
 with expansion:
-  {?} special exception has value of 1
+  SpecialException::what special exception has value of 1
 
 Matchers.tests.cpp:<line number>: FAILED:
   REQUIRE_THROWS_MATCHES( throws(4), SpecialException, ExceptionMatcher{1} )
 with expansion:
-  {?} special exception has value of 1
+  SpecialException::what special exception has value of 1
 
 -------------------------------------------------------------------------------
 Exception matchers that succeed
@@ -1655,17 +2463,15 @@
 Matchers.tests.cpp:<line number>
 ...............................................................................
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THROWS_MATCHES( throws(1), SpecialException, ExceptionMatcher{1} )
 with expansion:
-  {?} special exception has value of 1
+  SpecialException::what special exception has value of 1
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS_MATCHES( throws(2), SpecialException, ExceptionMatcher{2} )
 with expansion:
-  {?} special exception has value of 2
+  SpecialException::what special exception has value of 2
 
 -------------------------------------------------------------------------------
 Exception messages can be tested for
@@ -1674,8 +2480,7 @@
 Exception.tests.cpp:<line number>
 ...............................................................................
 
-Exception.tests.cpp:<line number>:
-PASSED:
+Exception.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS_WITH( thisThrows(), "expected exception" )
 with expansion:
   "expected exception" equals: "expected exception"
@@ -1687,8 +2492,7 @@
 Exception.tests.cpp:<line number>
 ...............................................................................
 
-Exception.tests.cpp:<line number>:
-PASSED:
+Exception.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS_WITH( thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) )
 with expansion:
   "expected exception" equals: "expected exception" (case insensitive)
@@ -1700,26 +2504,22 @@
 Exception.tests.cpp:<line number>
 ...............................................................................
 
-Exception.tests.cpp:<line number>:
-PASSED:
+Exception.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS_WITH( thisThrows(), StartsWith( "expected" ) )
 with expansion:
   "expected exception" starts with: "expected"
 
-Exception.tests.cpp:<line number>:
-PASSED:
+Exception.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS_WITH( thisThrows(), EndsWith( "exception" ) )
 with expansion:
   "expected exception" ends with: "exception"
 
-Exception.tests.cpp:<line number>:
-PASSED:
+Exception.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS_WITH( thisThrows(), Contains( "except" ) )
 with expansion:
   "expected exception" contains: "except"
 
-Exception.tests.cpp:<line number>:
-PASSED:
+Exception.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS_WITH( thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) )
 with expansion:
   "expected exception" contains: "except" (case insensitive)
@@ -1772,8 +2572,7 @@
 explicitly with message:
   This is a failure
 
-Message.tests.cpp:<line number>:
-warning:
+Message.tests.cpp:<line number>: warning:
   This message appears in the output
 
 -------------------------------------------------------------------------------
@@ -1782,32 +2581,27 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( Factorial(0) == 1 )
 with expansion:
   1 == 1
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( Factorial(1) == 1 )
 with expansion:
   1 == 1
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( Factorial(2) == 2 )
 with expansion:
   2 == 2
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( Factorial(3) == 6 )
 with expansion:
   6 == 6
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( Factorial(10) == 3628800 )
 with expansion:
   3628800 (0x<hex digits>) == 3628800 (0x<hex digits>)
@@ -1819,36 +2613,51 @@
 Matchers.tests.cpp:<line number>
 ...............................................................................
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( 1., WithinAbs(1., 0) )
 with expansion:
   1.0 is within 0.0 of 1.0
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( 0., WithinAbs(1., 1) )
 with expansion:
   0.0 is within 1.0 of 1.0
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( 0., !WithinAbs(1., 0.99) )
 with expansion:
   0.0 not is within 0.99 of 1.0
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( 0., !WithinAbs(1., 0.99) )
 with expansion:
   0.0 not is within 0.99 of 1.0
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( NAN, !WithinAbs(NAN, 0) )
 with expansion:
   nanf not is within 0.0 of nan
 
+Matchers.tests.cpp:<line number>: PASSED:
+  REQUIRE_THAT( 11., !WithinAbs(10., 0.5) )
+with expansion:
+  11.0 not is within 0.5 of 10.0
+
+Matchers.tests.cpp:<line number>: PASSED:
+  REQUIRE_THAT( 10., !WithinAbs(11., 0.5) )
+with expansion:
+  10.0 not is within 0.5 of 11.0
+
+Matchers.tests.cpp:<line number>: PASSED:
+  REQUIRE_THAT( -10., WithinAbs(-10., 0.5) )
+with expansion:
+  -10.0 is within 0.5 of -10.0
+
+Matchers.tests.cpp:<line number>: PASSED:
+  REQUIRE_THAT( -10., WithinAbs(-9.6, 0.5) )
+with expansion:
+  -10.0 is within 0.5 of -9.6
+
 -------------------------------------------------------------------------------
 Floating point matchers: double
   ULPs
@@ -1856,44 +2665,37 @@
 Matchers.tests.cpp:<line number>
 ...............................................................................
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( 1., WithinULP(1., 0) )
 with expansion:
   1.0 is within 0 ULPs of 1.0
 
-Matchers.tests.cpp:<line number>:
-PASSED:
-  REQUIRE_THAT( std::nextafter(1., 2.), WithinULP(1., 1) )
+Matchers.tests.cpp:<line number>: PASSED:
+  REQUIRE_THAT( nextafter(1., 2.), WithinULP(1., 1) )
 with expansion:
   1.0 is within 1 ULPs of 1.0
 
-Matchers.tests.cpp:<line number>:
-PASSED:
-  REQUIRE_THAT( std::nextafter(1., 0.), WithinULP(1., 1) )
+Matchers.tests.cpp:<line number>: PASSED:
+  REQUIRE_THAT( nextafter(1., 0.), WithinULP(1., 1) )
 with expansion:
   1.0 is within 1 ULPs of 1.0
 
-Matchers.tests.cpp:<line number>:
-PASSED:
-  REQUIRE_THAT( std::nextafter(1., 2.), !WithinULP(1., 0) )
+Matchers.tests.cpp:<line number>: PASSED:
+  REQUIRE_THAT( nextafter(1., 2.), !WithinULP(1., 0) )
 with expansion:
   1.0 not is within 0 ULPs of 1.0
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( 1., WithinULP(1., 0) )
 with expansion:
   1.0 is within 0 ULPs of 1.0
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( -0., WithinULP(0., 0) )
 with expansion:
   -0.0 is within 0 ULPs of 0.0
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( NAN, !WithinULP(NAN, 123) )
 with expansion:
   nanf not is within 123 ULPs of nanf
@@ -1905,20 +2707,17 @@
 Matchers.tests.cpp:<line number>
 ...............................................................................
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( 1., WithinAbs(1., 0.5) || WithinULP(2., 1) )
 with expansion:
   1.0 ( is within 0.5 of 1.0 or is within 1 ULPs of 2.0 )
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( 1., WithinAbs(2., 0.5) || WithinULP(1., 0) )
 with expansion:
   1.0 ( is within 0.5 of 2.0 or is within 0 ULPs of 1.0 )
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( NAN, !(WithinAbs(NAN, 100) || WithinULP(NAN, 123)) )
 with expansion:
   nanf not ( is within 100.0 of nan or is within 123 ULPs of nanf )
@@ -1930,20 +2729,16 @@
 Matchers.tests.cpp:<line number>
 ...............................................................................
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_NOTHROW( WithinAbs(1., 0.) )
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS_AS( WithinAbs(1., -1.), std::domain_error )
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_NOTHROW( WithinULP(1., 0) )
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS_AS( WithinULP(1., -1), std::domain_error )
 
 -------------------------------------------------------------------------------
@@ -1953,42 +2748,56 @@
 Matchers.tests.cpp:<line number>
 ...............................................................................
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( 1.f, WithinAbs(1.f, 0) )
 with expansion:
   1.0f is within 0.0 of 1.0
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( 0.f, WithinAbs(1.f, 1) )
 with expansion:
   0.0f is within 1.0 of 1.0
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( 0.f, !WithinAbs(1.f, 0.99f) )
 with expansion:
   0.0f not is within 0.9900000095 of 1.0
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( 0.f, !WithinAbs(1.f, 0.99f) )
 with expansion:
   0.0f not is within 0.9900000095 of 1.0
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( 0.f, WithinAbs(-0.f, 0) )
 with expansion:
   0.0f is within 0.0 of -0.0
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( NAN, !WithinAbs(NAN, 0) )
 with expansion:
   nanf not is within 0.0 of nan
 
+Matchers.tests.cpp:<line number>: PASSED:
+  REQUIRE_THAT( 11.f, !WithinAbs(10.f, 0.5f) )
+with expansion:
+  11.0f not is within 0.5 of 10.0
+
+Matchers.tests.cpp:<line number>: PASSED:
+  REQUIRE_THAT( 10.f, !WithinAbs(11.f, 0.5f) )
+with expansion:
+  10.0f not is within 0.5 of 11.0
+
+Matchers.tests.cpp:<line number>: PASSED:
+  REQUIRE_THAT( -10.f, WithinAbs(-10.f, 0.5f) )
+with expansion:
+  -10.0f is within 0.5 of -10.0
+
+Matchers.tests.cpp:<line number>: PASSED:
+  REQUIRE_THAT( -10.f, WithinAbs(-9.6f, 0.5f) )
+with expansion:
+  -10.0f is within 0.5 of -9.6000003815
+
 -------------------------------------------------------------------------------
 Floating point matchers: float
   ULPs
@@ -1996,44 +2805,37 @@
 Matchers.tests.cpp:<line number>
 ...............................................................................
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( 1.f, WithinULP(1.f, 0) )
 with expansion:
   1.0f is within 0 ULPs of 1.0f
 
-Matchers.tests.cpp:<line number>:
-PASSED:
-  REQUIRE_THAT( std::nextafter(1.f, 2.f), WithinULP(1.f, 1) )
+Matchers.tests.cpp:<line number>: PASSED:
+  REQUIRE_THAT( nextafter(1.f, 2.f), WithinULP(1.f, 1) )
 with expansion:
   1.0f is within 1 ULPs of 1.0f
 
-Matchers.tests.cpp:<line number>:
-PASSED:
-  REQUIRE_THAT( std::nextafter(1.f, 0.f), WithinULP(1.f, 1) )
+Matchers.tests.cpp:<line number>: PASSED:
+  REQUIRE_THAT( nextafter(1.f, 0.f), WithinULP(1.f, 1) )
 with expansion:
   1.0f is within 1 ULPs of 1.0f
 
-Matchers.tests.cpp:<line number>:
-PASSED:
-  REQUIRE_THAT( std::nextafter(1.f, 2.f), !WithinULP(1.f, 0) )
+Matchers.tests.cpp:<line number>: PASSED:
+  REQUIRE_THAT( nextafter(1.f, 2.f), !WithinULP(1.f, 0) )
 with expansion:
   1.0f not is within 0 ULPs of 1.0f
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( 1.f, WithinULP(1.f, 0) )
 with expansion:
   1.0f is within 0 ULPs of 1.0f
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( -0.f, WithinULP(0.f, 0) )
 with expansion:
   -0.0f is within 0 ULPs of 0.0f
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( NAN, !WithinULP(NAN, 123) )
 with expansion:
   nanf not is within 123 ULPs of nanf
@@ -2045,20 +2847,17 @@
 Matchers.tests.cpp:<line number>
 ...............................................................................
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( 1.f, WithinAbs(1.f, 0.5) || WithinULP(1.f, 1) )
 with expansion:
   1.0f ( is within 0.5 of 1.0 or is within 1 ULPs of 1.0f )
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( 1.f, WithinAbs(2.f, 0.5) || WithinULP(1.f, 0) )
 with expansion:
   1.0f ( is within 0.5 of 2.0 or is within 0 ULPs of 1.0f )
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( NAN, !(WithinAbs(NAN, 100) || WithinULP(NAN, 123)) )
 with expansion:
   nanf not ( is within 100.0 of nan or is within 123 ULPs of nanf )
@@ -2070,48 +2869,1373 @@
 Matchers.tests.cpp:<line number>
 ...............................................................................
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_NOTHROW( WithinAbs(1.f, 0.f) )
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS_AS( WithinAbs(1.f, -1.f), std::domain_error )
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_NOTHROW( WithinULP(1.f, 0) )
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS_AS( WithinULP(1.f, -1), std::domain_error )
 
 -------------------------------------------------------------------------------
+Generators -- adapters
+  Filtering by predicate
+  Basic usage
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( i % 2 == 0 )
+with expansion:
+  0 == 0
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Filtering by predicate
+  Basic usage
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( i % 2 == 0 )
+with expansion:
+  0 == 0
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Filtering by predicate
+  Basic usage
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( i % 2 == 0 )
+with expansion:
+  0 == 0
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Filtering by predicate
+  Throws if there are no matching values
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE_THROWS_AS( filter([] (int) {return false; }, value(1)), Catch::GeneratorException )
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Shortening a range
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( i < 4 )
+with expansion:
+  1 < 4
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Shortening a range
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( i < 4 )
+with expansion:
+  2 < 4
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Shortening a range
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( i < 4 )
+with expansion:
+  3 < 4
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Transforming elements
+  Same type
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( i % 2 == 0 )
+with expansion:
+  0 == 0
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Transforming elements
+  Same type
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( i % 2 == 0 )
+with expansion:
+  0 == 0
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Transforming elements
+  Same type
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( i % 2 == 0 )
+with expansion:
+  0 == 0
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Transforming elements
+  Different type
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( i.size() == 1 )
+with expansion:
+  1 == 1
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Transforming elements
+  Different type
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( i.size() == 1 )
+with expansion:
+  1 == 1
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Transforming elements
+  Different type
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( i.size() == 1 )
+with expansion:
+  1 == 1
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Repeating a generator
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( j > 0 )
+with expansion:
+  1 > 0
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Repeating a generator
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( j > 0 )
+with expansion:
+  2 > 0
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Repeating a generator
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( j > 0 )
+with expansion:
+  3 > 0
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Repeating a generator
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( j > 0 )
+with expansion:
+  1 > 0
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Repeating a generator
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( j > 0 )
+with expansion:
+  2 > 0
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Repeating a generator
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( j > 0 )
+with expansion:
+  3 > 0
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Chunking a generator into sized pieces
+  Number of elements in source is divisible by chunk size
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( chunk2.size() == 2 )
+with expansion:
+  2 == 2
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( chunk2.front() == chunk2.back() )
+with expansion:
+  1 == 1
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Chunking a generator into sized pieces
+  Number of elements in source is divisible by chunk size
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( chunk2.size() == 2 )
+with expansion:
+  2 == 2
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( chunk2.front() == chunk2.back() )
+with expansion:
+  2 == 2
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Chunking a generator into sized pieces
+  Number of elements in source is divisible by chunk size
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( chunk2.size() == 2 )
+with expansion:
+  2 == 2
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( chunk2.front() == chunk2.back() )
+with expansion:
+  3 == 3
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Chunking a generator into sized pieces
+  Number of elements in source is not divisible by chunk size
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( chunk2.size() == 2 )
+with expansion:
+  2 == 2
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( chunk2.front() == chunk2.back() )
+with expansion:
+  1 == 1
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( chunk2.front() < 3 )
+with expansion:
+  1 < 3
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Chunking a generator into sized pieces
+  Number of elements in source is not divisible by chunk size
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( chunk2.size() == 2 )
+with expansion:
+  2 == 2
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( chunk2.front() == chunk2.back() )
+with expansion:
+  2 == 2
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( chunk2.front() < 3 )
+with expansion:
+  2 < 3
+
+-------------------------------------------------------------------------------
+Generators -- adapters
+  Chunking a generator into sized pieces
+  Throws on too small generators
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE_THROWS_AS( chunk(2, value(1)), Catch::GeneratorException )
+
+-------------------------------------------------------------------------------
+Generators -- simple
+  one
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( j < i )
+with expansion:
+  -3 < 1
+
+-------------------------------------------------------------------------------
+Generators -- simple
+  one
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( j < i )
+with expansion:
+  -2 < 1
+
+-------------------------------------------------------------------------------
+Generators -- simple
+  one
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( j < i )
+with expansion:
+  -1 < 1
+
+-------------------------------------------------------------------------------
+Generators -- simple
+  two
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( 4u * i > str.size() )
+with expansion:
+  4 > 1
+
+-------------------------------------------------------------------------------
+Generators -- simple
+  two
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( 4u * i > str.size() )
+with expansion:
+  4 > 2
+
+-------------------------------------------------------------------------------
+Generators -- simple
+  two
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( 4u * i > str.size() )
+with expansion:
+  4 > 3
+
+-------------------------------------------------------------------------------
+Generators -- simple
+  one
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( j < i )
+with expansion:
+  -3 < 2
+
+-------------------------------------------------------------------------------
+Generators -- simple
+  one
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( j < i )
+with expansion:
+  -2 < 2
+
+-------------------------------------------------------------------------------
+Generators -- simple
+  one
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( j < i )
+with expansion:
+  -1 < 2
+
+-------------------------------------------------------------------------------
+Generators -- simple
+  two
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( 4u * i > str.size() )
+with expansion:
+  8 > 1
+
+-------------------------------------------------------------------------------
+Generators -- simple
+  two
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( 4u * i > str.size() )
+with expansion:
+  8 > 2
+
+-------------------------------------------------------------------------------
+Generators -- simple
+  two
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( 4u * i > str.size() )
+with expansion:
+  8 > 3
+
+-------------------------------------------------------------------------------
+Generators -- simple
+  one
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( j < i )
+with expansion:
+  -3 < 3
+
+-------------------------------------------------------------------------------
+Generators -- simple
+  one
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( j < i )
+with expansion:
+  -2 < 3
+
+-------------------------------------------------------------------------------
+Generators -- simple
+  one
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( j < i )
+with expansion:
+  -1 < 3
+
+-------------------------------------------------------------------------------
+Generators -- simple
+  two
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( 4u * i > str.size() )
+with expansion:
+  12 > 1
+
+-------------------------------------------------------------------------------
+Generators -- simple
+  two
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( 4u * i > str.size() )
+with expansion:
+  12 > 2
+
+-------------------------------------------------------------------------------
+Generators -- simple
+  two
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( 4u * i > str.size() )
+with expansion:
+  12 > 3
+
+-------------------------------------------------------------------------------
+Generators internals
+  Single value
+-------------------------------------------------------------------------------
+GeneratorsImpl.tests.cpp:<line number>
+...............................................................................
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 123 )
+with expansion:
+  123 == 123
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE_FALSE( gen.next() )
+with expansion:
+  !false
+
+-------------------------------------------------------------------------------
+Generators internals
+  Preset values
+-------------------------------------------------------------------------------
+GeneratorsImpl.tests.cpp:<line number>
+...............................................................................
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 1 )
+with expansion:
+  1 == 1
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 3 )
+with expansion:
+  3 == 3
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 5 )
+with expansion:
+  5 == 5
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE_FALSE( gen.next() )
+with expansion:
+  !false
+
+-------------------------------------------------------------------------------
+Generators internals
+  Generator combinator
+-------------------------------------------------------------------------------
+GeneratorsImpl.tests.cpp:<line number>
+...............................................................................
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 1 )
+with expansion:
+  1 == 1
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 5 )
+with expansion:
+  5 == 5
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 2 )
+with expansion:
+  2 == 2
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 4 )
+with expansion:
+  4 == 4
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 0 )
+with expansion:
+  0 == 0
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE_FALSE( gen.next() )
+with expansion:
+  !false
+
+-------------------------------------------------------------------------------
+Generators internals
+  Explicitly typed generator sequence
+-------------------------------------------------------------------------------
+GeneratorsImpl.tests.cpp:<line number>
+...............................................................................
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get().size() == 2 )
+with expansion:
+  2 == 2
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == "aa" )
+with expansion:
+  "aa" == "aa"
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == "bb" )
+with expansion:
+  "bb" == "bb"
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == "cc" )
+with expansion:
+  "cc" == "cc"
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE_FALSE( gen.next() )
+with expansion:
+  !false
+
+-------------------------------------------------------------------------------
+Generators internals
+  Filter generator
+-------------------------------------------------------------------------------
+GeneratorsImpl.tests.cpp:<line number>
+...............................................................................
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 1 )
+with expansion:
+  1 == 1
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 3 )
+with expansion:
+  3 == 3
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE_FALSE( gen.next() )
+with expansion:
+  !false
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE_THROWS_AS( filter([] (int) { return false; }, value(1)), Catch::GeneratorException )
+
+-------------------------------------------------------------------------------
+Generators internals
+  Take generator
+  Take less
+-------------------------------------------------------------------------------
+GeneratorsImpl.tests.cpp:<line number>
+...............................................................................
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 1 )
+with expansion:
+  1 == 1
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 2 )
+with expansion:
+  2 == 2
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE_FALSE( gen.next() )
+with expansion:
+  !false
+
+-------------------------------------------------------------------------------
+Generators internals
+  Take generator
+  Take more
+-------------------------------------------------------------------------------
+GeneratorsImpl.tests.cpp:<line number>
+...............................................................................
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 1 )
+with expansion:
+  1 == 1
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE_FALSE( gen.next() )
+with expansion:
+  !false
+
+-------------------------------------------------------------------------------
+Generators internals
+  Map
+-------------------------------------------------------------------------------
+GeneratorsImpl.tests.cpp:<line number>
+...............................................................................
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 2.0 )
+with expansion:
+  2.0 == 2.0
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 4.0 )
+with expansion:
+  4.0 == 4.0
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 6.0 )
+with expansion:
+  6.0 == 6.0
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE_FALSE( gen.next() )
+with expansion:
+  !false
+
+-------------------------------------------------------------------------------
+Generators internals
+  Repeat
+  Singular repeat
+-------------------------------------------------------------------------------
+GeneratorsImpl.tests.cpp:<line number>
+...............................................................................
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 3 )
+with expansion:
+  3 == 3
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE_FALSE( gen.next() )
+with expansion:
+  !false
+
+-------------------------------------------------------------------------------
+Generators internals
+  Repeat
+  Actual repeat
+-------------------------------------------------------------------------------
+GeneratorsImpl.tests.cpp:<line number>
+...............................................................................
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 1 )
+with expansion:
+  1 == 1
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 2 )
+with expansion:
+  2 == 2
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 3 )
+with expansion:
+  3 == 3
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 1 )
+with expansion:
+  1 == 1
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 2 )
+with expansion:
+  2 == 2
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 3 )
+with expansion:
+  3 == 3
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE_FALSE( gen.next() )
+with expansion:
+  !false
+
+-------------------------------------------------------------------------------
+Generators internals
+  Range
+  Positive auto step
+  Integer
+-------------------------------------------------------------------------------
+GeneratorsImpl.tests.cpp:<line number>
+...............................................................................
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == -2 )
+with expansion:
+  -2 == -2
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == -1 )
+with expansion:
+  -1 == -1
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 0 )
+with expansion:
+  0 == 0
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 1 )
+with expansion:
+  1 == 1
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE_FALSE( gen.next() )
+with expansion:
+  !false
+
+-------------------------------------------------------------------------------
+Generators internals
+  Range
+  Negative auto step
+  Integer
+-------------------------------------------------------------------------------
+GeneratorsImpl.tests.cpp:<line number>
+...............................................................................
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 2 )
+with expansion:
+  2 == 2
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 1 )
+with expansion:
+  1 == 1
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 0 )
+with expansion:
+  0 == 0
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == -1 )
+with expansion:
+  -1 == -1
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE_FALSE( gen.next() )
+with expansion:
+  !false
+
+-------------------------------------------------------------------------------
+Generators internals
+  Range
+  Positive manual step
+  Integer
+  Exact
+-------------------------------------------------------------------------------
+GeneratorsImpl.tests.cpp:<line number>
+...............................................................................
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == -7 )
+with expansion:
+  -7 == -7
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == -4 )
+with expansion:
+  -4 == -4
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == -1 )
+with expansion:
+  -1 == -1
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 2 )
+with expansion:
+  2 == 2
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE_FALSE( gen.next() )
+with expansion:
+  !false
+
+-------------------------------------------------------------------------------
+Generators internals
+  Range
+  Positive manual step
+  Integer
+  Slightly over end
+-------------------------------------------------------------------------------
+GeneratorsImpl.tests.cpp:<line number>
+...............................................................................
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == -7 )
+with expansion:
+  -7 == -7
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == -4 )
+with expansion:
+  -4 == -4
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == -1 )
+with expansion:
+  -1 == -1
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 2 )
+with expansion:
+  2 == 2
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE_FALSE( gen.next() )
+with expansion:
+  !false
+
+-------------------------------------------------------------------------------
+Generators internals
+  Range
+  Positive manual step
+  Integer
+  Slightly under end
+-------------------------------------------------------------------------------
+GeneratorsImpl.tests.cpp:<line number>
+...............................................................................
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == -7 )
+with expansion:
+  -7 == -7
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == -4 )
+with expansion:
+  -4 == -4
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == -1 )
+with expansion:
+  -1 == -1
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 2 )
+with expansion:
+  2 == 2
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 5 )
+with expansion:
+  5 == 5
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE_FALSE( gen.next() )
+with expansion:
+  !false
+
+-------------------------------------------------------------------------------
+Generators internals
+  Range
+  Negative manual step
+  Integer
+  Exact
+-------------------------------------------------------------------------------
+GeneratorsImpl.tests.cpp:<line number>
+...............................................................................
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 5 )
+with expansion:
+  5 == 5
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 2 )
+with expansion:
+  2 == 2
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == -1 )
+with expansion:
+  -1 == -1
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == -4 )
+with expansion:
+  -4 == -4
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE_FALSE( gen.next() )
+with expansion:
+  !false
+
+-------------------------------------------------------------------------------
+Generators internals
+  Range
+  Negative manual step
+  Integer
+  Slightly over end
+-------------------------------------------------------------------------------
+GeneratorsImpl.tests.cpp:<line number>
+...............................................................................
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 5 )
+with expansion:
+  5 == 5
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 2 )
+with expansion:
+  2 == 2
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == -1 )
+with expansion:
+  -1 == -1
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == -4 )
+with expansion:
+  -4 == -4
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE_FALSE( gen.next() )
+with expansion:
+  !false
+
+-------------------------------------------------------------------------------
+Generators internals
+  Range
+  Negative manual step
+  Integer
+  Slightly under end
+-------------------------------------------------------------------------------
+GeneratorsImpl.tests.cpp:<line number>
+...............................................................................
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 5 )
+with expansion:
+  5 == 5
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == 2 )
+with expansion:
+  2 == 2
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == -1 )
+with expansion:
+  -1 == -1
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == -4 )
+with expansion:
+  -4 == -4
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.next() )
+with expansion:
+  true
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE( gen.get() == -7 )
+with expansion:
+  -7 == -7
+
+GeneratorsImpl.tests.cpp:<line number>: PASSED:
+  REQUIRE_FALSE( gen.next() )
+with expansion:
+  !false
+
+-------------------------------------------------------------------------------
 Greater-than inequalities with different epsilons
 -------------------------------------------------------------------------------
 Approx.tests.cpp:<line number>
 ...............................................................................
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( d >= Approx( 1.22 ) )
 with expansion:
   1.23 >= Approx( 1.22 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( d >= Approx( 1.23 ) )
 with expansion:
   1.23 >= Approx( 1.23 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE_FALSE( d >= Approx( 1.24 ) )
 with expansion:
   !(1.23 >= Approx( 1.24 ))
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( d >= Approx( 1.24 ).epsilon(0.1) )
 with expansion:
   1.23 >= Approx( 1.24 )
@@ -2122,8 +4246,7 @@
 Message.tests.cpp:<line number>
 ...............................................................................
 
-Message.tests.cpp:<line number>:
-warning:
+Message.tests.cpp:<line number>: warning:
   this is a message
   this is a warning
 
@@ -2150,8 +4273,7 @@
 Message.tests.cpp:<line number>
 ...............................................................................
 
-Message.tests.cpp:<line number>:
-PASSED:
+Message.tests.cpp:<line number>: PASSED:
   CHECK( a == 2 )
 with expansion:
   2 == 2
@@ -2175,8 +4297,7 @@
   this message should be logged
   and this, but later
 
-Message.tests.cpp:<line number>:
-PASSED:
+Message.tests.cpp:<line number>: PASSED:
   CHECK( a == 2 )
 with expansion:
   2 == 2
@@ -2192,8 +4313,7 @@
 Message.tests.cpp:<line number>
 ...............................................................................
 
-Message.tests.cpp:<line number>:
-PASSED:
+Message.tests.cpp:<line number>: PASSED:
   REQUIRE( i < 10 )
 with expansion:
   0 < 10
@@ -2201,8 +4321,7 @@
   current counter 0
   i := 0
 
-Message.tests.cpp:<line number>:
-PASSED:
+Message.tests.cpp:<line number>: PASSED:
   REQUIRE( i < 10 )
 with expansion:
   1 < 10
@@ -2210,8 +4329,7 @@
   current counter 1
   i := 1
 
-Message.tests.cpp:<line number>:
-PASSED:
+Message.tests.cpp:<line number>: PASSED:
   REQUIRE( i < 10 )
 with expansion:
   2 < 10
@@ -2219,8 +4337,7 @@
   current counter 2
   i := 2
 
-Message.tests.cpp:<line number>:
-PASSED:
+Message.tests.cpp:<line number>: PASSED:
   REQUIRE( i < 10 )
 with expansion:
   3 < 10
@@ -2228,8 +4345,7 @@
   current counter 3
   i := 3
 
-Message.tests.cpp:<line number>:
-PASSED:
+Message.tests.cpp:<line number>: PASSED:
   REQUIRE( i < 10 )
 with expansion:
   4 < 10
@@ -2237,8 +4353,7 @@
   current counter 4
   i := 4
 
-Message.tests.cpp:<line number>:
-PASSED:
+Message.tests.cpp:<line number>: PASSED:
   REQUIRE( i < 10 )
 with expansion:
   5 < 10
@@ -2246,8 +4361,7 @@
   current counter 5
   i := 5
 
-Message.tests.cpp:<line number>:
-PASSED:
+Message.tests.cpp:<line number>: PASSED:
   REQUIRE( i < 10 )
 with expansion:
   6 < 10
@@ -2255,8 +4369,7 @@
   current counter 6
   i := 6
 
-Message.tests.cpp:<line number>:
-PASSED:
+Message.tests.cpp:<line number>: PASSED:
   REQUIRE( i < 10 )
 with expansion:
   7 < 10
@@ -2264,8 +4377,7 @@
   current counter 7
   i := 7
 
-Message.tests.cpp:<line number>:
-PASSED:
+Message.tests.cpp:<line number>: PASSED:
   REQUIRE( i < 10 )
 with expansion:
   8 < 10
@@ -2273,8 +4385,7 @@
   current counter 8
   i := 8
 
-Message.tests.cpp:<line number>:
-PASSED:
+Message.tests.cpp:<line number>: PASSED:
   REQUIRE( i < 10 )
 with expansion:
   9 < 10
@@ -2327,68 +4438,57 @@
 Condition.tests.cpp:<line number>
 ...............................................................................
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.int_seven != 6 )
 with expansion:
   7 != 6
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.int_seven != 8 )
 with expansion:
   7 != 8
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.float_nine_point_one != Approx( 9.11f ) )
 with expansion:
   9.1f != Approx( 9.1099996567 )
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.float_nine_point_one != Approx( 9.0f ) )
 with expansion:
   9.1f != Approx( 9.0 )
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.float_nine_point_one != Approx( 1 ) )
 with expansion:
   9.1f != Approx( 1.0 )
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.float_nine_point_one != Approx( 0 ) )
 with expansion:
   9.1f != Approx( 0.0 )
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.double_pi != Approx( 3.1415 ) )
 with expansion:
   3.1415926535 != Approx( 3.1415 )
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.str_hello != "goodbye" )
 with expansion:
   "hello" != "goodbye"
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.str_hello != "hell" )
 with expansion:
   "hello" != "hell"
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.str_hello != "hello1" )
 with expansion:
   "hello" != "hello1"
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.str_hello.size() != 6 )
 with expansion:
   5 != 6
@@ -2399,26 +4499,22 @@
 Approx.tests.cpp:<line number>
 ...............................................................................
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( d <= Approx( 1.24 ) )
 with expansion:
   1.23 <= Approx( 1.24 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( d <= Approx( 1.23 ) )
 with expansion:
   1.23 <= Approx( 1.23 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE_FALSE( d <= Approx( 1.22 ) )
 with expansion:
   !(1.23 <= Approx( 1.22 ))
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( d <= Approx( 1.22 ).epsilon(0.1) )
 with expansion:
   1.23 <= Approx( 1.22 )
@@ -2429,8 +4525,7 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
 with message:
   was called
 
@@ -2440,8 +4535,7 @@
 Matchers.tests.cpp:<line number>
 ...............................................................................
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( testStringForMatching(), Contains("string") && Contains("abc") && Contains("substring") && Contains("contains") )
 with expansion:
   "this string contains 'abc' as a substring" ( contains: "string" and
@@ -2453,15 +4547,13 @@
 Matchers.tests.cpp:<line number>
 ...............................................................................
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( testStringForMatching(), Contains("string") || Contains("different") || Contains("random") )
 with expansion:
   "this string contains 'abc' as a substring" ( contains: "string" or contains:
   "different" or contains: "random" )
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( testStringForMatching2(), Contains("string") || Contains("different") || Contains("random") )
 with expansion:
   "some completely different text that contains one common word" ( contains:
@@ -2473,8 +4565,7 @@
 Matchers.tests.cpp:<line number>
 ...............................................................................
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( testStringForMatching(), (Contains("string") || Contains("different")) && Contains("substring") )
 with expansion:
   "this string contains 'abc' as a substring" ( ( contains: "string" or
@@ -2498,8 +4589,7 @@
 Matchers.tests.cpp:<line number>
 ...............................................................................
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( testStringForMatching(), !Contains("different") )
 with expansion:
   "this string contains 'abc' as a substring" not contains: "different"
@@ -2521,8 +4611,7 @@
 Exception.tests.cpp:<line number>
 ...............................................................................
 
-Exception.tests.cpp:<line number>:
-PASSED:
+Exception.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS_WITH( thisThrows(), "expected exception" )
 with expansion:
   "expected exception" equals: "expected exception"
@@ -2538,8 +4627,7 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-warning:
+Misc.tests.cpp:<line number>: warning:
   This one ran
 
 
@@ -2561,25 +4649,36 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   CHECK( True )
 with expansion:
   {?}
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   CHECK( !False )
 with expansion:
   true
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   CHECK_FALSE( False )
 with expansion:
   !{?}
 
 -------------------------------------------------------------------------------
+Optionally static assertions
+-------------------------------------------------------------------------------
+Compilation.tests.cpp:<line number>
+...............................................................................
+
+Compilation.tests.cpp:<line number>: PASSED:
+with message:
+  std::is_void<void>::value
+
+Compilation.tests.cpp:<line number>: PASSED:
+with message:
+  !(std::is_void<int>::value)
+
+-------------------------------------------------------------------------------
 Ordering comparison checks that should fail
 -------------------------------------------------------------------------------
 Condition.tests.cpp:<line number>
@@ -2686,104 +4785,87 @@
 Condition.tests.cpp:<line number>
 ...............................................................................
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.int_seven < 8 )
 with expansion:
   7 < 8
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.int_seven > 6 )
 with expansion:
   7 > 6
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.int_seven > 0 )
 with expansion:
   7 > 0
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.int_seven > -1 )
 with expansion:
   7 > -1
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.int_seven >= 7 )
 with expansion:
   7 >= 7
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.int_seven >= 6 )
 with expansion:
   7 >= 6
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.int_seven <= 7 )
 with expansion:
   7 <= 7
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.int_seven <= 8 )
 with expansion:
   7 <= 8
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.float_nine_point_one > 9 )
 with expansion:
   9.1f > 9
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.float_nine_point_one < 10 )
 with expansion:
   9.1f < 10
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.float_nine_point_one < 9.2 )
 with expansion:
   9.1f < 9.2
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.str_hello <= "hello" )
 with expansion:
   "hello" <= "hello"
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.str_hello >= "hello" )
 with expansion:
   "hello" >= "hello"
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.str_hello < "hellp" )
 with expansion:
   "hello" < "hellp"
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.str_hello < "zebra" )
 with expansion:
   "hello" < "zebra"
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.str_hello > "hellm" )
 with expansion:
   "hello" > "hellm"
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( data.str_hello > "a" )
 with expansion:
   "hello" > "a"
@@ -2817,20 +4899,17 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == false )
 with expansion:
   false == false
@@ -2842,20 +4921,17 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches(tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == false )
 with expansion:
   false == false
@@ -2867,20 +4943,17 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == false )
 with expansion:
   false == false
@@ -2892,20 +4965,17 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == true )
 with expansion:
   true == true
@@ -2917,20 +4987,17 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == true )
 with expansion:
   true == true
@@ -2942,26 +5009,22 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == false )
 with expansion:
   false == false
@@ -2973,38 +5036,32 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcD ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( parseTestSpec( "*a" ).matches( tcA ) == true )
 with expansion:
   true == true
@@ -3016,38 +5073,32 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcD ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( parseTestSpec( "a*" ).matches( tcA ) == true )
 with expansion:
   true == true
@@ -3059,38 +5110,32 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcD ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( parseTestSpec( "*a*" ).matches( tcA ) == true )
 with expansion:
   true == true
@@ -3102,20 +5147,17 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == false )
 with expansion:
   false == false
@@ -3127,20 +5169,17 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == false )
 with expansion:
   false == false
@@ -3152,20 +5191,17 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == false )
 with expansion:
   false == false
@@ -3177,32 +5213,27 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcD ) == true )
 with expansion:
   true == true
@@ -3214,32 +5245,27 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcD ) == true )
 with expansion:
   true == true
@@ -3251,26 +5277,22 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == false )
 with expansion:
   false == false
@@ -3282,26 +5304,22 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == true )
 with expansion:
   true == true
@@ -3313,26 +5331,22 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == true )
 with expansion:
   true == true
@@ -3344,26 +5358,22 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == true )
 with expansion:
   true == true
@@ -3375,32 +5385,27 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcD ) == false )
 with expansion:
   false == false
@@ -3412,26 +5417,22 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == true )
 with expansion:
   true == true
@@ -3443,26 +5444,22 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == false )
 with expansion:
   false == false
@@ -3474,32 +5471,27 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcD ) == true )
 with expansion:
   true == true
@@ -3511,32 +5503,27 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcD ) == true )
 with expansion:
   true == true
@@ -3548,32 +5535,27 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcD ) == true )
 with expansion:
   true == true
@@ -3585,32 +5567,27 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcD ) == false )
 with expansion:
   false == false
@@ -3622,32 +5599,27 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcD ) == false )
 with expansion:
   false == false
@@ -3659,32 +5631,27 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcD ) == false )
 with expansion:
   false == false
@@ -3696,32 +5663,27 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcD ) == false )
 with expansion:
   false == false
@@ -3733,32 +5695,27 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcD ) == false )
 with expansion:
   false == false
@@ -3770,32 +5727,27 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcD ) == false )
 with expansion:
   false == false
@@ -3807,117 +5759,101 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.hasFilters() == true )
 with expansion:
   true == true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcA ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcB ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcC ) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( spec.matches( tcD ) == true )
 with expansion:
   true == true
 
 -------------------------------------------------------------------------------
-Parsing a std::pair
--------------------------------------------------------------------------------
-Tricky.tests.cpp:<line number>
-...............................................................................
-
-Tricky.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( (std::pair<int, int>( 1, 2 )) == aNicePair )
-with expansion:
-  {?} == {?}
-
--------------------------------------------------------------------------------
 Pointers can be compared to null
 -------------------------------------------------------------------------------
 Condition.tests.cpp:<line number>
 ...............................................................................
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( p == 0 )
 with expansion:
   0 == 0
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( p == pNULL )
 with expansion:
   0 == 0
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( p != 0 )
 with expansion:
   0x<hex digits> != 0
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( cp != 0 )
 with expansion:
   0x<hex digits> != 0
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( cpc != 0 )
 with expansion:
   0x<hex digits> != 0
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( returnsNull() == 0 )
 with expansion:
   {null string} == 0
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( returnsConstNull() == 0 )
 with expansion:
   {null string} == 0
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( 0 != p )
 with expansion:
   0 != 0x<hex digits>
 
 -------------------------------------------------------------------------------
+Predicate matcher can accept const char*
+-------------------------------------------------------------------------------
+Matchers.tests.cpp:<line number>
+...............................................................................
+
+Matchers.tests.cpp:<line number>: PASSED:
+  REQUIRE_THAT( "foo", Predicate<const char*>([] (const char* const&) { return true; }) )
+with expansion:
+  "foo" matches undescribed predicate
+
+-------------------------------------------------------------------------------
 Process can be configured on command line
   empty args don't cause a crash
 -------------------------------------------------------------------------------
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( result )
 with expansion:
   {?}
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( config.processName == "" )
 with expansion:
   "" == ""
@@ -3929,64 +5865,65 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( result )
 with expansion:
   {?}
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( config.processName == "test" )
 with expansion:
   "test" == "test"
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( config.shouldDebugBreak == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( config.abortAfter == -1 )
 with expansion:
   -1 == -1
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( config.noThrow == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
-  CHECK( config.reporterNames.empty() )
+CmdLine.tests.cpp:<line number>: PASSED:
+  CHECK( config.reporterName == "console" )
 with expansion:
-  true
+  "console" == "console"
+
+CmdLine.tests.cpp:<line number>: PASSED:
+  CHECK_FALSE( cfg.hasTestFilters() )
+with expansion:
+  !false
 
 -------------------------------------------------------------------------------
 Process can be configured on command line
   test lists
-  1 test
+  Specify one test case using
 -------------------------------------------------------------------------------
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( result )
 with expansion:
   {?}
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
+  REQUIRE( cfg.hasTestFilters() )
+with expansion:
+  true
+
+CmdLine.tests.cpp:<line number>: PASSED:
   REQUIRE( cfg.testSpec().matches(fakeTestCase("notIncluded")) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   REQUIRE( cfg.testSpec().matches(fakeTestCase("test1")) )
 with expansion:
   true
@@ -3999,20 +5936,22 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( result )
 with expansion:
   {?}
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
+  REQUIRE( cfg.hasTestFilters() )
+with expansion:
+  true
+
+CmdLine.tests.cpp:<line number>: PASSED:
   REQUIRE( cfg.testSpec().matches(fakeTestCase("test1")) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   REQUIRE( cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) )
 with expansion:
   true
@@ -4025,20 +5964,22 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( result )
 with expansion:
   {?}
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
+  REQUIRE( cfg.hasTestFilters() )
+with expansion:
+  true
+
+CmdLine.tests.cpp:<line number>: PASSED:
   REQUIRE( cfg.testSpec().matches(fakeTestCase("test1")) == false )
 with expansion:
   false == false
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   REQUIRE( cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) )
 with expansion:
   true
@@ -4051,15 +5992,13 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( cli.parse({"test", "-r", "console"}) )
 with expansion:
   {?}
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( config.reporterNames[0] == "console" )
+CmdLine.tests.cpp:<line number>: PASSED:
+  REQUIRE( config.reporterName == "console" )
 with expansion:
   "console" == "console"
 
@@ -4071,86 +6010,80 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( cli.parse({"test", "-r", "xml"}) )
 with expansion:
   {?}
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( config.reporterNames[0] == "xml" )
+CmdLine.tests.cpp:<line number>: PASSED:
+  REQUIRE( config.reporterName == "xml" )
 with expansion:
   "xml" == "xml"
 
 -------------------------------------------------------------------------------
 Process can be configured on command line
   reporter
-  -r xml and junit
--------------------------------------------------------------------------------
-CmdLine.tests.cpp:<line number>
-...............................................................................
-
-CmdLine.tests.cpp:<line number>:
-PASSED:
-  CHECK( cli.parse({"test", "-r", "xml", "-r", "junit"}) )
-with expansion:
-  {?}
-
-CmdLine.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( config.reporterNames.size() == 2 )
-with expansion:
-  2 == 2
-
-CmdLine.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( config.reporterNames[0] == "xml" )
-with expansion:
-  "xml" == "xml"
-
-CmdLine.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( config.reporterNames[1] == "junit" )
-with expansion:
-  "junit" == "junit"
-
--------------------------------------------------------------------------------
-Process can be configured on command line
-  reporter
   --reporter/junit
 -------------------------------------------------------------------------------
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( cli.parse({"test", "--reporter", "junit"}) )
 with expansion:
   {?}
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( config.reporterNames[0] == "junit" )
+CmdLine.tests.cpp:<line number>: PASSED:
+  REQUIRE( config.reporterName == "junit" )
 with expansion:
   "junit" == "junit"
 
 -------------------------------------------------------------------------------
 Process can be configured on command line
+  reporter
+  Only one reporter is accepted
+-------------------------------------------------------------------------------
+CmdLine.tests.cpp:<line number>
+...............................................................................
+
+CmdLine.tests.cpp:<line number>: PASSED:
+  REQUIRE_FALSE( cli.parse({ "test", "-r", "xml", "-r", "junit" }) )
+with expansion:
+  !{?}
+
+-------------------------------------------------------------------------------
+Process can be configured on command line
+  reporter
+  must match one of the available ones
+-------------------------------------------------------------------------------
+CmdLine.tests.cpp:<line number>
+...............................................................................
+
+CmdLine.tests.cpp:<line number>: PASSED:
+  CHECK( !result )
+with expansion:
+  true
+
+CmdLine.tests.cpp:<line number>: PASSED:
+  REQUIRE_THAT( result.errorMessage(), Contains("Unrecognized reporter") )
+with expansion:
+  "Unrecognized reporter, 'unsupported'. Check available with --list-reporters"
+  contains: "Unrecognized reporter"
+
+-------------------------------------------------------------------------------
+Process can be configured on command line
   debugger
   -b
 -------------------------------------------------------------------------------
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( cli.parse({"test", "-b"}) )
 with expansion:
   {?}
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   REQUIRE( config.shouldDebugBreak == true )
 with expansion:
   true == true
@@ -4163,14 +6096,12 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( cli.parse({"test", "--break"}) )
 with expansion:
   {?}
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   REQUIRE( config.shouldDebugBreak )
 with expansion:
   true
@@ -4183,14 +6114,12 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( cli.parse({"test", "-a"}) )
 with expansion:
   {?}
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   REQUIRE( config.abortAfter == 1 )
 with expansion:
   1 == 1
@@ -4203,14 +6132,12 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( cli.parse({"test", "-x", "2"}) )
 with expansion:
   {?}
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   REQUIRE( config.abortAfter == 2 )
 with expansion:
   2 == 2
@@ -4223,14 +6150,12 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( !result )
 with expansion:
   true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( result.errorMessage(), Contains("convert") && Contains("oops") )
 with expansion:
   "Unable to convert 'oops' to destination type" ( contains: "convert" and
@@ -4244,14 +6169,12 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( cli.parse({"test", "-e"}) )
 with expansion:
   {?}
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   REQUIRE( config.noThrow )
 with expansion:
   true
@@ -4264,14 +6187,12 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( cli.parse({"test", "--nothrow"}) )
 with expansion:
   {?}
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   REQUIRE( config.noThrow )
 with expansion:
   true
@@ -4284,14 +6205,12 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( cli.parse({"test", "-o", "filename.ext"}) )
 with expansion:
   {?}
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   REQUIRE( config.outputFilename == "filename.ext" )
 with expansion:
   "filename.ext" == "filename.ext"
@@ -4304,14 +6223,12 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( cli.parse({"test", "--out", "filename.ext"}) )
 with expansion:
   {?}
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   REQUIRE( config.outputFilename == "filename.ext" )
 with expansion:
   "filename.ext" == "filename.ext"
@@ -4324,26 +6241,22 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( cli.parse({"test", "-abe"}) )
 with expansion:
   {?}
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( config.abortAfter == 1 )
 with expansion:
   1 == 1
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( config.shouldDebugBreak )
 with expansion:
   true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( config.noThrow == true )
 with expansion:
   true == true
@@ -4356,14 +6269,12 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( cli.parse({"test"}) )
 with expansion:
   {?}
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   REQUIRE( config.useColour == UseColour::Auto )
 with expansion:
   0 == 0
@@ -4376,14 +6287,12 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( cli.parse({"test", "--use-colour", "auto"}) )
 with expansion:
   {?}
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   REQUIRE( config.useColour == UseColour::Auto )
 with expansion:
   0 == 0
@@ -4396,14 +6305,12 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( cli.parse({"test", "--use-colour", "yes"}) )
 with expansion:
   {?}
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   REQUIRE( config.useColour == UseColour::Yes )
 with expansion:
   1 == 1
@@ -4416,14 +6323,12 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( cli.parse({"test", "--use-colour", "no"}) )
 with expansion:
   {?}
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   REQUIRE( config.useColour == UseColour::No )
 with expansion:
   2 == 2
@@ -4436,20 +6341,51 @@
 CmdLine.tests.cpp:<line number>
 ...............................................................................
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK( !result )
 with expansion:
   true
 
-CmdLine.tests.cpp:<line number>:
-PASSED:
+CmdLine.tests.cpp:<line number>: PASSED:
   CHECK_THAT( result.errorMessage(), Contains( "colour mode must be one of" ) )
 with expansion:
   "colour mode must be one of: auto, yes or no. 'wrong' not recognised"
   contains: "colour mode must be one of"
 
 -------------------------------------------------------------------------------
+Product with differing arities - std::tuple<int, double, float>
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( std::tuple_size<TestType>::value >= 1 )
+with expansion:
+  3 >= 1
+
+-------------------------------------------------------------------------------
+Product with differing arities - std::tuple<int, double>
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( std::tuple_size<TestType>::value >= 1 )
+with expansion:
+  2 >= 1
+
+-------------------------------------------------------------------------------
+Product with differing arities - std::tuple<int>
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( std::tuple_size<TestType>::value >= 1 )
+with expansion:
+  1 >= 1
+
+-------------------------------------------------------------------------------
 Reconstruction should be based on stringification: #914
 -------------------------------------------------------------------------------
 Decomposition.tests.cpp:<line number>
@@ -4485,13 +6421,23 @@
   'abc' as a" case sensitively
 
 -------------------------------------------------------------------------------
+Regression test #1
+-------------------------------------------------------------------------------
+Matchers.tests.cpp:<line number>
+...............................................................................
+
+Matchers.tests.cpp:<line number>: PASSED:
+  CHECK_THAT( actual, !UnorderedEquals(expected) )
+with expansion:
+  { 'a', 'b' } not UnorderedEquals: { 'c', 'b' }
+
+-------------------------------------------------------------------------------
 SUCCEED counts as a test pass
 -------------------------------------------------------------------------------
 Message.tests.cpp:<line number>
 ...............................................................................
 
-Message.tests.cpp:<line number>:
-PASSED:
+Message.tests.cpp:<line number>: PASSED:
 with message:
   this is a success
 
@@ -4501,19 +6447,17 @@
 Message.tests.cpp:<line number>
 ...............................................................................
 
-Message.tests.cpp:<line number>:
-PASSED:
+Message.tests.cpp:<line number>: PASSED:
 
 -------------------------------------------------------------------------------
 Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or
           methods
-     Given: No operations precede me
+      Given: No operations precede me
 -------------------------------------------------------------------------------
 BDD.tests.cpp:<line number>
 ...............................................................................
 
-BDD.tests.cpp:<line number>:
-PASSED:
+BDD.tests.cpp:<line number>: PASSED:
   REQUIRE( before == 0 )
 with expansion:
   0 == 0
@@ -4521,46 +6465,45 @@
 -------------------------------------------------------------------------------
 Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or
           methods
-     Given: No operations precede me
-      When: We get the count
-      Then: Subsequently values are higher
+      Given: No operations precede me
+       When: We get the count
+       Then: Subsequently values are higher
 -------------------------------------------------------------------------------
 BDD.tests.cpp:<line number>
 ...............................................................................
 
-BDD.tests.cpp:<line number>:
-PASSED:
+BDD.tests.cpp:<line number>: PASSED:
   REQUIRE( after > before )
 with expansion:
   1 > 0
 
 -------------------------------------------------------------------------------
 Scenario: Do that thing with the thing
-     Given: This stuff exists
-      When: I do this
-      Then: it should do this
+      Given: This stuff exists
+  And given: And some assumption
+       When: I do this
+       Then: it should do this
 -------------------------------------------------------------------------------
 BDD.tests.cpp:<line number>
 ...............................................................................
 
-BDD.tests.cpp:<line number>:
-PASSED:
+BDD.tests.cpp:<line number>: PASSED:
   REQUIRE( itDoesThis() )
 with expansion:
   true
 
 -------------------------------------------------------------------------------
 Scenario: Do that thing with the thing
-     Given: This stuff exists
-      When: I do this
-      Then: it should do this
-       And: do that
+      Given: This stuff exists
+  And given: And some assumption
+       When: I do this
+       Then: it should do this
+        And: do that
 -------------------------------------------------------------------------------
 BDD.tests.cpp:<line number>
 ...............................................................................
 
-BDD.tests.cpp:<line number>:
-PASSED:
+BDD.tests.cpp:<line number>: PASSED:
   REQUIRE( itDoesThat() )
 with expansion:
   true
@@ -4568,108 +6511,99 @@
 -------------------------------------------------------------------------------
 Scenario: This is a really long scenario name to see how the list command deals
           with wrapping
-     Given: A section name that is so long that it cannot fit in a single
-            console width
-      When: The test headers are printed as part of the normal running of the
-            scenario
-      Then: The, deliberately very long and overly verbose (you see what I did
-            there?) section names must wrap, along with an indent
+      Given: A section name that is so long that it cannot fit in a single
+             console width
+       When: The test headers are printed as part of the normal running of the
+             scenario
+       Then: The, deliberately very long and overly verbose (you see what I did
+             there?) section names must wrap, along with an indent
 -------------------------------------------------------------------------------
 BDD.tests.cpp:<line number>
 ...............................................................................
 
-BDD.tests.cpp:<line number>:
-PASSED:
+BDD.tests.cpp:<line number>: PASSED:
 with message:
   boo!
 
 -------------------------------------------------------------------------------
 Scenario: Vector resizing affects size and capacity
-     Given: an empty vector
+      Given: an empty vector
 -------------------------------------------------------------------------------
 BDD.tests.cpp:<line number>
 ...............................................................................
 
-BDD.tests.cpp:<line number>:
-PASSED:
+BDD.tests.cpp:<line number>: PASSED:
   REQUIRE( v.size() == 0 )
 with expansion:
   0 == 0
 
 -------------------------------------------------------------------------------
 Scenario: Vector resizing affects size and capacity
-     Given: an empty vector
-      When: it is made larger
-      Then: the size and capacity go up
+      Given: an empty vector
+       When: it is made larger
+       Then: the size and capacity go up
 -------------------------------------------------------------------------------
 BDD.tests.cpp:<line number>
 ...............................................................................
 
-BDD.tests.cpp:<line number>:
-PASSED:
+BDD.tests.cpp:<line number>: PASSED:
   REQUIRE( v.size() == 10 )
 with expansion:
   10 == 10
 
-BDD.tests.cpp:<line number>:
-PASSED:
+BDD.tests.cpp:<line number>: PASSED:
   REQUIRE( v.capacity() >= 10 )
 with expansion:
   10 >= 10
 
 -------------------------------------------------------------------------------
 Scenario: Vector resizing affects size and capacity
-     Given: an empty vector
-      When: it is made larger
-      Then: the size and capacity go up
-  And when: it is made smaller again
-      Then: the size goes down but the capacity stays the same
+      Given: an empty vector
+       When: it is made larger
+       Then: the size and capacity go up
+   And when: it is made smaller again
+       Then: the size goes down but the capacity stays the same
 -------------------------------------------------------------------------------
 BDD.tests.cpp:<line number>
 ...............................................................................
 
-BDD.tests.cpp:<line number>:
-PASSED:
+BDD.tests.cpp:<line number>: PASSED:
   REQUIRE( v.size() == 5 )
 with expansion:
   5 == 5
 
-BDD.tests.cpp:<line number>:
-PASSED:
+BDD.tests.cpp:<line number>: PASSED:
   REQUIRE( v.capacity() >= 10 )
 with expansion:
   10 >= 10
 
 -------------------------------------------------------------------------------
 Scenario: Vector resizing affects size and capacity
-     Given: an empty vector
+      Given: an empty vector
 -------------------------------------------------------------------------------
 BDD.tests.cpp:<line number>
 ...............................................................................
 
-BDD.tests.cpp:<line number>:
-PASSED:
+BDD.tests.cpp:<line number>: PASSED:
   REQUIRE( v.size() == 0 )
 with expansion:
   0 == 0
 
 -------------------------------------------------------------------------------
 Scenario: Vector resizing affects size and capacity
-     Given: an empty vector
-      When: we reserve more space
-      Then: The capacity is increased but the size remains the same
+      Given: an empty vector
+       When: we reserve more space
+       Then: The capacity is increased but the size remains the same
 -------------------------------------------------------------------------------
 BDD.tests.cpp:<line number>
 ...............................................................................
 
-BDD.tests.cpp:<line number>:
-PASSED:
+BDD.tests.cpp:<line number>: PASSED:
   REQUIRE( v.capacity() >= 10 )
 with expansion:
   10 >= 10
 
-BDD.tests.cpp:<line number>:
-PASSED:
+BDD.tests.cpp:<line number>: PASSED:
   REQUIRE( v.size() == 0 )
 with expansion:
   0 == 0
@@ -4692,44 +6626,47 @@
 Approx.tests.cpp:<line number>
 ...............................................................................
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( d == Approx( 1.23 ) )
 with expansion:
   1.23 == Approx( 1.23 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( d != Approx( 1.22 ) )
 with expansion:
   1.23 != Approx( 1.22 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( d != Approx( 1.24 ) )
 with expansion:
   1.23 != Approx( 1.24 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
+  REQUIRE( d == 1.23_a )
+with expansion:
+  1.23 == Approx( 1.23 )
+
+Approx.tests.cpp:<line number>: PASSED:
+  REQUIRE( d != 1.22_a )
+with expansion:
+  1.23 != Approx( 1.22 )
+
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( Approx( d ) == 1.23 )
 with expansion:
   Approx( 1.23 ) == 1.23
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( Approx( d ) != 1.22 )
 with expansion:
   Approx( 1.23 ) != 1.22
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( Approx( d ) != 1.24 )
 with expansion:
   Approx( 1.23 ) != 1.24
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( INFINITY == Approx(INFINITY) )
 with expansion:
   inff == Approx( inf )
@@ -4780,8 +6717,7 @@
 ToStringGeneral.tests.cpp:<line number>
 ...............................................................................
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   REQUIRE( Catch::Detail::stringify(singular) == "{ 1 }" )
 with expansion:
   "{ 1 }" == "{ 1 }"
@@ -4793,8 +6729,7 @@
 ToStringGeneral.tests.cpp:<line number>
 ...............................................................................
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   REQUIRE( Catch::Detail::stringify(arr) == "{ 3, 2, 1 }" )
 with expansion:
   "{ 3, 2, 1 }" == "{ 3, 2, 1 }"
@@ -4806,8 +6741,7 @@
 ToStringGeneral.tests.cpp:<line number>
 ...............................................................................
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   REQUIRE( Catch::Detail::stringify(arr) == R"({ { "1:1", "1:2", "1:3" }, { "2:1", "2:2" } })" )
 with expansion:
   "{ { "1:1", "1:2", "1:3" }, { "2:1", "2:2" } }"
@@ -4820,53 +6754,45 @@
 Matchers.tests.cpp:<line number>
 ...............................................................................
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( testStringForMatching(), Contains("string") )
 with expansion:
   "this string contains 'abc' as a substring" contains: "string"
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( testStringForMatching(), Contains("string", Catch::CaseSensitive::No) )
 with expansion:
   "this string contains 'abc' as a substring" contains: "string" (case
   insensitive)
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( testStringForMatching(), Contains("abc") )
 with expansion:
   "this string contains 'abc' as a substring" contains: "abc"
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( testStringForMatching(), Contains("aBC", Catch::CaseSensitive::No) )
 with expansion:
-  "this string contains 'abc' as a substring" contains: "abc" (case insensitive)
+  "this string contains 'abc' as a substring" contains: "abc" (case
   insensitive)
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( testStringForMatching(), StartsWith("this") )
 with expansion:
   "this string contains 'abc' as a substring" starts with: "this"
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( testStringForMatching(), StartsWith("THIS", Catch::CaseSensitive::No) )
 with expansion:
   "this string contains 'abc' as a substring" starts with: "this" (case
   insensitive)
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( testStringForMatching(), EndsWith("substring") )
 with expansion:
   "this string contains 'abc' as a substring" ends with: "substring"
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( testStringForMatching(), EndsWith(" SuBsTrInG", Catch::CaseSensitive::No) )
 with expansion:
   "this string contains 'abc' as a substring" ends with: " substring" (case
@@ -4879,20 +6805,17 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( empty.empty() )
 with expansion:
   true
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( empty.size() == 0 )
 with expansion:
   0 == 0
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( std::strcmp( empty.c_str(), "" ) == 0 )
 with expansion:
   0 == 0
@@ -4904,26 +6827,22 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( s.empty() == false )
 with expansion:
   false == false
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( s.size() == 5 )
 with expansion:
   5 == 5
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( isSubstring( s ) == false )
 with expansion:
   false == false
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( std::strcmp( rawChars, "hello" ) == 0 )
 with expansion:
   0 == 0
@@ -4936,20 +6855,17 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( isOwned( s ) == false )
 with expansion:
   false == false
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( s.c_str() == rawChars )
 with expansion:
   "hello" == "hello"
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( isOwned( s ) == false )
 with expansion:
   false == false
@@ -4961,14 +6877,28 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( original == "original" )
 
-String.tests.cpp:<line number>: FAILED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( isSubstring( original ) )
 with expansion:
-  false
+  true
+
+String.tests.cpp:<line number>: PASSED:
+  REQUIRE( isOwned( original ) == false )
+with expansion:
+  false == false
+
+String.tests.cpp:<line number>: PASSED:
+  REQUIRE( isSubstring( original ) == false )
+with expansion:
+  false == false
+
+String.tests.cpp:<line number>: PASSED:
+  REQUIRE( isOwned( original ) )
+with expansion:
+  true
 
 -------------------------------------------------------------------------------
 StringRef
@@ -4978,26 +6908,22 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( ss.empty() == false )
 with expansion:
   false == false
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( ss.size() == 5 )
 with expansion:
   5 == 5
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( std::strcmp( ss.c_str(), "hello" ) == 0 )
 with expansion:
   0 == 0
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( ss == "hello" )
 with expansion:
   hello == "hello"
@@ -5010,45 +6936,38 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( isSubstring( ss ) )
 with expansion:
   true
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( isOwned( ss ) == false )
 with expansion:
   false == false
 
-String.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( rawChars == data( s ) )
+String.tests.cpp:<line number>: PASSED:
+  REQUIRE( rawChars == s.currentData() )
 with expansion:
   "hello world!" == "hello world!"
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( ss.c_str() != rawChars )
 with expansion:
   "hello" != "hello world!"
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( isSubstring( ss ) == false )
 with expansion:
   false == false
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( isOwned( ss ) )
 with expansion:
   true
 
-String.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( data( ss ) != data( s ) )
+String.tests.cpp:<line number>: PASSED:
+  REQUIRE( ss.currentData() != s.currentData() )
 with expansion:
   "hello" != "hello world!"
 
@@ -5060,14 +6979,12 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( ss.size() == 6 )
 with expansion:
   6 == 6
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( std::strcmp( ss.c_str(), "world!" ) == 0 )
 with expansion:
   0 == 0
@@ -5080,8 +6997,7 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( s.c_str() == s2.c_str() )
 with expansion:
   "hello world!" == "hello world!"
@@ -5094,8 +7010,7 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( s.c_str() != ss.c_str() )
 with expansion:
   "hello world!" != "hello"
@@ -5107,14 +7022,12 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( StringRef("hello") == StringRef("hello") )
 with expansion:
   hello == hello
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( StringRef("hello") != StringRef("cello") )
 with expansion:
   hello != cello
@@ -5127,14 +7040,12 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( sr == "a standard string" )
 with expansion:
   a standard string == "a standard string"
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( sr.size() == stdStr.size() )
 with expansion:
   17 == 17
@@ -5147,14 +7058,12 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( sr == "a standard string" )
 with expansion:
   a standard string == "a standard string"
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( sr.size() == stdStr.size() )
 with expansion:
   17 == 17
@@ -5167,14 +7076,12 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( sr == "a standard string" )
 with expansion:
   a standard string == "a standard string"
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( sr.size() == stdStr.size() )
 with expansion:
   17 == 17
@@ -5187,14 +7094,12 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( stdStr == "a stringref" )
 with expansion:
   "a stringref" == "a stringref"
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( stdStr.size() == sr.size() )
 with expansion:
   11 == 11
@@ -5207,14 +7112,12 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( stdStr == "a stringref" )
 with expansion:
   "a stringref" == "a stringref"
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( stdStr.size() == sr.size() )
 with expansion:
   11 == 11
@@ -5227,44 +7130,60 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( stdStr == "a stringref" )
 with expansion:
   "a stringref" == "a stringref"
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   REQUIRE( stdStr.size() == sr.size() )
 with expansion:
   11 == 11
 
 -------------------------------------------------------------------------------
+StringRef
+  Counting utf-8 codepoints
+-------------------------------------------------------------------------------
+String.tests.cpp:<line number>
+...............................................................................
+
+String.tests.cpp:<line number>: PASSED:
+  REQUIRE( ascii.numberOfCharacters() == ascii.size() )
+with expansion:
+  39 == 39
+
+String.tests.cpp:<line number>: PASSED:
+  REQUIRE( simpleu8.numberOfCharacters() == 30 )
+with expansion:
+  30 == 30
+
+String.tests.cpp:<line number>: PASSED:
+  REQUIRE( emojis.numberOfCharacters() == 9 )
+with expansion:
+  9 == 9
+
+-------------------------------------------------------------------------------
 Stringifying std::chrono::duration helpers
 -------------------------------------------------------------------------------
 ToStringChrono.tests.cpp:<line number>
 ...............................................................................
 
-ToStringChrono.tests.cpp:<line number>:
-PASSED:
+ToStringChrono.tests.cpp:<line number>: PASSED:
   REQUIRE( minute == seconds )
 with expansion:
   1 m == 60 s
 
-ToStringChrono.tests.cpp:<line number>:
-PASSED:
+ToStringChrono.tests.cpp:<line number>: PASSED:
   REQUIRE( hour != seconds )
 with expansion:
   1 h != 60 s
 
-ToStringChrono.tests.cpp:<line number>:
-PASSED:
+ToStringChrono.tests.cpp:<line number>: PASSED:
   REQUIRE( micro != milli )
 with expansion:
   1 us != 1 ms
 
-ToStringChrono.tests.cpp:<line number>:
-PASSED:
+ToStringChrono.tests.cpp:<line number>: PASSED:
   REQUIRE( nano != micro )
 with expansion:
   1 ns != 1 us
@@ -5275,14 +7194,12 @@
 ToStringChrono.tests.cpp:<line number>
 ...............................................................................
 
-ToStringChrono.tests.cpp:<line number>:
-PASSED:
+ToStringChrono.tests.cpp:<line number>: PASSED:
   REQUIRE( half_minute != femto_second )
 with expansion:
   1 [30/1]s != 1 fs
 
-ToStringChrono.tests.cpp:<line number>:
-PASSED:
+ToStringChrono.tests.cpp:<line number>: PASSED:
   REQUIRE( pico_second != atto_second )
 with expansion:
   1 ps != 1 as
@@ -5293,8 +7210,7 @@
 ToStringChrono.tests.cpp:<line number>
 ...............................................................................
 
-ToStringChrono.tests.cpp:<line number>:
-PASSED:
+ToStringChrono.tests.cpp:<line number>: PASSED:
   REQUIRE( now != later )
 with expansion:
   {iso8601-timestamp}
@@ -5326,32 +7242,28 @@
 TagAlias.tests.cpp:<line number>
 ...............................................................................
 
-TagAlias.tests.cpp:<line number>:
-PASSED:
+TagAlias.tests.cpp:<line number>: PASSED:
   CHECK_THAT( what, Contains( "[@zzz]" ) )
 with expansion:
   "error: tag alias, '[@zzz]' already registered.
   	First seen at: file:2
   	Redefined at: file:10" contains: "[@zzz]"
 
-TagAlias.tests.cpp:<line number>:
-PASSED:
+TagAlias.tests.cpp:<line number>: PASSED:
   CHECK_THAT( what, Contains( "file" ) )
 with expansion:
   "error: tag alias, '[@zzz]' already registered.
   	First seen at: file:2
   	Redefined at: file:10" contains: "file"
 
-TagAlias.tests.cpp:<line number>:
-PASSED:
+TagAlias.tests.cpp:<line number>: PASSED:
   CHECK_THAT( what, Contains( "2" ) )
 with expansion:
   "error: tag alias, '[@zzz]' already registered.
   	First seen at: file:2
   	Redefined at: file:10" contains: "2"
 
-TagAlias.tests.cpp:<line number>:
-PASSED:
+TagAlias.tests.cpp:<line number>: PASSED:
   CHECK_THAT( what, Contains( "10" ) )
 with expansion:
   "error: tag alias, '[@zzz]' already registered.
@@ -5365,30 +7277,605 @@
 TagAlias.tests.cpp:<line number>
 ...............................................................................
 
-TagAlias.tests.cpp:<line number>:
-PASSED:
+TagAlias.tests.cpp:<line number>: PASSED:
   CHECK_THROWS( registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) )
 
-TagAlias.tests.cpp:<line number>:
-PASSED:
+TagAlias.tests.cpp:<line number>: PASSED:
   CHECK_THROWS( registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) )
 
-TagAlias.tests.cpp:<line number>:
-PASSED:
+TagAlias.tests.cpp:<line number>: PASSED:
   CHECK_THROWS( registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) )
 
-TagAlias.tests.cpp:<line number>:
-PASSED:
+TagAlias.tests.cpp:<line number>: PASSED:
   CHECK_THROWS( registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) )
 
 -------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - float
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - float
+  resizing bigger changes size and capacity
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 10 )
+with expansion:
+  10 == 10
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 10 )
+with expansion:
+  10 >= 10
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - float
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - float
+  resizing smaller changes size but not capacity
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 0 )
+with expansion:
+  0 == 0
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - float
+  resizing smaller changes size but not capacity
+  We can use the 'swap trick' to reset the capacity
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() == 0 )
+with expansion:
+  0 == 0
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - float
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - float
+  reserving bigger changes capacity but not size
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 10 )
+with expansion:
+  10 >= 10
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - float
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - float
+  reserving smaller does not change size or capacity
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - int
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - int
+  resizing bigger changes size and capacity
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 10 )
+with expansion:
+  10 == 10
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 10 )
+with expansion:
+  10 >= 10
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - int
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - int
+  resizing smaller changes size but not capacity
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 0 )
+with expansion:
+  0 == 0
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - int
+  resizing smaller changes size but not capacity
+  We can use the 'swap trick' to reset the capacity
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() == 0 )
+with expansion:
+  0 == 0
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - int
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - int
+  reserving bigger changes capacity but not size
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 10 )
+with expansion:
+  10 >= 10
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - int
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - int
+  reserving smaller does not change size or capacity
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - std::string
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - std::string
+  resizing bigger changes size and capacity
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 10 )
+with expansion:
+  10 == 10
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 10 )
+with expansion:
+  10 >= 10
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - std::string
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - std::string
+  resizing smaller changes size but not capacity
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 0 )
+with expansion:
+  0 == 0
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - std::string
+  resizing smaller changes size but not capacity
+  We can use the 'swap trick' to reset the capacity
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() == 0 )
+with expansion:
+  0 == 0
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - std::string
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - std::string
+  reserving bigger changes capacity but not size
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 10 )
+with expansion:
+  10 >= 10
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - std::string
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - std::string
+  reserving smaller does not change size or capacity
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - std::tuple<int,float>
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - std::tuple<int,float>
+  resizing bigger changes size and capacity
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 10 )
+with expansion:
+  10 == 10
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 10 )
+with expansion:
+  10 >= 10
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - std::tuple<int,float>
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - std::tuple<int,float>
+  resizing smaller changes size but not capacity
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 0 )
+with expansion:
+  0 == 0
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - std::tuple<int,float>
+  resizing smaller changes size but not capacity
+  We can use the 'swap trick' to reset the capacity
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() == 0 )
+with expansion:
+  0 == 0
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - std::tuple<int,float>
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - std::tuple<int,float>
+  reserving bigger changes capacity but not size
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 10 )
+with expansion:
+  10 >= 10
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - std::tuple<int,float>
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
+TemplateTest: vectors can be sized and resized - std::tuple<int,float>
+  reserving smaller does not change size or capacity
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.size() == 5 )
+with expansion:
+  5 == 5
+
+Misc.tests.cpp:<line number>: PASSED:
+  REQUIRE( v.capacity() >= 5 )
+with expansion:
+  5 >= 5
+
+-------------------------------------------------------------------------------
 Test case with one argument
 -------------------------------------------------------------------------------
 VariadicMacros.tests.cpp:<line number>
 ...............................................................................
 
-VariadicMacros.tests.cpp:<line number>:
-PASSED:
+VariadicMacros.tests.cpp:<line number>: PASSED:
 with message:
   no assertions
 
@@ -5398,8 +7885,7 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( 0x<hex digits> == bit30and31 )
 with expansion:
   3221225472 (0x<hex digits>) == 3221225472
@@ -5410,8 +7896,7 @@
 Message.tests.cpp:<line number>
 ...............................................................................
 
-Message.tests.cpp:<line number>:
-FAILED - but was ok:
+Message.tests.cpp:<line number>: FAILED - but was ok:
   CHECK_NOFAIL( 1 == 2 )
 
 
@@ -5423,25 +7908,32 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
 with message:
   oops!
 
 -------------------------------------------------------------------------------
+Thrown string literals are translated
+-------------------------------------------------------------------------------
+Exception.tests.cpp:<line number>
+...............................................................................
+
+Exception.tests.cpp:<line number>: FAILED:
+due to unexpected exception with message:
+  For some reason someone is throwing a string literal!
+
+-------------------------------------------------------------------------------
 Tracker
 -------------------------------------------------------------------------------
 PartTracker.tests.cpp:<line number>
 ...............................................................................
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase.isOpen() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s1.isOpen() )
 with expansion:
   true
@@ -5453,26 +7945,22 @@
 PartTracker.tests.cpp:<line number>
 ...............................................................................
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s1.isSuccessfullyCompleted() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase.isComplete() == false )
 with expansion:
   false == false
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( ctx.completedCycle() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase.isSuccessfullyCompleted() )
 with expansion:
   true
@@ -5483,14 +7971,12 @@
 PartTracker.tests.cpp:<line number>
 ...............................................................................
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase.isOpen() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s1.isOpen() )
 with expansion:
   true
@@ -5502,32 +7988,27 @@
 PartTracker.tests.cpp:<line number>
 ...............................................................................
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s1.isComplete() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s1.isSuccessfullyCompleted() == false )
 with expansion:
   false == false
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase.isComplete() == false )
 with expansion:
   false == false
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( ctx.completedCycle() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase.isSuccessfullyCompleted() == false )
 with expansion:
   false == false
@@ -5540,32 +8021,27 @@
 PartTracker.tests.cpp:<line number>
 ...............................................................................
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase2.isOpen() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s1b.isOpen() == false )
 with expansion:
   false == false
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( ctx.completedCycle() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase.isComplete() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase.isSuccessfullyCompleted() )
 with expansion:
   true
@@ -5576,14 +8052,12 @@
 PartTracker.tests.cpp:<line number>
 ...............................................................................
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase.isOpen() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s1.isOpen() )
 with expansion:
   true
@@ -5595,32 +8069,27 @@
 PartTracker.tests.cpp:<line number>
 ...............................................................................
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s1.isComplete() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s1.isSuccessfullyCompleted() == false )
 with expansion:
   false == false
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase.isComplete() == false )
 with expansion:
   false == false
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( ctx.completedCycle() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase.isSuccessfullyCompleted() == false )
 with expansion:
   false == false
@@ -5633,38 +8102,32 @@
 PartTracker.tests.cpp:<line number>
 ...............................................................................
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase2.isOpen() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s1b.isOpen() == false )
 with expansion:
   false == false
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s2.isOpen() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( ctx.completedCycle() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase.isComplete() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase.isSuccessfullyCompleted() )
 with expansion:
   true
@@ -5675,14 +8138,12 @@
 PartTracker.tests.cpp:<line number>
 ...............................................................................
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase.isOpen() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s1.isOpen() )
 with expansion:
   true
@@ -5694,14 +8155,12 @@
 PartTracker.tests.cpp:<line number>
 ...............................................................................
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s2.isOpen() == false )
 with expansion:
   false == false
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase.isComplete() == false )
 with expansion:
   false == false
@@ -5714,26 +8173,22 @@
 PartTracker.tests.cpp:<line number>
 ...............................................................................
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase2.isOpen() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s1b.isOpen() == false )
 with expansion:
   false == false
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s2b.isOpen() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( ctx.completedCycle() == false )
 with expansion:
   false == false
@@ -5747,26 +8202,22 @@
 PartTracker.tests.cpp:<line number>
 ...............................................................................
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( ctx.completedCycle() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s2b.isSuccessfullyCompleted() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase2.isComplete() == false )
 with expansion:
   false == false
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase2.isSuccessfullyCompleted() )
 with expansion:
   true
@@ -5777,14 +8228,12 @@
 PartTracker.tests.cpp:<line number>
 ...............................................................................
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase.isOpen() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s1.isOpen() )
 with expansion:
   true
@@ -5796,14 +8245,12 @@
 PartTracker.tests.cpp:<line number>
 ...............................................................................
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s2.isOpen() == false )
 with expansion:
   false == false
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase.isComplete() == false )
 with expansion:
   false == false
@@ -5816,26 +8263,22 @@
 PartTracker.tests.cpp:<line number>
 ...............................................................................
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase2.isOpen() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s1b.isOpen() == false )
 with expansion:
   false == false
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s2b.isOpen() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( ctx.completedCycle() == false )
 with expansion:
   false == false
@@ -5849,50 +8292,42 @@
 PartTracker.tests.cpp:<line number>
 ...............................................................................
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( ctx.completedCycle() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s2b.isComplete() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s2b.isSuccessfullyCompleted() == false )
 with expansion:
   false == false
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase2.isSuccessfullyCompleted() == false )
 with expansion:
   false == false
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase3.isOpen() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s1c.isOpen() == false )
 with expansion:
   false == false
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s2c.isOpen() == false )
 with expansion:
   false == false
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase3.isSuccessfullyCompleted() )
 with expansion:
   true
@@ -5903,14 +8338,12 @@
 PartTracker.tests.cpp:<line number>
 ...............................................................................
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase.isOpen() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s1.isOpen() )
 with expansion:
   true
@@ -5922,511 +8355,37 @@
 PartTracker.tests.cpp:<line number>
 ...............................................................................
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s2.isOpen() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s2.isComplete() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s1.isComplete() == false )
 with expansion:
   false == false
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( s1.isComplete() )
 with expansion:
   true
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase.isComplete() == false )
 with expansion:
   false == false
 
-PartTracker.tests.cpp:<line number>:
-PASSED:
+PartTracker.tests.cpp:<line number>: PASSED:
   REQUIRE( testCase.isComplete() )
 with expansion:
   true
 
 -------------------------------------------------------------------------------
-Tracker
--------------------------------------------------------------------------------
-PartTracker.tests.cpp:<line number>
-...............................................................................
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( testCase.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s1.isOpen() )
-with expansion:
-  true
-
--------------------------------------------------------------------------------
-Tracker
-  start a generator
--------------------------------------------------------------------------------
-PartTracker.tests.cpp:<line number>
-...............................................................................
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( g1.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( g1.index() == 0 )
-with expansion:
-  0 == 0
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( g1.isComplete() == false )
-with expansion:
-  false == false
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s1.isComplete() == false )
-with expansion:
-  false == false
-
--------------------------------------------------------------------------------
-Tracker
-  start a generator
-  close outer section
--------------------------------------------------------------------------------
-PartTracker.tests.cpp:<line number>
-...............................................................................
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s1.isComplete() == false )
-with expansion:
-  false == false
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( testCase.isSuccessfullyCompleted() == false )
-with expansion:
-  false == false
-
--------------------------------------------------------------------------------
-Tracker
-  start a generator
-  close outer section
-  Re-enter for second generation
--------------------------------------------------------------------------------
-PartTracker.tests.cpp:<line number>
-...............................................................................
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( testCase2.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s1b.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( g1b.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( g1b.index() == 1 )
-with expansion:
-  1 == 1
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s1.isComplete() == false )
-with expansion:
-  false == false
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s1b.isComplete() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( g1b.isComplete() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( testCase2.isComplete() )
-with expansion:
-  true
-
--------------------------------------------------------------------------------
-Tracker
--------------------------------------------------------------------------------
-PartTracker.tests.cpp:<line number>
-...............................................................................
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( testCase.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s1.isOpen() )
-with expansion:
-  true
-
--------------------------------------------------------------------------------
-Tracker
-  start a generator
--------------------------------------------------------------------------------
-PartTracker.tests.cpp:<line number>
-...............................................................................
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( g1.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( g1.index() == 0 )
-with expansion:
-  0 == 0
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( g1.isComplete() == false )
-with expansion:
-  false == false
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s1.isComplete() == false )
-with expansion:
-  false == false
-
--------------------------------------------------------------------------------
-Tracker
-  start a generator
-  Start a new inner section
--------------------------------------------------------------------------------
-PartTracker.tests.cpp:<line number>
-...............................................................................
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s2.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s2.isComplete() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s1.isComplete() == false )
-with expansion:
-  false == false
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( testCase.isComplete() == false )
-with expansion:
-  false == false
-
--------------------------------------------------------------------------------
-Tracker
-  start a generator
-  Start a new inner section
-  Re-enter for second generation
--------------------------------------------------------------------------------
-PartTracker.tests.cpp:<line number>
-...............................................................................
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( testCase2.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s1b.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( g1b.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( g1b.index() == 1 )
-with expansion:
-  1 == 1
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s2b.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s2b.isComplete() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( g1b.isComplete() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s1b.isComplete() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( testCase2.isComplete() )
-with expansion:
-  true
-
--------------------------------------------------------------------------------
-Tracker
--------------------------------------------------------------------------------
-PartTracker.tests.cpp:<line number>
-...............................................................................
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( testCase.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s1.isOpen() )
-with expansion:
-  true
-
--------------------------------------------------------------------------------
-Tracker
-  start a generator
--------------------------------------------------------------------------------
-PartTracker.tests.cpp:<line number>
-...............................................................................
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( g1.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( g1.index() == 0 )
-with expansion:
-  0 == 0
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( g1.isComplete() == false )
-with expansion:
-  false == false
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s1.isComplete() == false )
-with expansion:
-  false == false
-
--------------------------------------------------------------------------------
-Tracker
-  start a generator
-  Fail an inner section
--------------------------------------------------------------------------------
-PartTracker.tests.cpp:<line number>
-...............................................................................
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s2.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s2.isComplete() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s2.isSuccessfullyCompleted() == false )
-with expansion:
-  false == false
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s1.isComplete() == false )
-with expansion:
-  false == false
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( testCase.isComplete() == false )
-with expansion:
-  false == false
-
--------------------------------------------------------------------------------
-Tracker
-  start a generator
-  Fail an inner section
-  Re-enter for second generation
--------------------------------------------------------------------------------
-PartTracker.tests.cpp:<line number>
-...............................................................................
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( testCase2.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s1b.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( g1b.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( g1b.index() == 0 )
-with expansion:
-  0 == 0
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s2b.isOpen() == false )
-with expansion:
-  false == false
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( g1b.isComplete() == false )
-with expansion:
-  false == false
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s1b.isComplete() == false )
-with expansion:
-  false == false
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( testCase2.isComplete() == false )
-with expansion:
-  false == false
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( testCase3.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s1c.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( g1c.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( g1c.index() == 1 )
-with expansion:
-  1 == 1
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s2c.isOpen() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s2c.isComplete() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( g1c.isComplete() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( s1c.isComplete() )
-with expansion:
-  true
-
-PartTracker.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( testCase3.isComplete() )
-with expansion:
-  true
-
--------------------------------------------------------------------------------
 Unexpected exceptions can be translated
 -------------------------------------------------------------------------------
 Exception.tests.cpp:<line number>
@@ -6442,50 +8401,42 @@
 Approx.tests.cpp:<line number>
 ...............................................................................
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( d == approx( 1.23 ) )
 with expansion:
   1.23 == Approx( 1.23 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( d == approx( 1.22 ) )
 with expansion:
   1.23 == Approx( 1.22 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( d == approx( 1.24 ) )
 with expansion:
   1.23 == Approx( 1.24 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( d != approx( 1.25 ) )
 with expansion:
   1.23 != Approx( 1.25 )
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( approx( d ) == 1.23 )
 with expansion:
   Approx( 1.23 ) == 1.23
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( approx( d ) == 1.22 )
 with expansion:
   Approx( 1.23 ) == 1.22
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( approx( d ) == 1.24 )
 with expansion:
   Approx( 1.23 ) == 1.24
 
-Approx.tests.cpp:<line number>:
-PASSED:
+Approx.tests.cpp:<line number>: PASSED:
   REQUIRE( approx( d ) != 1.25 )
 with expansion:
   Approx( 1.23 ) != 1.25
@@ -6497,8 +8448,7 @@
 VariadicMacros.tests.cpp:<line number>
 ...............................................................................
 
-VariadicMacros.tests.cpp:<line number>:
-PASSED:
+VariadicMacros.tests.cpp:<line number>: PASSED:
 with message:
   no assertions
 
@@ -6509,14 +8459,12 @@
 Matchers.tests.cpp:<line number>
 ...............................................................................
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( v, VectorContains(1) )
 with expansion:
   { 1, 2, 3 } Contains: 1
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( v, VectorContains(2) )
 with expansion:
   { 1, 2, 3 } Contains: 2
@@ -6528,26 +8476,22 @@
 Matchers.tests.cpp:<line number>
 ...............................................................................
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( v, Contains(v2) )
 with expansion:
   { 1, 2, 3 } Contains: { 1, 2 }
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( v, Contains(v2) )
 with expansion:
   { 1, 2, 3 } Contains: { 1, 2, 3 }
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( v, Contains(empty) )
 with expansion:
   { 1, 2, 3 } Contains: {  }
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( empty, Contains(empty) )
 with expansion:
   {  } Contains: {  }
@@ -6559,8 +8503,7 @@
 Matchers.tests.cpp:<line number>
 ...............................................................................
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( v, VectorContains(1) && VectorContains(2) )
 with expansion:
   { 1, 2, 3 } ( Contains: 1 and Contains: 2 )
@@ -6572,20 +8515,17 @@
 Matchers.tests.cpp:<line number>
 ...............................................................................
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( v, Equals(v) )
 with expansion:
   { 1, 2, 3 } Equals: { 1, 2, 3 }
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( empty, Equals(empty) )
 with expansion:
   {  } Equals: {  }
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( v, Equals(v2) )
 with expansion:
   { 1, 2, 3 } Equals: { 1, 2, 3 }
@@ -6597,26 +8537,22 @@
 Matchers.tests.cpp:<line number>
 ...............................................................................
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( v, UnorderedEquals(v) )
 with expansion:
   { 1, 2, 3 } UnorderedEquals: { 1, 2, 3 }
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   CHECK_THAT( empty, UnorderedEquals(empty) )
 with expansion:
   {  } UnorderedEquals: {  }
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( permuted, UnorderedEquals(v) )
 with expansion:
   { 1, 3, 2 } UnorderedEquals: { 1, 2, 3 }
 
-Matchers.tests.cpp:<line number>:
-PASSED:
+Matchers.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( permuted, UnorderedEquals(v) )
 with expansion:
   { 2, 3, 1 } UnorderedEquals: { 1, 2, 3 }
@@ -6715,16 +8651,13 @@
 Exception.tests.cpp:<line number>
 ...............................................................................
 
-Exception.tests.cpp:<line number>:
-PASSED:
+Exception.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS_AS( thisThrows(), std::domain_error )
 
-Exception.tests.cpp:<line number>:
-PASSED:
+Exception.tests.cpp:<line number>: PASSED:
   REQUIRE_NOTHROW( thisDoesntThrow() )
 
-Exception.tests.cpp:<line number>:
-PASSED:
+Exception.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS( thisThrows() )
 
 -------------------------------------------------------------------------------
@@ -6797,8 +8730,7 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-warning:
+Tricky.tests.cpp:<line number>: warning:
   Uncomment the code in this test to check that it gives a sensible compiler
   error
 
@@ -6811,8 +8743,7 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-warning:
+Tricky.tests.cpp:<line number>: warning:
   Uncomment the code in this test to check that it gives a sensible compiler
   error
 
@@ -6825,8 +8756,7 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
 
 -------------------------------------------------------------------------------
 X/level/0/b
@@ -6834,8 +8764,7 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
 
 -------------------------------------------------------------------------------
 X/level/1/a
@@ -6843,8 +8772,7 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
 
 -------------------------------------------------------------------------------
 X/level/1/b
@@ -6852,8 +8780,7 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
 
 -------------------------------------------------------------------------------
 XmlEncode
@@ -6862,8 +8789,7 @@
 Xml.tests.cpp:<line number>
 ...............................................................................
 
-Xml.tests.cpp:<line number>:
-PASSED:
+Xml.tests.cpp:<line number>: PASSED:
   REQUIRE( encode( "normal string" ) == "normal string" )
 with expansion:
   "normal string" == "normal string"
@@ -6875,8 +8801,7 @@
 Xml.tests.cpp:<line number>
 ...............................................................................
 
-Xml.tests.cpp:<line number>:
-PASSED:
+Xml.tests.cpp:<line number>: PASSED:
   REQUIRE( encode( "" ) == "" )
 with expansion:
   "" == ""
@@ -6888,8 +8813,7 @@
 Xml.tests.cpp:<line number>
 ...............................................................................
 
-Xml.tests.cpp:<line number>:
-PASSED:
+Xml.tests.cpp:<line number>: PASSED:
   REQUIRE( encode( "smith & jones" ) == "smith &amp; jones" )
 with expansion:
   "smith &amp; jones" == "smith &amp; jones"
@@ -6901,8 +8825,7 @@
 Xml.tests.cpp:<line number>
 ...............................................................................
 
-Xml.tests.cpp:<line number>:
-PASSED:
+Xml.tests.cpp:<line number>: PASSED:
   REQUIRE( encode( "smith < jones" ) == "smith &lt; jones" )
 with expansion:
   "smith &lt; jones" == "smith &lt; jones"
@@ -6914,14 +8837,12 @@
 Xml.tests.cpp:<line number>
 ...............................................................................
 
-Xml.tests.cpp:<line number>:
-PASSED:
+Xml.tests.cpp:<line number>: PASSED:
   REQUIRE( encode( "smith > jones" ) == "smith > jones" )
 with expansion:
   "smith > jones" == "smith > jones"
 
-Xml.tests.cpp:<line number>:
-PASSED:
+Xml.tests.cpp:<line number>: PASSED:
   REQUIRE( encode( "smith ]]> jones" ) == "smith ]]&gt; jones" )
 with expansion:
   "smith ]]&gt; jones"
@@ -6935,16 +8856,14 @@
 Xml.tests.cpp:<line number>
 ...............................................................................
 
-Xml.tests.cpp:<line number>:
-PASSED:
+Xml.tests.cpp:<line number>: PASSED:
   REQUIRE( encode( stringWithQuotes ) == stringWithQuotes )
 with expansion:
   "don't "quote" me on that"
   ==
   "don't "quote" me on that"
 
-Xml.tests.cpp:<line number>:
-PASSED:
+Xml.tests.cpp:<line number>: PASSED:
   REQUIRE( encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't &quot;quote&quot; me on that" )
 with expansion:
   "don't &quot;quote&quot; me on that"
@@ -6958,8 +8877,7 @@
 Xml.tests.cpp:<line number>
 ...............................................................................
 
-Xml.tests.cpp:<line number>:
-PASSED:
+Xml.tests.cpp:<line number>: PASSED:
   REQUIRE( encode( "[\x01]" ) == "[\\x01]" )
 with expansion:
   "[\x01]" == "[\x01]"
@@ -6971,32 +8889,285 @@
 Xml.tests.cpp:<line number>
 ...............................................................................
 
-Xml.tests.cpp:<line number>:
-PASSED:
+Xml.tests.cpp:<line number>: PASSED:
   REQUIRE( encode( "[\x7F]" ) == "[\\x7F]" )
 with expansion:
   "[\x7F]" == "[\x7F]"
 
 -------------------------------------------------------------------------------
+XmlEncode: UTF-8
+  Valid utf-8 strings
+-------------------------------------------------------------------------------
+Xml.tests.cpp:<line number>
+...............................................................................
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode(u8"Here be 👾") == u8"Here be 👾" )
+with expansion:
+  "Here be 👾" == "Here be 👾"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode(u8"šš") == u8"šš" )
+with expansion:
+  "šš" == "šš"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xDF\xBF") == "\xDF\xBF" )
+with expansion:
+  "߿" == "߿"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xE0\xA0\x80") == "\xE0\xA0\x80" )
+with expansion:
+  "ࠀ" == "ࠀ"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xED\x9F\xBF") == "\xED\x9F\xBF" )
+with expansion:
+  "퟿" == "퟿"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xEE\x80\x80") == "\xEE\x80\x80" )
+with expansion:
+  "" == ""
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xEF\xBF\xBF") == "\xEF\xBF\xBF" )
+with expansion:
+  "￿" == "￿"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xF0\x90\x80\x80") == "\xF0\x90\x80\x80" )
+with expansion:
+  "𐀀" == "𐀀"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xF4\x8F\xBF\xBF") == "\xF4\x8F\xBF\xBF" )
+with expansion:
+  "􏿿" == "􏿿"
+
+-------------------------------------------------------------------------------
+XmlEncode: UTF-8
+  Invalid utf-8 strings
+  Various broken strings
+-------------------------------------------------------------------------------
+Xml.tests.cpp:<line number>
+...............................................................................
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("Here \xFF be 👾") == u8"Here \\xFF be 👾" )
+with expansion:
+  "Here \xFF be 👾" == "Here \xFF be 👾"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xFF") == "\\xFF" )
+with expansion:
+  "\xFF" == "\xFF"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xC5\xC5\xA0") == u8"\\xC5Š" )
+with expansion:
+  "\xC5Š" == "\xC5Š"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xF4\x90\x80\x80") == u8"\\xF4\\x90\\x80\\x80" )
+with expansion:
+  "\xF4\x90\x80\x80" == "\xF4\x90\x80\x80"
+
+-------------------------------------------------------------------------------
+XmlEncode: UTF-8
+  Invalid utf-8 strings
+  Overlong encodings
+-------------------------------------------------------------------------------
+Xml.tests.cpp:<line number>
+...............................................................................
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xC0\x80") == u8"\\xC0\\x80" )
+with expansion:
+  "\xC0\x80" == "\xC0\x80"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xF0\x80\x80\x80") == u8"\\xF0\\x80\\x80\\x80" )
+with expansion:
+  "\xF0\x80\x80\x80" == "\xF0\x80\x80\x80"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xC1\xBF") == u8"\\xC1\\xBF" )
+with expansion:
+  "\xC1\xBF" == "\xC1\xBF"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xE0\x9F\xBF") == u8"\\xE0\\x9F\\xBF" )
+with expansion:
+  "\xE0\x9F\xBF" == "\xE0\x9F\xBF"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xF0\x8F\xBF\xBF") == u8"\\xF0\\x8F\\xBF\\xBF" )
+with expansion:
+  "\xF0\x8F\xBF\xBF" == "\xF0\x8F\xBF\xBF"
+
+-------------------------------------------------------------------------------
+XmlEncode: UTF-8
+  Invalid utf-8 strings
+  Surrogate pairs
+-------------------------------------------------------------------------------
+Xml.tests.cpp:<line number>
+...............................................................................
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xED\xA0\x80") == "\xED\xA0\x80" )
+with expansion:
+  "í €" == "í €"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xED\xAF\xBF") == "\xED\xAF\xBF" )
+with expansion:
+  "í¯¿" == "í¯¿"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xED\xB0\x80") == "\xED\xB0\x80" )
+with expansion:
+  "í°€" == "í°€"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xED\xBF\xBF") == "\xED\xBF\xBF" )
+with expansion:
+  "í¿¿" == "í¿¿"
+
+-------------------------------------------------------------------------------
+XmlEncode: UTF-8
+  Invalid utf-8 strings
+  Invalid start byte
+-------------------------------------------------------------------------------
+Xml.tests.cpp:<line number>
+...............................................................................
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\x80") == u8"\\x80" )
+with expansion:
+  "\x80" == "\x80"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\x81") == u8"\\x81" )
+with expansion:
+  "\x81" == "\x81"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xBC") == u8"\\xBC" )
+with expansion:
+  "\xBC" == "\xBC"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xBF") == u8"\\xBF" )
+with expansion:
+  "\xBF" == "\xBF"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xF5\x80\x80\x80") == u8"\\xF5\\x80\\x80\\x80" )
+with expansion:
+  "\xF5\x80\x80\x80" == "\xF5\x80\x80\x80"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xF6\x80\x80\x80") == u8"\\xF6\\x80\\x80\\x80" )
+with expansion:
+  "\xF6\x80\x80\x80" == "\xF6\x80\x80\x80"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xF7\x80\x80\x80") == u8"\\xF7\\x80\\x80\\x80" )
+with expansion:
+  "\xF7\x80\x80\x80" == "\xF7\x80\x80\x80"
+
+-------------------------------------------------------------------------------
+XmlEncode: UTF-8
+  Invalid utf-8 strings
+  Missing continuation byte(s)
+-------------------------------------------------------------------------------
+Xml.tests.cpp:<line number>
+...............................................................................
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xDE") == u8"\\xDE" )
+with expansion:
+  "\xDE" == "\xDE"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xDF") == u8"\\xDF" )
+with expansion:
+  "\xDF" == "\xDF"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xE0") == u8"\\xE0" )
+with expansion:
+  "\xE0" == "\xE0"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xEF") == u8"\\xEF" )
+with expansion:
+  "\xEF" == "\xEF"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xF0") == u8"\\xF0" )
+with expansion:
+  "\xF0" == "\xF0"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xF4") == u8"\\xF4" )
+with expansion:
+  "\xF4" == "\xF4"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xE0\x80") == u8"\\xE0\\x80" )
+with expansion:
+  "\xE0\x80" == "\xE0\x80"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xE0\xBF") == u8"\\xE0\\xBF" )
+with expansion:
+  "\xE0\xBF" == "\xE0\xBF"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xE1\x80") == u8"\\xE1\\x80" )
+with expansion:
+  "\xE1\x80" == "\xE1\x80"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xF0\x80") == u8"\\xF0\\x80" )
+with expansion:
+  "\xF0\x80" == "\xF0\x80"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xF4\x80") == u8"\\xF4\\x80" )
+with expansion:
+  "\xF4\x80" == "\xF4\x80"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xF0\x80\x80") == u8"\\xF0\\x80\\x80" )
+with expansion:
+  "\xF0\x80\x80" == "\xF0\x80\x80"
+
+Xml.tests.cpp:<line number>: PASSED:
+  CHECK( encode("\xF4\x80\x80") == u8"\\xF4\\x80\\x80" )
+with expansion:
+  "\xF4\x80\x80" == "\xF4\x80\x80"
+
+-------------------------------------------------------------------------------
 array<int, N> -> toString
 -------------------------------------------------------------------------------
 ToStringVector.tests.cpp:<line number>
 ...............................................................................
 
-ToStringVector.tests.cpp:<line number>:
-PASSED:
+ToStringVector.tests.cpp:<line number>: PASSED:
   REQUIRE( Catch::Detail::stringify( empty ) == "{  }" )
 with expansion:
   "{  }" == "{  }"
 
-ToStringVector.tests.cpp:<line number>:
-PASSED:
+ToStringVector.tests.cpp:<line number>: PASSED:
   REQUIRE( Catch::Detail::stringify( oneValue ) == "{ 42 }" )
 with expansion:
   "{ 42 }" == "{ 42 }"
 
-ToStringVector.tests.cpp:<line number>:
-PASSED:
+ToStringVector.tests.cpp:<line number>: PASSED:
   REQUIRE( Catch::Detail::stringify( twoValues ) == "{ 42, 250 }" )
 with expansion:
   "{ 42, 250 }" == "{ 42, 250 }"
@@ -7007,8 +9178,7 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( x == 0 )
 with expansion:
   0 == 0
@@ -7019,8 +9189,7 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( obj.prop != 0 )
 with expansion:
   0x<hex digits> != 0
@@ -7031,14 +9200,12 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   CHECKED_ELSE( flag )
 with expansion:
   true
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( testCheckedElse( true ) )
 with expansion:
   true
@@ -7065,14 +9232,12 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   CHECKED_IF( flag )
 with expansion:
   true
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( testCheckedIf( true ) )
 with expansion:
   true
@@ -7099,26 +9264,22 @@
 Condition.tests.cpp:<line number>
 ...............................................................................
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( unsigned_char_var == 1 )
 with expansion:
   1 == 1
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( unsigned_short_var == 1 )
 with expansion:
   1 == 1
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( unsigned_int_var == 1 )
 with expansion:
   1 == 1
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( unsigned_long_var == 1 )
 with expansion:
   1 == 1
@@ -7129,26 +9290,22 @@
 Condition.tests.cpp:<line number>
 ...............................................................................
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( long_var == unsigned_char_var )
 with expansion:
   1 == 1
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( long_var == unsigned_short_var )
 with expansion:
   1 == 1
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( long_var == unsigned_int_var )
 with expansion:
   1 == 1
 
-Condition.tests.cpp:<line number>:
-PASSED:
+Condition.tests.cpp:<line number>: PASSED:
   REQUIRE( long_var == unsigned_long_var )
 with expansion:
   1 == 1
@@ -7161,8 +9318,7 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
 
 -------------------------------------------------------------------------------
 even more nested SECTION tests
@@ -7172,8 +9328,7 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
 
 -------------------------------------------------------------------------------
 even more nested SECTION tests
@@ -7182,8 +9337,7 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
 
 -------------------------------------------------------------------------------
 first tag
@@ -7215,6 +9369,16 @@
   Previous info should not be seen
 
 -------------------------------------------------------------------------------
+just failure after unscoped info
+-------------------------------------------------------------------------------
+Message.tests.cpp:<line number>
+...............................................................................
+
+Message.tests.cpp:<line number>: FAILED:
+explicitly with message:
+  previous unscoped info SHOULD not be seen
+
+-------------------------------------------------------------------------------
 just info
 -------------------------------------------------------------------------------
 Message.tests.cpp:<line number>
@@ -7224,13 +9388,21 @@
 No assertions in test case 'just info'
 
 -------------------------------------------------------------------------------
+just unscoped info
+-------------------------------------------------------------------------------
+Message.tests.cpp:<line number>
+...............................................................................
+
+
+No assertions in test case 'just unscoped info'
+
+-------------------------------------------------------------------------------
 long long
 -------------------------------------------------------------------------------
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( l == std::numeric_limits<long long>::max() )
 with expansion:
   9223372036854775807 (0x<hex digits>)
@@ -7239,7 +9411,7 @@
 
 -------------------------------------------------------------------------------
 looped SECTION tests
-  s1
+  b is currently: 0
 -------------------------------------------------------------------------------
 Misc.tests.cpp:<line number>
 ...............................................................................
@@ -7250,6 +9422,114 @@
   0 > 1
 
 -------------------------------------------------------------------------------
+looped SECTION tests
+  b is currently: 1
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: FAILED:
+  CHECK( b > a )
+with expansion:
+  1 > 1
+
+-------------------------------------------------------------------------------
+looped SECTION tests
+  b is currently: 2
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  CHECK( b > a )
+with expansion:
+  2 > 1
+
+-------------------------------------------------------------------------------
+looped SECTION tests
+  b is currently: 3
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  CHECK( b > a )
+with expansion:
+  3 > 1
+
+-------------------------------------------------------------------------------
+looped SECTION tests
+  b is currently: 4
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  CHECK( b > a )
+with expansion:
+  4 > 1
+
+-------------------------------------------------------------------------------
+looped SECTION tests
+  b is currently: 5
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  CHECK( b > a )
+with expansion:
+  5 > 1
+
+-------------------------------------------------------------------------------
+looped SECTION tests
+  b is currently: 6
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  CHECK( b > a )
+with expansion:
+  6 > 1
+
+-------------------------------------------------------------------------------
+looped SECTION tests
+  b is currently: 7
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  CHECK( b > a )
+with expansion:
+  7 > 1
+
+-------------------------------------------------------------------------------
+looped SECTION tests
+  b is currently: 8
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  CHECK( b > a )
+with expansion:
+  8 > 1
+
+-------------------------------------------------------------------------------
+looped SECTION tests
+  b is currently: 9
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+  CHECK( b > a )
+with expansion:
+  9 > 1
+
+-------------------------------------------------------------------------------
 looped tests
 -------------------------------------------------------------------------------
 Misc.tests.cpp:<line number>
@@ -7269,8 +9549,7 @@
 with message:
   Testing if fib[1] (1) is even
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   CHECK( ( fib[i] % 2 ) == 0 )
 with expansion:
   0 == 0
@@ -7291,8 +9570,7 @@
 with message:
   Testing if fib[4] (5) is even
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   CHECK( ( fib[i] % 2 ) == 0 )
 with expansion:
   0 == 0
@@ -7314,9 +9592,28 @@
   Testing if fib[7] (21) is even
 
 -------------------------------------------------------------------------------
+mix info, unscoped info and warning
+-------------------------------------------------------------------------------
+Message.tests.cpp:<line number>
+...............................................................................
+
+Message.tests.cpp:<line number>: warning:
+  info
+  unscoped info
+  and warn may mix
+
+Message.tests.cpp:<line number>: warning:
+  info
+  unscoped info
+  they are not cleared after warnings
+
+
+No assertions in test case 'mix info, unscoped info and warning'
+
+-------------------------------------------------------------------------------
 more nested SECTION tests
-  s1
-  s2
+  doesn't equal
+  equal
 -------------------------------------------------------------------------------
 Misc.tests.cpp:<line number>
 ...............................................................................
@@ -7328,61 +9625,56 @@
 
 -------------------------------------------------------------------------------
 more nested SECTION tests
-  s1
-  s3
+  doesn't equal
+  not equal
 -------------------------------------------------------------------------------
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( a != b )
 with expansion:
   1 != 2
 
 -------------------------------------------------------------------------------
 more nested SECTION tests
-  s1
-  s4
+  doesn't equal
+  less than
 -------------------------------------------------------------------------------
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( a < b )
 with expansion:
   1 < 2
 
 -------------------------------------------------------------------------------
 nested SECTION tests
-  s1
+  doesn't equal
 -------------------------------------------------------------------------------
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( a != b )
 with expansion:
   1 != 2
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( b != a )
 with expansion:
   2 != 1
 
 -------------------------------------------------------------------------------
 nested SECTION tests
-  s1
-  s2
+  doesn't equal
+  not equal
 -------------------------------------------------------------------------------
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( a != b )
 with expansion:
   1 != 2
@@ -7393,8 +9685,7 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( s == "7" )
 with expansion:
   "7" == "7"
@@ -7405,8 +9696,7 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   CHECK( ti == typeid(int) )
 with expansion:
   {?} == {?}
@@ -7417,8 +9707,30 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
+
+-------------------------------------------------------------------------------
+not prints unscoped info from previous failures
+-------------------------------------------------------------------------------
+Message.tests.cpp:<line number>
+...............................................................................
+
+Message.tests.cpp:<line number>: PASSED:
+  REQUIRE( true )
+with message:
+  this MAY be seen only for the FIRST assertion IF info is printed for passing
+  assertions
+
+Message.tests.cpp:<line number>: PASSED:
+  REQUIRE( true )
+with message:
+  this MAY be seen only for the SECOND assertion IF info is printed for passing
+  assertions
+
+Message.tests.cpp:<line number>: FAILED:
+  REQUIRE( false )
+with message:
+  this SHOULD be seen
 
 -------------------------------------------------------------------------------
 null strings
@@ -7426,14 +9738,12 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( makeString( false ) != static_cast<char*>(0) )
 with expansion:
   "valid string" != {null string}
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( makeString( true ) == static_cast<char*>(0) )
 with expansion:
   {null string} == {null string}
@@ -7444,8 +9754,7 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( ptr.get() == 0 )
 with expansion:
   0 == 0
@@ -7456,8 +9765,7 @@
 ToStringPair.tests.cpp:<line number>
 ...............................................................................
 
-ToStringPair.tests.cpp:<line number>:
-PASSED:
+ToStringPair.tests.cpp:<line number>: PASSED:
   REQUIRE( ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" )
 with expansion:
   "{ { 42, "Arthur" }, { "Ford", 24 } }"
@@ -7470,40 +9778,81 @@
 Tricky.tests.cpp:<line number>
 ...............................................................................
 
-Tricky.tests.cpp:<line number>:
-PASSED:
+Tricky.tests.cpp:<line number>: PASSED:
   REQUIRE( p == 0 )
 with expansion:
   0 == 0
 
 -------------------------------------------------------------------------------
+print unscoped info if passing unscoped info is printed
+-------------------------------------------------------------------------------
+Message.tests.cpp:<line number>
+...............................................................................
+
+Message.tests.cpp:<line number>: PASSED:
+  REQUIRE( true )
+with message:
+  this MAY be seen IF info is printed for passing assertions
+
+-------------------------------------------------------------------------------
+prints unscoped info on failure
+-------------------------------------------------------------------------------
+Message.tests.cpp:<line number>
+...............................................................................
+
+Message.tests.cpp:<line number>: FAILED:
+  REQUIRE( false )
+with messages:
+  this SHOULD be seen
+  this SHOULD also be seen
+
+-------------------------------------------------------------------------------
+prints unscoped info only for the first assertion
+-------------------------------------------------------------------------------
+Message.tests.cpp:<line number>
+...............................................................................
+
+Message.tests.cpp:<line number>: FAILED:
+  CHECK( false )
+with message:
+  this SHOULD be seen only ONCE
+
+Message.tests.cpp:<line number>: PASSED:
+  CHECK( true )
+
+Message.tests.cpp:<line number>: PASSED:
+  CHECK( true )
+with message:
+  this MAY also be seen only ONCE IF info is printed for passing assertions
+
+Message.tests.cpp:<line number>: PASSED:
+  CHECK( true )
+
+-------------------------------------------------------------------------------
 random SECTION tests
-  s1
+  doesn't equal
 -------------------------------------------------------------------------------
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( a != b )
 with expansion:
   1 != 2
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( b != a )
 with expansion:
   2 != 1
 
 -------------------------------------------------------------------------------
 random SECTION tests
-  s2
+  not equal
 -------------------------------------------------------------------------------
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( a != b )
 with expansion:
   1 != 2
@@ -7515,14 +9864,12 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   CHECK( Catch::replaceInPlace( letters, "b", "z" ) )
 with expansion:
   true
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   CHECK( letters == "azcdefcg" )
 with expansion:
   "azcdefcg" == "azcdefcg"
@@ -7534,14 +9881,12 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   CHECK( Catch::replaceInPlace( letters, "c", "z" ) )
 with expansion:
   true
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   CHECK( letters == "abzdefzg" )
 with expansion:
   "abzdefzg" == "abzdefzg"
@@ -7553,14 +9898,12 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   CHECK( Catch::replaceInPlace( letters, "a", "z" ) )
 with expansion:
   true
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   CHECK( letters == "zbcdefcg" )
 with expansion:
   "zbcdefcg" == "zbcdefcg"
@@ -7572,14 +9915,12 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   CHECK( Catch::replaceInPlace( letters, "g", "z" ) )
 with expansion:
   true
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   CHECK( letters == "abcdefcz" )
 with expansion:
   "abcdefcz" == "abcdefcz"
@@ -7591,14 +9932,12 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   CHECK( Catch::replaceInPlace( letters, letters, "replaced" ) )
 with expansion:
   true
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   CHECK( letters == "replaced" )
 with expansion:
   "replaced" == "replaced"
@@ -7610,14 +9949,12 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   CHECK_FALSE( Catch::replaceInPlace( letters, "x", "z" ) )
 with expansion:
   !false
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   CHECK( letters == letters )
 with expansion:
   "abcdefcg" == "abcdefcg"
@@ -7629,14 +9966,12 @@
 String.tests.cpp:<line number>
 ...............................................................................
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   CHECK( Catch::replaceInPlace( s, "'", "|'" ) )
 with expansion:
   true
 
-String.tests.cpp:<line number>:
-PASSED:
+String.tests.cpp:<line number>: PASSED:
   CHECK( s == "didn|'t" )
 with expansion:
   "didn|'t" == "didn|'t"
@@ -7674,14 +10009,35 @@
   i := 7
 
 -------------------------------------------------------------------------------
+stacks unscoped info in loops
+-------------------------------------------------------------------------------
+Message.tests.cpp:<line number>
+...............................................................................
+
+Message.tests.cpp:<line number>: FAILED:
+  CHECK( false )
+with messages:
+  Count 1 to 3...
+  1
+  2
+  3
+
+Message.tests.cpp:<line number>: FAILED:
+  CHECK( false )
+with messages:
+  Count 4 to 6...
+  4
+  5
+  6
+
+-------------------------------------------------------------------------------
 std::map is convertible string
   empty
 -------------------------------------------------------------------------------
 ToStringGeneral.tests.cpp:<line number>
 ...............................................................................
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   REQUIRE( Catch::Detail::stringify( emptyMap ) == "{  }" )
 with expansion:
   "{  }" == "{  }"
@@ -7693,8 +10049,7 @@
 ToStringGeneral.tests.cpp:<line number>
 ...............................................................................
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   REQUIRE( Catch::Detail::stringify( map ) == "{ { \"one\", 1 } }" )
 with expansion:
   "{ { "one", 1 } }" == "{ { "one", 1 } }"
@@ -7706,8 +10061,7 @@
 ToStringGeneral.tests.cpp:<line number>
 ...............................................................................
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   REQUIRE( Catch::Detail::stringify( map ) == "{ { \"abc\", 1 }, { \"def\", 2 }, { \"ghi\", 3 } }" )
 with expansion:
   "{ { "abc", 1 }, { "def", 2 }, { "ghi", 3 } }"
@@ -7720,8 +10074,7 @@
 ToStringPair.tests.cpp:<line number>
 ...............................................................................
 
-ToStringPair.tests.cpp:<line number>:
-PASSED:
+ToStringPair.tests.cpp:<line number>: PASSED:
   REQUIRE( ::Catch::Detail::stringify(value) == "{ 34, \"xyzzy\" }" )
 with expansion:
   "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }"
@@ -7732,8 +10085,7 @@
 ToStringPair.tests.cpp:<line number>
 ...............................................................................
 
-ToStringPair.tests.cpp:<line number>:
-PASSED:
+ToStringPair.tests.cpp:<line number>: PASSED:
   REQUIRE( ::Catch::Detail::stringify( value ) == "{ 34, \"xyzzy\" }" )
 with expansion:
   "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }"
@@ -7745,8 +10097,7 @@
 ToStringGeneral.tests.cpp:<line number>
 ...............................................................................
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   REQUIRE( Catch::Detail::stringify( emptySet ) == "{  }" )
 with expansion:
   "{  }" == "{  }"
@@ -7758,8 +10109,7 @@
 ToStringGeneral.tests.cpp:<line number>
 ...............................................................................
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   REQUIRE( Catch::Detail::stringify( set ) == "{ \"one\" }" )
 with expansion:
   "{ "one" }" == "{ "one" }"
@@ -7771,8 +10121,7 @@
 ToStringGeneral.tests.cpp:<line number>
 ...............................................................................
 
-ToStringGeneral.tests.cpp:<line number>:
-PASSED:
+ToStringGeneral.tests.cpp:<line number>: PASSED:
   REQUIRE( Catch::Detail::stringify( set ) == "{ \"abc\", \"def\", \"ghi\" }" )
 with expansion:
   "{ "abc", "def", "ghi" }"
@@ -7785,8 +10134,7 @@
 ToStringPair.tests.cpp:<line number>
 ...............................................................................
 
-ToStringPair.tests.cpp:<line number>:
-PASSED:
+ToStringPair.tests.cpp:<line number>: PASSED:
   REQUIRE( ::Catch::Detail::stringify( pr ) == "{ { \"green\", 55 } }" )
 with expansion:
   "{ { "green", 55 } }"
@@ -7805,13 +10153,42 @@
   "first" == "second"
 
 -------------------------------------------------------------------------------
+stringify ranges
+-------------------------------------------------------------------------------
+ToStringWhich.tests.cpp:<line number>
+...............................................................................
+
+ToStringWhich.tests.cpp:<line number>: PASSED:
+  REQUIRE( ::Catch::Detail::stringify(streamable_range{}) == "op<<(streamable_range)" )
+with expansion:
+  "op<<(streamable_range)"
+  ==
+  "op<<(streamable_range)"
+
+ToStringWhich.tests.cpp:<line number>: PASSED:
+  REQUIRE( ::Catch::Detail::stringify(stringmaker_range{}) == "stringmaker(streamable_range)" )
+with expansion:
+  "stringmaker(streamable_range)"
+  ==
+  "stringmaker(streamable_range)"
+
+ToStringWhich.tests.cpp:<line number>: PASSED:
+  REQUIRE( ::Catch::Detail::stringify(just_range{}) == "{ 1, 2, 3, 4 }" )
+with expansion:
+  "{ 1, 2, 3, 4 }" == "{ 1, 2, 3, 4 }"
+
+ToStringWhich.tests.cpp:<line number>: PASSED:
+  REQUIRE( ::Catch::Detail::stringify(disabled_range{}) == "{ !!! }" )
+with expansion:
+  "{ !!! }" == "{ !!! }"
+
+-------------------------------------------------------------------------------
 stringify( has_maker )
 -------------------------------------------------------------------------------
 ToStringWhich.tests.cpp:<line number>
 ...............................................................................
 
-ToStringWhich.tests.cpp:<line number>:
-PASSED:
+ToStringWhich.tests.cpp:<line number>: PASSED:
   REQUIRE( ::Catch::Detail::stringify( item ) == "StringMaker<has_maker>" )
 with expansion:
   "StringMaker<has_maker>"
@@ -7819,13 +10196,12 @@
   "StringMaker<has_maker>"
 
 -------------------------------------------------------------------------------
-stringify( has_maker_and_toString )
+stringify( has_maker_and_operator )
 -------------------------------------------------------------------------------
 ToStringWhich.tests.cpp:<line number>
 ...............................................................................
 
-ToStringWhich.tests.cpp:<line number>:
-PASSED:
+ToStringWhich.tests.cpp:<line number>: PASSED:
   REQUIRE( ::Catch::Detail::stringify( item ) == "StringMaker<has_maker_and_operator>" )
 with expansion:
   "StringMaker<has_maker_and_operator>"
@@ -7833,13 +10209,23 @@
   "StringMaker<has_maker_and_operator>"
 
 -------------------------------------------------------------------------------
+stringify( has_neither )
+-------------------------------------------------------------------------------
+ToStringWhich.tests.cpp:<line number>
+...............................................................................
+
+ToStringWhich.tests.cpp:<line number>: PASSED:
+  REQUIRE( ::Catch::Detail::stringify(item) == "{ !!! }" )
+with expansion:
+  "{ !!! }" == "{ !!! }"
+
+-------------------------------------------------------------------------------
 stringify( has_operator )
 -------------------------------------------------------------------------------
 ToStringWhich.tests.cpp:<line number>
 ...............................................................................
 
-ToStringWhich.tests.cpp:<line number>:
-PASSED:
+ToStringWhich.tests.cpp:<line number>: PASSED:
   REQUIRE( ::Catch::Detail::stringify( item ) == "operator<<( has_operator )" )
 with expansion:
   "operator<<( has_operator )"
@@ -7847,13 +10233,162 @@
   "operator<<( has_operator )"
 
 -------------------------------------------------------------------------------
+stringify( has_template_operator )
+-------------------------------------------------------------------------------
+ToStringWhich.tests.cpp:<line number>
+...............................................................................
+
+ToStringWhich.tests.cpp:<line number>: PASSED:
+  REQUIRE( ::Catch::Detail::stringify( item ) == "operator<<( has_template_operator )" )
+with expansion:
+  "operator<<( has_template_operator )"
+  ==
+  "operator<<( has_template_operator )"
+
+-------------------------------------------------------------------------------
+stringify( vectors<has_maker> )
+-------------------------------------------------------------------------------
+ToStringWhich.tests.cpp:<line number>
+...............................................................................
+
+ToStringWhich.tests.cpp:<line number>: PASSED:
+  REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker> }" )
+with expansion:
+  "{ StringMaker<has_maker> }"
+  ==
+  "{ StringMaker<has_maker> }"
+
+-------------------------------------------------------------------------------
+stringify( vectors<has_maker_and_operator> )
+-------------------------------------------------------------------------------
+ToStringWhich.tests.cpp:<line number>
+...............................................................................
+
+ToStringWhich.tests.cpp:<line number>: PASSED:
+  REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker_and_operator> }" )
+with expansion:
+  "{ StringMaker<has_maker_and_operator> }"
+  ==
+  "{ StringMaker<has_maker_and_operator> }"
+
+-------------------------------------------------------------------------------
+stringify( vectors<has_operator> )
+-------------------------------------------------------------------------------
+ToStringWhich.tests.cpp:<line number>
+...............................................................................
+
+ToStringWhich.tests.cpp:<line number>: PASSED:
+  REQUIRE( ::Catch::Detail::stringify( v ) == "{ operator<<( has_operator ) }" )
+with expansion:
+  "{ operator<<( has_operator ) }"
+  ==
+  "{ operator<<( has_operator ) }"
+
+-------------------------------------------------------------------------------
+strlen3
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( data.str.size() == data.len )
+with expansion:
+  3 == 3
+
+-------------------------------------------------------------------------------
+strlen3
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( data.str.size() == data.len )
+with expansion:
+  3 == 3
+
+-------------------------------------------------------------------------------
+strlen3
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( data.str.size() == data.len )
+with expansion:
+  5 == 5
+
+-------------------------------------------------------------------------------
+strlen3
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( data.str.size() == data.len )
+with expansion:
+  4 == 4
+
+-------------------------------------------------------------------------------
+tables
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)) )
+with expansion:
+  5 == 5
+
+-------------------------------------------------------------------------------
+tables
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)) )
+with expansion:
+  6 == 6
+
+-------------------------------------------------------------------------------
+tables
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)) )
+with expansion:
+  5 == 5
+
+-------------------------------------------------------------------------------
+tables
+-------------------------------------------------------------------------------
+Generators.tests.cpp:<line number>
+...............................................................................
+
+Generators.tests.cpp:<line number>: PASSED:
+  REQUIRE( strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)) )
+with expansion:
+  6 == 6
+
+-------------------------------------------------------------------------------
+thrown std::strings are translated
+-------------------------------------------------------------------------------
+Exception.tests.cpp:<line number>
+...............................................................................
+
+Exception.tests.cpp:<line number>: FAILED:
+due to unexpected exception with message:
+  Why would you throw a std::string?
+
+-------------------------------------------------------------------------------
 toString on const wchar_t const pointer returns the string contents
 -------------------------------------------------------------------------------
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   CHECK( result == "\"wide load\"" )
 with expansion:
   ""wide load"" == ""wide load""
@@ -7864,8 +10399,7 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   CHECK( result == "\"wide load\"" )
 with expansion:
   ""wide load"" == ""wide load""
@@ -7876,8 +10410,7 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   CHECK( result == "\"wide load\"" )
 with expansion:
   ""wide load"" == ""wide load""
@@ -7888,108 +10421,28 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   CHECK( result == "\"wide load\"" )
 with expansion:
   ""wide load"" == ""wide load""
 
 -------------------------------------------------------------------------------
-toString streamable range
--------------------------------------------------------------------------------
-ToStringWhich.tests.cpp:<line number>
-...............................................................................
-
-ToStringWhich.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( ::Catch::Detail::stringify(streamable_range{}) == "op<<(streamable_range)" )
-with expansion:
-  "op<<(streamable_range)"
-  ==
-  "op<<(streamable_range)"
-
-ToStringWhich.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( ::Catch::Detail::stringify(stringmaker_range{}) == "stringmaker(streamable_range)" )
-with expansion:
-  "stringmaker(streamable_range)"
-  ==
-  "stringmaker(streamable_range)"
-
-ToStringWhich.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( ::Catch::Detail::stringify(just_range{}) == "{ 1, 2, 3, 4 }" )
-with expansion:
-  "{ 1, 2, 3, 4 }" == "{ 1, 2, 3, 4 }"
-
-ToStringWhich.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( ::Catch::Detail::stringify(disabled_range{}) == "{?}" )
-with expansion:
-  "{?}" == "{?}"
-
--------------------------------------------------------------------------------
-toString( vectors<has_maker> )
--------------------------------------------------------------------------------
-ToStringWhich.tests.cpp:<line number>
-...............................................................................
-
-ToStringWhich.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker> }" )
-with expansion:
-  "{ StringMaker<has_maker> }"
-  ==
-  "{ StringMaker<has_maker> }"
-
--------------------------------------------------------------------------------
-toString( vectors<has_maker_and_operator> )
--------------------------------------------------------------------------------
-ToStringWhich.tests.cpp:<line number>
-...............................................................................
-
-ToStringWhich.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker_and_operator> }" )
-with expansion:
-  "{ StringMaker<has_maker_and_operator> }"
-  ==
-  "{ StringMaker<has_maker_and_operator> }"
-
--------------------------------------------------------------------------------
-toString( vectors<has_operator> )
--------------------------------------------------------------------------------
-ToStringWhich.tests.cpp:<line number>
-...............................................................................
-
-ToStringWhich.tests.cpp:<line number>:
-PASSED:
-  REQUIRE( ::Catch::Detail::stringify( v ) == "{ operator<<( has_operator ) }" )
-with expansion:
-  "{ operator<<( has_operator ) }"
-  ==
-  "{ operator<<( has_operator ) }"
-
--------------------------------------------------------------------------------
 toString(enum class w/operator<<)
 -------------------------------------------------------------------------------
 EnumToString.tests.cpp:<line number>
 ...............................................................................
 
-EnumToString.tests.cpp:<line number>:
-PASSED:
+EnumToString.tests.cpp:<line number>: PASSED:
   CHECK( ::Catch::Detail::stringify(e0) == "E2/V0" )
 with expansion:
   "E2/V0" == "E2/V0"
 
-EnumToString.tests.cpp:<line number>:
-PASSED:
+EnumToString.tests.cpp:<line number>: PASSED:
   CHECK( ::Catch::Detail::stringify(e1) == "E2/V1" )
 with expansion:
   "E2/V1" == "E2/V1"
 
-EnumToString.tests.cpp:<line number>:
-PASSED:
+EnumToString.tests.cpp:<line number>: PASSED:
   CHECK( ::Catch::Detail::stringify(e3) == "Unknown enum value 10" )
 with expansion:
   "Unknown enum value 10"
@@ -8002,14 +10455,12 @@
 EnumToString.tests.cpp:<line number>
 ...............................................................................
 
-EnumToString.tests.cpp:<line number>:
-PASSED:
+EnumToString.tests.cpp:<line number>: PASSED:
   CHECK( ::Catch::Detail::stringify(e0) == "0" )
 with expansion:
   "0" == "0"
 
-EnumToString.tests.cpp:<line number>:
-PASSED:
+EnumToString.tests.cpp:<line number>: PASSED:
   CHECK( ::Catch::Detail::stringify(e1) == "1" )
 with expansion:
   "1" == "1"
@@ -8020,14 +10471,12 @@
 EnumToString.tests.cpp:<line number>
 ...............................................................................
 
-EnumToString.tests.cpp:<line number>:
-PASSED:
+EnumToString.tests.cpp:<line number>: PASSED:
   CHECK( ::Catch::Detail::stringify(e0) == "E2{0}" )
 with expansion:
   "E2{0}" == "E2{0}"
 
-EnumToString.tests.cpp:<line number>:
-PASSED:
+EnumToString.tests.cpp:<line number>: PASSED:
   CHECK( ::Catch::Detail::stringify(e1) == "E2{1}" )
 with expansion:
   "E2{1}" == "E2{1}"
@@ -8038,14 +10487,12 @@
 EnumToString.tests.cpp:<line number>
 ...............................................................................
 
-EnumToString.tests.cpp:<line number>:
-PASSED:
+EnumToString.tests.cpp:<line number>: PASSED:
   CHECK( ::Catch::Detail::stringify(e0) == "0" )
 with expansion:
   "0" == "0"
 
-EnumToString.tests.cpp:<line number>:
-PASSED:
+EnumToString.tests.cpp:<line number>: PASSED:
   CHECK( ::Catch::Detail::stringify(e1) == "1" )
 with expansion:
   "1" == "1"
@@ -8056,14 +10503,12 @@
 ToStringTuple.tests.cpp:<line number>
 ...............................................................................
 
-ToStringTuple.tests.cpp:<line number>:
-PASSED:
+ToStringTuple.tests.cpp:<line number>: PASSED:
   CHECK( "{ }" == ::Catch::Detail::stringify(type{}) )
 with expansion:
   "{ }" == "{ }"
 
-ToStringTuple.tests.cpp:<line number>:
-PASSED:
+ToStringTuple.tests.cpp:<line number>: PASSED:
   CHECK( "{ }" == ::Catch::Detail::stringify(value) )
 with expansion:
   "{ }" == "{ }"
@@ -8074,14 +10519,12 @@
 ToStringTuple.tests.cpp:<line number>
 ...............................................................................
 
-ToStringTuple.tests.cpp:<line number>:
-PASSED:
+ToStringTuple.tests.cpp:<line number>: PASSED:
   CHECK( "1.2f" == ::Catch::Detail::stringify(float(1.2)) )
 with expansion:
   "1.2f" == "1.2f"
 
-ToStringTuple.tests.cpp:<line number>:
-PASSED:
+ToStringTuple.tests.cpp:<line number>: PASSED:
   CHECK( "{ 1.2f, 0 }" == ::Catch::Detail::stringify(type{1.2f,0}) )
 with expansion:
   "{ 1.2f, 0 }" == "{ 1.2f, 0 }"
@@ -8092,8 +10535,7 @@
 ToStringTuple.tests.cpp:<line number>
 ...............................................................................
 
-ToStringTuple.tests.cpp:<line number>:
-PASSED:
+ToStringTuple.tests.cpp:<line number>: PASSED:
   CHECK( "{ 0 }" == ::Catch::Detail::stringify(type{0}) )
 with expansion:
   "{ 0 }" == "{ 0 }"
@@ -8104,8 +10546,7 @@
 ToStringTuple.tests.cpp:<line number>
 ...............................................................................
 
-ToStringTuple.tests.cpp:<line number>:
-PASSED:
+ToStringTuple.tests.cpp:<line number>: PASSED:
   CHECK( "{ 0, 42, \"Catch me\" }" == ::Catch::Detail::stringify(value) )
 with expansion:
   "{ 0, 42, "Catch me" }"
@@ -8118,8 +10559,7 @@
 ToStringTuple.tests.cpp:<line number>
 ...............................................................................
 
-ToStringTuple.tests.cpp:<line number>:
-PASSED:
+ToStringTuple.tests.cpp:<line number>: PASSED:
   CHECK( "{ \"hello\", \"world\" }" == ::Catch::Detail::stringify(type{"hello","world"}) )
 with expansion:
   "{ "hello", "world" }"
@@ -8132,8 +10572,7 @@
 ToStringTuple.tests.cpp:<line number>
 ...............................................................................
 
-ToStringTuple.tests.cpp:<line number>:
-PASSED:
+ToStringTuple.tests.cpp:<line number>: PASSED:
   CHECK( "{ { 42 }, { }, 1.2f }" == ::Catch::Detail::stringify(value) )
 with expansion:
   "{ { 42 }, { }, 1.2f }"
@@ -8146,14 +10585,12 @@
 ToStringVector.tests.cpp:<line number>
 ...............................................................................
 
-ToStringVector.tests.cpp:<line number>:
-PASSED:
+ToStringVector.tests.cpp:<line number>: PASSED:
   REQUIRE( ::Catch::Detail::stringify(v) == "{  }" )
 with expansion:
   "{  }" == "{  }"
 
-ToStringVector.tests.cpp:<line number>:
-PASSED:
+ToStringVector.tests.cpp:<line number>: PASSED:
   REQUIRE( ::Catch::Detail::stringify(v) == "{ { \"hello\" }, { \"world\" } }" )
 with expansion:
   "{ { "hello" }, { "world" } }"
@@ -8166,20 +10603,17 @@
 ToStringVector.tests.cpp:<line number>
 ...............................................................................
 
-ToStringVector.tests.cpp:<line number>:
-PASSED:
+ToStringVector.tests.cpp:<line number>: PASSED:
   REQUIRE( ::Catch::Detail::stringify(bools) == "{  }" )
 with expansion:
   "{  }" == "{  }"
 
-ToStringVector.tests.cpp:<line number>:
-PASSED:
+ToStringVector.tests.cpp:<line number>: PASSED:
   REQUIRE( ::Catch::Detail::stringify(bools) == "{ true }" )
 with expansion:
   "{ true }" == "{ true }"
 
-ToStringVector.tests.cpp:<line number>:
-PASSED:
+ToStringVector.tests.cpp:<line number>: PASSED:
   REQUIRE( ::Catch::Detail::stringify(bools) == "{ true, false }" )
 with expansion:
   "{ true, false }" == "{ true, false }"
@@ -8190,20 +10624,17 @@
 ToStringVector.tests.cpp:<line number>
 ...............................................................................
 
-ToStringVector.tests.cpp:<line number>:
-PASSED:
+ToStringVector.tests.cpp:<line number>: PASSED:
   REQUIRE( ::Catch::Detail::stringify(vv) == "{  }" )
 with expansion:
   "{  }" == "{  }"
 
-ToStringVector.tests.cpp:<line number>:
-PASSED:
+ToStringVector.tests.cpp:<line number>: PASSED:
   REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42 }" )
 with expansion:
   "{ 42 }" == "{ 42 }"
 
-ToStringVector.tests.cpp:<line number>:
-PASSED:
+ToStringVector.tests.cpp:<line number>: PASSED:
   REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42, 250 }" )
 with expansion:
   "{ 42, 250 }" == "{ 42, 250 }"
@@ -8214,20 +10645,17 @@
 ToStringVector.tests.cpp:<line number>
 ...............................................................................
 
-ToStringVector.tests.cpp:<line number>:
-PASSED:
+ToStringVector.tests.cpp:<line number>: PASSED:
   REQUIRE( ::Catch::Detail::stringify(vv) == "{  }" )
 with expansion:
   "{  }" == "{  }"
 
-ToStringVector.tests.cpp:<line number>:
-PASSED:
+ToStringVector.tests.cpp:<line number>: PASSED:
   REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42 }" )
 with expansion:
   "{ 42 }" == "{ 42 }"
 
-ToStringVector.tests.cpp:<line number>:
-PASSED:
+ToStringVector.tests.cpp:<line number>: PASSED:
   REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42, 250 }" )
 with expansion:
   "{ 42, 250 }" == "{ 42, 250 }"
@@ -8238,20 +10666,17 @@
 ToStringVector.tests.cpp:<line number>
 ...............................................................................
 
-ToStringVector.tests.cpp:<line number>:
-PASSED:
+ToStringVector.tests.cpp:<line number>: PASSED:
   REQUIRE( ::Catch::Detail::stringify(vv) == "{  }" )
 with expansion:
   "{  }" == "{  }"
 
-ToStringVector.tests.cpp:<line number>:
-PASSED:
+ToStringVector.tests.cpp:<line number>: PASSED:
   REQUIRE( ::Catch::Detail::stringify(vv) == "{ \"hello\" }" )
 with expansion:
   "{ "hello" }" == "{ "hello" }"
 
-ToStringVector.tests.cpp:<line number>:
-PASSED:
+ToStringVector.tests.cpp:<line number>: PASSED:
   REQUIRE( ::Catch::Detail::stringify(vv) == "{ \"hello\", \"world\" }" )
 with expansion:
   "{ "hello", "world" }"
@@ -8264,14 +10689,12 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( v.size() == 5 )
 with expansion:
   5 == 5
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( v.capacity() >= 5 )
 with expansion:
   5 >= 5
@@ -8283,14 +10706,12 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( v.size() == 10 )
 with expansion:
   10 == 10
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( v.capacity() >= 10 )
 with expansion:
   10 >= 10
@@ -8301,14 +10722,12 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( v.size() == 5 )
 with expansion:
   5 == 5
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( v.capacity() >= 5 )
 with expansion:
   5 >= 5
@@ -8320,14 +10739,12 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( v.size() == 0 )
 with expansion:
   0 == 0
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( v.capacity() >= 5 )
 with expansion:
   5 >= 5
@@ -8340,8 +10757,7 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( v.capacity() == 0 )
 with expansion:
   0 == 0
@@ -8352,14 +10768,12 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( v.size() == 5 )
 with expansion:
   5 == 5
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( v.capacity() >= 5 )
 with expansion:
   5 >= 5
@@ -8371,14 +10785,12 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( v.size() == 5 )
 with expansion:
   5 == 5
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( v.capacity() >= 10 )
 with expansion:
   10 >= 10
@@ -8389,14 +10801,12 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( v.size() == 5 )
 with expansion:
   5 == 5
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( v.capacity() >= 5 )
 with expansion:
   5 >= 5
@@ -8408,39 +10818,37 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( v.size() == 5 )
 with expansion:
   5 == 5
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( v.capacity() >= 5 )
 with expansion:
   5 >= 5
 
 -------------------------------------------------------------------------------
 xmlentitycheck
-  embedded xml
+  embedded xml: <test>it should be possible to embed xml characters, such as <,
+                " or &, or even whole <xml>documents</xml> within an attribute
+                </test>
 -------------------------------------------------------------------------------
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
 
 -------------------------------------------------------------------------------
 xmlentitycheck
-  encoded chars
+  encoded chars: these should all be encoded: &&&"""<<<&"<<&"
 -------------------------------------------------------------------------------
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
 
 ===============================================================================
-test cases:  198 | 133 passed |  61 failed |  4 failed as expected
-assertions: 1007 | 866 passed | 120 failed | 21 failed as expected
+test cases:  255 |  174 passed |  77 failed |  4 failed as expected
+assertions: 1409 | 1250 passed | 138 failed | 21 failed as expected
 
diff --git a/projects/SelfTest/Baselines/console.swa4.approved.txt b/projects/SelfTest/Baselines/console.swa4.approved.txt
index 6232f8d..2efd761 100644
--- a/projects/SelfTest/Baselines/console.swa4.approved.txt
+++ b/projects/SelfTest/Baselines/console.swa4.approved.txt
@@ -3,14 +3,15 @@
 <exe-name> is a <version> host application.
 Run with -? for options
 
+Randomness seeded to: 1
+
 -------------------------------------------------------------------------------
 # A test name that starts with a #
 -------------------------------------------------------------------------------
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
 with message:
   yay
 
@@ -21,14 +22,12 @@
 Decomposition.tests.cpp:<line number>
 ...............................................................................
 
-Decomposition.tests.cpp:<line number>:
-PASSED:
+Decomposition.tests.cpp:<line number>: PASSED:
   REQUIRE( fptr == 0 )
 with expansion:
   0 == 0
 
-Decomposition.tests.cpp:<line number>:
-PASSED:
+Decomposition.tests.cpp:<line number>: PASSED:
   REQUIRE( fptr == 0l )
 with expansion:
   0 == 0
@@ -39,14 +38,12 @@
 Compilation.tests.cpp:<line number>
 ...............................................................................
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( y.v == 0 )
 with expansion:
   0 == 0
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( 0 == y.v )
 with expansion:
   0 == 0
@@ -57,43 +54,109 @@
 Compilation.tests.cpp:<line number>
 ...............................................................................
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( t1 == t2 )
 with expansion:
   {?} == {?}
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( t1 != t2 )
 with expansion:
   {?} != {?}
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( t1 < t2 )
 with expansion:
   {?} < {?}
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( t1 > t2 )
 with expansion:
   {?} > {?}
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( t1 <= t2 )
 with expansion:
   {?} <= {?}
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( t1 >= t2 )
 with expansion:
   {?} >= {?}
 
 -------------------------------------------------------------------------------
+#1175 - Hidden Test
+-------------------------------------------------------------------------------
+Misc.tests.cpp:<line number>
+...............................................................................
+
+Misc.tests.cpp:<line number>: PASSED:
+
+-------------------------------------------------------------------------------
+#1238
+-------------------------------------------------------------------------------
+Compilation.tests.cpp:<line number>
+...............................................................................
+
+Compilation.tests.cpp:<line number>: PASSED:
+  REQUIRE( std::memcmp(uarr, "123", sizeof(uarr)) == 0 )
+with expansion:
+  0 == 0
+with messages:
+  uarr := "123"
+  sarr := "456"
+
+Compilation.tests.cpp:<line number>: PASSED:
+  REQUIRE( std::memcmp(sarr, "456", sizeof(sarr)) == 0 )
+with expansion:
+  0 == 0
+with messages:
+  uarr := "123"
+  sarr := "456"
+
+-------------------------------------------------------------------------------
+#1245
+-------------------------------------------------------------------------------
+Compilation.tests.cpp:<line number>
+...............................................................................
+
+Compilation.tests.cpp:<line number>: PASSED:
+
+-------------------------------------------------------------------------------
+#1403
+-------------------------------------------------------------------------------
+Compilation.tests.cpp:<line number>
+...............................................................................
+
+Compilation.tests.cpp:<line number>: PASSED:
+  REQUIRE( h1 == h2 )
+with expansion:
+  [1403 helper] == [1403 helper]
+
+This would not be caught previously
+Nor would this
+-------------------------------------------------------------------------------
+#1514: stderr/stdout is not captured in tests aborted by an exception
+-------------------------------------------------------------------------------
+Tricky.tests.cpp:<line number>
+...............................................................................
+
+Tricky.tests.cpp:<line number>: FAILED:
+explicitly with message:
+  1514
+
+-------------------------------------------------------------------------------
+#1548
+-------------------------------------------------------------------------------
+Compilation.tests.cpp:<line number>
+...............................................................................
+
+Compilation.tests.cpp:<line number>: PASSED:
+  REQUIRE( std::is_same<TypeList<int>, TypeList<int>>::value )
+with expansion:
+  true
+
+-------------------------------------------------------------------------------
 #748 - captures with unexpected exceptions
   outside assertions
 -------------------------------------------------------------------------------
@@ -125,8 +188,7 @@
 Exception.tests.cpp:<line number>
 ...............................................................................
 
-Exception.tests.cpp:<line number>:
-PASSED:
+Exception.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS( thisThrows() )
 with message:
   answer := 42
@@ -137,8 +199,7 @@
 Compilation.tests.cpp:<line number>
 ...............................................................................
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( 42 == f )
 with expansion:
   42 == {?}
@@ -149,38 +210,31 @@
 Compilation.tests.cpp:<line number>
 ...............................................................................
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( a == t )
 with expansion:
   3 == 3
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   CHECK( a == t )
 with expansion:
   3 == 3
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE_THROWS( throws_int(true) )
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   CHECK_THROWS_AS( throws_int(true), int )
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE_NOTHROW( throws_int(false) )
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE_THAT( "aaa", Catch::EndsWith("aaa") )
 with expansion:
   "aaa" ends with: "aaa"
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( templated_tests<int>(3) )
 with expansion:
   true
@@ -196,8 +250,7 @@
 with expansion:
   1 == 0
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
   REQUIRE( errno == 1 )
 with expansion:
   1 == 1
@@ -208,8 +261,7 @@
 Compilation.tests.cpp:<line number>
 ...............................................................................
 
-Compilation.tests.cpp:<line number>:
-PASSED:
+Compilation.tests.cpp:<line number>: PASSED:
   REQUIRE( x == 4 )
 with expansion:
   {?} == 4
@@ -223,8 +275,7 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
 with message:
   Everything is OK
 
@@ -235,8 +286,7 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
 with message:
   Everything is OK
 
@@ -247,8 +297,7 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
 with message:
   Everything is OK
 
@@ -259,8 +308,7 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
 with message:
   Everything is OK
 
@@ -271,8 +319,7 @@
 Misc.tests.cpp:<line number>
 ...............................................................................
 
-Misc.tests.cpp:<line number>:
-PASSED:
+Misc.tests.cpp:<line number>: PASSED:
 with message:
   Everything is OK
 
@@ -293,12 +340,7 @@
 with expansion:
   false
 
-Condition.tests.cpp:<line number>: FAILED:
-  CHECK_FALSE( true )
-with expansion:
-  !true
-
 ===============================================================================
-test cases: 11 |  8 passed | 1 failed | 2 failed as expected
-assertions: 34 | 27 passed | 4 failed | 3 failed as expected
+test cases: 17 | 13 passed | 2 failed | 2 failed as expected
+assertions: 40 | 33 passed | 4 failed | 3 failed as expected
 
diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt
index b99f0b8..25c4823 100644
--- a/projects/SelfTest/Baselines/junit.sw.approved.txt
+++ b/projects/SelfTest/Baselines/junit.sw.approved.txt
@@ -1,11 +1,31 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<testsuitesloose text artifact
->
-  <testsuite name="<exe-name>" errors="15" failures="106" tests="1008" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
+<testsuites>
+  <properties>
+    <property name="random-seed" value="1"/>
+  </properties>
+loose text artifact
+  <testsuite name="<exe-name>" errors="17" failures="122" tests="1410" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
     <testcase classname="<exe-name>.global" name="# A test name that starts with a #" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="#1005: Comparing pointer to int and long (NULL can be either on various systems)" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="#1027" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="#1147" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="#1175 - Hidden Test" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="#1238" time="{duration}"/>
+    <testcase classname="<exe-name>.(Fixture_1245&lt;int, int>)" name="#1245" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="#1403" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="#1514: stderr/stdout is not captured in tests aborted by an exception" time="{duration}">
+      <failure type="FAIL">
+1514
+Tricky.tests.cpp:<line number>
+      </failure>
+      <system-out>
+This would not be caught previously
+      </system-out>
+      <system-err>
+Nor would this
+      </system-err>
+    </testcase>
+    <testcase classname="<exe-name>.global" name="#1548" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="#748 - captures with unexpected exceptions/outside assertions" time="{duration}">
       <error type="TEST_CASE">
 expected exception
@@ -66,18 +86,66 @@
     <testcase classname="<exe-name>.global" name="(unimplemented) static bools can be evaluated/negation" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="(unimplemented) static bools can be evaluated/double negation" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="(unimplemented) static bools can be evaluated/direct" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="3x3x3 ints" time="{duration}"/>
     <testcase classname="<exe-name>.TestClass" name="A METHOD_AS_TEST_CASE based test run that fails" time="{duration}">
       <failure message="&quot;hello&quot; == &quot;world&quot;" type="REQUIRE">
 Class.tests.cpp:<line number>
       </failure>
     </testcase>
     <testcase classname="<exe-name>.TestClass" name="A METHOD_AS_TEST_CASE based test run that succeeds" time="{duration}"/>
+    <testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - Template_Foo&lt;float>" time="{duration}">
+      <failure message="0 == 1" type="REQUIRE">
+Class.tests.cpp:<line number>
+      </failure>
+    </testcase>
+    <testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - Template_Foo&lt;int>" time="{duration}">
+      <failure message="0 == 1" type="REQUIRE">
+Class.tests.cpp:<line number>
+      </failure>
+    </testcase>
+    <testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - std::vector&lt;float>" time="{duration}">
+      <failure message="0 == 1" type="REQUIRE">
+Class.tests.cpp:<line number>
+      </failure>
+    </testcase>
+    <testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - std::vector&lt;int>" time="{duration}">
+      <failure message="0 == 1" type="REQUIRE">
+Class.tests.cpp:<line number>
+      </failure>
+    </testcase>
+    <testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds - Template_Foo&lt;float>" time="{duration}"/>
+    <testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds - Template_Foo&lt;int>" time="{duration}"/>
+    <testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds - std::vector&lt;float>" time="{duration}"/>
+    <testcase classname="<exe-name>.Template_Fixture_2" name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds - std::vector&lt;int>" time="{duration}"/>
+    <testcase classname="<exe-name>.Template_Fixture" name="A TEMPLATE_TEST_CASE_METHOD based test run that fails - double" time="{duration}">
+      <failure message="1.0 == 2" type="REQUIRE">
+Class.tests.cpp:<line number>
+      </failure>
+    </testcase>
+    <testcase classname="<exe-name>.Template_Fixture" name="A TEMPLATE_TEST_CASE_METHOD based test run that fails - float" time="{duration}">
+      <failure message="1.0f == 2" type="REQUIRE">
+Class.tests.cpp:<line number>
+      </failure>
+    </testcase>
+    <testcase classname="<exe-name>.Template_Fixture" name="A TEMPLATE_TEST_CASE_METHOD based test run that fails - int" time="{duration}">
+      <failure message="1 == 2" type="REQUIRE">
+Class.tests.cpp:<line number>
+      </failure>
+    </testcase>
+    <testcase classname="<exe-name>.Template_Fixture" name="A TEMPLATE_TEST_CASE_METHOD based test run that succeeds - double" time="{duration}"/>
+    <testcase classname="<exe-name>.Template_Fixture" name="A TEMPLATE_TEST_CASE_METHOD based test run that succeeds - float" time="{duration}"/>
+    <testcase classname="<exe-name>.Template_Fixture" name="A TEMPLATE_TEST_CASE_METHOD based test run that succeeds - int" time="{duration}"/>
     <testcase classname="<exe-name>.Fixture" name="A TEST_CASE_METHOD based test run that fails" time="{duration}">
       <failure message="1 == 2" type="REQUIRE">
 Class.tests.cpp:<line number>
       </failure>
     </testcase>
     <testcase classname="<exe-name>.Fixture" name="A TEST_CASE_METHOD based test run that succeeds" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="A Template product test case - Foo&lt;float>" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="A Template product test case - Foo&lt;int>" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="A Template product test case - std::vector&lt;float>" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="A Template product test case - std::vector&lt;int>" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="A comparison that uses literals instead of the normal constructor" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="A couple of nested sections followed by a failure" time="{duration}">
       <failure type="FAIL">
 to infinity and beyond
@@ -109,12 +177,16 @@
     <testcase classname="<exe-name>.global" name="Approximate comparisons with floats" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Approximate comparisons with ints" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Approximate comparisons with mixed numeric types" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Arbitrary predicate matcher/Function pointer" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Arbitrary predicate matcher/Lambdas + different type" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Assertions then sections" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Assertions then sections/A section" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Assertions then sections/A section/Another section" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Assertions then sections/A section/Another other section" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Assorted miscellaneous tests" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Bitfields can be captured (#1027)" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="CAPTURE can deal with complex expressions" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="CAPTURE can deal with complex expressions involving commas" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Capture and info messages/Capture should stringify like assertions" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Capture and info messages/Info should NOT stringify the way assertions do" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Character pretty printing/Specifically escaped" time="{duration}"/>
@@ -213,6 +285,7 @@
 Matchers.tests.cpp:<line number>
       </failure>
     </testcase>
+    <testcase classname="<exe-name>.global" name="Exception as a value (e.g. in REQUIRE_THROWS_MATCHES) can be stringified" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Exception matchers that fail/No exception" time="{duration}">
       <failure message="doesNotThrow(), SpecialException, ExceptionMatcher{1}" type="CHECK_THROWS_MATCHES">
 Matchers.tests.cpp:<line number>
@@ -232,10 +305,10 @@
       </error>
     </testcase>
     <testcase classname="<exe-name>.global" name="Exception matchers that fail/Contents are wrong" time="{duration}">
-      <failure message="{?} special exception has value of 1" type="CHECK_THROWS_MATCHES">
+      <failure message="SpecialException::what special exception has value of 1" type="CHECK_THROWS_MATCHES">
 Matchers.tests.cpp:<line number>
       </failure>
-      <failure message="{?} special exception has value of 1" type="REQUIRE_THROWS_MATCHES">
+      <failure message="SpecialException::what special exception has value of 1" type="REQUIRE_THROWS_MATCHES">
 Matchers.tests.cpp:<line number>
       </failure>
     </testcase>
@@ -282,6 +355,35 @@
     <testcase classname="<exe-name>.global" name="Floating point matchers: float/ULPs" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Floating point matchers: float/Composed" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Floating point matchers: float/Constructor validation" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators -- adapters/Filtering by predicate/Basic usage" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators -- adapters/Filtering by predicate/Throws if there are no matching values" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators -- adapters/Shortening a range" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators -- adapters/Transforming elements/Same type" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators -- adapters/Transforming elements/Different type" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators -- adapters/Repeating a generator" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators -- adapters/Chunking a generator into sized pieces/Number of elements in source is divisible by chunk size" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators -- adapters/Chunking a generator into sized pieces/Number of elements in source is not divisible by chunk size" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators -- adapters/Chunking a generator into sized pieces/Throws on too small generators" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators -- simple/one" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators -- simple/two" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators internals/Single value" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators internals/Preset values" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators internals/Generator combinator" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators internals/Explicitly typed generator sequence" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators internals/Filter generator" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators internals/Take generator/Take less" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators internals/Take generator/Take more" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators internals/Map" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators internals/Repeat/Singular repeat" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators internals/Repeat/Actual repeat" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators internals/Range/Positive auto step/Integer" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators internals/Range/Negative auto step/Integer" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators internals/Range/Positive manual step/Integer/Exact" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators internals/Range/Positive manual step/Integer/Slightly over end" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators internals/Range/Positive manual step/Integer/Slightly under end" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators internals/Range/Negative manual step/Integer/Exact" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators internals/Range/Negative manual step/Integer/Slightly over end" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Generators internals/Range/Negative manual step/Integer/Slightly under end" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Greater-than inequalities with different epsilons" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="INFO and WARN do not abort tests" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="INFO gets logged on failure" time="{duration}">
@@ -358,6 +460,7 @@
       </error>
     </testcase>
     <testcase classname="<exe-name>.global" name="Objects that evaluated in boolean contexts can be checked" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Optionally static assertions" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Ordering comparison checks that should fail" time="{duration}">
       <failure message="7 > 7" type="CHECK">
 Condition.tests.cpp:<line number>
@@ -461,17 +564,18 @@
     <testcase classname="<exe-name>.global" name="Parse test names and tags/empty tag" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Parse test names and tags/empty quoted name" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Parse test names and tags/quoted string followed by tag exclusion" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="Parsing a std::pair" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Pointers can be compared to null" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Predicate matcher can accept const char*" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Process can be configured on command line/empty args don't cause a crash" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Process can be configured on command line/default - no arguments" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="Process can be configured on command line/test lists/1 test" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Process can be configured on command line/test lists/Specify one test case using" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Process can be configured on command line/test lists/Specify one test case exclusion using exclude:" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Process can be configured on command line/test lists/Specify one test case exclusion using ~" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/-r/console" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/-r/xml" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/-r xml and junit" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/--reporter/junit" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/Only one reporter is accepted" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Process can be configured on command line/reporter/must match one of the available ones" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Process can be configured on command line/debugger/-b" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Process can be configured on command line/debugger/--break" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Process can be configured on command line/abort/-a aborts after first failure" time="{duration}"/>
@@ -487,6 +591,9 @@
     <testcase classname="<exe-name>.global" name="Process can be configured on command line/use-colour/yes" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Process can be configured on command line/use-colour/no" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Process can be configured on command line/use-colour/error" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Product with differing arities - std::tuple&lt;int, double, float>" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Product with differing arities - std::tuple&lt;int, double>" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Product with differing arities - std::tuple&lt;int>" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Reconstruction should be based on stringification: #914" time="{duration}">
       <failure message="Hey, its truthy!" type="CHECK">
 Decomposition.tests.cpp:<line number>
@@ -503,12 +610,13 @@
 Matchers.tests.cpp:<line number>
       </failure>
     </testcase>
+    <testcase classname="<exe-name>.global" name="Regression test #1" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="SUCCEED counts as a test pass" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="SUCCEED does not require an argument" time="{duration}"/>
     <testcase classname="<exe-name>.Fixture" name="Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods/Given: No operations precede me" time="{duration}"/>
     <testcase classname="<exe-name>.Fixture" name="Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or methods/Given: No operations precede me/When: We get the count/Then: Subsequently values are higher" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="Scenario: Do that thing with the thing/Given: This stuff exists/When: I do this/Then: it should do this" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="Scenario: Do that thing with the thing/Given: This stuff exists/When: I do this/Then: it should do this/And: do that" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Scenario: Do that thing with the thing/Given: This stuff exists/And given: And some assumption/When: I do this/Then: it should do this" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Scenario: Do that thing with the thing/Given: This stuff exists/And given: And some assumption/When: I do this/Then: it should do this/And: do that" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Scenario: This is a really long scenario name to see how the list command deals with wrapping/Given: A section name that is so long that it cannot fit in a single console width/When: The test headers are printed as part of the normal running of the scenario/Then: The, deliberately very long and overly verbose (you see what I did there?) section names must wrap, along with an indent" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Scenario: Vector resizing affects size and capacity/Given: an empty vector" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Scenario: Vector resizing affects size and capacity/Given: an empty vector/When: it is made larger/Then: the size and capacity go up" time="{duration}"/>
@@ -545,11 +653,7 @@
     <testcase classname="<exe-name>.global" name="StringRef/Empty string" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="StringRef/From string literal" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="StringRef/From string literal/c_str() does not cause copy" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="StringRef/From sub-string" time="{duration}">
-      <failure message="false" type="REQUIRE">
-String.tests.cpp:<line number>
-      </failure>
-    </testcase>
+    <testcase classname="<exe-name>.global" name="StringRef/From sub-string" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="StringRef/Substrings/zero-based substring" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="StringRef/Substrings/c_str() causes copy" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="StringRef/Substrings/non-zero-based substring" time="{duration}"/>
@@ -562,6 +666,7 @@
     <testcase classname="<exe-name>.global" name="StringRef/to std::string/implicitly constructed" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="StringRef/to std::string/explicitly constructed" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="StringRef/to std::string/assigned" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="StringRef/Counting utf-8 codepoints" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Stringifying std::chrono::duration helpers" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Stringifying std::chrono::duration with weird ratios" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Stringifying std::chrono::time_point&lt;system_clock>" time="{duration}"/>
@@ -579,10 +684,40 @@
     </testcase>
     <testcase classname="<exe-name>.global" name="Tag alias can be registered against tag patterns/The same tag alias can only be registered once" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Tag alias can be registered against tag patterns/Tag aliases must be of the form [@name]" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - float" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - float/resizing bigger changes size and capacity" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - float/resizing smaller changes size but not capacity" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - float/resizing smaller changes size but not capacity/We can use the 'swap trick' to reset the capacity" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - float/reserving bigger changes capacity but not size" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - float/reserving smaller does not change size or capacity" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - int" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - int/resizing bigger changes size and capacity" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - int/resizing smaller changes size but not capacity" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - int/resizing smaller changes size but not capacity/We can use the 'swap trick' to reset the capacity" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - int/reserving bigger changes capacity but not size" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - int/reserving smaller does not change size or capacity" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::string" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::string/resizing bigger changes size and capacity" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::string/resizing smaller changes size but not capacity" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::string/resizing smaller changes size but not capacity/We can use the 'swap trick' to reset the capacity" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::string/reserving bigger changes capacity but not size" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::string/reserving smaller does not change size or capacity" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::tuple&lt;int,float>" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::tuple&lt;int,float>/resizing bigger changes size and capacity" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::tuple&lt;int,float>/resizing smaller changes size but not capacity" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::tuple&lt;int,float>/resizing smaller changes size but not capacity/We can use the 'swap trick' to reset the capacity" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::tuple&lt;int,float>/reserving bigger changes capacity but not size" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="TemplateTest: vectors can be sized and resized - std::tuple&lt;int,float>/reserving smaller does not change size or capacity" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Test case with one argument" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Test enum bit values" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="The NO_FAIL macro reports a failure but does not fail the test" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="This test 'should' fail but doesn't" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="Thrown string literals are translated" time="{duration}">
+      <error type="TEST_CASE">
+For some reason someone is throwing a string literal!
+Exception.tests.cpp:<line number>
+      </error>
+    </testcase>
     <testcase classname="<exe-name>.global" name="Tracker" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Tracker/successfully close one section" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Tracker/fail one section" time="{duration}"/>
@@ -593,13 +728,6 @@
     <testcase classname="<exe-name>.global" name="Tracker/successfully close one section, then find another/Re-enter - skips S1 and enters S2/Successfully close S2" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Tracker/successfully close one section, then find another/Re-enter - skips S1 and enters S2/fail S2" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Tracker/open a nested section" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="Tracker/start a generator" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="Tracker/start a generator/close outer section" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="Tracker/start a generator/close outer section/Re-enter for second generation" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="Tracker/start a generator/Start a new inner section" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="Tracker/start a generator/Start a new inner section/Re-enter for second generation" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="Tracker/start a generator/Fail an inner section" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="Tracker/start a generator/Fail an inner section/Re-enter for second generation" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="Unexpected exceptions can be translated" time="{duration}">
       <error type="TEST_CASE">
 3.14
@@ -702,6 +830,12 @@
     <testcase classname="<exe-name>.global" name="XmlEncode/string with quotes" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="XmlEncode/string with control char (1)" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="XmlEncode/string with control char (x7F)" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Valid utf-8 strings" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Invalid utf-8 strings/Various broken strings" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Invalid utf-8 strings/Overlong encodings" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Invalid utf-8 strings/Surrogate pairs" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Invalid utf-8 strings/Invalid start byte" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="XmlEncode: UTF-8/Invalid utf-8 strings/Missing continuation byte(s)" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="array&lt;int, N> -> toString" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="atomic if" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="boolean member" time="{duration}"/>
@@ -734,12 +868,31 @@
 Message.tests.cpp:<line number>
       </failure>
     </testcase>
+    <testcase classname="<exe-name>.global" name="just failure after unscoped info" time="{duration}">
+      <failure type="FAIL">
+previous unscoped info SHOULD not be seen
+Message.tests.cpp:<line number>
+      </failure>
+    </testcase>
     <testcase classname="<exe-name>.global" name="long long" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="looped SECTION tests/s1" time="{duration}">
+    <testcase classname="<exe-name>.global" name="looped SECTION tests/b is currently: 0" time="{duration}">
       <failure message="0 > 1" type="CHECK">
 Misc.tests.cpp:<line number>
       </failure>
     </testcase>
+    <testcase classname="<exe-name>.global" name="looped SECTION tests/b is currently: 1" time="{duration}">
+      <failure message="1 > 1" type="CHECK">
+Misc.tests.cpp:<line number>
+      </failure>
+    </testcase>
+    <testcase classname="<exe-name>.global" name="looped SECTION tests/b is currently: 2" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="looped SECTION tests/b is currently: 3" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="looped SECTION tests/b is currently: 4" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="looped SECTION tests/b is currently: 5" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="looped SECTION tests/b is currently: 6" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="looped SECTION tests/b is currently: 7" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="looped SECTION tests/b is currently: 8" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="looped SECTION tests/b is currently: 9" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="looped tests" time="{duration}">
       <failure message="1 == 0" type="CHECK">
 Testing if fib[0] (1) is even
@@ -766,24 +919,45 @@
 Misc.tests.cpp:<line number>
       </failure>
     </testcase>
-    <testcase classname="<exe-name>.global" name="more nested SECTION tests/s2/s1" time="{duration}">
+    <testcase classname="<exe-name>.global" name="mix info, unscoped info and warning" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="more nested SECTION tests/equal/doesn't equal" time="{duration}">
       <failure message="1 == 2" type="REQUIRE">
 Misc.tests.cpp:<line number>
       </failure>
     </testcase>
-    <testcase classname="<exe-name>.global" name="more nested SECTION tests/s1/s3" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="more nested SECTION tests/s1/s4" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="nested SECTION tests/s1" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="nested SECTION tests/s1/s2" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="more nested SECTION tests/doesn't equal/not equal" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="more nested SECTION tests/doesn't equal/less than" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="nested SECTION tests/doesn't equal" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="nested SECTION tests/doesn't equal/not equal" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="non streamable - with conv. op" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="non-copyable objects" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="not allowed" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="not prints unscoped info from previous failures" time="{duration}">
+      <failure message="false" type="REQUIRE">
+this SHOULD be seen
+Message.tests.cpp:<line number>
+      </failure>
+    </testcase>
     <testcase classname="<exe-name>.global" name="null strings" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="null_ptr" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="pair&lt;pair&lt;int,const char *,pair&lt;std::string,int> > -> toString" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="pointer to class" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="random SECTION tests/s1" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="random SECTION tests/s2" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="print unscoped info if passing unscoped info is printed" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="prints unscoped info on failure" time="{duration}">
+      <failure message="false" type="REQUIRE">
+this SHOULD be seen
+this SHOULD also be seen
+Message.tests.cpp:<line number>
+      </failure>
+    </testcase>
+    <testcase classname="<exe-name>.global" name="prints unscoped info only for the first assertion" time="{duration}">
+      <failure message="false" type="CHECK">
+this SHOULD be seen only ONCE
+Message.tests.cpp:<line number>
+      </failure>
+    </testcase>
+    <testcase classname="<exe-name>.global" name="random SECTION tests/doesn't equal" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="random SECTION tests/not equal" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="replaceInPlace/replace single char" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="replaceInPlace/replace two chars" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="replaceInPlace/replace first char" time="{duration}"/>
@@ -804,6 +978,22 @@
 Message.tests.cpp:<line number>
       </failure>
     </testcase>
+    <testcase classname="<exe-name>.global" name="stacks unscoped info in loops" time="{duration}">
+      <failure message="false" type="CHECK">
+Count 1 to 3...
+1
+2
+3
+Message.tests.cpp:<line number>
+      </failure>
+      <failure message="false" type="CHECK">
+Count 4 to 6...
+4
+5
+6
+Message.tests.cpp:<line number>
+      </failure>
+    </testcase>
     <testcase classname="<exe-name>.global" name="std::map is convertible string/empty" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="std::map is convertible string/single item" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="std::map is convertible string/several items" time="{duration}"/>
@@ -818,17 +1008,27 @@
 Tricky.tests.cpp:<line number>
       </failure>
     </testcase>
+    <testcase classname="<exe-name>.global" name="stringify ranges" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="stringify( has_maker )" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="stringify( has_maker_and_toString )" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="stringify( has_maker_and_operator )" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="stringify( has_neither )" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="stringify( has_operator )" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="stringify( has_template_operator )" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="stringify( vectors&lt;has_maker> )" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="stringify( vectors&lt;has_maker_and_operator> )" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="stringify( vectors&lt;has_operator> )" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="strlen3" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="tables" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="thrown std::strings are translated" time="{duration}">
+      <error type="TEST_CASE">
+Why would you throw a std::string?
+Exception.tests.cpp:<line number>
+      </error>
+    </testcase>
     <testcase classname="<exe-name>.global" name="toString on const wchar_t const pointer returns the string contents" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="toString on const wchar_t pointer returns the string contents" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="toString on wchar_t const pointer returns the string contents" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="toString on wchar_t returns the string contents" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="toString streamable range" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="toString( vectors&lt;has_maker> )" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="toString( vectors&lt;has_maker_and_operator> )" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="toString( vectors&lt;has_operator> )" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="toString(enum class w/operator&lt;&lt;)" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="toString(enum class)" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="toString(enum w/operator&lt;&lt;)" time="{duration}"/>
@@ -850,14 +1050,16 @@
     <testcase classname="<exe-name>.global" name="vectors can be sized and resized/resizing smaller changes size but not capacity/We can use the 'swap trick' to reset the capacity" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="vectors can be sized and resized/reserving bigger changes capacity but not size" time="{duration}"/>
     <testcase classname="<exe-name>.global" name="vectors can be sized and resized/reserving smaller does not change size or capacity" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="xmlentitycheck/embedded xml" time="{duration}"/>
-    <testcase classname="<exe-name>.global" name="xmlentitycheck/encoded chars" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="xmlentitycheck/embedded xml: &lt;test>it should be possible to embed xml characters, such as &lt;, &quot; or &amp;, or even whole &lt;xml>documents&lt;/xml> within an attribute&lt;/test>" time="{duration}"/>
+    <testcase classname="<exe-name>.global" name="xmlentitycheck/encoded chars: these should all be encoded: &amp;&amp;&amp;&quot;&quot;&quot;&lt;&lt;&lt;&amp;&quot;&lt;&lt;&amp;&quot;" time="{duration}"/>
     <system-out>
+This would not be caught previously
 A string sent directly to stdout
 Message from section one
 Message from section two
     </system-out>
     <system-err>
+Nor would this
 A string sent directly to stderr
 A string sent to stderr via clog
     </system-err>
diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt
index ceac33b..637689a 100644
--- a/projects/SelfTest/Baselines/xml.sw.approved.txt
+++ b/projects/SelfTest/Baselines/xml.sw.approved.txt
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Catch name="<exe-name>">
+  <Randomness seed="1"/>
   <Group name="<exe-name>">
     <TestCase name="# A test name that starts with a #" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
       <OverallResult success="true"/>
@@ -93,6 +94,78 @@
       </Expression>
       <OverallResult success="true"/>
     </TestCase>
+    <TestCase name="#1175 - Hidden Test" tags="[.]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="#1238" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
+      <Info>
+        uarr := "123"
+      </Info>
+      <Info>
+        sarr := "456"
+      </Info>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
+        <Original>
+          std::memcmp(uarr, "123", sizeof(uarr)) == 0
+        </Original>
+        <Expanded>
+          0 == 0
+        </Expanded>
+      </Expression>
+      <Info>
+        uarr := "123"
+      </Info>
+      <Info>
+        sarr := "456"
+      </Info>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
+        <Original>
+          std::memcmp(sarr, "456", sizeof(sarr)) == 0
+        </Original>
+        <Expanded>
+          0 == 0
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="#1245" tags="[compilation]" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="#1403" tags="[compilation]" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
+        <Original>
+          h1 == h2
+        </Original>
+        <Expanded>
+          [1403 helper] == [1403 helper]
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="#1514: stderr/stdout is not captured in tests aborted by an exception" tags="[.][output-capture][regression]" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
+      <Failure filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
+        1514
+      </Failure>
+      <OverallResult success="false">
+        <StdOut>
+This would not be caught previously
+        </StdOut>
+        <StdErr>
+Nor would this
+        </StdErr>
+      </OverallResult>
+    </TestCase>
+    <TestCase name="#1548" tags="[compilation]" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
+        <Original>
+          std::is_same&lt;TypeList&lt;int>, TypeList&lt;int>>::value
+        </Original>
+        <Expanded>
+          true
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
     <TestCase name="#748 - captures with unexpected exceptions" tags="[!shouldfail][!throws][.][failing]" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
       <Section name="outside assertions" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
         <Info>
@@ -473,6 +546,657 @@
       </Section>
       <OverallResult success="true"/>
     </TestCase>
+    <TestCase name="3x3x3 ints" tags="[generators]" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          1 &lt; 4
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          4 &lt; 7
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          1 &lt; 7
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          1 &lt; 4
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          4 &lt; 8
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          1 &lt; 8
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          1 &lt; 4
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          4 &lt; 9
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          1 &lt; 9
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          1 &lt; 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          5 &lt; 7
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          1 &lt; 7
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          1 &lt; 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          5 &lt; 8
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          1 &lt; 8
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          1 &lt; 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          5 &lt; 9
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          1 &lt; 9
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          1 &lt; 6
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          6 &lt; 7
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          1 &lt; 7
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          1 &lt; 6
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          6 &lt; 8
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          1 &lt; 8
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          1 &lt; 6
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          6 &lt; 9
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          1 &lt; 9
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          2 &lt; 4
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          4 &lt; 7
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          2 &lt; 7
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          2 &lt; 4
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          4 &lt; 8
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          2 &lt; 8
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          2 &lt; 4
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          4 &lt; 9
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          2 &lt; 9
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          2 &lt; 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          5 &lt; 7
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          2 &lt; 7
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          2 &lt; 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          5 &lt; 8
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          2 &lt; 8
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          2 &lt; 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          5 &lt; 9
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          2 &lt; 9
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          2 &lt; 6
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          6 &lt; 7
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          2 &lt; 7
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          2 &lt; 6
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          6 &lt; 8
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          2 &lt; 8
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          2 &lt; 6
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          6 &lt; 9
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          2 &lt; 9
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          3 &lt; 4
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          4 &lt; 7
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          3 &lt; 7
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          3 &lt; 4
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          4 &lt; 8
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          3 &lt; 8
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          3 &lt; 4
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          4 &lt; 9
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          3 &lt; 9
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          3 &lt; 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          5 &lt; 7
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          3 &lt; 7
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          3 &lt; 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          5 &lt; 8
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          3 &lt; 8
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          3 &lt; 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          5 &lt; 9
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          3 &lt; 9
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          3 &lt; 6
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          6 &lt; 7
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          3 &lt; 7
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          3 &lt; 6
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          6 &lt; 8
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          3 &lt; 8
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; y
+        </Original>
+        <Expanded>
+          3 &lt; 6
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          y &lt; z
+        </Original>
+        <Expanded>
+          6 &lt; 9
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          x &lt; z
+        </Original>
+        <Expanded>
+          3 &lt; 9
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
     <TestCase name="A METHOD_AS_TEST_CASE based test run that fails" tags="[.][class][failing]" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
       <Expression success="false" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
         <Original>
@@ -495,6 +1219,160 @@
       </Expression>
       <OverallResult success="true"/>
     </TestCase>
+    <TestCase name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - Template_Foo&lt;float>" tags="[.][class][failing][product][template]" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+      <Expression success="false" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+        <Original>
+          Template_Fixture_2&lt;TestType>::m_a.size() == 1
+        </Original>
+        <Expanded>
+          0 == 1
+        </Expanded>
+      </Expression>
+      <OverallResult success="false"/>
+    </TestCase>
+    <TestCase name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - Template_Foo&lt;int>" tags="[.][class][failing][product][template]" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+      <Expression success="false" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+        <Original>
+          Template_Fixture_2&lt;TestType>::m_a.size() == 1
+        </Original>
+        <Expanded>
+          0 == 1
+        </Expanded>
+      </Expression>
+      <OverallResult success="false"/>
+    </TestCase>
+    <TestCase name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - std::vector&lt;float>" tags="[.][class][failing][product][template]" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+      <Expression success="false" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+        <Original>
+          Template_Fixture_2&lt;TestType>::m_a.size() == 1
+        </Original>
+        <Expanded>
+          0 == 1
+        </Expanded>
+      </Expression>
+      <OverallResult success="false"/>
+    </TestCase>
+    <TestCase name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails - std::vector&lt;int>" tags="[.][class][failing][product][template]" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+      <Expression success="false" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+        <Original>
+          Template_Fixture_2&lt;TestType>::m_a.size() == 1
+        </Original>
+        <Expanded>
+          0 == 1
+        </Expanded>
+      </Expression>
+      <OverallResult success="false"/>
+    </TestCase>
+    <TestCase name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds - Template_Foo&lt;float>" tags="[class][product][template]" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+        <Original>
+          Template_Fixture_2&lt;TestType>::m_a.size() == 0
+        </Original>
+        <Expanded>
+          0 == 0
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds - Template_Foo&lt;int>" tags="[class][product][template]" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+        <Original>
+          Template_Fixture_2&lt;TestType>::m_a.size() == 0
+        </Original>
+        <Expanded>
+          0 == 0
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds - std::vector&lt;float>" tags="[class][product][template]" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+        <Original>
+          Template_Fixture_2&lt;TestType>::m_a.size() == 0
+        </Original>
+        <Expanded>
+          0 == 0
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds - std::vector&lt;int>" tags="[class][product][template]" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+        <Original>
+          Template_Fixture_2&lt;TestType>::m_a.size() == 0
+        </Original>
+        <Expanded>
+          0 == 0
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="A TEMPLATE_TEST_CASE_METHOD based test run that fails - double" tags="[.][class][failing][template]" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+      <Expression success="false" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+        <Original>
+          Template_Fixture&lt;TestType>::m_a == 2
+        </Original>
+        <Expanded>
+          1.0 == 2
+        </Expanded>
+      </Expression>
+      <OverallResult success="false"/>
+    </TestCase>
+    <TestCase name="A TEMPLATE_TEST_CASE_METHOD based test run that fails - float" tags="[.][class][failing][template]" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+      <Expression success="false" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+        <Original>
+          Template_Fixture&lt;TestType>::m_a == 2
+        </Original>
+        <Expanded>
+          1.0f == 2
+        </Expanded>
+      </Expression>
+      <OverallResult success="false"/>
+    </TestCase>
+    <TestCase name="A TEMPLATE_TEST_CASE_METHOD based test run that fails - int" tags="[.][class][failing][template]" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+      <Expression success="false" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+        <Original>
+          Template_Fixture&lt;TestType>::m_a == 2
+        </Original>
+        <Expanded>
+          1 == 2
+        </Expanded>
+      </Expression>
+      <OverallResult success="false"/>
+    </TestCase>
+    <TestCase name="A TEMPLATE_TEST_CASE_METHOD based test run that succeeds - double" tags="[class][template]" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+        <Original>
+          Template_Fixture&lt;TestType>::m_a == 1
+        </Original>
+        <Expanded>
+          1.0 == 1
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="A TEMPLATE_TEST_CASE_METHOD based test run that succeeds - float" tags="[class][template]" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+        <Original>
+          Template_Fixture&lt;TestType>::m_a == 1
+        </Original>
+        <Expanded>
+          1.0f == 1
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="A TEMPLATE_TEST_CASE_METHOD based test run that succeeds - int" tags="[class][template]" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
+        <Original>
+          Template_Fixture&lt;TestType>::m_a == 1
+        </Original>
+        <Expanded>
+          1 == 1
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
     <TestCase name="A TEST_CASE_METHOD based test run that fails" tags="[.][class][failing]" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
       <Expression success="false" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Class.tests.cpp" >
         <Original>
@@ -517,6 +1395,101 @@
       </Expression>
       <OverallResult success="true"/>
     </TestCase>
+    <TestCase name="A Template product test case - Foo&lt;float>" tags="[product][template]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          x.size() == 0
+        </Original>
+        <Expanded>
+          0 == 0
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="A Template product test case - Foo&lt;int>" tags="[product][template]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          x.size() == 0
+        </Original>
+        <Expanded>
+          0 == 0
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="A Template product test case - std::vector&lt;float>" tags="[product][template]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          x.size() == 0
+        </Original>
+        <Expanded>
+          0 == 0
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="A Template product test case - std::vector&lt;int>" tags="[product][template]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          x.size() == 0
+        </Original>
+        <Expanded>
+          0 == 0
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="A comparison that uses literals instead of the normal constructor" tags="[Approx]" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
+        <Original>
+          d == 1.23_a
+        </Original>
+        <Expanded>
+          1.23 == Approx( 1.23 )
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
+        <Original>
+          d != 1.22_a
+        </Original>
+        <Expanded>
+          1.23 != Approx( 1.22 )
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
+        <Original>
+          -d == -1.23_a
+        </Original>
+        <Expanded>
+          -1.23 == Approx( -1.23 )
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
+        <Original>
+          d == 1.2_a .epsilon(.1)
+        </Original>
+        <Expanded>
+          1.23 == Approx( 1.2 )
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
+        <Original>
+          d != 1.2_a .epsilon(.001)
+        </Original>
+        <Expanded>
+          1.23 != Approx( 1.2 )
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
+        <Original>
+          d == 1_a .epsilon(.3)
+        </Original>
+        <Expanded>
+          1.23 == Approx( 1.0 )
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
     <TestCase name="A couple of nested sections followed by a failure" tags="[.][failing]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
       <Section name="Outer" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
         <Section name="Inner" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
@@ -867,6 +1840,47 @@
       </Expression>
       <OverallResult success="true"/>
     </TestCase>
+    <TestCase name="Arbitrary predicate matcher" tags="[generic][matchers]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
+      <Section name="Function pointer" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
+        <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
+          <Original>
+            1, Predicate&lt;int>(alwaysTrue, "always true")
+          </Original>
+          <Expanded>
+            1 matches predicate: "always true"
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
+          <Original>
+            1, !Predicate&lt;int>(alwaysFalse, "always false")
+          </Original>
+          <Expanded>
+            1 not matches predicate: "always false"
+          </Expanded>
+        </Expression>
+        <OverallResults successes="2" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Lambdas + different type" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
+        <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
+          <Original>
+            "Hello olleH", Predicate&lt;std::string>( [] (std::string const&amp; str) -> bool { return str.front() == str.back(); }, "First and last character should be equal")
+          </Original>
+          <Expanded>
+            "Hello olleH" matches predicate: "First and last character should be equal"
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
+          <Original>
+            "This wouldn't pass", !Predicate&lt;std::string>( [] (std::string const&amp; str) -> bool { return str.front() == str.back(); } )
+          </Original>
+          <Expanded>
+            "This wouldn't pass" not matches undescribed predicate
+          </Expanded>
+        </Expression>
+        <OverallResults successes="2" failures="0" expectedFailures="0"/>
+      </Section>
+      <OverallResult success="true"/>
+    </TestCase>
     <TestCase name="Assertions then sections" tags="[Tricky]" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
         <Original>
@@ -976,6 +1990,54 @@
       </Expression>
       <OverallResult success="true"/>
     </TestCase>
+    <TestCase name="CAPTURE can deal with complex expressions" tags="[capture][messages]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+      <Info>
+        a := 1
+      </Info>
+      <Info>
+        b := 2
+      </Info>
+      <Info>
+        c := 3
+      </Info>
+      <Info>
+        a + b := 3
+      </Info>
+      <Info>
+        a+b := 3
+      </Info>
+      <Info>
+        c > b := true
+      </Info>
+      <Info>
+        a == 1 := true
+      </Info>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="CAPTURE can deal with complex expressions involving commas" tags="[capture][messages]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+      <Info>
+        std::vector&lt;int>{1, 2, 3}[0, 1, 2] := 3
+      </Info>
+      <Info>
+        std::vector&lt;int>{1, 2, 3}[(0, 1)] := 2
+      </Info>
+      <Info>
+        std::vector&lt;int>{1, 2, 3}[0] := 1
+      </Info>
+      <Info>
+        (helper_1436&lt;int, int>{12, -12}) := { 12, -12 }
+      </Info>
+      <Info>
+        (helper_1436&lt;int, int>(-12, 12)) := { -12, 12 }
+      </Info>
+      <Info>
+        (1, 2) := 2
+      </Info>
+      <Info>
+        (2, 3) := 3
+      </Info>
+      <OverallResult success="true"/>
+    </TestCase>
     <TestCase name="Capture and info messages" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
       <Section name="Capture should stringify like assertions" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
         <Info>
@@ -1823,6 +2885,37 @@
       </Expression>
       <OverallResult success="false"/>
     </TestCase>
+    <TestCase name="Exception as a value (e.g. in REQUIRE_THROWS_MATCHES) can be stringified" tags="[exception][toString]" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
+        <Original>
+          ::Catch::Detail::stringify(WhatException{}) == "This exception has overriden what() method"
+        </Original>
+        <Expanded>
+          "This exception has overriden what() method"
+==
+"This exception has overriden what() method"
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
+        <Original>
+          ::Catch::Detail::stringify(OperatorException{}) == "OperatorException"
+        </Original>
+        <Expanded>
+          "OperatorException" == "OperatorException"
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
+        <Original>
+          ::Catch::Detail::stringify(StringMakerException{}) == "StringMakerException"
+        </Original>
+        <Expanded>
+          "StringMakerException"
+==
+"StringMakerException"
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
     <TestCase name="Exception matchers that fail" tags="[!throws][.][.failing][exceptions][matchers]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
       <Section name="No exception" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
         <Expression success="false" type="CHECK_THROWS_MATCHES" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
@@ -1874,7 +2967,7 @@
             throws(3), SpecialException, ExceptionMatcher{1}
           </Original>
           <Expanded>
-            {?} special exception has value of 1
+            SpecialException::what special exception has value of 1
           </Expanded>
         </Expression>
         <Expression success="false" type="REQUIRE_THROWS_MATCHES" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
@@ -1882,7 +2975,7 @@
             throws(4), SpecialException, ExceptionMatcher{1}
           </Original>
           <Expanded>
-            {?} special exception has value of 1
+            SpecialException::what special exception has value of 1
           </Expanded>
         </Expression>
         <OverallResults successes="0" failures="2" expectedFailures="0"/>
@@ -1895,7 +2988,7 @@
           throws(1), SpecialException, ExceptionMatcher{1}
         </Original>
         <Expanded>
-          {?} special exception has value of 1
+          SpecialException::what special exception has value of 1
         </Expanded>
       </Expression>
       <Expression success="true" type="REQUIRE_THROWS_MATCHES" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
@@ -1903,7 +2996,7 @@
           throws(2), SpecialException, ExceptionMatcher{2}
         </Original>
         <Expanded>
-          {?} special exception has value of 2
+          SpecialException::what special exception has value of 2
         </Expanded>
       </Expression>
       <OverallResult success="true"/>
@@ -2105,7 +3198,39 @@
             nanf not is within 0.0 of nan
           </Expanded>
         </Expression>
-        <OverallResults successes="5" failures="0" expectedFailures="0"/>
+        <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
+          <Original>
+            11., !WithinAbs(10., 0.5)
+          </Original>
+          <Expanded>
+            11.0 not is within 0.5 of 10.0
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
+          <Original>
+            10., !WithinAbs(11., 0.5)
+          </Original>
+          <Expanded>
+            10.0 not is within 0.5 of 11.0
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
+          <Original>
+            -10., WithinAbs(-10., 0.5)
+          </Original>
+          <Expanded>
+            -10.0 is within 0.5 of -10.0
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
+          <Original>
+            -10., WithinAbs(-9.6, 0.5)
+          </Original>
+          <Expanded>
+            -10.0 is within 0.5 of -9.6
+          </Expanded>
+        </Expression>
+        <OverallResults successes="9" failures="0" expectedFailures="0"/>
       </Section>
       <Section name="ULPs" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
@@ -2118,7 +3243,7 @@
         </Expression>
         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
           <Original>
-            std::nextafter(1., 2.), WithinULP(1., 1)
+            nextafter(1., 2.), WithinULP(1., 1)
           </Original>
           <Expanded>
             1.0 is within 1 ULPs of 1.0
@@ -2126,7 +3251,7 @@
         </Expression>
         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
           <Original>
-            std::nextafter(1., 0.), WithinULP(1., 1)
+            nextafter(1., 0.), WithinULP(1., 1)
           </Original>
           <Expanded>
             1.0 is within 1 ULPs of 1.0
@@ -2134,7 +3259,7 @@
         </Expression>
         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
           <Original>
-            std::nextafter(1., 2.), !WithinULP(1., 0)
+            nextafter(1., 2.), !WithinULP(1., 0)
           </Original>
           <Expanded>
             1.0 not is within 0 ULPs of 1.0
@@ -2280,7 +3405,39 @@
             nanf not is within 0.0 of nan
           </Expanded>
         </Expression>
-        <OverallResults successes="6" failures="0" expectedFailures="0"/>
+        <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
+          <Original>
+            11.f, !WithinAbs(10.f, 0.5f)
+          </Original>
+          <Expanded>
+            11.0f not is within 0.5 of 10.0
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
+          <Original>
+            10.f, !WithinAbs(11.f, 0.5f)
+          </Original>
+          <Expanded>
+            10.0f not is within 0.5 of 11.0
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
+          <Original>
+            -10.f, WithinAbs(-10.f, 0.5f)
+          </Original>
+          <Expanded>
+            -10.0f is within 0.5 of -10.0
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
+          <Original>
+            -10.f, WithinAbs(-9.6f, 0.5f)
+          </Original>
+          <Expanded>
+            -10.0f is within 0.5 of -9.6000003815
+          </Expanded>
+        </Expression>
+        <OverallResults successes="10" failures="0" expectedFailures="0"/>
       </Section>
       <Section name="ULPs" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
@@ -2293,7 +3450,7 @@
         </Expression>
         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
           <Original>
-            std::nextafter(1.f, 2.f), WithinULP(1.f, 1)
+            nextafter(1.f, 2.f), WithinULP(1.f, 1)
           </Original>
           <Expanded>
             1.0f is within 1 ULPs of 1.0f
@@ -2301,7 +3458,7 @@
         </Expression>
         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
           <Original>
-            std::nextafter(1.f, 0.f), WithinULP(1.f, 1)
+            nextafter(1.f, 0.f), WithinULP(1.f, 1)
           </Original>
           <Expanded>
             1.0f is within 1 ULPs of 1.0f
@@ -2309,7 +3466,7 @@
         </Expression>
         <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
           <Original>
-            std::nextafter(1.f, 2.f), !WithinULP(1.f, 0)
+            nextafter(1.f, 2.f), !WithinULP(1.f, 0)
           </Original>
           <Expanded>
             1.0f not is within 0 ULPs of 1.0f
@@ -2405,6 +3562,1716 @@
       </Section>
       <OverallResult success="true"/>
     </TestCase>
+    <TestCase name="Generators -- adapters" tags="[generators][generic]" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+      <Section name="Filtering by predicate" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Section name="Basic usage" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              i % 2 == 0
+            </Original>
+            <Expanded>
+              0 == 0
+            </Expanded>
+          </Expression>
+          <OverallResults successes="1" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Filtering by predicate" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Section name="Basic usage" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              i % 2 == 0
+            </Original>
+            <Expanded>
+              0 == 0
+            </Expanded>
+          </Expression>
+          <OverallResults successes="1" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Filtering by predicate" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Section name="Basic usage" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              i % 2 == 0
+            </Original>
+            <Expanded>
+              0 == 0
+            </Expanded>
+          </Expression>
+          <OverallResults successes="1" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Filtering by predicate" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Section name="Throws if there are no matching values" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Expression success="true" type="REQUIRE_THROWS_AS" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              filter([] (int) {return false; }, value(1)), Catch::GeneratorException
+            </Original>
+            <Expanded>
+              filter([] (int) {return false; }, value(1)), Catch::GeneratorException
+            </Expanded>
+          </Expression>
+          <OverallResults successes="1" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Shortening a range" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            i &lt; 4
+          </Original>
+          <Expanded>
+            1 &lt; 4
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Shortening a range" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            i &lt; 4
+          </Original>
+          <Expanded>
+            2 &lt; 4
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Shortening a range" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            i &lt; 4
+          </Original>
+          <Expanded>
+            3 &lt; 4
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Transforming elements" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Section name="Same type" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              i % 2 == 0
+            </Original>
+            <Expanded>
+              0 == 0
+            </Expanded>
+          </Expression>
+          <OverallResults successes="1" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Transforming elements" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Section name="Same type" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              i % 2 == 0
+            </Original>
+            <Expanded>
+              0 == 0
+            </Expanded>
+          </Expression>
+          <OverallResults successes="1" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Transforming elements" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Section name="Same type" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              i % 2 == 0
+            </Original>
+            <Expanded>
+              0 == 0
+            </Expanded>
+          </Expression>
+          <OverallResults successes="1" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Transforming elements" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Section name="Different type" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              i.size() == 1
+            </Original>
+            <Expanded>
+              1 == 1
+            </Expanded>
+          </Expression>
+          <OverallResults successes="1" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Transforming elements" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Section name="Different type" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              i.size() == 1
+            </Original>
+            <Expanded>
+              1 == 1
+            </Expanded>
+          </Expression>
+          <OverallResults successes="1" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Transforming elements" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Section name="Different type" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              i.size() == 1
+            </Original>
+            <Expanded>
+              1 == 1
+            </Expanded>
+          </Expression>
+          <OverallResults successes="1" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Repeating a generator" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            j > 0
+          </Original>
+          <Expanded>
+            1 > 0
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Repeating a generator" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            j > 0
+          </Original>
+          <Expanded>
+            2 > 0
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Repeating a generator" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            j > 0
+          </Original>
+          <Expanded>
+            3 > 0
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Repeating a generator" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            j > 0
+          </Original>
+          <Expanded>
+            1 > 0
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Repeating a generator" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            j > 0
+          </Original>
+          <Expanded>
+            2 > 0
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Repeating a generator" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            j > 0
+          </Original>
+          <Expanded>
+            3 > 0
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Chunking a generator into sized pieces" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Section name="Number of elements in source is divisible by chunk size" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              chunk2.size() == 2
+            </Original>
+            <Expanded>
+              2 == 2
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              chunk2.front() == chunk2.back()
+            </Original>
+            <Expanded>
+              1 == 1
+            </Expanded>
+          </Expression>
+          <OverallResults successes="2" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="2" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Chunking a generator into sized pieces" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Section name="Number of elements in source is divisible by chunk size" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              chunk2.size() == 2
+            </Original>
+            <Expanded>
+              2 == 2
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              chunk2.front() == chunk2.back()
+            </Original>
+            <Expanded>
+              2 == 2
+            </Expanded>
+          </Expression>
+          <OverallResults successes="2" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="2" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Chunking a generator into sized pieces" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Section name="Number of elements in source is divisible by chunk size" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              chunk2.size() == 2
+            </Original>
+            <Expanded>
+              2 == 2
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              chunk2.front() == chunk2.back()
+            </Original>
+            <Expanded>
+              3 == 3
+            </Expanded>
+          </Expression>
+          <OverallResults successes="2" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="2" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Chunking a generator into sized pieces" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Section name="Number of elements in source is not divisible by chunk size" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              chunk2.size() == 2
+            </Original>
+            <Expanded>
+              2 == 2
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              chunk2.front() == chunk2.back()
+            </Original>
+            <Expanded>
+              1 == 1
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              chunk2.front() &lt; 3
+            </Original>
+            <Expanded>
+              1 &lt; 3
+            </Expanded>
+          </Expression>
+          <OverallResults successes="3" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="3" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Chunking a generator into sized pieces" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Section name="Number of elements in source is not divisible by chunk size" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              chunk2.size() == 2
+            </Original>
+            <Expanded>
+              2 == 2
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              chunk2.front() == chunk2.back()
+            </Original>
+            <Expanded>
+              2 == 2
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              chunk2.front() &lt; 3
+            </Original>
+            <Expanded>
+              2 &lt; 3
+            </Expanded>
+          </Expression>
+          <OverallResults successes="3" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="3" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Chunking a generator into sized pieces" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Section name="Throws on too small generators" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Expression success="true" type="REQUIRE_THROWS_AS" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+            <Original>
+              chunk(2, value(1)), Catch::GeneratorException
+            </Original>
+            <Expanded>
+              chunk(2, value(1)), Catch::GeneratorException
+            </Expanded>
+          </Expression>
+          <OverallResults successes="1" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="Generators -- simple" tags="[generators]" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+      <Section name="one" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            j &lt; i
+          </Original>
+          <Expanded>
+            -3 &lt; 1
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="one" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            j &lt; i
+          </Original>
+          <Expanded>
+            -2 &lt; 1
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="one" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            j &lt; i
+          </Original>
+          <Expanded>
+            -1 &lt; 1
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="two" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            4u * i > str.size()
+          </Original>
+          <Expanded>
+            4 > 1
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="two" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            4u * i > str.size()
+          </Original>
+          <Expanded>
+            4 > 2
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="two" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            4u * i > str.size()
+          </Original>
+          <Expanded>
+            4 > 3
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="one" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            j &lt; i
+          </Original>
+          <Expanded>
+            -3 &lt; 2
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="one" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            j &lt; i
+          </Original>
+          <Expanded>
+            -2 &lt; 2
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="one" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            j &lt; i
+          </Original>
+          <Expanded>
+            -1 &lt; 2
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="two" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            4u * i > str.size()
+          </Original>
+          <Expanded>
+            8 > 1
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="two" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            4u * i > str.size()
+          </Original>
+          <Expanded>
+            8 > 2
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="two" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            4u * i > str.size()
+          </Original>
+          <Expanded>
+            8 > 3
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="one" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            j &lt; i
+          </Original>
+          <Expanded>
+            -3 &lt; 3
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="one" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            j &lt; i
+          </Original>
+          <Expanded>
+            -2 &lt; 3
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="one" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            j &lt; i
+          </Original>
+          <Expanded>
+            -1 &lt; 3
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="two" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            4u * i > str.size()
+          </Original>
+          <Expanded>
+            12 > 1
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="two" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            4u * i > str.size()
+          </Original>
+          <Expanded>
+            12 > 2
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="two" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+          <Original>
+            4u * i > str.size()
+          </Original>
+          <Expanded>
+            12 > 3
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="Generators internals" tags="[generators][internals]" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+      <Section name="Single value" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.get() == 123
+          </Original>
+          <Expanded>
+            123 == 123
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            !(gen.next())
+          </Original>
+          <Expanded>
+            !false
+          </Expanded>
+        </Expression>
+        <OverallResults successes="2" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Preset values" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.get() == 1
+          </Original>
+          <Expanded>
+            1 == 1
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.next()
+          </Original>
+          <Expanded>
+            true
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.get() == 3
+          </Original>
+          <Expanded>
+            3 == 3
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.next()
+          </Original>
+          <Expanded>
+            true
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.get() == 5
+          </Original>
+          <Expanded>
+            5 == 5
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            !(gen.next())
+          </Original>
+          <Expanded>
+            !false
+          </Expanded>
+        </Expression>
+        <OverallResults successes="6" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Generator combinator" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.get() == 1
+          </Original>
+          <Expanded>
+            1 == 1
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.next()
+          </Original>
+          <Expanded>
+            true
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.get() == 5
+          </Original>
+          <Expanded>
+            5 == 5
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.next()
+          </Original>
+          <Expanded>
+            true
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.get() == 2
+          </Original>
+          <Expanded>
+            2 == 2
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.next()
+          </Original>
+          <Expanded>
+            true
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.get() == 4
+          </Original>
+          <Expanded>
+            4 == 4
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.next()
+          </Original>
+          <Expanded>
+            true
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.get() == 0
+          </Original>
+          <Expanded>
+            0 == 0
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            !(gen.next())
+          </Original>
+          <Expanded>
+            !false
+          </Expanded>
+        </Expression>
+        <OverallResults successes="10" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Explicitly typed generator sequence" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.get().size() == 2
+          </Original>
+          <Expanded>
+            2 == 2
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.get() == "aa"
+          </Original>
+          <Expanded>
+            "aa" == "aa"
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.next()
+          </Original>
+          <Expanded>
+            true
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.get() == "bb"
+          </Original>
+          <Expanded>
+            "bb" == "bb"
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.next()
+          </Original>
+          <Expanded>
+            true
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.get() == "cc"
+          </Original>
+          <Expanded>
+            "cc" == "cc"
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            !(gen.next())
+          </Original>
+          <Expanded>
+            !false
+          </Expanded>
+        </Expression>
+        <OverallResults successes="7" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Filter generator" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.get() == 1
+          </Original>
+          <Expanded>
+            1 == 1
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.next()
+          </Original>
+          <Expanded>
+            true
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.get() == 3
+          </Original>
+          <Expanded>
+            3 == 3
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            !(gen.next())
+          </Original>
+          <Expanded>
+            !false
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE_THROWS_AS" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            filter([] (int) { return false; }, value(1)), Catch::GeneratorException
+          </Original>
+          <Expanded>
+            filter([] (int) { return false; }, value(1)), Catch::GeneratorException
+          </Expanded>
+        </Expression>
+        <OverallResults successes="5" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Take generator" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+        <Section name="Take less" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Original>
+              gen.get() == 1
+            </Original>
+            <Expanded>
+              1 == 1
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Original>
+              gen.next()
+            </Original>
+            <Expanded>
+              true
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Original>
+              gen.get() == 2
+            </Original>
+            <Expanded>
+              2 == 2
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Original>
+              !(gen.next())
+            </Original>
+            <Expanded>
+              !false
+            </Expanded>
+          </Expression>
+          <OverallResults successes="4" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="4" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Take generator" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+        <Section name="Take more" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Original>
+              gen.get() == 1
+            </Original>
+            <Expanded>
+              1 == 1
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Original>
+              !(gen.next())
+            </Original>
+            <Expanded>
+              !false
+            </Expanded>
+          </Expression>
+          <OverallResults successes="2" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="2" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Map" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.get() == 2.0
+          </Original>
+          <Expanded>
+            2.0 == 2.0
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.next()
+          </Original>
+          <Expanded>
+            true
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.get() == 4.0
+          </Original>
+          <Expanded>
+            4.0 == 4.0
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.next()
+          </Original>
+          <Expanded>
+            true
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            gen.get() == 6.0
+          </Original>
+          <Expanded>
+            6.0 == 6.0
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Original>
+            !(gen.next())
+          </Original>
+          <Expanded>
+            !false
+          </Expanded>
+        </Expression>
+        <OverallResults successes="6" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Repeat" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+        <Section name="Singular repeat" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Original>
+              gen.get() == 3
+            </Original>
+            <Expanded>
+              3 == 3
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Original>
+              !(gen.next())
+            </Original>
+            <Expanded>
+              !false
+            </Expanded>
+          </Expression>
+          <OverallResults successes="2" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="2" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Repeat" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+        <Section name="Actual repeat" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Original>
+              gen.get() == 1
+            </Original>
+            <Expanded>
+              1 == 1
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Original>
+              gen.next()
+            </Original>
+            <Expanded>
+              true
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Original>
+              gen.get() == 2
+            </Original>
+            <Expanded>
+              2 == 2
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Original>
+              gen.next()
+            </Original>
+            <Expanded>
+              true
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Original>
+              gen.get() == 3
+            </Original>
+            <Expanded>
+              3 == 3
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Original>
+              gen.next()
+            </Original>
+            <Expanded>
+              true
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Original>
+              gen.get() == 1
+            </Original>
+            <Expanded>
+              1 == 1
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Original>
+              gen.next()
+            </Original>
+            <Expanded>
+              true
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Original>
+              gen.get() == 2
+            </Original>
+            <Expanded>
+              2 == 2
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Original>
+              gen.next()
+            </Original>
+            <Expanded>
+              true
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Original>
+              gen.get() == 3
+            </Original>
+            <Expanded>
+              3 == 3
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Original>
+              !(gen.next())
+            </Original>
+            <Expanded>
+              !false
+            </Expanded>
+          </Expression>
+          <OverallResults successes="12" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="12" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Range" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+        <Section name="Positive auto step" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Section name="Integer" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Original>
+                gen.get() == -2
+              </Original>
+              <Expanded>
+                -2 == -2
+              </Expanded>
+            </Expression>
+            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Original>
+                gen.next()
+              </Original>
+              <Expanded>
+                true
+              </Expanded>
+            </Expression>
+            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Original>
+                gen.get() == -1
+              </Original>
+              <Expanded>
+                -1 == -1
+              </Expanded>
+            </Expression>
+            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Original>
+                gen.next()
+              </Original>
+              <Expanded>
+                true
+              </Expanded>
+            </Expression>
+            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Original>
+                gen.get() == 0
+              </Original>
+              <Expanded>
+                0 == 0
+              </Expanded>
+            </Expression>
+            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Original>
+                gen.next()
+              </Original>
+              <Expanded>
+                true
+              </Expanded>
+            </Expression>
+            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Original>
+                gen.get() == 1
+              </Original>
+              <Expanded>
+                1 == 1
+              </Expanded>
+            </Expression>
+            <Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Original>
+                !(gen.next())
+              </Original>
+              <Expanded>
+                !false
+              </Expanded>
+            </Expression>
+            <OverallResults successes="8" failures="0" expectedFailures="0"/>
+          </Section>
+          <OverallResults successes="8" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="8" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Range" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+        <Section name="Negative auto step" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Section name="Integer" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Original>
+                gen.get() == 2
+              </Original>
+              <Expanded>
+                2 == 2
+              </Expanded>
+            </Expression>
+            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Original>
+                gen.next()
+              </Original>
+              <Expanded>
+                true
+              </Expanded>
+            </Expression>
+            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Original>
+                gen.get() == 1
+              </Original>
+              <Expanded>
+                1 == 1
+              </Expanded>
+            </Expression>
+            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Original>
+                gen.next()
+              </Original>
+              <Expanded>
+                true
+              </Expanded>
+            </Expression>
+            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Original>
+                gen.get() == 0
+              </Original>
+              <Expanded>
+                0 == 0
+              </Expanded>
+            </Expression>
+            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Original>
+                gen.next()
+              </Original>
+              <Expanded>
+                true
+              </Expanded>
+            </Expression>
+            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Original>
+                gen.get() == -1
+              </Original>
+              <Expanded>
+                -1 == -1
+              </Expanded>
+            </Expression>
+            <Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Original>
+                !(gen.next())
+              </Original>
+              <Expanded>
+                !false
+              </Expanded>
+            </Expression>
+            <OverallResults successes="8" failures="0" expectedFailures="0"/>
+          </Section>
+          <OverallResults successes="8" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="8" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Range" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+        <Section name="Positive manual step" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Section name="Integer" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Section name="Exact" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == -7
+                </Original>
+                <Expanded>
+                  -7 == -7
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.next()
+                </Original>
+                <Expanded>
+                  true
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == -4
+                </Original>
+                <Expanded>
+                  -4 == -4
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.next()
+                </Original>
+                <Expanded>
+                  true
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == -1
+                </Original>
+                <Expanded>
+                  -1 == -1
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.next()
+                </Original>
+                <Expanded>
+                  true
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == 2
+                </Original>
+                <Expanded>
+                  2 == 2
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  !(gen.next())
+                </Original>
+                <Expanded>
+                  !false
+                </Expanded>
+              </Expression>
+              <OverallResults successes="8" failures="0" expectedFailures="0"/>
+            </Section>
+            <OverallResults successes="8" failures="0" expectedFailures="0"/>
+          </Section>
+          <OverallResults successes="8" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="8" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Range" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+        <Section name="Positive manual step" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Section name="Integer" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Section name="Slightly over end" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == -7
+                </Original>
+                <Expanded>
+                  -7 == -7
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.next()
+                </Original>
+                <Expanded>
+                  true
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == -4
+                </Original>
+                <Expanded>
+                  -4 == -4
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.next()
+                </Original>
+                <Expanded>
+                  true
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == -1
+                </Original>
+                <Expanded>
+                  -1 == -1
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.next()
+                </Original>
+                <Expanded>
+                  true
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == 2
+                </Original>
+                <Expanded>
+                  2 == 2
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  !(gen.next())
+                </Original>
+                <Expanded>
+                  !false
+                </Expanded>
+              </Expression>
+              <OverallResults successes="8" failures="0" expectedFailures="0"/>
+            </Section>
+            <OverallResults successes="8" failures="0" expectedFailures="0"/>
+          </Section>
+          <OverallResults successes="8" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="8" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Range" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+        <Section name="Positive manual step" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Section name="Integer" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Section name="Slightly under end" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == -7
+                </Original>
+                <Expanded>
+                  -7 == -7
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.next()
+                </Original>
+                <Expanded>
+                  true
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == -4
+                </Original>
+                <Expanded>
+                  -4 == -4
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.next()
+                </Original>
+                <Expanded>
+                  true
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == -1
+                </Original>
+                <Expanded>
+                  -1 == -1
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.next()
+                </Original>
+                <Expanded>
+                  true
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == 2
+                </Original>
+                <Expanded>
+                  2 == 2
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.next()
+                </Original>
+                <Expanded>
+                  true
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == 5
+                </Original>
+                <Expanded>
+                  5 == 5
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  !(gen.next())
+                </Original>
+                <Expanded>
+                  !false
+                </Expanded>
+              </Expression>
+              <OverallResults successes="10" failures="0" expectedFailures="0"/>
+            </Section>
+            <OverallResults successes="10" failures="0" expectedFailures="0"/>
+          </Section>
+          <OverallResults successes="10" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="10" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Range" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+        <Section name="Negative manual step" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Section name="Integer" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Section name="Exact" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == 5
+                </Original>
+                <Expanded>
+                  5 == 5
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.next()
+                </Original>
+                <Expanded>
+                  true
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == 2
+                </Original>
+                <Expanded>
+                  2 == 2
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.next()
+                </Original>
+                <Expanded>
+                  true
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == -1
+                </Original>
+                <Expanded>
+                  -1 == -1
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.next()
+                </Original>
+                <Expanded>
+                  true
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == -4
+                </Original>
+                <Expanded>
+                  -4 == -4
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  !(gen.next())
+                </Original>
+                <Expanded>
+                  !false
+                </Expanded>
+              </Expression>
+              <OverallResults successes="8" failures="0" expectedFailures="0"/>
+            </Section>
+            <OverallResults successes="8" failures="0" expectedFailures="0"/>
+          </Section>
+          <OverallResults successes="8" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="8" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Range" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+        <Section name="Negative manual step" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Section name="Integer" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Section name="Slightly over end" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == 5
+                </Original>
+                <Expanded>
+                  5 == 5
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.next()
+                </Original>
+                <Expanded>
+                  true
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == 2
+                </Original>
+                <Expanded>
+                  2 == 2
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.next()
+                </Original>
+                <Expanded>
+                  true
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == -1
+                </Original>
+                <Expanded>
+                  -1 == -1
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.next()
+                </Original>
+                <Expanded>
+                  true
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == -4
+                </Original>
+                <Expanded>
+                  -4 == -4
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  !(gen.next())
+                </Original>
+                <Expanded>
+                  !false
+                </Expanded>
+              </Expression>
+              <OverallResults successes="8" failures="0" expectedFailures="0"/>
+            </Section>
+            <OverallResults successes="8" failures="0" expectedFailures="0"/>
+          </Section>
+          <OverallResults successes="8" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="8" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Range" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+        <Section name="Negative manual step" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+          <Section name="Integer" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+            <Section name="Slightly under end" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == 5
+                </Original>
+                <Expanded>
+                  5 == 5
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.next()
+                </Original>
+                <Expanded>
+                  true
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == 2
+                </Original>
+                <Expanded>
+                  2 == 2
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.next()
+                </Original>
+                <Expanded>
+                  true
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == -1
+                </Original>
+                <Expanded>
+                  -1 == -1
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.next()
+                </Original>
+                <Expanded>
+                  true
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == -4
+                </Original>
+                <Expanded>
+                  -4 == -4
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.next()
+                </Original>
+                <Expanded>
+                  true
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  gen.get() == -7
+                </Original>
+                <Expanded>
+                  -7 == -7
+                </Expanded>
+              </Expression>
+              <Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
+                <Original>
+                  !(gen.next())
+                </Original>
+                <Expanded>
+                  !false
+                </Expanded>
+              </Expression>
+              <OverallResults successes="10" failures="0" expectedFailures="0"/>
+            </Section>
+            <OverallResults successes="10" failures="0" expectedFailures="0"/>
+          </Section>
+          <OverallResults successes="10" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="10" failures="0" expectedFailures="0"/>
+      </Section>
+      <OverallResult success="true"/>
+    </TestCase>
     <TestCase name="Greater-than inequalities with different epsilons" tags="[Approx]" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
         <Original>
@@ -2992,6 +5859,9 @@
       </Expression>
       <OverallResult success="true"/>
     </TestCase>
+    <TestCase name="Optionally static assertions" tags="[compilation]" filename="projects/<exe-name>/UsageTests/Compilation.tests.cpp" >
+      <OverallResult success="true"/>
+    </TestCase>
     <TestCase name="Ordering comparison checks that should fail" tags="[.][failing]" filename="projects/<exe-name>/UsageTests/Condition.tests.cpp" >
       <Expression success="false" type="CHECK" filename="projects/<exe-name>/UsageTests/Condition.tests.cpp" >
         <Original>
@@ -4477,17 +7347,6 @@
       </Section>
       <OverallResult success="true"/>
     </TestCase>
-    <TestCase name="Parsing a std::pair" tags="[Tricky][std::pair]" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
-      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
-        <Original>
-          (std::pair&lt;int, int>( 1, 2 )) == aNicePair
-        </Original>
-        <Expanded>
-          {?} == {?}
-        </Expanded>
-      </Expression>
-      <OverallResult success="true"/>
-    </TestCase>
     <TestCase name="Pointers can be compared to null" filename="projects/<exe-name>/UsageTests/Condition.tests.cpp" >
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Condition.tests.cpp" >
         <Original>
@@ -4555,6 +7414,17 @@
       </Expression>
       <OverallResult success="true"/>
     </TestCase>
+    <TestCase name="Predicate matcher can accept const char*" tags="[compilation][matchers]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
+      <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
+        <Original>
+          "foo", Predicate&lt;const char*>([] (const char* const&amp;) { return true; })
+        </Original>
+        <Expanded>
+          "foo" matches undescribed predicate
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
     <TestCase name="Process can be configured on command line" tags="[command-line][config]" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
       <Section name="empty args don't cause a crash" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
         <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
@@ -4618,16 +7488,24 @@
         </Expression>
         <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
           <Original>
-            config.reporterNames.empty()
+            config.reporterName == "console"
           </Original>
           <Expanded>
-            true
+            "console" == "console"
           </Expanded>
         </Expression>
-        <OverallResults successes="6" failures="0" expectedFailures="0"/>
+        <Expression success="true" type="CHECK_FALSE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
+          <Original>
+            !(cfg.hasTestFilters())
+          </Original>
+          <Expanded>
+            !false
+          </Expanded>
+        </Expression>
+        <OverallResults successes="7" failures="0" expectedFailures="0"/>
       </Section>
       <Section name="test lists" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
-        <Section name="1 test" description="Specify one test case using" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
+        <Section name="Specify one test case using" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
           <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
             <Original>
               result
@@ -4638,6 +7516,14 @@
           </Expression>
           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
             <Original>
+              cfg.hasTestFilters()
+            </Original>
+            <Expanded>
+              true
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
+            <Original>
               cfg.testSpec().matches(fakeTestCase("notIncluded")) == false
             </Original>
             <Expanded>
@@ -4652,9 +7538,9 @@
               true
             </Expanded>
           </Expression>
-          <OverallResults successes="3" failures="0" expectedFailures="0"/>
+          <OverallResults successes="4" failures="0" expectedFailures="0"/>
         </Section>
-        <OverallResults successes="3" failures="0" expectedFailures="0"/>
+        <OverallResults successes="4" failures="0" expectedFailures="0"/>
       </Section>
       <Section name="test lists" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
         <Section name="Specify one test case exclusion using exclude:" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
@@ -4668,6 +7554,14 @@
           </Expression>
           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
             <Original>
+              cfg.hasTestFilters()
+            </Original>
+            <Expanded>
+              true
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
+            <Original>
               cfg.testSpec().matches(fakeTestCase("test1")) == false
             </Original>
             <Expanded>
@@ -4682,9 +7576,9 @@
               true
             </Expanded>
           </Expression>
-          <OverallResults successes="3" failures="0" expectedFailures="0"/>
+          <OverallResults successes="4" failures="0" expectedFailures="0"/>
         </Section>
-        <OverallResults successes="3" failures="0" expectedFailures="0"/>
+        <OverallResults successes="4" failures="0" expectedFailures="0"/>
       </Section>
       <Section name="test lists" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
         <Section name="Specify one test case exclusion using ~" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
@@ -4698,6 +7592,14 @@
           </Expression>
           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
             <Original>
+              cfg.hasTestFilters()
+            </Original>
+            <Expanded>
+              true
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
+            <Original>
               cfg.testSpec().matches(fakeTestCase("test1")) == false
             </Original>
             <Expanded>
@@ -4712,9 +7614,9 @@
               true
             </Expanded>
           </Expression>
-          <OverallResults successes="3" failures="0" expectedFailures="0"/>
+          <OverallResults successes="4" failures="0" expectedFailures="0"/>
         </Section>
-        <OverallResults successes="3" failures="0" expectedFailures="0"/>
+        <OverallResults successes="4" failures="0" expectedFailures="0"/>
       </Section>
       <Section name="reporter" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
         <Section name="-r/console" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
@@ -4728,7 +7630,7 @@
           </Expression>
           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
             <Original>
-              config.reporterNames[0] == "console"
+              config.reporterName == "console"
             </Original>
             <Expanded>
               "console" == "console"
@@ -4750,7 +7652,7 @@
           </Expression>
           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
             <Original>
-              config.reporterNames[0] == "xml"
+              config.reporterName == "xml"
             </Original>
             <Expanded>
               "xml" == "xml"
@@ -4761,44 +7663,6 @@
         <OverallResults successes="2" failures="0" expectedFailures="0"/>
       </Section>
       <Section name="reporter" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
-        <Section name="-r xml and junit" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
-          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
-            <Original>
-              cli.parse({"test", "-r", "xml", "-r", "junit"})
-            </Original>
-            <Expanded>
-              {?}
-            </Expanded>
-          </Expression>
-          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
-            <Original>
-              config.reporterNames.size() == 2
-            </Original>
-            <Expanded>
-              2 == 2
-            </Expanded>
-          </Expression>
-          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
-            <Original>
-              config.reporterNames[0] == "xml"
-            </Original>
-            <Expanded>
-              "xml" == "xml"
-            </Expanded>
-          </Expression>
-          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
-            <Original>
-              config.reporterNames[1] == "junit"
-            </Original>
-            <Expanded>
-              "junit" == "junit"
-            </Expanded>
-          </Expression>
-          <OverallResults successes="4" failures="0" expectedFailures="0"/>
-        </Section>
-        <OverallResults successes="4" failures="0" expectedFailures="0"/>
-      </Section>
-      <Section name="reporter" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
         <Section name="--reporter/junit" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
           <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
             <Original>
@@ -4810,7 +7674,7 @@
           </Expression>
           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
             <Original>
-              config.reporterNames[0] == "junit"
+              config.reporterName == "junit"
             </Original>
             <Expanded>
               "junit" == "junit"
@@ -4820,6 +7684,42 @@
         </Section>
         <OverallResults successes="2" failures="0" expectedFailures="0"/>
       </Section>
+      <Section name="reporter" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
+        <Section name="Only one reporter is accepted" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
+          <Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
+            <Original>
+              !(cli.parse({ "test", "-r", "xml", "-r", "junit" }))
+            </Original>
+            <Expanded>
+              !{?}
+            </Expanded>
+          </Expression>
+          <OverallResults successes="1" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="reporter" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
+        <Section name="must match one of the available ones" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
+            <Original>
+              !result
+            </Original>
+            <Expanded>
+              true
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
+            <Original>
+              result.errorMessage(), Contains("Unrecognized reporter")
+            </Original>
+            <Expanded>
+              "Unrecognized reporter, 'unsupported'. Check available with --list-reporters" contains: "Unrecognized reporter"
+            </Expanded>
+          </Expression>
+          <OverallResults successes="2" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="2" failures="0" expectedFailures="0"/>
+      </Section>
       <Section name="debugger" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
         <Section name="-b" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
           <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/CmdLine.tests.cpp" >
@@ -5168,6 +8068,39 @@
       </Section>
       <OverallResult success="true"/>
     </TestCase>
+    <TestCase name="Product with differing arities - std::tuple&lt;int, double, float>" tags="[product][template]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          std::tuple_size&lt;TestType>::value >= 1
+        </Original>
+        <Expanded>
+          3 >= 1
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="Product with differing arities - std::tuple&lt;int, double>" tags="[product][template]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          std::tuple_size&lt;TestType>::value >= 1
+        </Original>
+        <Expanded>
+          2 >= 1
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="Product with differing arities - std::tuple&lt;int>" tags="[product][template]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          std::tuple_size&lt;TestType>::value >= 1
+        </Original>
+        <Expanded>
+          1 >= 1
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
     <TestCase name="Reconstruction should be based on stringification: #914" tags="[.][Decomposition][failing]" filename="projects/<exe-name>/UsageTests/Decomposition.tests.cpp" >
       <Expression success="false" type="CHECK" filename="projects/<exe-name>/UsageTests/Decomposition.tests.cpp" >
         <Original>
@@ -5206,6 +8139,17 @@
       </Expression>
       <OverallResult success="false"/>
     </TestCase>
+    <TestCase name="Regression test #1" tags="[matchers][vector]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
+      <Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
+        <Original>
+          actual, !UnorderedEquals(expected)
+        </Original>
+        <Expanded>
+          { 'a', 'b' } not UnorderedEquals: { 'c', 'b' }
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
     <TestCase name="SUCCEED counts as a test pass" tags="[messages]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
       <OverallResult success="true"/>
     </TestCase>
@@ -5242,26 +8186,29 @@
     </TestCase>
     <TestCase name="Scenario: Do that thing with the thing" tags="[Tags]" filename="projects/<exe-name>/UsageTests/BDD.tests.cpp" >
       <Section name="Given: This stuff exists" filename="projects/<exe-name>/UsageTests/BDD.tests.cpp" >
-        <Section name="When: I do this" filename="projects/<exe-name>/UsageTests/BDD.tests.cpp" >
-          <Section name="Then: it should do this" filename="projects/<exe-name>/UsageTests/BDD.tests.cpp" >
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/BDD.tests.cpp" >
-              <Original>
-                itDoesThis()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Section name="And: do that" filename="projects/<exe-name>/UsageTests/BDD.tests.cpp" >
+        <Section name="And given: And some assumption" filename="projects/<exe-name>/UsageTests/BDD.tests.cpp" >
+          <Section name="When: I do this" filename="projects/<exe-name>/UsageTests/BDD.tests.cpp" >
+            <Section name="Then: it should do this" filename="projects/<exe-name>/UsageTests/BDD.tests.cpp" >
               <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/BDD.tests.cpp" >
                 <Original>
-                  itDoesThat()
+                  itDoesThis()
                 </Original>
                 <Expanded>
                   true
                 </Expanded>
               </Expression>
-              <OverallResults successes="1" failures="0" expectedFailures="0"/>
+              <Section name="And: do that" filename="projects/<exe-name>/UsageTests/BDD.tests.cpp" >
+                <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/BDD.tests.cpp" >
+                  <Original>
+                    itDoesThat()
+                  </Original>
+                  <Expanded>
+                    true
+                  </Expanded>
+                </Expression>
+                <OverallResults successes="1" failures="0" expectedFailures="0"/>
+              </Section>
+              <OverallResults successes="2" failures="0" expectedFailures="0"/>
             </Section>
             <OverallResults successes="2" failures="0" expectedFailures="0"/>
           </Section>
@@ -5412,6 +8359,22 @@
       </Expression>
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
         <Original>
+          d == 1.23_a
+        </Original>
+        <Expanded>
+          1.23 == Approx( 1.23 )
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
+        <Original>
+          d != 1.22_a
+        </Original>
+        <Expanded>
+          1.23 != Approx( 1.22 )
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Approx.tests.cpp" >
+        <Original>
           Approx( d ) == 1.23
         </Original>
         <Expanded>
@@ -5582,7 +8545,7 @@
       </Expression>
       <OverallResult success="true"/>
     </TestCase>
-    <TestCase name="StringRef" tags="[Strings]" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
+    <TestCase name="StringRef" tags="[StringRef][Strings]" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
       <Section name="Empty string" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
         <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
           <Original>
@@ -5681,15 +8644,39 @@
             original == "original"
           </Expanded>
         </Expression>
-        <Expression success="false" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
           <Original>
             isSubstring( original )
           </Original>
           <Expanded>
-            false
+            true
           </Expanded>
         </Expression>
-        <OverallResults successes="1" failures="1" expectedFailures="0"/>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
+          <Original>
+            isOwned( original ) == false
+          </Original>
+          <Expanded>
+            false == false
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
+          <Original>
+            isSubstring( original ) == false
+          </Original>
+          <Expanded>
+            false == false
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
+          <Original>
+            isOwned( original )
+          </Original>
+          <Expanded>
+            true
+          </Expanded>
+        </Expression>
+        <OverallResults successes="5" failures="0" expectedFailures="0"/>
       </Section>
       <Section name="Substrings" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
         <Section name="zero-based substring" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
@@ -5749,7 +8736,7 @@
           </Expression>
           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
             <Original>
-              rawChars == data( s )
+              rawChars == s.currentData()
             </Original>
             <Expanded>
               "hello world!" == "hello world!"
@@ -5781,7 +8768,7 @@
           </Expression>
           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
             <Original>
-              data( ss ) != data( s )
+              ss.currentData() != s.currentData()
             </Original>
             <Expanded>
               "hello" != "hello world!"
@@ -5992,7 +8979,34 @@
         </Section>
         <OverallResults successes="2" failures="0" expectedFailures="0"/>
       </Section>
-      <OverallResult success="false"/>
+      <Section name="Counting utf-8 codepoints" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
+          <Original>
+            ascii.numberOfCharacters() == ascii.size()
+          </Original>
+          <Expanded>
+            39 == 39
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
+          <Original>
+            simpleu8.numberOfCharacters() == 30
+          </Original>
+          <Expanded>
+            30 == 30
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
+          <Original>
+            emojis.numberOfCharacters() == 9
+          </Original>
+          <Expanded>
+            9 == 9
+          </Expanded>
+        </Expression>
+        <OverallResults successes="3" failures="0" expectedFailures="0"/>
+      </Section>
+      <OverallResult success="true"/>
     </TestCase>
     <TestCase name="Stringifying std::chrono::duration helpers" tags="[chrono][toString]" filename="projects/<exe-name>/UsageTests/ToStringChrono.tests.cpp" >
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringChrono.tests.cpp" >
@@ -6160,6 +9174,622 @@
       </Section>
       <OverallResult success="true"/>
     </TestCase>
+    <TestCase name="TemplateTest: vectors can be sized and resized - float" tags="[template][vector]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.size() == 5
+        </Original>
+        <Expanded>
+          5 == 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.capacity() >= 5
+        </Original>
+        <Expanded>
+          5 >= 5
+        </Expanded>
+      </Expression>
+      <Section name="resizing bigger changes size and capacity" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.size() == 10
+          </Original>
+          <Expanded>
+            10 == 10
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.capacity() >= 10
+          </Original>
+          <Expanded>
+            10 >= 10
+          </Expanded>
+        </Expression>
+        <OverallResults successes="2" failures="0" expectedFailures="0"/>
+      </Section>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.size() == 5
+        </Original>
+        <Expanded>
+          5 == 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.capacity() >= 5
+        </Original>
+        <Expanded>
+          5 >= 5
+        </Expanded>
+      </Expression>
+      <Section name="resizing smaller changes size but not capacity" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.size() == 0
+          </Original>
+          <Expanded>
+            0 == 0
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.capacity() >= 5
+          </Original>
+          <Expanded>
+            5 >= 5
+          </Expanded>
+        </Expression>
+        <Section name="We can use the 'swap trick' to reset the capacity" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+            <Original>
+              v.capacity() == 0
+            </Original>
+            <Expanded>
+              0 == 0
+            </Expanded>
+          </Expression>
+          <OverallResults successes="1" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="3" failures="0" expectedFailures="0"/>
+      </Section>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.size() == 5
+        </Original>
+        <Expanded>
+          5 == 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.capacity() >= 5
+        </Original>
+        <Expanded>
+          5 >= 5
+        </Expanded>
+      </Expression>
+      <Section name="reserving bigger changes capacity but not size" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.size() == 5
+          </Original>
+          <Expanded>
+            5 == 5
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.capacity() >= 10
+          </Original>
+          <Expanded>
+            10 >= 10
+          </Expanded>
+        </Expression>
+        <OverallResults successes="2" failures="0" expectedFailures="0"/>
+      </Section>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.size() == 5
+        </Original>
+        <Expanded>
+          5 == 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.capacity() >= 5
+        </Original>
+        <Expanded>
+          5 >= 5
+        </Expanded>
+      </Expression>
+      <Section name="reserving smaller does not change size or capacity" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.size() == 5
+          </Original>
+          <Expanded>
+            5 == 5
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.capacity() >= 5
+          </Original>
+          <Expanded>
+            5 >= 5
+          </Expanded>
+        </Expression>
+        <OverallResults successes="2" failures="0" expectedFailures="0"/>
+      </Section>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="TemplateTest: vectors can be sized and resized - int" tags="[template][vector]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.size() == 5
+        </Original>
+        <Expanded>
+          5 == 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.capacity() >= 5
+        </Original>
+        <Expanded>
+          5 >= 5
+        </Expanded>
+      </Expression>
+      <Section name="resizing bigger changes size and capacity" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.size() == 10
+          </Original>
+          <Expanded>
+            10 == 10
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.capacity() >= 10
+          </Original>
+          <Expanded>
+            10 >= 10
+          </Expanded>
+        </Expression>
+        <OverallResults successes="2" failures="0" expectedFailures="0"/>
+      </Section>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.size() == 5
+        </Original>
+        <Expanded>
+          5 == 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.capacity() >= 5
+        </Original>
+        <Expanded>
+          5 >= 5
+        </Expanded>
+      </Expression>
+      <Section name="resizing smaller changes size but not capacity" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.size() == 0
+          </Original>
+          <Expanded>
+            0 == 0
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.capacity() >= 5
+          </Original>
+          <Expanded>
+            5 >= 5
+          </Expanded>
+        </Expression>
+        <Section name="We can use the 'swap trick' to reset the capacity" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+            <Original>
+              v.capacity() == 0
+            </Original>
+            <Expanded>
+              0 == 0
+            </Expanded>
+          </Expression>
+          <OverallResults successes="1" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="3" failures="0" expectedFailures="0"/>
+      </Section>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.size() == 5
+        </Original>
+        <Expanded>
+          5 == 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.capacity() >= 5
+        </Original>
+        <Expanded>
+          5 >= 5
+        </Expanded>
+      </Expression>
+      <Section name="reserving bigger changes capacity but not size" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.size() == 5
+          </Original>
+          <Expanded>
+            5 == 5
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.capacity() >= 10
+          </Original>
+          <Expanded>
+            10 >= 10
+          </Expanded>
+        </Expression>
+        <OverallResults successes="2" failures="0" expectedFailures="0"/>
+      </Section>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.size() == 5
+        </Original>
+        <Expanded>
+          5 == 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.capacity() >= 5
+        </Original>
+        <Expanded>
+          5 >= 5
+        </Expanded>
+      </Expression>
+      <Section name="reserving smaller does not change size or capacity" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.size() == 5
+          </Original>
+          <Expanded>
+            5 == 5
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.capacity() >= 5
+          </Original>
+          <Expanded>
+            5 >= 5
+          </Expanded>
+        </Expression>
+        <OverallResults successes="2" failures="0" expectedFailures="0"/>
+      </Section>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="TemplateTest: vectors can be sized and resized - std::string" tags="[template][vector]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.size() == 5
+        </Original>
+        <Expanded>
+          5 == 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.capacity() >= 5
+        </Original>
+        <Expanded>
+          5 >= 5
+        </Expanded>
+      </Expression>
+      <Section name="resizing bigger changes size and capacity" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.size() == 10
+          </Original>
+          <Expanded>
+            10 == 10
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.capacity() >= 10
+          </Original>
+          <Expanded>
+            10 >= 10
+          </Expanded>
+        </Expression>
+        <OverallResults successes="2" failures="0" expectedFailures="0"/>
+      </Section>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.size() == 5
+        </Original>
+        <Expanded>
+          5 == 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.capacity() >= 5
+        </Original>
+        <Expanded>
+          5 >= 5
+        </Expanded>
+      </Expression>
+      <Section name="resizing smaller changes size but not capacity" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.size() == 0
+          </Original>
+          <Expanded>
+            0 == 0
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.capacity() >= 5
+          </Original>
+          <Expanded>
+            5 >= 5
+          </Expanded>
+        </Expression>
+        <Section name="We can use the 'swap trick' to reset the capacity" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+            <Original>
+              v.capacity() == 0
+            </Original>
+            <Expanded>
+              0 == 0
+            </Expanded>
+          </Expression>
+          <OverallResults successes="1" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="3" failures="0" expectedFailures="0"/>
+      </Section>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.size() == 5
+        </Original>
+        <Expanded>
+          5 == 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.capacity() >= 5
+        </Original>
+        <Expanded>
+          5 >= 5
+        </Expanded>
+      </Expression>
+      <Section name="reserving bigger changes capacity but not size" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.size() == 5
+          </Original>
+          <Expanded>
+            5 == 5
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.capacity() >= 10
+          </Original>
+          <Expanded>
+            10 >= 10
+          </Expanded>
+        </Expression>
+        <OverallResults successes="2" failures="0" expectedFailures="0"/>
+      </Section>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.size() == 5
+        </Original>
+        <Expanded>
+          5 == 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.capacity() >= 5
+        </Original>
+        <Expanded>
+          5 >= 5
+        </Expanded>
+      </Expression>
+      <Section name="reserving smaller does not change size or capacity" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.size() == 5
+          </Original>
+          <Expanded>
+            5 == 5
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.capacity() >= 5
+          </Original>
+          <Expanded>
+            5 >= 5
+          </Expanded>
+        </Expression>
+        <OverallResults successes="2" failures="0" expectedFailures="0"/>
+      </Section>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="TemplateTest: vectors can be sized and resized - std::tuple&lt;int,float>" tags="[template][vector]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.size() == 5
+        </Original>
+        <Expanded>
+          5 == 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.capacity() >= 5
+        </Original>
+        <Expanded>
+          5 >= 5
+        </Expanded>
+      </Expression>
+      <Section name="resizing bigger changes size and capacity" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.size() == 10
+          </Original>
+          <Expanded>
+            10 == 10
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.capacity() >= 10
+          </Original>
+          <Expanded>
+            10 >= 10
+          </Expanded>
+        </Expression>
+        <OverallResults successes="2" failures="0" expectedFailures="0"/>
+      </Section>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.size() == 5
+        </Original>
+        <Expanded>
+          5 == 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.capacity() >= 5
+        </Original>
+        <Expanded>
+          5 >= 5
+        </Expanded>
+      </Expression>
+      <Section name="resizing smaller changes size but not capacity" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.size() == 0
+          </Original>
+          <Expanded>
+            0 == 0
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.capacity() >= 5
+          </Original>
+          <Expanded>
+            5 >= 5
+          </Expanded>
+        </Expression>
+        <Section name="We can use the 'swap trick' to reset the capacity" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+            <Original>
+              v.capacity() == 0
+            </Original>
+            <Expanded>
+              0 == 0
+            </Expanded>
+          </Expression>
+          <OverallResults successes="1" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="3" failures="0" expectedFailures="0"/>
+      </Section>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.size() == 5
+        </Original>
+        <Expanded>
+          5 == 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.capacity() >= 5
+        </Original>
+        <Expanded>
+          5 >= 5
+        </Expanded>
+      </Expression>
+      <Section name="reserving bigger changes capacity but not size" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.size() == 5
+          </Original>
+          <Expanded>
+            5 == 5
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.capacity() >= 10
+          </Original>
+          <Expanded>
+            10 >= 10
+          </Expanded>
+        </Expression>
+        <OverallResults successes="2" failures="0" expectedFailures="0"/>
+      </Section>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.size() == 5
+        </Original>
+        <Expanded>
+          5 == 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Original>
+          v.capacity() >= 5
+        </Original>
+        <Expanded>
+          5 >= 5
+        </Expanded>
+      </Expression>
+      <Section name="reserving smaller does not change size or capacity" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.size() == 5
+          </Original>
+          <Expanded>
+            5 == 5
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            v.capacity() >= 5
+          </Original>
+          <Expanded>
+            5 >= 5
+          </Expanded>
+        </Expression>
+        <OverallResults successes="2" failures="0" expectedFailures="0"/>
+      </Section>
+      <OverallResult success="true"/>
+    </TestCase>
     <TestCase name="Test case with one argument" filename="projects/<exe-name>/UsageTests/VariadicMacros.tests.cpp" >
       <OverallResult success="true"/>
     </TestCase>
@@ -6188,6 +9818,12 @@
     <TestCase name="This test 'should' fail but doesn't" tags="[!shouldfail][.][failing]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
       <OverallResult success="false"/>
     </TestCase>
+    <TestCase name="Thrown string literals are translated" tags="[!throws][.][failing]" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
+      <Exception filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
+        For some reason someone is throwing a string literal!
+      </Exception>
+      <OverallResult success="false"/>
+    </TestCase>
     <TestCase name="Tracker" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
         <Original>
@@ -6761,537 +10397,6 @@
         </Expression>
         <OverallResults successes="6" failures="0" expectedFailures="0"/>
       </Section>
-      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-        <Original>
-          testCase.isOpen()
-        </Original>
-        <Expanded>
-          true
-        </Expanded>
-      </Expression>
-      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-        <Original>
-          s1.isOpen()
-        </Original>
-        <Expanded>
-          true
-        </Expanded>
-      </Expression>
-      <Section name="start a generator" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-          <Original>
-            g1.isOpen()
-          </Original>
-          <Expanded>
-            true
-          </Expanded>
-        </Expression>
-        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-          <Original>
-            g1.index() == 0
-          </Original>
-          <Expanded>
-            0 == 0
-          </Expanded>
-        </Expression>
-        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-          <Original>
-            g1.isComplete() == false
-          </Original>
-          <Expanded>
-            false == false
-          </Expanded>
-        </Expression>
-        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-          <Original>
-            s1.isComplete() == false
-          </Original>
-          <Expanded>
-            false == false
-          </Expanded>
-        </Expression>
-        <Section name="close outer section" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-            <Original>
-              s1.isComplete() == false
-            </Original>
-            <Expanded>
-              false == false
-            </Expanded>
-          </Expression>
-          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-            <Original>
-              testCase.isSuccessfullyCompleted() == false
-            </Original>
-            <Expanded>
-              false == false
-            </Expanded>
-          </Expression>
-          <Section name="Re-enter for second generation" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                testCase2.isOpen()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                s1b.isOpen()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                g1b.isOpen()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                g1b.index() == 1
-              </Original>
-              <Expanded>
-                1 == 1
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                s1.isComplete() == false
-              </Original>
-              <Expanded>
-                false == false
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                s1b.isComplete()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                g1b.isComplete()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                testCase2.isComplete()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <OverallResults successes="8" failures="0" expectedFailures="0"/>
-          </Section>
-          <OverallResults successes="10" failures="0" expectedFailures="0"/>
-        </Section>
-        <OverallResults successes="14" failures="0" expectedFailures="0"/>
-      </Section>
-      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-        <Original>
-          testCase.isOpen()
-        </Original>
-        <Expanded>
-          true
-        </Expanded>
-      </Expression>
-      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-        <Original>
-          s1.isOpen()
-        </Original>
-        <Expanded>
-          true
-        </Expanded>
-      </Expression>
-      <Section name="start a generator" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-          <Original>
-            g1.isOpen()
-          </Original>
-          <Expanded>
-            true
-          </Expanded>
-        </Expression>
-        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-          <Original>
-            g1.index() == 0
-          </Original>
-          <Expanded>
-            0 == 0
-          </Expanded>
-        </Expression>
-        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-          <Original>
-            g1.isComplete() == false
-          </Original>
-          <Expanded>
-            false == false
-          </Expanded>
-        </Expression>
-        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-          <Original>
-            s1.isComplete() == false
-          </Original>
-          <Expanded>
-            false == false
-          </Expanded>
-        </Expression>
-        <Section name="Start a new inner section" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-            <Original>
-              s2.isOpen()
-            </Original>
-            <Expanded>
-              true
-            </Expanded>
-          </Expression>
-          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-            <Original>
-              s2.isComplete()
-            </Original>
-            <Expanded>
-              true
-            </Expanded>
-          </Expression>
-          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-            <Original>
-              s1.isComplete() == false
-            </Original>
-            <Expanded>
-              false == false
-            </Expanded>
-          </Expression>
-          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-            <Original>
-              testCase.isComplete() == false
-            </Original>
-            <Expanded>
-              false == false
-            </Expanded>
-          </Expression>
-          <Section name="Re-enter for second generation" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                testCase2.isOpen()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                s1b.isOpen()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                g1b.isOpen()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                g1b.index() == 1
-              </Original>
-              <Expanded>
-                1 == 1
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                s2b.isOpen()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                s2b.isComplete()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                g1b.isComplete()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                s1b.isComplete()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                testCase2.isComplete()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <OverallResults successes="9" failures="0" expectedFailures="0"/>
-          </Section>
-          <OverallResults successes="13" failures="0" expectedFailures="0"/>
-        </Section>
-        <OverallResults successes="17" failures="0" expectedFailures="0"/>
-      </Section>
-      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-        <Original>
-          testCase.isOpen()
-        </Original>
-        <Expanded>
-          true
-        </Expanded>
-      </Expression>
-      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-        <Original>
-          s1.isOpen()
-        </Original>
-        <Expanded>
-          true
-        </Expanded>
-      </Expression>
-      <Section name="start a generator" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-          <Original>
-            g1.isOpen()
-          </Original>
-          <Expanded>
-            true
-          </Expanded>
-        </Expression>
-        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-          <Original>
-            g1.index() == 0
-          </Original>
-          <Expanded>
-            0 == 0
-          </Expanded>
-        </Expression>
-        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-          <Original>
-            g1.isComplete() == false
-          </Original>
-          <Expanded>
-            false == false
-          </Expanded>
-        </Expression>
-        <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-          <Original>
-            s1.isComplete() == false
-          </Original>
-          <Expanded>
-            false == false
-          </Expanded>
-        </Expression>
-        <Section name="Fail an inner section" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-            <Original>
-              s2.isOpen()
-            </Original>
-            <Expanded>
-              true
-            </Expanded>
-          </Expression>
-          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-            <Original>
-              s2.isComplete()
-            </Original>
-            <Expanded>
-              true
-            </Expanded>
-          </Expression>
-          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-            <Original>
-              s2.isSuccessfullyCompleted() == false
-            </Original>
-            <Expanded>
-              false == false
-            </Expanded>
-          </Expression>
-          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-            <Original>
-              s1.isComplete() == false
-            </Original>
-            <Expanded>
-              false == false
-            </Expanded>
-          </Expression>
-          <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-            <Original>
-              testCase.isComplete() == false
-            </Original>
-            <Expanded>
-              false == false
-            </Expanded>
-          </Expression>
-          <Section name="Re-enter for second generation" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                testCase2.isOpen()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                s1b.isOpen()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                g1b.isOpen()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                g1b.index() == 0
-              </Original>
-              <Expanded>
-                0 == 0
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                s2b.isOpen() == false
-              </Original>
-              <Expanded>
-                false == false
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                g1b.isComplete() == false
-              </Original>
-              <Expanded>
-                false == false
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                s1b.isComplete() == false
-              </Original>
-              <Expanded>
-                false == false
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                testCase2.isComplete() == false
-              </Original>
-              <Expanded>
-                false == false
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                testCase3.isOpen()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                s1c.isOpen()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                g1c.isOpen()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                g1c.index() == 1
-              </Original>
-              <Expanded>
-                1 == 1
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                s2c.isOpen()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                s2c.isComplete()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                g1c.isComplete()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                s1c.isComplete()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/PartTracker.tests.cpp" >
-              <Original>
-                testCase3.isComplete()
-              </Original>
-              <Expanded>
-                true
-              </Expanded>
-            </Expression>
-            <OverallResults successes="17" failures="0" expectedFailures="0"/>
-          </Section>
-          <OverallResults successes="22" failures="0" expectedFailures="0"/>
-        </Section>
-        <OverallResults successes="26" failures="0" expectedFailures="0"/>
-      </Section>
       <OverallResult success="true"/>
     </TestCase>
     <TestCase name="Unexpected exceptions can be translated" tags="[!throws][.][failing]" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
@@ -7725,7 +10830,7 @@
     <TestCase name="X/level/1/b" tags="[Tricky]" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
       <OverallResult success="true"/>
     </TestCase>
-    <TestCase name="XmlEncode" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+    <TestCase name="XmlEncode" tags="[XML]" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
       <Section name="normal string" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
         <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
           <Original>
@@ -7838,6 +10943,378 @@
       </Section>
       <OverallResult success="true"/>
     </TestCase>
+    <TestCase name="XmlEncode: UTF-8" tags="[UTF-8][XML]" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+      <Section name="Valid utf-8 strings" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+        <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+          <Original>
+            encode(u8"Here be 👾") == u8"Here be 👾"
+          </Original>
+          <Expanded>
+            "Here be 👾" == "Here be 👾"
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+          <Original>
+            encode(u8"šš") == u8"šš"
+          </Original>
+          <Expanded>
+            "šš" == "šš"
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+          <Original>
+            encode("\xDF\xBF") == "\xDF\xBF"
+          </Original>
+          <Expanded>
+            "߿" == "߿"
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+          <Original>
+            encode("\xE0\xA0\x80") == "\xE0\xA0\x80"
+          </Original>
+          <Expanded>
+            "ࠀ" == "ࠀ"
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+          <Original>
+            encode("\xED\x9F\xBF") == "\xED\x9F\xBF"
+          </Original>
+          <Expanded>
+            "퟿" == "퟿"
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+          <Original>
+            encode("\xEE\x80\x80") == "\xEE\x80\x80"
+          </Original>
+          <Expanded>
+            "" == ""
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+          <Original>
+            encode("\xEF\xBF\xBF") == "\xEF\xBF\xBF"
+          </Original>
+          <Expanded>
+            "￿" == "￿"
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+          <Original>
+            encode("\xF0\x90\x80\x80") == "\xF0\x90\x80\x80"
+          </Original>
+          <Expanded>
+            "𐀀" == "𐀀"
+          </Expanded>
+        </Expression>
+        <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+          <Original>
+            encode("\xF4\x8F\xBF\xBF") == "\xF4\x8F\xBF\xBF"
+          </Original>
+          <Expanded>
+            "􏿿" == "􏿿"
+          </Expanded>
+        </Expression>
+        <OverallResults successes="9" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Invalid utf-8 strings" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+        <Section name="Various broken strings" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("Here \xFF be 👾") == u8"Here \\xFF be 👾"
+            </Original>
+            <Expanded>
+              "Here \xFF be 👾" == "Here \xFF be 👾"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xFF") == "\\xFF"
+            </Original>
+            <Expanded>
+              "\xFF" == "\xFF"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xC5\xC5\xA0") == u8"\\xC5Š"
+            </Original>
+            <Expanded>
+              "\xC5Š" == "\xC5Š"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xF4\x90\x80\x80") == u8"\\xF4\\x90\\x80\\x80"
+            </Original>
+            <Expanded>
+              "\xF4\x90\x80\x80" == "\xF4\x90\x80\x80"
+            </Expanded>
+          </Expression>
+          <OverallResults successes="4" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="4" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Invalid utf-8 strings" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+        <Section name="Overlong encodings" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xC0\x80") == u8"\\xC0\\x80"
+            </Original>
+            <Expanded>
+              "\xC0\x80" == "\xC0\x80"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xF0\x80\x80\x80") == u8"\\xF0\\x80\\x80\\x80"
+            </Original>
+            <Expanded>
+              "\xF0\x80\x80\x80" == "\xF0\x80\x80\x80"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xC1\xBF") == u8"\\xC1\\xBF"
+            </Original>
+            <Expanded>
+              "\xC1\xBF" == "\xC1\xBF"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xE0\x9F\xBF") == u8"\\xE0\\x9F\\xBF"
+            </Original>
+            <Expanded>
+              "\xE0\x9F\xBF" == "\xE0\x9F\xBF"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xF0\x8F\xBF\xBF") == u8"\\xF0\\x8F\\xBF\\xBF"
+            </Original>
+            <Expanded>
+              "\xF0\x8F\xBF\xBF" == "\xF0\x8F\xBF\xBF"
+            </Expanded>
+          </Expression>
+          <OverallResults successes="5" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="5" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Invalid utf-8 strings" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+        <Section name="Surrogate pairs" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xED\xA0\x80") == "\xED\xA0\x80"
+            </Original>
+            <Expanded>
+              "í €" == "í €"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xED\xAF\xBF") == "\xED\xAF\xBF"
+            </Original>
+            <Expanded>
+              "í¯¿" == "í¯¿"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xED\xB0\x80") == "\xED\xB0\x80"
+            </Original>
+            <Expanded>
+              "í°€" == "í°€"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xED\xBF\xBF") == "\xED\xBF\xBF"
+            </Original>
+            <Expanded>
+              "í¿¿" == "í¿¿"
+            </Expanded>
+          </Expression>
+          <OverallResults successes="4" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="4" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Invalid utf-8 strings" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+        <Section name="Invalid start byte" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\x80") == u8"\\x80"
+            </Original>
+            <Expanded>
+              "\x80" == "\x80"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\x81") == u8"\\x81"
+            </Original>
+            <Expanded>
+              "\x81" == "\x81"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xBC") == u8"\\xBC"
+            </Original>
+            <Expanded>
+              "\xBC" == "\xBC"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xBF") == u8"\\xBF"
+            </Original>
+            <Expanded>
+              "\xBF" == "\xBF"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xF5\x80\x80\x80") == u8"\\xF5\\x80\\x80\\x80"
+            </Original>
+            <Expanded>
+              "\xF5\x80\x80\x80" == "\xF5\x80\x80\x80"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xF6\x80\x80\x80") == u8"\\xF6\\x80\\x80\\x80"
+            </Original>
+            <Expanded>
+              "\xF6\x80\x80\x80" == "\xF6\x80\x80\x80"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xF7\x80\x80\x80") == u8"\\xF7\\x80\\x80\\x80"
+            </Original>
+            <Expanded>
+              "\xF7\x80\x80\x80" == "\xF7\x80\x80\x80"
+            </Expanded>
+          </Expression>
+          <OverallResults successes="7" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="7" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="Invalid utf-8 strings" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+        <Section name="Missing continuation byte(s)" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xDE") == u8"\\xDE"
+            </Original>
+            <Expanded>
+              "\xDE" == "\xDE"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xDF") == u8"\\xDF"
+            </Original>
+            <Expanded>
+              "\xDF" == "\xDF"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xE0") == u8"\\xE0"
+            </Original>
+            <Expanded>
+              "\xE0" == "\xE0"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xEF") == u8"\\xEF"
+            </Original>
+            <Expanded>
+              "\xEF" == "\xEF"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xF0") == u8"\\xF0"
+            </Original>
+            <Expanded>
+              "\xF0" == "\xF0"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xF4") == u8"\\xF4"
+            </Original>
+            <Expanded>
+              "\xF4" == "\xF4"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xE0\x80") == u8"\\xE0\\x80"
+            </Original>
+            <Expanded>
+              "\xE0\x80" == "\xE0\x80"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xE0\xBF") == u8"\\xE0\\xBF"
+            </Original>
+            <Expanded>
+              "\xE0\xBF" == "\xE0\xBF"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xE1\x80") == u8"\\xE1\\x80"
+            </Original>
+            <Expanded>
+              "\xE1\x80" == "\xE1\x80"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xF0\x80") == u8"\\xF0\\x80"
+            </Original>
+            <Expanded>
+              "\xF0\x80" == "\xF0\x80"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xF4\x80") == u8"\\xF4\\x80"
+            </Original>
+            <Expanded>
+              "\xF4\x80" == "\xF4\x80"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xF0\x80\x80") == u8"\\xF0\\x80\\x80"
+            </Original>
+            <Expanded>
+              "\xF0\x80\x80" == "\xF0\x80\x80"
+            </Expanded>
+          </Expression>
+          <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/Xml.tests.cpp" >
+            <Original>
+              encode("\xF4\x80\x80") == u8"\\xF4\\x80\\x80"
+            </Original>
+            <Expanded>
+              "\xF4\x80\x80" == "\xF4\x80\x80"
+            </Expanded>
+          </Expression>
+          <OverallResults successes="13" failures="0" expectedFailures="0"/>
+        </Section>
+        <OverallResults successes="13" failures="0" expectedFailures="0"/>
+      </Section>
+      <OverallResult success="true"/>
+    </TestCase>
     <TestCase name="array&lt;int, N> -> toString" tags="[array][containers][toString]" filename="projects/<exe-name>/UsageTests/ToStringVector.tests.cpp" >
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringVector.tests.cpp" >
         <Original>
@@ -8064,9 +11541,18 @@
       </Failure>
       <OverallResult success="false"/>
     </TestCase>
+    <TestCase name="just failure after unscoped info" tags="[.][failing][info][unscoped]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+      <Failure filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+        previous unscoped info SHOULD not be seen
+      </Failure>
+      <OverallResult success="false"/>
+    </TestCase>
     <TestCase name="just info" tags="[info][isolated info][messages]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
       <OverallResult success="false"/>
     </TestCase>
+    <TestCase name="just unscoped info" tags="[info][unscoped]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+      <OverallResult success="false"/>
+    </TestCase>
     <TestCase name="long long" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
         <Original>
@@ -8081,7 +11567,7 @@
       <OverallResult success="true"/>
     </TestCase>
     <TestCase name="looped SECTION tests" tags="[.][failing][sections]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
-      <Section name="s1" description="b is currently: 0" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+      <Section name="b is currently: 0" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
         <Expression success="false" type="CHECK" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
           <Original>
             b > a
@@ -8092,6 +11578,105 @@
         </Expression>
         <OverallResults successes="0" failures="1" expectedFailures="0"/>
       </Section>
+      <Section name="b is currently: 1" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="false" type="CHECK" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            b > a
+          </Original>
+          <Expanded>
+            1 > 1
+          </Expanded>
+        </Expression>
+        <OverallResults successes="0" failures="1" expectedFailures="0"/>
+      </Section>
+      <Section name="b is currently: 2" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            b > a
+          </Original>
+          <Expanded>
+            2 > 1
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="b is currently: 3" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            b > a
+          </Original>
+          <Expanded>
+            3 > 1
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="b is currently: 4" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            b > a
+          </Original>
+          <Expanded>
+            4 > 1
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="b is currently: 5" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            b > a
+          </Original>
+          <Expanded>
+            5 > 1
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="b is currently: 6" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            b > a
+          </Original>
+          <Expanded>
+            6 > 1
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="b is currently: 7" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            b > a
+          </Original>
+          <Expanded>
+            7 > 1
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="b is currently: 8" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            b > a
+          </Original>
+          <Expanded>
+            8 > 1
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
+      <Section name="b is currently: 9" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+          <Original>
+            b > a
+          </Original>
+          <Expanded>
+            9 > 1
+          </Expanded>
+        </Expression>
+        <OverallResults successes="1" failures="0" expectedFailures="0"/>
+      </Section>
       <OverallResult success="false"/>
     </TestCase>
     <TestCase name="looped tests" tags="[.][failing]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
@@ -8185,9 +11770,30 @@
       </Expression>
       <OverallResult success="false"/>
     </TestCase>
+    <TestCase name="mix info, unscoped info and warning" tags="[info][unscoped]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+      <Info>
+        info
+      </Info>
+      <Info>
+        unscoped info
+      </Info>
+      <Warning>
+        and warn may mix
+      </Warning>
+      <Info>
+        info
+      </Info>
+      <Info>
+        unscoped info
+      </Info>
+      <Warning>
+        they are not cleared after warnings
+      </Warning>
+      <OverallResult success="false"/>
+    </TestCase>
     <TestCase name="more nested SECTION tests" tags="[.][failing][sections]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
-      <Section name="s1" description="doesn't equal" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
-        <Section name="s2" description="equal" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+      <Section name="doesn't equal" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Section name="equal" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
           <Expression success="false" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
             <Original>
               a == b
@@ -8200,8 +11806,8 @@
         </Section>
         <OverallResults successes="0" failures="1" expectedFailures="0"/>
       </Section>
-      <Section name="s1" description="doesn't equal" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
-        <Section name="s3" description="not equal" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+      <Section name="doesn't equal" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Section name="not equal" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
             <Original>
               a != b
@@ -8214,8 +11820,8 @@
         </Section>
         <OverallResults successes="1" failures="0" expectedFailures="0"/>
       </Section>
-      <Section name="s1" description="doesn't equal" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
-        <Section name="s4" description="less than" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+      <Section name="doesn't equal" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Section name="less than" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
             <Original>
               a &lt; b
@@ -8231,7 +11837,7 @@
       <OverallResult success="false"/>
     </TestCase>
     <TestCase name="nested SECTION tests" tags="[.][failing][sections]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
-      <Section name="s1" description="doesn't equal" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+      <Section name="doesn't equal" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
         <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
           <Original>
             a != b
@@ -8248,7 +11854,7 @@
             2 != 1
           </Expanded>
         </Expression>
-        <Section name="s2" description="not equal" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+        <Section name="not equal" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
             <Original>
               a != b
@@ -8288,6 +11894,42 @@
     <TestCase name="not allowed" tags="[!throws]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
       <OverallResult success="true"/>
     </TestCase>
+    <TestCase name="not prints unscoped info from previous failures" tags="[.][failing][info][unscoped]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+      <Info>
+        this MAY be seen only for the FIRST assertion IF info is printed for passing assertions
+      </Info>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+        <Original>
+          true
+        </Original>
+        <Expanded>
+          true
+        </Expanded>
+      </Expression>
+      <Info>
+        this MAY be seen only for the SECOND assertion IF info is printed for passing assertions
+      </Info>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+        <Original>
+          true
+        </Original>
+        <Expanded>
+          true
+        </Expanded>
+      </Expression>
+      <Info>
+        this SHOULD be seen
+      </Info>
+      <Expression success="false" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+        <Original>
+          false
+        </Original>
+        <Expanded>
+          false
+        </Expanded>
+      </Expression>
+      <OverallResult success="false"/>
+    </TestCase>
     <TestCase name="null strings" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
         <Original>
@@ -8342,8 +11984,80 @@
       </Expression>
       <OverallResult success="true"/>
     </TestCase>
+    <TestCase name="print unscoped info if passing unscoped info is printed" tags="[info][unscoped]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+      <Info>
+        this MAY be seen IF info is printed for passing assertions
+      </Info>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+        <Original>
+          true
+        </Original>
+        <Expanded>
+          true
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="prints unscoped info on failure" tags="[.][failing][info][unscoped]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+      <Info>
+        this SHOULD be seen
+      </Info>
+      <Info>
+        this SHOULD also be seen
+      </Info>
+      <Expression success="false" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+        <Original>
+          false
+        </Original>
+        <Expanded>
+          false
+        </Expanded>
+      </Expression>
+      <OverallResult success="false"/>
+    </TestCase>
+    <TestCase name="prints unscoped info only for the first assertion" tags="[.][failing][info][unscoped]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+      <Info>
+        this SHOULD be seen only ONCE
+      </Info>
+      <Expression success="false" type="CHECK" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+        <Original>
+          false
+        </Original>
+        <Expanded>
+          false
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+        <Original>
+          true
+        </Original>
+        <Expanded>
+          true
+        </Expanded>
+      </Expression>
+      <Info>
+        this MAY also be seen only ONCE IF info is printed for passing assertions
+      </Info>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+        <Original>
+          true
+        </Original>
+        <Expanded>
+          true
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+        <Original>
+          true
+        </Original>
+        <Expanded>
+          true
+        </Expanded>
+      </Expression>
+      <OverallResult success="false"/>
+    </TestCase>
     <TestCase name="random SECTION tests" tags="[.][failing][sections]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
-      <Section name="s1" description="doesn't equal" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+      <Section name="doesn't equal" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
         <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
           <Original>
             a != b
@@ -8362,7 +12076,7 @@
         </Expression>
         <OverallResults successes="2" failures="0" expectedFailures="0"/>
       </Section>
-      <Section name="s2" description="not equal" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+      <Section name="not equal" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
         <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
           <Original>
             a != b
@@ -8375,7 +12089,7 @@
       </Section>
       <OverallResult success="true"/>
     </TestCase>
-    <TestCase name="replaceInPlace" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
+    <TestCase name="replaceInPlace" tags="[StringManip][Strings]" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
       <Section name="replace single char" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
         <Expression success="true" type="CHECK" filename="projects/<exe-name>/IntrospectiveTests/String.tests.cpp" >
           <Original>
@@ -8545,6 +12259,49 @@
       </Expression>
       <OverallResult success="false"/>
     </TestCase>
+    <TestCase name="stacks unscoped info in loops" tags="[.][failing][info][unscoped]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+      <Info>
+        Count 1 to 3...
+      </Info>
+      <Info>
+        1
+      </Info>
+      <Info>
+        2
+      </Info>
+      <Info>
+        3
+      </Info>
+      <Expression success="false" type="CHECK" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+        <Original>
+          false
+        </Original>
+        <Expanded>
+          false
+        </Expanded>
+      </Expression>
+      <Info>
+        Count 4 to 6...
+      </Info>
+      <Info>
+        4
+      </Info>
+      <Info>
+        5
+      </Info>
+      <Info>
+        6
+      </Info>
+      <Expression success="false" type="CHECK" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
+        <Original>
+          false
+        </Original>
+        <Expanded>
+          false
+        </Expanded>
+      </Expression>
+      <OverallResult success="false"/>
+    </TestCase>
     <TestCase name="std::map is convertible string" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
       <Section name="empty" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
         <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
@@ -8667,6 +12424,45 @@
       </Expression>
       <OverallResult success="false"/>
     </TestCase>
+    <TestCase name="stringify ranges" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
+        <Original>
+          ::Catch::Detail::stringify(streamable_range{}) == "op&lt;&lt;(streamable_range)"
+        </Original>
+        <Expanded>
+          "op&lt;&lt;(streamable_range)"
+==
+"op&lt;&lt;(streamable_range)"
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
+        <Original>
+          ::Catch::Detail::stringify(stringmaker_range{}) == "stringmaker(streamable_range)"
+        </Original>
+        <Expanded>
+          "stringmaker(streamable_range)"
+==
+"stringmaker(streamable_range)"
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
+        <Original>
+          ::Catch::Detail::stringify(just_range{}) == "{ 1, 2, 3, 4 }"
+        </Original>
+        <Expanded>
+          "{ 1, 2, 3, 4 }" == "{ 1, 2, 3, 4 }"
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
+        <Original>
+          ::Catch::Detail::stringify(disabled_range{}) == "{ !!! }"
+        </Original>
+        <Expanded>
+          "{ !!! }" == "{ !!! }"
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
     <TestCase name="stringify( has_maker )" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
         <Original>
@@ -8680,7 +12476,7 @@
       </Expression>
       <OverallResult success="true"/>
     </TestCase>
-    <TestCase name="stringify( has_maker_and_toString )" tags="[.][toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
+    <TestCase name="stringify( has_maker_and_operator )" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
         <Original>
           ::Catch::Detail::stringify( item ) == "StringMaker&lt;has_maker_and_operator>"
@@ -8693,6 +12489,17 @@
       </Expression>
       <OverallResult success="true"/>
     </TestCase>
+    <TestCase name="stringify( has_neither )" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
+        <Original>
+          ::Catch::Detail::stringify(item) == "{ !!! }"
+        </Original>
+        <Expanded>
+          "{ !!! }" == "{ !!! }"
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
     <TestCase name="stringify( has_operator )" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
       <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
         <Original>
@@ -8706,6 +12513,134 @@
       </Expression>
       <OverallResult success="true"/>
     </TestCase>
+    <TestCase name="stringify( has_template_operator )" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
+        <Original>
+          ::Catch::Detail::stringify( item ) == "operator&lt;&lt;( has_template_operator )"
+        </Original>
+        <Expanded>
+          "operator&lt;&lt;( has_template_operator )"
+==
+"operator&lt;&lt;( has_template_operator )"
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="stringify( vectors&lt;has_maker> )" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
+        <Original>
+          ::Catch::Detail::stringify( v ) == "{ StringMaker&lt;has_maker> }"
+        </Original>
+        <Expanded>
+          "{ StringMaker&lt;has_maker> }"
+==
+"{ StringMaker&lt;has_maker> }"
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="stringify( vectors&lt;has_maker_and_operator> )" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
+        <Original>
+          ::Catch::Detail::stringify( v ) == "{ StringMaker&lt;has_maker_and_operator> }"
+        </Original>
+        <Expanded>
+          "{ StringMaker&lt;has_maker_and_operator> }"
+==
+"{ StringMaker&lt;has_maker_and_operator> }"
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="stringify( vectors&lt;has_operator> )" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
+        <Original>
+          ::Catch::Detail::stringify( v ) == "{ operator&lt;&lt;( has_operator ) }"
+        </Original>
+        <Expanded>
+          "{ operator&lt;&lt;( has_operator ) }"
+==
+"{ operator&lt;&lt;( has_operator ) }"
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="strlen3" tags="[generators]" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          data.str.size() == data.len
+        </Original>
+        <Expanded>
+          3 == 3
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          data.str.size() == data.len
+        </Original>
+        <Expanded>
+          3 == 3
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          data.str.size() == data.len
+        </Original>
+        <Expanded>
+          5 == 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          data.str.size() == data.len
+        </Original>
+        <Expanded>
+          4 == 4
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="tables" tags="[generators]" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          strlen(std::get&lt;0>(data)) == static_cast&lt;size_t>(std::get&lt;1>(data))
+        </Original>
+        <Expanded>
+          5 == 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          strlen(std::get&lt;0>(data)) == static_cast&lt;size_t>(std::get&lt;1>(data))
+        </Original>
+        <Expanded>
+          6 == 6
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          strlen(std::get&lt;0>(data)) == static_cast&lt;size_t>(std::get&lt;1>(data))
+        </Original>
+        <Expanded>
+          5 == 5
+        </Expanded>
+      </Expression>
+      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
+        <Original>
+          strlen(std::get&lt;0>(data)) == static_cast&lt;size_t>(std::get&lt;1>(data))
+        </Original>
+        <Expanded>
+          6 == 6
+        </Expanded>
+      </Expression>
+      <OverallResult success="true"/>
+    </TestCase>
+    <TestCase name="thrown std::strings are translated" tags="[!throws][.][failing]" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
+      <Exception filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
+        Why would you throw a std::string?
+      </Exception>
+      <OverallResult success="false"/>
+    </TestCase>
     <TestCase name="toString on const wchar_t const pointer returns the string contents" tags="[toString]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
       <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
         <Original>
@@ -8750,84 +12685,6 @@
       </Expression>
       <OverallResult success="true"/>
     </TestCase>
-    <TestCase name="toString streamable range" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
-      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
-        <Original>
-          ::Catch::Detail::stringify(streamable_range{}) == "op&lt;&lt;(streamable_range)"
-        </Original>
-        <Expanded>
-          "op&lt;&lt;(streamable_range)"
-==
-"op&lt;&lt;(streamable_range)"
-        </Expanded>
-      </Expression>
-      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
-        <Original>
-          ::Catch::Detail::stringify(stringmaker_range{}) == "stringmaker(streamable_range)"
-        </Original>
-        <Expanded>
-          "stringmaker(streamable_range)"
-==
-"stringmaker(streamable_range)"
-        </Expanded>
-      </Expression>
-      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
-        <Original>
-          ::Catch::Detail::stringify(just_range{}) == "{ 1, 2, 3, 4 }"
-        </Original>
-        <Expanded>
-          "{ 1, 2, 3, 4 }" == "{ 1, 2, 3, 4 }"
-        </Expanded>
-      </Expression>
-      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
-        <Original>
-          ::Catch::Detail::stringify(disabled_range{}) == "{?}"
-        </Original>
-        <Expanded>
-          "{?}" == "{?}"
-        </Expanded>
-      </Expression>
-      <OverallResult success="true"/>
-    </TestCase>
-    <TestCase name="toString( vectors&lt;has_maker> )" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
-      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
-        <Original>
-          ::Catch::Detail::stringify( v ) == "{ StringMaker&lt;has_maker> }"
-        </Original>
-        <Expanded>
-          "{ StringMaker&lt;has_maker> }"
-==
-"{ StringMaker&lt;has_maker> }"
-        </Expanded>
-      </Expression>
-      <OverallResult success="true"/>
-    </TestCase>
-    <TestCase name="toString( vectors&lt;has_maker_and_operator> )" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
-      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
-        <Original>
-          ::Catch::Detail::stringify( v ) == "{ StringMaker&lt;has_maker_and_operator> }"
-        </Original>
-        <Expanded>
-          "{ StringMaker&lt;has_maker_and_operator> }"
-==
-"{ StringMaker&lt;has_maker_and_operator> }"
-        </Expanded>
-      </Expression>
-      <OverallResult success="true"/>
-    </TestCase>
-    <TestCase name="toString( vectors&lt;has_operator> )" tags="[toString]" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
-      <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringWhich.tests.cpp" >
-        <Original>
-          ::Catch::Detail::stringify( v ) == "{ operator&lt;&lt;( has_operator ) }"
-        </Original>
-        <Expanded>
-          "{ operator&lt;&lt;( has_operator ) }"
-==
-"{ operator&lt;&lt;( has_operator ) }"
-        </Expanded>
-      </Expression>
-      <OverallResult success="true"/>
-    </TestCase>
     <TestCase name="toString(enum class w/operator&lt;&lt;)" tags="[enum][enumClass][toString]" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
       <Expression success="true" type="CHECK" filename="projects/<exe-name>/UsageTests/EnumToString.tests.cpp" >
         <Original>
@@ -9288,15 +13145,15 @@
       <OverallResult success="true"/>
     </TestCase>
     <TestCase name="xmlentitycheck" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
-      <Section name="embedded xml" description="&lt;test>it should be possible to embed xml characters, such as &lt;, &quot; or &amp;, or even whole &lt;xml>documents&lt;/xml> within an attribute&lt;/test>" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+      <Section name="embedded xml: &lt;test>it should be possible to embed xml characters, such as &lt;, &quot; or &amp;, or even whole &lt;xml>documents&lt;/xml> within an attribute&lt;/test>" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
         <OverallResults successes="1" failures="0" expectedFailures="0"/>
       </Section>
-      <Section name="encoded chars" description="these should all be encoded: &amp;&amp;&amp;&quot;&quot;&quot;&lt;&lt;&lt;&amp;&quot;&lt;&lt;&amp;&quot;" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
+      <Section name="encoded chars: these should all be encoded: &amp;&amp;&amp;&quot;&quot;&quot;&lt;&lt;&lt;&amp;&quot;&lt;&lt;&amp;&quot;" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
         <OverallResults successes="1" failures="0" expectedFailures="0"/>
       </Section>
       <OverallResult success="true"/>
     </TestCase>
-    <OverallResults successes="866" failures="121" expectedFailures="21"/>
+    <OverallResults successes="1250" failures="139" expectedFailures="21"/>
   </Group>
-  <OverallResults successes="866" failures="120" expectedFailures="21"/>
+  <OverallResults successes="1250" failures="138" expectedFailures="21"/>
 </Catch>
diff --git a/projects/SelfTest/IntrospectiveTests/CmdLine.tests.cpp b/projects/SelfTest/IntrospectiveTests/CmdLine.tests.cpp
index a073585..9b5b0ed 100644
--- a/projects/SelfTest/IntrospectiveTests/CmdLine.tests.cpp
+++ b/projects/SelfTest/IntrospectiveTests/CmdLine.tests.cpp
@@ -15,7 +15,7 @@
 #   pragma clang diagnostic ignored "-Wc++98-compat"
 #endif
 
-inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ return Catch::makeTestCase( nullptr, "", name, desc, CATCH_INTERNAL_LINEINFO ); }
+inline Catch::TestCase fakeTestCase(const char* name, const char* desc = "") { return Catch::makeTestCase(nullptr, "", { name, desc }, CATCH_INTERNAL_LINEINFO); }
 
 TEST_CASE( "Parse test names and tags" ) {
 
@@ -280,7 +280,6 @@
         CHECK(config.processName == "");
     }
 
-
     SECTION("default - no arguments") {
         auto result = cli.parse({"test"});
         CHECK(result);
@@ -288,15 +287,19 @@
         CHECK(config.shouldDebugBreak == false);
         CHECK(config.abortAfter == -1);
         CHECK(config.noThrow == false);
-        CHECK(config.reporterNames.empty());
+        CHECK(config.reporterName == "console");
+
+        Catch::Config cfg(config);
+        CHECK_FALSE(cfg.hasTestFilters());
     }
 
     SECTION("test lists") {
-        SECTION("1 test", "Specify one test case using") {
+        SECTION("Specify one test case using") {
             auto result = cli.parse({"test", "test1"});
             CHECK(result);
 
             Catch::Config cfg(config);
+            REQUIRE(cfg.hasTestFilters());
             REQUIRE(cfg.testSpec().matches(fakeTestCase("notIncluded")) == false);
             REQUIRE(cfg.testSpec().matches(fakeTestCase("test1")));
         }
@@ -305,6 +308,7 @@
             CHECK(result);
 
             Catch::Config cfg(config);
+            REQUIRE(cfg.hasTestFilters());
             REQUIRE(cfg.testSpec().matches(fakeTestCase("test1")) == false);
             REQUIRE(cfg.testSpec().matches(fakeTestCase("alwaysIncluded")));
         }
@@ -314,6 +318,7 @@
             CHECK(result);
 
             Catch::Config cfg(config);
+            REQUIRE(cfg.hasTestFilters());
             REQUIRE(cfg.testSpec().matches(fakeTestCase("test1")) == false);
             REQUIRE(cfg.testSpec().matches(fakeTestCase("alwaysIncluded")));
         }
@@ -324,28 +329,31 @@
         SECTION("-r/console") {
             CHECK(cli.parse({"test", "-r", "console"}));
 
-            REQUIRE(config.reporterNames[0] == "console");
+            REQUIRE(config.reporterName == "console");
         }
         SECTION("-r/xml") {
             CHECK(cli.parse({"test", "-r", "xml"}));
 
-            REQUIRE(config.reporterNames[0] == "xml");
-        }
-        SECTION("-r xml and junit") {
-            CHECK(cli.parse({"test", "-r", "xml", "-r", "junit"}));
-
-            REQUIRE(config.reporterNames.size() == 2);
-            REQUIRE(config.reporterNames[0] == "xml");
-            REQUIRE(config.reporterNames[1] == "junit");
+            REQUIRE(config.reporterName == "xml");
         }
         SECTION("--reporter/junit") {
             CHECK(cli.parse({"test", "--reporter", "junit"}));
 
-            REQUIRE(config.reporterNames[0] == "junit");
+            REQUIRE(config.reporterName == "junit");
+        }
+        SECTION("Only one reporter is accepted") {
+            REQUIRE_FALSE(cli.parse({ "test", "-r", "xml", "-r", "junit" }));
+        }
+        SECTION("must match one of the available ones") {
+            auto result = cli.parse({"test", "--reporter", "unsupported"});
+            CHECK(!result);
+
+#ifndef CATCH_CONFIG_DISABLE_MATCHERS
+            REQUIRE_THAT(result.errorMessage(), Contains("Unrecognized reporter"));
+#endif
         }
     }
 
-
     SECTION("debugger") {
         SECTION("-b") {
             CHECK(cli.parse({"test", "-b"}));
diff --git a/projects/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp b/projects/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp
new file mode 100644
index 0000000..de8b0ff
--- /dev/null
+++ b/projects/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp
@@ -0,0 +1,209 @@
+#include "catch.hpp"
+
+// Tests of generator implementation details
+TEST_CASE("Generators internals", "[generators][internals]") {
+    using namespace Catch::Generators;
+
+    SECTION("Single value") {
+        auto gen = value(123);
+        REQUIRE(gen.get() == 123);
+        REQUIRE_FALSE(gen.next());
+    }
+    SECTION("Preset values") {
+        auto gen = values({ 1, 3, 5 });
+        REQUIRE(gen.get() == 1);
+        REQUIRE(gen.next());
+        REQUIRE(gen.get() == 3);
+        REQUIRE(gen.next());
+        REQUIRE(gen.get() == 5);
+        REQUIRE_FALSE(gen.next());
+    }
+    SECTION("Generator combinator") {
+        auto gen = makeGenerators(1, 5, values({ 2, 4 }), 0);
+        REQUIRE(gen.get() == 1);
+        REQUIRE(gen.next());
+        REQUIRE(gen.get() == 5);
+        REQUIRE(gen.next());
+        REQUIRE(gen.get() == 2);
+        REQUIRE(gen.next());
+        REQUIRE(gen.get() == 4);
+        REQUIRE(gen.next());
+        REQUIRE(gen.get() == 0);
+        REQUIRE_FALSE(gen.next());
+    }
+    SECTION("Explicitly typed generator sequence") {
+        auto gen = makeGenerators(as<std::string>{}, "aa", "bb", "cc");
+        // This just checks that the type is std::string:
+        REQUIRE(gen.get().size() == 2);
+        // Iterate over the generator
+        REQUIRE(gen.get() == "aa");
+        REQUIRE(gen.next());
+        REQUIRE(gen.get() == "bb");
+        REQUIRE(gen.next());
+        REQUIRE(gen.get() == "cc");
+        REQUIRE_FALSE(gen.next());
+    }
+    SECTION("Filter generator") {
+        // Normal usage
+        auto gen = filter([] (int i) { return i != 2; }, values({ 2, 1, 2, 3, 2, 2 }));
+        REQUIRE(gen.get() == 1);
+        REQUIRE(gen.next());
+        REQUIRE(gen.get() == 3);
+        REQUIRE_FALSE(gen.next());
+
+        // Completely filtered-out generator should throw on construction
+        REQUIRE_THROWS_AS(filter([] (int) { return false; }, value(1)), Catch::GeneratorException);
+    }
+    SECTION("Take generator") {
+        SECTION("Take less") {
+            auto gen = take(2, values({ 1, 2, 3 }));
+            REQUIRE(gen.get() == 1);
+            REQUIRE(gen.next());
+            REQUIRE(gen.get() == 2);
+            REQUIRE_FALSE(gen.next());
+        }
+        SECTION("Take more") {
+            auto gen = take(2, value(1));
+            REQUIRE(gen.get() == 1);
+            REQUIRE_FALSE(gen.next());
+        }
+    }
+    SECTION("Map") {
+        auto gen = map<double>([] (int i) {return 2.0 * i; }, values({ 1, 2, 3 }));
+        REQUIRE(gen.get() == 2.0);
+        REQUIRE(gen.next());
+        REQUIRE(gen.get() == 4.0);
+        REQUIRE(gen.next());
+        REQUIRE(gen.get() == 6.0);
+        REQUIRE_FALSE(gen.next());
+    }
+    SECTION("Repeat") {
+        SECTION("Singular repeat") {
+            auto gen = repeat(1, value(3));
+            REQUIRE(gen.get() == 3);
+            REQUIRE_FALSE(gen.next());
+        }
+        SECTION("Actual repeat") {
+            auto gen = repeat(2, values({ 1, 2, 3 }));
+            REQUIRE(gen.get() == 1);
+            REQUIRE(gen.next());
+            REQUIRE(gen.get() == 2);
+            REQUIRE(gen.next());
+            REQUIRE(gen.get() == 3);
+            REQUIRE(gen.next());
+            REQUIRE(gen.get() == 1);
+            REQUIRE(gen.next());
+            REQUIRE(gen.get() == 2);
+            REQUIRE(gen.next());
+            REQUIRE(gen.get() == 3);
+            REQUIRE_FALSE(gen.next());
+        }
+    }
+    SECTION("Range") {
+        SECTION("Positive auto step") {
+            SECTION("Integer") {
+                auto gen = range(-2, 2);
+                REQUIRE(gen.get() == -2);
+                REQUIRE(gen.next());
+                REQUIRE(gen.get() == -1);
+                REQUIRE(gen.next());
+                REQUIRE(gen.get() == 0);
+                REQUIRE(gen.next());
+                REQUIRE(gen.get() == 1);
+                REQUIRE_FALSE(gen.next());
+            }
+        }
+        SECTION("Negative auto step") {
+            SECTION("Integer") {
+                auto gen = range(2, -2);
+                REQUIRE(gen.get() == 2);
+                REQUIRE(gen.next());
+                REQUIRE(gen.get() == 1);
+                REQUIRE(gen.next());
+                REQUIRE(gen.get() == 0);
+                REQUIRE(gen.next());
+                REQUIRE(gen.get() == -1);
+                REQUIRE_FALSE(gen.next());
+            }
+        }
+        SECTION("Positive manual step") {
+            SECTION("Integer") {
+                SECTION("Exact") {
+                    auto gen = range(-7, 5, 3);
+                    REQUIRE(gen.get() == -7);
+                    REQUIRE(gen.next());
+                    REQUIRE(gen.get() == -4);
+                    REQUIRE(gen.next());
+                    REQUIRE(gen.get() == -1);
+                    REQUIRE(gen.next());
+                    REQUIRE(gen.get() == 2);
+                    REQUIRE_FALSE(gen.next());
+                }
+                SECTION("Slightly over end") {
+                    auto gen = range(-7, 4, 3);
+                    REQUIRE(gen.get() == -7);
+                    REQUIRE(gen.next());
+                    REQUIRE(gen.get() == -4);
+                    REQUIRE(gen.next());
+                    REQUIRE(gen.get() == -1);
+                    REQUIRE(gen.next());
+                    REQUIRE(gen.get() == 2);
+                    REQUIRE_FALSE(gen.next());
+                }
+                SECTION("Slightly under end") {
+                    auto gen = range(-7, 6, 3);
+                    REQUIRE(gen.get() == -7);
+                    REQUIRE(gen.next());
+                    REQUIRE(gen.get() == -4);
+                    REQUIRE(gen.next());
+                    REQUIRE(gen.get() == -1);
+                    REQUIRE(gen.next());
+                    REQUIRE(gen.get() == 2);
+                    REQUIRE(gen.next());
+                    REQUIRE(gen.get() == 5);
+                    REQUIRE_FALSE(gen.next());
+                }
+            }
+        }
+        SECTION("Negative manual step") {
+            SECTION("Integer") {
+                SECTION("Exact") {
+                    auto gen = range(5, -7, -3);
+                    REQUIRE(gen.get() == 5);
+                    REQUIRE(gen.next());
+                    REQUIRE(gen.get() == 2);
+                    REQUIRE(gen.next());
+                    REQUIRE(gen.get() == -1);
+                    REQUIRE(gen.next());
+                    REQUIRE(gen.get() == -4);
+                    REQUIRE_FALSE(gen.next());
+                }
+                SECTION("Slightly over end") {
+                    auto gen = range(5, -6, -3);
+                    REQUIRE(gen.get() == 5);
+                    REQUIRE(gen.next());
+                    REQUIRE(gen.get() == 2);
+                    REQUIRE(gen.next());
+                    REQUIRE(gen.get() == -1);
+                    REQUIRE(gen.next());
+                    REQUIRE(gen.get() == -4);
+                    REQUIRE_FALSE(gen.next());
+                }
+                SECTION("Slightly under end") {
+                    auto gen = range(5, -8, -3);
+                    REQUIRE(gen.get() == 5);
+                    REQUIRE(gen.next());
+                    REQUIRE(gen.get() == 2);
+                    REQUIRE(gen.next());
+                    REQUIRE(gen.get() == -1);
+                    REQUIRE(gen.next());
+                    REQUIRE(gen.get() == -4);
+                    REQUIRE(gen.next());
+                    REQUIRE(gen.get() == -7);
+                    REQUIRE_FALSE(gen.next());
+                }
+            }
+        }
+    }
+
+}
diff --git a/projects/SelfTest/IntrospectiveTests/PartTracker.tests.cpp b/projects/SelfTest/IntrospectiveTests/PartTracker.tests.cpp
index 042c03a..9372b1c 100644
--- a/projects/SelfTest/IntrospectiveTests/PartTracker.tests.cpp
+++ b/projects/SelfTest/IntrospectiveTests/PartTracker.tests.cpp
@@ -21,24 +21,17 @@
 
 } // namespace Catch
 
-inline Catch::TrackerContext& C_A_T_C_H_Context() {
-    return Catch::TrackerContext::instance();
-}
-
 // -------------------
 
 #include "catch.hpp"
 
 using namespace Catch;
 
-//inline void testCase( Catch::LocalContext const& C_A_T_C_H_Context ) {
-//
-//    REQUIRE( C_A_T_C_H_Context().i() == 42 );
-//}
-
+namespace {
 Catch::TestCaseTracking::NameAndLocation makeNAL( std::string const& name ) {
     return Catch::TestCaseTracking::NameAndLocation( name, Catch::SourceLineInfo("",0) );
 }
+}
 
 TEST_CASE( "Tracker" ) {
 
@@ -180,154 +173,34 @@
         testCase.close();
         REQUIRE( testCase.isComplete() );
     }
+}
 
-    SECTION( "start a generator" ) {
-        IndexTracker& g1 = IndexTracker::acquire( ctx, makeNAL( "G1" ), 2 );
-        REQUIRE( g1.isOpen() );
-        REQUIRE( g1.index() == 0 );
+static bool previouslyRun = false;
+static bool previouslyRunNested = false;
 
-        REQUIRE( g1.isComplete() == false );
-        REQUIRE( s1.isComplete() == false );
+TEST_CASE( "#1394", "[.][approvals][tracker]" ) {
+    // -- Don't re-run after specified section is done
+    REQUIRE(previouslyRun == false);
 
-        SECTION( "close outer section" )
-        {
-            s1.close();
-            REQUIRE( s1.isComplete() == false );
-            testCase.close();
-            REQUIRE( testCase.isSuccessfullyCompleted() == false );
+    SECTION( "RunSection" ) {
+        previouslyRun = true;
+    }
+    SECTION( "SkipSection" ) {
+        // cause an error if this section is called because it shouldn't be
+        REQUIRE(1 == 0);
+    }
+}
 
-            SECTION( "Re-enter for second generation" ) {
-                ctx.startCycle();
-                ITracker& testCase2 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) );
-                REQUIRE( testCase2.isOpen() );
+TEST_CASE( "#1394 nested", "[.][approvals][tracker]" ) {
+    REQUIRE(previouslyRunNested == false);
 
-                ITracker& s1b = SectionTracker::acquire( ctx, makeNAL( "S1" ) );
-                REQUIRE( s1b.isOpen() );
-
-
-                IndexTracker& g1b = IndexTracker::acquire( ctx, makeNAL( "G1" ), 2 );
-                REQUIRE( g1b.isOpen() );
-                REQUIRE( g1b.index() == 1 );
-
-                REQUIRE( s1.isComplete() == false );
-
-                s1b.close();
-                REQUIRE( s1b.isComplete() );
-                REQUIRE( g1b.isComplete() );
-                testCase2.close();
-                REQUIRE( testCase2.isComplete() );
-            }
+    SECTION( "NestedRunSection" ) {
+        SECTION( "s1" ) {
+            previouslyRunNested = true;
         }
-        SECTION( "Start a new inner section" ) {
-            ITracker& s2 = SectionTracker::acquire( ctx, makeNAL( "S2" ) );
-            REQUIRE( s2.isOpen() );
-
-            s2.close();
-            REQUIRE( s2.isComplete() );
-
-            s1.close();
-            REQUIRE( s1.isComplete() == false );
-
-            testCase.close();
-            REQUIRE( testCase.isComplete() == false );
-
-            SECTION( "Re-enter for second generation" ) {
-                ctx.startCycle();
-                ITracker& testCase2 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) );
-                REQUIRE( testCase2.isOpen() );
-
-                ITracker& s1b = SectionTracker::acquire( ctx, makeNAL( "S1" ) );
-                REQUIRE( s1b.isOpen() );
-
-                // generator - next value
-                IndexTracker& g1b = IndexTracker::acquire( ctx, makeNAL( "G1" ), 2 );
-                REQUIRE( g1b.isOpen() );
-                REQUIRE( g1b.index() == 1 );
-
-                // inner section again
-                ITracker& s2b = SectionTracker::acquire( ctx, makeNAL( "S2" ) );
-                REQUIRE( s2b.isOpen() );
-
-                s2b.close();
-                REQUIRE( s2b.isComplete() );
-
-                s1b.close();
-                REQUIRE( g1b.isComplete() );
-                REQUIRE( s1b.isComplete() );
-
-                testCase2.close();
-                REQUIRE( testCase2.isComplete() );
-            }
-        }
-
-        SECTION( "Fail an inner section" ) {
-            ITracker& s2 = SectionTracker::acquire( ctx, makeNAL( "S2" ) );
-            REQUIRE( s2.isOpen() );
-
-            s2.fail();
-            REQUIRE( s2.isComplete() );
-            REQUIRE( s2.isSuccessfullyCompleted() == false );
-
-            s1.close();
-            REQUIRE( s1.isComplete() == false );
-
-            testCase.close();
-            REQUIRE( testCase.isComplete() == false );
-
-            SECTION( "Re-enter for second generation" ) {
-                ctx.startCycle();
-                ITracker& testCase2 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) );
-                REQUIRE( testCase2.isOpen() );
-
-                ITracker& s1b = SectionTracker::acquire( ctx, makeNAL( "S1" ) );
-                REQUIRE( s1b.isOpen() );
-
-                // generator - still same value
-                IndexTracker& g1b = IndexTracker::acquire( ctx, makeNAL( "G1" ), 2 );
-                REQUIRE( g1b.isOpen() );
-                REQUIRE( g1b.index() == 0 );
-
-                // inner section again - this time won't open
-                ITracker& s2b = SectionTracker::acquire( ctx, makeNAL( "S2" ) );
-                REQUIRE( s2b.isOpen() == false );
-
-                s1b.close();
-                REQUIRE( g1b.isComplete() == false );
-                REQUIRE( s1b.isComplete() == false );
-
-                testCase2.close();
-                REQUIRE( testCase2.isComplete() == false );
-
-                // Another cycle - now should complete
-                ctx.startCycle();
-                ITracker& testCase3 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) );
-                REQUIRE( testCase3.isOpen() );
-
-                ITracker& s1c = SectionTracker::acquire( ctx, makeNAL( "S1" ) );
-                REQUIRE( s1c.isOpen() );
-
-                // generator - now next value
-                IndexTracker& g1c = IndexTracker::acquire( ctx, makeNAL( "G1" ), 2 );
-                REQUIRE( g1c.isOpen() );
-                REQUIRE( g1c.index() == 1 );
-
-                // inner section - now should open again
-                ITracker& s2c = SectionTracker::acquire( ctx, makeNAL( "S2" ) );
-                REQUIRE( s2c.isOpen() );
-
-                s2c.close();
-                REQUIRE( s2c.isComplete() );
-
-                s1c.close();
-                REQUIRE( g1c.isComplete() );
-                REQUIRE( s1c.isComplete() );
-
-                testCase3.close();
-                REQUIRE( testCase3.isComplete() );
-            }
-        }
-        // !TBD"
-        //   nested generator
-        //   two sections within a generator
+    }
+    SECTION( "NestedSkipSection" ) {
+        // cause an error if this section is called because it shouldn't be
+        REQUIRE(1 == 0);
     }
 }
diff --git a/projects/SelfTest/IntrospectiveTests/String.tests.cpp b/projects/SelfTest/IntrospectiveTests/String.tests.cpp
index 9c9c559..ae21bb3 100644
--- a/projects/SelfTest/IntrospectiveTests/String.tests.cpp
+++ b/projects/SelfTest/IntrospectiveTests/String.tests.cpp
@@ -14,31 +14,24 @@
         static auto isSubstring( StringRef const& stringRef ) -> bool {
             return stringRef.isSubstring();
         }
-        static auto data( StringRef const& stringRef ) -> char const* {
-            return stringRef.data();
-        }
     };
 
+
+    namespace {
     auto isOwned( StringRef const& stringRef ) -> bool {
         return StringRefTestAccess::isOwned( stringRef );
     }
     auto isSubstring( StringRef const& stringRef ) -> bool {
         return StringRefTestAccess::isSubstring( stringRef );
     }
-    auto data( StringRef const& stringRef ) -> char const* {
-        return StringRefTestAccess::data( stringRef );
-    }
-} // namespace Catch2
+    } // end anonymous namespace
 
-namespace Catch {
-    inline auto toString( Catch::StringRef const& stringRef ) -> std::string {
-        return std::string( data( stringRef ), stringRef.size() );
-    }
 } // namespace Catch
 
-TEST_CASE( "StringRef", "[Strings]" ) {
-    
+TEST_CASE( "StringRef", "[Strings][StringRef]" ) {
+
     using Catch::StringRef;
+    using Catch::isOwned; using Catch::isSubstring;
 
     SECTION( "Empty string" ) {
         StringRef empty;
@@ -46,21 +39,21 @@
         REQUIRE( empty.size() == 0 );
         REQUIRE( std::strcmp( empty.c_str(), "" ) == 0 );
     }
-    
+
     SECTION( "From string literal" ) {
         StringRef s = "hello";
         REQUIRE( s.empty() == false );
         REQUIRE( s.size() == 5 );
         REQUIRE( isSubstring( s ) == false );
-        
-        auto rawChars = data( s );
+
+        auto rawChars = s.currentData();
         REQUIRE( std::strcmp( rawChars, "hello" ) == 0 );
-        
+
         SECTION( "c_str() does not cause copy" ) {
             REQUIRE( isOwned( s ) == false );
-            
+
             REQUIRE( s.c_str() == rawChars );
-            
+
             REQUIRE( isOwned( s ) == false );
         }
     }
@@ -69,19 +62,18 @@
         REQUIRE( original == "original" );
         REQUIRE( isSubstring( original ) );
         REQUIRE( isOwned( original ) == false );
-        
+
         original.c_str(); // Forces it to take ownership
-        
+
         REQUIRE( isSubstring( original ) == false );
         REQUIRE( isOwned( original ) );
-        
     }
-    
-    
+
+
     SECTION( "Substrings" ) {
         StringRef s = "hello world!";
         StringRef ss = s.substr(0, 5);
-        
+
         SECTION( "zero-based substring" ) {
             REQUIRE( ss.empty() == false );
             REQUIRE( ss.size() == 5 );
@@ -91,33 +83,33 @@
         SECTION( "c_str() causes copy" ) {
             REQUIRE( isSubstring( ss ) );
             REQUIRE( isOwned( ss ) == false );
-            
-            auto rawChars = data( ss );
-            REQUIRE( rawChars == data( s ) ); // same pointer value
+
+            auto rawChars = ss.currentData();
+            REQUIRE( rawChars == s.currentData() ); // same pointer value
             REQUIRE( ss.c_str() != rawChars );
-            
+
             REQUIRE( isSubstring( ss ) == false );
             REQUIRE( isOwned( ss ) );
-            
-            REQUIRE( data( ss ) != data( s ) ); // different pointer value
+
+            REQUIRE( ss.currentData() != s.currentData() ); // different pointer value
         }
-        
+
         SECTION( "non-zero-based substring") {
             ss = s.substr( 6, 6 );
             REQUIRE( ss.size() == 6 );
             REQUIRE( std::strcmp( ss.c_str(), "world!" ) == 0 );
         }
-        
+
         SECTION( "Pointer values of full refs should match" ) {
             StringRef s2 = s;
             REQUIRE( s.c_str() == s2.c_str() );
         }
-        
+
         SECTION( "Pointer values of substring refs should not match" ) {
             REQUIRE( s.c_str() != ss.c_str() );
         }
     }
-    
+
     SECTION( "Comparisons" ) {
         REQUIRE( StringRef("hello") == StringRef("hello") );
         REQUIRE( StringRef("hello") != StringRef("cello") );
@@ -164,9 +156,21 @@
             REQUIRE( stdStr.size() == sr.size() );
         }
     }
+
+    SECTION( "Counting utf-8 codepoints" ) {
+        StringRef ascii = "just a plain old boring ascii string...";
+        REQUIRE(ascii.numberOfCharacters() == ascii.size());
+
+        StringRef simpleu8 = u8"Trocha češtiny nikoho nezabila";
+        REQUIRE(simpleu8.numberOfCharacters() == 30);
+
+        StringRef emojis = u8"Here be 👾";
+        REQUIRE(emojis.numberOfCharacters() == 9);
+    }
+
 }
 
-TEST_CASE( "replaceInPlace" ) {
+TEST_CASE( "replaceInPlace", "[Strings][StringManip]" ) {
     std::string letters = "abcdefcg";
     SECTION( "replace single char" ) {
         CHECK( Catch::replaceInPlace( letters, "b", "z" ) );
diff --git a/projects/SelfTest/IntrospectiveTests/TagAlias.tests.cpp b/projects/SelfTest/IntrospectiveTests/TagAlias.tests.cpp
index 8a0bdae..5428589 100644
--- a/projects/SelfTest/IntrospectiveTests/TagAlias.tests.cpp
+++ b/projects/SelfTest/IntrospectiveTests/TagAlias.tests.cpp
@@ -9,9 +9,8 @@
 #include "catch.hpp"
 #include "internal/catch_tag_alias_registry.h"
 
-
 TEST_CASE( "Tag alias can be registered against tag patterns" ) {
-#if CATCH_CONFIG_USE_EXCEPTIONS
+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
 
     Catch::TagAliasRegistry registry;
 
diff --git a/projects/SelfTest/IntrospectiveTests/Xml.tests.cpp b/projects/SelfTest/IntrospectiveTests/Xml.tests.cpp
index 9bbed25..c3886ab 100644
--- a/projects/SelfTest/IntrospectiveTests/Xml.tests.cpp
+++ b/projects/SelfTest/IntrospectiveTests/Xml.tests.cpp
@@ -1,5 +1,4 @@
 #include "catch.hpp"
-
 #include "internal/catch_xmlwriter.h"
 
 #include <sstream>
@@ -10,7 +9,7 @@
     return oss.str();
 }
 
-TEST_CASE( "XmlEncode" ) {
+TEST_CASE( "XmlEncode", "[XML]" ) {
     SECTION( "normal string" ) {
         REQUIRE( encode( "normal string" ) == "normal string" );
     }
@@ -38,4 +37,76 @@
     SECTION( "string with control char (x7F)" ) {
         REQUIRE( encode( "[\x7F]" ) == "[\\x7F]" );
     }
-}
\ No newline at end of file
+}
+
+// Thanks to Peter Bindels (dascandy) for some of the tests
+TEST_CASE("XmlEncode: UTF-8", "[XML][UTF-8]") {
+    SECTION("Valid utf-8 strings") {
+        CHECK(encode(u8"Here be 👾") == u8"Here be 👾");
+        CHECK(encode(u8"šš") == u8"šš");
+
+        CHECK(encode("\xDF\xBF")         == "\xDF\xBF"); // 0x7FF
+        CHECK(encode("\xE0\xA0\x80")     == "\xE0\xA0\x80"); // 0x800
+        CHECK(encode("\xED\x9F\xBF")     == "\xED\x9F\xBF"); // 0xD7FF
+        CHECK(encode("\xEE\x80\x80")     == "\xEE\x80\x80"); // 0xE000
+        CHECK(encode("\xEF\xBF\xBF")     == "\xEF\xBF\xBF"); // 0xFFFF
+        CHECK(encode("\xF0\x90\x80\x80") == "\xF0\x90\x80\x80"); // 0x10000
+        CHECK(encode("\xF4\x8F\xBF\xBF") == "\xF4\x8F\xBF\xBF"); // 0x10FFFF
+    }
+    SECTION("Invalid utf-8 strings") {
+        SECTION("Various broken strings") {
+            CHECK(encode("Here \xFF be 👾") == u8"Here \\xFF be 👾");
+            CHECK(encode("\xFF") == "\\xFF");
+            CHECK(encode("\xC5\xC5\xA0") == u8"\\xC5Š");
+            CHECK(encode("\xF4\x90\x80\x80") == u8"\\xF4\\x90\\x80\\x80"); // 0x110000 -- out of unicode range
+        }
+
+        SECTION("Overlong encodings") {
+            CHECK(encode("\xC0\x80") == u8"\\xC0\\x80"); // \0
+            CHECK(encode("\xF0\x80\x80\x80") == u8"\\xF0\\x80\\x80\\x80"); // Super-over-long \0
+            CHECK(encode("\xC1\xBF") == u8"\\xC1\\xBF"); // ASCII char as UTF-8 (0x7F)
+            CHECK(encode("\xE0\x9F\xBF") == u8"\\xE0\\x9F\\xBF"); // 0x7FF
+            CHECK(encode("\xF0\x8F\xBF\xBF") == u8"\\xF0\\x8F\\xBF\\xBF"); // 0xFFFF
+        }
+
+        // Note that we actually don't modify surrogate pairs, as we do not do strict checking
+        SECTION("Surrogate pairs") {
+            CHECK(encode("\xED\xA0\x80") == "\xED\xA0\x80"); // Invalid surrogate half 0xD800
+            CHECK(encode("\xED\xAF\xBF") == "\xED\xAF\xBF"); // Invalid surrogate half 0xDBFF
+            CHECK(encode("\xED\xB0\x80") == "\xED\xB0\x80"); // Invalid surrogate half 0xDC00
+            CHECK(encode("\xED\xBF\xBF") == "\xED\xBF\xBF"); // Invalid surrogate half 0xDFFF
+        }
+
+        SECTION("Invalid start byte") {
+            CHECK(encode("\x80") == u8"\\x80");
+            CHECK(encode("\x81") == u8"\\x81");
+            CHECK(encode("\xBC") == u8"\\xBC");
+            CHECK(encode("\xBF") == u8"\\xBF");
+            // Out of range
+            CHECK(encode("\xF5\x80\x80\x80") == u8"\\xF5\\x80\\x80\\x80");
+            CHECK(encode("\xF6\x80\x80\x80") == u8"\\xF6\\x80\\x80\\x80");
+            CHECK(encode("\xF7\x80\x80\x80") == u8"\\xF7\\x80\\x80\\x80");
+        }
+
+        SECTION("Missing continuation byte(s)") {
+            // Missing first continuation byte
+            CHECK(encode("\xDE") == u8"\\xDE");
+            CHECK(encode("\xDF") == u8"\\xDF");
+            CHECK(encode("\xE0") == u8"\\xE0");
+            CHECK(encode("\xEF") == u8"\\xEF");
+            CHECK(encode("\xF0") == u8"\\xF0");
+            CHECK(encode("\xF4") == u8"\\xF4");
+
+            // Missing second continuation byte
+            CHECK(encode("\xE0\x80") == u8"\\xE0\\x80");
+            CHECK(encode("\xE0\xBF") == u8"\\xE0\\xBF");
+            CHECK(encode("\xE1\x80") == u8"\\xE1\\x80");
+            CHECK(encode("\xF0\x80") == u8"\\xF0\\x80");
+            CHECK(encode("\xF4\x80") == u8"\\xF4\\x80");
+
+            // Missing third continuation byte
+            CHECK(encode("\xF0\x80\x80") == u8"\\xF0\\x80\\x80");
+            CHECK(encode("\xF4\x80\x80") == u8"\\xF4\\x80\\x80");
+        }
+    }
+}
diff --git a/projects/SelfTest/UsageTests/Approx.tests.cpp b/projects/SelfTest/UsageTests/Approx.tests.cpp
index 06052b0..b95394a 100644
--- a/projects/SelfTest/UsageTests/Approx.tests.cpp
+++ b/projects/SelfTest/UsageTests/Approx.tests.cpp
@@ -33,8 +33,21 @@
 
 #endif
 
+using namespace Catch::literals;
 
 ///////////////////////////////////////////////////////////////////////////////
+TEST_CASE( "A comparison that uses literals instead of the normal constructor", "[Approx]" ) {
+    double d = 1.23;
+
+    REQUIRE( d == 1.23_a );
+    REQUIRE( d != 1.22_a );
+    REQUIRE( -d == -1.23_a );
+
+    REQUIRE( d == 1.2_a .epsilon(.1) );
+    REQUIRE( d != 1.2_a .epsilon(.001) );
+    REQUIRE( d == 1_a .epsilon(.3) );
+}
+
 TEST_CASE( "Some simple comparisons between doubles", "[Approx]" ) {
     double d = 1.23;
 
@@ -42,6 +55,9 @@
     REQUIRE( d != Approx( 1.22 ) );
     REQUIRE( d != Approx( 1.24 ) );
 
+    REQUIRE( d == 1.23_a );
+    REQUIRE( d != 1.22_a );
+
     REQUIRE( Approx( d ) == 1.23 );
     REQUIRE( Approx( d ) != 1.22 );
     REQUIRE( Approx( d ) != 1.24 );
@@ -149,17 +165,13 @@
     REQUIRE_NOTHROW(Approx(0).margin(0));
     REQUIRE_NOTHROW(Approx(0).margin(1234656));
 
-#if CATCH_CONFIG_USE_EXCEPTIONS
     REQUIRE_THROWS_AS(Approx(0).margin(-2), std::domain_error);
-#endif
 
     REQUIRE_NOTHROW(Approx(0).epsilon(0));
     REQUIRE_NOTHROW(Approx(0).epsilon(1));
 
-#if CATCH_CONFIG_USE_EXCEPTIONS
     REQUIRE_THROWS_AS(Approx(0).epsilon(-0.001), std::domain_error);
     REQUIRE_THROWS_AS(Approx(0).epsilon(1.0001), std::domain_error);
-#endif
 }
 
 TEST_CASE("Default scale is invisible to comparison", "[Approx]") {
diff --git a/projects/SelfTest/UsageTests/BDD.tests.cpp b/projects/SelfTest/UsageTests/BDD.tests.cpp
index f43fd96..d0d3e03 100644
--- a/projects/SelfTest/UsageTests/BDD.tests.cpp
+++ b/projects/SelfTest/UsageTests/BDD.tests.cpp
@@ -38,11 +38,14 @@
     SCENARIO("Do that thing with the thing", "[Tags]") {
         GIVEN("This stuff exists") {
             // make stuff exist
-            WHEN("I do this") {
-                // do this
-                THEN("it should do this") {
-                    REQUIRE(itDoesThis());
-                    AND_THEN("do that")REQUIRE(itDoesThat());
+            AND_GIVEN("And some assumption") {
+                // Validate assumption
+                WHEN("I do this") {
+                    // do this
+                    THEN("it should do this") {
+                        REQUIRE(itDoesThis());
+                        AND_THEN("do that")REQUIRE(itDoesThat());
+                    }
                 }
             }
         }
diff --git a/projects/SelfTest/UsageTests/Class.tests.cpp b/projects/SelfTest/UsageTests/Class.tests.cpp
index c19a517..3bde1d8 100644
--- a/projects/SelfTest/UsageTests/Class.tests.cpp
+++ b/projects/SelfTest/UsageTests/Class.tests.cpp
@@ -39,6 +39,25 @@
     int m_a;
 };
 
+template< typename T >
+struct Template_Fixture {
+    Template_Fixture(): m_a(1) {}
+
+    T m_a;
+};
+
+template<typename T>
+struct Template_Fixture_2 {
+    Template_Fixture_2() {}
+
+    T m_a;
+};
+
+template< typename T>
+struct Template_Foo {
+    size_t size() { return 0; }
+};
+
 #endif
 
 
@@ -51,6 +70,15 @@
     REQUIRE( m_a == 1 );
 }
 
+TEMPLATE_TEST_CASE_METHOD(Template_Fixture, "A TEMPLATE_TEST_CASE_METHOD based test run that succeeds", "[class][template]", int, float, double) {
+    REQUIRE( Template_Fixture<TestType>::m_a == 1 );
+}
+
+TEMPLATE_PRODUCT_TEST_CASE_METHOD(Template_Fixture_2, "A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that succeeds","[class][template][product]",(std::vector,Template_Foo),(int,float))
+{
+    REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 0 );
+}
+
 // We should be able to write our tests within a different namespace
 namespace Inner
 {
@@ -58,6 +86,18 @@
     {
         REQUIRE( m_a == 2 );
     }
+
+    TEMPLATE_TEST_CASE_METHOD(Template_Fixture,"A TEMPLATE_TEST_CASE_METHOD based test run that fails", "[.][class][template][failing]", int, float, double)
+    {
+        REQUIRE( Template_Fixture<TestType>::m_a == 2 );
+    }
+
+    TEMPLATE_PRODUCT_TEST_CASE_METHOD(Template_Fixture_2, "A TEMPLATE_PRODUCT_TEST_CASE_METHOD based test run that fails","[.][class][template][product][failing]",(std::vector,Template_Foo),(int,float))
+    {
+        REQUIRE( Template_Fixture_2<TestType>::m_a.size() == 1 );
+    }
 }
 
+
+
 }} // namespace ClassTests
diff --git a/projects/SelfTest/UsageTests/Compilation.tests.cpp b/projects/SelfTest/UsageTests/Compilation.tests.cpp
index a2f8af0..70b814a 100644
--- a/projects/SelfTest/UsageTests/Compilation.tests.cpp
+++ b/projects/SelfTest/UsageTests/Compilation.tests.cpp
@@ -5,8 +5,35 @@
  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  */
 
+#include <type_traits>
+
+// Setup for #1403 -- look for global overloads of operator << for classes
+// in a different namespace.
+#include <ostream>
+
+namespace foo {
+    struct helper_1403 {
+        bool operator==(helper_1403) const { return true; }
+    };
+}
+
+namespace bar {
+    template <typename... Ts>
+    struct TypeList {};
+}
+
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Wmissing-declarations"
+#endif
+std::ostream& operator<<(std::ostream& out, foo::helper_1403 const&) {
+    return out << "[1403 helper]";
+}
+///////////////////////////////
+
 #include "catch.hpp"
 
+#include <cstring>
+
 namespace { namespace CompilationTests {
 
 #ifndef COMPILATION_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU
@@ -41,7 +68,7 @@
 
     void throws_int(bool b) {
         if (b) {
-#if CATCH_CONFIG_USE_EXCEPTIONS
+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
             throw 1;
 #else
             std::terminate();
@@ -54,10 +81,8 @@
         int a = 3;
         REQUIRE(a == t);
         CHECK(a == t);
-#if CATCH_CONFIG_USE_EXCEPTIONS
         REQUIRE_THROWS(throws_int(true));
         CHECK_THROWS_AS(throws_int(true), int);
-#endif
         REQUIRE_NOTHROW(throws_int(false));
 #ifndef CATCH_CONFIG_DISABLE_MATCHERS
         REQUIRE_THAT("aaa", Catch::EndsWith("aaa"));
@@ -92,6 +117,9 @@
 #pragma clang diagnostic pop
 #endif
 
+    template <typename, typename>
+    struct Fixture_1245 {};
+
 #endif
 
     TEST_CASE("#809") {
@@ -140,4 +168,36 @@
         REQUIRE(t1 >= t2);
     }
 
+    // unsigned array
+    TEST_CASE("#1238") {
+        unsigned char uarr[] = "123";
+        CAPTURE(uarr);
+        signed char sarr[] = "456";
+        CAPTURE(sarr);
+
+        REQUIRE(std::memcmp(uarr, "123", sizeof(uarr)) == 0);
+        REQUIRE(std::memcmp(sarr, "456", sizeof(sarr)) == 0);
+    }
+
+    TEST_CASE_METHOD((Fixture_1245<int, int>), "#1245", "[compilation]") {
+        SUCCEED();
+    }
+
+    TEST_CASE("#1403", "[compilation]") {
+        ::foo::helper_1403 h1, h2;
+        REQUIRE(h1 == h2);
+    }
+
+    TEST_CASE("Optionally static assertions", "[compilation]") {
+        STATIC_REQUIRE( std::is_void<void>::value );
+        STATIC_REQUIRE_FALSE( std::is_void<int>::value );
+    }
+
+    TEST_CASE("#1548", "[compilation]") {
+        using namespace bar;
+        REQUIRE(std::is_same<TypeList<int>, TypeList<int>>::value);
+    }
+
 }} // namespace CompilationTests
+
+
diff --git a/projects/SelfTest/UsageTests/Decomposition.tests.cpp b/projects/SelfTest/UsageTests/Decomposition.tests.cpp
index 1b44b60..5bb19cd 100644
--- a/projects/SelfTest/UsageTests/Decomposition.tests.cpp
+++ b/projects/SelfTest/UsageTests/Decomposition.tests.cpp
@@ -9,6 +9,8 @@
 #include <iostream>
 #include <cstdio>
 
+namespace {
+
 struct truthy {
     truthy(bool b):m_value(b){}
     operator bool() const {
@@ -22,6 +24,8 @@
     return o;
 }
 
+} // end anonymous namespace
+
 #include "catch.hpp"
 
 TEST_CASE( "Reconstruction should be based on stringification: #914" , "[Decomposition][failing][.]") {
diff --git a/projects/SelfTest/UsageTests/EnumToString.tests.cpp b/projects/SelfTest/UsageTests/EnumToString.tests.cpp
index 7d18a29..0b188a8 100644
--- a/projects/SelfTest/UsageTests/EnumToString.tests.cpp
+++ b/projects/SelfTest/UsageTests/EnumToString.tests.cpp
@@ -1,22 +1,24 @@
 #include "catch.hpp"
 
 
+namespace {
 // Enum without user-provided stream operator
 enum Enum1 { Enum1Value0, Enum1Value1 };
 
-TEST_CASE( "toString(enum)", "[toString][enum]" ) {
-    Enum1 e0 = Enum1Value0;
-    CHECK( ::Catch::Detail::stringify(e0) == "0" );
-    Enum1 e1 = Enum1Value1;
-    CHECK( ::Catch::Detail::stringify(e1) == "1" );
-}
-
 // Enum with user-provided stream operator
 enum Enum2 { Enum2Value0, Enum2Value1 };
 
 std::ostream& operator<<( std::ostream& os, Enum2 v ) {
     return os << "E2{" << static_cast<int>(v) << "}";
 }
+} // end anonymous namespace
+
+TEST_CASE( "toString(enum)", "[toString][enum]" ) {
+    Enum1 e0 = Enum1Value0;
+    CHECK( ::Catch::Detail::stringify(e0) == "0" );
+    Enum1 e1 = Enum1Value1;
+    CHECK( ::Catch::Detail::stringify(e1) == "1" );
+}
 
 TEST_CASE( "toString(enum w/operator<<)", "[toString][enum]" ) {
     Enum2 e0 = Enum2Value0;
@@ -26,17 +28,11 @@
 }
 
 // Enum class without user-provided stream operator
+namespace {
 enum class EnumClass1 { EnumClass1Value0, EnumClass1Value1 };
 
-TEST_CASE( "toString(enum class)", "[toString][enum][enumClass]" ) {
-    EnumClass1 e0 = EnumClass1::EnumClass1Value0;
-    CHECK( ::Catch::Detail::stringify(e0) == "0" );
-    EnumClass1 e1 = EnumClass1::EnumClass1Value1;
-    CHECK( ::Catch::Detail::stringify(e1) == "1" );
-}
-
 // Enum class with user-provided stream operator
-enum class EnumClass2 : short { EnumClass2Value0, EnumClass2Value1 };
+enum class EnumClass2 { EnumClass2Value0, EnumClass2Value1 };
 
 std::ostream& operator<<( std::ostream& os, EnumClass2 e2 ) {
     switch( static_cast<int>( e2 ) ) {
@@ -49,6 +45,16 @@
     }
 }
 
+} // end anonymous namespace
+
+TEST_CASE( "toString(enum class)", "[toString][enum][enumClass]" ) {
+    EnumClass1 e0 = EnumClass1::EnumClass1Value0;
+    CHECK( ::Catch::Detail::stringify(e0) == "0" );
+    EnumClass1 e1 = EnumClass1::EnumClass1Value1;
+    CHECK( ::Catch::Detail::stringify(e1) == "1" );
+}
+
+
 TEST_CASE( "toString(enum class w/operator<<)", "[toString][enum][enumClass]" ) {
     EnumClass2 e0 = EnumClass2::EnumClass2Value0;
     CHECK( ::Catch::Detail::stringify(e0) == "E2/V0" );
@@ -58,4 +64,3 @@
     EnumClass2 e3 = static_cast<EnumClass2>(10);
     CHECK( ::Catch::Detail::stringify(e3) == "Unknown enum value 10" );
 }
-
diff --git a/projects/SelfTest/UsageTests/Exception.tests.cpp b/projects/SelfTest/UsageTests/Exception.tests.cpp
index 5b8082f..b13b93b 100644
--- a/projects/SelfTest/UsageTests/Exception.tests.cpp
+++ b/projects/SelfTest/UsageTests/Exception.tests.cpp
@@ -12,15 +12,16 @@
 #include <stdexcept>
 
 #ifdef _MSC_VER
-#pragma warning(disable:4702) // Unreachable code -- uncoditional throws and so on
+#pragma warning(disable:4702) // Unreachable code -- unconditional throws and so on
 #endif
 #ifdef __clang__
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wweak-vtables"
 #pragma clang diagnostic ignored "-Wmissing-noreturn"
+#pragma clang diagnostic ignored "-Wunreachable-code"
 #endif
 
-#if CATCH_CONFIG_USE_EXCEPTIONS
+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
 // Cannot use try/catch keywords with -fno-exceptions.
 // Even if an exception was to be "thrown" it would just call std::terminate instead.
 
@@ -158,6 +159,15 @@
     throw double( 3.14 );
 }
 
+TEST_CASE("Thrown string literals are translated", "[.][failing][!throws]") {
+    throw "For some reason someone is throwing a string literal!";
+}
+
+TEST_CASE("thrown std::strings are translated", "[.][failing][!throws]") {
+    throw std::string{ "Why would you throw a std::string?" };
+}
+
+
 #ifndef CATCH_CONFIG_DISABLE_MATCHERS
 
 TEST_CASE( "Exception messages can be tested for", "[!throws]" ) {
diff --git a/projects/SelfTest/UsageTests/Generators.tests.cpp b/projects/SelfTest/UsageTests/Generators.tests.cpp
new file mode 100644
index 0000000..0cf1ce6
--- /dev/null
+++ b/projects/SelfTest/UsageTests/Generators.tests.cpp
@@ -0,0 +1,185 @@
+#include "catch.hpp"
+
+#include <cstring>
+
+
+// Generators and sections can be nested freely
+TEST_CASE("Generators -- simple", "[generators]") {
+    auto i = GENERATE(1, 2, 3);
+    SECTION("one") {
+        auto j = GENERATE(values({ -3, -2, -1 }));
+        REQUIRE(j < i);
+    }
+
+    SECTION("two") {
+        // You can also explicitly set type for generators via Catch::Generators::as
+        auto str = GENERATE(as<std::string>{}, "a", "bb", "ccc");
+        REQUIRE(4u * i > str.size());
+    }
+}
+
+// You can create a cartesian-product of generators by creating multiple ones
+TEST_CASE("3x3x3 ints", "[generators]") {
+    auto x = GENERATE(1, 2, 3);
+    auto y = GENERATE(4, 5, 6);
+    auto z = GENERATE(7, 8, 9);
+    // These assertions will be run 27 times (3x3x3)
+    CHECK(x < y);
+    CHECK(y < z);
+    REQUIRE(x < z);
+}
+
+// You can also create data tuples
+TEST_CASE("tables", "[generators]") {
+    // Note that this will not compile with libstdc++ older than libstdc++6
+    // See https://stackoverflow.com/questions/12436586/tuple-vector-and-initializer-list
+    // for possible workarounds
+    //    auto data = GENERATE(table<char const*, int>({
+    //        {"first", 5},
+    //        {"second", 6},
+    //        {"third", 5},
+    //        {"etc...", 6}
+    //    }));
+
+    // Workaround for the libstdc++ bug mentioned above
+    using tuple_type = std::tuple<char const*, int>;
+    auto data = GENERATE(table<char const*, int>({
+        tuple_type{"first", 5},
+        tuple_type{"second", 6},
+        tuple_type{"third", 5},
+        tuple_type{"etc...", 6}
+    }));
+
+    REQUIRE(strlen(std::get<0>(data)) == static_cast<size_t>(std::get<1>(data)));
+}
+
+
+#ifdef __cpp_structured_bindings
+
+// Structured bindings make the table utility much nicer to use
+TEST_CASE( "strlen2", "[approvals][generators]" ) {
+    auto [test_input, expected] = GENERATE( table<std::string, size_t>({
+            {"one", 3},
+            {"two", 3},
+            {"three", 5},
+            {"four", 4}
+        }));
+
+    REQUIRE( test_input.size() == expected );
+}
+#endif
+
+
+// An alternate way of doing data tables without structured bindings
+struct Data { std::string str; size_t len; };
+
+TEST_CASE( "strlen3", "[generators]" ) {
+    auto data = GENERATE( values<Data>({
+            {"one", 3},
+            {"two", 3},
+            {"three", 5},
+            {"four", 4}
+        }));
+
+    REQUIRE( data.str.size() == data.len );
+}
+
+
+
+#ifdef __cpp_structured_bindings
+
+// Based on example from https://docs.cucumber.io/gherkin/reference/#scenario-outline
+// (thanks to https://github.com/catchorg/Catch2/issues/850#issuecomment-399504851)
+
+// Note that GIVEN, WHEN, and THEN now forward onto DYNAMIC_SECTION instead of SECTION.
+// DYNAMIC_SECTION takes its name as a stringstream-style expression, so can be formatted using
+// variables in scope - such as the generated variables here. This reads quite nicely in the
+// test name output (the full scenario description).
+
+static auto eatCucumbers( int start, int eat ) -> int { return start-eat; }
+
+SCENARIO("Eating cucumbers", "[generators][approvals]") {
+
+    auto [start, eat, left] = GENERATE( table<int,int,int> ({
+            { 12, 5, 7 },
+            { 20, 5, 15 }
+        }));
+
+    GIVEN( "there are " << start << " cucumbers" )
+    WHEN( "I eat " << eat << " cucumbers" )
+    THEN( "I should have " << left << " cucumbers" ) {
+        REQUIRE( eatCucumbers( start, eat ) == left );
+    }
+}
+#endif
+
+// There are also some generic generator manipulators
+TEST_CASE("Generators -- adapters", "[generators][generic]") {
+    // TODO: This won't work yet, introduce GENERATE_VAR?
+    //auto numbers = Catch::Generators::values({ 1, 2, 3, 4, 5, 6 });
+    SECTION("Filtering by predicate") {
+        SECTION("Basic usage") {
+            // This filters out all odd (false) numbers, giving [2, 4, 6]
+            auto i = GENERATE(filter([] (int val) { return val % 2 == 0; }, values({ 1, 2, 3, 4, 5, 6 })));
+            REQUIRE(i % 2 == 0);
+        }
+        SECTION("Throws if there are no matching values") {
+            using namespace Catch::Generators;
+            REQUIRE_THROWS_AS(filter([] (int) {return false; }, value(1)), Catch::GeneratorException);
+        }
+    }
+    SECTION("Shortening a range") {
+        // This takes the first 3 elements from the values, giving back [1, 2, 3]
+        auto i = GENERATE(take(3, values({ 1, 2, 3, 4, 5, 6 })));
+        REQUIRE(i < 4);
+    }
+    SECTION("Transforming elements") {
+        SECTION("Same type") {
+            // This doubles values [1, 2, 3] into [2, 4, 6]
+            auto i = GENERATE(map([] (int val) { return val * 2; }, values({ 1, 2, 3 })));
+            REQUIRE(i % 2 == 0);
+        }
+        SECTION("Different type") {
+            // This takes a generator that returns ints and maps them into strings
+            auto i = GENERATE(map<std::string>([] (int val) { return std::to_string(val); }, values({ 1, 2, 3 })));
+            REQUIRE(i.size() == 1);
+        }
+    }
+    SECTION("Repeating a generator") {
+        // This will return values [1, 2, 3, 1, 2, 3]
+        auto j = GENERATE(repeat(2, values({ 1, 2, 3 })));
+        REQUIRE(j > 0);
+    }
+    SECTION("Chunking a generator into sized pieces") {
+        SECTION("Number of elements in source is divisible by chunk size") {
+            auto chunk2 = GENERATE(chunk(2, values({ 1, 1, 2, 2, 3, 3 })));
+            REQUIRE(chunk2.size() == 2);
+            REQUIRE(chunk2.front() == chunk2.back());
+        }
+        SECTION("Number of elements in source is not divisible by chunk size") {
+            auto chunk2 = GENERATE(chunk(2, values({ 1, 1, 2, 2, 3 })));
+            REQUIRE(chunk2.size() == 2);
+            REQUIRE(chunk2.front() == chunk2.back());
+            REQUIRE(chunk2.front() < 3);
+        }
+        SECTION("Throws on too small generators") {
+            using namespace Catch::Generators;
+            REQUIRE_THROWS_AS(chunk(2, value(1)), Catch::GeneratorException);
+        }
+    }
+}
+
+// Note that because of the non-reproducibility of distributions,
+// anything involving the random generators cannot be part of approvals
+TEST_CASE("Random generator", "[generators][.][approvals]") {
+    SECTION("Infer int from integral arguments") {
+        auto val = GENERATE(take(4, random(0, 1)));
+        STATIC_REQUIRE(std::is_same<decltype(val), int>::value);
+        static_cast<void>(val); // Silence VS 2015 unused variable warning
+    }
+    SECTION("Infer double from double arguments") {
+        auto val = GENERATE(take(4, random(0., 1.)));
+        STATIC_REQUIRE(std::is_same<decltype(val), double>::value);
+        static_cast<void>(val); // Silence VS 2015 unused variable warning
+    }
+}
diff --git a/projects/SelfTest/UsageTests/Matchers.tests.cpp b/projects/SelfTest/UsageTests/Matchers.tests.cpp
index ca25cca..dc4b701 100644
--- a/projects/SelfTest/UsageTests/Matchers.tests.cpp
+++ b/projects/SelfTest/UsageTests/Matchers.tests.cpp
@@ -32,6 +32,9 @@
         return "some completely different text that contains one common word";
     }
 
+    inline bool alwaysTrue(int) { return true; }
+    inline bool alwaysFalse(int) { return false; }
+
 
 #ifdef _MSC_VER
 #pragma warning(disable:4702) // Unreachable code -- MSVC 19 (VS 2015) sees right through the indirection
@@ -42,10 +45,14 @@
     struct SpecialException : std::exception {
         SpecialException(int i_) : i(i_) {}
 
+        char const* what() const noexcept override {
+            return "SpecialException::what";
+        }
+
         int i;
     };
 
-#if CATCH_CONFIG_USE_EXCEPTIONS
+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
     void doesNotThrow() {}
 
     [[noreturn]]
@@ -79,6 +86,20 @@
 
     using namespace Catch::Matchers;
 
+#ifdef __DJGPP__
+    float nextafter(float from, float to)
+    {
+        return ::nextafterf(from, to);
+    }
+
+    double nextafter(double from, double to)
+    {
+        return ::nextafter(from, to);
+    }
+#else
+    using std::nextafter;
+#endif
+
     TEST_CASE("String matchers", "[matchers]") {
         REQUIRE_THAT(testStringForMatching(), Contains("string"));
         REQUIRE_THAT(testStringForMatching(), Contains("string", Catch::CaseSensitive::No));
@@ -132,6 +153,8 @@
              (defined(_GLIBCXX_RELEASE) && \
              _GLIBCXX_RELEASE > 4))))
 
+// DJGPP meets the above condition but <regex> does not work properly anyway
+#ifndef __DJGPP__
             REQUIRE_THAT(testStringForMatching(), Matches("this string contains 'abc' as a substring"));
             REQUIRE_THAT(testStringForMatching(),
                          Matches("this string CONTAINS 'abc' as a substring", Catch::CaseSensitive::No));
@@ -140,6 +163,8 @@
             REQUIRE_THAT(testStringForMatching(), Matches("^.* 'ABC' .*$", Catch::CaseSensitive::No));
 #endif
 
+#endif
+
             REQUIRE_THAT(testStringForMatching2(), !Matches("this string contains 'abc' as a substring"));
         }
 
@@ -275,7 +300,7 @@
             }
         }
 
-#if CATCH_CONFIG_USE_EXCEPTIONS
+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
         TEST_CASE("Exception matchers that succeed", "[matchers][exceptions][!throws]") {
             CHECK_THROWS_MATCHES(throws(1), SpecialException, ExceptionMatcher{1});
             REQUIRE_THROWS_MATCHES(throws(2), SpecialException, ExceptionMatcher{2});
@@ -307,13 +332,18 @@
 
                 REQUIRE_THAT(0.f, WithinAbs(-0.f, 0));
                 REQUIRE_THAT(NAN, !WithinAbs(NAN, 0));
+
+                REQUIRE_THAT(11.f, !WithinAbs(10.f, 0.5f));
+                REQUIRE_THAT(10.f, !WithinAbs(11.f, 0.5f));
+                REQUIRE_THAT(-10.f, WithinAbs(-10.f, 0.5f));
+                REQUIRE_THAT(-10.f, WithinAbs(-9.6f, 0.5f));
             }
             SECTION("ULPs") {
                 REQUIRE_THAT(1.f, WithinULP(1.f, 0));
 
-                REQUIRE_THAT(std::nextafter(1.f, 2.f), WithinULP(1.f, 1));
-                REQUIRE_THAT(std::nextafter(1.f, 0.f), WithinULP(1.f, 1));
-                REQUIRE_THAT(std::nextafter(1.f, 2.f), !WithinULP(1.f, 0));
+                REQUIRE_THAT(nextafter(1.f, 2.f), WithinULP(1.f, 1));
+                REQUIRE_THAT(nextafter(1.f, 0.f), WithinULP(1.f, 1));
+                REQUIRE_THAT(nextafter(1.f, 2.f), !WithinULP(1.f, 0));
 
                 REQUIRE_THAT(1.f, WithinULP(1.f, 0));
                 REQUIRE_THAT(-0.f, WithinULP(0.f, 0));
@@ -326,7 +356,6 @@
 
                 REQUIRE_THAT(NAN, !(WithinAbs(NAN, 100) || WithinULP(NAN, 123)));
             }
-#if CHECK_CONFIG_USE_EXCEPTIONS
             SECTION("Constructor validation") {
                 REQUIRE_NOTHROW(WithinAbs(1.f, 0.f));
                 REQUIRE_THROWS_AS(WithinAbs(1.f, -1.f), std::domain_error);
@@ -334,7 +363,6 @@
                 REQUIRE_NOTHROW(WithinULP(1.f, 0));
                 REQUIRE_THROWS_AS(WithinULP(1.f, -1), std::domain_error);
             }
-#endif
         }
 
         TEST_CASE("Floating point matchers: double", "[matchers][floating-point]") {
@@ -346,13 +374,18 @@
                 REQUIRE_THAT(0., !WithinAbs(1., 0.99));
 
                 REQUIRE_THAT(NAN, !WithinAbs(NAN, 0));
+
+                REQUIRE_THAT(11., !WithinAbs(10., 0.5));
+                REQUIRE_THAT(10., !WithinAbs(11., 0.5));
+                REQUIRE_THAT(-10., WithinAbs(-10., 0.5));
+                REQUIRE_THAT(-10., WithinAbs(-9.6, 0.5));
             }
             SECTION("ULPs") {
                 REQUIRE_THAT(1., WithinULP(1., 0));
 
-                REQUIRE_THAT(std::nextafter(1., 2.), WithinULP(1., 1));
-                REQUIRE_THAT(std::nextafter(1., 0.), WithinULP(1., 1));
-                REQUIRE_THAT(std::nextafter(1., 2.), !WithinULP(1., 0));
+                REQUIRE_THAT(nextafter(1., 2.), WithinULP(1., 1));
+                REQUIRE_THAT(nextafter(1., 0.), WithinULP(1., 1));
+                REQUIRE_THAT(nextafter(1., 2.), !WithinULP(1., 0));
 
                 REQUIRE_THAT(1., WithinULP(1., 0));
                 REQUIRE_THAT(-0., WithinULP(0., 0));
@@ -365,7 +398,6 @@
 
                 REQUIRE_THAT(NAN, !(WithinAbs(NAN, 100) || WithinULP(NAN, 123)));
             }
-#if CHECK_CONFIG_USE_EXCEPTIONS
             SECTION("Constructor validation") {
                 REQUIRE_NOTHROW(WithinAbs(1., 0.));
                 REQUIRE_THROWS_AS(WithinAbs(1., -1.), std::domain_error);
@@ -373,7 +405,39 @@
                 REQUIRE_NOTHROW(WithinULP(1., 0));
                 REQUIRE_THROWS_AS(WithinULP(1., -1), std::domain_error);
             }
-#endif
+        }
+
+        TEST_CASE("Arbitrary predicate matcher", "[matchers][generic]") {
+            SECTION("Function pointer") {
+                REQUIRE_THAT(1,  Predicate<int>(alwaysTrue, "always true"));
+                REQUIRE_THAT(1, !Predicate<int>(alwaysFalse, "always false"));
+            }
+            SECTION("Lambdas + different type") {
+                REQUIRE_THAT("Hello olleH",
+                             Predicate<std::string>(
+                                 [] (std::string const& str) -> bool { return str.front() == str.back(); },
+                                 "First and last character should be equal")
+                );
+
+                REQUIRE_THAT("This wouldn't pass",
+                             !Predicate<std::string>(
+                                 [] (std::string const& str) -> bool { return str.front() == str.back(); }
+                             )
+                );
+            }
+        }
+
+        TEST_CASE("Regression test #1", "[matchers][vector]") {
+            // At some point, UnorderedEqualsMatcher skipped
+            // mismatched prefixed before doing the comparison itself
+            std::vector<char> actual = { 'a', 'b' };
+            std::vector<char> expected = { 'c', 'b' };
+
+            CHECK_THAT(actual, !UnorderedEquals(expected));
+        }
+
+        TEST_CASE("Predicate matcher can accept const char*", "[matchers][compilation]") {
+            REQUIRE_THAT("foo", Predicate<const char*>([] (const char* const&) { return true; }));
         }
 
 } } // namespace MatchersTests
diff --git a/projects/SelfTest/UsageTests/Message.tests.cpp b/projects/SelfTest/UsageTests/Message.tests.cpp
index f3ac02a..c955822 100644
--- a/projects/SelfTest/UsageTests/Message.tests.cpp
+++ b/projects/SelfTest/UsageTests/Message.tests.cpp
@@ -9,10 +9,6 @@
 #include "catch.hpp"
 #include <iostream>
 
-#ifdef __clang__
-#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
-#endif
-
 TEST_CASE( "INFO and WARN do not abort tests", "[messages][.]" ) {
     INFO( "this is a " << "message" );    // This should output the message if a failure occurs
     WARN( "this is a " << "warning" );    // This should always output the message but then continue
@@ -135,3 +131,125 @@
     WARN( "actual address of p: " << &p );
     WARN( "toString(p): " << ::Catch::Detail::stringify( &p ) );
 }
+
+template <typename T>
+static void unscoped_info( T msg ) {
+    UNSCOPED_INFO( msg );
+}
+
+TEST_CASE( "just unscoped info", "[unscoped][info]" ) {
+    unscoped_info( "this should NOT be seen" );
+    unscoped_info( "this also should NOT be seen" );
+}
+
+TEST_CASE( "just failure after unscoped info", "[failing][.][unscoped][info]" ) {
+    FAIL( "previous unscoped info SHOULD not be seen" );
+}
+
+TEST_CASE( "print unscoped info if passing unscoped info is printed", "[unscoped][info]" ) {
+    unscoped_info( "this MAY be seen IF info is printed for passing assertions" );
+    REQUIRE( true );
+}
+
+TEST_CASE( "prints unscoped info on failure", "[failing][.][unscoped][info]" ) {
+    unscoped_info( "this SHOULD be seen" );
+    unscoped_info( "this SHOULD also be seen" );
+    REQUIRE( false );
+    unscoped_info( "but this should NOT be seen" );
+}
+
+TEST_CASE( "not prints unscoped info from previous failures", "[failing][.][unscoped][info]" ) {
+    unscoped_info( "this MAY be seen only for the FIRST assertion IF info is printed for passing assertions" );
+    REQUIRE( true );
+    unscoped_info( "this MAY be seen only for the SECOND assertion IF info is printed for passing assertions" );
+    REQUIRE( true );
+    unscoped_info( "this SHOULD be seen" );
+    REQUIRE( false );
+}
+
+TEST_CASE( "prints unscoped info only for the first assertion", "[failing][.][unscoped][info]" ) {
+    unscoped_info( "this SHOULD be seen only ONCE" );
+    CHECK( false );
+    CHECK( true );
+    unscoped_info( "this MAY also be seen only ONCE IF info is printed for passing assertions" );
+    CHECK( true );
+    CHECK( true );
+}
+
+TEST_CASE( "stacks unscoped info in loops", "[failing][.][unscoped][info]" ) {
+    UNSCOPED_INFO("Count 1 to 3...");
+    for (int i = 1; i <= 3; i++) {
+        unscoped_info(i);
+    }
+    CHECK( false );
+
+    UNSCOPED_INFO("Count 4 to 6...");
+    for (int i = 4; i <= 6; i++) {
+        unscoped_info(i);
+    }
+    CHECK( false );
+}
+
+TEST_CASE( "mix info, unscoped info and warning", "[unscoped][info]" ) {
+    INFO("info");
+    unscoped_info("unscoped info");
+    WARN("and warn may mix");
+    WARN("they are not cleared after warnings");
+}
+
+TEST_CASE( "CAPTURE can deal with complex expressions", "[messages][capture]" ) {
+    int a = 1;
+    int b = 2;
+    int c = 3;
+    CAPTURE( a, b, c, a + b, a+b, c > b, a == 1 );
+    SUCCEED();
+}
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-value" // In (1, 2), the "1" is unused ...
+#endif
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-value" // All the comma operators are side-effect free
+#endif
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4709) // comma in indexing operator
+#endif
+
+template <typename T1, typename T2>
+struct helper_1436 {
+    helper_1436(T1 t1, T2 t2):
+        t1{ t1 },
+        t2{ t2 }
+    {}
+    T1 t1;
+    T2 t2;
+};
+
+template <typename T1, typename T2>
+std::ostream& operator<<(std::ostream& out, helper_1436<T1, T2> const& helper) {
+    out << "{ " << helper.t1 << ", " << helper.t2 << " }";
+    return out;
+}
+
+TEST_CASE("CAPTURE can deal with complex expressions involving commas", "[messages][capture]") {
+    CAPTURE(std::vector<int>{1, 2, 3}[0, 1, 2],
+            std::vector<int>{1, 2, 3}[(0, 1)],
+            std::vector<int>{1, 2, 3}[0]);
+    CAPTURE((helper_1436<int, int>{12, -12}),
+            (helper_1436<int, int>(-12, 12)));
+    CAPTURE( (1, 2), (2, 3) );
+    SUCCEED();
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
diff --git a/projects/SelfTest/UsageTests/Misc.tests.cpp b/projects/SelfTest/UsageTests/Misc.tests.cpp
index 757a99b..4de6f1a 100644
--- a/projects/SelfTest/UsageTests/Misc.tests.cpp
+++ b/projects/SelfTest/UsageTests/Misc.tests.cpp
@@ -61,18 +61,23 @@
 static AutoTestReg autoTestReg;
 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
 
+template<typename T>
+struct Foo {
+    size_t size() { return 0; }
+};
+
 #endif
 
 TEST_CASE( "random SECTION tests", "[.][sections][failing]" ) {
     int a = 1;
     int b = 2;
 
-    SECTION( "s1", "doesn't equal" ) {
+    SECTION( "doesn't equal" ) {
         REQUIRE( a != b );
         REQUIRE( b != a );
     }
 
-    SECTION( "s2", "not equal" ) {
+    SECTION( "not equal" ) {
         REQUIRE( a != b);
     }
 }
@@ -81,11 +86,11 @@
     int a = 1;
     int b = 2;
 
-    SECTION( "s1", "doesn't equal" ) {
+    SECTION( "doesn't equal" ) {
         REQUIRE( a != b );
         REQUIRE( b != a );
 
-        SECTION( "s2", "not equal" ) {
+        SECTION( "not equal" ) {
             REQUIRE( a != b);
         }
     }
@@ -95,15 +100,15 @@
     int a = 1;
     int b = 2;
 
-    SECTION( "s1", "doesn't equal" ) {
-        SECTION( "s2", "equal" ) {
+    SECTION( "doesn't equal" ) {
+        SECTION( "equal" ) {
             REQUIRE( a == b );
         }
 
-        SECTION( "s3", "not equal" ) {
+        SECTION( "not equal" ) {
             REQUIRE( a != b );
         }
-        SECTION( "s4", "less than" ) {
+        SECTION( "less than" ) {
             REQUIRE( a < b );
         }
     }
@@ -112,16 +117,16 @@
 TEST_CASE( "even more nested SECTION tests", "[sections]" ) {
     SECTION( "c" ) {
         SECTION( "d (leaf)" ) {
-            SUCCEED(""); // avoid failing due to no tests
+            SUCCEED(); // avoid failing due to no tests
         }
 
         SECTION( "e (leaf)" ) {
-            SUCCEED(""); // avoid failing due to no tests
+            SUCCEED(); // avoid failing due to no tests
         }
     }
 
     SECTION( "f (leaf)" ) {
-        SUCCEED(""); // avoid failing due to no tests
+        SUCCEED(); // avoid failing due to no tests
     }
 }
 
@@ -129,9 +134,7 @@
     int a = 1;
 
     for( int b = 0; b < 10; ++b ) {
-        std::ostringstream oss;
-        oss << "b is currently: " << b;
-        SECTION( "s1", oss.str() ) {
+        DYNAMIC_SECTION( "b is currently: " << b ) {
             CHECK( b > a );
         }
     }
@@ -174,11 +177,11 @@
 }
 
 TEST_CASE( "xmlentitycheck" ) {
-    SECTION( "embedded xml", "<test>it should be possible to embed xml characters, such as <, \" or &, or even whole <xml>documents</xml> within an attribute</test>" ) {
-        SUCCEED(""); // We need this here to stop it failing due to no tests
+    SECTION( "embedded xml: <test>it should be possible to embed xml characters, such as <, \" or &, or even whole <xml>documents</xml> within an attribute</test>" ) {
+        SUCCEED(); // We need this here to stop it failing due to no tests
     }
-    SECTION( "encoded chars", "these should all be encoded: &&&\"\"\"<<<&\"<<&\"" ) {
-        SUCCEED(""); // We need this here to stop it failing due to no tests
+    SECTION( "encoded chars: these should all be encoded: &&&\"\"\"<<<&\"<<&\"" ) {
+        SUCCEED(); // We need this here to stop it failing due to no tests
     }
 }
 
@@ -263,10 +266,59 @@
     }
 }
 
+TEMPLATE_TEST_CASE( "TemplateTest: vectors can be sized and resized", "[vector][template]", int, float, std::string, (std::tuple<int,float>) ) {
+
+    std::vector<TestType> v( 5 );
+
+    REQUIRE( v.size() == 5 );
+    REQUIRE( v.capacity() >= 5 );
+
+    SECTION( "resizing bigger changes size and capacity" ) {
+        v.resize( 10 );
+
+        REQUIRE( v.size() == 10 );
+        REQUIRE( v.capacity() >= 10 );
+    }
+    SECTION( "resizing smaller changes size but not capacity" ) {
+        v.resize( 0 );
+
+        REQUIRE( v.size() == 0 );
+        REQUIRE( v.capacity() >= 5 );
+
+        SECTION( "We can use the 'swap trick' to reset the capacity" ) {
+            std::vector<TestType> empty;
+            empty.swap( v );
+
+            REQUIRE( v.capacity() == 0 );
+        }
+    }
+    SECTION( "reserving bigger changes capacity but not size" ) {
+        v.reserve( 10 );
+
+        REQUIRE( v.size() == 5 );
+        REQUIRE( v.capacity() >= 10 );
+    }
+    SECTION( "reserving smaller does not change size or capacity" ) {
+        v.reserve( 0 );
+
+        REQUIRE( v.size() == 5 );
+        REQUIRE( v.capacity() >= 5 );
+    }
+}
+
+TEMPLATE_PRODUCT_TEST_CASE("A Template product test case", "[template][product]", (std::vector, Foo), (int, float)) {
+    TestType x;
+    REQUIRE(x.size() == 0);
+}
+
+TEMPLATE_PRODUCT_TEST_CASE("Product with differing arities", "[template][product]", std::tuple, (int, (int, double), (int, double, float))) {
+    REQUIRE(std::tuple_size<TestType>::value >= 1);
+}
+
 // https://github.com/philsquared/Catch/issues/166
 TEST_CASE("A couple of nested sections followed by a failure", "[failing][.]") {
-    SECTION("Outer", "")
-        SECTION("Inner", "")
+    SECTION("Outer")
+        SECTION("Inner")
             SUCCEED("that's not flying - that's failing in style");
 
     FAIL("to infinity and beyond");
@@ -274,7 +326,7 @@
 
 TEST_CASE("not allowed", "[!throws]") {
     // This test case should not be included if you run with -e on the command line
-    SUCCEED( "" );
+    SUCCEED();
 }
 
 //TEST_CASE( "Is big endian" ) {
@@ -290,6 +342,7 @@
 }
 
 
+#ifdef CATCH_CONFIG_WCHAR
 TEST_CASE( "toString on const wchar_t const pointer returns the string contents", "[toString]" ) {
         const wchar_t * const s = L"wide load";
         std::string result = ::Catch::Detail::stringify( s );
@@ -303,7 +356,7 @@
 }
 
 TEST_CASE( "toString on wchar_t const pointer returns the string contents", "[toString]" ) {
-        auto const s = const_cast<wchar_t* const>( L"wide load" );
+        auto const s = const_cast<wchar_t*>( L"wide load" );
         std::string result = ::Catch::Detail::stringify( s );
         CHECK( result == "\"wide load\"" );
 }
@@ -313,6 +366,7 @@
         std::string result = ::Catch::Detail::stringify( s );
         CHECK( result == "\"wide load\"" );
 }
+#endif
 
 TEST_CASE( "long long" ) {
     long long l = std::numeric_limits<long long>::max();
@@ -348,4 +402,9 @@
     }
 }
 
+TEST_CASE( "#1175 - Hidden Test", "[.]" ) {
+  // Just for checking that hidden test is not listed by default
+  SUCCEED();
+}
+
 }} // namespace MiscTests
diff --git a/projects/SelfTest/UsageTests/ToStringGeneral.tests.cpp b/projects/SelfTest/UsageTests/ToStringGeneral.tests.cpp
index 8ab3324..acddf22 100644
--- a/projects/SelfTest/UsageTests/ToStringGeneral.tests.cpp
+++ b/projects/SelfTest/UsageTests/ToStringGeneral.tests.cpp
@@ -115,3 +115,62 @@
         REQUIRE(Catch::Detail::stringify(arr) == R"({ { "1:1", "1:2", "1:3" }, { "2:1", "2:2" } })");
     }
 }
+
+#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
+
+TEST_CASE("String views are stringified like other strings", "[toString][approvals]") {
+    std::string_view view{"abc"};
+    CHECK(Catch::Detail::stringify(view) == R"("abc")");
+
+    std::string_view arr[] { view };
+    CHECK(Catch::Detail::stringify(arr) == R"({ "abc" })");
+}
+
+#endif
+
+namespace {
+
+struct WhatException : std::exception {
+    char const* what() const noexcept override {
+        return "This exception has overriden what() method";
+    }
+    ~WhatException() override;
+};
+
+struct OperatorException : std::exception {
+    ~OperatorException() override;
+};
+
+std::ostream& operator<<(std::ostream& out, OperatorException const&) {
+    out << "OperatorException";
+    return out;
+}
+
+struct StringMakerException : std::exception {
+    ~StringMakerException() override;
+};
+
+} // end anonymous namespace
+
+namespace Catch {
+template <>
+struct StringMaker<StringMakerException> {
+    static std::string convert(StringMakerException const&) {
+        return "StringMakerException";
+    }
+};
+}
+
+// Avoid -Wweak-tables
+WhatException::~WhatException() = default;
+OperatorException::~OperatorException() = default;
+StringMakerException::~StringMakerException() = default;
+
+
+
+
+TEST_CASE("Exception as a value (e.g. in REQUIRE_THROWS_MATCHES) can be stringified", "[toString][exception]") {
+    REQUIRE(::Catch::Detail::stringify(WhatException{}) == "This exception has overriden what() method");
+    REQUIRE(::Catch::Detail::stringify(OperatorException{}) == "OperatorException");
+    REQUIRE(::Catch::Detail::stringify(StringMakerException{}) == "StringMakerException");
+}
diff --git a/projects/SelfTest/UsageTests/ToStringOptional.tests.cpp b/projects/SelfTest/UsageTests/ToStringOptional.tests.cpp
new file mode 100644
index 0000000..d78579d
--- /dev/null
+++ b/projects/SelfTest/UsageTests/ToStringOptional.tests.cpp
@@ -0,0 +1,23 @@
+#define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
+#include "catch.hpp"
+
+#if defined(CATCH_CONFIG_CPP17_OPTIONAL)
+
+TEST_CASE( "std::optional<int> -> toString", "[toString][optional][approvals]" ) {
+    using type = std::optional<int>;
+    REQUIRE( "{ }" == ::Catch::Detail::stringify( type{} ) );
+    REQUIRE( "0" == ::Catch::Detail::stringify( type{ 0 } ) );
+}
+
+TEST_CASE( "std::optional<std::string> -> toString", "[toString][optional][approvals]" ) {
+    using type = std::optional<std::string>;
+    REQUIRE( "{ }" == ::Catch::Detail::stringify( type{} ) );
+    REQUIRE( "\"abc\"" == ::Catch::Detail::stringify( type{ "abc" } ) );
+}
+
+TEST_CASE( "std::vector<std::optional<int> > -> toString", "[toString][optional][approvals]" ) {
+    using type = std::vector<std::optional<int> >;
+    REQUIRE( "{ 0, { }, 2 }" == ::Catch::Detail::stringify( type{ 0, {}, 2 } ) );
+}
+
+#endif // CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
diff --git a/projects/SelfTest/UsageTests/ToStringVariant.tests.cpp b/projects/SelfTest/UsageTests/ToStringVariant.tests.cpp
new file mode 100644
index 0000000..a048e15
--- /dev/null
+++ b/projects/SelfTest/UsageTests/ToStringVariant.tests.cpp
@@ -0,0 +1,91 @@
+#define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
+#include "catch.hpp"
+
+#if defined(CATCH_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
+
+#include <string>
+#include <variant>
+
+// We need 2 types with non-trivial copies/moves
+struct MyType1 {
+    MyType1() = default;
+    MyType1(MyType1 const&) { throw 1; }
+    MyType1& operator=(MyType1 const&) { throw 3; }
+};
+struct MyType2 {
+    MyType2() = default;
+    MyType2(MyType2 const&) { throw 2; }
+    MyType2& operator=(MyType2 const&) { throw 4; }
+};
+
+TEST_CASE( "variant<std::monostate>", "[toString][variant][approvals]")
+{
+    using type = std::variant<std::monostate>;
+    CHECK( "{ }" == ::Catch::Detail::stringify(type{}) );
+    type value {};
+    CHECK( "{ }" == ::Catch::Detail::stringify(value) );
+    CHECK( "{ }" == ::Catch::Detail::stringify(std::get<0>(value)) );
+}
+
+TEST_CASE( "variant<int>", "[toString][variant][approvals]")
+{
+    using type = std::variant<int>;
+    CHECK( "0" == ::Catch::Detail::stringify(type{0}) );
+}
+
+TEST_CASE( "variant<float, int>", "[toString][variant][approvals]")
+{
+    using type = std::variant<float, int>;
+    CHECK( "0.5f" == ::Catch::Detail::stringify(type{0.5f}) );
+    CHECK( "0" == ::Catch::Detail::stringify(type{0}) );
+}
+
+TEST_CASE( "variant -- valueless-by-exception", "[toString][variant][approvals]" ) {
+    using type = std::variant<MyType1, MyType2>;
+
+    type value;
+    REQUIRE_THROWS_AS(value.emplace<MyType2>(MyType2{}), int);
+    REQUIRE(value.valueless_by_exception());
+    CHECK("{valueless variant}" == ::Catch::Detail::stringify(value));
+}
+
+
+TEST_CASE( "variant<string, int>", "[toString][variant][approvals]")
+{
+    using type = std::variant<std::string, int>;
+    CHECK( "\"foo\"" == ::Catch::Detail::stringify(type{"foo"}) );
+    CHECK( "0" == ::Catch::Detail::stringify(type{0}) );
+}
+
+TEST_CASE( "variant<variant<float, int>, string>", "[toString][variant][approvals]")
+{
+    using inner = std::variant<MyType1, float, int>;
+    using type = std::variant<inner, std::string>;
+    CHECK( "0.5f" == ::Catch::Detail::stringify(type{0.5f}) );
+    CHECK( "0" == ::Catch::Detail::stringify(type{0}) );
+    CHECK( "\"foo\"" == ::Catch::Detail::stringify(type{"foo"}) );
+
+    SECTION("valueless nested variant") {
+        type value = inner{0.5f};
+        REQUIRE( std::holds_alternative<inner>(value) );
+        REQUIRE( std::holds_alternative<float>(std::get<inner>(value)) );
+
+        REQUIRE_THROWS_AS( std::get<0>(value).emplace<MyType1>(MyType1{}), int );
+
+        // outer variant is still valid and contains inner
+        REQUIRE( std::holds_alternative<inner>(value) );
+        // inner variant is valueless
+        REQUIRE( std::get<inner>(value).valueless_by_exception() );
+        CHECK( "{valueless variant}" == ::Catch::Detail::stringify(value) );
+    }
+}
+
+TEST_CASE( "variant<nullptr,int,const char *>", "[toString][variant][approvals]" )
+{
+    using type = std::variant<std::nullptr_t,int,const char *>;
+    CHECK( "nullptr" == ::Catch::Detail::stringify(type{nullptr}) );
+    CHECK( "42" == ::Catch::Detail::stringify(type{42}) );
+    CHECK( "\"Catch me\"" == ::Catch::Detail::stringify(type{"Catch me"}) );
+}
+
+#endif // CATCH_INTERNAL_CONFIG_CPP17_VARIANT
diff --git a/projects/SelfTest/UsageTests/ToStringVector.tests.cpp b/projects/SelfTest/UsageTests/ToStringVector.tests.cpp
index 18e56c0..63b49e5 100644
--- a/projects/SelfTest/UsageTests/ToStringVector.tests.cpp
+++ b/projects/SelfTest/UsageTests/ToStringVector.tests.cpp
@@ -2,7 +2,7 @@
 #include <vector>
 #include <array>
 
-// vedctor
+// vector
 TEST_CASE( "vector<int> -> toString", "[toString][vector]" )
 {
     std::vector<int> vv;
diff --git a/projects/SelfTest/UsageTests/ToStringWhich.tests.cpp b/projects/SelfTest/UsageTests/ToStringWhich.tests.cpp
index fe96186..cd4a151 100644
--- a/projects/SelfTest/UsageTests/ToStringWhich.tests.cpp
+++ b/projects/SelfTest/UsageTests/ToStringWhich.tests.cpp
@@ -1,13 +1,36 @@
-#include "catch.hpp"
 /*
-    Demonstrate which version of toString/StringMaker is being used
-    for various types
-*/
+ * Demonstrate which version of toString/StringMaker is being used
+ * for various types
+ */
 
+// Replace fallback stringifier for this TU
+// We should avoid ODR violations because these specific types aren't
+// present in different TUs
+#include <string>
+template <typename T>
+std::string fallbackStringifier(T const&) {
+    return "{ !!! }";
+}
+
+#define CATCH_CONFIG_FALLBACK_STRINGIFIER fallbackStringifier
+#include "catch.hpp"
+
+
+
+#if defined(__GNUC__)
+// This has to be left enabled until end of the TU, because the GCC
+// frontend reports operator<<(std::ostream& os, const has_maker_and_operator&)
+// as unused anyway
+#    pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+namespace {
 
 struct has_operator { };
 struct has_maker {};
 struct has_maker_and_operator {};
+struct has_neither {};
+struct has_template_operator {};
 
 std::ostream& operator<<(std::ostream& os, const has_operator&) {
     os << "operator<<( has_operator )";
@@ -19,6 +42,14 @@
     return os;
 }
 
+template <typename StreamT>
+StreamT& operator<<(StreamT& os, const has_template_operator&) {
+    os << "operator<<( has_template_operator )";
+    return os;
+}
+
+} // end anonymous namespace
+
 namespace Catch {
     template<>
     struct StringMaker<has_maker> {
@@ -47,33 +78,43 @@
 }
 
 // Call the stringmaker
-TEST_CASE( "stringify( has_maker_and_toString )", "[.][toString]" ) {
+TEST_CASE( "stringify( has_maker_and_operator )", "[toString]" ) {
     has_maker_and_operator item;
     REQUIRE( ::Catch::Detail::stringify( item ) == "StringMaker<has_maker_and_operator>" );
 }
 
+TEST_CASE("stringify( has_neither )", "[toString]") {
+    has_neither item;
+    REQUIRE( ::Catch::Detail::stringify(item) == "{ !!! }" );
+}
+
+// Call the templated operator
+TEST_CASE( "stringify( has_template_operator )", "[toString]" ) {
+    has_template_operator item;
+    REQUIRE( ::Catch::Detail::stringify( item ) == "operator<<( has_template_operator )" );
+}
+
+
 // Vectors...
 
-// Don't run this in approval tests as it is sensitive to two phase lookup differences
-TEST_CASE( "toString( vectors<has_operator> )", "[toString]" ) {
+TEST_CASE( "stringify( vectors<has_operator> )", "[toString]" ) {
     std::vector<has_operator> v(1);
     REQUIRE( ::Catch::Detail::stringify( v ) == "{ operator<<( has_operator ) }" );
 }
 
-TEST_CASE( "toString( vectors<has_maker> )", "[toString]" ) {
+TEST_CASE( "stringify( vectors<has_maker> )", "[toString]" ) {
     std::vector<has_maker> v(1);
     REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker> }" );
 }
 
-
-// Don't run this in approval tests as it is sensitive to two phase lookup differences
-TEST_CASE( "toString( vectors<has_maker_and_operator> )", "[toString]" ) {
+TEST_CASE( "stringify( vectors<has_maker_and_operator> )", "[toString]" ) {
     std::vector<has_maker_and_operator> v(1);
     REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker_and_operator> }" );
 }
 
-// Conversion should go
-// StringMaker specialization, operator<<, range/enum detection, unprintable
+namespace {
+
+// Range-based conversion should only be used if other possibilities fail
 struct int_iterator {
     using iterator_category = std::input_iterator_tag;
     using difference_type = std::ptrdiff_t;
@@ -112,6 +153,8 @@
     int_iterator end() const { return {}; }
 };
 
+} // end anonymous namespace
+
 namespace Catch {
 template <>
 struct StringMaker<stringmaker_range> {
@@ -121,6 +164,8 @@
 };
 }
 
+namespace {
+
 struct just_range {
     int_iterator begin() const { return int_iterator{ 1 }; }
     int_iterator end() const { return {}; }
@@ -131,6 +176,8 @@
     int_iterator end() const { return {}; }
 };
 
+} // end anonymous namespace
+
 namespace Catch {
 template <>
 struct is_range<disabled_range> {
@@ -138,9 +185,9 @@
 };
 }
 
-TEST_CASE("toString streamable range", "[toString]") {
+TEST_CASE("stringify ranges", "[toString]") {
     REQUIRE(::Catch::Detail::stringify(streamable_range{}) == "op<<(streamable_range)");
     REQUIRE(::Catch::Detail::stringify(stringmaker_range{}) == "stringmaker(streamable_range)");
     REQUIRE(::Catch::Detail::stringify(just_range{}) == "{ 1, 2, 3, 4 }");
-    REQUIRE(::Catch::Detail::stringify(disabled_range{}) == "{?}");
+    REQUIRE(::Catch::Detail::stringify(disabled_range{}) == "{ !!! }");
 }
diff --git a/projects/SelfTest/UsageTests/Tricky.tests.cpp b/projects/SelfTest/UsageTests/Tricky.tests.cpp
index 304f492..77bad2f 100644
--- a/projects/SelfTest/UsageTests/Tricky.tests.cpp
+++ b/projects/SelfTest/UsageTests/Tricky.tests.cpp
@@ -19,26 +19,7 @@
 
 #include <stdio.h>
 #include <sstream>
-
-namespace Catch {
-    std::string toString( const std::pair<int, int>& value ) {
-        std::ostringstream oss;
-        oss << "std::pair( " << value.first << ", " << value.second << " )";
-        return oss.str();
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-TEST_CASE
-(
-    "Parsing a std::pair",
-    "[Tricky][std::pair]"
-)
-{
-    std::pair<int, int> aNicePair( 1, 2 );
-
-    REQUIRE( (std::pair<int, int>( 1, 2 )) == aNicePair );
-}
+#include <iostream>
 
 ///////////////////////////////////////////////////////////////////////////////
 TEST_CASE
@@ -175,7 +156,7 @@
     ///////////////////////////////////////////////////////////////////////////////
     TEST_CASE
     (
-        "Operators at different namespace levels not hijacked by Koenig lookup",
+        "Implicit conversions are supported inside assertion macros",
         "[Tricky][approvals]"
     )
     {
@@ -232,28 +213,28 @@
 
 TEST_CASE( "(unimplemented) static bools can be evaluated", "[Tricky]" )
 {
-    SECTION("compare to true","")
+    SECTION("compare to true")
     {
         REQUIRE( is_true<true>::value == true );
         REQUIRE( true == is_true<true>::value );
     }
-    SECTION("compare to false","")
+    SECTION("compare to false")
     {
         REQUIRE( is_true<false>::value == false );
         REQUIRE( false == is_true<false>::value );
     }
 
-    SECTION("negation", "")
+    SECTION("negation")
     {
         REQUIRE( !is_true<false>::value );
     }
 
-    SECTION("double negation","")
+    SECTION("double negation")
     {
         REQUIRE( !!is_true<true>::value );
     }
 
-    SECTION("direct","")
+    SECTION("direct")
     {
         REQUIRE( is_true<true>::value );
         REQUIRE_FALSE( is_true<false>::value );
@@ -383,7 +364,7 @@
 }
 
 namespace {
-#if CHECK_CONFIG_USE_EXCEPTIONS
+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
     struct constructor_throws {
         [[noreturn]] constructor_throws() {
             throw 1;
@@ -393,7 +374,7 @@
 }
 
 TEST_CASE("Commas in various macros are allowed") {
-#if CHECK_CONFIG_USE_EXCEPTIONS
+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
     REQUIRE_THROWS( std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} );
     CHECK_THROWS( std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} );
 #endif
@@ -452,3 +433,10 @@
     REQUIRE( y.v == 0 );
     REQUIRE( 0 == y.v );
 }
+
+TEST_CASE("#1514: stderr/stdout is not captured in tests aborted by an exception", "[output-capture][regression][.]") {
+    std::cout << "This would not be caught previously\n" << std::flush;
+    std::clog << "Nor would this\n" << std::flush;
+    // FAIL aborts the test by throwing a Catch exception
+    FAIL("1514");
+}
diff --git a/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj b/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj
index 91e2cd9..7153203 100644
--- a/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj
+++ b/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj
@@ -120,7 +120,7 @@
 		4A63D29C14E3C1A900F615CB /* Project object */ = {
 			isa = PBXProject;
 			attributes = {
-				LastUpgradeCheck = 0500;
+				LastUpgradeCheck = 0940;
 			};
 			buildConfigurationList = 4A63D29F14E3C1A900F615CB /* Build configuration list for PBXProject "OCTest" */;
 			compatibilityVersion = "Xcode 3.2";
@@ -159,16 +159,30 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
 				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
 				CLANG_WARN_EMPTY_BODY = YES;
 				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
 				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
 				GCC_C_LANGUAGE_STANDARD = gnu99;
 				GCC_DYNAMIC_NO_PIC = NO;
 				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
 				GCC_OPTIMIZATION_LEVEL = 0;
 				GCC_PREPROCESSOR_DEFINITIONS = (
 					"DEBUG=1",
@@ -194,16 +208,29 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
 				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
 				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
 				CLANG_WARN_EMPTY_BODY = YES;
 				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
 				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = YES;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				GCC_C_LANGUAGE_STANDARD = gnu99;
 				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
 				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
 				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
 				GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
diff --git a/projects/XCode/OCTest/OCTest.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/projects/XCode/OCTest/OCTest.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/projects/XCode/OCTest/OCTest.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDEDidComputeMac32BitWarning</key>
+	<true/>
+</dict>
+</plist>
diff --git a/projects/XCode/OCTest/OCTest/OCTest.1 b/projects/XCode/OCTest/OCTest/OCTest.1
index 38afeb5..1cd333e 100644
--- a/projects/XCode/OCTest/OCTest/OCTest.1
+++ b/projects/XCode/OCTest/OCTest/OCTest.1
@@ -61,9 +61,9 @@
 .\" .Sh DIAGNOSTICS       \" May not be needed
 .\" .Bl -diag
 .\" .It Diagnostic Tag
-.\" Diagnostic informtion here.
+.\" Diagnostic information here.
 .\" .It Diagnostic Tag
-.\" Diagnostic informtion here.
+.\" Diagnostic information here.
 .\" .El
 .Sh SEE ALSO
 .\" List links in ascending order by section, alphabetically within a section.
diff --git a/projects/XCode/OCTest/catch_objc_impl.mm b/projects/XCode/OCTest/catch_objc_impl.mm
index 01443cc..e439a3a 100644
--- a/projects/XCode/OCTest/catch_objc_impl.mm
+++ b/projects/XCode/OCTest/catch_objc_impl.mm
@@ -1,6 +1,7 @@
 // This file #includes all the .cpp files into a single .mm
 // - so they get compiled as ObjectiveC++
 
+#include "../../../include/internal/catch_tostring.cpp"
 #include "../../../include/internal/catch_approx.cpp"
 #include "../../../include/internal/catch_assertionhandler.cpp"
 #include "../../../include/internal/catch_assertionresult.cpp"
@@ -29,6 +30,7 @@
 #include "../../../include/internal/catch_matchers.cpp"
 #include "../../../include/internal/catch_matchers_string.cpp"
 #include "../../../include/internal/catch_message.cpp"
+#include "../../../include/internal/catch_output_redirect.cpp"
 #include "../../../include/internal/catch_random_number_generator.cpp"
 #include "../../../include/internal/catch_registry_hub.cpp"
 #include "../../../include/internal/catch_reporter_registry.cpp"
@@ -51,8 +53,8 @@
 #include "../../../include/internal/catch_test_spec.cpp"
 #include "../../../include/internal/catch_test_spec_parser.cpp"
 #include "../../../include/internal/catch_timer.cpp"
-#include "../../../include/internal/catch_tostring.cpp"
 #include "../../../include/internal/catch_totals.cpp"
+#include "../../../include/internal/catch_uncaught_exceptions.cpp"
 #include "../../../include/internal/catch_version.cpp"
 #include "../../../include/internal/catch_wildcard_pattern.cpp"
 #include "../../../include/internal/catch_xmlwriter.cpp"
@@ -63,5 +65,5 @@
 #include "../../../include/reporters/catch_reporter_compact.cpp"
 #include "../../../include/reporters/catch_reporter_console.cpp"
 #include "../../../include/reporters/catch_reporter_junit.cpp"
-#include "../../../include/reporters/catch_reporter_multi.cpp"
+#include "../../../include/reporters/catch_reporter_listening.cpp"
 #include "../../../include/reporters/catch_reporter_xml.cpp"
diff --git a/scripts/approvalTests.py b/scripts/approvalTests.py
index a2ab5d5..bb01e6d 100755
--- a/scripts/approvalTests.py
+++ b/scripts/approvalTests.py
@@ -1,7 +1,8 @@
 #!/usr/bin/env python
 
-from  __future__ import print_function
+from __future__ import print_function
 
+import io
 import os
 import sys
 import subprocess
@@ -11,9 +12,13 @@
 import scriptCommon
 from scriptCommon import catchPath
 
+if os.name == 'nt':
+    # Enable console colours on windows
+    os.system('')
+
 rootPath = os.path.join(catchPath, 'projects/SelfTest/Baselines')
 
-
+langFilenameParser = re.compile(r'(.+\.[ch]pp)')
 filelocParser = re.compile(r'''
     .*/
     (.+\.[ch]pp)  # filename
@@ -72,10 +77,11 @@
 
 overallResult = 0
 
+
 def diffFiles(fileA, fileB):
-    with open(fileA, 'r') as file:
+    with io.open(fileA, 'r', encoding='utf-8', errors='surrogateescape') as file:
         aLines = [line.rstrip() for line in file.readlines()]
-    with open(fileB, 'r') as file:
+    with io.open(fileB, 'r', encoding='utf-8', errors='surrogateescape') as file:
         bLines = [line.rstrip() for line in file.readlines()]
 
     shortenedFilenameA = fileA.rsplit(os.sep, 1)[-1]
@@ -85,13 +91,24 @@
     return [line for line in diff if line[0] in ('+', '-')]
 
 
-def filterLine(line):
+def normalizeFilepath(line):
     if catchPath in line:
         # make paths relative to Catch root
         line = line.replace(catchPath + os.sep, '')
-        # go from \ in windows paths to /
-        line = line.replace('\\', '/')
 
+    m = langFilenameParser.match(line)
+    if m:
+        filepath = m.group(0)
+        # go from \ in windows paths to /
+        filepath = filepath.replace('\\', '/')
+        # remove start of relative path
+        filepath = filepath.replace('../', '')
+        line = line[:m.start()] + filepath + line[m.end():]
+
+    return line
+
+def filterLine(line, isCompact):
+    line = normalizeFilepath(line)
 
     # strip source line numbers
     m = filelocParser.match(line)
@@ -103,6 +120,10 @@
     else:
         line = lineNumberParser.sub(" ", line)
 
+    if isCompact:
+        line = line.replace(': FAILED', ': failed')
+        line = line.replace(': PASSED', ': passed')
+
     # strip Catch version number
     line = versionParser.sub("<version>", line)
 
@@ -139,10 +160,10 @@
     subprocess.call(args, stdout=f, stderr=f)
     f.close()
 
-    rawFile = open(rawResultsPath, 'r')
-    filteredFile = open(filteredResultsPath, 'w')
+    rawFile = io.open(rawResultsPath, 'r', encoding='utf-8', errors='surrogateescape')
+    filteredFile = io.open(filteredResultsPath, 'w', encoding='utf-8', errors='surrogateescape')
     for line in rawFile:
-        filteredFile.write(filterLine(line).rstrip() + "\n")
+        filteredFile.write(filterLine(line, 'compact' in baseName).rstrip() + "\n")
     filteredFile.close()
     rawFile.close()
 
@@ -170,19 +191,19 @@
 print("  " + cmdPath)
 
 
-### Keep default reporters here
+# ## Keep default reporters here ##
 # Standard console reporter
-approve("console.std", ["~[!nonportable]~[!benchmark]~[approvals]", "--order", "lex"])
+approve("console.std", ["~[!nonportable]~[!benchmark]~[approvals]", "--order", "lex", "--rng-seed", "1"])
 # console reporter, include passes, warn about No Assertions
-approve("console.sw", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "--order", "lex"])
+approve("console.sw", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "--order", "lex", "--rng-seed", "1"])
 # console reporter, include passes, warn about No Assertions, limit failures to first 4
-approve("console.swa4", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "-x", "4", "--order", "lex"])
+approve("console.swa4", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "-x", "4", "--order", "lex", "--rng-seed", "1"])
 # junit reporter, include passes, warn about No Assertions
-approve("junit.sw", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "-r", "junit", "--order", "lex"])
+approve("junit.sw", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "-r", "junit", "--order", "lex", "--rng-seed", "1"])
 # xml reporter, include passes, warn about No Assertions
-approve("xml.sw", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "-r", "xml", "--order", "lex"])
+approve("xml.sw", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "-r", "xml", "--order", "lex", "--rng-seed", "1"])
 # compact reporter, include passes, warn about No Assertions
-approve('compact.sw', ['~[!nonportable]~[!benchmark]~[approvals]', '-s', '-w', 'NoAssertions', '-r', 'compact', '--order', 'lex'])
+approve('compact.sw', ['~[!nonportable]~[!benchmark]~[approvals]', '-s', '-w', 'NoAssertions', '-r', 'compact', '--order', 'lex', "--rng-seed", "1"])
 
 if overallResult != 0:
     print("If these differences are expected, run approve.py to approve new baselines.")
diff --git a/scripts/approve.py b/scripts/approve.py
index 78a2a9e..f03417d 100755
--- a/scripts/approve.py
+++ b/scripts/approve.py
@@ -11,23 +11,23 @@
 rootPath = os.path.join( catchPath, 'projects/SelfTest/Baselines' )
 
 if len(sys.argv) > 1:
-	files = [os.path.join( rootPath, f ) for f in sys.argv[1:]]
+    files = [os.path.join( rootPath, f ) for f in sys.argv[1:]]
 else:
-	files = glob.glob( os.path.join( rootPath, "*.unapproved.txt" ) )
+    files = glob.glob( os.path.join( rootPath, "*.unapproved.txt" ) )
 
 
 def approveFile( approvedFile, unapprovedFile ):
-	justFilename = unapprovedFile[len(rootPath)+1:]
-	if os.path.exists( unapprovedFile ):
-		if os.path.exists( approvedFile ):
-			os.remove( approvedFile )
-		os.rename( unapprovedFile, approvedFile )
-		print( "approved " + justFilename )
-	else:
-		print( "approval file " + justFilename + " does not exist" )
+    justFilename = unapprovedFile[len(rootPath)+1:]
+    if os.path.exists( unapprovedFile ):
+        if os.path.exists( approvedFile ):
+            os.remove( approvedFile )
+        os.rename( unapprovedFile, approvedFile )
+        print( "approved " + justFilename )
+    else:
+        print( "approval file " + justFilename + " does not exist" )
 
-if len(files) > 0:
-	for unapprovedFile in files:
-		approveFile( unapprovedFile.replace( "unapproved.txt", "approved.txt" ), unapprovedFile )
+if files:
+    for unapprovedFile in files:
+        approveFile( unapprovedFile.replace( "unapproved.txt", "approved.txt" ), unapprovedFile )
 else:
-	print( "no files to approve" )
+    print( "no files to approve" )
diff --git a/scripts/embed.py b/scripts/embed.py
index 23b157c..6675703 100644
--- a/scripts/embed.py
+++ b/scripts/embed.py
@@ -25,7 +25,7 @@
     # TBD:
     #  #if, #ifdef, comments after #else
     def mapLine( self, lineNo, line ):
-        for idFrom, idTo in self.idMap.iteritems():
+        for idFrom, idTo in self.idMap.items():
             r = re.compile("(.*)" + idFrom + "(.*)")
 
             m = r.match( line )
@@ -38,7 +38,7 @@
             # print("[{0}] originalNs: '{1}' - closing".format(lineNo, originalNs))
             # print( "  " + line )
             # print( "  1:[{0}]\n  2:[{1}]\n  3:[{2}]\n  4:[{3}]\n  5:[{4}]".format( m.group(1), m.group(2), m.group(3), m.group(4), m.group(5) ) )
-            if self.outerNamespace.has_key(originalNs):
+            if originalNs in self.outerNamespace:
                 outerNs, innerNs = self.outerNamespace[originalNs]
                 return "{0}}}{1}{2}::{3}{4}{5}\n".format( m.group(1), m.group(2), outerNs, innerNs, m.group(4), m.group(5))
         m = nsRe.match( line )
@@ -47,7 +47,7 @@
             # print("[{0}] originalNs: '{1}'".format(lineNo, originalNs))
             # print( "  " + line )
             # print( "  1:[{0}]\n  2:[{1}]\n  3:[{2}]\n  4:[{3}]".format( m.group(1), m.group(2), m.group(3), m.group(4) ) )
-            if self.outerNamespace.has_key(originalNs):
+            if originalNs in self.outerNamespace:
                 outerNs, innerNs = self.outerNamespace[originalNs]
                 return "{0}{1} {{ namespace {2}{3}{4}\n".format( m.group(1), outerNs, innerNs, m.group(3), m.group(4) )
 
diff --git a/scripts/embedClara.py b/scripts/embedClara.py
old mode 100644
new mode 100755
index e7bb933..7ceb3e3
--- a/scripts/embedClara.py
+++ b/scripts/embedClara.py
@@ -1,3 +1,5 @@
+#!/usr/bin/env python
+
 # Execute this script any time you import a new copy of Clara into the third_party area
 import os
 import sys
diff --git a/scripts/fixWhitespace.py b/scripts/fixWhitespace.py
index 6f37c53..bfa4aa0 100755
--- a/scripts/fixWhitespace.py
+++ b/scripts/fixWhitespace.py
@@ -4,19 +4,20 @@
 import os
 from scriptCommon import catchPath
 
-changedFiles = 0
-
 def isSourceFile( path ):
     return path.endswith( ".cpp" ) or path.endswith( ".h" ) or path.endswith( ".hpp" )
 
 def fixAllFilesInDir( dir ):
+    changedFiles = 0
     for f in os.listdir( dir ):
         path = os.path.join( dir,f )
         if os.path.isfile( path ):
             if isSourceFile( path ):
-                fixFile( path )
+                if fixFile( path ):
+                    changedFiles += 1
         else:
             fixAllFilesInDir( path )
+    return changedFiles
 
 def fixFile( path ):
     f = open( path, 'r' )
@@ -41,8 +42,10 @@
             f2.write( line )
         f2.close()
         os.remove( altPath )
+        return True
+    return False
 
-fixAllFilesInDir(catchPath)
+changedFiles = fixAllFilesInDir(catchPath)
 if changedFiles > 0:
     print( "Fixed " + str(changedFiles) + " file(s)" )
 else:
diff --git a/scripts/generateSingleHeader.py b/scripts/generateSingleHeader.py
index 633e8c1..31033d6 100755
--- a/scripts/generateSingleHeader.py
+++ b/scripts/generateSingleHeader.py
@@ -7,7 +7,6 @@
 import sys
 import re
 import datetime
-import string
 from glob import glob
 
 from scriptCommon import catchPath
@@ -25,7 +24,7 @@
 
     seenHeaders = set([])
     rootPath = os.path.join( catchPath, 'include/' )
-    outputPath = os.path.join( catchPath, 'single_include/catch.hpp' )
+    outputPath = os.path.join( catchPath, 'single_include/catch2/catch.hpp' )
 
     globals = {
         'includeImpl' : True,
@@ -34,7 +33,7 @@
     }
 
     for arg in sys.argv[1:]:
-        arg = string.lower(arg)
+        arg = arg.lower()
         if arg == "noimpl":
             globals['includeImpl'] = False
             print( "Not including impl code" )
@@ -47,11 +46,11 @@
     outDir = os.path.dirname(outputPath)
     if not os.path.exists(outDir):
         os.makedirs(outDir)
-    out = io.open( outputPath, 'w', newline='\n')
+    out = io.open( outputPath, 'w', newline='\n', encoding='utf-8')
 
     def write( line ):
         if globals['includeImpl'] or globals['implIfDefs'] == -1:
-            out.write( line.decode('utf-8') )
+            out.write( line )
 
     def insertCpps():
         dirs = [os.path.join( rootPath, s) for s in ['', 'internal', 'reporters']]
@@ -65,9 +64,9 @@
             parseFile(dir, name)
 
     def parseFile( path, filename ):
-        f = open( os.path.join(path, filename), 'r' )
+        f = io.open( os.path.join(path, filename), 'r', encoding='utf-8' )
         blanks = 0
-        write( "// start {0}\n".format( filename ) )
+        write( u"// start {0}\n".format( filename ) )
         for line in f:
             if '// ~*~* CATCH_CPP_STITCH_PLACE *~*~' in line:
                 insertCpps()
@@ -82,7 +81,7 @@
             if m:
                 header = m.group(1)
                 headerPath, sep, headerFile = header.rpartition( "/" )
-                if not headerFile in seenHeaders:
+                if headerFile not in seenHeaders:
                     if headerFile != "tbc_text_format.h" and headerFile != "clara.h":
                         seenHeaders.add( headerFile )
                     if headerPath == "internal" and path.endswith("internal/"):
@@ -102,25 +101,25 @@
                         blanks = 0
                     if blanks < 2 and not defineParser.match(line):
                         write( line.rstrip() + "\n" )
-        write( '// end {}\n'.format(filename) )
+        write( u'// end {}\n'.format(filename) )
 
 
-    write( "/*\n" )
-    write( " *  Catch v{0}\n".format( v.getVersionString() ) )
-    write( " *  Generated: {0}\n".format( datetime.datetime.now() ) )
-    write( " *  ----------------------------------------------------------\n" )
-    write( " *  This file has been merged from multiple headers. Please don't edit it directly\n" )
-    write( " *  Copyright (c) {} Two Blue Cubes Ltd. All rights reserved.\n".format( datetime.date.today().year ) )
-    write( " *\n" )
-    write( " *  Distributed under the Boost Software License, Version 1.0. (See accompanying\n" )
-    write( " *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n" )
-    write( " */\n" )
-    write( "#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" )
-    write( "#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" )
+    write( u"/*\n" )
+    write( u" *  Catch v{0}\n".format( v.getVersionString() ) )
+    write( u" *  Generated: {0}\n".format( datetime.datetime.now() ) )
+    write( u" *  ----------------------------------------------------------\n" )
+    write( u" *  This file has been merged from multiple headers. Please don't edit it directly\n" )
+    write( u" *  Copyright (c) {} Two Blue Cubes Ltd. All rights reserved.\n".format( datetime.date.today().year ) )
+    write( u" *\n" )
+    write( u" *  Distributed under the Boost Software License, Version 1.0. (See accompanying\n" )
+    write( u" *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n" )
+    write( u" */\n" )
+    write( u"#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" )
+    write( u"#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" )
 
     parseFile( rootPath, 'catch.hpp' )
 
-    write( "#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n\n" )
+    write( u"#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n\n" )
     out.close()
     print ("Generated single include for Catch v{0}\n".format( v.getVersionString() ) )
 
diff --git a/scripts/releaseCommon.py b/scripts/releaseCommon.py
index 6e44da2..9cdc4f6 100644
--- a/scripts/releaseCommon.py
+++ b/scripts/releaseCommon.py
@@ -12,8 +12,6 @@
 versionPath = os.path.join( rootPath, "internal/catch_version.cpp" )
 definePath = os.path.join(rootPath, 'catch.hpp')
 readmePath = os.path.join( catchPath, "README.md" )
-conanPath = os.path.join(catchPath, 'conanfile.py')
-conanTestPath = os.path.join(catchPath, 'test_package', 'conanfile.py')
 cmakePath = os.path.join(catchPath, 'CMakeLists.txt')
 
 class Version:
@@ -98,35 +96,6 @@
             line = '[![Try online](https://img.shields.io/badge/try-online-blue.svg)]({0})'.format(wandboxLink)
         f.write( line + "\n" )
 
-def updateConanFile(version):
-    conanParser = re.compile( r'    version = "\d+\.\d+\.\d+.*"')
-    f = open( conanPath, 'r' )
-    lines = []
-    for line in f:
-        m = conanParser.match( line )
-        if m:
-            lines.append( '    version = "{0}"'.format(format(version.getVersionString())) )
-        else:
-            lines.append( line.rstrip() )
-    f.close()
-    f = open( conanPath, 'w' )
-    for line in lines:
-        f.write( line + "\n" )
-
-def updateConanTestFile(version):
-    conanParser = re.compile( r'    requires = \"Catch\/\d+\.\d+\.\d+.*@%s\/%s\" % \(username, channel\)')
-    f = open( conanTestPath, 'r' )
-    lines = []
-    for line in f:
-        m = conanParser.match( line )
-        if m:
-            lines.append( '    requires = "Catch/{0}@%s/%s" % (username, channel)'.format(format(version.getVersionString())) )
-        else:
-            lines.append( line.rstrip() )
-    f.close()
-    f = open( conanTestPath, 'w' )
-    for line in lines:
-        f.write( line + "\n" )
 
 def updateCmakeFile(version):
     with open(cmakePath, 'r') as file:
@@ -169,10 +138,8 @@
     import shutil
     for rep in ('automake', 'tap', 'teamcity'):
         sourceFile = os.path.join(catchPath, 'include/reporters/catch_reporter_{}.hpp'.format(rep))
-        destFile = os.path.join(catchPath, 'single_include/catch_reporter_{}.hpp'.format(rep))
+        destFile = os.path.join(catchPath, 'single_include', 'catch2', 'catch_reporter_{}.hpp'.format(rep))
         shutil.copyfile(sourceFile, destFile)
 
     updateReadmeFile(version)
-    updateConanFile(version)
-    updateConanTestFile(version)
     updateCmakeFile(version)
diff --git a/scripts/releaseNotes.py b/scripts/releaseNotes.py
index 80fffbf..5e770bb 100755
--- a/scripts/releaseNotes.py
+++ b/scripts/releaseNotes.py
@@ -1,5 +1,7 @@
 #!/usr/bin/env python
 
+from __future__ import print_function
+
 import os
 import re
 import urllib2
@@ -41,7 +43,6 @@
         pass
     elif line.startswith( "Date:"):
         dates.append( line[5:].lstrip() )
-        pass
     elif line == "" and prevLine == "":
         pass
     else:
@@ -58,7 +59,7 @@
         else:
             messages.append( line2 )
 
-print "All changes between {0} and {1}:\n".format( dates[-1], dates[0] )
+print("All changes between {0} and {1}:\n".format( dates[-1], dates[0] ))
 
 for line in messages:
-    print line
+    print(line)
diff --git a/scripts/scriptCommon.py b/scripts/scriptCommon.py
index 9adadb6..eadf9ff 100644
--- a/scripts/scriptCommon.py
+++ b/scripts/scriptCommon.py
@@ -6,8 +6,13 @@
 catchPath = os.path.dirname(os.path.realpath( os.path.dirname(sys.argv[0])))
 
 def getBuildExecutable():
-    dir = os.environ.get('CATCH_DEV_OUT_DIR', "cmake-build-debug/SelfTest")
-    return dir
+    if os.name == 'nt':
+        dir = os.environ.get('CATCH_DEV_OUT_DIR', "cmake-build-debug/projects/SelfTest.exe")
+        return dir
+    else:
+        dir = os.environ.get('CATCH_DEV_OUT_DIR', "cmake-build-debug/projects/SelfTest")
+        return dir
+
 
 def runAndCapture( args ):
     child = subprocess.Popen(" ".join( args ), shell=True, stdout=subprocess.PIPE)
@@ -15,7 +20,7 @@
     line = ""
     while True:
         out = child.stdout.read(1)
-        if out == '' and child.poll() != None:
+        if out == '' and child.poll():
             break
         if out != '':
             if out == '\n':
diff --git a/scripts/updateDocumentToC.py b/scripts/updateDocumentToC.py
index 948e5e1..325c8a3 100644
--- a/scripts/updateDocumentToC.py
+++ b/scripts/updateDocumentToC.py
@@ -12,7 +12,6 @@
 #
 
 from  __future__  import print_function
-from scriptCommon import catchPath
 
 import argparse
 import glob
@@ -20,12 +19,14 @@
 import re
 import sys
 
+from scriptCommon import catchPath
+
 # Configuration:
 
 minTocEntries = 4
 
 headingExcludeDefault = [1,3,4,5]  # use level 2 headers for at default
-headingExcludeRelease = [2,3,4,5]  # use level 1 headers for release-notes.md
+headingExcludeRelease = [1,3,4,5]  # use level 1 headers for release-notes.md
 
 documentsDefault = os.path.join(os.path.relpath(catchPath), 'docs/*.md')
 releaseNotesName = 'release-notes.md'
@@ -90,18 +91,20 @@
     level = len(stripped_right) - len(stripped_both)
     stripped_wspace = stripped_both.strip()
 
-    # character replacements
-    replaced_colon = stripped_wspace.replace('.', '')
-    replaced_slash = replaced_colon.replace('/', '')
-    rem_nonvalids = ''.join([c if c in VALIDS
-                             else '-' for c in replaced_slash])
+    # GitHub's sluggification works in an interesting way
+    # 1) '+', '/', '(', ')' and so on are just removed
+    # 2) spaces are converted into '-' directly
+    # 3) multiple -- are not collapsed
 
-    lowered = rem_nonvalids.lower()
-    dashified = re.sub(r'(-)\1+', r'\1', lowered)  # remove duplicate dashes
-    dashified = dashified.strip('-')  # strip dashes from start and end
-
-    # exception '&' (double-dash in github)
-    dashified = dashified.replace('-&-', '--')
+    dashified = ''
+    for c in stripped_wspace:
+        if c in VALIDS:
+            dashified += c.lower()
+        elif c.isspace():
+            dashified += '-'
+        else:
+            # Unknown symbols are just removed
+            continue
 
     return [stripped_wspace, dashified, level]
 
@@ -127,7 +130,7 @@
             A list of 3-value sublists, where the first value
             represents the heading, the second value the string
             that was inserted assigned to the IDs in the anchor tags,
-            and the third value is an integer that reprents the headline level.
+            and the third value is an integer that represents the headline level.
             E.g.,
             [['some header lvl3', 'some-header-lvl3', 3], ...]
 
@@ -282,7 +285,7 @@
       input_file: str
         Path to the markdown input file.
 
-      output_file: str (defaul: None)
+      output_file: str (default: None)
         Path to the markdown output file.
 
       min_toc_len: int (default: 2)
@@ -420,7 +423,7 @@
         default=minTocEntries,
         type=int,
         metavar='N',
-        help='the minimum number of entries to create a table of contents for [{deflt}]'.format(deflt=minTocEntries))
+        help='the minimum number of entries to create a table of contents for [{default}]'.format(default=minTocEntries))
 
     parser.add_argument(
         '--remove-toc',
@@ -431,7 +434,7 @@
 
     args = parser.parse_args()
 
-    paths = args.Input if len(args.Input) > 0 else [documentsDefault]
+    paths = args.Input if args.Input else [documentsDefault]
 
     changedFiles = updateDocumentToC(paths=paths, min_toc_len=args.minTocEntries, verbose=args.verbose)
 
diff --git a/scripts/updateVcpkgPackage.py b/scripts/updateVcpkgPackage.py
deleted file mode 100644
index 43321e1..0000000
--- a/scripts/updateVcpkgPackage.py
+++ /dev/null
@@ -1,110 +0,0 @@
-#!/usr/bin/env python
-
-import io, os, re, sys, subprocess
-import hashlib
-
-from scriptCommon import catchPath
-from releaseCommon import Version
-
-print(catchPath)
-
-default_path = '../vcpkg/ports/catch2/'
-
-def adjusted_path(path):
-    return os.path.join(catchPath, path)
-
-def get_hash(path):
-    BUFF_SIZE = 65536
-    sha512 = hashlib.sha512()
-    # The newlines should be normalized into \n, which is what we want
-    # If reused use 'rb' with a file written with io.open(newline='\n')
-    with open(path, 'r') as f:
-        while True:
-            data = f.read(BUFF_SIZE)
-            if not data:
-                break
-            if sys.version_info[0] < 3:
-                sha512.update(data)
-            else:
-                sha512.update(data.encode('utf-8'))
-    return sha512.hexdigest()
-
-def update_control(path):
-    v = Version()
-    ver_string = v.getVersionString()
-
-    # Update control
-    lines = []
-    control_path = os.path.join(path, 'CONTROL')
-    with open(control_path, 'r') as f:
-        for line in f:
-            lines.append(line)
-    with open(control_path, 'w') as f:
-        for line in lines:
-            if 'Version: ' in line:
-                line = 'Version: {}\n'.format(v.getVersionString())
-            f.write(line)
-
-def update_portfile(path, header_hash, licence_hash):
-    print('Updating portfile')
-    v = Version()
-    ver_string = v.getVersionString()
-
-    # Update portfile
-    lines = []
-    portfile_path = os.path.join(path, 'portfile.cmake')
-    with open(portfile_path, 'r') as f:
-        for line in f:
-            lines.append(line)
-    with open(portfile_path, 'w') as f:
-        # There are three things we need to change/update
-        # 1) CATCH_VERSION cmake variable
-        # 2) Hash of header
-        # 3) Hash of licence
-        # We could assume licence never changes, but where is the fun in that?
-        for line in lines:
-            # Update the version
-            if 'set(CATCH_VERSION' in line:
-                line = 'set(CATCH_VERSION v{})\n'.format(v.getVersionString())
-
-            # Determine which file we are updating
-            if 'vcpkg_download_distfile' in line:
-                kind = line.split('(')[-1].strip()
-
-            # Update the hashes
-            if 'SHA512' in line and kind == 'HEADER':
-                line = '    SHA512 {}\n'.format(header_hash)
-            if 'SHA512' in line and kind == 'LICENSE':
-                line = '    SHA512 {}\n'.format(licence_hash)
-            f.write(line)
-
-
-def git_push(path_to_repo):
-    v = Version()
-    ver_string = v.getVersionString()
-
-    os.chdir(path_to_repo)
-
-    # Work with git
-    # Make sure we branch off master
-    subprocess.call('git checkout master', shell=True)
-    
-    # Update repo to current master, so we don't work off old version of the portsfile 
-    subprocess.call('git pull Microsoft master', shell=True)
-    subprocess.call('git push', shell=True)
-
-    # Create a new branch for the update
-    subprocess.call('git checkout -b catch-{}'.format(ver_string), shell=True)
-    # Add changed files (should be only our files)
-    subprocess.call('git add -u .', shell=True)
-    # Create a commit with these changes
-    subprocess.call('git commit -m "Update Catch to {}"'.format(ver_string), shell=True)
-    # Don't push, so author can review
-    print('Changes were commited to the vcpkg fork. Please check, push and open PR.')
-
-header_hash = get_hash(adjusted_path('single_include/catch.hpp'))
-licence_hash = get_hash(adjusted_path('LICENSE.txt'))
-update_control(adjusted_path(default_path))
-update_portfile(adjusted_path(default_path), header_hash, licence_hash)
-
-git_push(adjusted_path('../vcpkg'))
diff --git a/scripts/updateWandbox.py b/scripts/updateWandbox.py
index 25a7463..564f948 100644
--- a/scripts/updateWandbox.py
+++ b/scripts/updateWandbox.py
@@ -34,14 +34,14 @@
         'code': main_file,
         'codes': [{
             'file': 'catch.hpp',
-            'code': open(os.path.join(catchPath, 'single_include', 'catch.hpp')).read()
+            'code': open(os.path.join(catchPath, 'single_include', 'catch2', 'catch.hpp')).read()
         }],
         'options': 'c++11,cpp-no-pedantic,boost-nothing',
         'compiler-option-raw': '-DCATCH_CONFIG_FAST_COMPILE',
         'save': True
     })
 
-    if 'status' in response and not 'compiler_error' in response:
+    if 'status' in response and 'compiler_error' not in response:
         return True, response['url']
     else:
         return False, response
diff --git a/single_include/catch.hpp b/single_include/catch2/catch.hpp
similarity index 75%
rename from single_include/catch.hpp
rename to single_include/catch2/catch.hpp
index 808debb..1850fff 100644
--- a/single_include/catch.hpp
+++ b/single_include/catch2/catch.hpp
@@ -1,9 +1,9 @@
 /*
- *  Catch v2.1.1
- *  Generated: 2018-01-26 16:04:07.190063
+ *  Catch v2.7.0
+ *  Generated: 2019-03-07 21:34:30.252164
  *  ----------------------------------------------------------
  *  This file has been merged from multiple headers. Please don't edit it directly
- *  Copyright (c) 2018 Two Blue Cubes Ltd. All rights reserved.
+ *  Copyright (c) 2019 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)
@@ -13,6 +13,10 @@
 // start catch.hpp
 
 
+#define CATCH_VERSION_MAJOR 2
+#define CATCH_VERSION_MINOR 7
+#define CATCH_VERSION_PATCH 0
+
 #ifdef __clang__
 #    pragma clang system_header
 #elif defined __GNUC__
@@ -26,16 +30,19 @@
 #       pragma warning(push)
 #       pragma warning(disable: 161 1682)
 #   else // __ICC
-#       pragma clang diagnostic ignored "-Wunused-variable"
 #       pragma clang diagnostic push
 #       pragma clang diagnostic ignored "-Wpadded"
 #       pragma clang diagnostic ignored "-Wswitch-enum"
 #       pragma clang diagnostic ignored "-Wcovered-switch-default"
 #    endif
 #elif defined __GNUC__
-#    pragma GCC diagnostic ignored "-Wunused-variable"
-#    pragma GCC diagnostic ignored "-Wparentheses"
+     // Because REQUIREs trigger GCC's -Wparentheses, and because still
+     // supported version of g++ have only buggy support for _Pragmas,
+     // Wparentheses have to be suppressed globally.
+#    pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details
+
 #    pragma GCC diagnostic push
+#    pragma GCC diagnostic ignored "-Wunused-variable"
 #    pragma GCC diagnostic ignored "-Wpadded"
 #endif
 // end catch_suppress_warnings.h
@@ -51,7 +58,9 @@
 #  if defined(CATCH_CONFIG_DISABLE_MATCHERS)
 #    undef CATCH_CONFIG_DISABLE_MATCHERS
 #  endif
-#  define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
+#  if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
+#    define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
+#  endif
 #endif
 
 #if !defined(CATCH_CONFIG_IMPL_ONLY)
@@ -68,7 +77,7 @@
 #elif defined(linux) || defined(__linux) || defined(__linux__)
 #  define CATCH_PLATFORM_LINUX
 
-#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
+#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__)
 #  define CATCH_PLATFORM_WINDOWS
 #endif
 
@@ -100,6 +109,7 @@
 // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
 // CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
 // CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
+// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled?
 // ****************
 // Note to maintainers: if new toggles are added please document them
 // in configuration.md, too
@@ -112,10 +122,18 @@
 
 #ifdef __cplusplus
 
-#  if __cplusplus >= 201402L
+#  if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
 #    define CATCH_CPP14_OR_GREATER
 #  endif
 
+#  if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
+#    define CATCH_CPP17_OR_GREATER
+#  endif
+
+#endif
+
+#if defined(CATCH_CPP17_OR_GREATER)
+#  define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
 #endif
 
 #ifdef __clang__
@@ -133,16 +151,24 @@
 #       define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
             _Pragma( "clang diagnostic pop" )
 
+#       define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
+            _Pragma( "clang diagnostic push" ) \
+            _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" )
+#       define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS \
+            _Pragma( "clang diagnostic pop" )
+
 #endif // __clang__
 
 ////////////////////////////////////////////////////////////////////////////////
+// Assume that non-Windows platforms support posix signals by default
+#if !defined(CATCH_PLATFORM_WINDOWS)
+    #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
 // We know some environments not to support full POSIX signals
-#if defined(__CYGWIN__) || defined(__QNX__)
-
-#   if !defined(CATCH_CONFIG_POSIX_SIGNALS)
-#       define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
-#   endif
-
+#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__)
+    #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
 #endif
 
 #ifdef __OS400__
@@ -151,19 +177,48 @@
 #endif
 
 ////////////////////////////////////////////////////////////////////////////////
+// Android somehow still does not support std::to_string
+#if defined(__ANDROID__)
+#    define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// Not all Windows environments support SEH properly
+#if defined(__MINGW32__)
+#    define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// PS4
+#if defined(__ORBIS__)
+#    define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
 // Cygwin
 #ifdef __CYGWIN__
 
 // Required for some versions of Cygwin to declare gettimeofday
 // see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
 #   define _BSD_SOURCE
+// some versions of cygwin (most) do not support std::to_string. Use the libstd check.
+// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813
+# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
+	       && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
 
+#	define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
+
+# endif
 #endif // __CYGWIN__
 
 ////////////////////////////////////////////////////////////////////////////////
 // Visual C++
 #ifdef _MSC_VER
 
+#  if _MSC_VER >= 1900 // Visual Studio 2015 or newer
+#    define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
+#  endif
+
 // Universal Windows platform does not support SEH
 // Or console colours (or console at all...)
 #  if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
@@ -172,9 +227,34 @@
 #    define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
 #  endif
 
+// MSVC traditional preprocessor needs some workaround for __VA_ARGS__
+// _MSVC_TRADITIONAL == 0 means new conformant preprocessor
+// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor
+#  if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
+#    define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#  endif
+
 #endif // _MSC_VER
 
 ////////////////////////////////////////////////////////////////////////////////
+// Check if we are compiled with -fno-exceptions or equivalent
+#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND)
+#  define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// DJGPP
+#ifdef __DJGPP__
+#  define CATCH_INTERNAL_CONFIG_NO_WCHAR
+#endif // __DJGPP__
+
+////////////////////////////////////////////////////////////////////////////////
+// Embarcadero C++Build
+#if defined(__BORLANDC__)
+    #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
 
 // Use of __COUNTER__ is suppressed during code analysis in
 // CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly
@@ -185,16 +265,92 @@
     #define CATCH_INTERNAL_CONFIG_COUNTER
 #endif
 
+////////////////////////////////////////////////////////////////////////////////
+// Check if string_view is available and usable
+// The check is split apart to work around v140 (VS2015) preprocessor issue...
+#if defined(__has_include)
+#if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER)
+#    define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW
+#endif
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// Check if optional is available and usable
+#if defined(__has_include)
+#  if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
+#    define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
+#  endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
+#endif // __has_include
+
+////////////////////////////////////////////////////////////////////////////////
+// Check if variant is available and usable
+#if defined(__has_include)
+#  if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
+#    if defined(__clang__) && (__clang_major__ < 8)
+       // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852
+       // fix should be in clang 8, workaround in libstdc++ 8.2
+#      include <ciso646>
+#      if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
+#        define CATCH_CONFIG_NO_CPP17_VARIANT
+#      else
+#        define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
+#      endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
+#    else
+#      define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
+#    endif // defined(__clang__) && (__clang_major__ < 8)
+#  endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
+#endif // __has_include
+
 #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
 #   define CATCH_CONFIG_COUNTER
 #endif
-#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH)
+#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH)
 #   define CATCH_CONFIG_WINDOWS_SEH
 #endif
 // This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
-#if !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
+#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
 #   define CATCH_CONFIG_POSIX_SIGNALS
 #endif
+// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions.
+#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR)
+#   define CATCH_CONFIG_WCHAR
+#endif
+
+#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING)
+#    define CATCH_CONFIG_CPP11_TO_STRING
+#endif
+
+#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL)
+#  define CATCH_CONFIG_CPP17_OPTIONAL
+#endif
+
+#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
+#  define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
+#endif
+
+#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW)
+#  define CATCH_CONFIG_CPP17_STRING_VIEW
+#endif
+
+#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT)
+#  define CATCH_CONFIG_CPP17_VARIANT
+#endif
+
+#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
+#  define CATCH_INTERNAL_CONFIG_NEW_CAPTURE
+#endif
+
+#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE)
+#  define CATCH_CONFIG_NEW_CAPTURE
+#endif
+
+#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
+#  define CATCH_CONFIG_DISABLE_EXCEPTIONS
+#endif
+
+#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN)
+#  define CATCH_CONFIG_POLYFILL_ISNAN
+#endif
 
 #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
 #   define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
@@ -204,6 +360,24 @@
 #   define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
 #   define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
 #endif
+#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS)
+#   define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS
+#   define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
+#endif
+
+#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
+#define CATCH_TRY if ((true))
+#define CATCH_CATCH_ALL if ((false))
+#define CATCH_CATCH_ANON(type) if ((false))
+#else
+#define CATCH_TRY try
+#define CATCH_CATCH_ALL catch (...)
+#define CATCH_CATCH_ANON(type) catch (type)
+#endif
+
+#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR)
+#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#endif
 
 // end catch_compiler_capabilities.h
 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
@@ -218,6 +392,10 @@
 #include <string>
 #include <cstdint>
 
+// We need a dummy global operator<< so we can bring it into Catch namespace later
+struct Catch_global_namespace_dummy {};
+std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy);
+
 namespace Catch {
 
     struct CaseSensitive { enum Choice {
@@ -244,10 +422,10 @@
             line( _line )
         {}
 
-        SourceLineInfo( SourceLineInfo const& other )        = default;
-        SourceLineInfo( SourceLineInfo && )                  = default;
-        SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
-        SourceLineInfo& operator = ( SourceLineInfo && )     = default;
+        SourceLineInfo( SourceLineInfo const& other )            = default;
+        SourceLineInfo& operator = ( SourceLineInfo const& )     = default;
+        SourceLineInfo( SourceLineInfo&& )              noexcept = default;
+        SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default;
 
         bool empty() const noexcept;
         bool operator == ( SourceLineInfo const& other ) const noexcept;
@@ -259,6 +437,11 @@
 
     std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
 
+    // Bring in operator<< from global namespace into Catch namespace
+    // This is necessary because the overload of operator<< above makes
+    // lookup stop at namespace Catch
+    using ::operator<<;
+
     // Use this in variadic streaming macros to allow
     //    >> +StreamEndStop
     // as well as
@@ -295,7 +478,6 @@
 // start catch_interfaces_testcase.h
 
 #include <vector>
-#include <memory>
 
 namespace Catch {
 
@@ -306,8 +488,6 @@
         virtual ~ITestInvoker();
     };
 
-    using ITestCasePtr = std::shared_ptr<ITestInvoker>;
-
     class TestCase;
     struct IConfig;
 
@@ -332,8 +512,6 @@
 
 namespace Catch {
 
-    class StringData;
-
     /// A non-owning string class (similar to the forthcoming std::string_view)
     /// Note that, because a StringRef may be a substring of another string,
     /// it may not be null terminated. c_str() must return a null terminated
@@ -423,16 +601,20 @@
     public: // substrings and searches
         auto substr( size_type start, size_type size ) const noexcept -> StringRef;
 
+        // Returns the current start pointer.
+        // Note that the pointer can change when if the StringRef is a substring
+        auto currentData() const noexcept -> char const*;
+
     private: // ownership queries - may not be consistent between calls
         auto isOwned() const noexcept -> bool;
         auto isSubstring() const noexcept -> bool;
-        auto data() const noexcept -> char const*;
     };
 
     auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string;
     auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string;
     auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string;
 
+    auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&;
     auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&;
 
     inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {
@@ -441,7 +623,193 @@
 
 } // namespace Catch
 
+inline auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef {
+    return Catch::StringRef( rawChars, size );
+}
+
 // end catch_stringref.h
+// start catch_type_traits.hpp
+
+
+#include <type_traits>
+
+namespace Catch{
+
+#ifdef CATCH_CPP17_OR_GREATER
+	template <typename...>
+	inline constexpr auto is_unique = std::true_type{};
+
+	template <typename T, typename... Rest>
+	inline constexpr auto is_unique<T, Rest...> = std::bool_constant<
+		(!std::is_same_v<T, Rest> && ...) && is_unique<Rest...>
+	>{};
+#else
+
+template <typename...>
+struct is_unique : std::true_type{};
+
+template <typename T0, typename T1, typename... Rest>
+struct is_unique<T0, T1, Rest...> : std::integral_constant
+<bool,
+     !std::is_same<T0, T1>::value
+     && is_unique<T0, Rest...>::value
+     && is_unique<T1, Rest...>::value
+>{};
+
+#endif
+}
+
+// end catch_type_traits.hpp
+// start catch_preprocessor.hpp
+
+
+#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__
+#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__)))
+#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__)))
+#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__)))
+#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__)))
+#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__)))
+
+#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__
+// MSVC needs more evaluations
+#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__)))
+#define CATCH_RECURSE(...)  CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__))
+#else
+#define CATCH_RECURSE(...)  CATCH_RECURSION_LEVEL5(__VA_ARGS__)
+#endif
+
+#define CATCH_REC_END(...)
+#define CATCH_REC_OUT
+
+#define CATCH_EMPTY()
+#define CATCH_DEFER(id) id CATCH_EMPTY()
+
+#define CATCH_REC_GET_END2() 0, CATCH_REC_END
+#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2
+#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1
+#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT
+#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0)
+#define CATCH_REC_NEXT(test, next)  CATCH_REC_NEXT1(CATCH_REC_GET_END test, next)
+
+#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
+#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ )
+#define CATCH_REC_LIST2(f, x, peek, ...)   f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
+
+#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )
+#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ )
+#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...)   f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )
+
+// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results,
+// and passes userdata as the first parameter to each invocation,
+// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c)
+#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
+
+#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
+
+#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param)
+#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__
+#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
+#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
+#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__)
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__
+#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param))
+#else
+// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
+#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__)
+#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__
+#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1)
+#endif
+
+#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__)
+
+#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name, __VA_ARGS__)
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name,...) Name " - " #__VA_ARGS__
+#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name,...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))
+#else
+// MSVC is adding extra space and needs more calls to properly remove ()
+#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name,...) Name " -" #__VA_ARGS__
+#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, __VA_ARGS__)
+#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
+#endif
+
+#define INTERNAL_CATCH_MAKE_TYPE_LIST(types) Catch::TypeList<INTERNAL_CATCH_REMOVE_PARENS(types)>
+
+#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(types)\
+    CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,INTERNAL_CATCH_REMOVE_PARENS(types))
+
+// end catch_preprocessor.hpp
+// start catch_meta.hpp
+
+
+#include <type_traits>
+
+namespace Catch {
+template< typename... >
+struct TypeList {};
+
+template< typename... >
+struct append;
+
+template< template<typename...> class L1
+    , typename...E1
+    , template<typename...> class L2
+    , typename...E2
+>
+struct append< L1<E1...>, L2<E2...> > {
+    using type = L1<E1..., E2...>;
+};
+
+template< template<typename...> class L1
+    , typename...E1
+    , template<typename...> class L2
+    , typename...E2
+    , typename...Rest
+>
+struct append< L1<E1...>, L2<E2...>, Rest...> {
+    using type = typename append< L1<E1..., E2...>, Rest... >::type;
+};
+
+template< template<typename...> class
+    , typename...
+>
+struct rewrap;
+
+template< template<typename...> class Container
+    , template<typename...> class List
+    , typename...elems
+>
+struct rewrap<Container, List<elems...>> {
+    using type = TypeList< Container< elems... > >;
+};
+
+template< template<typename...> class Container
+    , template<typename...> class List
+    , class...Elems
+    , typename...Elements>
+    struct rewrap<Container, List<Elems...>, Elements...> {
+    using type = typename append<TypeList<Container<Elems...>>, typename rewrap<Container, Elements...>::type>::type;
+};
+
+template< template<typename...> class...Containers >
+struct combine {
+    template< typename...Types >
+    struct with_types {
+        template< template <typename...> class Final >
+        struct into {
+            using type = typename append<Final<>, typename rewrap<Containers, Types...>::type...>::type;
+        };
+    };
+};
+
+template<typename T>
+struct always_false : std::false_type {};
+
+} // namespace Catch
+
+// end catch_meta.hpp
 namespace Catch {
 
 template<typename C>
@@ -464,13 +832,13 @@
 }
 
 struct NameAndTags {
-    NameAndTags( StringRef name_ = StringRef(), StringRef tags_ = StringRef() ) noexcept;
+    NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept;
     StringRef name;
     StringRef tags;
 };
 
 struct AutoReg : NonCopyable {
-    AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept;
+    AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept;
     ~AutoReg();
 };
 
@@ -481,19 +849,30 @@
         static void TestName()
     #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
         namespace{                        \
-            struct TestName : ClassName { \
+            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
                 void test();              \
             };                            \
         }                                 \
         void TestName::test()
-
+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION( TestName, ... )  \
+        template<typename TestType>                                             \
+        static void TestName()
+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... )    \
+        namespace{                                                                                  \
+            template<typename TestType>                                                             \
+            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) {     \
+                void test();                                                                        \
+            };                                                                                      \
+        }                                                                                           \
+        template<typename TestType>                                                                 \
+        void TestName::test()
 #endif
 
     ///////////////////////////////////////////////////////////////////////////////
     #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
         static void TestName(); \
         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
-        namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
+        namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
         CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
         static void TestName()
     #define INTERNAL_CATCH_TESTCASE( ... ) \
@@ -509,7 +888,7 @@
     #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
         namespace{ \
-            struct TestName : ClassName{ \
+            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
                 void test(); \
             }; \
             Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
@@ -522,9 +901,153 @@
     ///////////////////////////////////////////////////////////////////////////////
     #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
-        Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
+        Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
         CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
 
+    ///////////////////////////////////////////////////////////////////////////////
+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, ... )\
+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+        template<typename TestType> \
+        static void TestFunc();\
+        namespace {\
+            template<typename...Types> \
+            struct TestName{\
+                template<typename...Ts> \
+                TestName(Ts...names){\
+                    CATCH_INTERNAL_CHECK_UNIQUE_TYPES(CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \
+                    using expander = int[];\
+                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ names, Tags } ), 0)... };/* NOLINT */ \
+                }\
+            };\
+            INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, __VA_ARGS__) \
+        }\
+        CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
+        template<typename TestType> \
+        static void TestFunc()
+
+#if defined(CATCH_CPP17_OR_GREATER)
+#define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) static_assert(Catch::is_unique<__VA_ARGS__>,"Duplicate type detected in declaration of template test case");
+#else
+#define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) static_assert(Catch::is_unique<__VA_ARGS__>::value,"Duplicate type detected in declaration of template test case");
+#endif
+
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
+        INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ )
+#else
+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ ) )
+#endif
+
+    #define INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, ...)\
+        static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
+            TestName<CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)>(CATCH_REC_LIST_UD(INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME,Name, __VA_ARGS__));\
+            return 0;\
+        }();
+
+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, TmplTypes, TypesList) \
+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS                      \
+        template<typename TestType> static void TestFuncName();       \
+        namespace {                                                   \
+            template<typename... Types>                               \
+            struct TestName {                                         \
+                TestName() {                                          \
+                    CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...)       \
+                    int index = 0;                                    \
+                    using expander = int[];                           \
+                    constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
+                    constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
+                    constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
+                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */\
+                }                                                     \
+            };                                                        \
+            static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
+                using TestInit = Catch::combine<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)> \
+                            ::with_types<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(TypesList)>::into<TestName>::type; \
+                TestInit();                                           \
+                return 0;                                             \
+            }();                                                      \
+        }                                                             \
+        CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS                    \
+        template<typename TestType>                                   \
+        static void TestFuncName()
+
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
+        INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ),Name,Tags,__VA_ARGS__)
+#else
+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ ) )
+#endif
+
+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, ... ) \
+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+        namespace{ \
+            template<typename TestType> \
+            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
+                void test();\
+            };\
+            template<typename...Types> \
+            struct TestNameClass{\
+                template<typename...Ts> \
+                TestNameClass(Ts...names){\
+                    CATCH_INTERNAL_CHECK_UNIQUE_TYPES(CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \
+                    using expander = int[];\
+                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ names, Tags } ), 0)... };/* NOLINT */ \
+                }\
+            };\
+            INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestNameClass, Name, __VA_ARGS__)\
+        }\
+        CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS\
+        template<typename TestType> \
+        void TestName<TestType>::test()
+
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
+        INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, __VA_ARGS__ )
+#else
+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, __VA_ARGS__ ) )
+#endif
+
+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, TmplTypes, TypesList)\
+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+        template<typename TestType> \
+            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
+                void test();\
+            };\
+        namespace {\
+            template<typename...Types>\
+            struct TestNameClass{\
+                TestNameClass(){\
+                    CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...)\
+                    int index = 0;\
+                    using expander = int[];\
+                    constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
+                    constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
+                    constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
+                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */ \
+                }\
+            };\
+            static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
+                using TestInit = Catch::combine<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>\
+                            ::with_types<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(TypesList)>::into<TestNameClass>::type;\
+                TestInit();\
+                return 0;\
+            }(); \
+        }\
+        CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
+        template<typename TestType> \
+        void TestName<TestType>::test()
+
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
+        INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, __VA_ARGS__ )
+#else
+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, __VA_ARGS__ ) )
+#endif
+
 // end catch_test_registry.h
 // start catch_capture.hpp
 
@@ -639,13 +1162,15 @@
             return *this;
         }
         auto get() -> std::ostream& { return *m_oss; }
-
-        static void cleanup();
     };
 }
 
 // end catch_stream.h
 
+#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
+#include <string_view>
+#endif
+
 #ifdef __OBJC__
 // start catch_objc_arc.hpp
 
@@ -697,14 +1222,7 @@
 #pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless
 #endif
 
-// We need a dummy global operator<< so we can bring it into Catch namespace later
-struct Catch_global_namespace_dummy {};
-std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy);
-
 namespace Catch {
-    // Bring in operator<< from global namespace into Catch namespace
-    using ::operator<<;
-
     namespace Detail {
 
         extern const std::string unprintableString;
@@ -733,13 +1251,36 @@
         std::string convertUnknownEnumToString( E e );
 
         template<typename T>
-        typename std::enable_if<!std::is_enum<T>::value, std::string>::type convertUnstreamable( T const& ) {
+        typename std::enable_if<
+            !std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value,
+        std::string>::type convertUnstreamable( T const& ) {
             return Detail::unprintableString;
-        };
+        }
         template<typename T>
-        typename std::enable_if<std::is_enum<T>::value, std::string>::type convertUnstreamable( T const& value ) {
+        typename std::enable_if<
+            !std::is_enum<T>::value && std::is_base_of<std::exception, T>::value,
+         std::string>::type convertUnstreamable(T const& ex) {
+            return ex.what();
+        }
+
+        template<typename T>
+        typename std::enable_if<
+            std::is_enum<T>::value
+        , std::string>::type convertUnstreamable( T const& value ) {
             return convertUnknownEnumToString( value );
-        };
+        }
+
+#if defined(_MANAGED)
+        //! Convert a CLR string to a utf8 std::string
+        template<typename T>
+        std::string clrReferenceToString( T^ ref ) {
+            if (ref == nullptr)
+                return std::string("null");
+            auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());
+            cli::pin_ptr<System::Byte> p = &bytes[0];
+            return std::string(reinterpret_cast<char const *>(p), bytes->Length);
+        }
+#endif
 
     } // namespace Detail
 
@@ -751,7 +1292,9 @@
         typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
             convert(const Fake& value) {
                 ReusableStringStream rss;
-                rss << value;
+                // NB: call using the function-like syntax to avoid ambiguity with
+                // user-defined templated operator<< under clang.
+                rss.operator<<(value);
                 return rss.str();
         }
 
@@ -759,7 +1302,11 @@
         static
         typename std::enable_if<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
             convert( const Fake& value ) {
-                return Detail::convertUnstreamable( value );
+#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
+            return Detail::convertUnstreamable(value);
+#else
+            return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);
+#endif
         }
     };
 
@@ -777,6 +1324,13 @@
             return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<E>::type>(e));
         }
 
+#if defined(_MANAGED)
+        template <typename T>
+        std::string stringify( T^ e ) {
+            return ::Catch::StringMaker<T^>::convert(e);
+        }
+#endif
+
     } // namespace Detail
 
     // Some predefined specializations
@@ -785,10 +1339,13 @@
     struct StringMaker<std::string> {
         static std::string convert(const std::string& str);
     };
+
+#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
     template<>
-    struct StringMaker<std::wstring> {
-        static std::string convert(const std::wstring& wstr);
+    struct StringMaker<std::string_view> {
+        static std::string convert(std::string_view str);
     };
+#endif
 
     template<>
     struct StringMaker<char const *> {
@@ -798,6 +1355,20 @@
     struct StringMaker<char *> {
         static std::string convert(char * str);
     };
+
+#ifdef CATCH_CONFIG_WCHAR
+    template<>
+    struct StringMaker<std::wstring> {
+        static std::string convert(const std::wstring& wstr);
+    };
+
+# ifdef CATCH_CONFIG_CPP17_STRING_VIEW
+    template<>
+    struct StringMaker<std::wstring_view> {
+        static std::string convert(std::wstring_view str);
+    };
+# endif
+
     template<>
     struct StringMaker<wchar_t const *> {
         static std::string convert(wchar_t const * str);
@@ -806,23 +1377,26 @@
     struct StringMaker<wchar_t *> {
         static std::string convert(wchar_t * str);
     };
+#endif
 
+    // TBD: Should we use `strnlen` to ensure that we don't go out of the buffer,
+    //      while keeping string semantics?
     template<int SZ>
     struct StringMaker<char[SZ]> {
-        static std::string convert(const char* str) {
+        static std::string convert(char const* str) {
             return ::Catch::Detail::stringify(std::string{ str });
         }
     };
     template<int SZ>
     struct StringMaker<signed char[SZ]> {
-        static std::string convert(const char* str) {
-            return ::Catch::Detail::stringify(std::string{ str });
+        static std::string convert(signed char const* str) {
+            return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) });
         }
     };
     template<int SZ>
     struct StringMaker<unsigned char[SZ]> {
-        static std::string convert(const char* str) {
-            return ::Catch::Detail::stringify(std::string{ str });
+        static std::string convert(unsigned char const* str) {
+            return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) });
         }
     };
 
@@ -906,6 +1480,15 @@
         }
     };
 
+#if defined(_MANAGED)
+    template <typename T>
+    struct StringMaker<T^> {
+        static std::string convert( T^ ref ) {
+            return ::Catch::Detail::clrReferenceToString(ref);
+        }
+    };
+#endif
+
     namespace Detail {
         template<typename InputIterator>
         std::string rangeToString(InputIterator first, InputIterator last) {
@@ -954,7 +1537,9 @@
 #if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)
 #  define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
 #  define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
+#  define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
 #  define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
+#  define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
 #endif
 
 // Separate std::pair specialization
@@ -976,6 +1561,24 @@
 }
 #endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
 
+#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL)
+#include <optional>
+namespace Catch {
+    template<typename T>
+    struct StringMaker<std::optional<T> > {
+        static std::string convert(const std::optional<T>& optional) {
+            ReusableStringStream rss;
+            if (optional.has_value()) {
+                rss << ::Catch::Detail::stringify(*optional);
+            } else {
+                rss << "{ }";
+            }
+            return rss.str();
+        }
+    };
+}
+#endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
+
 // Separate std::tuple specialization
 #if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
 #include <tuple>
@@ -1017,6 +1620,34 @@
 }
 #endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
 
+#if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT)
+#include <variant>
+namespace Catch {
+    template<>
+    struct StringMaker<std::monostate> {
+        static std::string convert(const std::monostate&) {
+            return "{ }";
+        }
+    };
+
+    template<typename... Elements>
+    struct StringMaker<std::variant<Elements...>> {
+        static std::string convert(const std::variant<Elements...>& variant) {
+            if (variant.valueless_by_exception()) {
+                return "{valueless variant}";
+            } else {
+                return std::visit(
+                    [](const auto& value) {
+                        return ::Catch::Detail::stringify(value);
+                    },
+                    variant
+                );
+            }
+        }
+    };
+}
+#endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
+
 namespace Catch {
     struct not_this_one {}; // Tag type for detecting which begin/ end are being selected
 
@@ -1034,6 +1665,13 @@
             !std::is_same<decltype(end(std::declval<T>())), not_this_one>::value;
     };
 
+#if defined(_MANAGED) // Managed types are never ranges
+    template <typename T>
+    struct is_range<T^> {
+        static const bool value = false;
+    };
+#endif
+
     template<typename Range>
     std::string rangeToString( Range const& range ) {
         return ::Catch::Detail::rangeToString( begin( range ), end( range ) );
@@ -1057,7 +1695,7 @@
     }
 
     template<typename R>
-    struct StringMaker<R, typename std::enable_if<is_range<R>::value && !std::is_array<R>::value>::type> {
+    struct StringMaker<R, typename std::enable_if<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>::type> {
         static std::string convert( R const& range ) {
             return rangeToString( range );
         }
@@ -1202,6 +1840,7 @@
 #pragma warning(disable:4018) // more "signed/unsigned mismatch"
 #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
 #pragma warning(disable:4180) // qualifier applied to function type has no meaning
+#pragma warning(disable:4800) // Forcing result to true or false
 #endif
 
 namespace Catch {
@@ -1245,6 +1884,62 @@
             m_op( op ),
             m_rhs( rhs )
         {}
+
+        template<typename T>
+        auto operator && ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
+            static_assert(always_false<T>::value,
+            "chained comparisons are not supported inside assertions, "
+            "wrap the expression inside parentheses, or decompose it");
+        }
+
+        template<typename T>
+        auto operator || ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
+            static_assert(always_false<T>::value,
+            "chained comparisons are not supported inside assertions, "
+            "wrap the expression inside parentheses, or decompose it");
+        }
+
+        template<typename T>
+        auto operator == ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
+            static_assert(always_false<T>::value,
+            "chained comparisons are not supported inside assertions, "
+            "wrap the expression inside parentheses, or decompose it");
+        }
+
+        template<typename T>
+        auto operator != ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
+            static_assert(always_false<T>::value,
+            "chained comparisons are not supported inside assertions, "
+            "wrap the expression inside parentheses, or decompose it");
+        }
+
+        template<typename T>
+        auto operator > ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
+            static_assert(always_false<T>::value,
+            "chained comparisons are not supported inside assertions, "
+            "wrap the expression inside parentheses, or decompose it");
+        }
+
+        template<typename T>
+        auto operator < ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
+            static_assert(always_false<T>::value,
+            "chained comparisons are not supported inside assertions, "
+            "wrap the expression inside parentheses, or decompose it");
+        }
+
+        template<typename T>
+        auto operator >= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
+            static_assert(always_false<T>::value,
+            "chained comparisons are not supported inside assertions, "
+            "wrap the expression inside parentheses, or decompose it");
+        }
+
+        template<typename T>
+        auto operator <= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
+            static_assert(always_false<T>::value,
+            "chained comparisons are not supported inside assertions, "
+            "wrap the expression inside parentheses, or decompose it");
+        }
     };
 
     template<typename LhsT>
@@ -1257,14 +1952,14 @@
 
     public:
         explicit UnaryExpr( LhsT lhs )
-        :   ITransientExpression{ false, lhs ? true : false },
+        :   ITransientExpression{ false, static_cast<bool>(lhs) },
             m_lhs( lhs )
         {}
     };
 
     // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int)
     template<typename LhsT, typename RhsT>
-    auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast<bool>(lhs == rhs); };
+    auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast<bool>(lhs == rhs); }
     template<typename T>
     auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }
     template<typename T>
@@ -1275,7 +1970,7 @@
     auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }
 
     template<typename LhsT, typename RhsT>
-    auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); };
+    auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); }
     template<typename T>
     auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }
     template<typename T>
@@ -1324,6 +2019,20 @@
             return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };
         }
 
+        template<typename RhsT>
+        auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {
+            static_assert(always_false<RhsT>::value,
+            "operator&& is not supported inside assertions, "
+            "wrap the expression inside parentheses, or decompose it");
+        }
+
+        template<typename RhsT>
+        auto operator || ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {
+            static_assert(always_false<RhsT>::value,
+            "operator|| is not supported inside assertions, "
+            "wrap the expression inside parentheses, or decompose it");
+        }
+
         auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
             return UnaryExpr<LhsT>{ m_lhs };
         }
@@ -1365,12 +2074,15 @@
     struct SectionInfo;
     struct SectionEndInfo;
     struct MessageInfo;
+    struct MessageBuilder;
     struct Counts;
     struct BenchmarkInfo;
     struct BenchmarkStats;
     struct AssertionReaction;
+    struct SourceLineInfo;
 
     struct ITransientExpression;
+    struct IGeneratorTracker;
 
     struct IResultCapture {
 
@@ -1381,12 +2093,16 @@
         virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
         virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
 
+        virtual auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0;
+
         virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0;
         virtual void benchmarkEnded( BenchmarkStats const& stats ) = 0;
 
         virtual void pushScopedMessage( MessageInfo const& message ) = 0;
         virtual void popScopedMessage( MessageInfo const& message ) = 0;
 
+        virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0;
+
         virtual void handleFatalErrorCondition( StringRef message ) = 0;
 
         virtual void handleExpr
@@ -1462,7 +2178,7 @@
 
     public:
         AssertionHandler
-            (   StringRef macroName,
+            (   StringRef const& macroName,
                 SourceLineInfo const& lineInfo,
                 StringRef capturedExpression,
                 ResultDisposition::Flags resultDisposition );
@@ -1493,7 +2209,7 @@
         auto allowThrows() const -> bool;
     };
 
-    void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString );
+    void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString );
 
 } // namespace Catch
 
@@ -1501,15 +2217,16 @@
 // start catch_message.h
 
 #include <string>
+#include <vector>
 
 namespace Catch {
 
     struct MessageInfo {
-        MessageInfo(    std::string const& _macroName,
+        MessageInfo(    StringRef const& _macroName,
                         SourceLineInfo const& _lineInfo,
                         ResultWas::OfType _type );
 
-        std::string macroName;
+        StringRef macroName;
         std::string message;
         SourceLineInfo lineInfo;
         ResultWas::OfType type;
@@ -1533,7 +2250,7 @@
     };
 
     struct MessageBuilder : MessageStream {
-        MessageBuilder( std::string const& macroName,
+        MessageBuilder( StringRef const& macroName,
                         SourceLineInfo const& lineInfo,
                         ResultWas::OfType type );
 
@@ -1549,9 +2266,34 @@
     class ScopedMessage {
     public:
         explicit ScopedMessage( MessageBuilder const& builder );
+        ScopedMessage( ScopedMessage& duplicate ) = delete;
+        ScopedMessage( ScopedMessage&& old );
         ~ScopedMessage();
 
         MessageInfo m_info;
+        bool m_moved;
+    };
+
+    class Capturer {
+        std::vector<MessageInfo> m_messages;
+        IResultCapture& m_resultCapture = getResultCapture();
+        size_t m_captured = 0;
+    public:
+        Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names );
+        ~Capturer();
+
+        void captureValue( size_t index, std::string const& value );
+
+        template<typename T>
+        void captureValues( size_t index, T const& value ) {
+            captureValue( index, Catch::Detail::stringify( value ) );
+        }
+
+        template<typename T, typename... Ts>
+        void captureValues( size_t index, T const& value, Ts const&... values ) {
+            captureValue( index, Catch::Detail::stringify(value) );
+            captureValues( index+1, values... );
+        }
     };
 
 } // end namespace Catch
@@ -1565,17 +2307,17 @@
   #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
 #endif
 
-#if defined(CATCH_CONFIG_FAST_COMPILE)
+#if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
 
 ///////////////////////////////////////////////////////////////////////////////
 // Another way to speed-up compilation is to omit local try-catch for REQUIRE*
 // macros.
-#define CATCH_INTERNAL_TRY
+#define INTERNAL_CATCH_TRY
 #define INTERNAL_CATCH_CATCH( capturer )
 
 #else // CATCH_CONFIG_FAST_COMPILE
 
-#define CATCH_INTERNAL_TRY try
+#define INTERNAL_CATCH_TRY try
 #define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); }
 
 #endif
@@ -1585,14 +2327,14 @@
 ///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
     do { \
-        Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
-        CATCH_INTERNAL_TRY { \
+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
+        INTERNAL_CATCH_TRY { \
             CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
             catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \
             CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
         } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
-    } while( (void)0, false && static_cast<bool>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look
+    } while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look
     // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1608,7 +2350,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
     do { \
-        Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
         try { \
             static_cast<void>(__VA_ARGS__); \
             catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
@@ -1622,7 +2364,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
     do { \
-        Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
         if( catchAssertionHandler.allowThrows() ) \
             try { \
                 static_cast<void>(__VA_ARGS__); \
@@ -1639,7 +2381,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
     do { \
-        Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
         if( catchAssertionHandler.allowThrows() ) \
             try { \
                 static_cast<void>(expr); \
@@ -1659,27 +2401,36 @@
 ///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
     do { \
-        Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \
         catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
     } while( false )
 
 ///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \
+    auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \
+    varName.captureValues( 0, __VA_ARGS__ )
+
+///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CATCH_INFO( macroName, log ) \
-    Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );
+    Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \
+    Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
 
 ///////////////////////////////////////////////////////////////////////////////
 // Although this is matcher-based, it can be used with just a string
 #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
     do { \
-        Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
         if( catchAssertionHandler.allowThrows() ) \
             try { \
                 static_cast<void>(__VA_ARGS__); \
                 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
             } \
             catch( ... ) { \
-                Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher ); \
+                Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \
             } \
         else \
             catchAssertionHandler.handleThrowingCallSkipped(); \
@@ -1719,6 +2470,7 @@
 
         Totals delta( Totals const& prevTotals ) const;
 
+        int error = 0;
         Counts assertions;
         Counts testCases;
     };
@@ -1732,17 +2484,20 @@
     struct SectionInfo {
         SectionInfo
             (   SourceLineInfo const& _lineInfo,
+                std::string const& _name );
+
+        // Deprecated
+        SectionInfo
+            (   SourceLineInfo const& _lineInfo,
                 std::string const& _name,
-                std::string const& _description = std::string() );
+                std::string const& ) : SectionInfo( _lineInfo, _name ) {}
 
         std::string name;
-        std::string description;
+        std::string description; // !Deprecated: this will always be empty
         SourceLineInfo lineInfo;
     };
 
     struct SectionEndInfo {
-        SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds );
-
         SectionInfo sectionInfo;
         Counts prevAssertions;
         double durationInSeconds;
@@ -1796,8 +2551,15 @@
 
 } // end namespace Catch
 
-    #define INTERNAL_CATCH_SECTION( ... ) \
-        if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
+#define INTERNAL_CATCH_SECTION( ... ) \
+    CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
+    if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
+    CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
+
+#define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
+    CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
+    if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \
+    CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
 
 // end catch_section.h
 // start catch_benchmark.h
@@ -1873,7 +2635,7 @@
         virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
         virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
 
-        virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
+        virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0;
 
         virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
     };
@@ -1888,7 +2650,7 @@
         virtual void registerStartupException() noexcept = 0;
     };
 
-    IRegistryHub& getRegistryHub();
+    IRegistryHub const& getRegistryHub();
     IMutableRegistryHub& getMutableRegistryHub();
     void cleanUp();
     std::string translateActiveException();
@@ -1970,7 +2732,6 @@
 // start catch_approx.h
 
 #include <type_traits>
-#include <stdexcept>
 
 namespace Catch {
 namespace Detail {
@@ -1978,18 +2739,26 @@
     class Approx {
     private:
         bool equalityComparisonImpl(double other) const;
+        // Validates the new margin (margin >= 0)
+        // out-of-line to avoid including stdexcept in the header
+        void setMargin(double margin);
+        // Validates the new epsilon (0 < epsilon < 1)
+        // out-of-line to avoid including stdexcept in the header
+        void setEpsilon(double epsilon);
 
     public:
         explicit Approx ( double value );
 
         static Approx custom();
 
+        Approx operator-() const;
+
         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
         Approx operator()( T const& value ) {
             Approx approx( static_cast<double>(value) );
-            approx.epsilon( m_epsilon );
-            approx.margin( m_margin );
-            approx.scale( m_scale );
+            approx.m_epsilon = m_epsilon;
+            approx.m_margin = m_margin;
+            approx.m_scale = m_scale;
             return approx;
         }
 
@@ -2041,27 +2810,14 @@
         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
         Approx& epsilon( T const& newEpsilon ) {
             double epsilonAsDouble = static_cast<double>(newEpsilon);
-            if( epsilonAsDouble < 0 || epsilonAsDouble > 1.0 ) {
-                throw std::domain_error
-                    (   "Invalid Approx::epsilon: " +
-                        Catch::Detail::stringify( epsilonAsDouble ) +
-                        ", Approx::epsilon has to be between 0 and 1" );
-            }
-            m_epsilon = epsilonAsDouble;
+            setEpsilon(epsilonAsDouble);
             return *this;
         }
 
         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
         Approx& margin( T const& newMargin ) {
             double marginAsDouble = static_cast<double>(newMargin);
-            if( marginAsDouble < 0 ) {
-                throw std::domain_error
-                    (   "Invalid Approx::margin: " +
-                         Catch::Detail::stringify( marginAsDouble ) +
-                         ", Approx::Margin has to be non-negative." );
-
-            }
-            m_margin = marginAsDouble;
+            setMargin(marginAsDouble);
             return *this;
         }
 
@@ -2079,7 +2835,12 @@
         double m_scale;
         double m_value;
     };
-}
+} // end namespace Detail
+
+namespace literals {
+    Detail::Approx operator "" _a(long double val);
+    Detail::Approx operator "" _a(unsigned long long val);
+} // end namespace literals
 
 template<>
 struct StringMaker<Catch::Detail::Approx> {
@@ -2146,14 +2907,19 @@
             mutable std::string m_cachedToString;
         };
 
+#ifdef __clang__
+#    pragma clang diagnostic push
+#    pragma clang diagnostic ignored "-Wnon-virtual-dtor"
+#endif
+
         template<typename ObjectT>
         struct MatcherMethod {
             virtual bool match( ObjectT const& arg ) const = 0;
         };
-        template<typename PtrT>
-        struct MatcherMethod<PtrT*> {
-            virtual bool match( PtrT* arg ) const = 0;
-        };
+
+#ifdef __clang__
+#    pragma clang diagnostic pop
+#endif
 
         template<typename T>
         struct MatcherBase : MatcherUntypedBase, MatcherMethod<T> {
@@ -2310,6 +3076,54 @@
 } // namespace Catch
 
 // end catch_matchers_floating.h
+// start catch_matchers_generic.hpp
+
+#include <functional>
+#include <string>
+
+namespace Catch {
+namespace Matchers {
+namespace Generic {
+
+namespace Detail {
+    std::string finalizeDescription(const std::string& desc);
+}
+
+template <typename T>
+class PredicateMatcher : public MatcherBase<T> {
+    std::function<bool(T const&)> m_predicate;
+    std::string m_description;
+public:
+
+    PredicateMatcher(std::function<bool(T const&)> const& elem, std::string const& descr)
+        :m_predicate(std::move(elem)),
+        m_description(Detail::finalizeDescription(descr))
+    {}
+
+    bool match( T const& item ) const override {
+        return m_predicate(item);
+    }
+
+    std::string describe() const override {
+        return m_description;
+    }
+};
+
+} // namespace Generic
+
+    // The following functions create the actual matcher objects.
+    // The user has to explicitly specify type to the function, because
+    // infering std::function<bool(T const&)> is hard (but possible) and
+    // requires a lot of TMP.
+    template<typename T>
+    Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = "") {
+        return Generic::PredicateMatcher<T>(predicate, description);
+    }
+
+} // namespace Matchers
+} // namespace Catch
+
+// end catch_matchers_generic.hpp
 // start catch_matchers_string.h
 
 #include <string>
@@ -2495,7 +3309,7 @@
                 auto lfirst = m_target.begin(), llast = m_target.end();
                 auto rfirst = vec.begin(), rlast = vec.end();
                 // Cut common prefix to optimize checking of permuted parts
-                while (lfirst != llast && *lfirst != *rfirst) {
+                while (lfirst != llast && *lfirst == *rfirst) {
                     ++lfirst; ++rfirst;
                 }
                 if (lfirst == llast) {
@@ -2560,7 +3374,7 @@
         MatcherT m_matcher;
         StringRef m_matcherString;
     public:
-        MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString )
+        MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString )
         :   ITransientExpression{ true, matcher.match( arg ) },
             m_arg( arg ),
             m_matcher( matcher ),
@@ -2579,10 +3393,10 @@
 
     using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
 
-    void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString  );
+    void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString  );
 
     template<typename ArgT, typename MatcherT>
-    auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString  ) -> MatchExpr<ArgT, MatcherT> {
+    auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString  ) -> MatchExpr<ArgT, MatcherT> {
         return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString );
     }
 
@@ -2591,9 +3405,9 @@
 ///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
     do { \
-        Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
-        CATCH_INTERNAL_TRY { \
-            catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \
+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
+        INTERNAL_CATCH_TRY { \
+            catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \
         } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
     } while( false )
@@ -2601,14 +3415,14 @@
 ///////////////////////////////////////////////////////////////////////////////
 #define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \
     do { \
-        Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
         if( catchAssertionHandler.allowThrows() ) \
             try { \
                 static_cast<void>(__VA_ARGS__ ); \
                 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
             } \
             catch( exceptionType const& ex ) { \
-                catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher ) ); \
+                catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \
             } \
             catch( ... ) { \
                 catchAssertionHandler.handleUnexpectedInflightException(); \
@@ -2620,6 +3434,725 @@
 
 // end catch_capture_matchers.h
 #endif
+// start catch_generators.hpp
+
+// start catch_interfaces_generatortracker.h
+
+
+#include <memory>
+
+namespace Catch {
+
+    namespace Generators {
+        class GeneratorUntypedBase {
+        public:
+            GeneratorUntypedBase() = default;
+            virtual ~GeneratorUntypedBase();
+            // Attempts to move the generator to the next element
+             //
+             // Returns true iff the move succeeded (and a valid element
+             // can be retrieved).
+            virtual bool next() = 0;
+        };
+        using GeneratorBasePtr = std::unique_ptr<GeneratorUntypedBase>;
+
+    } // namespace Generators
+
+    struct IGeneratorTracker {
+        virtual ~IGeneratorTracker();
+        virtual auto hasGenerator() const -> bool = 0;
+        virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;
+        virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0;
+    };
+
+} // namespace Catch
+
+// end catch_interfaces_generatortracker.h
+// start catch_enforce.h
+
+#include <stdexcept>
+
+namespace Catch {
+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
+    template <typename Ex>
+    [[noreturn]]
+    void throw_exception(Ex const& e) {
+        throw e;
+    }
+#else // ^^ Exceptions are enabled //  Exceptions are disabled vv
+    [[noreturn]]
+    void throw_exception(std::exception const& e);
+#endif
+} // namespace Catch;
+
+#define CATCH_PREPARE_EXCEPTION( type, msg ) \
+    type( ( Catch::ReusableStringStream() << msg ).str() )
+#define CATCH_INTERNAL_ERROR( msg ) \
+    Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg))
+#define CATCH_ERROR( msg ) \
+    Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::domain_error, msg ))
+#define CATCH_RUNTIME_ERROR( msg ) \
+    Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::runtime_error, msg ))
+#define CATCH_ENFORCE( condition, msg ) \
+    do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false)
+
+// end catch_enforce.h
+#include <memory>
+#include <vector>
+#include <cassert>
+
+#include <utility>
+#include <exception>
+
+namespace Catch {
+
+class GeneratorException : public std::exception {
+    const char* const m_msg = "";
+
+public:
+    GeneratorException(const char* msg):
+        m_msg(msg)
+    {}
+
+    const char* what() const noexcept override final;
+};
+
+namespace Generators {
+
+    // !TBD move this into its own location?
+    namespace pf{
+        template<typename T, typename... Args>
+        std::unique_ptr<T> make_unique( Args&&... args ) {
+            return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+        }
+    }
+
+    template<typename T>
+    struct IGenerator : GeneratorUntypedBase {
+        virtual ~IGenerator() = default;
+
+        // Returns the current element of the generator
+        //
+        // \Precondition The generator is either freshly constructed,
+        // or the last call to `next()` returned true
+        virtual T const& get() const = 0;
+        using type = T;
+    };
+
+    template<typename T>
+    class SingleValueGenerator final : public IGenerator<T> {
+        T m_value;
+    public:
+        SingleValueGenerator(T const& value) : m_value( value ) {}
+        SingleValueGenerator(T&& value) : m_value(std::move(value)) {}
+
+        T const& get() const override {
+            return m_value;
+        }
+        bool next() override {
+            return false;
+        }
+    };
+
+    template<typename T>
+    class FixedValuesGenerator final : public IGenerator<T> {
+        std::vector<T> m_values;
+        size_t m_idx = 0;
+    public:
+        FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {}
+
+        T const& get() const override {
+            return m_values[m_idx];
+        }
+        bool next() override {
+            ++m_idx;
+            return m_idx < m_values.size();
+        }
+    };
+
+    template <typename T>
+    class GeneratorWrapper final {
+        std::unique_ptr<IGenerator<T>> m_generator;
+    public:
+        GeneratorWrapper(std::unique_ptr<IGenerator<T>> generator):
+            m_generator(std::move(generator))
+        {}
+        T const& get() const {
+            return m_generator->get();
+        }
+        bool next() {
+            return m_generator->next();
+        }
+    };
+
+    template <typename T>
+    GeneratorWrapper<T> value(T&& value) {
+        return GeneratorWrapper<T>(pf::make_unique<SingleValueGenerator<T>>(std::forward<T>(value)));
+    }
+    template <typename T>
+    GeneratorWrapper<T> values(std::initializer_list<T> values) {
+        return GeneratorWrapper<T>(pf::make_unique<FixedValuesGenerator<T>>(values));
+    }
+
+    template<typename T>
+    class Generators : public IGenerator<T> {
+        std::vector<GeneratorWrapper<T>> m_generators;
+        size_t m_current = 0;
+
+        void populate(GeneratorWrapper<T>&& generator) {
+            m_generators.emplace_back(std::move(generator));
+        }
+        void populate(T&& val) {
+            m_generators.emplace_back(value(std::move(val)));
+        }
+        template<typename U>
+        void populate(U&& val) {
+            populate(T(std::move(val)));
+        }
+        template<typename U, typename... Gs>
+        void populate(U&& valueOrGenerator, Gs... moreGenerators) {
+            populate(std::forward<U>(valueOrGenerator));
+            populate(std::forward<Gs>(moreGenerators)...);
+        }
+
+    public:
+        template <typename... Gs>
+        Generators(Gs... moreGenerators) {
+            m_generators.reserve(sizeof...(Gs));
+            populate(std::forward<Gs>(moreGenerators)...);
+        }
+
+        T const& get() const override {
+            return m_generators[m_current].get();
+        }
+
+        bool next() override {
+            if (m_current >= m_generators.size()) {
+                return false;
+            }
+            const bool current_status = m_generators[m_current].next();
+            if (!current_status) {
+                ++m_current;
+            }
+            return m_current < m_generators.size();
+        }
+    };
+
+    template<typename... Ts>
+    GeneratorWrapper<std::tuple<Ts...>> table( std::initializer_list<std::tuple<typename std::decay<Ts>::type...>> tuples ) {
+        return values<std::tuple<Ts...>>( tuples );
+    }
+
+    // Tag type to signal that a generator sequence should convert arguments to a specific type
+    template <typename T>
+    struct as {};
+
+    template<typename T, typename... Gs>
+    auto makeGenerators( GeneratorWrapper<T>&& generator, Gs... moreGenerators ) -> Generators<T> {
+        return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...);
+    }
+    template<typename T>
+    auto makeGenerators( GeneratorWrapper<T>&& generator ) -> Generators<T> {
+        return Generators<T>(std::move(generator));
+    }
+    template<typename T, typename... Gs>
+    auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators<T> {
+        return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
+    }
+    template<typename T, typename U, typename... Gs>
+    auto makeGenerators( as<T>, U&& val, Gs... moreGenerators ) -> Generators<T> {
+        return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
+    }
+
+    auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&;
+
+    template<typename L>
+    // Note: The type after -> is weird, because VS2015 cannot parse
+    //       the expression used in the typedef inside, when it is in
+    //       return type. Yeah.
+    auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) {
+        using UnderlyingType = typename decltype(generatorExpression())::type;
+
+        IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo );
+        if (!tracker.hasGenerator()) {
+            tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression()));
+        }
+
+        auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker.getGenerator() );
+        return generator.get();
+    }
+
+} // namespace Generators
+} // namespace Catch
+
+#define GENERATE( ... ) \
+    Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, []{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
+
+// end catch_generators.hpp
+// start catch_generators_generic.hpp
+
+namespace Catch {
+namespace Generators {
+
+    template <typename T>
+    class TakeGenerator : public IGenerator<T> {
+        GeneratorWrapper<T> m_generator;
+        size_t m_returned = 0;
+        size_t m_target;
+    public:
+        TakeGenerator(size_t target, GeneratorWrapper<T>&& generator):
+            m_generator(std::move(generator)),
+            m_target(target)
+        {
+            assert(target != 0 && "Empty generators are not allowed");
+        }
+        T const& get() const override {
+            return m_generator.get();
+        }
+        bool next() override {
+            ++m_returned;
+            if (m_returned >= m_target) {
+                return false;
+            }
+
+            const auto success = m_generator.next();
+            // If the underlying generator does not contain enough values
+            // then we cut short as well
+            if (!success) {
+                m_returned = m_target;
+            }
+            return success;
+        }
+    };
+
+    template <typename T>
+    GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator) {
+        return GeneratorWrapper<T>(pf::make_unique<TakeGenerator<T>>(target, std::move(generator)));
+    }
+
+    template <typename T, typename Predicate>
+    class FilterGenerator : public IGenerator<T> {
+        GeneratorWrapper<T> m_generator;
+        Predicate m_predicate;
+    public:
+        template <typename P = Predicate>
+        FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator):
+            m_generator(std::move(generator)),
+            m_predicate(std::forward<P>(pred))
+        {
+            if (!m_predicate(m_generator.get())) {
+                // It might happen that there are no values that pass the
+                // filter. In that case we throw an exception.
+                auto has_initial_value = next();
+                if (!has_initial_value) {
+                    Catch::throw_exception(GeneratorException("No valid value found in filtered generator"));
+                }
+            }
+        }
+
+        T const& get() const override {
+            return m_generator.get();
+        }
+
+        bool next() override {
+            bool success = m_generator.next();
+            if (!success) {
+                return false;
+            }
+            while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true);
+            return success;
+        }
+    };
+
+    template <typename T, typename Predicate>
+    GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) {
+        return GeneratorWrapper<T>(std::unique_ptr<IGenerator<T>>(pf::make_unique<FilterGenerator<T, Predicate>>(std::forward<Predicate>(pred), std::move(generator))));
+    }
+
+    template <typename T>
+    class RepeatGenerator : public IGenerator<T> {
+        GeneratorWrapper<T> m_generator;
+        mutable std::vector<T> m_returned;
+        size_t m_target_repeats;
+        size_t m_current_repeat = 0;
+        size_t m_repeat_index = 0;
+    public:
+        RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator):
+            m_generator(std::move(generator)),
+            m_target_repeats(repeats)
+        {
+            assert(m_target_repeats > 0 && "Repeat generator must repeat at least once");
+        }
+
+        T const& get() const override {
+            if (m_current_repeat == 0) {
+                m_returned.push_back(m_generator.get());
+                return m_returned.back();
+            }
+            return m_returned[m_repeat_index];
+        }
+
+        bool next() override {
+            // There are 2 basic cases:
+            // 1) We are still reading the generator
+            // 2) We are reading our own cache
+
+            // In the first case, we need to poke the underlying generator.
+            // If it happily moves, we are left in that state, otherwise it is time to start reading from our cache
+            if (m_current_repeat == 0) {
+                const auto success = m_generator.next();
+                if (!success) {
+                    ++m_current_repeat;
+                }
+                return m_current_repeat < m_target_repeats;
+            }
+
+            // In the second case, we need to move indices forward and check that we haven't run up against the end
+            ++m_repeat_index;
+            if (m_repeat_index == m_returned.size()) {
+                m_repeat_index = 0;
+                ++m_current_repeat;
+            }
+            return m_current_repeat < m_target_repeats;
+        }
+    };
+
+    template <typename T>
+    GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) {
+        return GeneratorWrapper<T>(pf::make_unique<RepeatGenerator<T>>(repeats, std::move(generator)));
+    }
+
+    template <typename T, typename U, typename Func>
+    class MapGenerator : public IGenerator<T> {
+        // TBD: provide static assert for mapping function, for friendly error message
+        GeneratorWrapper<U> m_generator;
+        Func m_function;
+        // To avoid returning dangling reference, we have to save the values
+        T m_cache;
+    public:
+        template <typename F2 = Func>
+        MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) :
+            m_generator(std::move(generator)),
+            m_function(std::forward<F2>(function)),
+            m_cache(m_function(m_generator.get()))
+        {}
+
+        T const& get() const override {
+            return m_cache;
+        }
+        bool next() override {
+            const auto success = m_generator.next();
+            if (success) {
+                m_cache = m_function(m_generator.get());
+            }
+            return success;
+        }
+    };
+
+    template <typename T, typename U, typename Func>
+    GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
+        return GeneratorWrapper<T>(
+            pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))
+        );
+    }
+    template <typename T, typename Func>
+    GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<T>&& generator) {
+        return GeneratorWrapper<T>(
+            pf::make_unique<MapGenerator<T, T, Func>>(std::forward<Func>(function), std::move(generator))
+        );
+    }
+
+    template <typename T>
+    class ChunkGenerator final : public IGenerator<std::vector<T>> {
+        std::vector<T> m_chunk;
+        size_t m_chunk_size;
+        GeneratorWrapper<T> m_generator;
+        bool m_used_up = false;
+    public:
+        ChunkGenerator(size_t size, GeneratorWrapper<T> generator) :
+            m_chunk_size(size), m_generator(std::move(generator))
+        {
+            m_chunk.reserve(m_chunk_size);
+            m_chunk.push_back(m_generator.get());
+            for (size_t i = 1; i < m_chunk_size; ++i) {
+                if (!m_generator.next()) {
+                    Catch::throw_exception(GeneratorException("Not enough values to initialize the first chunk"));
+                }
+                m_chunk.push_back(m_generator.get());
+            }
+        }
+        std::vector<T> const& get() const override {
+            return m_chunk;
+        }
+        bool next() override {
+            m_chunk.clear();
+            for (size_t idx = 0; idx < m_chunk_size; ++idx) {
+                if (!m_generator.next()) {
+                    return false;
+                }
+                m_chunk.push_back(m_generator.get());
+            }
+            return true;
+        }
+    };
+
+    template <typename T>
+    GeneratorWrapper<std::vector<T>> chunk(size_t size, GeneratorWrapper<T>&& generator) {
+        return GeneratorWrapper<std::vector<T>>(
+            pf::make_unique<ChunkGenerator<T>>(size, std::move(generator))
+        );
+    }
+
+} // namespace Generators
+} // namespace Catch
+
+// end catch_generators_generic.hpp
+// start catch_generators_specific.hpp
+
+// start catch_context.h
+
+#include <memory>
+
+namespace Catch {
+
+    struct IResultCapture;
+    struct IRunner;
+    struct IConfig;
+    struct IMutableContext;
+
+    using IConfigPtr = std::shared_ptr<IConfig const>;
+
+    struct IContext
+    {
+        virtual ~IContext();
+
+        virtual IResultCapture* getResultCapture() = 0;
+        virtual IRunner* getRunner() = 0;
+        virtual IConfigPtr const& getConfig() const = 0;
+    };
+
+    struct IMutableContext : IContext
+    {
+        virtual ~IMutableContext();
+        virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
+        virtual void setRunner( IRunner* runner ) = 0;
+        virtual void setConfig( IConfigPtr const& config ) = 0;
+
+    private:
+        static IMutableContext *currentContext;
+        friend IMutableContext& getCurrentMutableContext();
+        friend void cleanUpContext();
+        static void createContext();
+    };
+
+    inline IMutableContext& getCurrentMutableContext()
+    {
+        if( !IMutableContext::currentContext )
+            IMutableContext::createContext();
+        return *IMutableContext::currentContext;
+    }
+
+    inline IContext& getCurrentContext()
+    {
+        return getCurrentMutableContext();
+    }
+
+    void cleanUpContext();
+}
+
+// end catch_context.h
+// start catch_interfaces_config.h
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+#include <memory>
+
+namespace Catch {
+
+    enum class Verbosity {
+        Quiet = 0,
+        Normal,
+        High
+    };
+
+    struct WarnAbout { enum What {
+        Nothing = 0x00,
+        NoAssertions = 0x01,
+        NoTests = 0x02
+    }; };
+
+    struct ShowDurations { enum OrNot {
+        DefaultForReporter,
+        Always,
+        Never
+    }; };
+    struct RunTests { enum InWhatOrder {
+        InDeclarationOrder,
+        InLexicographicalOrder,
+        InRandomOrder
+    }; };
+    struct UseColour { enum YesOrNo {
+        Auto,
+        Yes,
+        No
+    }; };
+    struct WaitForKeypress { enum When {
+        Never,
+        BeforeStart = 1,
+        BeforeExit = 2,
+        BeforeStartAndExit = BeforeStart | BeforeExit
+    }; };
+
+    class TestSpec;
+
+    struct IConfig : NonCopyable {
+
+        virtual ~IConfig();
+
+        virtual bool allowThrows() const = 0;
+        virtual std::ostream& stream() const = 0;
+        virtual std::string name() const = 0;
+        virtual bool includeSuccessfulResults() const = 0;
+        virtual bool shouldDebugBreak() const = 0;
+        virtual bool warnAboutMissingAssertions() const = 0;
+        virtual bool warnAboutNoTests() const = 0;
+        virtual int abortAfter() const = 0;
+        virtual bool showInvisibles() const = 0;
+        virtual ShowDurations::OrNot showDurations() const = 0;
+        virtual TestSpec const& testSpec() const = 0;
+        virtual bool hasTestFilters() const = 0;
+        virtual RunTests::InWhatOrder runOrder() const = 0;
+        virtual unsigned int rngSeed() const = 0;
+        virtual int benchmarkResolutionMultiple() const = 0;
+        virtual UseColour::YesOrNo useColour() const = 0;
+        virtual std::vector<std::string> const& getSectionsToRun() const = 0;
+        virtual Verbosity verbosity() const = 0;
+    };
+
+    using IConfigPtr = std::shared_ptr<IConfig const>;
+}
+
+// end catch_interfaces_config.h
+#include <random>
+
+namespace Catch {
+namespace Generators {
+
+template <typename Float>
+class RandomFloatingGenerator final : public IGenerator<Float> {
+    // FIXME: What is the right seed?
+    std::minstd_rand m_rand;
+    std::uniform_real_distribution<Float> m_dist;
+    Float m_current_number;
+public:
+
+    RandomFloatingGenerator(Float a, Float b):
+        m_rand(getCurrentContext().getConfig()->rngSeed()),
+        m_dist(a, b) {
+        static_cast<void>(next());
+    }
+
+    Float const& get() const override {
+        return m_current_number;
+    }
+    bool next() override {
+        m_current_number = m_dist(m_rand);
+        return true;
+    }
+};
+
+template <typename Integer>
+class RandomIntegerGenerator final : public IGenerator<Integer> {
+    std::minstd_rand m_rand;
+    std::uniform_int_distribution<Integer> m_dist;
+    Integer m_current_number;
+public:
+
+    RandomIntegerGenerator(Integer a, Integer b):
+        m_rand(getCurrentContext().getConfig()->rngSeed()),
+        m_dist(a, b) {
+        static_cast<void>(next());
+    }
+
+    Integer const& get() const override {
+        return m_current_number;
+    }
+    bool next() override {
+        m_current_number = m_dist(m_rand);
+        return true;
+    }
+};
+
+// TODO: Ideally this would be also constrained against the various char types,
+//       but I don't expect users to run into that in practice.
+template <typename T>
+typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value,
+GeneratorWrapper<T>>::type
+random(T a, T b) {
+    return GeneratorWrapper<T>(
+        pf::make_unique<RandomIntegerGenerator<T>>(a, b)
+    );
+}
+
+template <typename T>
+typename std::enable_if<std::is_floating_point<T>::value,
+GeneratorWrapper<T>>::type
+random(T a, T b) {
+    return GeneratorWrapper<T>(
+        pf::make_unique<RandomFloatingGenerator<T>>(a, b)
+    );
+}
+
+template <typename T>
+class RangeGenerator final : public IGenerator<T> {
+    T m_current;
+    T m_end;
+    T m_step;
+    bool m_positive;
+
+public:
+    RangeGenerator(T const& start, T const& end, T const& step):
+        m_current(start),
+        m_end(end),
+        m_step(step),
+        m_positive(m_step > T(0))
+    {
+        assert(m_current != m_end && "Range start and end cannot be equal");
+        assert(m_step != T(0) && "Step size cannot be zero");
+        assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && "Step moves away from end");
+    }
+
+    RangeGenerator(T const& start, T const& end):
+        RangeGenerator(start, end, (start < end) ? T(1) : T(-1))
+    {}
+
+    T const& get() const override {
+        return m_current;
+    }
+
+    bool next() override {
+        m_current += m_step;
+        return (m_positive) ? (m_current < m_end) : (m_current > m_end);
+    }
+};
+
+template <typename T>
+GeneratorWrapper<T> range(T const& start, T const& end, T const& step) {
+    static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer");
+    return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end, step));
+}
+
+template <typename T>
+GeneratorWrapper<T> range(T const& start, T const& end) {
+    static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer");
+    return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end));
+}
+
+} // namespace Generators
+} // namespace Catch
+
+// end catch_generators_specific.hpp
 
 // These files are included here so the single_include script doesn't put them
 // in the conditionally compiled sections
@@ -2676,7 +4209,7 @@
     class TestCase : public TestCaseInfo {
     public:
 
-        TestCase( ITestInvoker* testCase, TestCaseInfo const& info );
+        TestCase( ITestInvoker* testCase, TestCaseInfo&& info );
 
         TestCase withName( std::string const& _newName ) const;
 
@@ -2693,8 +4226,7 @@
 
     TestCase makeTestCase(  ITestInvoker* testCase,
                             std::string const& className,
-                            std::string const& name,
-                            std::string const& description,
+                            NameAndTags const& nameAndTags,
                             SourceLineInfo const& lineInfo );
 }
 
@@ -2797,7 +4329,7 @@
                         std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
                         const char* className = class_getName( cls );
 
-                        getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo("",0) ) );
+                        getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, NameAndTags( name.c_str(), desc.c_str() ), SourceLineInfo("",0) ) );
                         noTestMethods++;
                     }
                 }
@@ -3107,76 +4639,6 @@
 #endif
 
 // end catch_test_spec_parser.h
-// start catch_interfaces_config.h
-
-#include <iosfwd>
-#include <string>
-#include <vector>
-#include <memory>
-
-namespace Catch {
-
-    enum class Verbosity {
-        Quiet = 0,
-        Normal,
-        High
-    };
-
-    struct WarnAbout { enum What {
-        Nothing = 0x00,
-        NoAssertions = 0x01
-    }; };
-
-    struct ShowDurations { enum OrNot {
-        DefaultForReporter,
-        Always,
-        Never
-    }; };
-    struct RunTests { enum InWhatOrder {
-        InDeclarationOrder,
-        InLexicographicalOrder,
-        InRandomOrder
-    }; };
-    struct UseColour { enum YesOrNo {
-        Auto,
-        Yes,
-        No
-    }; };
-    struct WaitForKeypress { enum When {
-        Never,
-        BeforeStart = 1,
-        BeforeExit = 2,
-        BeforeStartAndExit = BeforeStart | BeforeExit
-    }; };
-
-    class TestSpec;
-
-    struct IConfig : NonCopyable {
-
-        virtual ~IConfig();
-
-        virtual bool allowThrows() const = 0;
-        virtual std::ostream& stream() const = 0;
-        virtual std::string name() const = 0;
-        virtual bool includeSuccessfulResults() const = 0;
-        virtual bool shouldDebugBreak() const = 0;
-        virtual bool warnAboutMissingAssertions() const = 0;
-        virtual int abortAfter() const = 0;
-        virtual bool showInvisibles() const = 0;
-        virtual ShowDurations::OrNot showDurations() const = 0;
-        virtual TestSpec const& testSpec() const = 0;
-        virtual RunTests::InWhatOrder runOrder() const = 0;
-        virtual unsigned int rngSeed() const = 0;
-        virtual int benchmarkResolutionMultiple() const = 0;
-        virtual UseColour::YesOrNo useColour() const = 0;
-        virtual std::vector<std::string> const& getSectionsToRun() const = 0;
-        virtual Verbosity verbosity() const = 0;
-    };
-
-    using IConfigPtr = std::shared_ptr<IConfig const>;
-}
-
-// end catch_interfaces_config.h
 // Libstdc++ doesn't like incomplete classes for unique_ptr
 
 #include <memory>
@@ -3219,8 +4681,12 @@
         std::string outputFilename;
         std::string name;
         std::string processName;
+#ifndef CATCH_CONFIG_DEFAULT_REPORTER
+#define CATCH_CONFIG_DEFAULT_REPORTER "console"
+#endif
+        std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER;
+#undef CATCH_CONFIG_DEFAULT_REPORTER
 
-        std::vector<std::string> reporterNames;
         std::vector<std::string> testsOrTags;
         std::vector<std::string> sectionsToRun;
     };
@@ -3240,11 +4706,13 @@
         bool listReporters() const;
 
         std::string getProcessName() const;
+        std::string const& getReporterName() const;
 
-        std::vector<std::string> const& getReporterNames() const;
+        std::vector<std::string> const& getTestsOrTags() const;
         std::vector<std::string> const& getSectionsToRun() const override;
 
         virtual TestSpec const& testSpec() const override;
+        bool hasTestFilters() const override;
 
         bool showHelp() const;
 
@@ -3254,6 +4722,7 @@
         std::string name() const override;
         bool includeSuccessfulResults() const override;
         bool warnAboutMissingAssertions() const override;
+        bool warnAboutNoTests() const override;
         ShowDurations::OrNot showDurations() const override;
         RunTests::InWhatOrder runOrder() const override;
         unsigned int rngSeed() const override;
@@ -3271,6 +4740,7 @@
 
         std::unique_ptr<IStream const> m_stream;
         TestSpec m_testSpec;
+        bool m_hasTestFilters = false;
     };
 
 } // end namespace Catch
@@ -3410,6 +4880,7 @@
 
     struct ReporterPreferences {
         bool shouldRedirectStdOut = false;
+        bool shouldReportAllAssertions = false;
     };
 
     template<typename T>
@@ -3447,8 +4918,8 @@
 
         AssertionStats( AssertionStats const& )              = default;
         AssertionStats( AssertionStats && )                  = default;
-        AssertionStats& operator = ( AssertionStats const& ) = default;
-        AssertionStats& operator = ( AssertionStats && )     = default;
+        AssertionStats& operator = ( AssertionStats const& ) = delete;
+        AssertionStats& operator = ( AssertionStats && )     = delete;
         virtual ~AssertionStats();
 
         AssertionResult assertionResult;
@@ -3594,8 +5065,6 @@
         virtual Listeners const& getListeners() const = 0;
     };
 
-    void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter );
-
 } // end namespace Catch
 
 // end catch_interfaces_reporter.h
@@ -3603,7 +5072,7 @@
 #include <cstring>
 #include <cfloat>
 #include <cstdio>
-#include <assert.h>
+#include <cassert>
 #include <memory>
 #include <ostream>
 
@@ -3622,7 +5091,7 @@
         {
             m_reporterPrefs.shouldRedirectStdOut = false;
             if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
-                throw std::domain_error( "Verbosity level not supported by this reporter" );
+                CATCH_ERROR( "Verbosity level not supported by this reporter" );
         }
 
         ReporterPreferences getPreferences() const override {
@@ -3736,7 +5205,7 @@
         {
             m_reporterPrefs.shouldRedirectStdOut = false;
             if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
-                throw std::domain_error( "Verbosity level not supported by this reporter" );
+                CATCH_ERROR( "Verbosity level not supported by this reporter" );
         }
         ~CumulativeReporterBase() override = default;
 
@@ -3852,6 +5321,8 @@
     struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> {
         TestEventListenerBase( ReporterConfig const& _config );
 
+        static std::set<Verbosity> getSupportedVerbosities();
+
         void assertionStarting(AssertionInfo const&) override;
         bool assertionEnded(AssertionStats const&) override;
     };
@@ -3881,10 +5352,11 @@
             BrightGreen = Bright | Green,
             LightGrey = Bright | Grey,
             BrightWhite = Bright | White,
+            BrightYellow = Bright | Yellow,
 
             // By intention
             FileName = LightGrey,
-            Warning = Yellow,
+            Warning = BrightYellow,
             ResultError = BrightRed,
             ResultSuccess = BrightGreen,
             ResultExpectedFailure = Warning,
@@ -3893,7 +5365,7 @@
             Success = Green,
 
             OriginalExpression = Cyan,
-            ReconstructedExpression = Yellow,
+            ReconstructedExpression = BrightYellow,
 
             SecondaryText = LightGrey,
             Headers = White
@@ -4334,7 +5806,7 @@
 
         // Debug/ checking
         virtual bool isSectionTracker() const = 0;
-        virtual bool isIndexTracker() const = 0;
+        virtual bool isGeneratorTracker() const = 0;
     };
 
     class TrackerContext {
@@ -4375,13 +5847,6 @@
             Failed
         };
 
-        class TrackerHasName {
-            NameAndLocation m_nameAndLocation;
-        public:
-            TrackerHasName( NameAndLocation const& nameAndLocation );
-            bool operator ()( ITrackerPtr const& tracker ) const;
-        };
-
         using Children = std::vector<ITrackerPtr>;
         NameAndLocation m_nameAndLocation;
         TrackerContext& m_ctx;
@@ -4406,7 +5871,7 @@
         void openChild() override;
 
         bool isSectionTracker() const override;
-        bool isIndexTracker() const override;
+        bool isGeneratorTracker() const override;
 
         void open();
 
@@ -4426,6 +5891,8 @@
 
         bool isSectionTracker() const override;
 
+        bool isComplete() const override;
+
         static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation );
 
         void tryOpen();
@@ -4434,28 +5901,11 @@
         void addNextFilters( std::vector<std::string> const& filters );
     };
 
-    class IndexTracker : public TrackerBase {
-        int m_size;
-        int m_index = -1;
-    public:
-        IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size );
-
-        bool isIndexTracker() const override;
-        void close() override;
-
-        static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size );
-
-        int index() const;
-
-        void moveNext();
-    };
-
 } // namespace TestCaseTracking
 
 using TestCaseTracking::ITracker;
 using TestCaseTracking::TrackerContext;
 using TestCaseTracking::SectionTracker;
-using TestCaseTracking::IndexTracker;
 
 } // namespace Catch
 
@@ -4467,6 +5917,7 @@
 
     struct LeakDetector {
         LeakDetector();
+        ~LeakDetector();
     };
 
 }
@@ -4501,6 +5952,12 @@
         return Approx( 0 );
     }
 
+    Approx Approx::operator-() const {
+        auto temp(*this);
+        temp.m_value = -temp.m_value;
+        return temp;
+    }
+
     std::string Approx::toString() const {
         ReusableStringStream rss;
         rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )";
@@ -4513,8 +5970,31 @@
         return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value)));
     }
 
+    void Approx::setMargin(double margin) {
+        CATCH_ENFORCE(margin >= 0,
+            "Invalid Approx::margin: " << margin << '.'
+            << " Approx::Margin has to be non-negative.");
+        m_margin = margin;
+    }
+
+    void Approx::setEpsilon(double epsilon) {
+        CATCH_ENFORCE(epsilon >= 0 && epsilon <= 1.0,
+            "Invalid Approx::epsilon: " << epsilon << '.'
+            << " Approx::epsilon has to be in [0, 1]");
+        m_epsilon = epsilon;
+    }
+
 } // end namespace Detail
 
+namespace literals {
+    Detail::Approx operator "" _a(long double val) {
+        return Detail::Approx(val);
+    }
+    Detail::Approx operator "" _a(unsigned long long val) {
+        return Detail::Approx(val);
+    }
+} // end namespace literals
+
 std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value) {
     return value.toString();
 }
@@ -4523,58 +6003,6 @@
 // end catch_approx.cpp
 // start catch_assertionhandler.cpp
 
-// start catch_context.h
-
-#include <memory>
-
-namespace Catch {
-
-    struct IResultCapture;
-    struct IRunner;
-    struct IConfig;
-    struct IMutableContext;
-
-    using IConfigPtr = std::shared_ptr<IConfig const>;
-
-    struct IContext
-    {
-        virtual ~IContext();
-
-        virtual IResultCapture* getResultCapture() = 0;
-        virtual IRunner* getRunner() = 0;
-        virtual IConfigPtr const& getConfig() const = 0;
-    };
-
-    struct IMutableContext : IContext
-    {
-        virtual ~IMutableContext();
-        virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
-        virtual void setRunner( IRunner* runner ) = 0;
-        virtual void setConfig( IConfigPtr const& config ) = 0;
-
-    private:
-        static IMutableContext *currentContext;
-        friend IMutableContext& getCurrentMutableContext();
-        friend void cleanUpContext();
-        static void createContext();
-    };
-
-    inline IMutableContext& getCurrentMutableContext()
-    {
-        if( !IMutableContext::currentContext )
-            IMutableContext::createContext();
-        return *IMutableContext::currentContext;
-    }
-
-    inline IContext& getCurrentContext()
-    {
-        return getCurrentMutableContext();
-    }
-
-    void cleanUpContext();
-}
-
-// end catch_context.h
 // start catch_debugger.h
 
 namespace Catch {
@@ -4604,9 +6032,9 @@
 #endif
 
 #ifdef CATCH_TRAP
-    #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
+    #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }()
 #else
-    #define CATCH_BREAK_INTO_DEBUGGER() (void)0, 0
+    #define CATCH_BREAK_INTO_DEBUGGER() []{}()
 #endif
 
 // end catch_debugger.h
@@ -4614,9 +6042,6 @@
 
 // start catch_fatal_condition.h
 
-#include <string>
-
-#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
 // start catch_windows_h_proxy.h
 
 
@@ -4647,16 +6072,7 @@
 #endif // defined(CATCH_PLATFORM_WINDOWS)
 
 // end catch_windows_h_proxy.h
-
-#  if !defined ( CATCH_CONFIG_WINDOWS_SEH )
-
-namespace Catch {
-    struct FatalConditionHandler {
-        void reset();
-    };
-}
-
-#  else // CATCH_CONFIG_WINDOWS_SEH is defined
+#if defined( CATCH_CONFIG_WINDOWS_SEH )
 
 namespace Catch {
 
@@ -4675,19 +6091,7 @@
 
 } // namespace Catch
 
-#  endif // CATCH_CONFIG_WINDOWS_SEH
-
-#else // Not Windows - assumed to be POSIX compatible //////////////////////////
-
-#  if !defined(CATCH_CONFIG_POSIX_SIGNALS)
-
-namespace Catch {
-    struct FatalConditionHandler {
-        void reset();
-    };
-}
-
-#  else // CATCH_CONFIG_POSIX_SIGNALS is defined
+#elif defined ( CATCH_CONFIG_POSIX_SIGNALS )
 
 #include <signal.h>
 
@@ -4696,7 +6100,7 @@
     struct FatalConditionHandler {
 
         static bool isSet;
-        static struct sigaction oldSigActions[];// [sizeof(signalDefs) / sizeof(SignalDefs)];
+        static struct sigaction oldSigActions[];
         static stack_t oldSigStack;
         static char altStackMem[];
 
@@ -4709,9 +6113,15 @@
 
 } // namespace Catch
 
-#  endif // CATCH_CONFIG_POSIX_SIGNALS
+#else
 
-#endif // not Windows
+namespace Catch {
+    struct FatalConditionHandler {
+        void reset();
+    };
+}
+
+#endif
 
 // end catch_fatal_condition.h
 #include <string>
@@ -4771,12 +6181,16 @@
         void sectionEnded( SectionEndInfo const& endInfo ) override;
         void sectionEndedEarly( SectionEndInfo const& endInfo ) override;
 
+        auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override;
+
         void benchmarkStarting( BenchmarkInfo const& info ) override;
         void benchmarkEnded( BenchmarkStats const& stats ) override;
 
         void pushScopedMessage( MessageInfo const& message ) override;
         void popScopedMessage( MessageInfo const& message ) override;
 
+        void emplaceUnscopedMessage( MessageBuilder const& builder ) override;
+
         std::string getCurrentTestName() const override;
 
         const AssertionResult* getLastResult() const override;
@@ -4791,7 +6205,7 @@
 
     public:
         // !TBD We need to do this another way!
-        bool aborting() const override;
+        bool aborting() const final;
 
     private:
 
@@ -4817,13 +6231,14 @@
         TestRunInfo m_runInfo;
         IMutableContext& m_context;
         TestCase const* m_activeTestCase = nullptr;
-        ITracker* m_testCaseTracker;
+        ITracker* m_testCaseTracker = nullptr;
         Option<AssertionResult> m_lastResult;
 
         IConfigPtr m_config;
         Totals m_totals;
         IStreamingReporterPtr m_reporter;
         std::vector<MessageInfo> m_messages;
+        std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */
         AssertionInfo m_lastAssertionInfo;
         std::vector<SectionEndInfo> m_unfinishedSections;
         std::vector<ITracker*> m_activeSections;
@@ -4838,9 +6253,11 @@
 // end catch_run_context.h
 namespace Catch {
 
-    auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& {
-        expr.streamReconstructedExpression( os );
-        return os;
+    namespace {
+        auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& {
+            expr.streamReconstructedExpression( os );
+            return os;
+        }
     }
 
     LazyExpression::LazyExpression( bool isNegated )
@@ -4870,7 +6287,7 @@
     }
 
     AssertionHandler::AssertionHandler
-        (   StringRef macroName,
+        (   StringRef const& macroName,
             SourceLineInfo const& lineInfo,
             StringRef capturedExpression,
             ResultDisposition::Flags resultDisposition )
@@ -4899,8 +6316,13 @@
             // (To go back to the test and change execution, jump over the throw, next)
             CATCH_BREAK_INTO_DEBUGGER();
         }
-        if( m_reaction.shouldThrow )
+        if (m_reaction.shouldThrow) {
+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
             throw Catch::TestFailureException();
+#else
+            CATCH_ERROR( "Test failure requires aborting test!" );
+#endif
+        }
     }
     void AssertionHandler::setCompleted() {
         m_completed = true;
@@ -4927,7 +6349,7 @@
 
     // This is the overload that takes a string and infers the Equals matcher from it
     // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp
-    void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString  ) {
+    void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString  ) {
         handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString );
     }
 
@@ -4992,9 +6414,9 @@
             expr = m_info.capturedExpression;
         else {
             expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
-            expr += m_info.macroName.c_str();
+            expr += m_info.macroName;
             expr += "( ";
-            expr += m_info.capturedExpression.c_str();
+            expr += m_info.capturedExpression;
             expr += " )";
         }
         return expr;
@@ -5057,9 +6479,9 @@
     using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
 
     // This is the general overload that takes a any string matcher
-    // There is another overload, in catch_assertinhandler.h/.cpp, that only takes a string and infers
+    // There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers
     // the Equals matcher (so the header does not mention matchers)
-    void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString  ) {
+    void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString  ) {
         std::string exceptionMessage = Catch::translateActiveException();
         MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString );
         handler.handleExpr( expr );
@@ -5095,7 +6517,7 @@
 //
 // See https://github.com/philsquared/Clara for more details
 
-// Clara v1.1.1
+// Clara v1.1.5
 
 
 #ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH
@@ -5106,14 +6528,23 @@
 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH
 #endif
 
+#ifndef CLARA_CONFIG_OPTIONAL_TYPE
+#ifdef __has_include
+#if __has_include(<optional>) && __cplusplus >= 201703L
+#include <optional>
+#define CLARA_CONFIG_OPTIONAL_TYPE std::optional
+#endif
+#endif
+#endif
+
 // ----------- #included from clara_textflow.hpp -----------
 
 // TextFlowCpp
 //
 // A single-header library for wrapping and laying out basic text, by Phil Nash
 //
-// This work is licensed under the BSD 2-Clause license.
-// See the accompanying LICENSE file, or the one at https://opensource.org/licenses/BSD-2-Clause
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 //
 // This project is hosted at https://github.com/philsquared/textflowcpp
 
@@ -5127,314 +6558,325 @@
 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80
 #endif
 
-namespace Catch { namespace clara { namespace TextFlow {
+namespace Catch {
+namespace clara {
+namespace TextFlow {
 
-    inline auto isWhitespace( char c ) -> bool {
-        static std::string chars = " \t\n\r";
-        return chars.find( c ) != std::string::npos;
-    }
-    inline auto isBreakableBefore( char c ) -> bool {
-        static std::string chars = "[({<|";
-        return chars.find( c ) != std::string::npos;
-    }
-    inline auto isBreakableAfter( char c ) -> bool {
-        static std::string chars = "])}>.,:;*+-=&/\\";
-        return chars.find( c ) != std::string::npos;
-    }
+inline auto isWhitespace(char c) -> bool {
+	static std::string chars = " \t\n\r";
+	return chars.find(c) != std::string::npos;
+}
+inline auto isBreakableBefore(char c) -> bool {
+	static std::string chars = "[({<|";
+	return chars.find(c) != std::string::npos;
+}
+inline auto isBreakableAfter(char c) -> bool {
+	static std::string chars = "])}>.,:;*+-=&/\\";
+	return chars.find(c) != std::string::npos;
+}
 
-    class Columns;
+class Columns;
 
-    class Column {
-        std::vector<std::string> m_strings;
-        size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH;
-        size_t m_indent = 0;
-        size_t m_initialIndent = std::string::npos;
+class Column {
+	std::vector<std::string> m_strings;
+	size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH;
+	size_t m_indent = 0;
+	size_t m_initialIndent = std::string::npos;
 
-    public:
-        class iterator {
-            friend Column;
+public:
+	class iterator {
+		friend Column;
 
-            Column const& m_column;
-            size_t m_stringIndex = 0;
-            size_t m_pos = 0;
+		Column const& m_column;
+		size_t m_stringIndex = 0;
+		size_t m_pos = 0;
 
-            size_t m_len = 0;
-            size_t m_end = 0;
-            bool m_suffix = false;
+		size_t m_len = 0;
+		size_t m_end = 0;
+		bool m_suffix = false;
 
-            iterator( Column const& column, size_t stringIndex )
-            :   m_column( column ),
-                m_stringIndex( stringIndex )
-            {}
+		iterator(Column const& column, size_t stringIndex)
+			: m_column(column),
+			m_stringIndex(stringIndex) {}
 
-            auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; }
+		auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; }
 
-            auto isBoundary( size_t at ) const -> bool {
-                assert( at > 0 );
-                assert( at <= line().size() );
+		auto isBoundary(size_t at) const -> bool {
+			assert(at > 0);
+			assert(at <= line().size());
 
-                return at == line().size() ||
-                       ( isWhitespace( line()[at] ) && !isWhitespace( line()[at-1] ) ) ||
-                       isBreakableBefore( line()[at] ) ||
-                       isBreakableAfter( line()[at-1] );
-            }
+			return at == line().size() ||
+				(isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) ||
+				isBreakableBefore(line()[at]) ||
+				isBreakableAfter(line()[at - 1]);
+		}
 
-            void calcLength() {
-                assert( m_stringIndex < m_column.m_strings.size() );
+		void calcLength() {
+			assert(m_stringIndex < m_column.m_strings.size());
 
-                m_suffix = false;
-                auto width = m_column.m_width-indent();
-                m_end = m_pos;
-                while( m_end < line().size() && line()[m_end] != '\n' )
-                    ++m_end;
+			m_suffix = false;
+			auto width = m_column.m_width - indent();
+			m_end = m_pos;
+			while (m_end < line().size() && line()[m_end] != '\n')
+				++m_end;
 
-                if( m_end < m_pos + width ) {
-                    m_len = m_end - m_pos;
-                }
-                else {
-                    size_t len = width;
-                    while (len > 0 && !isBoundary(m_pos + len))
-                        --len;
-                    while (len > 0 && isWhitespace( line()[m_pos + len - 1] ))
-                        --len;
+			if (m_end < m_pos + width) {
+				m_len = m_end - m_pos;
+			} else {
+				size_t len = width;
+				while (len > 0 && !isBoundary(m_pos + len))
+					--len;
+				while (len > 0 && isWhitespace(line()[m_pos + len - 1]))
+					--len;
 
-                    if (len > 0) {
-                        m_len = len;
-                    } else {
-                        m_suffix = true;
-                        m_len = width - 1;
-                    }
-                }
-            }
+				if (len > 0) {
+					m_len = len;
+				} else {
+					m_suffix = true;
+					m_len = width - 1;
+				}
+			}
+		}
 
-            auto indent() const -> size_t {
-                auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;
-                return initial == std::string::npos ? m_column.m_indent : initial;
-            }
+		auto indent() const -> size_t {
+			auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;
+			return initial == std::string::npos ? m_column.m_indent : initial;
+		}
 
-            auto addIndentAndSuffix(std::string const &plain) const -> std::string {
-                return std::string( indent(), ' ' ) + (m_suffix ? plain + "-" : plain);
-            }
+		auto addIndentAndSuffix(std::string const &plain) const -> std::string {
+			return std::string(indent(), ' ') + (m_suffix ? plain + "-" : plain);
+		}
 
-        public:
-            explicit iterator( Column const& column ) : m_column( column ) {
-                assert( m_column.m_width > m_column.m_indent );
-                assert( m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent );
-                calcLength();
-                if( m_len == 0 )
-                    m_stringIndex++; // Empty string
-            }
+	public:
+		using difference_type = std::ptrdiff_t;
+		using value_type = std::string;
+		using pointer = value_type * ;
+		using reference = value_type & ;
+		using iterator_category = std::forward_iterator_tag;
 
-            auto operator *() const -> std::string {
-                assert( m_stringIndex < m_column.m_strings.size() );
-                assert( m_pos <= m_end );
-                if( m_pos + m_column.m_width < m_end )
-                    return addIndentAndSuffix(line().substr(m_pos, m_len));
-                else
-                    return addIndentAndSuffix(line().substr(m_pos, m_end - m_pos));
-            }
+		explicit iterator(Column const& column) : m_column(column) {
+			assert(m_column.m_width > m_column.m_indent);
+			assert(m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent);
+			calcLength();
+			if (m_len == 0)
+				m_stringIndex++; // Empty string
+		}
 
-            auto operator ++() -> iterator& {
-                m_pos += m_len;
-                if( m_pos < line().size() && line()[m_pos] == '\n' )
-                    m_pos += 1;
-                else
-                    while( m_pos < line().size() && isWhitespace( line()[m_pos] ) )
-                        ++m_pos;
+		auto operator *() const -> std::string {
+			assert(m_stringIndex < m_column.m_strings.size());
+			assert(m_pos <= m_end);
+			return addIndentAndSuffix(line().substr(m_pos, m_len));
+		}
 
-                if( m_pos == line().size() ) {
-                    m_pos = 0;
-                    ++m_stringIndex;
-                }
-                if( m_stringIndex < m_column.m_strings.size() )
-                    calcLength();
-                return *this;
-            }
-            auto operator ++(int) -> iterator {
-                iterator prev( *this );
-                operator++();
-                return prev;
-            }
+		auto operator ++() -> iterator& {
+			m_pos += m_len;
+			if (m_pos < line().size() && line()[m_pos] == '\n')
+				m_pos += 1;
+			else
+				while (m_pos < line().size() && isWhitespace(line()[m_pos]))
+					++m_pos;
 
-            auto operator ==( iterator const& other ) const -> bool {
-                return
-                    m_pos == other.m_pos &&
-                    m_stringIndex == other.m_stringIndex &&
-                    &m_column == &other.m_column;
-            }
-            auto operator !=( iterator const& other ) const -> bool {
-                return !operator==( other );
-            }
-        };
-        using const_iterator = iterator;
+			if (m_pos == line().size()) {
+				m_pos = 0;
+				++m_stringIndex;
+			}
+			if (m_stringIndex < m_column.m_strings.size())
+				calcLength();
+			return *this;
+		}
+		auto operator ++(int) -> iterator {
+			iterator prev(*this);
+			operator++();
+			return prev;
+		}
 
-        explicit Column( std::string const& text ) { m_strings.push_back( text ); }
+		auto operator ==(iterator const& other) const -> bool {
+			return
+				m_pos == other.m_pos &&
+				m_stringIndex == other.m_stringIndex &&
+				&m_column == &other.m_column;
+		}
+		auto operator !=(iterator const& other) const -> bool {
+			return !operator==(other);
+		}
+	};
+	using const_iterator = iterator;
 
-        auto width( size_t newWidth ) -> Column& {
-            assert( newWidth > 0 );
-            m_width = newWidth;
-            return *this;
-        }
-        auto indent( size_t newIndent ) -> Column& {
-            m_indent = newIndent;
-            return *this;
-        }
-        auto initialIndent( size_t newIndent ) -> Column& {
-            m_initialIndent = newIndent;
-            return *this;
-        }
+	explicit Column(std::string const& text) { m_strings.push_back(text); }
 
-        auto width() const -> size_t { return m_width; }
-        auto begin() const -> iterator { return iterator( *this ); }
-        auto end() const -> iterator { return { *this, m_strings.size() }; }
+	auto width(size_t newWidth) -> Column& {
+		assert(newWidth > 0);
+		m_width = newWidth;
+		return *this;
+	}
+	auto indent(size_t newIndent) -> Column& {
+		m_indent = newIndent;
+		return *this;
+	}
+	auto initialIndent(size_t newIndent) -> Column& {
+		m_initialIndent = newIndent;
+		return *this;
+	}
 
-        inline friend std::ostream& operator << ( std::ostream& os, Column const& col ) {
-            bool first = true;
-            for( auto line : col ) {
-                if( first )
-                    first = false;
-                else
-                    os << "\n";
-                os <<  line;
-            }
-            return os;
-        }
+	auto width() const -> size_t { return m_width; }
+	auto begin() const -> iterator { return iterator(*this); }
+	auto end() const -> iterator { return { *this, m_strings.size() }; }
 
-        auto operator + ( Column const& other ) -> Columns;
+	inline friend std::ostream& operator << (std::ostream& os, Column const& col) {
+		bool first = true;
+		for (auto line : col) {
+			if (first)
+				first = false;
+			else
+				os << "\n";
+			os << line;
+		}
+		return os;
+	}
 
-        auto toString() const -> std::string {
-            std::ostringstream oss;
-            oss << *this;
-            return oss.str();
-        }
-    };
+	auto operator + (Column const& other)->Columns;
 
-    class Spacer : public Column {
+	auto toString() const -> std::string {
+		std::ostringstream oss;
+		oss << *this;
+		return oss.str();
+	}
+};
 
-    public:
-        explicit Spacer( size_t spaceWidth ) : Column( "" ) {
-            width( spaceWidth );
-        }
-    };
+class Spacer : public Column {
 
-    class Columns {
-        std::vector<Column> m_columns;
+public:
+	explicit Spacer(size_t spaceWidth) : Column("") {
+		width(spaceWidth);
+	}
+};
 
-    public:
+class Columns {
+	std::vector<Column> m_columns;
 
-        class iterator {
-            friend Columns;
-            struct EndTag {};
+public:
 
-            std::vector<Column> const& m_columns;
-            std::vector<Column::iterator> m_iterators;
-            size_t m_activeIterators;
+	class iterator {
+		friend Columns;
+		struct EndTag {};
 
-            iterator( Columns const& columns, EndTag )
-            :   m_columns( columns.m_columns ),
-                m_activeIterators( 0 )
-            {
-                m_iterators.reserve( m_columns.size() );
+		std::vector<Column> const& m_columns;
+		std::vector<Column::iterator> m_iterators;
+		size_t m_activeIterators;
 
-                for( auto const& col : m_columns )
-                    m_iterators.push_back( col.end() );
-            }
+		iterator(Columns const& columns, EndTag)
+			: m_columns(columns.m_columns),
+			m_activeIterators(0) {
+			m_iterators.reserve(m_columns.size());
 
-        public:
-            explicit iterator( Columns const& columns )
-            :   m_columns( columns.m_columns ),
-                m_activeIterators( m_columns.size() )
-            {
-                m_iterators.reserve( m_columns.size() );
+			for (auto const& col : m_columns)
+				m_iterators.push_back(col.end());
+		}
 
-                for( auto const& col : m_columns )
-                    m_iterators.push_back( col.begin() );
-            }
+	public:
+		using difference_type = std::ptrdiff_t;
+		using value_type = std::string;
+		using pointer = value_type * ;
+		using reference = value_type & ;
+		using iterator_category = std::forward_iterator_tag;
 
-            auto operator ==( iterator const& other ) const -> bool {
-                return m_iterators == other.m_iterators;
-            }
-            auto operator !=( iterator const& other ) const -> bool {
-                return m_iterators != other.m_iterators;
-            }
-            auto operator *() const -> std::string {
-                std::string row, padding;
+		explicit iterator(Columns const& columns)
+			: m_columns(columns.m_columns),
+			m_activeIterators(m_columns.size()) {
+			m_iterators.reserve(m_columns.size());
 
-                for( size_t i = 0; i < m_columns.size(); ++i ) {
-                    auto width = m_columns[i].width();
-                    if( m_iterators[i] != m_columns[i].end() ) {
-                        std::string col = *m_iterators[i];
-                        row += padding + col;
-                        if( col.size() < width )
-                            padding = std::string( width - col.size(), ' ' );
-                        else
-                            padding = "";
-                    }
-                    else {
-                        padding += std::string( width, ' ' );
-                    }
-                }
-                return row;
-            }
-            auto operator ++() -> iterator& {
-                for( size_t i = 0; i < m_columns.size(); ++i ) {
-                    if (m_iterators[i] != m_columns[i].end())
-                        ++m_iterators[i];
-                }
-                return *this;
-            }
-            auto operator ++(int) -> iterator {
-                iterator prev( *this );
-                operator++();
-                return prev;
-            }
-        };
-        using const_iterator = iterator;
+			for (auto const& col : m_columns)
+				m_iterators.push_back(col.begin());
+		}
 
-        auto begin() const -> iterator { return iterator( *this ); }
-        auto end() const -> iterator { return { *this, iterator::EndTag() }; }
+		auto operator ==(iterator const& other) const -> bool {
+			return m_iterators == other.m_iterators;
+		}
+		auto operator !=(iterator const& other) const -> bool {
+			return m_iterators != other.m_iterators;
+		}
+		auto operator *() const -> std::string {
+			std::string row, padding;
 
-        auto operator += ( Column const& col ) -> Columns& {
-            m_columns.push_back( col );
-            return *this;
-        }
-        auto operator + ( Column const& col ) -> Columns {
-            Columns combined = *this;
-            combined += col;
-            return combined;
-        }
+			for (size_t i = 0; i < m_columns.size(); ++i) {
+				auto width = m_columns[i].width();
+				if (m_iterators[i] != m_columns[i].end()) {
+					std::string col = *m_iterators[i];
+					row += padding + col;
+					if (col.size() < width)
+						padding = std::string(width - col.size(), ' ');
+					else
+						padding = "";
+				} else {
+					padding += std::string(width, ' ');
+				}
+			}
+			return row;
+		}
+		auto operator ++() -> iterator& {
+			for (size_t i = 0; i < m_columns.size(); ++i) {
+				if (m_iterators[i] != m_columns[i].end())
+					++m_iterators[i];
+			}
+			return *this;
+		}
+		auto operator ++(int) -> iterator {
+			iterator prev(*this);
+			operator++();
+			return prev;
+		}
+	};
+	using const_iterator = iterator;
 
-        inline friend std::ostream& operator << ( std::ostream& os, Columns const& cols ) {
+	auto begin() const -> iterator { return iterator(*this); }
+	auto end() const -> iterator { return { *this, iterator::EndTag() }; }
 
-            bool first = true;
-            for( auto line : cols ) {
-                if( first )
-                    first = false;
-                else
-                    os << "\n";
-                os << line;
-            }
-            return os;
-        }
+	auto operator += (Column const& col) -> Columns& {
+		m_columns.push_back(col);
+		return *this;
+	}
+	auto operator + (Column const& col) -> Columns {
+		Columns combined = *this;
+		combined += col;
+		return combined;
+	}
 
-        auto toString() const -> std::string {
-            std::ostringstream oss;
-            oss << *this;
-            return oss.str();
-        }
-    };
+	inline friend std::ostream& operator << (std::ostream& os, Columns const& cols) {
 
-    inline auto Column::operator + ( Column const& other ) -> Columns {
-        Columns cols;
-        cols += *this;
-        cols += other;
-        return cols;
-    }
-}}} // namespace Catch::clara::TextFlow
+		bool first = true;
+		for (auto line : cols) {
+			if (first)
+				first = false;
+			else
+				os << "\n";
+			os << line;
+		}
+		return os;
+	}
+
+	auto toString() const -> std::string {
+		std::ostringstream oss;
+		oss << *this;
+		return oss.str();
+	}
+};
+
+inline auto Column::operator + (Column const& other) -> Columns {
+	Columns cols;
+	cols += *this;
+	cols += other;
+	return cols;
+}
+}
+
+}
+}
 
 // ----------- end of #include from clara_textflow.hpp -----------
 // ........... back in clara.hpp
 
+#include <cctype>
+#include <string>
 #include <memory>
 #include <set>
 #include <algorithm>
@@ -5471,11 +6913,9 @@
         std::vector<std::string> m_args;
 
     public:
-        Args( int argc, char *argv[] ) {
-            m_exeName = argv[0];
-            for( int i = 1; i < argc; ++i )
-                m_args.push_back( argv[i] );
-        }
+        Args( int argc, char const* const* argv )
+            : m_exeName(argv[0]),
+              m_args(argv + 1, argv + argc) {}
 
         Args( std::initializer_list<std::string> args )
         :   m_exeName( *args.begin() ),
@@ -5661,15 +7101,13 @@
 
     protected:
         void enforceOk() const override {
-            // !TBD: If no exceptions, std::terminate here or something
-            switch( m_type ) {
-                case ResultBase::LogicError:
-                    throw std::logic_error( m_errorMessage );
-                case ResultBase::RuntimeError:
-                    throw std::runtime_error( m_errorMessage );
-                case ResultBase::Ok:
-                    break;
-            }
+
+            // Errors shouldn't reach this point, but if they do
+            // the actual error message will be in m_errorMessage
+            assert( m_type != ResultBase::LogicError );
+            assert( m_type != ResultBase::RuntimeError );
+            if( m_type != ResultBase::Ok )
+                std::abort();
         }
 
         std::string m_errorMessage; // Only populated if resultType is an error
@@ -5730,7 +7168,7 @@
     }
     inline auto convertInto( std::string const &source, bool &target ) -> ParserResult {
         std::string srcLC = source;
-        std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( ::tolower(c) ); } );
+        std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( std::tolower(c) ); } );
         if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on")
             target = true;
         else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off")
@@ -5739,6 +7177,16 @@
             return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" );
         return ParserResult::ok( ParseResultType::Matched );
     }
+#ifdef CLARA_CONFIG_OPTIONAL_TYPE
+    template<typename T>
+    inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult {
+        T temp;
+        auto result = convertInto( source, temp );
+        if( result )
+            target = std::move(temp);
+        return result;
+    }
+#endif // CLARA_CONFIG_OPTIONAL_TYPE
 
     struct NonCopyable {
         NonCopyable() = default;
@@ -5751,12 +7199,14 @@
     struct BoundRef : NonCopyable {
         virtual ~BoundRef() = default;
         virtual auto isContainer() const -> bool { return false; }
+        virtual auto isFlag() const -> bool { return false; }
     };
     struct BoundValueRefBase : BoundRef {
         virtual auto setValue( std::string const &arg ) -> ParserResult = 0;
     };
     struct BoundFlagRefBase : BoundRef {
         virtual auto setFlag( bool flag ) -> ParserResult = 0;
+        virtual auto isFlag() const -> bool { return true; }
     };
 
     template<typename T>
@@ -5987,7 +7437,7 @@
             if( token.type != TokenType::Argument )
                 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
 
-            assert( dynamic_cast<detail::BoundValueRefBase*>( m_ref.get() ) );
+            assert( !m_ref->isFlag() );
             auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
 
             auto result = valueRef->setValue( remainingTokens->token );
@@ -6063,14 +7513,14 @@
             if( remainingTokens && remainingTokens->type == TokenType::Option ) {
                 auto const &token = *remainingTokens;
                 if( isMatch(token.token ) ) {
-                    if( auto flagRef = dynamic_cast<detail::BoundFlagRefBase*>( m_ref.get() ) ) {
+                    if( m_ref->isFlag() ) {
+                        auto flagRef = static_cast<detail::BoundFlagRefBase*>( m_ref.get() );
                         auto result = flagRef->setFlag( true );
                         if( !result )
                             return InternalParseResult( result );
                         if( result.value() == ParseResultType::ShortCircuitAll )
                             return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
                     } else {
-                        assert( dynamic_cast<detail::BoundValueRefBase*>( m_ref.get() ) );
                         auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
                         ++remainingTokens;
                         if( !remainingTokens )
@@ -6340,9 +7790,19 @@
         using namespace clara;
 
         auto const setWarning = [&]( std::string const& warning ) {
-                if( warning != "NoAssertions" )
+                auto warningSet = [&]() {
+                    if( warning == "NoAssertions" )
+                        return WarnAbout::NoAssertions;
+
+                    if ( warning == "NoTests" )
+                        return WarnAbout::NoTests;
+
+                    return WarnAbout::Nothing;
+                }();
+
+                if (warningSet == WarnAbout::Nothing)
                     return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" );
-                config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
+                config.warnings = static_cast<WarnAbout::What>( config.warnings | warningSet );
                 return ParserResult::ok( ParseResultType::Matched );
             };
         auto const loadTestNamesFromFile = [&]( std::string const& filename ) {
@@ -6415,6 +7875,18 @@
                 return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" );
             return ParserResult::ok( ParseResultType::Matched );
         };
+        auto const setReporter = [&]( std::string const& reporter ) {
+            IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
+
+            auto lcReporter = toLower( reporter );
+            auto result = factories.find( lcReporter );
+
+            if( factories.end() != result )
+                config.reporterName = lcReporter;
+            else
+                return ParserResult::runtimeError( "Unrecognized reporter, '" + reporter + "'. Check available with --list-reporters" );
+            return ParserResult::ok( ParseResultType::Matched );
+        };
 
         auto cli
             = ExeName( config.processName )
@@ -6440,7 +7912,7 @@
             | Opt( config.outputFilename, "filename" )
                 ["-o"]["--out"]
                 ( "output filename" )
-            | Opt( config.reporterNames, "name" )
+            | Opt( setReporter, "name" )
                 ["-r"]["--reporter"]
                 ( "reporter to use (defaults to console)" )
             | Opt( config.name, "name" )
@@ -6517,7 +7989,9 @@
         return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
     }
     bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept {
-        return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0));
+        // We can assume that the same file will usually have the same pointer.
+        // Thus, if the pointers are the same, there is no point in calling the strcmp
+        return line < other.line || ( line == other.line && file != other.file && (std::strcmp(file, other.file) < 0));
     }
 
     std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
@@ -6540,33 +8014,22 @@
 // end catch_common.cpp
 // start catch_config.cpp
 
-// start catch_enforce.h
-
-#include <stdexcept>
-#include <iosfwd>
-
-#define CATCH_PREPARE_EXCEPTION( type, msg ) \
-    type( static_cast<std::ostringstream&&>( Catch::ReusableStringStream().get() << msg ).str() )
-#define CATCH_INTERNAL_ERROR( msg ) \
-    throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg);
-#define CATCH_ERROR( msg ) \
-    throw CATCH_PREPARE_EXCEPTION( std::domain_error, msg )
-#define CATCH_ENFORCE( condition, msg ) \
-    do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false)
-
-// end catch_enforce.h
 namespace Catch {
 
     Config::Config( ConfigData const& data )
     :   m_data( data ),
         m_stream( openStream() )
     {
-        if( !data.testsOrTags.empty() ) {
-            TestSpecParser parser( ITagAliasRegistry::get() );
+        TestSpecParser parser(ITagAliasRegistry::get());
+        if (data.testsOrTags.empty()) {
+            parser.parse("~[.]"); // All not hidden tests
+        }
+        else {
+            m_hasTestFilters = true;
             for( auto const& testOrTags : data.testsOrTags )
                 parser.parse( testOrTags );
-            m_testSpec = parser.testSpec();
         }
+        m_testSpec = parser.testSpec();
     }
 
     std::string const& Config::getFilename() const {
@@ -6579,11 +8042,13 @@
     bool Config::listReporters() const      { return m_data.listReporters; }
 
     std::string Config::getProcessName() const { return m_data.processName; }
+    std::string const& Config::getReporterName() const { return m_data.reporterName; }
 
-    std::vector<std::string> const& Config::getReporterNames() const { return m_data.reporterNames; }
+    std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; }
     std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }
 
     TestSpec const& Config::testSpec() const { return m_testSpec; }
+    bool Config::hasTestFilters() const { return m_hasTestFilters; }
 
     bool Config::showHelp() const { return m_data.showHelp; }
 
@@ -6592,7 +8057,8 @@
     std::ostream& Config::stream() const               { return m_stream->stream(); }
     std::string Config::name() const                   { return m_data.name.empty() ? m_data.processName : m_data.name; }
     bool Config::includeSuccessfulResults() const      { return m_data.showSuccessfulTests; }
-    bool Config::warnAboutMissingAssertions() const    { return m_data.warnings & WarnAbout::NoAssertions; }
+    bool Config::warnAboutMissingAssertions() const    { return !!(m_data.warnings & WarnAbout::NoAssertions); }
+    bool Config::warnAboutNoTests() const              { return !!(m_data.warnings & WarnAbout::NoTests); }
     ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; }
     RunTests::InWhatOrder Config::runOrder() const     { return m_data.runOrder; }
     unsigned int Config::rngSeed() const               { return m_data.rngSeed; }
@@ -6691,8 +8157,12 @@
                 case Colour::BrightRed:     return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
                 case Colour::BrightGreen:   return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
                 case Colour::BrightWhite:   return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
+                case Colour::BrightYellow:  return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );
 
                 case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
+
+                default:
+                    CATCH_ERROR( "Unknown colour requested" );
             }
         }
 
@@ -6750,8 +8220,10 @@
                 case Colour::BrightRed:     return setColour( "[1;31m" );
                 case Colour::BrightGreen:   return setColour( "[1;32m" );
                 case Colour::BrightWhite:   return setColour( "[1;37m" );
+                case Colour::BrightYellow:  return setColour( "[1;33m" );
 
                 case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
+                default: CATCH_INTERNAL_ERROR( "Unknown colour requested" );
             }
         }
         static IColourImpl* instance() {
@@ -6761,7 +8233,8 @@
 
     private:
         void setColour( const char* _escapeCode ) {
-            Catch::cout() << '\033' << _escapeCode;
+            getCurrentContext().getConfig()->stream()
+                << '\033' << _escapeCode;
         }
     };
 
@@ -6770,7 +8243,12 @@
 #ifdef CATCH_PLATFORM_MAC
             !isDebuggerActive() &&
 #endif
-            isatty(STDOUT_FILENO);
+#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
+            isatty(STDOUT_FILENO)
+#else
+            false
+#endif
+            ;
     }
     IColourImpl* platformColourInstance() {
         ErrnoGuard guard;
@@ -6904,13 +8382,16 @@
             ::OutputDebugStringA( text.c_str() );
         }
     }
+
 #else
+
     namespace Catch {
         void writeToDebugConsole( std::string const& text ) {
             // !TBD: Need a version for Mac/ XCode and other IDEs
             Catch::cout() << text;
         }
     }
+
 #endif // Platform
 // end catch_debug_console.cpp
 // start catch_debugger.cpp
@@ -7031,6 +8512,19 @@
     }
 }
 // end catch_decomposer.cpp
+// start catch_enforce.cpp
+
+namespace Catch {
+#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER)
+    [[noreturn]]
+    void throw_exception(std::exception const& e) {
+        Catch::cerr() << "Catch will terminate because it needed to throw an exception.\n"
+                      << "The message was: " << e.what() << '\n';
+        std::terminate();
+    }
+#endif
+} // namespace Catch;
+// end catch_enforce.cpp
 // start catch_errno_guard.cpp
 
 #include <cerrno>
@@ -7076,6 +8570,7 @@
         m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) );
     }
 
+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
     std::string ExceptionTranslatorRegistry::translateActiveException() const {
         try {
 #ifdef __OBJC__
@@ -7119,11 +8614,23 @@
     }
 
     std::string ExceptionTranslatorRegistry::tryTranslators() const {
-        if( m_translators.empty() )
+        if (m_translators.empty()) {
             std::rethrow_exception(std::current_exception());
-        else
-            return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
+        } else {
+            return m_translators[0]->translate(m_translators.begin() + 1, m_translators.end());
+        }
     }
+
+#else // ^^ Exceptions are enabled // Exceptions are disabled vv
+    std::string ExceptionTranslatorRegistry::translateActiveException() const {
+        CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
+    }
+
+    std::string ExceptionTranslatorRegistry::tryTranslators() const {
+        CATCH_INTERNAL_ERROR("Attempted to use exception translators under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
+    }
+#endif
+
 }
 // end catch_exception_translator_registry.cpp
 // start catch_fatal_condition.cpp
@@ -7133,6 +8640,8 @@
 #    pragma GCC diagnostic ignored "-Wmissing-field-initializers"
 #endif
 
+#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
+
 namespace {
     // Report the error condition
     void reportFatal( char const * const message ) {
@@ -7140,15 +8649,9 @@
     }
 }
 
-#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
+#endif // signals/SEH handling
 
-#  if !defined ( CATCH_CONFIG_WINDOWS_SEH )
-
-namespace Catch {
-    void FatalConditionHandler::reset() {}
-}
-
-#  else // CATCH_CONFIG_WINDOWS_SEH is defined
+#if defined( CATCH_CONFIG_WINDOWS_SEH )
 
 namespace Catch {
     struct SignalDefs { DWORD id; const char* name; };
@@ -7188,7 +8691,6 @@
 
     void FatalConditionHandler::reset() {
         if (isSet) {
-            // Unregister handler and restore the old guarantee
             RemoveVectoredExceptionHandler(exceptionHandlerHandle);
             SetThreadStackGuarantee(&guaranteeSize);
             exceptionHandlerHandle = nullptr;
@@ -7206,19 +8708,7 @@
 
 } // namespace Catch
 
-#  endif // CATCH_CONFIG_WINDOWS_SEH
-
-#else // Not Windows - assumed to be POSIX compatible //////////////////////////
-
-#  if !defined(CATCH_CONFIG_POSIX_SIGNALS)
-
-namespace Catch {
-    void FatalConditionHandler::reset() {}
-}
-
-#  else // CATCH_CONFIG_POSIX_SIGNALS is defined
-
-#include <signal.h>
+#elif defined( CATCH_CONFIG_POSIX_SIGNALS )
 
 namespace Catch {
 
@@ -7226,6 +8716,11 @@
         int id;
         const char* name;
     };
+
+    // 32kb for the alternate stack seems to be sufficient. However, this value
+    // is experimentally determined, so that's not guaranteed.
+    constexpr static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
+
     static SignalDefs signalDefs[] = {
         { SIGINT,  "SIGINT - Terminal interrupt signal" },
         { SIGILL,  "SIGILL - Illegal instruction signal" },
@@ -7252,7 +8747,7 @@
         isSet = true;
         stack_t sigStack;
         sigStack.ss_sp = altStackMem;
-        sigStack.ss_size = SIGSTKSZ;
+        sigStack.ss_size = sigStackSize;
         sigStack.ss_flags = 0;
         sigaltstack(&sigStack, &oldSigStack);
         struct sigaction sa = { };
@@ -7283,18 +8778,62 @@
     bool FatalConditionHandler::isSet = false;
     struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
     stack_t FatalConditionHandler::oldSigStack = {};
-    char FatalConditionHandler::altStackMem[SIGSTKSZ] = {};
+    char FatalConditionHandler::altStackMem[sigStackSize] = {};
 
 } // namespace Catch
 
-#  endif // CATCH_CONFIG_POSIX_SIGNALS
+#else
 
-#endif // not Windows
+namespace Catch {
+    void FatalConditionHandler::reset() {}
+}
+
+#endif // signals/SEH handling
 
 #if defined(__GNUC__)
 #    pragma GCC diagnostic pop
 #endif
 // end catch_fatal_condition.cpp
+// start catch_generators.cpp
+
+// start catch_random_number_generator.h
+
+#include <algorithm>
+#include <random>
+
+namespace Catch {
+
+    struct IConfig;
+
+    std::mt19937& rng();
+    void seedRng( IConfig const& config );
+    unsigned int rngSeed();
+
+}
+
+// end catch_random_number_generator.h
+#include <limits>
+#include <set>
+
+namespace Catch {
+
+IGeneratorTracker::~IGeneratorTracker() {}
+
+const char* GeneratorException::what() const noexcept {
+    return m_msg;
+}
+
+namespace Generators {
+
+    GeneratorUntypedBase::~GeneratorUntypedBase() {}
+
+    auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
+        return getResultCapture().acquireGeneratorTracker( lineInfo );
+    }
+
+} // namespace Generators
+} // namespace Catch
+// end catch_generators.cpp
 // start catch_interfaces_capture.cpp
 
 namespace Catch {
@@ -7323,16 +8862,21 @@
 // end catch_interfaces_registry_hub.cpp
 // start catch_interfaces_reporter.cpp
 
-// start catch_reporter_multi.h
+// start catch_reporter_listening.h
 
 namespace Catch {
 
-    class MultipleReporters : public IStreamingReporter {
+    class ListeningReporter : public IStreamingReporter {
         using Reporters = std::vector<IStreamingReporterPtr>;
-        Reporters m_reporters;
+        Reporters m_listeners;
+        IStreamingReporterPtr m_reporter = nullptr;
+        ReporterPreferences m_preferences;
 
     public:
-        void add( IStreamingReporterPtr&& reporter );
+        ListeningReporter();
+
+        void addListener( IStreamingReporterPtr&& listener );
+        void addReporter( IStreamingReporterPtr&& reporter );
 
     public: // IStreamingReporter
 
@@ -7365,7 +8909,7 @@
 
 } // end namespace Catch
 
-// end catch_reporter_multi.h
+// end catch_reporter_listening.h
 namespace Catch {
 
     ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig )
@@ -7466,27 +9010,6 @@
     IReporterFactory::~IReporterFactory() = default;
     IReporterRegistry::~IReporterRegistry() = default;
 
-    void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ) {
-
-        if( !existingReporter ) {
-            existingReporter = std::move( additionalReporter );
-            return;
-        }
-
-        MultipleReporters* multi = nullptr;
-
-        if( existingReporter->isMulti() ) {
-            multi = static_cast<MultipleReporters*>( existingReporter.get() );
-        }
-        else {
-            auto newMulti = std::unique_ptr<MultipleReporters>( new MultipleReporters );
-            newMulti->add( std::move( existingReporter ) );
-            multi = newMulti.get();
-            existingReporter = std::move( newMulti );
-        }
-        multi->add( std::move( additionalReporter ) );
-    }
-
 } // end namespace Catch
 // end catch_interfaces_reporter.cpp
 // start catch_interfaces_runner.cpp
@@ -7509,16 +9032,16 @@
 
 namespace Catch {
 
-	LeakDetector::LeakDetector() {
-		int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
-		flag |= _CRTDBG_LEAK_CHECK_DF;
-		flag |= _CRTDBG_ALLOC_MEM_DF;
-		_CrtSetDbgFlag(flag);
-		_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
-		_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
-		// Change this to leaking allocation's number to break there
-		_CrtSetBreakAlloc(-1);
-	}
+    LeakDetector::LeakDetector() {
+        int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
+        flag |= _CRTDBG_LEAK_CHECK_DF;
+        flag |= _CRTDBG_ALLOC_MEM_DF;
+        _CrtSetDbgFlag(flag);
+        _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+        _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
+        // Change this to leaking allocation's number to break there
+        _CrtSetBreakAlloc(-1);
+    }
 }
 
 #else
@@ -7526,6 +9049,10 @@
     Catch::LeakDetector::LeakDetector() {}
 
 #endif
+
+Catch::LeakDetector::~LeakDetector() {
+    Catch::cleanUp();
+}
 // end catch_leak_detector.cpp
 // start catch_list.cpp
 
@@ -7549,9 +9076,9 @@
 
     std::size_t listTags( Config const& config );
 
-    std::size_t listReporters( Config const& /*config*/ );
+    std::size_t listReporters();
 
-    Option<std::size_t> list( Config const& config );
+    Option<std::size_t> list( std::shared_ptr<Config> const& config );
 
 } // end namespace Catch
 
@@ -7571,11 +9098,10 @@
 
     std::size_t listTests( Config const& config ) {
         TestSpec testSpec = config.testSpec();
-        if( config.testSpec().hasFilters() )
+        if( config.hasTestFilters() )
             Catch::cout() << "Matching test cases:\n";
         else {
             Catch::cout() << "All available test cases:\n";
-            testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
         }
 
         auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
@@ -7597,7 +9123,7 @@
                 Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n";
         }
 
-        if( !config.testSpec().hasFilters() )
+        if( !config.hasTestFilters() )
             Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl;
         else
             Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl;
@@ -7606,8 +9132,6 @@
 
     std::size_t listTestsNamesOnly( Config const& config ) {
         TestSpec testSpec = config.testSpec();
-        if( !config.testSpec().hasFilters() )
-            testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
         std::size_t matchedTests = 0;
         std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
         for( auto const& testCaseInfo : matchedTestCases ) {
@@ -7637,11 +9161,10 @@
 
     std::size_t listTags( Config const& config ) {
         TestSpec testSpec = config.testSpec();
-        if( config.testSpec().hasFilters() )
+        if( config.hasTestFilters() )
             Catch::cout() << "Tags for matching test cases:\n";
         else {
             Catch::cout() << "All available tags:\n";
-            testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
         }
 
         std::map<std::string, TagInfo> tagCounts;
@@ -7671,7 +9194,7 @@
         return tagCounts.size();
     }
 
-    std::size_t listReporters( Config const& /*config*/ ) {
+    std::size_t listReporters() {
         Catch::cout() << "Available reporters:\n";
         IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
         std::size_t maxNameLen = 0;
@@ -7693,16 +9216,17 @@
         return factories.size();
     }
 
-    Option<std::size_t> list( Config const& config ) {
+    Option<std::size_t> list( std::shared_ptr<Config> const& config ) {
         Option<std::size_t> listedCount;
-        if( config.listTests() )
-            listedCount = listedCount.valueOr(0) + listTests( config );
-        if( config.listTestNamesOnly() )
-            listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
-        if( config.listTags() )
-            listedCount = listedCount.valueOr(0) + listTags( config );
-        if( config.listReporters() )
-            listedCount = listedCount.valueOr(0) + listReporters( config );
+        getCurrentMutableContext().setConfig( config );
+        if( config->listTests() )
+            listedCount = listedCount.valueOr(0) + listTests( *config );
+        if( config->listTestNamesOnly() )
+            listedCount = listedCount.valueOr(0) + listTestsNamesOnly( *config );
+        if( config->listTags() )
+            listedCount = listedCount.valueOr(0) + listTags( *config );
+        if( config->listReporters() )
+            listedCount = listedCount.valueOr(0) + listReporters();
         return listedCount;
     }
 
@@ -7732,10 +9256,35 @@
 // end catch_matchers.cpp
 // start catch_matchers_floating.cpp
 
+// start catch_polyfills.hpp
+
+namespace Catch {
+    bool isnan(float f);
+    bool isnan(double d);
+}
+
+// end catch_polyfills.hpp
+// start catch_to_string.hpp
+
+#include <string>
+
+namespace Catch {
+    template <typename T>
+    std::string to_string(T const& t) {
+#if defined(CATCH_CONFIG_CPP11_TO_STRING)
+        return std::to_string(t);
+#else
+        ReusableStringStream rss;
+        rss << t;
+        return rss.str();
+#endif
+    }
+} // end namespace Catch
+
+// end catch_to_string.hpp
 #include <cstdlib>
 #include <cstdint>
 #include <cstring>
-#include <stdexcept>
 
 namespace Catch {
 namespace Matchers {
@@ -7780,7 +9329,7 @@
 bool almostEqualUlps(FP lhs, FP rhs, int maxUlpDiff) {
     // Comparison with NaN should always be false.
     // This way we can rule it out before getting into the ugly details
-    if (std::isnan(lhs) || std::isnan(rhs)) {
+    if (Catch::isnan(lhs) || Catch::isnan(rhs)) {
         return false;
     }
 
@@ -7803,15 +9352,14 @@
 namespace Floating {
     WithinAbsMatcher::WithinAbsMatcher(double target, double margin)
         :m_target{ target }, m_margin{ margin } {
-        if (m_margin < 0) {
-            throw std::domain_error("Allowed margin difference has to be >= 0");
-        }
+        CATCH_ENFORCE(margin >= 0, "Invalid margin: " << margin << '.'
+            << " Margin has to be non-negative.");
     }
 
     // Performs equivalent check of std::fabs(lhs - rhs) <= margin
     // But without the subtraction to allow for INFINITY in comparison
     bool WithinAbsMatcher::match(double const& matchee) const {
-        return (matchee + m_margin >= m_target) && (m_target + m_margin >= m_margin);
+        return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);
     }
 
     std::string WithinAbsMatcher::describe() const {
@@ -7820,11 +9368,16 @@
 
     WithinUlpsMatcher::WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType)
         :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
-        if (m_ulps < 0) {
-            throw std::domain_error("Allowed ulp difference has to be >= 0");
-        }
+        CATCH_ENFORCE(ulps >= 0, "Invalid ULP setting: " << ulps << '.'
+            << " ULPs have to be non-negative.");
     }
 
+#if defined(__clang__)
+#pragma clang diagnostic push
+// Clang <3.5 reports on the default branch in the switch below
+#pragma clang diagnostic ignored "-Wunreachable-code"
+#endif
+
     bool WithinUlpsMatcher::match(double const& matchee) const {
         switch (m_type) {
         case FloatingPointKind::Float:
@@ -7832,12 +9385,16 @@
         case FloatingPointKind::Double:
             return almostEqualUlps<double>(matchee, m_target, m_ulps);
         default:
-            throw std::domain_error("Unknown FloatingPointKind value");
+            CATCH_INTERNAL_ERROR( "Unknown FloatingPointKind value" );
         }
     }
 
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
     std::string WithinUlpsMatcher::describe() const {
-        return "is within " + std::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : "");
+        return "is within " + Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : "");
     }
 
 }// namespace Floating
@@ -7858,6 +9415,16 @@
 } // namespace Catch
 
 // end catch_matchers_floating.cpp
+// start catch_matchers_generic.cpp
+
+std::string Catch::Matchers::Generic::Detail::finalizeDescription(const std::string& desc) {
+    if (desc.empty()) {
+        return "matches undescribed predicate";
+    } else {
+        return "matches predicate: \"" + desc + '"';
+    }
+}
+// end catch_matchers_generic.cpp
 // start catch_matchers_string.cpp
 
 #include <regex>
@@ -7962,9 +9529,19 @@
 // end catch_matchers_string.cpp
 // start catch_message.cpp
 
+// start catch_uncaught_exceptions.h
+
+namespace Catch {
+    bool uncaught_exceptions();
+} // end namespace Catch
+
+// end catch_uncaught_exceptions.h
+#include <cassert>
+#include <stack>
+
 namespace Catch {
 
-    MessageInfo::MessageInfo(   std::string const& _macroName,
+    MessageInfo::MessageInfo(   StringRef const& _macroName,
                                 SourceLineInfo const& _lineInfo,
                                 ResultWas::OfType _type )
     :   macroName( _macroName ),
@@ -7986,7 +9563,7 @@
 
     ////////////////////////////////////////////////////////////////////////////
 
-    Catch::MessageBuilder::MessageBuilder( std::string const& macroName,
+    Catch::MessageBuilder::MessageBuilder( StringRef const& macroName,
                                            SourceLineInfo const& lineInfo,
                                            ResultWas::OfType type )
         :m_info(macroName, lineInfo, type) {}
@@ -7994,79 +9571,374 @@
     ////////////////////////////////////////////////////////////////////////////
 
     ScopedMessage::ScopedMessage( MessageBuilder const& builder )
-    : m_info( builder.m_info )
+    : m_info( builder.m_info ), m_moved()
     {
         m_info.message = builder.m_stream.str();
         getResultCapture().pushScopedMessage( m_info );
     }
 
-#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17
-#endif
+    ScopedMessage::ScopedMessage( ScopedMessage&& old )
+    : m_info( old.m_info ), m_moved()
+    {
+        old.m_moved = true;
+    }
+
     ScopedMessage::~ScopedMessage() {
-        if ( !std::uncaught_exception() ){
+        if ( !uncaught_exceptions() && !m_moved ){
             getResultCapture().popScopedMessage(m_info);
         }
     }
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#endif
+
+    Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) {
+        auto trimmed = [&] (size_t start, size_t end) {
+            while (names[start] == ',' || isspace(names[start])) {
+                ++start;
+            }
+            while (names[end] == ',' || isspace(names[end])) {
+                --end;
+            }
+            return names.substr(start, end - start + 1);
+        };
+
+        size_t start = 0;
+        std::stack<char> openings;
+        for (size_t pos = 0; pos < names.size(); ++pos) {
+            char c = names[pos];
+            switch (c) {
+            case '[':
+            case '{':
+            case '(':
+            // It is basically impossible to disambiguate between
+            // comparison and start of template args in this context
+//            case '<':
+                openings.push(c);
+                break;
+            case ']':
+            case '}':
+            case ')':
+//           case '>':
+                openings.pop();
+                break;
+            case ',':
+                if (start != pos && openings.size() == 0) {
+                    m_messages.emplace_back(macroName, lineInfo, resultType);
+                    m_messages.back().message = trimmed(start, pos);
+                    m_messages.back().message += " := ";
+                    start = pos;
+                }
+            }
+        }
+        assert(openings.size() == 0 && "Mismatched openings");
+        m_messages.emplace_back(macroName, lineInfo, resultType);
+        m_messages.back().message = trimmed(start, names.size() - 1);
+        m_messages.back().message += " := ";
+    }
+    Capturer::~Capturer() {
+        if ( !uncaught_exceptions() ){
+            assert( m_captured == m_messages.size() );
+            for( size_t i = 0; i < m_captured; ++i  )
+                m_resultCapture.popScopedMessage( m_messages[i] );
+        }
+    }
+
+    void Capturer::captureValue( size_t index, std::string const& value ) {
+        assert( index < m_messages.size() );
+        m_messages[index].message += value;
+        m_resultCapture.pushScopedMessage( m_messages[index] );
+        m_captured++;
+    }
 
 } // end namespace Catch
 // end catch_message.cpp
-// start catch_random_number_generator.cpp
+// start catch_output_redirect.cpp
 
-// start catch_random_number_generator.h
+// start catch_output_redirect.h
+#ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
+#define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
 
-#include <algorithm>
+#include <cstdio>
+#include <iosfwd>
+#include <string>
 
 namespace Catch {
 
-    struct IConfig;
+    class RedirectedStream {
+        std::ostream& m_originalStream;
+        std::ostream& m_redirectionStream;
+        std::streambuf* m_prevBuf;
 
-    void seedRng( IConfig const& config );
-
-    unsigned int rngSeed();
-
-    struct RandomNumberGenerator {
-        using result_type = unsigned int;
-
-        static constexpr result_type (min)() { return 0; }
-        static constexpr result_type (max)() { return 1000000; }
-
-        result_type operator()( result_type n ) const;
-        result_type operator()() const;
-
-        template<typename V>
-        static void shuffle( V& vector ) {
-            RandomNumberGenerator rng;
-            std::shuffle( vector.begin(), vector.end(), rng );
-        }
+    public:
+        RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream );
+        ~RedirectedStream();
     };
 
-}
+    class RedirectedStdOut {
+        ReusableStringStream m_rss;
+        RedirectedStream m_cout;
+    public:
+        RedirectedStdOut();
+        auto str() const -> std::string;
+    };
 
-// end catch_random_number_generator.h
-#include <cstdlib>
+    // StdErr has two constituent streams in C++, std::cerr and std::clog
+    // This means that we need to redirect 2 streams into 1 to keep proper
+    // order of writes
+    class RedirectedStdErr {
+        ReusableStringStream m_rss;
+        RedirectedStream m_cerr;
+        RedirectedStream m_clog;
+    public:
+        RedirectedStdErr();
+        auto str() const -> std::string;
+    };
+
+    class RedirectedStreams {
+    public:
+        RedirectedStreams(RedirectedStreams const&) = delete;
+        RedirectedStreams& operator=(RedirectedStreams const&) = delete;
+        RedirectedStreams(RedirectedStreams&&) = delete;
+        RedirectedStreams& operator=(RedirectedStreams&&) = delete;
+
+        RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr);
+        ~RedirectedStreams();
+    private:
+        std::string& m_redirectedCout;
+        std::string& m_redirectedCerr;
+        RedirectedStdOut m_redirectedStdOut;
+        RedirectedStdErr m_redirectedStdErr;
+    };
+
+#if defined(CATCH_CONFIG_NEW_CAPTURE)
+
+    // Windows's implementation of std::tmpfile is terrible (it tries
+    // to create a file inside system folder, thus requiring elevated
+    // privileges for the binary), so we have to use tmpnam(_s) and
+    // create the file ourselves there.
+    class TempFile {
+    public:
+        TempFile(TempFile const&) = delete;
+        TempFile& operator=(TempFile const&) = delete;
+        TempFile(TempFile&&) = delete;
+        TempFile& operator=(TempFile&&) = delete;
+
+        TempFile();
+        ~TempFile();
+
+        std::FILE* getFile();
+        std::string getContents();
+
+    private:
+        std::FILE* m_file = nullptr;
+    #if defined(_MSC_VER)
+        char m_buffer[L_tmpnam] = { 0 };
+    #endif
+    };
+
+    class OutputRedirect {
+    public:
+        OutputRedirect(OutputRedirect const&) = delete;
+        OutputRedirect& operator=(OutputRedirect const&) = delete;
+        OutputRedirect(OutputRedirect&&) = delete;
+        OutputRedirect& operator=(OutputRedirect&&) = delete;
+
+        OutputRedirect(std::string& stdout_dest, std::string& stderr_dest);
+        ~OutputRedirect();
+
+    private:
+        int m_originalStdout = -1;
+        int m_originalStderr = -1;
+        TempFile m_stdoutFile;
+        TempFile m_stderrFile;
+        std::string& m_stdoutDest;
+        std::string& m_stderrDest;
+    };
+
+#endif
+
+} // end namespace Catch
+
+#endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
+// end catch_output_redirect.h
+#include <cstdio>
+#include <cstring>
+#include <fstream>
+#include <sstream>
+#include <stdexcept>
+
+#if defined(CATCH_CONFIG_NEW_CAPTURE)
+    #if defined(_MSC_VER)
+    #include <io.h>      //_dup and _dup2
+    #define dup _dup
+    #define dup2 _dup2
+    #define fileno _fileno
+    #else
+    #include <unistd.h>  // dup and dup2
+    #endif
+#endif
 
 namespace Catch {
 
-    void seedRng( IConfig const& config ) {
-        if( config.rngSeed() != 0 )
-            std::srand( config.rngSeed() );
+    RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
+    :   m_originalStream( originalStream ),
+        m_redirectionStream( redirectionStream ),
+        m_prevBuf( m_originalStream.rdbuf() )
+    {
+        m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
     }
+
+    RedirectedStream::~RedirectedStream() {
+        m_originalStream.rdbuf( m_prevBuf );
+    }
+
+    RedirectedStdOut::RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {}
+    auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); }
+
+    RedirectedStdErr::RedirectedStdErr()
+    :   m_cerr( Catch::cerr(), m_rss.get() ),
+        m_clog( Catch::clog(), m_rss.get() )
+    {}
+    auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); }
+
+    RedirectedStreams::RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr)
+    :   m_redirectedCout(redirectedCout),
+        m_redirectedCerr(redirectedCerr)
+    {}
+
+    RedirectedStreams::~RedirectedStreams() {
+        m_redirectedCout += m_redirectedStdOut.str();
+        m_redirectedCerr += m_redirectedStdErr.str();
+    }
+
+#if defined(CATCH_CONFIG_NEW_CAPTURE)
+
+#if defined(_MSC_VER)
+    TempFile::TempFile() {
+        if (tmpnam_s(m_buffer)) {
+            CATCH_RUNTIME_ERROR("Could not get a temp filename");
+        }
+        if (fopen_s(&m_file, m_buffer, "w")) {
+            char buffer[100];
+            if (strerror_s(buffer, errno)) {
+                CATCH_RUNTIME_ERROR("Could not translate errno to a string");
+            }
+            CATCH_RUNTIME_ERROR("Coul dnot open the temp file: '" << m_buffer << "' because: " << buffer);
+        }
+    }
+#else
+    TempFile::TempFile() {
+        m_file = std::tmpfile();
+        if (!m_file) {
+            CATCH_RUNTIME_ERROR("Could not create a temp file.");
+        }
+    }
+
+#endif
+
+    TempFile::~TempFile() {
+         // TBD: What to do about errors here?
+         std::fclose(m_file);
+         // We manually create the file on Windows only, on Linux
+         // it will be autodeleted
+#if defined(_MSC_VER)
+         std::remove(m_buffer);
+#endif
+    }
+
+    FILE* TempFile::getFile() {
+        return m_file;
+    }
+
+    std::string TempFile::getContents() {
+        std::stringstream sstr;
+        char buffer[100] = {};
+        std::rewind(m_file);
+        while (std::fgets(buffer, sizeof(buffer), m_file)) {
+            sstr << buffer;
+        }
+        return sstr.str();
+    }
+
+    OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) :
+        m_originalStdout(dup(1)),
+        m_originalStderr(dup(2)),
+        m_stdoutDest(stdout_dest),
+        m_stderrDest(stderr_dest) {
+        dup2(fileno(m_stdoutFile.getFile()), 1);
+        dup2(fileno(m_stderrFile.getFile()), 2);
+    }
+
+    OutputRedirect::~OutputRedirect() {
+        Catch::cout() << std::flush;
+        fflush(stdout);
+        // Since we support overriding these streams, we flush cerr
+        // even though std::cerr is unbuffered
+        Catch::cerr() << std::flush;
+        Catch::clog() << std::flush;
+        fflush(stderr);
+
+        dup2(m_originalStdout, 1);
+        dup2(m_originalStderr, 2);
+
+        m_stdoutDest += m_stdoutFile.getContents();
+        m_stderrDest += m_stderrFile.getContents();
+    }
+
+#endif // CATCH_CONFIG_NEW_CAPTURE
+
+} // namespace Catch
+
+#if defined(CATCH_CONFIG_NEW_CAPTURE)
+    #if defined(_MSC_VER)
+    #undef dup
+    #undef dup2
+    #undef fileno
+    #endif
+#endif
+// end catch_output_redirect.cpp
+// start catch_polyfills.cpp
+
+#include <cmath>
+
+namespace Catch {
+
+#if !defined(CATCH_CONFIG_POLYFILL_ISNAN)
+    bool isnan(float f) {
+        return std::isnan(f);
+    }
+    bool isnan(double d) {
+        return std::isnan(d);
+    }
+#else
+    // For now we only use this for embarcadero
+    bool isnan(float f) {
+        return std::_isnan(f);
+    }
+    bool isnan(double d) {
+        return std::_isnan(d);
+    }
+#endif
+
+} // end namespace Catch
+// end catch_polyfills.cpp
+// start catch_random_number_generator.cpp
+
+namespace Catch {
+
+    std::mt19937& rng() {
+        static std::mt19937 s_rng;
+        return s_rng;
+    }
+
+    void seedRng( IConfig const& config ) {
+        if( config.rngSeed() != 0 ) {
+            std::srand( config.rngSeed() );
+            rng().seed( config.rngSeed() );
+        }
+    }
+
     unsigned int rngSeed() {
         return getCurrentContext().getConfig()->rngSeed();
     }
-
-    RandomNumberGenerator::result_type RandomNumberGenerator::operator()( result_type n ) const {
-        return std::rand() % n;
-    }
-    RandomNumberGenerator::result_type RandomNumberGenerator::operator()() const {
-        return std::rand() % (max)();
-    }
-
 }
 // end catch_random_number_generator.cpp
 // start catch_registry_hub.cpp
@@ -8118,7 +9990,7 @@
         void invoke() const override;
     };
 
-    std::string extractClassName( std::string const& classOrQualifiedMethodName );
+    std::string extractClassName( StringRef const& classOrQualifiedMethodName );
 
     ///////////////////////////////////////////////////////////////////////////
 
@@ -8206,6 +10078,41 @@
 } // end namespace Catch
 
 // end catch_startup_exception_registry.h
+// start catch_singletons.hpp
+
+namespace Catch {
+
+    struct ISingleton {
+        virtual ~ISingleton();
+    };
+
+    void addSingleton( ISingleton* singleton );
+    void cleanupSingletons();
+
+    template<typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT>
+    class Singleton : SingletonImplT, public ISingleton {
+
+        static auto getInternal() -> Singleton* {
+            static Singleton* s_instance = nullptr;
+            if( !s_instance ) {
+                s_instance = new Singleton;
+                addSingleton( s_instance );
+            }
+            return s_instance;
+        }
+
+    public:
+        static auto get() -> InterfaceT const& {
+            return *getInternal();
+        }
+        static auto getMutable() -> MutableInterfaceT& {
+            return *getInternal();
+        }
+    };
+
+} // namespace Catch
+
+// end catch_singletons.hpp
 namespace Catch {
 
     namespace {
@@ -8221,7 +10128,7 @@
             ITestCaseRegistry const& getTestCaseRegistry() const override {
                 return m_testCaseRegistry;
             }
-            IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() override {
+            IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const override {
                 return m_exceptionTranslatorRegistry;
             }
             ITagAliasRegistry const& getTagAliasRegistry() const override {
@@ -8258,27 +10165,19 @@
             TagAliasRegistry m_tagAliasRegistry;
             StartupExceptionRegistry m_exceptionRegistry;
         };
-
-        // Single, global, instance
-        RegistryHub*& getTheRegistryHub() {
-            static RegistryHub* theRegistryHub = nullptr;
-            if( !theRegistryHub )
-                theRegistryHub = new RegistryHub();
-            return theRegistryHub;
-        }
     }
 
-    IRegistryHub& getRegistryHub() {
-        return *getTheRegistryHub();
+    using RegistryHubSingleton = Singleton<RegistryHub, IRegistryHub, IMutableRegistryHub>;
+
+    IRegistryHub const& getRegistryHub() {
+        return RegistryHubSingleton::get();
     }
     IMutableRegistryHub& getMutableRegistryHub() {
-        return *getTheRegistryHub();
+        return RegistryHubSingleton::getMutable();
     }
     void cleanUp() {
-        delete getTheRegistryHub();
-        getTheRegistryHub() = nullptr;
+        cleanupSingletons();
         cleanUpContext();
-        ReusableStringStream::cleanup();
     }
     std::string translateActiveException() {
         return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
@@ -8343,54 +10242,68 @@
 
 namespace Catch {
 
-    class RedirectedStream {
-        std::ostream& m_originalStream;
-        std::ostream& m_redirectionStream;
-        std::streambuf* m_prevBuf;
+    namespace Generators {
+        struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
+            GeneratorBasePtr m_generator;
 
-    public:
-        RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
-        :   m_originalStream( originalStream ),
-            m_redirectionStream( redirectionStream ),
-            m_prevBuf( m_originalStream.rdbuf() )
-        {
-            m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
-        }
-        ~RedirectedStream() {
-            m_originalStream.rdbuf( m_prevBuf );
-        }
-    };
+            GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
+            :   TrackerBase( nameAndLocation, ctx, parent )
+            {}
+            ~GeneratorTracker();
 
-    class RedirectedStdOut {
-        ReusableStringStream m_rss;
-        RedirectedStream m_cout;
-    public:
-        RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {}
-        auto str() const -> std::string { return m_rss.str(); }
-    };
+            static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) {
+                std::shared_ptr<GeneratorTracker> tracker;
 
-    // StdErr has two constituent streams in C++, std::cerr and std::clog
-    // This means that we need to redirect 2 streams into 1 to keep proper
-    // order of writes
-    class RedirectedStdErr {
-        ReusableStringStream m_rss;
-        RedirectedStream m_cerr;
-        RedirectedStream m_clog;
-    public:
-        RedirectedStdErr()
-        :   m_cerr( Catch::cerr(), m_rss.get() ),
-            m_clog( Catch::clog(), m_rss.get() )
-        {}
-        auto str() const -> std::string { return m_rss.str(); }
-    };
+                ITracker& currentTracker = ctx.currentTracker();
+                if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
+                    assert( childTracker );
+                    assert( childTracker->isGeneratorTracker() );
+                    tracker = std::static_pointer_cast<GeneratorTracker>( childTracker );
+                }
+                else {
+                    tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, &currentTracker );
+                    currentTracker.addChild( tracker );
+                }
+
+                if( !ctx.completedCycle() && !tracker->isComplete() ) {
+                    tracker->open();
+                }
+
+                return *tracker;
+            }
+
+            // TrackerBase interface
+            bool isGeneratorTracker() const override { return true; }
+            auto hasGenerator() const -> bool override {
+                return !!m_generator;
+            }
+            void close() override {
+                TrackerBase::close();
+                // Generator interface only finds out if it has another item on atual move
+                if (m_runState == CompletedSuccessfully && m_generator->next()) {
+                    m_children.clear();
+                    m_runState = Executing;
+                }
+            }
+
+            // IGeneratorTracker interface
+            auto getGenerator() const -> GeneratorBasePtr const& override {
+                return m_generator;
+            }
+            void setGenerator( GeneratorBasePtr&& generator ) override {
+                m_generator = std::move( generator );
+            }
+        };
+        GeneratorTracker::~GeneratorTracker() {}
+    }
 
     RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter)
     :   m_runInfo(_config->name()),
         m_context(getCurrentMutableContext()),
         m_config(_config),
         m_reporter(std::move(reporter)),
-        m_lastAssertionInfo{ "", SourceLineInfo("",0), "", ResultDisposition::Normal },
-        m_includeSuccessfulResults( m_config->includeSuccessfulResults() )
+        m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal },
+        m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions )
     {
         m_context.setRunner(this);
         m_context.setConfig(m_config);
@@ -8416,7 +10329,7 @@
         std::string redirectedCout;
         std::string redirectedCerr;
 
-        TestCaseInfo testInfo = testCase.getTestCaseInfo();
+        auto const& testInfo = testCase.getTestCaseInfo();
 
         m_reporter->testCaseStarting(testInfo);
 
@@ -8477,6 +10390,9 @@
         // and should be let to clear themselves out.
         static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
 
+        if (result.getResultType() != ResultWas::Warning)
+            m_messageScopes.clear();
+
         // Reset working state
         resetAssertionInfo();
         m_lastResult = result;
@@ -8500,6 +10416,13 @@
 
         return true;
     }
+    auto RunContext::acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
+        using namespace Generators;
+        GeneratorTracker& tracker = GeneratorTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( "generator", lineInfo ) );
+        assert( tracker.isOpen() );
+        m_lastAssertionInfo.lineInfo = lineInfo;
+        return tracker;
+    }
 
     bool RunContext::testForMissingAssertions(Counts& assertions) {
         if (assertions.total() != 0)
@@ -8524,6 +10447,7 @@
 
         m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
         m_messages.clear();
+        m_messageScopes.clear();
     }
 
     void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) {
@@ -8550,6 +10474,10 @@
         m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
     }
 
+    void RunContext::emplaceUnscopedMessage( MessageBuilder const& builder ) {
+        m_messageScopes.emplace_back( builder );
+    }
+
     std::string RunContext::getCurrentTestName() const {
         return m_activeTestCase
             ? m_activeTestCase->getTestCaseInfo().name
@@ -8580,7 +10508,7 @@
 
         // Recreate section for test case (as we will lose the one that was in scope)
         auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
-        SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
+        SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
 
         Counts assertions;
         assertions.failed = 1;
@@ -8610,41 +10538,45 @@
         m_lastAssertionPassed = true;
         ++m_totals.assertions.passed;
         resetAssertionInfo();
+        m_messageScopes.clear();
     }
 
     bool RunContext::aborting() const {
-        return m_totals.assertions.failed == static_cast<std::size_t>(m_config->abortAfter());
+        return m_totals.assertions.failed >= static_cast<std::size_t>(m_config->abortAfter());
     }
 
     void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) {
         auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
-        SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
+        SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
         m_reporter->sectionStarting(testCaseSection);
         Counts prevAssertions = m_totals.assertions;
         double duration = 0;
         m_shouldReportUnexpected = true;
-        m_lastAssertionInfo = { "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal };
+        m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal };
 
         seedRng(*m_config);
 
         Timer timer;
-        try {
+        CATCH_TRY {
             if (m_reporter->getPreferences().shouldRedirectStdOut) {
-                RedirectedStdOut redirectedStdOut;
-                RedirectedStdErr redirectedStdErr;
+#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
+                RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr);
+
                 timer.start();
                 invokeActiveTestCase();
-                redirectedCout += redirectedStdOut.str();
-                redirectedCerr += redirectedStdErr.str();
-
+#else
+                OutputRedirect r(redirectedCout, redirectedCerr);
+                timer.start();
+                invokeActiveTestCase();
+#endif
             } else {
                 timer.start();
                 invokeActiveTestCase();
             }
             duration = timer.getElapsedSeconds();
-        } catch (TestFailureException&) {
+        } CATCH_CATCH_ANON (TestFailureException&) {
             // This just means the test was aborted due to failure
-        } catch (...) {
+        } CATCH_CATCH_ALL {
             // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
             // are reported without translation at the point of origin.
             if( m_shouldReportUnexpected ) {
@@ -8652,12 +10584,14 @@
                 handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction );
             }
         }
+        Counts assertions = m_totals.assertions - prevAssertions;
+        bool missingAssertions = testForMissingAssertions(assertions);
+
         m_testCaseTracker->close();
         handleUnfinishedSections();
         m_messages.clear();
+        m_messageScopes.clear();
 
-        Counts assertions = m_totals.assertions - prevAssertions;
-        bool missingAssertions = testForMissingAssertions(assertions);
         SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
         m_reporter->sectionEnded(testCaseSectionStats);
     }
@@ -8804,22 +10738,15 @@
         m_timer.start();
     }
 
-#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17
-#endif
     Section::~Section() {
         if( m_sectionIncluded ) {
-            SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
-            if( std::uncaught_exception() )
+            SectionEndInfo endInfo{ m_info, m_assertions, m_timer.getElapsedSeconds() };
+            if( uncaught_exceptions() )
                 getResultCapture().sectionEndedEarly( endInfo );
             else
                 getResultCapture().sectionEnded( endInfo );
         }
     }
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#endif
 
     // This indicates whether the section should be executed or not
     Section::operator bool() const {
@@ -8834,17 +10761,11 @@
 
     SectionInfo::SectionInfo
         (   SourceLineInfo const& _lineInfo,
-            std::string const& _name,
-            std::string const& _description )
+            std::string const& _name )
     :   name( _name ),
-        description( _description ),
         lineInfo( _lineInfo )
     {}
 
-    SectionEndInfo::SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds )
-    : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
-    {}
-
 } // end namespace Catch
 // end catch_section_info.cpp
 // start catch_session.cpp
@@ -8864,14 +10785,23 @@
         void showHelp() const;
         void libIdentify();
 
-        int applyCommandLine( int argc, char* argv[] );
+        int applyCommandLine( int argc, char const * const * argv );
+    #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
+        int applyCommandLine( int argc, wchar_t const * const * argv );
+    #endif
 
         void useConfigData( ConfigData const& configData );
 
-        int run( int argc, char* argv[] );
-    #if defined(WIN32) && defined(UNICODE)
-        int run( int argc, wchar_t* const argv[] );
-    #endif
+        template<typename CharT>
+        int run(int argc, CharT const * const argv[]) {
+            if (m_startupExceptions)
+                return 1;
+            int returnCode = applyCommandLine(argc, argv);
+            if (returnCode == 0)
+                returnCode = run();
+            return returnCode;
+        }
+
         int run();
 
         clara::Parser const& cli() const;
@@ -8936,32 +10866,28 @@
             return reporter;
         }
 
-#ifndef CATCH_CONFIG_DEFAULT_REPORTER
-#define CATCH_CONFIG_DEFAULT_REPORTER "console"
-#endif
-
         IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) {
-            auto const& reporterNames = config->getReporterNames();
-            if (reporterNames.empty())
-                return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config);
+            if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) {
+                return createReporter(config->getReporterName(), config);
+            }
 
-            IStreamingReporterPtr reporter;
-            for (auto const& name : reporterNames)
-                addReporter(reporter, createReporter(name, config));
-            return reporter;
-        }
-
-#undef CATCH_CONFIG_DEFAULT_REPORTER
-
-        void addListeners(IStreamingReporterPtr& reporters, IConfigPtr const& config) {
+            // On older platforms, returning std::unique_ptr<ListeningReporter>
+            // when the return type is std::unique_ptr<IStreamingReporter>
+            // doesn't compile without a std::move call. However, this causes
+            // a warning on newer platforms. Thus, we have to work around
+            // it a bit and downcast the pointer manually.
+            auto ret = std::unique_ptr<IStreamingReporter>(new ListeningReporter);
+            auto& multi = static_cast<ListeningReporter&>(*ret);
             auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
-            for (auto const& listener : listeners)
-                addReporter(reporters, listener->create(Catch::ReporterConfig(config)));
+            for (auto const& listener : listeners) {
+                multi.addListener(listener->create(Catch::ReporterConfig(config)));
+            }
+            multi.addReporter(createReporter(config->getReporterName(), config));
+            return ret;
         }
 
         Catch::Totals runTests(std::shared_ptr<Config> const& config) {
-            IStreamingReporterPtr reporter = makeReporter(config);
-            addListeners(reporter, config);
+            auto reporter = makeReporter(config);
 
             RunContext context(config, std::move(reporter));
 
@@ -8970,8 +10896,6 @@
             context.testGroupStarting(config->name(), 1, 1);
 
             TestSpec testSpec = config->testSpec();
-            if (!testSpec.hasFilters())
-                testSpec = TestSpecParser(ITagAliasRegistry::get()).parse("~[.]").testSpec(); // All not hidden tests
 
             auto const& allTestCases = getAllTestCasesSorted(*config);
             for (auto const& testCase : allTestCases) {
@@ -8981,6 +10905,20 @@
                     context.reporter().skipTest(testCase);
             }
 
+            if (config->warnAboutNoTests() && totals.testCases.total() == 0) {
+                ReusableStringStream testConfig;
+
+                bool first = true;
+                for (const auto& input : config->getTestsOrTags()) {
+                    if (!first) { testConfig << ' '; }
+                    first = false;
+                    testConfig << input;
+                }
+
+                context.reporter().noMatchingTestCases(testConfig.str());
+                totals.error = -1;
+            }
+
             context.testGroupEnded(config->name(), totals, 1, 1);
             return totals;
         }
@@ -9012,15 +10950,17 @@
     Session::Session() {
         static bool alreadyInstantiated = false;
         if( alreadyInstantiated ) {
-            try         { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); }
-            catch(...)  { getMutableRegistryHub().registerStartupException(); }
+            CATCH_TRY { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); }
+            CATCH_CATCH_ALL { getMutableRegistryHub().registerStartupException(); }
         }
 
+        // There cannot be exceptions at startup in no-exception mode.
+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
         const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();
         if ( !exceptions.empty() ) {
             m_startupExceptions = true;
             Colour colourGuard( Colour::Red );
-            Catch::cerr() << "Errors occured during startup!" << '\n';
+            Catch::cerr() << "Errors occurred during startup!" << '\n';
             // iterate over all exceptions and notify user
             for ( const auto& ex_ptr : exceptions ) {
                 try {
@@ -9030,6 +10970,7 @@
                 }
             }
         }
+#endif
 
         alreadyInstantiated = true;
         m_cli = makeCommandLineParser( m_configData );
@@ -9052,12 +10993,14 @@
                 << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
     }
 
-    int Session::applyCommandLine( int argc, char* argv[] ) {
+    int Session::applyCommandLine( int argc, char const * const * argv ) {
         if( m_startupExceptions )
             return 1;
 
         auto result = m_cli.parse( clara::Args( argc, argv ) );
         if( !result ) {
+            config();
+            getCurrentMutableContext().setConfig(m_config);
             Catch::cerr()
                 << Colour( Colour::Red )
                 << "\nError(s) in input:\n"
@@ -9075,22 +11018,8 @@
         return 0;
     }
 
-    void Session::useConfigData( ConfigData const& configData ) {
-        m_configData = configData;
-        m_config.reset();
-    }
-
-    int Session::run( int argc, char* argv[] ) {
-        if( m_startupExceptions )
-            return 1;
-        int returnCode = applyCommandLine( argc, argv );
-        if( returnCode == 0 )
-            returnCode = run();
-        return returnCode;
-    }
-
-#if defined(WIN32) && defined(UNICODE)
-    int Session::run( int argc, wchar_t* const argv[] ) {
+#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
+    int Session::applyCommandLine( int argc, wchar_t const * const * argv ) {
 
         char **utf8Argv = new char *[ argc ];
 
@@ -9102,7 +11031,7 @@
             WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
         }
 
-        int returnCode = run( argc, utf8Argv );
+        int returnCode = applyCommandLine( argc, utf8Argv );
 
         for ( int i = 0; i < argc; ++i )
             delete [] utf8Argv[ i ];
@@ -9112,6 +11041,12 @@
         return returnCode;
     }
 #endif
+
+    void Session::useConfigData( ConfigData const& configData ) {
+        m_configData = configData;
+        m_config.reset();
+    }
+
     int Session::run() {
         if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
             Catch::cout() << "...waiting for enter/ return before starting" << std::endl;
@@ -9144,11 +11079,11 @@
         if( m_startupExceptions )
             return 1;
 
-        if( m_configData.showHelp || m_configData.libIdentify )
+        if (m_configData.showHelp || m_configData.libIdentify) {
             return 0;
+        }
 
-        try
-        {
+        CATCH_TRY {
             config(); // Force config to be constructed
 
             seedRng( *m_config );
@@ -9157,30 +11092,62 @@
                 applyFilenamesAsTags( *m_config );
 
             // Handle list request
-            if( Option<std::size_t> listed = list( config() ) )
+            if( Option<std::size_t> listed = list( m_config ) )
                 return static_cast<int>( *listed );
 
+            auto totals = runTests( m_config );
             // Note that on unices only the lower 8 bits are usually used, clamping
             // the return value to 255 prevents false negative when some multiple
             // of 256 tests has failed
-            return (std::min)( MaxExitCode, static_cast<int>( runTests( m_config ).assertions.failed ) );
+            return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed)));
         }
+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
         catch( std::exception& ex ) {
             Catch::cerr() << ex.what() << std::endl;
             return MaxExitCode;
         }
+#endif
     }
 
 } // end namespace Catch
 // end catch_session.cpp
+// start catch_singletons.cpp
+
+#include <vector>
+
+namespace Catch {
+
+    namespace {
+        static auto getSingletons() -> std::vector<ISingleton*>*& {
+            static std::vector<ISingleton*>* g_singletons = nullptr;
+            if( !g_singletons )
+                g_singletons = new std::vector<ISingleton*>();
+            return g_singletons;
+        }
+    }
+
+    ISingleton::~ISingleton() {}
+
+    void addSingleton(ISingleton* singleton ) {
+        getSingletons()->push_back( singleton );
+    }
+    void cleanupSingletons() {
+        auto& singletons = getSingletons();
+        for( auto singleton : *singletons )
+            delete singleton;
+        delete singletons;
+        singletons = nullptr;
+    }
+
+} // namespace Catch
+// end catch_singletons.cpp
 // start catch_startup_exception_registry.cpp
 
 namespace Catch {
-    void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept {
-        try {
+void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept {
+        CATCH_TRY {
             m_exceptions.push_back(exception);
-        }
-        catch(...) {
+        } CATCH_CATCH_ALL {
             // If we run out of memory during start-up there's really not a lot more we can do about it
             std::terminate();
         }
@@ -9201,11 +11168,6 @@
 #include <vector>
 #include <memory>
 
-#if defined(__clang__)
-#    pragma clang diagnostic push
-#    pragma clang diagnostic ignored "-Wexit-time-destructors"
-#endif
-
 namespace Catch {
 
     Catch::IStream::~IStream() = default;
@@ -9325,7 +11287,6 @@
         std::vector<std::unique_ptr<std::ostringstream>> m_streams;
         std::vector<std::size_t> m_unused;
         std::ostringstream m_referenceStream; // Used for copy state/ flags from
-        static StringStreams* s_instance;
 
         auto add() -> std::size_t {
             if( m_unused.empty() ) {
@@ -9343,34 +11304,17 @@
             m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state
             m_unused.push_back(index);
         }
-
-        // !TBD: put in TLS
-        static auto instance() -> StringStreams& {
-            if( !s_instance )
-                s_instance = new StringStreams();
-            return *s_instance;
-        }
-        static void cleanup() {
-            delete s_instance;
-            s_instance = nullptr;
-        }
     };
 
-    StringStreams* StringStreams::s_instance = nullptr;
-
-    void ReusableStringStream::cleanup() {
-        StringStreams::cleanup();
-    }
-
     ReusableStringStream::ReusableStringStream()
-    :   m_index( StringStreams::instance().add() ),
-        m_oss( StringStreams::instance().m_streams[m_index].get() )
+    :   m_index( Singleton<StringStreams>::getMutable().add() ),
+        m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].get() )
     {}
 
     ReusableStringStream::~ReusableStringStream() {
         static_cast<std::ostringstream*>( m_oss )->str("");
         m_oss->clear();
-        StringStreams::instance().release( m_index );
+        Singleton<StringStreams>::getMutable().release( m_index );
     }
 
     auto ReusableStringStream::str() const -> std::string {
@@ -9385,10 +11329,6 @@
     std::ostream& clog() { return std::clog; }
 #endif
 }
-
-#if defined(__clang__)
-#    pragma clang diagnostic pop
-#endif
 // end catch_stream.cpp
 // start catch_string_manip.cpp
 
@@ -9399,6 +11339,12 @@
 
 namespace Catch {
 
+    namespace {
+        char toLowerCh(char c) {
+            return static_cast<char>( std::tolower( c ) );
+        }
+    }
+
     bool startsWith( std::string const& s, std::string const& prefix ) {
         return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
     }
@@ -9414,9 +11360,6 @@
     bool contains( std::string const& s, std::string const& infix ) {
         return s.find( infix ) != std::string::npos;
     }
-    char toLowerCh(char c) {
-        return static_cast<char>( std::tolower( c ) );
-    }
     void toLowerInPlace( std::string& s ) {
         std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
     }
@@ -9470,6 +11413,13 @@
 
 #include <ostream>
 #include <cstring>
+#include <cstdint>
+
+namespace {
+    const uint32_t byte_2_lead = 0xC0;
+    const uint32_t byte_3_lead = 0xE0;
+    const uint32_t byte_4_lead = 0xF0;
+}
 
 namespace Catch {
     StringRef::StringRef( char const* rawChars ) noexcept
@@ -9491,7 +11441,7 @@
            const_cast<StringRef*>( this )->takeOwnership();
         return m_start;
     }
-    auto StringRef::data() const noexcept -> char const* {
+    auto StringRef::currentData() const noexcept -> char const* {
         return m_start;
     }
 
@@ -9534,13 +11484,12 @@
         // Make adjustments for uft encodings
         for( size_type i=0; i < m_size; ++i ) {
             char c = m_start[i];
-            if( ( c & 0b11000000 ) == 0b11000000 ) {
-                if( ( c & 0b11100000 ) == 0b11000000 )
+            if( ( c & byte_2_lead ) == byte_2_lead ) {
+                noChars--;
+                if (( c & byte_3_lead ) == byte_3_lead )
                     noChars--;
-                else if( ( c & 0b11110000 ) == 0b11100000 )
-                    noChars-=2;
-                else if( ( c & 0b11111000 ) == 0b11110000 )
-                    noChars-=3;
+                if( ( c & byte_4_lead ) == byte_4_lead )
+                    noChars--;
             }
         }
         return noChars;
@@ -9561,7 +11510,12 @@
     }
 
     auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& {
-        return os << str.c_str();
+        return os.write(str.currentData(), str.size());
+    }
+
+    auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& {
+        lhs.append(rhs.currentData(), rhs.size());
+        return lhs;
     }
 
 } // namespace Catch
@@ -9581,9 +11535,9 @@
 namespace Catch {
 
     RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) {
-        try {
+        CATCH_TRY {
             getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo);
-        } catch (...) {
+        } CATCH_CATCH_ALL {
             // Do not throw when constructing global objects, instead register the exception to be processed later
             getMutableRegistryHub().registerStartupException();
         }
@@ -9647,37 +11601,38 @@
 
 namespace Catch {
 
-    TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
-        if( startsWith( tag, '.' ) ||
-            tag == "!hide" )
-            return TestCaseInfo::IsHidden;
-        else if( tag == "!throws" )
-            return TestCaseInfo::Throws;
-        else if( tag == "!shouldfail" )
-            return TestCaseInfo::ShouldFail;
-        else if( tag == "!mayfail" )
-            return TestCaseInfo::MayFail;
-        else if( tag == "!nonportable" )
-            return TestCaseInfo::NonPortable;
-        else if( tag == "!benchmark" )
-            return static_cast<TestCaseInfo::SpecialProperties>( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden );
-        else
-            return TestCaseInfo::None;
-    }
-    bool isReservedTag( std::string const& tag ) {
-        return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] );
-    }
-    void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
-        CATCH_ENFORCE( !isReservedTag(tag),
-                      "Tag name: [" << tag << "] is not allowed.\n"
-                      << "Tag names starting with non alpha-numeric characters are reserved\n"
-                      << _lineInfo );
+    namespace {
+        TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
+            if( startsWith( tag, '.' ) ||
+                tag == "!hide" )
+                return TestCaseInfo::IsHidden;
+            else if( tag == "!throws" )
+                return TestCaseInfo::Throws;
+            else if( tag == "!shouldfail" )
+                return TestCaseInfo::ShouldFail;
+            else if( tag == "!mayfail" )
+                return TestCaseInfo::MayFail;
+            else if( tag == "!nonportable" )
+                return TestCaseInfo::NonPortable;
+            else if( tag == "!benchmark" )
+                return static_cast<TestCaseInfo::SpecialProperties>( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden );
+            else
+                return TestCaseInfo::None;
+        }
+        bool isReservedTag( std::string const& tag ) {
+            return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( static_cast<unsigned char>(tag[0]) );
+        }
+        void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
+            CATCH_ENFORCE( !isReservedTag(tag),
+                          "Tag name: [" << tag << "] is not allowed.\n"
+                          << "Tag names starting with non alpha-numeric characters are reserved\n"
+                          << _lineInfo );
+        }
     }
 
     TestCase makeTestCase(  ITestInvoker* _testCase,
                             std::string const& _className,
-                            std::string const& _name,
-                            std::string const& _descOrTags,
+                            NameAndTags const& nameAndTags,
                             SourceLineInfo const& _lineInfo )
     {
         bool isHidden = false;
@@ -9686,6 +11641,7 @@
         std::vector<std::string> tags;
         std::string desc, tag;
         bool inTag = false;
+        std::string _descOrTags = nameAndTags.tags;
         for (char c : _descOrTags) {
             if( !inTag ) {
                 if( c == '[' )
@@ -9713,8 +11669,8 @@
             tags.push_back( "." );
         }
 
-        TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
-        return TestCase( _testCase, info );
+        TestCaseInfo info( nameAndTags.name, _className, desc, tags, _lineInfo );
+        return TestCase( _testCase, std::move(info) );
     }
 
     void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) {
@@ -9774,7 +11730,7 @@
         return ret;
     }
 
-    TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
+    TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo( std::move(info) ), test( testCase ) {}
 
     TestCase TestCase::withName( std::string const& _newName ) const {
         TestCase other( *this );
@@ -9819,7 +11775,7 @@
                 break;
             case RunTests::InRandomOrder:
                 seedRng( config );
-                RandomNumberGenerator::shuffle( sorted );
+                std::shuffle( sorted.begin(), sorted.end(), rng() );
                 break;
             case RunTests::InDeclarationOrder:
                 // already in declaration order
@@ -9885,7 +11841,7 @@
         m_testAsFunction();
     }
 
-    std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
+    std::string extractClassName( StringRef const& classOrQualifiedMethodName ) {
         std::string className = classOrQualifiedMethodName;
         if( startsWith( className, '&' ) )
         {
@@ -9903,7 +11859,7 @@
 // start catch_test_case_tracker.cpp
 
 #include <algorithm>
-#include <assert.h>
+#include <cassert>
 #include <stdexcept>
 #include <memory>
 #include <sstream>
@@ -9959,13 +11915,6 @@
         m_currentTracker = tracker;
     }
 
-    TrackerBase::TrackerHasName::TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {}
-    bool TrackerBase::TrackerHasName::operator ()( ITrackerPtr const& tracker ) const {
-        return
-            tracker->nameAndLocation().name == m_nameAndLocation.name &&
-            tracker->nameAndLocation().location == m_nameAndLocation.location;
-    }
-
     TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
     :   m_nameAndLocation( nameAndLocation ),
         m_ctx( ctx ),
@@ -9993,7 +11942,12 @@
     }
 
     ITrackerPtr TrackerBase::findChild( NameAndLocation const& nameAndLocation ) {
-        auto it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) );
+        auto it = std::find_if( m_children.begin(), m_children.end(),
+            [&nameAndLocation]( ITrackerPtr const& tracker ){
+                return
+                    tracker->nameAndLocation().location == nameAndLocation.location &&
+                    tracker->nameAndLocation().name == nameAndLocation.name;
+            } );
         return( it != m_children.end() )
             ? *it
             : nullptr;
@@ -10012,7 +11966,7 @@
     }
 
     bool TrackerBase::isSectionTracker() const { return false; }
-    bool TrackerBase::isIndexTracker() const { return false; }
+    bool TrackerBase::isGeneratorTracker() const { return false; }
 
     void TrackerBase::open() {
         m_runState = Executing;
@@ -10081,6 +12035,17 @@
         }
     }
 
+    bool SectionTracker::isComplete() const {
+        bool complete = true;
+
+        if ((m_filters.empty() || m_filters[0] == "") ||
+             std::find(m_filters.begin(), m_filters.end(),
+                       m_nameAndLocation.name) != m_filters.end())
+            complete = TrackerBase::isComplete();
+        return complete;
+
+    }
+
     bool SectionTracker::isSectionTracker() const { return true; }
 
     SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
@@ -10118,55 +12083,11 @@
             m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() );
     }
 
-    IndexTracker::IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size )
-    :   TrackerBase( nameAndLocation, ctx, parent ),
-        m_size( size )
-    {}
-
-    bool IndexTracker::isIndexTracker() const { return true; }
-
-    IndexTracker& IndexTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) {
-        std::shared_ptr<IndexTracker> tracker;
-
-        ITracker& currentTracker = ctx.currentTracker();
-        if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
-            assert( childTracker );
-            assert( childTracker->isIndexTracker() );
-            tracker = std::static_pointer_cast<IndexTracker>( childTracker );
-        }
-        else {
-            tracker = std::make_shared<IndexTracker>( nameAndLocation, ctx, &currentTracker, size );
-            currentTracker.addChild( tracker );
-        }
-
-        if( !ctx.completedCycle() && !tracker->isComplete() ) {
-            if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
-                tracker->moveNext();
-            tracker->open();
-        }
-
-        return *tracker;
-    }
-
-    int IndexTracker::index() const { return m_index; }
-
-    void IndexTracker::moveNext() {
-        m_index++;
-        m_children.clear();
-    }
-
-    void IndexTracker::close() {
-        TrackerBase::close();
-        if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
-            m_runState = Executing;
-    }
-
 } // namespace TestCaseTracking
 
 using TestCaseTracking::ITracker;
 using TestCaseTracking::TrackerContext;
 using TestCaseTracking::SectionTracker;
-using TestCaseTracking::IndexTracker;
 
 } // namespace Catch
 
@@ -10182,19 +12103,18 @@
         return new(std::nothrow) TestInvokerAsFunction( testAsFunction );
     }
 
-    NameAndTags::NameAndTags( StringRef name_ , StringRef tags_ ) noexcept : name( name_ ), tags( tags_ ) {}
+    NameAndTags::NameAndTags( StringRef const& name_ , StringRef const& tags_ ) noexcept : name( name_ ), tags( tags_ ) {}
 
-    AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept {
-        try {
+    AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept {
+        CATCH_TRY {
             getMutableRegistryHub()
                     .registerTest(
                         makeTestCase(
                             invoker,
                             extractClassName( classOrMethod ),
-                            nameAndTags.name,
-                            nameAndTags.tags,
+                            nameAndTags,
                             lineInfo));
-        } catch (...) {
+        } CATCH_CATCH_ALL {
             // Do not throw when constructing global objects, instead register the exception to be processed later
             getMutableRegistryHub().registerStartupException();
         }
@@ -10340,32 +12260,44 @@
 
 #include <chrono>
 
+static const uint64_t nanosecondsInSecond = 1000000000;
+
 namespace Catch {
 
     auto getCurrentNanosecondsSinceEpoch() -> uint64_t {
         return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count();
     }
 
-    auto estimateClockResolution() -> uint64_t {
-        uint64_t sum = 0;
-        static const uint64_t iterations = 1000000;
+    namespace {
+        auto estimateClockResolution() -> uint64_t {
+            uint64_t sum = 0;
+            static const uint64_t iterations = 1000000;
 
-        for( std::size_t i = 0; i < iterations; ++i ) {
+            auto startTime = getCurrentNanosecondsSinceEpoch();
 
-            uint64_t ticks;
-            uint64_t baseTicks = getCurrentNanosecondsSinceEpoch();
-            do {
-                ticks = getCurrentNanosecondsSinceEpoch();
+            for( std::size_t i = 0; i < iterations; ++i ) {
+
+                uint64_t ticks;
+                uint64_t baseTicks = getCurrentNanosecondsSinceEpoch();
+                do {
+                    ticks = getCurrentNanosecondsSinceEpoch();
+                } while( ticks == baseTicks );
+
+                auto delta = ticks - baseTicks;
+                sum += delta;
+
+                // If we have been calibrating for over 3 seconds -- the clock
+                // is terrible and we should move on.
+                // TBD: How to signal that the measured resolution is probably wrong?
+                if (ticks > startTime + 3 * nanosecondsInSecond) {
+                    return sum / ( i + 1u );
+                }
             }
-            while( ticks == baseTicks );
 
-            auto delta = ticks - baseTicks;
-            sum += delta;
+            // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers
+            // - and potentially do more iterations if there's a high variance.
+            return sum/iterations;
         }
-
-        // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers
-        // - and potentially do more iterations if there's a high variance.
-        return sum/iterations;
     }
     auto getEstimatedClockResolution() -> uint64_t {
         static auto s_resolution = estimateClockResolution();
@@ -10449,7 +12381,7 @@
 
 template<typename T>
 std::string fpToString( T value, int precision ) {
-    if (std::isnan(value)) {
+    if (Catch::isnan(value)) {
         return "nan";
     }
 
@@ -10496,14 +12428,11 @@
     return s;
 }
 
-std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) {
-    std::string s;
-    s.reserve(wstr.size());
-    for (auto c : wstr) {
-        s += (c <= 0xff) ? static_cast<char>(c) : '?';
-    }
-    return ::Catch::Detail::stringify(s);
+#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
+std::string StringMaker<std::string_view>::convert(std::string_view str) {
+    return ::Catch::Detail::stringify(std::string{ str });
 }
+#endif
 
 std::string StringMaker<char const*>::convert(char const* str) {
     if (str) {
@@ -10519,6 +12448,23 @@
         return{ "{null string}" };
     }
 }
+
+#ifdef CATCH_CONFIG_WCHAR
+std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) {
+    std::string s;
+    s.reserve(wstr.size());
+    for (auto c : wstr) {
+        s += (c <= 0xff) ? static_cast<char>(c) : '?';
+    }
+    return ::Catch::Detail::stringify(s);
+}
+
+# ifdef CATCH_CONFIG_CPP17_STRING_VIEW
+std::string StringMaker<std::wstring_view>::convert(std::wstring_view str) {
+    return StringMaker<std::wstring>::convert(std::wstring(str));
+}
+# endif
+
 std::string StringMaker<wchar_t const*>::convert(wchar_t const * str) {
     if (str) {
         return ::Catch::Detail::stringify(std::wstring{ str });
@@ -10533,6 +12479,7 @@
         return{ "{null string}" };
     }
 }
+#endif
 
 std::string StringMaker<int>::convert(int value) {
     return ::Catch::Detail::stringify(static_cast<long long>(value));
@@ -10568,7 +12515,7 @@
     return b ? "true" : "false";
 }
 
-std::string StringMaker<char>::convert(char value) {
+std::string StringMaker<signed char>::convert(signed char value) {
     if (value == '\r') {
         return "'\\r'";
     } else if (value == '\f') {
@@ -10585,8 +12532,8 @@
         return chstr;
     }
 }
-std::string StringMaker<signed char>::convert(signed char c) {
-    return ::Catch::Detail::stringify(static_cast<char>(c));
+std::string StringMaker<char>::convert(char c) {
+    return ::Catch::Detail::stringify(static_cast<signed char>(c));
 }
 std::string StringMaker<unsigned char>::convert(unsigned char c) {
     return ::Catch::Detail::stringify(static_cast<char>(c));
@@ -10605,8 +12552,8 @@
 
 std::string ratio_string<std::atto>::symbol() { return "a"; }
 std::string ratio_string<std::femto>::symbol() { return "f"; }
-std::string  ratio_string<std::pico>::symbol() { return "p"; }
-std::string  ratio_string<std::nano>::symbol() { return "n"; }
+std::string ratio_string<std::pico>::symbol() { return "p"; }
+std::string ratio_string<std::nano>::symbol() { return "n"; }
 std::string ratio_string<std::micro>::symbol() { return "u"; }
 std::string ratio_string<std::milli>::symbol() { return "m"; }
 
@@ -10672,6 +12619,20 @@
 
 }
 // end catch_totals.cpp
+// start catch_uncaught_exceptions.cpp
+
+#include <exception>
+
+namespace Catch {
+    bool uncaught_exceptions() {
+#if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
+        return std::uncaught_exceptions() > 0;
+#else
+        return std::uncaught_exception();
+#endif
+  }
+} // end namespace Catch
+// end catch_uncaught_exceptions.cpp
 // start catch_version.cpp
 
 #include <ostream>
@@ -10704,7 +12665,7 @@
     }
 
     Version const& libraryVersion() {
-        static Version version( 2, 1, 1, "", 0 );
+        static Version version( 2, 7, 0, "", 0 );
         return version;
     }
 
@@ -10755,49 +12716,143 @@
 
 #include <iomanip>
 
+using uchar = unsigned char;
+
 namespace Catch {
 
+namespace {
+
+    size_t trailingBytes(unsigned char c) {
+        if ((c & 0xE0) == 0xC0) {
+            return 2;
+        }
+        if ((c & 0xF0) == 0xE0) {
+            return 3;
+        }
+        if ((c & 0xF8) == 0xF0) {
+            return 4;
+        }
+        CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
+    }
+
+    uint32_t headerValue(unsigned char c) {
+        if ((c & 0xE0) == 0xC0) {
+            return c & 0x1F;
+        }
+        if ((c & 0xF0) == 0xE0) {
+            return c & 0x0F;
+        }
+        if ((c & 0xF8) == 0xF0) {
+            return c & 0x07;
+        }
+        CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
+    }
+
+    void hexEscapeChar(std::ostream& os, unsigned char c) {
+        std::ios_base::fmtflags f(os.flags());
+        os << "\\x"
+            << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
+            << static_cast<int>(c);
+        os.flags(f);
+    }
+
+} // anonymous namespace
+
     XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat )
     :   m_str( str ),
         m_forWhat( forWhat )
     {}
 
     void XmlEncode::encodeTo( std::ostream& os ) const {
-
         // Apostrophe escaping not necessary if we always use " to write attributes
         // (see: http://www.w3.org/TR/xml/#syntax)
 
-        for( std::size_t i = 0; i < m_str.size(); ++ i ) {
-            char c = m_str[i];
-            switch( c ) {
-                case '<':   os << "&lt;"; break;
-                case '&':   os << "&amp;"; break;
+        for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
+            uchar c = m_str[idx];
+            switch (c) {
+            case '<':   os << "&lt;"; break;
+            case '&':   os << "&amp;"; break;
 
-                case '>':
-                    // See: http://www.w3.org/TR/xml/#syntax
-                    if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' )
-                        os << "&gt;";
-                    else
-                        os << c;
+            case '>':
+                // See: http://www.w3.org/TR/xml/#syntax
+                if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']')
+                    os << "&gt;";
+                else
+                    os << c;
+                break;
+
+            case '\"':
+                if (m_forWhat == ForAttributes)
+                    os << "&quot;";
+                else
+                    os << c;
+                break;
+
+            default:
+                // Check for control characters and invalid utf-8
+
+                // Escape control characters in standard ascii
+                // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
+                if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
+                    hexEscapeChar(os, c);
                     break;
+                }
 
-                case '\"':
-                    if( m_forWhat == ForAttributes )
-                        os << "&quot;";
-                    else
-                        os << c;
+                // Plain ASCII: Write it to stream
+                if (c < 0x7F) {
+                    os << c;
                     break;
+                }
 
-                default:
-                    // Escape control chars - based on contribution by @espenalb in PR #465 and
-                    // by @mrpi PR #588
-                    if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) {
-                        // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
-                        os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
-                           << static_cast<int>( c );
-                    }
-                    else
-                        os << c;
+                // UTF-8 territory
+                // Check if the encoding is valid and if it is not, hex escape bytes.
+                // Important: We do not check the exact decoded values for validity, only the encoding format
+                // First check that this bytes is a valid lead byte:
+                // This means that it is not encoded as 1111 1XXX
+                // Or as 10XX XXXX
+                if (c <  0xC0 ||
+                    c >= 0xF8) {
+                    hexEscapeChar(os, c);
+                    break;
+                }
+
+                auto encBytes = trailingBytes(c);
+                // Are there enough bytes left to avoid accessing out-of-bounds memory?
+                if (idx + encBytes - 1 >= m_str.size()) {
+                    hexEscapeChar(os, c);
+                    break;
+                }
+                // The header is valid, check data
+                // The next encBytes bytes must together be a valid utf-8
+                // This means: bitpattern 10XX XXXX and the extracted value is sane (ish)
+                bool valid = true;
+                uint32_t value = headerValue(c);
+                for (std::size_t n = 1; n < encBytes; ++n) {
+                    uchar nc = m_str[idx + n];
+                    valid &= ((nc & 0xC0) == 0x80);
+                    value = (value << 6) | (nc & 0x3F);
+                }
+
+                if (
+                    // Wrong bit pattern of following bytes
+                    (!valid) ||
+                    // Overlong encodings
+                    (value < 0x80) ||
+                    (0x80 <= value && value < 0x800   && encBytes > 2) ||
+                    (0x800 < value && value < 0x10000 && encBytes > 3) ||
+                    // Encoded value out of range
+                    (value >= 0x110000)
+                    ) {
+                    hexEscapeChar(os, c);
+                    break;
+                }
+
+                // If we got here, this is in fact a valid(ish) utf-8 sequence
+                for (std::size_t n = 0; n < encBytes; ++n) {
+                    os << m_str[idx + n];
+                }
+                idx += encBytes - 1;
+                break;
             }
         }
     }
@@ -10939,7 +12994,7 @@
 #include <cstring>
 #include <cfloat>
 #include <cstdio>
-#include <assert.h>
+#include <cassert>
 #include <memory>
 
 namespace Catch {
@@ -10962,7 +13017,7 @@
 #ifdef _MSC_VER
         sprintf_s(buffer, "%.3f", duration);
 #else
-        sprintf(buffer, "%.3f", duration);
+        std::sprintf(buffer, "%.3f", duration);
 #endif
         return std::string(buffer);
     }
@@ -10970,6 +13025,10 @@
     TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config)
         :StreamingReporterBase(_config) {}
 
+    std::set<Verbosity> TestEventListenerBase::getSupportedVerbosities() {
+        return { Verbosity::Quiet, Verbosity::Normal, Verbosity::High };
+    }
+
     void TestEventListenerBase::assertionStarting(AssertionInfo const &) {}
 
     bool TestEventListenerBase::assertionEnded(AssertionStats const &) {
@@ -11214,9 +13273,7 @@
         }
 
         ReporterPreferences CompactReporter::getPreferences() const {
-            ReporterPreferences prefs;
-            prefs.shouldRedirectStdOut = false;
-            return prefs;
+            return m_reporterPrefs;
         }
 
         void CompactReporter::noMatchingTestCases( std::string const& spec ) {
@@ -11360,8 +13417,6 @@
     void print() const {
         printSourceInfo();
         if (stats.totals.assertions.total() > 0) {
-            if (result.isOk())
-                stream << '\n';
             printResultType();
             printOriginalExpression();
             printReconstructedExpression();
@@ -11496,7 +13551,7 @@
         case Unit::Nanoseconds:
             return "ns";
         case Unit::Microseconds:
-            return "µs";
+            return "us";
         case Unit::Milliseconds:
             return "ms";
         case Unit::Seconds:
@@ -11882,7 +13937,7 @@
 // end catch_reporter_console.cpp
 // start catch_reporter_junit.cpp
 
-#include <assert.h>
+#include <cassert>
 #include <sstream>
 #include <ctime>
 #include <algorithm>
@@ -11931,9 +13986,10 @@
             xml( _config.stream() )
         {
             m_reporterPrefs.shouldRedirectStdOut = true;
+            m_reporterPrefs.shouldReportAllAssertions = true;
         }
 
-    JunitReporter::~JunitReporter() {};
+    JunitReporter::~JunitReporter() {}
 
     std::string JunitReporter::getDescription() {
         return "Reports test results in an XML format that looks like Ant's junitreport target";
@@ -11944,6 +14000,13 @@
     void JunitReporter::testRunStarting( TestRunInfo const& runInfo )  {
         CumulativeReporterBase::testRunStarting( runInfo );
         xml.startElement( "testsuites" );
+        if( m_config->rngSeed() != 0 ) {
+            xml.startElement( "properties" );
+            xml.scopedElement( "property" )
+                .writeAttribute( "name", "random-seed" )
+                .writeAttribute( "value", m_config->rngSeed() );
+            xml.endElement();
+        }
     }
 
     void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) {
@@ -12115,100 +14178,139 @@
 
 } // end namespace Catch
 // end catch_reporter_junit.cpp
-// start catch_reporter_multi.cpp
+// start catch_reporter_listening.cpp
+
+#include <cassert>
 
 namespace Catch {
 
-    void MultipleReporters::add( IStreamingReporterPtr&& reporter ) {
-        m_reporters.push_back( std::move( reporter ) );
+    ListeningReporter::ListeningReporter() {
+        // We will assume that listeners will always want all assertions
+        m_preferences.shouldReportAllAssertions = true;
     }
 
-    ReporterPreferences MultipleReporters::getPreferences() const {
-        return m_reporters[0]->getPreferences();
+    void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) {
+        m_listeners.push_back( std::move( listener ) );
     }
 
-    std::set<Verbosity> MultipleReporters::getSupportedVerbosities() {
+    void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) {
+        assert(!m_reporter && "Listening reporter can wrap only 1 real reporter");
+        m_reporter = std::move( reporter );
+        m_preferences.shouldRedirectStdOut = m_reporter->getPreferences().shouldRedirectStdOut;
+    }
+
+    ReporterPreferences ListeningReporter::getPreferences() const {
+        return m_preferences;
+    }
+
+    std::set<Verbosity> ListeningReporter::getSupportedVerbosities() {
         return std::set<Verbosity>{ };
     }
 
-    void MultipleReporters::noMatchingTestCases( std::string const& spec ) {
-        for( auto const& reporter : m_reporters )
-            reporter->noMatchingTestCases( spec );
+    void ListeningReporter::noMatchingTestCases( std::string const& spec ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->noMatchingTestCases( spec );
+        }
+        m_reporter->noMatchingTestCases( spec );
     }
 
-    void MultipleReporters::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) {
-        for( auto const& reporter : m_reporters )
-            reporter->benchmarkStarting( benchmarkInfo );
+    void ListeningReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->benchmarkStarting( benchmarkInfo );
+        }
+        m_reporter->benchmarkStarting( benchmarkInfo );
     }
-    void MultipleReporters::benchmarkEnded( BenchmarkStats const& benchmarkStats ) {
-        for( auto const& reporter : m_reporters )
-            reporter->benchmarkEnded( benchmarkStats );
+    void ListeningReporter::benchmarkEnded( BenchmarkStats const& benchmarkStats ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->benchmarkEnded( benchmarkStats );
+        }
+        m_reporter->benchmarkEnded( benchmarkStats );
     }
 
-    void MultipleReporters::testRunStarting( TestRunInfo const& testRunInfo ) {
-        for( auto const& reporter : m_reporters )
-            reporter->testRunStarting( testRunInfo );
+    void ListeningReporter::testRunStarting( TestRunInfo const& testRunInfo ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->testRunStarting( testRunInfo );
+        }
+        m_reporter->testRunStarting( testRunInfo );
     }
 
-    void MultipleReporters::testGroupStarting( GroupInfo const& groupInfo ) {
-        for( auto const& reporter : m_reporters )
-            reporter->testGroupStarting( groupInfo );
+    void ListeningReporter::testGroupStarting( GroupInfo const& groupInfo ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->testGroupStarting( groupInfo );
+        }
+        m_reporter->testGroupStarting( groupInfo );
     }
 
-    void MultipleReporters::testCaseStarting( TestCaseInfo const& testInfo ) {
-        for( auto const& reporter : m_reporters )
-            reporter->testCaseStarting( testInfo );
+    void ListeningReporter::testCaseStarting( TestCaseInfo const& testInfo ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->testCaseStarting( testInfo );
+        }
+        m_reporter->testCaseStarting( testInfo );
     }
 
-    void MultipleReporters::sectionStarting( SectionInfo const& sectionInfo ) {
-        for( auto const& reporter : m_reporters )
-            reporter->sectionStarting( sectionInfo );
+    void ListeningReporter::sectionStarting( SectionInfo const& sectionInfo ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->sectionStarting( sectionInfo );
+        }
+        m_reporter->sectionStarting( sectionInfo );
     }
 
-    void MultipleReporters::assertionStarting( AssertionInfo const& assertionInfo ) {
-        for( auto const& reporter : m_reporters )
-            reporter->assertionStarting( assertionInfo );
+    void ListeningReporter::assertionStarting( AssertionInfo const& assertionInfo ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->assertionStarting( assertionInfo );
+        }
+        m_reporter->assertionStarting( assertionInfo );
     }
 
     // The return value indicates if the messages buffer should be cleared:
-    bool MultipleReporters::assertionEnded( AssertionStats const& assertionStats ) {
-        bool clearBuffer = false;
-        for( auto const& reporter : m_reporters )
-            clearBuffer |= reporter->assertionEnded( assertionStats );
-        return clearBuffer;
+    bool ListeningReporter::assertionEnded( AssertionStats const& assertionStats ) {
+        for( auto const& listener : m_listeners ) {
+            static_cast<void>( listener->assertionEnded( assertionStats ) );
+        }
+        return m_reporter->assertionEnded( assertionStats );
     }
 
-    void MultipleReporters::sectionEnded( SectionStats const& sectionStats ) {
-        for( auto const& reporter : m_reporters )
-            reporter->sectionEnded( sectionStats );
+    void ListeningReporter::sectionEnded( SectionStats const& sectionStats ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->sectionEnded( sectionStats );
+        }
+        m_reporter->sectionEnded( sectionStats );
     }
 
-    void MultipleReporters::testCaseEnded( TestCaseStats const& testCaseStats ) {
-        for( auto const& reporter : m_reporters )
-            reporter->testCaseEnded( testCaseStats );
+    void ListeningReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->testCaseEnded( testCaseStats );
+        }
+        m_reporter->testCaseEnded( testCaseStats );
     }
 
-    void MultipleReporters::testGroupEnded( TestGroupStats const& testGroupStats ) {
-        for( auto const& reporter : m_reporters )
-            reporter->testGroupEnded( testGroupStats );
+    void ListeningReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->testGroupEnded( testGroupStats );
+        }
+        m_reporter->testGroupEnded( testGroupStats );
     }
 
-    void MultipleReporters::testRunEnded( TestRunStats const& testRunStats ) {
-        for( auto const& reporter : m_reporters )
-            reporter->testRunEnded( testRunStats );
+    void ListeningReporter::testRunEnded( TestRunStats const& testRunStats ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->testRunEnded( testRunStats );
+        }
+        m_reporter->testRunEnded( testRunStats );
     }
 
-    void MultipleReporters::skipTest( TestCaseInfo const& testInfo ) {
-        for( auto const& reporter : m_reporters )
-            reporter->skipTest( testInfo );
+    void ListeningReporter::skipTest( TestCaseInfo const& testInfo ) {
+        for ( auto const& listener : m_listeners ) {
+            listener->skipTest( testInfo );
+        }
+        m_reporter->skipTest( testInfo );
     }
 
-    bool MultipleReporters::isMulti() const {
+    bool ListeningReporter::isMulti() const {
         return true;
     }
 
 } // end namespace Catch
-// end catch_reporter_multi.cpp
+// end catch_reporter_listening.cpp
 // start catch_reporter_xml.cpp
 
 #if defined(_MSC_VER)
@@ -12224,6 +14326,7 @@
         m_xml(_config.stream())
     {
         m_reporterPrefs.shouldRedirectStdOut = true;
+        m_reporterPrefs.shouldReportAllAssertions = true;
     }
 
     XmlReporter::~XmlReporter() = default;
@@ -12254,6 +14357,9 @@
         m_xml.startElement( "Catch" );
         if( !m_config->name().empty() )
             m_xml.writeAttribute( "name", m_config->name() );
+        if( m_config->rngSeed() != 0 )
+            m_xml.scopedElement( "Randomness" )
+                .writeAttribute( "seed", m_config->rngSeed() );
     }
 
     void XmlReporter::testGroupStarting( GroupInfo const& groupInfo ) {
@@ -12280,8 +14386,7 @@
         StreamingReporterBase::sectionStarting( sectionInfo );
         if( m_sectionDepth++ > 0 ) {
             m_xml.startElement( "Section" )
-                .writeAttribute( "name", trim( sectionInfo.name ) )
-                .writeAttribute( "description", sectionInfo.description );
+                .writeAttribute( "name", trim( sectionInfo.name ) );
             writeSourceInfo( sectionInfo.lineInfo );
             m_xml.ensureTagClosed();
         }
@@ -12438,7 +14543,7 @@
 
 #ifndef __OBJC__
 
-#if defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
+#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
 // Standard C/C++ Win32 Unicode wmain entry point
 extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {
 #else
@@ -12486,7 +14591,7 @@
 #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
 #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
 
-#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ )
+#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
@@ -12500,7 +14605,7 @@
 #define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
 #define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
 
-#define CATCH_CHECK_THROWS( ... )  INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ )
+#define CATCH_CHECK_THROWS( ... )  INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
@@ -12516,27 +14621,49 @@
 
 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
-#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) )
+#define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE",__VA_ARGS__ )
 
 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
+#define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
 #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
 
 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
 
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
+#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
+#else
+#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
+#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
+#endif
+
+#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
+#define CATCH_STATIC_REQUIRE( ... )       static_assert(   __VA_ARGS__ ,      #__VA_ARGS__ );     CATCH_SUCCEED( #__VA_ARGS__ )
+#define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ )
+#else
+#define CATCH_STATIC_REQUIRE( ... )       CATCH_REQUIRE( __VA_ARGS__ )
+#define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ )
+#endif
+
 // "BDD-style" convenience wrappers
 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
-#define CATCH_GIVEN( desc )    CATCH_SECTION( std::string( "Given: ") + desc )
-#define CATCH_WHEN( desc )     CATCH_SECTION( std::string( " When: ") + desc )
-#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( "  And: ") + desc )
-#define CATCH_THEN( desc )     CATCH_SECTION( std::string( " Then: ") + desc )
-#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( "  And: ") + desc )
+#define CATCH_GIVEN( desc )     INTERNAL_CATCH_DYNAMIC_SECTION( "    Given: " << desc )
+#define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
+#define CATCH_WHEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     When: " << desc )
+#define CATCH_AND_WHEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
+#define CATCH_THEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     Then: " << desc )
+#define CATCH_AND_THEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( "      And: " << desc )
 
 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
 #else
@@ -12573,19 +14700,41 @@
 #endif // CATCH_CONFIG_DISABLE_MATCHERS
 
 #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
+#define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg )
 #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
-#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) )
+#define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ )
 
 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
+#define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
 #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
 #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
 
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
+#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
+#define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
+#else
+#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
+#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
+#define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
+#endif
+
+#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
+#define STATIC_REQUIRE( ... )       static_assert(   __VA_ARGS__,  #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ )
+#define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" )
+#else
+#define STATIC_REQUIRE( ... )       REQUIRE( __VA_ARGS__ )
+#define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ )
+#endif
+
 #endif
 
 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
@@ -12594,15 +14743,17 @@
 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
 
-#define GIVEN( desc )    SECTION( std::string("   Given: ") + desc )
-#define WHEN( desc )     SECTION( std::string("    When: ") + desc )
-#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc )
-#define THEN( desc )     SECTION( std::string("    Then: ") + desc )
-#define AND_THEN( desc ) SECTION( std::string("     And: ") + desc )
+#define GIVEN( desc )     INTERNAL_CATCH_DYNAMIC_SECTION( "    Given: " << desc )
+#define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
+#define WHEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     When: " << desc )
+#define AND_WHEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
+#define THEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     Then: " << desc )
+#define AND_THEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( "      And: " << desc )
 
 using Catch::Detail::Approx;
 
-#else
+#else // CATCH_CONFIG_DISABLE
+
 //////
 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_
 #ifdef CATCH_CONFIG_PREFIX_ALL
@@ -12647,21 +14798,38 @@
 #define CATCH_METHOD_AS_TEST_CASE( method, ... )
 #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
 #define CATCH_SECTION( ... )
+#define CATCH_DYNAMIC_SECTION( ... )
 #define CATCH_FAIL( ... ) (void)(0)
 #define CATCH_FAIL_CHECK( ... ) (void)(0)
 #define CATCH_SUCCEED( ... ) (void)(0)
 
 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
 
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) )
+#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className )
+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
+#else
+#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) )
+#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) )
+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
+#endif
+
 // "BDD-style" convenience wrappers
 #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
 #define CATCH_GIVEN( desc )
+#define CATCH_AND_GIVEN( desc )
 #define CATCH_WHEN( desc )
 #define CATCH_AND_WHEN( desc )
 #define CATCH_THEN( desc )
 #define CATCH_AND_THEN( desc )
 
+#define CATCH_STATIC_REQUIRE( ... )       (void)(0)
+#define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0)
+
 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
 #else
 
@@ -12705,11 +14873,27 @@
 #define METHOD_AS_TEST_CASE( method, ... )
 #define REGISTER_TEST_CASE( Function, ... ) (void)(0)
 #define SECTION( ... )
+#define DYNAMIC_SECTION( ... )
 #define FAIL( ... ) (void)(0)
 #define FAIL_CHECK( ... ) (void)(0)
 #define SUCCEED( ... ) (void)(0)
 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
 
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) )
+#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className )
+#define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
+#else
+#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) )
+#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) )
+#define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
+#endif
+
+#define STATIC_REQUIRE( ... )       (void)(0)
+#define STATIC_REQUIRE_FALSE( ... ) (void)(0)
+
 #endif
 
 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
@@ -12719,6 +14903,7 @@
 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
 
 #define GIVEN( desc )
+#define AND_GIVEN( desc )
 #define WHEN( desc )
 #define AND_WHEN( desc )
 #define THEN( desc )
diff --git a/single_include/catch_reporter_automake.hpp b/single_include/catch2/catch_reporter_automake.hpp
similarity index 100%
rename from single_include/catch_reporter_automake.hpp
rename to single_include/catch2/catch_reporter_automake.hpp
diff --git a/single_include/catch_reporter_tap.hpp b/single_include/catch2/catch_reporter_tap.hpp
similarity index 97%
rename from single_include/catch_reporter_tap.hpp
rename to single_include/catch2/catch_reporter_tap.hpp
index edb75b5..1bfe4f5 100644
--- a/single_include/catch_reporter_tap.hpp
+++ b/single_include/catch2/catch_reporter_tap.hpp
@@ -26,13 +26,11 @@
         ~TAPReporter() override;
 
         static std::string getDescription() {
-            return "Reports test results in TAP format, suitable for test harneses";
+            return "Reports test results in TAP format, suitable for test harnesses";
         }
 
         ReporterPreferences getPreferences() const override {
-            ReporterPreferences prefs;
-            prefs.shouldRedirectStdOut = false;
-            return prefs;
+            return m_reporterPrefs;
         }
 
         void noMatchingTestCases( std::string const& spec ) override {
@@ -44,9 +42,9 @@
         bool assertionEnded( AssertionStats const& _assertionStats ) override {
             ++counter;
 
+            stream << "# " << currentTestCaseInfo->name << std::endl;
             AssertionPrinter printer( stream, _assertionStats, counter );
             printer.print();
-            stream << " # " << currentTestCaseInfo->name ;
 
             stream << std::endl;
             return true;
diff --git a/single_include/catch_reporter_teamcity.hpp b/single_include/catch2/catch_reporter_teamcity.hpp
similarity index 97%
rename from single_include/catch_reporter_teamcity.hpp
rename to single_include/catch2/catch_reporter_teamcity.hpp
index dbd0db5..eca2885 100644
--- a/single_include/catch_reporter_teamcity.hpp
+++ b/single_include/catch2/catch_reporter_teamcity.hpp
@@ -97,12 +97,12 @@
                     case ResultWas::Ok:
                     case ResultWas::Info:
                     case ResultWas::Warning:
-                        throw std::domain_error( "Internal error in TeamCity reporter" );
+                        CATCH_ERROR( "Internal error in TeamCity reporter" );
                     // These cases are here to prevent compiler warnings
                     case ResultWas::Unknown:
                     case ResultWas::FailureBit:
                     case ResultWas::Exception:
-                        throw std::domain_error( "Not implemented" );
+                        CATCH_ERROR( "Not implemented" );
                 }
                 if( assertionStats.infoMessages.size() == 1 )
                     msg << " with message:";
diff --git a/test_package/CMakeLists.txt b/test_package/CMakeLists.txt
deleted file mode 100644
index 339facb..0000000
--- a/test_package/CMakeLists.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-cmake_minimum_required(VERSION 3.0)
-project(CatchTest CXX)
-
-include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
-conan_basic_setup()
-
-add_executable(${CMAKE_PROJECT_NAME} MainTest.cpp)
diff --git a/test_package/MainTest.cpp b/test_package/MainTest.cpp
deleted file mode 100644
index b8ed744..0000000
--- a/test_package/MainTest.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- *  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)
- */
-#define CATCH_CONFIG_MAIN
-#include "catch.hpp"
-
-unsigned int Factorial( unsigned int number ) {
-  return number > 1 ? Factorial(number-1)*number : 1;
-}
-
-TEST_CASE( "Factorials are computed", "[factorial]" ) {
-    REQUIRE( Factorial(0) == 1 );
-    REQUIRE( Factorial(1) == 1 );
-    REQUIRE( Factorial(2) == 2 );
-    REQUIRE( Factorial(3) == 6 );
-    REQUIRE( Factorial(10) == 3628800 );
-}
diff --git a/test_package/conanfile.py b/test_package/conanfile.py
deleted file mode 100644
index 174beba..0000000
--- a/test_package/conanfile.py
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env python
-from os import getenv
-from os import path
-from conans import ConanFile
-from conans import CMake
-
-
-class CatchConanTest(ConanFile):
-    generators = "cmake"
-    settings = "os", "compiler", "arch", "build_type"
-    username = getenv("CONAN_USERNAME", "philsquared")
-    channel = getenv("CONAN_CHANNEL", "testing")
-    requires = "Catch/2.1.1@%s/%s" % (username, channel)
-
-    def build(self):
-        cmake = CMake(self)
-        cmake.configure(build_dir="./")
-        cmake.build()
-
-    def test(self):
-        self.run(path.join("bin", "CatchTest"))
diff --git a/third_party/clara.hpp b/third_party/clara.hpp
index 2134a46..6be5a98 100644
--- a/third_party/clara.hpp
+++ b/third_party/clara.hpp
@@ -5,7 +5,7 @@
 //
 // See https://github.com/philsquared/Clara for more details
 
-// Clara v1.1.1
+// Clara v1.1.5
 
 #ifndef CLARA_HPP_INCLUDED
 #define CLARA_HPP_INCLUDED
@@ -18,14 +18,24 @@
 #define CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
 #endif
 
+#ifndef CLARA_CONFIG_OPTIONAL_TYPE
+#ifdef __has_include
+#if __has_include(<optional>) && __cplusplus >= 201703L
+#include <optional>
+#define CLARA_CONFIG_OPTIONAL_TYPE std::optional
+#endif
+#endif
+#endif
+
+
 // ----------- #included from clara_textflow.hpp -----------
 
 // TextFlowCpp
 //
 // A single-header library for wrapping and laying out basic text, by Phil Nash
 //
-// This work is licensed under the BSD 2-Clause license.
-// See the accompanying LICENSE file, or the one at https://opensource.org/licenses/BSD-2-Clause
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 //
 // This project is hosted at https://github.com/philsquared/textflowcpp
 
@@ -132,6 +142,12 @@
             }
 
         public:
+            using difference_type = std::ptrdiff_t;
+            using value_type = std::string;
+            using pointer = value_type*;
+            using reference = value_type&;
+            using iterator_category = std::forward_iterator_tag;
+
             explicit iterator( Column const& column ) : m_column( column ) {
                 assert( m_column.m_width > m_column.m_indent );
                 assert( m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent );
@@ -143,10 +159,7 @@
             auto operator *() const -> std::string {
                 assert( m_stringIndex < m_column.m_strings.size() );
                 assert( m_pos <= m_end );
-                if( m_pos + m_column.m_width < m_end )
-                    return addIndentAndSuffix(line().substr(m_pos, m_len));
-                else
-                    return addIndentAndSuffix(line().substr(m_pos, m_end - m_pos));
+                return addIndentAndSuffix(line().substr(m_pos, m_len));
             }
 
             auto operator ++() -> iterator& {
@@ -256,6 +269,12 @@
             }
 
         public:
+            using difference_type = std::ptrdiff_t;
+            using value_type = std::string;
+            using pointer = value_type*;
+            using reference = value_type&;
+            using iterator_category = std::forward_iterator_tag;
+
             explicit iterator( Columns const& columns )
             :   m_columns( columns.m_columns ),
                 m_activeIterators( m_columns.size() )
@@ -345,7 +364,7 @@
         cols += other;
         return cols;
     }
-}} // namespace clara::TextFlow
+}}
 
 #endif // CLARA_TEXTFLOW_HPP_INCLUDED
 
@@ -389,11 +408,9 @@
         std::vector<std::string> m_args;
 
     public:
-        Args( int argc, char *argv[] ) {
-            m_exeName = argv[0];
-            for( int i = 1; i < argc; ++i )
-                m_args.push_back( argv[i] );
-        }
+        Args( int argc, char const* const* argv )
+            : m_exeName(argv[0]),
+              m_args(argv + 1, argv + argc) {}
 
         Args( std::initializer_list<std::string> args )
         :   m_exeName( *args.begin() ),
@@ -580,15 +597,13 @@
 
     protected:
         void enforceOk() const override {
-            // !TBD: If no exceptions, std::terminate here or something
-            switch( m_type ) {
-                case ResultBase::LogicError:
-                    throw std::logic_error( m_errorMessage );
-                case ResultBase::RuntimeError:
-                    throw std::runtime_error( m_errorMessage );
-                case ResultBase::Ok:
-                    break;
-            }
+
+            // Errors shouldn't reach this point, but if they do
+            // the actual error message will be in m_errorMessage
+            assert( m_type != ResultBase::LogicError );
+            assert( m_type != ResultBase::RuntimeError );
+            if( m_type != ResultBase::Ok )
+                std::abort();
         }
 
         std::string m_errorMessage; // Only populated if resultType is an error
@@ -658,6 +673,16 @@
             return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" );
         return ParserResult::ok( ParseResultType::Matched );
     }
+#ifdef CLARA_CONFIG_OPTIONAL_TYPE
+    template<typename T>
+    inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult {
+        T temp;
+        auto result = convertInto( source, temp );
+        if( result )
+            target = std::move(temp);
+        return result;
+    }
+#endif // CLARA_CONFIG_OPTIONAL_TYPE
 
     struct NonCopyable {
         NonCopyable() = default;
@@ -670,12 +695,14 @@
     struct BoundRef : NonCopyable {
         virtual ~BoundRef() = default;
         virtual auto isContainer() const -> bool { return false; }
+        virtual auto isFlag() const -> bool { return false; }
     };
     struct BoundValueRefBase : BoundRef {
         virtual auto setValue( std::string const &arg ) -> ParserResult = 0;
     };
     struct BoundFlagRefBase : BoundRef {
         virtual auto setFlag( bool flag ) -> ParserResult = 0;
+        virtual auto isFlag() const -> bool { return true; }
     };
 
     template<typename T>
@@ -907,7 +934,7 @@
             if( token.type != TokenType::Argument )
                 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
 
-            assert( dynamic_cast<detail::BoundValueRefBase*>( m_ref.get() ) );
+            assert( !m_ref->isFlag() );
             auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
 
             auto result = valueRef->setValue( remainingTokens->token );
@@ -983,14 +1010,14 @@
             if( remainingTokens && remainingTokens->type == TokenType::Option ) {
                 auto const &token = *remainingTokens;
                 if( isMatch(token.token ) ) {
-                    if( auto flagRef = dynamic_cast<detail::BoundFlagRefBase*>( m_ref.get() ) ) {
+                    if( m_ref->isFlag() ) {
+                        auto flagRef = static_cast<detail::BoundFlagRefBase*>( m_ref.get() );
                         auto result = flagRef->setFlag( true );
                         if( !result )
                             return InternalParseResult( result );
                         if( result.value() == ParseResultType::ShortCircuitAll )
                             return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
                     } else {
-                        assert( dynamic_cast<detail::BoundValueRefBase*>( m_ref.get() ) );
                         auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
                         ++remainingTokens;
                         if( !remainingTokens )