From 80ee81d1a81f139d39bd2fc18e872671a648257d Mon Sep 17 00:00:00 2001
From: Nicolas Pope <nicolas.pope@utu.fi>
Date: Sun, 9 Jun 2019 20:34:23 +0300
Subject: [PATCH] Resolves #36 and most of #59

---
 applications/gui/src/main.cpp                 |     2 +-
 applications/gui/src/src_window.cpp           |    16 +-
 applications/gui/src/src_window.hpp           |     4 +-
 .../include/ftl/depth_camera_params.hpp       |     2 +-
 .../reconstruct/include/ftl/registration.hpp  |    16 +-
 .../include/ftl/scene_rep_hash_sdf.hpp        |     2 +-
 .../include/ftl/virtual_source.hpp            |    14 +-
 applications/reconstruct/src/main.cpp         |    80 +-
 applications/reconstruct/src/registration.cpp |    38 +-
 .../reconstruct/src/virtual_source.cpp        |    23 +-
 applications/vision/src/main.cpp              |    19 +-
 components/common/cpp/include/ftl/config.h.in |     2 +
 .../common/cpp/include/ftl/configurable.hpp   |     2 +
 .../common/cpp/include/ftl/configuration.hpp  |    76 +-
 components/common/cpp/include/ftl/uri.hpp     |     3 +-
 components/common/cpp/src/configuration.cpp   |    20 +-
 components/common/cpp/src/loguru.cpp          |     3 +
 components/common/cpp/src/uri.cpp             |     4 +-
 .../renderers/cpp/include/ftl/display.hpp     |     4 +-
 .../cpp/include/ftl/rgbd_display.hpp          |     8 +-
 components/renderers/cpp/src/display.cpp      |     4 +-
 components/renderers/cpp/src/rgbd_display.cpp |     8 +-
 components/rgbd-sources/CMakeLists.txt        |    28 +-
 components/rgbd-sources/include/ftl/rgbd.hpp  |    10 +-
 .../{camera_params.hpp => rgbd/camera.hpp}    |     2 +-
 .../include/ftl/rgbd/detail/source.hpp        |    39 +
 .../{rgbdimage_source.hpp => rgbd/group.hpp}  |     0
 .../include/ftl/{ => rgbd}/snapshot.hpp       |     8 +-
 .../rgbd-sources/include/ftl/rgbd/source.hpp  |   167 +
 .../{rgbd_streamer.hpp => rgbd/streamer.hpp}  |    10 +-
 .../include/ftl/rgbdvideo_source.hpp          |     0
 .../include/ftl/snapshot_source.hpp           |    23 -
 .../include/ftl/stereoimage_source.hpp        |     0
 .../src/algorithms/fixstars_sgm.hpp           |     2 +-
 .../rgbd-sources/src/algorithms/rtcensus.hpp  |     2 +-
 .../src/algorithms/rtcensus_sgm.cpp           |     2 +-
 .../src/algorithms/rtcensus_sgm.hpp           |     2 +-
 components/rgbd-sources/src/calibrate.cpp     |     5 +-
 components/rgbd-sources/src/calibrate.hpp     |    11 +-
 components/rgbd-sources/src/disparity.cpp     |     6 +-
 components/rgbd-sources/src/disparity.hpp     |     7 +-
 components/rgbd-sources/src/image.hpp         |    25 +
 components/rgbd-sources/src/local.cpp         |     2 +-
 components/rgbd-sources/src/local.hpp         |     8 +-
 .../src/{net_source.cpp => net.cpp}           |    56 +-
 .../ftl/net_source.hpp => src/net.hpp}        |    21 +-
 components/rgbd-sources/src/rgbd_source.cpp   |    80 -
 components/rgbd-sources/src/snapshot.cpp      |    12 +-
 .../rgbd-sources/src/snapshot_source.cpp      |     5 +-
 .../rgbd-sources/src/snapshot_source.hpp      |    31 +
 components/rgbd-sources/src/source.cpp        |   166 +
 ...stereovideo_source.cpp => stereovideo.cpp} |    39 +-
 .../stereovideo.hpp}                          |    28 +-
 .../src/{rgbd_streamer.cpp => streamer.cpp}   |    22 +-
 components/rgbd-sources/test/CMakeLists.txt   |    10 +
 components/rgbd-sources/test/catch.hpp        | 14362 ++++++++++++++++
 components/rgbd-sources/test/data/image.png   |   Bin 0 -> 509 bytes
 components/rgbd-sources/test/data/video.mp4   |   Bin 0 -> 179698 bytes
 components/rgbd-sources/test/source_unit.cpp  |   171 +
 components/rgbd-sources/test/tests.cpp        |     3 +
 60 files changed, 15334 insertions(+), 381 deletions(-)
 rename components/rgbd-sources/include/ftl/{camera_params.hpp => rgbd/camera.hpp} (91%)
 create mode 100644 components/rgbd-sources/include/ftl/rgbd/detail/source.hpp
 rename components/rgbd-sources/include/ftl/{rgbdimage_source.hpp => rgbd/group.hpp} (100%)
 rename components/rgbd-sources/include/ftl/{ => rgbd}/snapshot.hpp (90%)
 create mode 100644 components/rgbd-sources/include/ftl/rgbd/source.hpp
 rename components/rgbd-sources/include/ftl/{rgbd_streamer.hpp => rgbd/streamer.hpp} (94%)
 delete mode 100644 components/rgbd-sources/include/ftl/rgbdvideo_source.hpp
 delete mode 100644 components/rgbd-sources/include/ftl/snapshot_source.hpp
 delete mode 100644 components/rgbd-sources/include/ftl/stereoimage_source.hpp
 create mode 100644 components/rgbd-sources/src/image.hpp
 rename components/rgbd-sources/src/{net_source.cpp => net.cpp} (64%)
 rename components/rgbd-sources/{include/ftl/net_source.hpp => src/net.hpp} (68%)
 delete mode 100644 components/rgbd-sources/src/rgbd_source.cpp
 create mode 100644 components/rgbd-sources/src/snapshot_source.hpp
 create mode 100644 components/rgbd-sources/src/source.cpp
 rename components/rgbd-sources/src/{stereovideo_source.cpp => stereovideo.cpp} (75%)
 rename components/rgbd-sources/{include/ftl/stereovideo_source.hpp => src/stereovideo.hpp} (56%)
 rename components/rgbd-sources/src/{rgbd_streamer.cpp => streamer.cpp} (93%)
 create mode 100644 components/rgbd-sources/test/CMakeLists.txt
 create mode 100644 components/rgbd-sources/test/catch.hpp
 create mode 100644 components/rgbd-sources/test/data/image.png
 create mode 100644 components/rgbd-sources/test/data/video.mp4
 create mode 100644 components/rgbd-sources/test/source_unit.cpp
 create mode 100644 components/rgbd-sources/test/tests.cpp

diff --git a/applications/gui/src/main.cpp b/applications/gui/src/main.cpp
index 184e38c88..f090bc019 100644
--- a/applications/gui/src/main.cpp
+++ b/applications/gui/src/main.cpp
@@ -20,7 +20,7 @@
 #include "src_window.hpp"
 
 using std::string;
-using ftl::rgbd::RGBDSource;
+using ftl::rgbd::Source;
 
 /*struct SourceViews {
 	ftl::rgbd::RGBDSource *source;
diff --git a/applications/gui/src/src_window.cpp b/applications/gui/src/src_window.cpp
index a4f30d997..15b8c5439 100644
--- a/applications/gui/src/src_window.cpp
+++ b/applications/gui/src/src_window.cpp
@@ -9,11 +9,11 @@
 #include <nanogui/layout.h>
 
 #ifdef HAVE_LIBARCHIVE
-#include "ftl/snapshot.hpp"
+#include "ftl/rgbd/snapshot.hpp"
 #endif
 
 using ftl::gui::SourceWindow;
-using ftl::rgbd::RGBDSource;
+using ftl::rgbd::Source;
 using std::string;
 
 class GLTexture {
@@ -84,7 +84,7 @@ class VirtualCameraView : public nanogui::ImageView {
 		depth_ = false;
 	}
 
-	void setSource(RGBDSource *src) { src_ = src; }
+	void setSource(Source *src) { src_ = src; }
 
 	bool mouseButtonEvent(const nanogui::Vector2i &p, int button, bool down, int modifiers) {
 		//LOG(INFO) << "Mouse move: " << p[0];
@@ -118,7 +118,7 @@ class VirtualCameraView : public nanogui::ImageView {
 
 			src_->setPose(viewPose);
 			src_->grab();
-			src_->getRGBD(rgb, depth);
+			src_->getFrames(rgb, depth);
 
 			if (depth_) {
 				if (depth.rows > 0) {
@@ -143,7 +143,7 @@ class VirtualCameraView : public nanogui::ImageView {
 	void setDepth(bool d) { depth_ = d; }
 
 	private:
-	RGBDSource *src_;
+	Source *src_;
 	GLTexture texture_;
 	Eigen::Vector3f eye_;
 	Eigen::Vector3f centre_;
@@ -159,7 +159,7 @@ SourceWindow::SourceWindow(nanogui::Widget *parent, ftl::ctrl::Master *ctrl)
 
 	using namespace nanogui;
 
-    src_ = ftl::create<ftl::rgbd::NetSource>(ctrl->getRoot(), "source", ctrl->getNet());
+    src_ = ftl::create<Source>(ctrl->getRoot(), "source", ctrl->getNet());
 
 	Widget *tools = new Widget(this);
         tools->setLayout(new BoxLayout(Orientation::Horizontal,
@@ -193,13 +193,13 @@ SourceWindow::SourceWindow(nanogui::Widget *parent, ftl::ctrl::Master *ctrl)
 			std::strftime(timestamp, sizeof(timestamp), "%F-%H%M%S", std::localtime(&t));
 			auto writer = ftl::rgbd::SnapshotWriter(std::string(timestamp) + ".tar.gz");
 			cv::Mat rgb, depth;
-			this->src_->getRGBD(rgb, depth);
+			this->src_->getFrames(rgb, depth);
 			if (!writer.addCameraRGBD(
 					"0", // TODO
 					rgb,
 					depth,
 					this->src_->getPose(),
-					this->src_->getParameters()
+					this->src_->parameters()
 				)) {
 				LOG(ERROR) << "Snapshot failed";
 			}
diff --git a/applications/gui/src/src_window.hpp b/applications/gui/src/src_window.hpp
index bba8f9bfa..4b92f2e1f 100644
--- a/applications/gui/src/src_window.hpp
+++ b/applications/gui/src/src_window.hpp
@@ -4,7 +4,7 @@
 #include <nanogui/window.h>
 #include <ftl/master.hpp>
 #include <ftl/uuid.hpp>
-#include <ftl/net_source.hpp>
+#include <ftl/rgbd/source.hpp>
 #include <vector>
 #include <string>
 
@@ -23,7 +23,7 @@ class SourceWindow : public nanogui::Window {
 
 	private:
 	ftl::ctrl::Master *ctrl_;
-	ftl::rgbd::NetSource *src_;
+	ftl::rgbd::Source *src_;
 	VirtualCameraView *image_;
 	std::vector<std::string> available_;
 
diff --git a/applications/reconstruct/include/ftl/depth_camera_params.hpp b/applications/reconstruct/include/ftl/depth_camera_params.hpp
index f425ccf13..bf4263b9b 100644
--- a/applications/reconstruct/include/ftl/depth_camera_params.hpp
+++ b/applications/reconstruct/include/ftl/depth_camera_params.hpp
@@ -6,7 +6,7 @@
 #include <cuda_runtime.h>
 
 #include <ftl/cuda_matrix_util.hpp>
-#include <ftl/camera_params.hpp>
+#include <ftl/rgbd/camera.hpp>
 
 struct __align__(16) DepthCameraParams {
 	float fx;
diff --git a/applications/reconstruct/include/ftl/registration.hpp b/applications/reconstruct/include/ftl/registration.hpp
index e5375dfe0..be5154f30 100644
--- a/applications/reconstruct/include/ftl/registration.hpp
+++ b/applications/reconstruct/include/ftl/registration.hpp
@@ -28,12 +28,12 @@ Eigen::Matrix4f findTransformation(	std::vector<pcl::PointCloud<pcl::PointXYZ>::
 
 
 /** @brief Convert chessboard corners found with OpenCV's findChessboardCorners to PCL point cloud. */
-pcl::PointCloud<pcl::PointXYZ>::Ptr cornersToPointCloud(const std::vector<cv::Point2f> &corners, const cv::Mat &disp, const ftl::rgbd::CameraParameters &p);
+pcl::PointCloud<pcl::PointXYZ>::Ptr cornersToPointCloud(const std::vector<cv::Point2f> &corners, const cv::Mat &disp, const ftl::rgbd::Camera &p);
 
 /** @brief 	Find chessboard corners from image and store them in PCL PointCloud.
  * 	@note	Corners will be drawn in rgb.
  */
-bool findChessboardCorners(cv::Mat &rgb, const cv::Mat &depth, const ftl::rgbd::CameraParameters &p, const cv::Size pattern_size, pcl::PointCloud<pcl::PointXYZ>::Ptr &out, float error_threshold);
+bool findChessboardCorners(cv::Mat &rgb, const cv::Mat &depth, const ftl::rgbd::Camera &p, const cv::Size pattern_size, pcl::PointCloud<pcl::PointXYZ>::Ptr &out, float error_threshold);
 
 /**
  * @brief	Abstract class for registration
@@ -45,7 +45,7 @@ bool findChessboardCorners(cv::Mat &rgb, const cv::Mat &depth, const ftl::rgbd::
 class Registration : public ftl::Configurable {
 public:
 	explicit Registration(nlohmann::json &config);
-	void addSource(ftl::rgbd::RGBDSource* source);
+	void addSource(ftl::rgbd::Source* source);
 	size_t getSourcesCount() { return sources_.size(); }
 
 	/**
@@ -75,11 +75,11 @@ public:
 	virtual bool findTransformations(std::map<std::string, Eigen::Matrix4f> &data);
 
 protected:
-	ftl::rgbd::RGBDSource* getSource(size_t idx);
+	ftl::rgbd::Source* getSource(size_t idx);
 
 	bool isTargetSourceSet();
 	bool isTargetSourceFound();
-	bool isTargetSource(ftl::rgbd::RGBDSource* source); 
+	bool isTargetSource(ftl::rgbd::Source* source); 
 	bool isTargetSource(size_t idx); 
 	
 	/**
@@ -124,13 +124,13 @@ protected:
 	 * 			always have same idx. Implementations may choose to ignore it.
 	 * @return	True/false if feature was found. Used to build adjacency matrix.
 	 */
-	virtual bool findFeatures(ftl::rgbd::RGBDSource* source, size_t idx)=0;
+	virtual bool findFeatures(ftl::rgbd::Source* source, size_t idx)=0;
 
 	std::vector<std::vector<bool>> visibility_; /*< Adjacency matrix for sources (feature visibility). */
 
 private:
 	std::optional<std::string> target_source_; /*< Reference coordinate system for transformations. */
-	std::vector<ftl::rgbd::RGBDSource*> sources_;
+	std::vector<ftl::rgbd::Source*> sources_;
 };
 
 /**
@@ -173,7 +173,7 @@ public:
 	bool findTransformations(std::vector<Eigen::Matrix4f> &data) override;
 
 protected:
-	bool findFeatures(ftl::rgbd::RGBDSource* source, size_t idx) override;
+	bool findFeatures(ftl::rgbd::Source* source, size_t idx) override;
 	bool processData() override;
 	cv::Size pattern_size_;
 	std::vector<std::vector<std::optional<pcl::PointCloud<pcl::PointXYZ>::Ptr>>> data_;
diff --git a/applications/reconstruct/include/ftl/scene_rep_hash_sdf.hpp b/applications/reconstruct/include/ftl/scene_rep_hash_sdf.hpp
index 5da37d479..09fd3d1a7 100644
--- a/applications/reconstruct/include/ftl/scene_rep_hash_sdf.hpp
+++ b/applications/reconstruct/include/ftl/scene_rep_hash_sdf.hpp
@@ -337,7 +337,7 @@ private:
 
 		//t.startEvent("compactifyAllInOne");
 		m_hashParams.m_numOccupiedBlocks = compactifyHashAllInOneCUDA(m_hashData, m_hashParams);		//this version uses atomics over prefix sums, which has a much better performance
-		//std::cout << "Occ blocks = " << m_hashParams.m_numOccupiedBlocks << std::endl;
+		std::cout << "Occ blocks = " << m_hashParams.m_numOccupiedBlocks << std::endl;
 		m_hashData.updateParams(m_hashParams);	//make sure numOccupiedBlocks is updated on the GPU
 		//t.endEvent();
 		//t.evaluate();
diff --git a/applications/reconstruct/include/ftl/virtual_source.hpp b/applications/reconstruct/include/ftl/virtual_source.hpp
index aed3dee50..ff1a89d78 100644
--- a/applications/reconstruct/include/ftl/virtual_source.hpp
+++ b/applications/reconstruct/include/ftl/virtual_source.hpp
@@ -2,7 +2,7 @@
 #ifndef _FTL_RGBD_VIRTUAL_HPP_
 #define _FTL_RGBD_VIRTUAL_HPP_
 
-#include <ftl/rgbd_source.hpp>
+#include <ftl/rgbd/source.hpp>
 
 class CUDARayCastSDF;
 
@@ -19,21 +19,17 @@ namespace rgbd {
  * calculating disparity, before converting to depth.  Calibration of the images
  * is also performed.
  */
-class VirtualSource : public RGBDSource {
+class VirtualSource : public ftl::rgbd::detail::Source {
 	public:
-	VirtualSource(nlohmann::json &config, ftl::net::Universe *net);
+	VirtualSource(ftl::rgbd::Source*);
 	~VirtualSource();
 
 	void setScene(ftl::voxhash::SceneRep *);
 
-	void grab();
-	void getRGBD(cv::Mat &rgb, cv::Mat &depth);
+	bool grab();
+	//void getRGBD(cv::Mat &rgb, cv::Mat &depth);
 	bool isReady();
 
-	static inline RGBDSource *create(nlohmann::json &config, ftl::net::Universe *net) {
-		return new VirtualSource(config, net);
-	}
-
 	private:
 	ftl::voxhash::SceneRep *scene_;
 	CUDARayCastSDF *rays_;
diff --git a/applications/reconstruct/src/main.cpp b/applications/reconstruct/src/main.cpp
index f30080957..5ff41ebe4 100644
--- a/applications/reconstruct/src/main.cpp
+++ b/applications/reconstruct/src/main.cpp
@@ -12,7 +12,7 @@
 #include <ftl/scene_rep_hash_sdf.hpp>
 #include <ftl/rgbd.hpp>
 #include <ftl/virtual_source.hpp>
-#include <ftl/rgbd_streamer.hpp>
+#include <ftl/rgbd/streamer.hpp>
 
 // #include <zlib.h>
 // #include <lz4.h>
@@ -50,7 +50,7 @@ using ftl::net::Universe;
 using ftl::rgbd::Display;
 using std::string;
 using std::vector;
-using ftl::rgbd::RGBDSource;
+using ftl::rgbd::Source;
 using ftl::config::json_t;
 
 using json = nlohmann::json;
@@ -67,7 +67,7 @@ using ftl::registration::loadTransformations;
 using ftl::registration::saveTransformations;
 
 struct Cameras {
-	RGBDSource *source;
+	Source *source;
 	DepthCameraData gpu;
 	DepthCameraParams params;
 };
@@ -76,36 +76,21 @@ static void run(ftl::Configurable *root) {
 	Universe *net = ftl::create<Universe>(root, "net");
 	
 	net->start();
-	net->waitConnections();
+	//net->waitConnections();
 	
 	std::vector<Cameras> inputs;
-	auto sources = root->get<vector<json_t>>("sources");
+	auto sources = ftl::createArray<Source>(root, "sources", net); //root->get<vector<json_t>>("sources");
 
-	if (!sources) {
+	if (sources.size() == 0) {
 		LOG(ERROR) << "No sources configured!";
 		return;
 	}
 
-	// TODO Allow for non-net source types
-	for (auto &src : *sources) {
-		RGBDSource *in = ftl::rgbd::RGBDSource::create(src, net);
-		if (!in) {
-			LOG(ERROR) << "Unrecognized source: " << src;
-		} else {
-			auto &cam = inputs.emplace_back();
-			cam.source = in;
-			cam.params.fx = in->getParameters().fx;
-			cam.params.fy = in->getParameters().fy;
-			cam.params.mx = -in->getParameters().cx;
-			cam.params.my = -in->getParameters().cy;
-			cam.params.m_imageWidth = in->getParameters().width;
-			cam.params.m_imageHeight = in->getParameters().height;
-			cam.params.m_sensorDepthWorldMax = in->getParameters().maxDepth;
-			cam.params.m_sensorDepthWorldMin = in->getParameters().minDepth;
-			cam.gpu.alloc(cam.params);
-			
-			LOG(INFO) << (string) src["uri"] << " loaded " << cam.params.fx;
-		}
+	for (int i=0; i<sources.size(); i++) {
+		Source *in = sources[i];
+		auto &cam = inputs.emplace_back();
+		cam.source = in;
+		cam.params.m_imageWidth = 0;
 	}
 
 	// TODO	move this block in its own method and add automated tests
@@ -115,6 +100,7 @@ static void run(ftl::Configurable *root) {
 	if (!merge) {
 		LOG(WARNING) << "Input merging not configured, using only first input in configuration";
 		inputs = { inputs[0] };
+		inputs[0].source->setPose(Eigen::Matrix4f::Identity());
 	}
 
 	if (inputs.size() > 1) {
@@ -171,9 +157,13 @@ static void run(ftl::Configurable *root) {
 	for (auto &input : inputs) { LOG(INFO) << "    " + (string) input.source->getURI(); }
 	
 	ftl::rgbd::Display *display = ftl::create<ftl::rgbd::Display>(root, "display");
-	ftl::rgbd::VirtualSource *virt = ftl::create<ftl::rgbd::VirtualSource>(root, "virtual", net);
+	ftl::rgbd::Source *virt = ftl::create<ftl::rgbd::Source>(root, "virtual", net);
+
+	auto virtimpl = new ftl::rgbd::VirtualSource(virt);
+	virt->customImplementation(virtimpl);
+
 	ftl::voxhash::SceneRep *scene = ftl::create<ftl::voxhash::SceneRep>(root, "voxelhash");
-	virt->setScene(scene);
+	virtimpl->setScene(scene);
 	display->setSource(virt);
 
 	ftl::rgbd::Streamer *stream = ftl::create<ftl::rgbd::Streamer>(root, "stream", net);
@@ -192,7 +182,12 @@ static void run(ftl::Configurable *root) {
 	});
 
 	int active = inputs.size();
-	while (active > 0 && display->active()) {
+	while (ftl::running && display->active()) {
+		if (active == 0) {
+			LOG(INFO) << "Waiting for sources...";
+			sleep_for(milliseconds(1000));
+		}
+
 		active = 0;
 
 		if (!paused) {
@@ -200,11 +195,34 @@ static void run(ftl::Configurable *root) {
 			scene->nextFrame();
 		
 			for (size_t i = 0; i < inputs.size(); i++) {
+				if (!inputs[i].source->isReady()) {
+					inputs[i].params.m_imageWidth = 0;
+					// TODO(Nick) : Free gpu allocs if was ready before
+					continue;
+				} else {
+					auto &cam = inputs[i];
+					auto in = inputs[i].source;
+					if (cam.params.m_imageWidth == 0) {
+						LOG(INFO) << "SETTING UP CAM PARAMS: " << in->parameters().fx;
+						cam.params.fx = in->parameters().fx;
+						cam.params.fy = in->parameters().fy;
+						cam.params.mx = -in->parameters().cx;
+						cam.params.my = -in->parameters().cy;
+						cam.params.m_imageWidth = in->parameters().width;
+						cam.params.m_imageHeight = in->parameters().height;
+						cam.params.m_sensorDepthWorldMax = in->parameters().maxDepth;
+						cam.params.m_sensorDepthWorldMin = in->parameters().minDepth;
+						cam.gpu.alloc(cam.params);
+					}
+					
+					//LOG(INFO) << in->getURI() << " loaded " << cam.params.fx;
+				}
+
 				// Get the RGB-Depth frame from input
-				RGBDSource *input = inputs[i].source;
+				Source *input = inputs[i].source;
 				Mat rgb, depth;
 				input->grab();
-				input->getRGBD(rgb,depth);
+				input->getFrames(rgb,depth);
 				
 				active += 1;
 
diff --git a/applications/reconstruct/src/registration.cpp b/applications/reconstruct/src/registration.cpp
index 370fcf59d..1d61e4c06 100644
--- a/applications/reconstruct/src/registration.cpp
+++ b/applications/reconstruct/src/registration.cpp
@@ -25,8 +25,8 @@
 namespace ftl {
 namespace registration {
 
-using ftl::rgbd::CameraParameters;
-using ftl::rgbd::RGBDSource;
+using ftl::rgbd::Camera;
+using ftl::rgbd::Source;
 
 using std::string;
 using std::vector;
@@ -132,7 +132,7 @@ float fitPlaneError(PointCloud<PointXYZ>::Ptr cloud_in, float distance_threshold
 }
 
 //template<typename T = PointXYZ> typename
-PointCloud<PointXYZ>::Ptr cornersToPointCloud(const vector<cv::Point2f> &corners, const Mat &depth, const CameraParameters &p) {
+PointCloud<PointXYZ>::Ptr cornersToPointCloud(const vector<cv::Point2f> &corners, const Mat &depth, const Camera &p) {
 	
 	int corners_len = corners.size();
 	vector<cv::Vec3f> points(corners_len);
@@ -170,7 +170,7 @@ PointCloud<PointXYZ>::Ptr cornersToPointCloud(const vector<cv::Point2f> &corners
 	return cloud;
 }
 
-bool findChessboardCorners(Mat &rgb, const Mat &depth, const CameraParameters &p, const cv::Size pattern_size, PointCloud<PointXYZ>::Ptr &out, float error_threshold) {
+bool findChessboardCorners(Mat &rgb, const Mat &depth, const Camera &p, const cv::Size pattern_size, PointCloud<PointXYZ>::Ptr &out, float error_threshold) {
 	vector<cv::Point2f> corners(pattern_size.width * pattern_size.height);
 
 #if CV_VERSION_MAJOR >= 4
@@ -257,7 +257,7 @@ Registration::Registration(nlohmann::json &config) :
 	}
 }
 
-RGBDSource* Registration::getSource(size_t idx) {
+Source* Registration::getSource(size_t idx) {
 	return sources_[idx];
 }
 
@@ -266,14 +266,14 @@ bool Registration::isTargetSourceSet() {
 }
 
 bool Registration::isTargetSourceFound() {
-	for (RGBDSource* source : sources_ ) {
+	for (Source* source : sources_ ) {
 		if (isTargetSource(source)) return true;
 	}
 	return false;
 }
 
-bool Registration::isTargetSource(RGBDSource *source) {
-	if (target_source_) { return source->getURI() == *target_source_; }
+bool Registration::isTargetSource(Source *source) {
+	if (target_source_) { return source->getID() == *target_source_; }
 	return false;
 }
 
@@ -291,7 +291,7 @@ size_t Registration::getTargetSourceIdx() {
 	return 0;
 }
 
-void Registration::addSource(RGBDSource *source) {
+void Registration::addSource(Source *source) {
 	// TODO: check that source is not already included
 	sources_.push_back(source);
 }
@@ -390,7 +390,7 @@ bool Registration::findTransformations(map<string, Matrix4f> &data) {
 
 	if (!findTransformations(T)) return false;
 	for (size_t i = 0; i < sources_.size(); ++i) {
-		data[sources_[i]->getURI()] = T[i];
+		data[sources_[i]->getID()] = T[i];
 	}
 	return true;
 }
@@ -438,31 +438,31 @@ void ChessboardRegistration::run() {
 
 	// TODO: Move GUI elsewhere. Also applies to processData() and findFeatures()
 	for (size_t i = 0; i < getSourcesCount(); ++i) { 
-		cv::namedWindow("Registration: " + getSource(i)->getURI(),
+		cv::namedWindow("Registration: " + getSource(i)->getID(),
 						cv::WINDOW_KEEPRATIO|cv::WINDOW_NORMAL);
 	}
 
 	Registration::run();
 
 	for (size_t i = 0; i < getSourcesCount(); ++i) { 
-		cv::destroyWindow("Registration: " + getSource(i)->getURI());
+		cv::destroyWindow("Registration: " + getSource(i)->getID());
 	}
 }
 
-bool ChessboardRegistration::findFeatures(RGBDSource *source, size_t idx) {
+bool ChessboardRegistration::findFeatures(Source *source, size_t idx) {
 	optional<PointCloud<PointXYZ>::Ptr> result;
 	PointCloud<PointXYZ>::Ptr cloud(new PointCloud<PointXYZ>);
 
 	Mat rgb, depth;
-	source->getRGBD(rgb, depth);
+	source->getFrames(rgb, depth);
 
-	bool retval = findChessboardCorners(rgb, depth, source->getParameters(), pattern_size_, cloud, error_threshold_);
+	bool retval = findChessboardCorners(rgb, depth, source->parameters(), pattern_size_, cloud, error_threshold_);
 	if (retval) {
 		result.emplace(cloud);
 	}
 	data_[idx].push_back(result);
 	
-	cv::imshow("Registration: " + source->getURI(), rgb);
+	cv::imshow("Registration: " + source->getID(), rgb);
 
 	return retval;
 }
@@ -546,11 +546,11 @@ bool ChessboardRegistrationChain::findTransformations(vector<Matrix4f> &data) {
 	for (vector<pair<size_t, size_t>> level : edges_) {
 		for (pair<size_t, size_t> edge : level) {
 			LOG(INFO) 	<< "Registering source "
-						<< getSource(edge.second)->getURI() << " to source"
-						<< getSource(edge.first)->getURI();
+						<< getSource(edge.second)->getID() << " to source"
+						<< getSource(edge.first)->getID();
 			
 			nlohmann::json conf(config_);
-			conf["targetsource"] = getSource(edge.first)->getURI();
+			conf["targetsource"] = getSource(edge.first)->getID();
 			conf["chain"] = false;
 
 			vector<Matrix4f> result;
diff --git a/applications/reconstruct/src/virtual_source.cpp b/applications/reconstruct/src/virtual_source.cpp
index ecaec6d2f..072f71cb5 100644
--- a/applications/reconstruct/src/virtual_source.cpp
+++ b/applications/reconstruct/src/virtual_source.cpp
@@ -10,19 +10,19 @@ using ftl::rgbd::VirtualSource;
 using std::mutex;
 using std::unique_lock;
 
-VirtualSource::VirtualSource(nlohmann::json &config, ftl::net::Universe *net)
-		: RGBDSource(config, net) {
-	rays_ = new CUDARayCastSDF(config);
+VirtualSource::VirtualSource(ftl::rgbd::Source *host)
+		: ftl::rgbd::detail::Source(host) {
+	rays_ = ftl::create<CUDARayCastSDF>(host, "raycaster"); //new CUDARayCastSDF(host->getConfig());
 	scene_ = nullptr;
 
-	params_.fx = config.value("focal", 430.0f);
+	params_.fx = rays_->value("focal", 430.0f);
 	params_.fy = params_.fx;
-	params_.width = config.value("width", 640);
-	params_.height = config.value("height", 480);
+	params_.width = rays_->value("width", 640);
+	params_.height = rays_->value("height", 480);
 	params_.cx = params_.width / 2;
 	params_.cy = params_.height / 2;
-	params_.maxDepth = config.value("max_depth", 10.0f);
-	params_.minDepth = config.value("min_depth", 0.1f);
+	params_.maxDepth = rays_->value("max_depth", 10.0f);
+	params_.minDepth = rays_->value("min_depth", 0.1f);
 
 	rgb_ = cv::Mat(cv::Size(params_.width,params_.height), CV_8UC3);
 	idepth_ = cv::Mat(cv::Size(params_.width,params_.height), CV_32SC1);
@@ -37,7 +37,7 @@ void VirtualSource::setScene(ftl::voxhash::SceneRep *scene) {
 	scene_ = scene;
 }
 
-void VirtualSource::grab() {
+bool VirtualSource::grab() {
 	if (scene_) {
 		DepthCameraParams params;
 		params.fx = params_.fx;
@@ -49,12 +49,13 @@ void VirtualSource::grab() {
 		params.m_sensorDepthWorldMin = params_.minDepth;
 		params.m_sensorDepthWorldMax = params_.maxDepth;
 
-		rays_->render(scene_->getHashData(), scene_->getHashParams(), params, getPose());
+		rays_->render(scene_->getHashData(), scene_->getHashParams(), params, host_->getPose());
 
-		unique_lock<mutex> lk(mutex_);
+		//unique_lock<mutex> lk(mutex_);
 		rays_->getRayCastData().download((int*)idepth_.data, (uchar3*)rgb_.data, rays_->getRayCastParams());
 		idepth_.convertTo(depth_, CV_32FC1, 1.0f / 100.0f);
 	}
+	return true;
 }
 
 bool VirtualSource::isReady() {
diff --git a/applications/vision/src/main.cpp b/applications/vision/src/main.cpp
index 9a49c9c25..620ebd738 100644
--- a/applications/vision/src/main.cpp
+++ b/applications/vision/src/main.cpp
@@ -22,7 +22,7 @@
 #include <ftl/rgbd.hpp>
 #include <ftl/middlebury.hpp>
 #include <ftl/display.hpp>
-#include <ftl/rgbd_streamer.hpp>
+#include <ftl/rgbd/streamer.hpp>
 #include <ftl/net/universe.hpp>
 #include <ftl/slave.hpp>
 #include <nlohmann/json.hpp>
@@ -36,9 +36,8 @@
 #pragma comment(lib, "Rpcrt4.lib")
 #endif
 
-using ftl::rgbd::RGBDSource;
-using ftl::rgbd::CameraParameters;
-using ftl::rgbd::StereoVideoSource;
+using ftl::rgbd::Source;
+using ftl::rgbd::Camera;
 using ftl::Display;
 using ftl::rgbd::Streamer;
 using ftl::net::Universe;
@@ -87,8 +86,10 @@ static void run(ftl::Configurable *root) {
 	string file = "";
 	if (paths && (*paths).size() > 0) file = (*paths)[0];
 
-	StereoVideoSource *source = nullptr;
-	source = ftl::create<StereoVideoSource>(root, "source", file);
+	Source *source = nullptr;
+	source = ftl::create<Source>(root, "source");
+
+	if (file != "") source->set("uri", file);
 	
 	Display *display = ftl::create<Display>(root, "display", "local");
 	
@@ -101,8 +102,8 @@ static void run(ftl::Configurable *root) {
 
 	while (ftl::running && display->active()) {
 		cv::Mat rgb, depth;
-		source->getRGBD(rgb, depth);
-		if (!rgb.empty()) display->render(rgb, depth, source->getParameters());
+		source->getFrames(rgb, depth);
+		if (!rgb.empty()) display->render(rgb, depth, source->parameters());
 		display->wait(10);
 	}
 
@@ -113,7 +114,7 @@ static void run(ftl::Configurable *root) {
 
 	delete stream;
 	delete display;
-	delete source;
+	//delete source;  // TODO(Nick) Add ftl::destroy
 	delete net;
 }
 
diff --git a/components/common/cpp/include/ftl/config.h.in b/components/common/cpp/include/ftl/config.h.in
index 67dc859e6..779918c14 100644
--- a/components/common/cpp/include/ftl/config.h.in
+++ b/components/common/cpp/include/ftl/config.h.in
@@ -30,6 +30,8 @@ extern const int FTL_VERSION_PATCH;
 extern const int FTL_VERSION_COMMITS;
 extern const char *FTL_VERSION_SHA1;
 
+#define FTL_SOURCE_DIRECTORY "@CMAKE_SOURCE_DIR@"
+
 #define FTL_LOCAL_CONFIG_ROOT @FTL_LOCAL_CONFIG_ROOT@
 #define FTL_LOCAL_CACHE_ROOT @FTL_LOCAL_CACHE_ROOT@
 #define FTL_LOCAL_DATA_ROOT @FTL_LOCAL_DATA_ROOT@
diff --git a/components/common/cpp/include/ftl/configurable.hpp b/components/common/cpp/include/ftl/configurable.hpp
index 092fc1493..7999bcfa8 100644
--- a/components/common/cpp/include/ftl/configurable.hpp
+++ b/components/common/cpp/include/ftl/configurable.hpp
@@ -60,6 +60,8 @@ class Configurable {
 	template <typename T>
 	std::optional<T> get(const std::string &name);
 
+	std::string getID() { return *get<std::string>("$id"); }
+
 	/**
 	 * Get a configuration property, but return a default if not found.
 	 */
diff --git a/components/common/cpp/include/ftl/configuration.hpp b/components/common/cpp/include/ftl/configuration.hpp
index fd21c63cd..9a01b56b3 100644
--- a/components/common/cpp/include/ftl/configuration.hpp
+++ b/components/common/cpp/include/ftl/configuration.hpp
@@ -31,6 +31,8 @@ std::optional<std::string> locateFile(const std::string &name);
 
 Configurable *configure(int argc, char **argv, const std::string &root);
 
+Configurable *configure(json_t &);
+
 /**
  * Change a configuration value based upon a URI. Return true if changed,
  * false if it was not able to change.
@@ -84,8 +86,13 @@ T *create(ftl::Configurable *parent, const std::string &name, ARGS ...args);
  * Create a configurable rooted on a parent but with a specific object
  * that is not directly a child of the parent. Used by RGB-D Factory.
  */
+//template <typename T, typename... ARGS>
+//T *create(ftl::Configurable *parent, json_t &obj, const std::string &name, ARGS ...args);
+
 template <typename T, typename... ARGS>
-T *create(ftl::Configurable *parent, json_t &obj, const std::string &name, ARGS ...args);
+std::vector<T*> createArray(ftl::Configurable *parent, const std::string &name, ARGS ...args);
+
+void destroy(ftl::Configurable *);
 
 void set(const std::string &uri, const nlohmann::json &);
 
@@ -93,6 +100,7 @@ void set(const std::string &uri, const nlohmann::json &);
 
 // Deprecated
 using config::create;
+using config::createArray;
 using config::locateFile;
 using config::configure;
 
@@ -128,8 +136,9 @@ T *ftl::config::create(json_t &link, ARGS ...args) {
 
 template <typename T, typename... ARGS>
 T *ftl::config::create(ftl::Configurable *parent, const std::string &name, ARGS ...args) {
-    //nlohmann::json &entity = ftl::config::resolve(parent->getConfig()[name]);
-    nlohmann::json &entity = (!parent->getConfig()[name].is_null()) ? parent->getConfig()[name] : ftl::config::resolve(parent->getConfig())[name];
+    nlohmann::json &entity = (!parent->getConfig()[name].is_null())
+			? parent->getConfig()[name]
+			: ftl::config::resolve(parent->getConfig())[name];
 
     if (entity.is_object()) {
         if (!entity["$id"].is_string()) {
@@ -164,26 +173,51 @@ T *ftl::config::create(ftl::Configurable *parent, const std::string &name, ARGS
 }
 
 template <typename T, typename... ARGS>
-T *ftl::config::create(ftl::Configurable *parent, json_t &obj, const std::string &name, ARGS ...args) {
-    //nlohmann::json &entity = ftl::config::resolve(parent->getConfig()[name]);
-    nlohmann::json &entity = obj;
+std::vector<T*> ftl::config::createArray(ftl::Configurable *parent, const std::string &name, ARGS ...args) {
+    nlohmann::json &base = (!parent->getConfig()[name].is_null())
+			? parent->getConfig()[name]
+			: ftl::config::resolve(parent->getConfig())[name];
+
+	std::vector<T*> result;
+
+	if (base.is_array()) {
+		for (auto &entity : base) {
+			if (entity.is_object()) {
+				if (!entity["$id"].is_string()) {
+					std::string id_str = *parent->get<std::string>("$id");
+					if (id_str.find('#') != std::string::npos) {
+						entity["$id"] = id_str + std::string("/") + name;
+					} else {
+						entity["$id"] = id_str + std::string("#") + name;
+					}
+				}
+
+				result.push_back(create<T>(entity, args...));
+			} else if (entity.is_null()) {
+				// Must create the object from scratch...
+				std::string id_str = *parent->get<std::string>("$id");
+				if (id_str.find('#') != std::string::npos) {
+					id_str = id_str + std::string("/") + name;
+				} else {
+					id_str = id_str + std::string("#") + name;
+				}
+				parent->getConfig()[name] = {
+					// cppcheck-suppress constStatement
+					{"$id", id_str}
+				};
+
+				nlohmann::json &entity2 = parent->getConfig()[name];
+				result.push_back(create<T>(entity2, args...));
+			}
+		}
+	} else {
+		LOG(WARNING) << "Expected an array for '" << name << "' in " << parent->getID();
+	}
+
+	return result;
+}
 
-    if (entity.is_object()) {
-        if (!entity["$id"].is_string()) {
-            std::string id_str = *parent->get<std::string>("$id");
-            if (id_str.find('#') != std::string::npos) {
-                entity["$id"] = id_str + std::string("/") + name;
-            } else {
-                entity["$id"] = id_str + std::string("#") + name;
-            }
-        }
 
-        return create<T>(entity, args...);
-    } else if (entity.is_null()) {
-        LOG(FATAL) << "Invalid raw object in Configurable construction";
-        return nullptr;
-    }
-}
 
 #endif  // _FTL_COMMON_CONFIGURATION_HPP_
 
diff --git a/components/common/cpp/include/ftl/uri.hpp b/components/common/cpp/include/ftl/uri.hpp
index be6b7fd3e..05325b346 100644
--- a/components/common/cpp/include/ftl/uri.hpp
+++ b/components/common/cpp/include/ftl/uri.hpp
@@ -30,7 +30,8 @@ namespace ftl {
 			SCHEME_WS,
 			SCHEME_IPC,
 			SCHEME_FILE,
-			SCHEME_OTHER
+			SCHEME_OTHER,
+			SCHEME_DEVICE
 		};
 
 		bool isValid() const { return m_valid; };
diff --git a/components/common/cpp/src/configuration.cpp b/components/common/cpp/src/configuration.cpp
index 52e8998f8..af8bbd655 100644
--- a/components/common/cpp/src/configuration.cpp
+++ b/components/common/cpp/src/configuration.cpp
@@ -189,7 +189,7 @@ void ftl::config::registerConfigurable(ftl::Configurable *cfg) {
 	}
 	auto ix = config_instance.find(*uri);
 	if (ix != config_instance.end()) {
-		LOG(ERROR) << "Attempting to create a duplicate object: " << *uri;
+		LOG(FATAL) << "Attempting to create a duplicate object: " << *uri;
 	} else {
 		config_instance[*uri] = cfg;
 		LOG(INFO) << "Registering instance: " << *uri;
@@ -430,6 +430,24 @@ static void signalIntHandler( int signum ) {
    ftl::running = false;
 }
 
+Configurable *ftl::config::configure(ftl::config::json_t &cfg) {
+	loguru::g_preamble_date = false;
+	loguru::g_preamble_uptime = false;
+	loguru::g_preamble_thread = false;
+	int argc = 1;
+	const char *argv[] = {"d",0};
+	loguru::init(argc, const_cast<char**>(argv), "--verbosity");
+
+	config_index.clear();
+	config_instance.clear();
+
+	config = cfg;
+	_indexConfig(config);
+	Configurable *rootcfg = create<Configurable>(config);
+	return rootcfg;
+}
+
+
 Configurable *ftl::config::configure(int argc, char **argv, const std::string &root) {
 	loguru::g_preamble_date = false;
 	loguru::g_preamble_uptime = false;
diff --git a/components/common/cpp/src/loguru.cpp b/components/common/cpp/src/loguru.cpp
index b481a411e..dd71e012a 100644
--- a/components/common/cpp/src/loguru.cpp
+++ b/components/common/cpp/src/loguru.cpp
@@ -533,6 +533,9 @@ namespace loguru
 		CHECK_GT_F(argc,       0,       "Expected proper argc/argv");
 		CHECK_EQ_F(argv[argc], nullptr, "Expected proper argc/argv");
 
+		// Nick: Added to allow for multiple calls to init during tests
+		if (s_argv0_filename.size() > 0) return;
+
 		s_argv0_filename = filename(argv[0]);
 
 		#ifdef _WIN32
diff --git a/components/common/cpp/src/uri.cpp b/components/common/cpp/src/uri.cpp
index ab306786b..fe78c9ffe 100644
--- a/components/common/cpp/src/uri.cpp
+++ b/components/common/cpp/src/uri.cpp
@@ -51,6 +51,8 @@ void URI::_parse(uri_t puri) {
         else if (prototext == "http") m_proto = SCHEME_HTTP;
         else if (prototext == "ws") m_proto = SCHEME_WS;
         else if (prototext == "ipc") m_proto = SCHEME_IPC;
+		else if (prototext == "device") m_proto = SCHEME_DEVICE;
+		else if (prototext == "file") m_proto = SCHEME_FILE;
         else m_proto = SCHEME_OTHER;
         m_protostr = prototext;
 
@@ -91,7 +93,7 @@ void URI::_parse(uri_t puri) {
 			m_frag = std::string(uri.fragment.first, fraglast - uri.fragment.first);
 		}
 
-        m_valid = m_proto != SCHEME_NONE && m_host.size() > 0;
+        m_valid = m_proto != SCHEME_NONE && (m_host.size() > 0 || m_path.size() > 0);
 
         if (m_valid) {
             if (m_qmap.size() > 0) m_base = std::string(uri.scheme.first, uri.query.first - uri.scheme.first - 1);
diff --git a/components/renderers/cpp/include/ftl/display.hpp b/components/renderers/cpp/include/ftl/display.hpp
index bf4eb51f5..2e56c459b 100644
--- a/components/renderers/cpp/include/ftl/display.hpp
+++ b/components/renderers/cpp/include/ftl/display.hpp
@@ -7,7 +7,7 @@
 
 #include <ftl/config.h>
 #include <ftl/configurable.hpp>
-#include "../../../rgbd-sources/include/ftl/camera_params.hpp"
+#include "../../../rgbd-sources/include/ftl/rgbd/camera.hpp"
 
 #include <nlohmann/json.hpp>
 #include <opencv2/opencv.hpp>
@@ -35,7 +35,7 @@ class Display : public ftl::Configurable {
 	explicit Display(nlohmann::json &config, std::string name);
 	~Display();
 	
-	bool render(const cv::Mat &rgb, const cv::Mat &depth, const ftl::rgbd::CameraParameters &p);
+	bool render(const cv::Mat &rgb, const cv::Mat &depth, const ftl::rgbd::Camera &p);
 
 #if defined HAVE_PCL
 	bool render(pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr);
diff --git a/components/renderers/cpp/include/ftl/rgbd_display.hpp b/components/renderers/cpp/include/ftl/rgbd_display.hpp
index 0467030b0..2d0c26a36 100644
--- a/components/renderers/cpp/include/ftl/rgbd_display.hpp
+++ b/components/renderers/cpp/include/ftl/rgbd_display.hpp
@@ -2,7 +2,7 @@
 #define _FTL_RGBD_DISPLAY_HPP_
 
 #include <nlohmann/json.hpp>
-#include <ftl/rgbd_source.hpp>
+#include <ftl/rgbd/source.hpp>
 
 using MouseAction = std::function<void(int, int, int, int)>;
 
@@ -12,10 +12,10 @@ namespace rgbd {
 class Display : public ftl::Configurable {
 	public:
 	explicit Display(nlohmann::json &);
-	Display(nlohmann::json &, RGBDSource *);
+	Display(nlohmann::json &, Source *);
 	~Display();
 
-	void setSource(RGBDSource *src) { source_ = src; }
+	void setSource(Source *src) { source_ = src; }
 	void update();
 
 	bool active() const { return active_; }
@@ -25,7 +25,7 @@ class Display : public ftl::Configurable {
 	void wait(int ms);
 
 	private:
-	RGBDSource *source_;
+	Source *source_;
 	std::string name_;
 	std::vector<std::function<void(int)>> key_handlers_;
 	Eigen::Vector3f eye_;
diff --git a/components/renderers/cpp/src/display.cpp b/components/renderers/cpp/src/display.cpp
index 712590d80..4a7d88e44 100644
--- a/components/renderers/cpp/src/display.cpp
+++ b/components/renderers/cpp/src/display.cpp
@@ -93,7 +93,7 @@ Display::~Display() {
 /**
  * Convert an OpenCV RGB and Depth Mats to a PCL XYZRGB point cloud.
  */
-static pcl::PointCloud<pcl::PointXYZRGB>::Ptr rgbdToPointXYZ(const cv::Mat &rgb, const cv::Mat &depth, const ftl::rgbd::CameraParameters &p) {
+static pcl::PointCloud<pcl::PointXYZRGB>::Ptr rgbdToPointXYZ(const cv::Mat &rgb, const cv::Mat &depth, const ftl::rgbd::Camera &p) {
 	const double CX = p.cx;
 	const double CY = p.cy;
 	const double FX = p.fx;
@@ -129,7 +129,7 @@ static pcl::PointCloud<pcl::PointXYZRGB>::Ptr rgbdToPointXYZ(const cv::Mat &rgb,
 }
 #endif  // HAVE_PCL
 
-bool Display::render(const cv::Mat &rgb, const cv::Mat &depth, const ftl::rgbd::CameraParameters &p) {
+bool Display::render(const cv::Mat &rgb, const cv::Mat &depth, const ftl::rgbd::Camera &p) {
 	Mat idepth;
 
 	if (value("points", false) && rgb.rows != 0) {
diff --git a/components/renderers/cpp/src/rgbd_display.cpp b/components/renderers/cpp/src/rgbd_display.cpp
index d8f588ad1..4d31132e2 100644
--- a/components/renderers/cpp/src/rgbd_display.cpp
+++ b/components/renderers/cpp/src/rgbd_display.cpp
@@ -1,7 +1,7 @@
 #include <ftl/rgbd_display.hpp>
 #include <opencv2/opencv.hpp>
 
-using ftl::rgbd::RGBDSource;
+using ftl::rgbd::Source;
 using ftl::rgbd::Display;
 using std::string;
 using cv::Mat;
@@ -48,7 +48,7 @@ Display::Display(nlohmann::json &config) : ftl::Configurable(config) {
 	init();
 }
 
-Display::Display(nlohmann::json &config, RGBDSource *source)
+Display::Display(nlohmann::json &config, Source *source)
 		: ftl::Configurable(config) {
 	name_ = config.value("name", string("View [")+std::to_string(viewcount__)+string("]"));
 	viewcount__++;
@@ -122,8 +122,8 @@ void Display::update() {
 	source_->setPose(viewPose);
 
 	Mat rgb, depth;
-	//source_->grab();
-	source_->getRGBD(rgb, depth);
+	source_->grab();
+	source_->getFrames(rgb, depth);
 	if (rgb.rows > 0) cv::imshow(name_, rgb);
 	wait(1);
 }
diff --git a/components/rgbd-sources/CMakeLists.txt b/components/rgbd-sources/CMakeLists.txt
index d1326ec16..37b7d0606 100644
--- a/components/rgbd-sources/CMakeLists.txt
+++ b/components/rgbd-sources/CMakeLists.txt
@@ -2,14 +2,14 @@ set(RGBDSRC
 	src/calibrate.cpp
 	src/local.cpp
 	src/disparity.cpp
-	src/rgbd_source.cpp
-	src/stereovideo_source.cpp
-	src/net_source.cpp
-	src/rgbd_streamer.cpp
+	src/source.cpp
+	src/stereovideo.cpp
+	src/net.cpp
+	src/streamer.cpp
 	src/algorithms/rtcensus.cpp
-	src/algorithms/rtcensus_sgm.cpp
-	src/algorithms/opencv_sgbm.cpp
-	src/algorithms/opencv_bm.cpp
+#	src/algorithms/rtcensus_sgm.cpp
+#	src/algorithms/opencv_sgbm.cpp
+#	src/algorithms/opencv_bm.cpp
 )
 
 if (LibArchive_FOUND)
@@ -25,15 +25,16 @@ endif (LIBSGM_FOUND)
 
 if (CUDA_FOUND)
 	list(APPEND RGBDSRC
-		"src/algorithms/opencv_cuda_bm.cpp"
-		"src/algorithms/opencv_cuda_bp.cpp"
+#		"src/algorithms/opencv_cuda_bm.cpp"
+#		"src/algorithms/opencv_cuda_bp.cpp"
 		"src/algorithms/rtcensus.cu"
-		"src/algorithms/rtcensus_sgm.cu"
+#		"src/algorithms/rtcensus_sgm.cu"
 		"src/algorithms/consistency.cu"
 		"src/algorithms/sparse_census.cu"
 		"src/algorithms/tex_filter.cu"
-		"src/algorithms/nick1.cu"
-		"src/algorithms/nick.cpp")
+#		"src/algorithms/nick1.cu"
+#		"src/algorithms/nick.cpp")
+)
 endif (CUDA_FOUND)
 
 add_library(ftlrgbd ${RGBDSRC})
@@ -51,6 +52,7 @@ set_property(TARGET ftlrgbd PROPERTY CUDA_SEPARABLE_COMPILATION OFF)
 endif()
 
 #target_include_directories(cv-node PUBLIC ${PROJECT_SOURCE_DIR}/include)
-target_link_libraries(ftlrgbd ftlcommon Threads::Threads ${OpenCV_LIBS} ${LIBSGM_LIBRARIES} ${CUDA_LIBRARIES} Eigen3::Eigen glog::glog ftlnet ${LibArchive_LIBRARIES})
+target_link_libraries(ftlrgbd ftlcommon ${OpenCV_LIBS} ${LIBSGM_LIBRARIES} ${CUDA_LIBRARIES} Eigen3::Eigen ftlnet ${LibArchive_LIBRARIES})
 
+add_subdirectory(test)
 
diff --git a/components/rgbd-sources/include/ftl/rgbd.hpp b/components/rgbd-sources/include/ftl/rgbd.hpp
index 774ebfe67..37c7a3b55 100644
--- a/components/rgbd-sources/include/ftl/rgbd.hpp
+++ b/components/rgbd-sources/include/ftl/rgbd.hpp
@@ -2,14 +2,6 @@
 #ifndef _FTL_RGBD_HPP_
 #define _FTL_RGBD_HPP_
 
-#include <ftl/rgbd_source.hpp>
-#include <ftl/rgbdimage_source.hpp>
-#include <ftl/stereoimage_source.hpp>
-#include <ftl/stereovideo_source.hpp>
-#include <ftl/net_source.hpp>
-
-#ifdef HAVE_LIBARCHIVE
-#include <ftl/snapshot_source.hpp>
-#endif // HAVE_LIBARCHIVE
+#include <ftl/rgbd/source.hpp>
 
 #endif  // _FTL_RGBD_HPP_
diff --git a/components/rgbd-sources/include/ftl/camera_params.hpp b/components/rgbd-sources/include/ftl/rgbd/camera.hpp
similarity index 91%
rename from components/rgbd-sources/include/ftl/camera_params.hpp
rename to components/rgbd-sources/include/ftl/rgbd/camera.hpp
index 40f64a1ed..3f4614887 100644
--- a/components/rgbd-sources/include/ftl/camera_params.hpp
+++ b/components/rgbd-sources/include/ftl/rgbd/camera.hpp
@@ -5,7 +5,7 @@
 namespace ftl{
 namespace rgbd {
 
-struct CameraParameters {
+struct Camera {
 	double fx;
 	double fy;
 	double cx;
diff --git a/components/rgbd-sources/include/ftl/rgbd/detail/source.hpp b/components/rgbd-sources/include/ftl/rgbd/detail/source.hpp
new file mode 100644
index 000000000..65d4b5d3f
--- /dev/null
+++ b/components/rgbd-sources/include/ftl/rgbd/detail/source.hpp
@@ -0,0 +1,39 @@
+#ifndef _FTL_RGBD_DETAIL_SOURCE_HPP_
+#define _FTL_RGBD_DETAIL_SOURCE_HPP_
+
+#include <Eigen/Eigen>
+#include <opencv2/opencv.hpp>
+#include <ftl/rgbd/camera.hpp>
+
+namespace ftl{
+namespace rgbd {
+
+class Source;
+
+namespace detail {
+
+class Source {
+	public:
+	friend class ftl::rgbd::Source;
+
+	public:
+	explicit Source(ftl::rgbd::Source *host) : host_(host), params_({0}) { }
+	virtual ~Source() {}
+
+	virtual bool grab()=0;
+	virtual bool isReady() { return false; };
+	virtual void setPose(const Eigen::Matrix4f &pose) { };
+
+	protected:
+	ftl::rgbd::Source *host_;
+	ftl::rgbd::Camera params_;
+	cv::Mat rgb_;
+	cv::Mat depth_;
+	//Eigen::Matrix4f pose_;
+};
+
+}	
+}
+}
+
+#endif  // _FTL_RGBD_DETAIL_SOURCE_HPP_
diff --git a/components/rgbd-sources/include/ftl/rgbdimage_source.hpp b/components/rgbd-sources/include/ftl/rgbd/group.hpp
similarity index 100%
rename from components/rgbd-sources/include/ftl/rgbdimage_source.hpp
rename to components/rgbd-sources/include/ftl/rgbd/group.hpp
diff --git a/components/rgbd-sources/include/ftl/snapshot.hpp b/components/rgbd-sources/include/ftl/rgbd/snapshot.hpp
similarity index 90%
rename from components/rgbd-sources/include/ftl/snapshot.hpp
rename to components/rgbd-sources/include/ftl/rgbd/snapshot.hpp
index b146c49d8..7e055b7cc 100644
--- a/components/rgbd-sources/include/ftl/snapshot.hpp
+++ b/components/rgbd-sources/include/ftl/rgbd/snapshot.hpp
@@ -9,7 +9,7 @@
 #include <Eigen/Eigen>
 #include <opencv2/core/eigen.hpp>
 
-#include <ftl/camera_params.hpp>
+#include <ftl/rgbd/camera.hpp>
 
 #include <archive.h>
 #include <archive_entry.h>
@@ -24,7 +24,7 @@ public:
 	explicit SnapshotWriter(const std::string &filename);
 	~SnapshotWriter();
 	
-	bool addCameraRGBD(const std::string &name, const cv::Mat &rgb, const cv::Mat &depth, const Eigen::Matrix4f &pose, const ftl::rgbd::CameraParameters &params);
+	bool addCameraRGBD(const std::string &name, const cv::Mat &rgb, const cv::Mat &depth, const Eigen::Matrix4f &pose, const ftl::rgbd::Camera &params);
 	bool addMat(const std::string &name, const cv::Mat &mat, const std::string &format="tiff");
 	bool addEigenMatrix4f(const std::string &name, const Eigen::Matrix4f &m, const std::string &format="pfm");
 	bool addFile(const std::string &name, const std::vector<uchar> &buf);
@@ -39,7 +39,7 @@ struct SnapshotEntry {
 	cv::Mat rgb;
 	cv::Mat depth;
 	Eigen::Matrix4f pose;
-	ftl::rgbd::CameraParameters params;
+	ftl::rgbd::Camera params;
 	uint status;
 	SnapshotEntry() : status(1+2+4+8) {};
 };
@@ -49,7 +49,7 @@ public:
 	explicit SnapshotReader(const std::string &filename);
 	~SnapshotReader();
 	
-	bool getCameraRGBD(const std::string &id, cv::Mat &rgb, cv::Mat &depth, Eigen::Matrix4f &pose, ftl::rgbd::CameraParameters &params);
+	bool getCameraRGBD(const std::string &id, cv::Mat &rgb, cv::Mat &depth, Eigen::Matrix4f &pose, ftl::rgbd::Camera &params);
 	std::vector<std::string> getIds();
 
 private:
diff --git a/components/rgbd-sources/include/ftl/rgbd/source.hpp b/components/rgbd-sources/include/ftl/rgbd/source.hpp
new file mode 100644
index 000000000..885046c3a
--- /dev/null
+++ b/components/rgbd-sources/include/ftl/rgbd/source.hpp
@@ -0,0 +1,167 @@
+#ifndef _FTL_RGBD_SOURCE_HPP_
+#define _FTL_RGBD_SOURCE_HPP_
+
+#include <ftl/configuration.hpp>
+#include <ftl/rgbd/camera.hpp>
+//#include <ftl/net/universe.hpp>
+#include <ftl/uri.hpp>
+#include <ftl/rgbd/detail/source.hpp>
+#include <opencv2/opencv.hpp>
+#include <Eigen/Eigen>
+#include <shared_mutex>
+#include <string>
+
+namespace ftl {
+
+namespace net {
+class Universe;
+}
+
+namespace rgbd {
+
+class SnapshotReader;
+
+enum capability_t {
+	kCapColour,		// Has a colour feed
+	kCapDepth,		// Has a depth feed
+	kCapRight,		// It is possible to get a right image
+	kCapMovable,	// Camera is software movable
+	kCapVideo,		// It is a video feed, not static
+	kCapDisparity	// Raw disparity is available
+};
+
+/**
+ * RGBD Generic data source configurable entity. This class hides the
+ * internal implementation of an RGBD source by providing accessor functions
+ * and by automatically changing the implementation in response to any URI
+ * changes.
+ * 
+ * Cannot be constructed directly, use ftl::create<Source>(...).
+ * @see ftl::create
+ */
+class Source : public ftl::Configurable {
+	public:
+	template <typename T, typename... ARGS>
+	friend T *ftl::config::create(ftl::config::json_t &, ARGS ...);
+
+	//template <typename T, typename... ARGS>
+	//friend T *ftl::config::create(ftl::Configurable *, const std::string &, ARGS ...);
+
+	// This class cannot be constructed directly, use ftl::create
+	Source()=delete;
+
+	// Also cannot be copied
+	Source(const Source&)=delete;
+	Source &operator=(const Source&) =delete;
+
+	private:
+	explicit Source(ftl::config::json_t &cfg);
+	Source(ftl::config::json_t &cfg, ftl::rgbd::SnapshotReader *);
+	Source(ftl::config::json_t &cfg, ftl::net::Universe *net);
+	~Source();
+
+	public:
+	/**
+	 * Is this source valid and ready to grab?.
+	 */
+	bool isReady() { return (impl_) ? impl_->isReady() : false; }
+
+	/**
+	 * Perform the hardware or virtual frame grab operation. 
+	 */
+	bool grab();
+
+	/**
+	 * Do any post-grab processing. This function
+	 * may take considerable time to return, especially for sources requiring
+	 * software stereo correspondance. If `process` is not called manually
+	 * after a `grab` and before a `get`, then it will be called automatically
+	 * on first `get`.
+	 */
+	//void process();
+
+	/**
+	 * Get a copy of both colour and depth frames.
+	 */
+	void getFrames(cv::Mat &c, cv::Mat &d);
+
+	/**
+	 * Get a copy of the colour frame only.
+	 */
+	void getColour(cv::Mat &c);
+
+	/**
+	 * Get a copy of the depth frame only.
+	 */
+	void getDepth(cv::Mat &d);
+
+	/**
+	 * Directly upload source RGB and Depth to GPU.
+	 */
+	void upload(cv::cuda::GpuMat&, cv::cuda::GpuMat&);
+
+	void uploadColour(cv::cuda::GpuMat&);
+	void uploadDepth(cv::cuda::GpuMat&);
+
+	/**
+	 * Get the source's camera intrinsics.
+	 */
+	const Camera &parameters() const {
+		if (impl_) return impl_->params_;
+		else return params_;
+	}
+
+	/**
+	 * Change the camera extrinsics by providing a new pose matrix. For virtual
+	 * cameras this will move the camera, for physical cameras it is set by the
+	 * registration process as it attempts to work out a cameras relative pose.
+	 */
+	virtual void setPose(const Eigen::Matrix4f &pose);
+
+	/**
+	 * Get the camera position as a pose matrix.
+	 */
+	const Eigen::Matrix4f &getPose() const;
+
+	/**
+	 * Check what features this source has available.
+	 */
+	virtual bool hasCapability(capability_t);
+
+	/**
+	 * Get a point in camera coordinates at specified pixel location.
+	 */
+	Eigen::Vector4f point(uint x, uint y);
+
+	/**
+	 * Force the internal implementation to be reconstructed.
+	 */
+	void reset();
+
+	ftl::net::Universe *getNet() const { return net_; }
+
+	std::string getURI() { return value("uri", std::string("")); }
+
+	void customImplementation(detail::Source *);
+
+	std::shared_mutex &mutex() { return mutex_; }
+
+	private:
+	detail::Source *impl_;
+	cv::Mat rgb_;
+	cv::Mat depth_;
+	Camera params_;		// TODO Find better solution
+	Eigen::Matrix4f pose_;
+	ftl::net::Universe *net_;
+	std::shared_mutex mutex_;
+
+	detail::Source *_createImplementation();
+	detail::Source *_createFileImpl(const ftl::URI &uri);
+	detail::Source *_createNetImpl(const ftl::URI &uri);
+	detail::Source *_createDeviceImpl(const ftl::URI &uri);
+};
+
+}
+}
+
+#endif  // _FTL_RGBD_SOURCE_HPP_
diff --git a/components/rgbd-sources/include/ftl/rgbd_streamer.hpp b/components/rgbd-sources/include/ftl/rgbd/streamer.hpp
similarity index 94%
rename from components/rgbd-sources/include/ftl/rgbd_streamer.hpp
rename to components/rgbd-sources/include/ftl/rgbd/streamer.hpp
index bbe9449ec..02025e222 100644
--- a/components/rgbd-sources/include/ftl/rgbd_streamer.hpp
+++ b/components/rgbd-sources/include/ftl/rgbd/streamer.hpp
@@ -5,7 +5,7 @@
 #include <loguru.hpp>
 #include <ftl/configuration.hpp>
 #include <ftl/configurable.hpp>
-#include <ftl/rgbd_source.hpp>
+#include <ftl/rgbd/source.hpp>
 #include <ftl/net/universe.hpp>
 #include <string>
 #include <list>
@@ -28,7 +28,7 @@ static const unsigned int kGrabbed = 0x1;
 static const unsigned int kTransmitted = 0x2; 
 
 struct StreamSource {
-	ftl::rgbd::RGBDSource *src;
+	ftl::rgbd::Source *src;
 	unsigned int state;								// Busy or ready to swap?
 	cv::Mat rgb;									// Tx buffer
 	cv::Mat depth;									// Tx buffer
@@ -69,9 +69,9 @@ class Streamer : public ftl::Configurable {
 	/**
 	 * Add an RGB-Depth source to be made available for streaming.
 	 */
-	void add(RGBDSource *);
+	void add(Source *);
 
-	void remove(RGBDSource *);
+	void remove(Source *);
 	void remove(const std::string &);
 
 	/**
@@ -91,7 +91,7 @@ class Streamer : public ftl::Configurable {
 	 */
 	void poll();
 
-	RGBDSource *get(const std::string &uri);
+	Source *get(const std::string &uri);
 
 	private:
 	std::map<std::string, detail::StreamSource*> sources_;
diff --git a/components/rgbd-sources/include/ftl/rgbdvideo_source.hpp b/components/rgbd-sources/include/ftl/rgbdvideo_source.hpp
deleted file mode 100644
index e69de29bb..000000000
diff --git a/components/rgbd-sources/include/ftl/snapshot_source.hpp b/components/rgbd-sources/include/ftl/snapshot_source.hpp
deleted file mode 100644
index d4900f76a..000000000
--- a/components/rgbd-sources/include/ftl/snapshot_source.hpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#pragma once
-#ifndef _FTL_RGBD_SNAPSHOT_SOURCE_HPP_
-#define _FTL_RGBD_SNAPSHOT_SOURCE_HPP_
-
-#include <loguru.hpp>
-
-#include "ftl/rgbd_source.hpp"
-#include "ftl/snapshot.hpp"
-
-namespace ftl {
-namespace rgbd {
-
-class SnapshotSource : public RGBDSource {
-	public:
-	SnapshotSource(nlohmann::json &config, ftl::rgbd::SnapshotReader &reader, const std::string &id);
-	~SnapshotSource() {};
-	void grab() override {};
-};
-
-};
-};
-
-#endif  // _FTL_RGBD_SNAPSHOT_SOURCE_HPP_
diff --git a/components/rgbd-sources/include/ftl/stereoimage_source.hpp b/components/rgbd-sources/include/ftl/stereoimage_source.hpp
deleted file mode 100644
index e69de29bb..000000000
diff --git a/components/rgbd-sources/src/algorithms/fixstars_sgm.hpp b/components/rgbd-sources/src/algorithms/fixstars_sgm.hpp
index dd92efdb2..18492c6f1 100644
--- a/components/rgbd-sources/src/algorithms/fixstars_sgm.hpp
+++ b/components/rgbd-sources/src/algorithms/fixstars_sgm.hpp
@@ -22,7 +22,7 @@ namespace algorithms {
  * NOTE: We are using a modified version that supports disparity of 256.
  * @see https://github.com/knicos/libSGM
  */
-class FixstarsSGM : public ftl::Disparity {
+class FixstarsSGM : public ftl::rgbd::detail::Disparity {
 	public:
 	explicit FixstarsSGM(nlohmann::json &config);
 
diff --git a/components/rgbd-sources/src/algorithms/rtcensus.hpp b/components/rgbd-sources/src/algorithms/rtcensus.hpp
index 0a31a49b1..785af6261 100644
--- a/components/rgbd-sources/src/algorithms/rtcensus.hpp
+++ b/components/rgbd-sources/src/algorithms/rtcensus.hpp
@@ -23,7 +23,7 @@ namespace algorithms {
 /**
  * Real-time Sparse Census disparity algorithm.
  */
-class RTCensus : public ftl::Disparity {
+class RTCensus : public ftl::rgbd::detail::Disparity {
 	public:
 	explicit RTCensus(nlohmann::json &config);
 	
diff --git a/components/rgbd-sources/src/algorithms/rtcensus_sgm.cpp b/components/rgbd-sources/src/algorithms/rtcensus_sgm.cpp
index be534d290..e84819e60 100644
--- a/components/rgbd-sources/src/algorithms/rtcensus_sgm.cpp
+++ b/components/rgbd-sources/src/algorithms/rtcensus_sgm.cpp
@@ -30,7 +30,7 @@ using std::get;
 using std::make_tuple;
 using std::bitset;
 
-static ftl::Disparity::Register rtcensus("rtcensus_sgm", RTCensusSGM::create);
+//static ftl::Disparity::Register rtcensus("rtcensus_sgm", RTCensusSGM::create);
 
 RTCensusSGM::RTCensusSGM(nlohmann::json &config)
 	:	Disparity(config),
diff --git a/components/rgbd-sources/src/algorithms/rtcensus_sgm.hpp b/components/rgbd-sources/src/algorithms/rtcensus_sgm.hpp
index 015c67b08..ef4dd7fd9 100644
--- a/components/rgbd-sources/src/algorithms/rtcensus_sgm.hpp
+++ b/components/rgbd-sources/src/algorithms/rtcensus_sgm.hpp
@@ -21,7 +21,7 @@ namespace algorithms {
 /**
  * WORK IN PROGRESS
  */
-class RTCensusSGM : public ftl::Disparity {
+class RTCensusSGM : public ftl::rgbd::detail::Disparity {
 	public:
 	explicit RTCensusSGM(nlohmann::json &config);
 	
diff --git a/components/rgbd-sources/src/calibrate.cpp b/components/rgbd-sources/src/calibrate.cpp
index 315fc8f35..7fe953c03 100644
--- a/components/rgbd-sources/src/calibrate.cpp
+++ b/components/rgbd-sources/src/calibrate.cpp
@@ -22,7 +22,8 @@
 #include <opencv2/videoio.hpp>
 #include <opencv2/highgui.hpp>
 
-using ftl::Calibrate;
+using ftl::rgbd::detail::Calibrate;
+using ftl::rgbd::detail::LocalSource;
 using cv::FileStorage;
 using cv::CALIB_FIX_PRINCIPAL_POINT;
 using cv::CALIB_ZERO_TANGENT_DIST;
@@ -181,7 +182,7 @@ bool runCalibration(const Calibrate::Settings& s, Size imageSize,
 		bool release_object);
 
 
-Calibrate::Calibrate(nlohmann::json &config, ftl::LocalSource *s) : ftl::Configurable(config), local_(s) {
+Calibrate::Calibrate(nlohmann::json &config, LocalSource *s) : ftl::Configurable(config), local_(s) {
     /*FileStorage fs(cal, FileStorage::READ); // Read the settings
     if (!fs.isOpened())
     {
diff --git a/components/rgbd-sources/src/calibrate.hpp b/components/rgbd-sources/src/calibrate.hpp
index 08c0525ea..c3a163a03 100644
--- a/components/rgbd-sources/src/calibrate.hpp
+++ b/components/rgbd-sources/src/calibrate.hpp
@@ -17,6 +17,8 @@ class FileNode;
 };
 
 namespace ftl {
+namespace rgbd {
+namespace detail {
 
 /**
  * Manage both performing and applying camera calibration. It will attempt to
@@ -83,7 +85,7 @@ class Calibrate : public ftl::Configurable {
 
 	};
 	public:
-	Calibrate(nlohmann::json &config, ftl::LocalSource *s);
+	Calibrate(nlohmann::json &config, LocalSource *s);
 	
 	/**
 	 * Perform a new camera calibration. Ignore and replace any existing
@@ -122,7 +124,7 @@ class Calibrate : public ftl::Configurable {
 	bool _loadCalibration();
 	
 	private:
-	ftl::LocalSource *local_;
+	LocalSource *local_;
 	Settings settings_;
 	bool calibrated_;
 	std::vector<cv::Mat> map1_;
@@ -132,7 +134,10 @@ class Calibrate : public ftl::Configurable {
 	cv::Mat r1_;
 	cv::Mat Q_;
 };
-};
+
+}
+}
+}
 
 #endif // _FTL_CALIBRATION_HPP_
 
diff --git a/components/rgbd-sources/src/disparity.cpp b/components/rgbd-sources/src/disparity.cpp
index e482fa60c..6f413bc2e 100644
--- a/components/rgbd-sources/src/disparity.cpp
+++ b/components/rgbd-sources/src/disparity.cpp
@@ -7,7 +7,7 @@
 #include <ftl/config.h>
 #include <ftl/configuration.hpp>
 
-using ftl::Disparity;
+using ftl::rgbd::detail::Disparity;
 
 std::map<std::string, std::function<Disparity*(ftl::Configurable *, const std::string &)>>
 		*Disparity::algorithms__ = nullptr;
@@ -40,10 +40,10 @@ void Disparity::_register(const std::string &n,
 // TODO(Nick) Add remaining algorithms
 
 #include "algorithms/rtcensus.hpp"
-static ftl::Disparity::Register rtcensus("rtcensus", ftl::algorithms::RTCensus::create);
+static ftl::rgbd::detail::Disparity::Register rtcensus("rtcensus", ftl::algorithms::RTCensus::create);
 
 #ifdef HAVE_LIBSGM
 #include "algorithms/fixstars_sgm.hpp"
-static ftl::Disparity::Register fixstarssgm("libsgm", ftl::algorithms::FixstarsSGM::create);
+static ftl::rgbd::detail::Disparity::Register fixstarssgm("libsgm", ftl::algorithms::FixstarsSGM::create);
 #endif  // HAVE_LIBSGM
 
diff --git a/components/rgbd-sources/src/disparity.hpp b/components/rgbd-sources/src/disparity.hpp
index cb25e2895..838a4a164 100644
--- a/components/rgbd-sources/src/disparity.hpp
+++ b/components/rgbd-sources/src/disparity.hpp
@@ -10,6 +10,8 @@
 #include <ftl/configurable.hpp>
 
 namespace ftl {
+namespace rgbd {
+namespace detail {
 
 /**
  * Virtual base class for disparity algorithms. An automatic factory is used
@@ -61,7 +63,10 @@ class Disparity : public ftl::Configurable {
 	private:
 	static std::map<std::string,std::function<Disparity*(ftl::Configurable *, const std::string &)>> *algorithms__;
 };
-};
+
+}
+}
+}
 
 #endif // _FTL_DISPARITY_HPP_
 
diff --git a/components/rgbd-sources/src/image.hpp b/components/rgbd-sources/src/image.hpp
new file mode 100644
index 000000000..296a1c876
--- /dev/null
+++ b/components/rgbd-sources/src/image.hpp
@@ -0,0 +1,25 @@
+#ifndef _FTL_RGBD_IMAGE_HPP_
+#define _FTL_RGBD_IMAGE_HPP_
+
+namespace ftl {
+namespace rgbd {
+namespace detail {
+
+class ImageSource : public ftl::rgbd::detail::Source {
+	public:
+	explicit ImageSource(ftl::rgbd::Source *host) : ftl::rgbd::detail::Source(host) {
+	
+	}
+	ImageSource(ftl::rgbd::Source *host, const std::string &f) : ftl::rgbd::detail::Source(host) {
+
+	}
+
+	bool grab() { return false; };
+	bool isReady() { return false; };
+};
+
+}
+}
+}
+
+#endif  // _FTL_RGBD_IMAGE_HPP_
diff --git a/components/rgbd-sources/src/local.cpp b/components/rgbd-sources/src/local.cpp
index d3d33d735..63257bad5 100644
--- a/components/rgbd-sources/src/local.cpp
+++ b/components/rgbd-sources/src/local.cpp
@@ -12,7 +12,7 @@
 #include <opencv2/core.hpp>
 #include <opencv2/opencv.hpp>
 
-using ftl::LocalSource;
+using ftl::rgbd::detail::LocalSource;
 using cv::Mat;
 using cv::VideoCapture;
 using cv::Rect;
diff --git a/components/rgbd-sources/src/local.hpp b/components/rgbd-sources/src/local.hpp
index d3286684b..92437b8c4 100644
--- a/components/rgbd-sources/src/local.hpp
+++ b/components/rgbd-sources/src/local.hpp
@@ -11,6 +11,9 @@ namespace cv {
 };
 
 namespace ftl {
+namespace rgbd {
+namespace detail {
+
 class LocalSource : public Configurable {
 	public:
 	explicit LocalSource(nlohmann::json &config);
@@ -44,7 +47,10 @@ class LocalSource : public Configurable {
 	unsigned int width_;
 	unsigned int height_;
 };
-};
+
+}
+}
+}
 
 #endif // _FTL_LOCAL_HPP_
 
diff --git a/components/rgbd-sources/src/net_source.cpp b/components/rgbd-sources/src/net.cpp
similarity index 64%
rename from components/rgbd-sources/src/net_source.cpp
rename to components/rgbd-sources/src/net.cpp
index ae8bd9f9e..96b6d762a 100644
--- a/components/rgbd-sources/src/net_source.cpp
+++ b/components/rgbd-sources/src/net.cpp
@@ -1,20 +1,21 @@
-#include <ftl/net_source.hpp>
+#include "net.hpp"
 #include <vector>
 #include <thread>
 #include <chrono>
+#include <shared_mutex>
 
-using ftl::rgbd::NetSource;
+using ftl::rgbd::detail::NetSource;
 using ftl::net::Universe;
 using ftl::UUID;
 using std::string;
-using ftl::rgbd::CameraParameters;
-using std::mutex;
+using ftl::rgbd::Camera;
+using std::shared_mutex;
 using std::unique_lock;
 using std::vector;
 using std::this_thread::sleep_for;
 using std::chrono::milliseconds;
 
-bool NetSource::_getCalibration(Universe &net, const UUID &peer, const string &src, ftl::rgbd::CameraParameters &p) {
+bool NetSource::_getCalibration(Universe &net, const UUID &peer, const string &src, ftl::rgbd::Camera &p) {
 	try {
 		while(true) {
 			auto buf = net.call<vector<unsigned char>>(peer_, "source_calibration", src);
@@ -40,20 +41,13 @@ bool NetSource::_getCalibration(Universe &net, const UUID &peer, const string &s
 	}
 }
 
-NetSource::NetSource(nlohmann::json &config) : RGBDSource(config) {
-
-}
-
-NetSource::NetSource(nlohmann::json &config, ftl::net::Universe *net)
-		: RGBDSource(config, net), active_(false) {
-
-	on("uri", [this](const config::Event &e) {
-		_updateURI();
-	});
+NetSource::NetSource(ftl::rgbd::Source *host)
+		: ftl::rgbd::detail::Source(host), active_(false) {
 
 	_updateURI();
 
-	h_ = net->onConnect([this](ftl::net::Peer *p) {
+	h_ = host_->getNet()->onConnect([this](ftl::net::Peer *p) {
+		if (active_) return;
 		LOG(INFO) << "NetSource restart...";
 		_updateURI();
 	});
@@ -61,13 +55,15 @@ NetSource::NetSource(nlohmann::json &config, ftl::net::Universe *net)
 
 NetSource::~NetSource() {
 	if (uri_.size() > 0) {
-		net_->unbind(uri_);
+		host_->getNet()->unbind(uri_);
 	}
 
-	net_->removeCallback(h_);
+	host_->getNet()->removeCallback(h_);
 }
 
 void NetSource::_recv(const vector<unsigned char> &jpg, const vector<unsigned char> &d) {
+	unique_lock<shared_mutex> lk(host_->mutex());
+
 	cv::imdecode(jpg, cv::IMREAD_COLOR, &rgb_);
 	//Mat(rgb_.size(), CV_16UC1);
 	cv::imdecode(d, cv::IMREAD_UNCHANGED, &depth_);
@@ -76,7 +72,7 @@ void NetSource::_recv(const vector<unsigned char> &jpg, const vector<unsigned ch
 	N_--;
 	if (N_ == 0) {
 		N_ += 10;
-		if (!net_->send(peer_, "get_stream", *get<string>("uri"), 10, 0, net_->id(), *get<string>("uri"))) {
+		if (!host_->getNet()->send(peer_, "get_stream", *host_->get<string>("uri"), 10, 0, host_->getNet()->id(), *host_->get<string>("uri"))) {
 			active_ = false;
 		}
 	}
@@ -87,37 +83,36 @@ void NetSource::setPose(const Eigen::Matrix4f &pose) {
 
 	vector<unsigned char> vec((unsigned char*)pose.data(), (unsigned char*)(pose.data()+(pose.size())));
 	try {
-		if (!net_->send(peer_, "set_pose", *get<string>("uri"), vec)) {
+		if (!host_->getNet()->send(peer_, "set_pose", *host_->get<string>("uri"), vec)) {
 			active_ = false;
 		}
 	} catch (...) {
 
 	}
-	RGBDSource::setPose(pose);
+	Source::setPose(pose);
 }
 
 void NetSource::_updateURI() {
-	unique_lock<mutex> lk(mutex_);
+	//unique_lock<mutex> lk(mutex_);
 	active_ = false;
-	auto uri = get<string>("uri");
+	auto uri = host_->get<string>("uri");
 
 	// TODO(Nick) If URI changes then must unbind + rebind.
 	if (uri_.size() > 0) {
-		net_->unbind(uri_);
+		host_->getNet()->unbind(uri_);
 	}
 
 	if (uri) {
-		auto p = net_->findOne<ftl::UUID>("find_stream", *uri);
+		auto p = host_->getNet()->findOne<ftl::UUID>("find_stream", *uri);
 		if (!p) {
 			LOG(ERROR) << "Could not find stream: " << *uri;
 			return;
 		}
 		peer_ = *p;
 
-		has_calibration_ = _getCalibration(*net_, peer_, *uri, params_);
+		has_calibration_ = _getCalibration(*host_->getNet(), peer_, *uri, params_);
 
-		net_->bind(*uri, [this](const vector<unsigned char> &jpg, const vector<unsigned char> &d) {
-			unique_lock<mutex> lk(mutex_);
+		host_->getNet()->bind(*uri, [this](const vector<unsigned char> &jpg, const vector<unsigned char> &d) {
 			_recv(jpg, d);
 		});
 
@@ -125,7 +120,7 @@ void NetSource::_updateURI() {
 
 		// Initiate stream with request for first 10 frames
 		try {
-			net_->send(peer_, "get_stream", *uri, 10, 0, net_->id(), *uri);
+			host_->getNet()->send(peer_, "get_stream", *uri, 10, 0, host_->getNet()->id(), *uri);
 		} catch(...) {
 			LOG(ERROR) << "Could not connect to stream " << *uri;
 		}
@@ -138,8 +133,9 @@ void NetSource::_updateURI() {
 	}
 }
 
-void NetSource::grab() {
+bool NetSource::grab() {
 	// net_.broadcast("grab");
+	return true;
 }
 
 bool NetSource::isReady() {
diff --git a/components/rgbd-sources/include/ftl/net_source.hpp b/components/rgbd-sources/src/net.hpp
similarity index 68%
rename from components/rgbd-sources/include/ftl/net_source.hpp
rename to components/rgbd-sources/src/net.hpp
index 4199d0e80..de4a3b00b 100644
--- a/components/rgbd-sources/include/ftl/net_source.hpp
+++ b/components/rgbd-sources/src/net.hpp
@@ -3,11 +3,13 @@
 #define _FTL_RGBD_NET_HPP_
 
 #include <ftl/net/universe.hpp>
-#include <ftl/rgbd_source.hpp>
+#include <ftl/rgbd/source.hpp>
 #include <string>
+#include <mutex>
 
 namespace ftl {
 namespace rgbd {
+namespace detail {
 
 /**
  * RGBD source from either a stereo video file with left + right images, or
@@ -15,21 +17,18 @@ namespace rgbd {
  * calculating disparity, before converting to depth.  Calibration of the images
  * is also performed.
  */
-class NetSource : public RGBDSource {
+class NetSource : public detail::Source {
 	public:
-	explicit NetSource(nlohmann::json &config);
-	NetSource(nlohmann::json &config, ftl::net::Universe *net);
+	explicit NetSource(ftl::rgbd::Source *);
 	~NetSource();
 
-	void grab();
+	bool grab();
 	bool isReady();
 
-	static inline RGBDSource *create(nlohmann::json &config, ftl::net::Universe *net) {
-		return new NetSource(config, net);
-	}
-
 	void setPose(const Eigen::Matrix4f &pose);
 
+	void reset();
+
 	private:
 	bool has_calibration_;
 	ftl::UUID peer_;
@@ -37,12 +36,14 @@ class NetSource : public RGBDSource {
 	bool active_;
 	std::string uri_;
 	ftl::net::callback_t h_;
+	std::mutex mutex_;
 
-	bool _getCalibration(ftl::net::Universe &net, const ftl::UUID &peer, const std::string &src, ftl::rgbd::CameraParameters &p);
+	bool _getCalibration(ftl::net::Universe &net, const ftl::UUID &peer, const std::string &src, ftl::rgbd::Camera &p);
 	void _recv(const std::vector<unsigned char> &jpg, const std::vector<unsigned char> &d);
 	void _updateURI();
 };
 
+}
 }
 }
 
diff --git a/components/rgbd-sources/src/rgbd_source.cpp b/components/rgbd-sources/src/rgbd_source.cpp
deleted file mode 100644
index d796c02e9..000000000
--- a/components/rgbd-sources/src/rgbd_source.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-#include <ftl/rgbd_source.hpp>
-
-using ftl::rgbd::RGBDSource;
-using ftl::Configurable;
-using std::string;
-using std::mutex;
-using std::unique_lock;
-
-std::map<std::string, std::function<RGBDSource*(nlohmann::json&,ftl::net::Universe*)>> *RGBDSource::sources__ = nullptr;
-
-RGBDSource::RGBDSource(nlohmann::json &config) : Configurable(config), net_(nullptr) {
-
-}
-
-RGBDSource::RGBDSource(nlohmann::json &config, ftl::net::Universe *net) : Configurable(config), net_(net) {
-
-}
-
-RGBDSource::~RGBDSource() {
-
-}
-
-bool RGBDSource::isReady() {
-	return false;
-}
-
-/*void RGBDSource::setURI(const std::string &uri) {
-	config_["uri"] = uri;
-}*/
-
-void RGBDSource::getRGBD(cv::Mat &rgb, cv::Mat &depth) {
-	unique_lock<mutex> lk(mutex_);
-	rgb_.copyTo(rgb);
-	depth_.copyTo(depth);
-}
-
-Eigen::Vector4f RGBDSource::point(uint ux, uint uy) {
-	const auto &params = getParameters();
-	const float x = ((float)ux-params.width/2) / (float)params.fx;
-	const float y = ((float)uy-params.height/2) / (float)params.fy;
-
-	unique_lock<mutex> lk(mutex_);
-	const float depth = depth_.at<float>(uy,ux);
-	return Eigen::Vector4f(x*depth,y*depth,depth,1.0);
-}
-
-bool RGBDSource::snapshot(const std::string &fileprefix) {
-	cv::Mat rgb;
-	cv::Mat depth;
-	getRGBD(rgb, depth);
-
-	cv::Mat d2;
-    depth.convertTo(d2, CV_16UC1, 16*100);
-
-	cv::imwrite(fileprefix+"-RGB.jpg", rgb);
-	cv::imwrite(fileprefix+"-DEPTH.png",depth);
-	return true;
-}
-
-RGBDSource *RGBDSource::create(nlohmann::json &config, ftl::net::Universe *net) {
-	auto &cfg = ftl::config::resolve(config);
-	if (!cfg["type"].is_string()) {
-		LOG(ERROR) << "Missing RGB-D source type: " << cfg["type"].type_name();
-		//return nullptr;
-	}
-	if (sources__->count(cfg["type"].get<string>()) != 1) return nullptr;
-	return (*sources__)[cfg["type"].get<string>()](config, net);
-}
-
-void RGBDSource::_register(const std::string &n,
-		std::function<RGBDSource*(nlohmann::json&,ftl::net::Universe*)> f) {
-	if (!sources__) sources__ = new std::map<std::string, std::function<RGBDSource*(nlohmann::json&,ftl::net::Universe*)>>;
-	//LOG(INFO) << "Register RGB-D Source: " << n;
-	(*sources__)[n] = f;
-}
-
-#include <ftl/net_source.hpp>
-static RGBDSource::Register netsource("net", ftl::rgbd::NetSource::create);
-#include <ftl/stereovideo_source.hpp>
-static RGBDSource::Register svsource("stereovideo", ftl::rgbd::StereoVideoSource::create);
diff --git a/components/rgbd-sources/src/snapshot.cpp b/components/rgbd-sources/src/snapshot.cpp
index 5142612b9..51b8a635f 100644
--- a/components/rgbd-sources/src/snapshot.cpp
+++ b/components/rgbd-sources/src/snapshot.cpp
@@ -1,4 +1,4 @@
-#include <ftl/snapshot.hpp>
+#include <ftl/rgbd/snapshot.hpp>
 
 #include <nlohmann/json.hpp>
 
@@ -16,9 +16,9 @@ using std::vector;
 using Eigen::Matrix4f;
 
 // TODO: move to camera_params
-using ftl::rgbd::CameraParameters;
+using ftl::rgbd::Camera;
 
-void to_json(nlohmann::json& j, const CameraParameters &p) {
+void to_json(nlohmann::json& j, const Camera &p) {
 	j = nlohmann::json{
 		{"fx", p.fx},
 		{"fy", p.fy},
@@ -31,7 +31,7 @@ void to_json(nlohmann::json& j, const CameraParameters &p) {
 	};
 }
 
-void from_json(const nlohmann::json& j, CameraParameters &p) {
+void from_json(const nlohmann::json& j, Camera &p) {
 	j.at("fx").get_to(p.fx);
 	j.at("fy").get_to(p.fy);
 	j.at("cx").get_to(p.cx);
@@ -127,7 +127,7 @@ bool SnapshotWriter::addEigenMatrix4f(const string &name, const Matrix4f &m, con
 }
 
 bool SnapshotWriter::addCameraRGBD(const string &name, const Mat &rgb, const Mat &depth,
-							 const Matrix4f &pose, const CameraParameters &params) {
+							 const Matrix4f &pose, const Camera &params) {
 	bool retval = true;
 	retval &= addMat(name + "-RGB", rgb);
 	retval &= addMat(name + "-D", depth);
@@ -256,7 +256,7 @@ vector<string> SnapshotReader::getIds() {
 }
 
 bool SnapshotReader::getCameraRGBD(const string &id, Mat &rgb, Mat &depth,
-							 Matrix4f &pose, CameraParameters &params) {
+							 Matrix4f &pose, Camera &params) {
 	if (data_.find(id) == data_.end()) {
 		LOG(ERROR) << "entry not found: " << id;
 		return false;
diff --git a/components/rgbd-sources/src/snapshot_source.cpp b/components/rgbd-sources/src/snapshot_source.cpp
index 40751e58a..96c16e4d0 100644
--- a/components/rgbd-sources/src/snapshot_source.cpp
+++ b/components/rgbd-sources/src/snapshot_source.cpp
@@ -1,14 +1,15 @@
-#include "ftl/snapshot_source.hpp"
+#include "snapshot_source.hpp"
 
 #include <opencv2/opencv.hpp>
 #include <Eigen/Eigen>
 #include <opencv2/core/eigen.hpp>
 
 using namespace ftl::rgbd;
+using ftl::rgbd::detail::SnapshotSource;
 
 using std::string;
 
-SnapshotSource::SnapshotSource(nlohmann::json &config, SnapshotReader &reader, const string &id) : RGBDSource(config) {
+SnapshotSource::SnapshotSource(ftl::rgbd::Source *host, SnapshotReader &reader, const string &id) : detail::Source(host) {
     Eigen::Matrix4f pose;
     reader.getCameraRGBD(id, rgb_, depth_, pose, params_);
     setPose(pose);
diff --git a/components/rgbd-sources/src/snapshot_source.hpp b/components/rgbd-sources/src/snapshot_source.hpp
new file mode 100644
index 000000000..3ba9a7f02
--- /dev/null
+++ b/components/rgbd-sources/src/snapshot_source.hpp
@@ -0,0 +1,31 @@
+#pragma once
+#ifndef _FTL_RGBD_SNAPSHOT_SOURCE_HPP_
+#define _FTL_RGBD_SNAPSHOT_SOURCE_HPP_
+
+#include <loguru.hpp>
+
+#include "ftl/rgbd/source.hpp"
+#include "ftl/rgbd/snapshot.hpp"
+
+namespace ftl {
+namespace rgbd {
+namespace detail {
+
+class SnapshotSource : public detail::Source {
+	public:
+	SnapshotSource(ftl::rgbd::Source *);
+	SnapshotSource(ftl::rgbd::Source *, ftl::rgbd::SnapshotReader &reader, const std::string &id);
+	~SnapshotSource() {};
+
+	bool grab() override {};
+	bool isReady() { return true; }
+
+	//void reset();
+
+};
+
+}
+}
+}
+
+#endif  // _FTL_RGBD_SNAPSHOT_SOURCE_HPP_
diff --git a/components/rgbd-sources/src/source.cpp b/components/rgbd-sources/src/source.cpp
new file mode 100644
index 000000000..bd68b0ae8
--- /dev/null
+++ b/components/rgbd-sources/src/source.cpp
@@ -0,0 +1,166 @@
+#include <loguru.hpp>
+#include <ftl/rgbd/source.hpp>
+
+#include "net.hpp"
+#include "stereovideo.hpp"
+#include "image.hpp"
+
+#ifdef HAVE_LIBARCHIVE
+#include "snapshot_source.hpp"
+#endif
+
+using ftl::rgbd::Source;
+using ftl::Configurable;
+using std::string;
+using std::shared_mutex;
+using std::unique_lock;
+using std::shared_lock;
+using ftl::rgbd::detail::StereoVideoSource;
+using ftl::rgbd::detail::NetSource;
+using ftl::rgbd::detail::ImageSource;
+using ftl::rgbd::capability_t;
+
+Source::Source(ftl::config::json_t &cfg) : Configurable(cfg), net_(nullptr) {
+	impl_ = nullptr;
+	params_ = {0};
+	reset();
+
+	on("uri", [this](const ftl::config::Event &e) {
+		LOG(INFO) << "URI change for source: " << getURI();
+		reset();
+	});
+}
+
+Source::Source(ftl::config::json_t &cfg, ftl::net::Universe *net) : Configurable(cfg), net_(net) {
+	impl_ = nullptr;
+	params_ = {0};
+	reset();
+
+	on("uri", [this](const ftl::config::Event &e) {
+		LOG(INFO) << "URI change for source: " << getURI();
+		reset();
+	});
+}
+
+Source::~Source() {
+
+}
+
+void Source::customImplementation(ftl::rgbd::detail::Source *impl) {
+	if (impl_) delete impl_;
+	impl_ = impl;
+}
+
+ftl::rgbd::detail::Source *Source::_createImplementation() {
+	auto uristr = get<string>("uri");
+	if (!uristr) {
+		//LOG(WARNING) << "Missing URI for source";
+		return nullptr;
+	}
+
+	ftl::URI uri(*uristr);
+	if (!uri.isValid()) {
+		LOG(WARNING) << "Invalid URI for source: " << *uristr;
+		return nullptr;
+	}
+
+	switch (uri.getScheme()) {
+	case ftl::URI::SCHEME_FILE		:	return _createFileImpl(uri);
+	case ftl::URI::SCHEME_FTL		:	return _createNetImpl(uri);
+	case ftl::URI::SCHEME_DEVICE	:	return _createDeviceImpl(uri);
+	default: break;
+	}
+
+	LOG(WARNING) << "Unrecognised source URI: " << *uristr;
+	return nullptr;
+}
+
+ftl::rgbd::detail::Source *Source::_createFileImpl(const ftl::URI &uri) {
+	std::string path = uri.getPath();
+	// Note: This is non standard
+	if (uri.getHost() == "." || uri.getHost() == "~") path = uri.getHost()+path;
+
+	auto eix = path.find_last_of('.');
+
+	if (eix == string::npos) {
+		// Might be a directory
+		if (ftl::is_directory(path)) {
+			return new StereoVideoSource(this);
+		} else {
+			return nullptr;
+		}
+	} else if (ftl::is_file(path)) {
+		string ext = path.substr(eix+1);
+
+		if (ext == "png" || ext == "jpg") {
+			return new ImageSource(this, path);
+		} else if (ext == "mp4") {
+			return new StereoVideoSource(this, path);
+		} else if (ext == "tar") {
+			return nullptr;
+		} else {
+			LOG(WARNING) << "Unrecognised file type: " << path;	
+		}
+	} else {
+		LOG(WARNING) << "File does not exist: " << path;
+	}
+
+	return nullptr;
+}
+
+ftl::rgbd::detail::Source *Source::_createNetImpl(const ftl::URI &uri) {
+	LOG(INFO) << "MAKE NET SOURCE";
+	return new NetSource(this);
+}
+
+ftl::rgbd::detail::Source *Source::_createDeviceImpl(const ftl::URI &uri) {
+	if (uri.getPathSegment(0) == "video") {
+		return new StereoVideoSource(this);
+	}
+	return nullptr;
+}
+
+void Source::getFrames(cv::Mat &rgb, cv::Mat &depth) {
+	shared_lock<shared_mutex> lk(mutex_);
+	rgb_.copyTo(rgb);
+	depth_.copyTo(depth);
+}
+
+Eigen::Vector4f Source::point(uint ux, uint uy) {
+	const auto &params = parameters();
+	const float x = ((float)ux-params.width/2) / (float)params.fx;
+	const float y = ((float)uy-params.height/2) / (float)params.fy;
+
+	shared_lock<shared_mutex> lk(mutex_);
+	const float depth = depth_.at<float>(uy,ux);
+	return Eigen::Vector4f(x*depth,y*depth,depth,1.0);
+}
+
+void Source::setPose(const Eigen::Matrix4f &pose) {
+	pose_ = pose;
+	if (impl_) impl_->setPose(pose);
+}
+
+const Eigen::Matrix4f &Source::getPose() const {
+	return pose_;
+}
+
+bool Source::hasCapability(capability_t) {
+	return false;
+}
+
+void Source::reset() {
+	unique_lock<shared_mutex> lk(mutex_);
+	if (impl_) delete impl_;
+	impl_ = _createImplementation();
+}
+
+bool Source::grab() {
+	unique_lock<shared_mutex> lk(mutex_);
+	if (impl_ && impl_->grab()) {
+		impl_->rgb_.copyTo(rgb_);
+		impl_->depth_.copyTo(depth_);
+		return true;
+	}
+	return false;
+}
diff --git a/components/rgbd-sources/src/stereovideo_source.cpp b/components/rgbd-sources/src/stereovideo.cpp
similarity index 75%
rename from components/rgbd-sources/src/stereovideo_source.cpp
rename to components/rgbd-sources/src/stereovideo.cpp
index 047c9be55..07cc16885 100644
--- a/components/rgbd-sources/src/stereovideo_source.cpp
+++ b/components/rgbd-sources/src/stereovideo.cpp
@@ -1,35 +1,31 @@
 #include <loguru.hpp>
-#include <ftl/stereovideo_source.hpp>
+#include "stereovideo.hpp"
 #include <ftl/configuration.hpp>
 #include "calibrate.hpp"
 #include "local.hpp"
 #include "disparity.hpp"
 #include <mutex>
 
-using ftl::Calibrate;
-using ftl::LocalSource;
-using ftl::rgbd::StereoVideoSource;
+using ftl::rgbd::detail::Calibrate;
+using ftl::rgbd::detail::LocalSource;
+using ftl::rgbd::detail::StereoVideoSource;
 using std::string;
 using std::mutex;
 using std::unique_lock;
 
-StereoVideoSource::StereoVideoSource(nlohmann::json &config, ftl::net::Universe *net)
-		: RGBDSource(config, net) {
+StereoVideoSource::StereoVideoSource(ftl::rgbd::Source *host)
+		: ftl::rgbd::detail::Source(host) {
 
 }
 
-StereoVideoSource::StereoVideoSource(nlohmann::json &config, const string &file)
-		: RGBDSource(config), ready_(false) {
+StereoVideoSource::StereoVideoSource(ftl::rgbd::Source *host, const string &file)
+		: ftl::rgbd::detail::Source(host), ready_(false) {
 
-	REQUIRED({
-		{"feed","Details on source video [object]","object"}
-	});
-	
 	if (ftl::is_video(file)) {
 		// Load video file
 		LOG(INFO) << "Using video file...";
 		//lsrc_ = new LocalSource(file, config["source"]);
-		lsrc_ = ftl::create<LocalSource>(this, "feed", file);
+		lsrc_ = ftl::create<LocalSource>(host_, "feed", file);
 	} else if (file != "") {
 		auto vid = ftl::locateFile("video.mp4");
 		if (!vid) {
@@ -37,19 +33,19 @@ StereoVideoSource::StereoVideoSource(nlohmann::json &config, const string &file)
 		} else {
 			LOG(INFO) << "Using test directory...";
 			//lsrc_ = new LocalSource(*vid, config["source"]);
-			lsrc_ = ftl::create<LocalSource>(this, "feed", *vid);
+			lsrc_ = ftl::create<LocalSource>(host_, "feed", *vid);
 		}
 	} else {
 		// Use cameras
 		LOG(INFO) << "Using cameras...";
 		//lsrc_ = new LocalSource(config["source"]);
-		lsrc_ = ftl::create<LocalSource>(this, "feed");
+		lsrc_ = ftl::create<LocalSource>(host_, "feed");
 	}
 
 	//calib_ = new Calibrate(lsrc_, ftl::resolve(config["calibration"]));
-	calib_ = ftl::create<Calibrate>(this, "calibration", lsrc_);
+	calib_ = ftl::create<Calibrate>(host_, "calibration", lsrc_);
 
-	if (value("calibrate", false)) calib_->recalibrate();
+	if (host_->value("calibrate", false)) calib_->recalibrate();
 	if (!calib_->isCalibrated()) LOG(WARNING) << "Cameras are not calibrated!";
 	else LOG(INFO) << "Calibration initiated.";
 
@@ -73,8 +69,8 @@ StereoVideoSource::StereoVideoSource(nlohmann::json &config, const string &file)
 	calib_->rectifyStereo(mask_l, mask_r);
 	mask_l_ = (mask_l == 0);
 	
-	disp_ = Disparity::create(this, "disparity");
-    if (!disp_) LOG(FATAL) << "Unknown disparity algorithm : " << *get<ftl::config::json_t>("disparity");
+	disp_ = Disparity::create(host_, "disparity");
+    if (!disp_) LOG(FATAL) << "Unknown disparity algorithm : " << *host_->get<ftl::config::json_t>("disparity");
 	disp_->setMask(mask_l_);
 
 	LOG(INFO) << "StereoVideo source ready...";
@@ -110,15 +106,16 @@ static void disparityToDepth(const cv::Mat &disparity, cv::Mat &depth, const cv:
 	}
 }
 
-void StereoVideoSource::grab() {
+bool StereoVideoSource::grab() {
 	calib_->rectified(left_, right_);
 
 	cv::Mat disp;
 	disp_->compute(left_, right_, disp);
 
-	unique_lock<mutex> lk(mutex_);
+	//unique_lock<mutex> lk(mutex_);
 	left_.copyTo(rgb_);
 	disparityToDepth(disp, depth_, calib_->getQ());
+	return true;
 }
 
 bool StereoVideoSource::isReady() {
diff --git a/components/rgbd-sources/include/ftl/stereovideo_source.hpp b/components/rgbd-sources/src/stereovideo.hpp
similarity index 56%
rename from components/rgbd-sources/include/ftl/stereovideo_source.hpp
rename to components/rgbd-sources/src/stereovideo.hpp
index 47e2d089c..8b07e8764 100644
--- a/components/rgbd-sources/include/ftl/stereovideo_source.hpp
+++ b/components/rgbd-sources/src/stereovideo.hpp
@@ -2,48 +2,46 @@
 #ifndef _FTL_RGBD_STEREOVIDEO_HPP_
 #define _FTL_RGBD_STEREOVIDEO_HPP_
 
-#include <ftl/rgbd_source.hpp>
+#include <ftl/rgbd/source.hpp>
 #include <string>
 
 namespace ftl {
 
+namespace rgbd {
+namespace detail {
+
 class LocalSource;
 class Calibrate;
 class Disparity;
 
-namespace rgbd {
-
 /**
  * RGBD source from either a stereo video file with left + right images, or
  * direct from two camera devices. A variety of algorithms are included for
  * calculating disparity, before converting to depth.  Calibration of the images
  * is also performed.
  */
-class StereoVideoSource : public RGBDSource {
+class StereoVideoSource : public detail::Source {
 	public:
-	StereoVideoSource(nlohmann::json &config, ftl::net::Universe *net);
-	StereoVideoSource(nlohmann::json &config, const std::string &file);
+	explicit StereoVideoSource(ftl::rgbd::Source*);
+	StereoVideoSource(ftl::rgbd::Source*, const std::string &);
 	~StereoVideoSource();
 
-	void grab();
+	bool grab();
 	bool isReady();
 
-	const cv::Mat &getRight() const { return right_; }
-
-	static inline RGBDSource *create(nlohmann::json &config, ftl::net::Universe *net) {
-		return new StereoVideoSource(config, net);
-	}
+	//const cv::Mat &getRight() const { return right_; }
 
 	private:
-	ftl::LocalSource *lsrc_;
-	ftl::Calibrate *calib_;
-	ftl::Disparity *disp_;
+	LocalSource *lsrc_;
+	Calibrate *calib_;
+	Disparity *disp_;
 	bool ready_;
 	cv::Mat left_;
 	cv::Mat right_;
 	cv::Mat mask_l_;
 };
 
+}
 }
 }
 
diff --git a/components/rgbd-sources/src/rgbd_streamer.cpp b/components/rgbd-sources/src/streamer.cpp
similarity index 93%
rename from components/rgbd-sources/src/rgbd_streamer.cpp
rename to components/rgbd-sources/src/streamer.cpp
index 9ab2d184f..2ea5babc8 100644
--- a/components/rgbd-sources/src/rgbd_streamer.cpp
+++ b/components/rgbd-sources/src/streamer.cpp
@@ -1,11 +1,11 @@
-#include <ftl/rgbd_streamer.hpp>
+#include <ftl/rgbd/streamer.hpp>
 #include <vector>
 #include <optional>
 #include <thread>
 #include <chrono>
 
 using ftl::rgbd::Streamer;
-using ftl::rgbd::RGBDSource;
+using ftl::rgbd::Source;
 using ftl::rgbd::detail::StreamSource;
 using ftl::rgbd::detail::StreamClient;
 using ftl::net::Universe;
@@ -60,9 +60,9 @@ Streamer::Streamer(nlohmann::json &config, Universe *net)
 		shared_lock<shared_mutex> slk(mutex_);
 
 		if (sources_.find(uri) != sources_.end()) {
-			buf.resize(sizeof(CameraParameters));
+			buf.resize(sizeof(Camera));
 			LOG(INFO) << "Calib buf size = " << buf.size();
-			memcpy(buf.data(), &sources_[uri]->src->getParameters(), buf.size());
+			memcpy(buf.data(), &sources_[uri]->src->parameters(), buf.size());
 		}
 		return buf;
 	});
@@ -90,16 +90,16 @@ Streamer::~Streamer() {
 	pool_.stop();
 }
 
-void Streamer::add(RGBDSource *src) {
+void Streamer::add(Source *src) {
 	unique_lock<shared_mutex> ulk(mutex_);
-	if (sources_.find(src->getURI()) != sources_.end()) return;
+	if (sources_.find(src->getID()) != sources_.end()) return;
 
 	StreamSource *s = new StreamSource;
 	s->src = src;
 	s->state = 0;
-	sources_[src->getURI()] = s;
+	sources_[src->getID()] = s;
 
-	LOG(INFO) << "Streaming: " << src->getURI();
+	LOG(INFO) << "Streaming: " << src->getID();
 }
 
 void Streamer::_addClient(const string &source, int N, int rate, const ftl::UUID &peer, const string &dest) {
@@ -120,7 +120,7 @@ void Streamer::_addClient(const string &source, int N, int rate, const ftl::UUID
 	s->clients[rate].push_back(c);
 }
 
-void Streamer::remove(RGBDSource *) {
+void Streamer::remove(Source *) {
 
 }
 
@@ -170,7 +170,7 @@ void Streamer::run(bool block) {
 
 void Streamer::_swap(StreamSource &src) {
 	if (src.state == (ftl::rgbd::detail::kGrabbed | ftl::rgbd::detail::kTransmitted)) {
-		src.src->getRGBD(src.rgb, src.depth);
+		src.src->getFrames(src.rgb, src.depth);
 		src.state = 0;
 	}
 }
@@ -293,7 +293,7 @@ void Streamer::_schedule() {
 	job_cv.wait(lk, [&jobs]{ return jobs == 0; });
 }
 
-RGBDSource *Streamer::get(const std::string &uri) {
+Source *Streamer::get(const std::string &uri) {
 	shared_lock<shared_mutex> slk(mutex_);
 	if (sources_.find(uri) != sources_.end()) return sources_[uri]->src;
 	else return nullptr;
diff --git a/components/rgbd-sources/test/CMakeLists.txt b/components/rgbd-sources/test/CMakeLists.txt
new file mode 100644
index 000000000..538c4d757
--- /dev/null
+++ b/components/rgbd-sources/test/CMakeLists.txt
@@ -0,0 +1,10 @@
+### Source Unit ################################################################
+add_executable(source_unit
+	./tests.cpp
+	./source_unit.cpp
+)
+target_include_directories(source_unit PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../include")
+target_link_libraries(source_unit
+	ftlcommon Eigen3::Eigen)
+
+add_test(SourceUnitTest source_unit)
diff --git a/components/rgbd-sources/test/catch.hpp b/components/rgbd-sources/test/catch.hpp
new file mode 100644
index 000000000..b1b2411d2
--- /dev/null
+++ b/components/rgbd-sources/test/catch.hpp
@@ -0,0 +1,14362 @@
+/*
+ *  Catch v2.5.0
+ *  Generated: 2018-11-26 20:46:12.165372
+ *  ----------------------------------------------------------
+ *  This file has been merged from multiple headers. Please don't edit it directly
+ *  Copyright (c) 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_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
+#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
+// start catch.hpp
+
+
+#define CATCH_VERSION_MAJOR 2
+#define CATCH_VERSION_MINOR 5
+#define CATCH_VERSION_PATCH 0
+
+#ifdef __clang__
+#    pragma clang system_header
+#elif defined __GNUC__
+#    pragma GCC system_header
+#endif
+
+// start catch_suppress_warnings.h
+
+#ifdef __clang__
+#   ifdef __ICC // icpc defines the __clang__ macro
+#       pragma warning(push)
+#       pragma warning(disable: 161 1682)
+#   else // __ICC
+#       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__
+     // GCC likes to warn on REQUIREs, and we cannot suppress them
+     // locally because g++'s support for _Pragma is lacking in older,
+     // still supported, versions
+#    pragma GCC diagnostic ignored "-Wparentheses"
+#    pragma GCC diagnostic push
+#    pragma GCC diagnostic ignored "-Wunused-variable"
+#    pragma GCC diagnostic ignored "-Wpadded"
+#endif
+// end catch_suppress_warnings.h
+#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
+#  define CATCH_IMPL
+#  define CATCH_CONFIG_ALL_PARTS
+#endif
+
+// In the impl file, we want to have access to all parts of the headers
+// Can also be used to sanely support PCHs
+#if defined(CATCH_CONFIG_ALL_PARTS)
+#  define CATCH_CONFIG_EXTERNAL_INTERFACES
+#  if defined(CATCH_CONFIG_DISABLE_MATCHERS)
+#    undef CATCH_CONFIG_DISABLE_MATCHERS
+#  endif
+#  if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
+#    define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
+#  endif
+#endif
+
+#if !defined(CATCH_CONFIG_IMPL_ONLY)
+// start catch_platform.h
+
+#ifdef __APPLE__
+# include <TargetConditionals.h>
+# if TARGET_OS_OSX == 1
+#  define CATCH_PLATFORM_MAC
+# elif TARGET_OS_IPHONE == 1
+#  define CATCH_PLATFORM_IPHONE
+# endif
+
+#elif defined(linux) || defined(__linux) || defined(__linux__)
+#  define CATCH_PLATFORM_LINUX
+
+#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__)
+#  define CATCH_PLATFORM_WINDOWS
+#endif
+
+// end catch_platform.h
+
+#ifdef CATCH_IMPL
+#  ifndef CLARA_CONFIG_MAIN
+#    define CLARA_CONFIG_MAIN_NOT_DEFINED
+#    define CLARA_CONFIG_MAIN
+#  endif
+#endif
+
+// start catch_user_interfaces.h
+
+namespace Catch {
+    unsigned int rngSeed();
+}
+
+// end catch_user_interfaces.h
+// start catch_tag_alias_autoregistrar.h
+
+// start catch_common.h
+
+// start catch_compiler_capabilities.h
+
+// Detect a number of compiler features - by compiler
+// The following features are defined:
+//
+// 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
+// ****************
+
+// In general each macro has a _NO_<feature name> form
+// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature.
+// Many features, at point of detection, define an _INTERNAL_ macro, so they
+// can be combined, en-mass, with the _NO_ forms later.
+
+#ifdef __cplusplus
+
+#  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__
+
+#       define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+            _Pragma( "clang diagnostic push" ) \
+            _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \
+            _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"")
+#       define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
+            _Pragma( "clang diagnostic pop" )
+
+#       define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
+            _Pragma( "clang diagnostic push" ) \
+            _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
+#       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__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__)
+    #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
+#endif
+
+#ifdef __OS400__
+#       define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
+#       define CATCH_CONFIG_COLOUR_NONE
+#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)
+#    define CATCH_CONFIG_COLOUR_NONE
+#  else
+#    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
+// handled by it.
+// Otherwise all supported compilers support COUNTER macro,
+// but user still might want to turn it off
+#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L )
+    #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 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)
+#    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) && !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_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_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
+#   define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
+#endif
+#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS)
+#   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
+#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
+#ifdef CATCH_CONFIG_COUNTER
+#  define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
+#else
+#  define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
+#endif
+
+#include <iosfwd>
+#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 {
+        Yes,
+        No
+    }; };
+
+    class NonCopyable {
+        NonCopyable( NonCopyable const& )              = delete;
+        NonCopyable( NonCopyable && )                  = delete;
+        NonCopyable& operator = ( NonCopyable const& ) = delete;
+        NonCopyable& operator = ( NonCopyable && )     = delete;
+
+    protected:
+        NonCopyable();
+        virtual ~NonCopyable();
+    };
+
+    struct SourceLineInfo {
+
+        SourceLineInfo() = delete;
+        SourceLineInfo( char const* _file, std::size_t _line ) noexcept
+        :   file( _file ),
+            line( _line )
+        {}
+
+        SourceLineInfo( SourceLineInfo const& other )        = default;
+        SourceLineInfo( SourceLineInfo && )                  = default;
+        SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
+        SourceLineInfo& operator = ( SourceLineInfo && )     = default;
+
+        bool empty() const noexcept;
+        bool operator == ( SourceLineInfo const& other ) const noexcept;
+        bool operator < ( SourceLineInfo const& other ) const noexcept;
+
+        char const* file;
+        std::size_t line;
+    };
+
+    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
+    //    >> stuff +StreamEndStop
+    struct StreamEndStop {
+        std::string operator+() const;
+    };
+    template<typename T>
+    T const& operator + ( T const& value, StreamEndStop ) {
+        return value;
+    }
+}
+
+#define CATCH_INTERNAL_LINEINFO \
+    ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
+
+// end catch_common.h
+namespace Catch {
+
+    struct RegistrarForTagAliases {
+        RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
+    };
+
+} // end namespace Catch
+
+#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \
+    CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+    namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \
+    CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
+
+// end catch_tag_alias_autoregistrar.h
+// start catch_test_registry.h
+
+// start catch_interfaces_testcase.h
+
+#include <vector>
+#include <memory>
+
+namespace Catch {
+
+    class TestSpec;
+
+    struct ITestInvoker {
+        virtual void invoke () const = 0;
+        virtual ~ITestInvoker();
+    };
+
+    using ITestCasePtr = std::shared_ptr<ITestInvoker>;
+
+    class TestCase;
+    struct IConfig;
+
+    struct ITestCaseRegistry {
+        virtual ~ITestCaseRegistry();
+        virtual std::vector<TestCase> const& getAllTests() const = 0;
+        virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
+    };
+
+    bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
+    std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
+    std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
+
+}
+
+// end catch_interfaces_testcase.h
+// start catch_stringref.h
+
+#include <cstddef>
+#include <string>
+#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,
+    /// it may not be null terminated. c_str() must return a null terminated
+    /// string, however, and so the StringRef will internally take ownership
+    /// (taking a copy), if necessary. In theory this ownership is not externally
+    /// visible - but it does mean (substring) StringRefs should not be shared between
+    /// threads.
+    class StringRef {
+    public:
+        using size_type = std::size_t;
+
+    private:
+        friend struct StringRefTestAccess;
+
+        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 )
+        {}
+
+        StringRef( StringRef const& other ) noexcept
+        :   m_start( other.m_start ),
+            m_size( other.m_size )
+        {}
+
+        StringRef( StringRef&& other ) noexcept
+        :   m_start( other.m_start ),
+            m_size( other.m_size ),
+            m_data( other.m_data )
+        {
+            other.m_data = nullptr;
+        }
+
+        StringRef( char const* rawChars ) noexcept;
+
+        StringRef( char const* rawChars, size_type size ) noexcept
+        :   m_start( rawChars ),
+            m_size( size )
+        {}
+
+        StringRef( std::string const& stdString ) noexcept
+        :   m_start( stdString.c_str() ),
+            m_size( stdString.size() )
+        {}
+
+        ~StringRef() noexcept {
+            delete[] m_data;
+        }
+
+        auto operator = ( StringRef const &other ) noexcept -> StringRef& {
+            delete[] m_data;
+            m_data = nullptr;
+            m_start = other.m_start;
+            m_size = other.m_size;
+            return *this;
+        }
+
+        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;
+        }
+        auto size() const noexcept -> size_type {
+            return m_size;
+        }
+
+        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 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 );
+}
+
+// end catch_stringref.h
+// start catch_type_traits.hpp
+
+
+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_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
+
+// end catch_preprocessor.hpp
+namespace Catch {
+
+template<typename C>
+class TestInvokerAsMethod : public ITestInvoker {
+    void (C::*m_testAsMethod)();
+public:
+    TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {}
+
+    void invoke() const override {
+        C obj;
+        (obj.*m_testAsMethod)();
+    }
+};
+
+auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*;
+
+template<typename C>
+auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* {
+    return new(std::nothrow) TestInvokerAsMethod<C>( testAsMethod );
+}
+
+struct NameAndTags {
+    NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept;
+    StringRef name;
+    StringRef tags;
+};
+
+struct AutoReg : NonCopyable {
+    AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept;
+    ~AutoReg();
+};
+
+} // end namespace Catch
+
+#if defined(CATCH_CONFIG_DISABLE)
+    #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
+        static void TestName()
+    #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
+        namespace{                        \
+            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::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
+        CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
+        static void TestName()
+    #define INTERNAL_CATCH_TESTCASE( ... ) \
+        INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
+
+    ///////////////////////////////////////////////////////////////////////////////
+    #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+        namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
+        CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
+
+    ///////////////////////////////////////////////////////////////////////////////
+    #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+        namespace{ \
+            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 */ \
+        } \
+        CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
+        void TestName::test()
+    #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
+        INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
+
+    ///////////////////////////////////////////////////////////////////////////////
+    #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::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_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
+
+// end catch_test_registry.h
+// start catch_capture.hpp
+
+// start catch_assertionhandler.h
+
+// start catch_assertioninfo.h
+
+// start catch_result_type.h
+
+namespace Catch {
+
+    // ResultWas::OfType enum
+    struct ResultWas { enum OfType {
+        Unknown = -1,
+        Ok = 0,
+        Info = 1,
+        Warning = 2,
+
+        FailureBit = 0x10,
+
+        ExpressionFailed = FailureBit | 1,
+        ExplicitFailure = FailureBit | 2,
+
+        Exception = 0x100 | FailureBit,
+
+        ThrewException = Exception | 1,
+        DidntThrowException = Exception | 2,
+
+        FatalErrorCondition = 0x200 | FailureBit
+
+    }; };
+
+    bool isOk( ResultWas::OfType resultType );
+    bool isJustInfo( int flags );
+
+    // ResultDisposition::Flags enum
+    struct ResultDisposition { enum Flags {
+        Normal = 0x01,
+
+        ContinueOnFailure = 0x02,   // Failures fail test, but execution continues
+        FalseTest = 0x04,           // Prefix expression with !
+        SuppressFail = 0x08         // Failures are reported but do not fail the test
+    }; };
+
+    ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs );
+
+    bool shouldContinueOnFailure( int flags );
+    inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
+    bool shouldSuppressFailure( int flags );
+
+} // end namespace Catch
+
+// end catch_result_type.h
+namespace Catch {
+
+    struct AssertionInfo
+    {
+        StringRef macroName;
+        SourceLineInfo lineInfo;
+        StringRef capturedExpression;
+        ResultDisposition::Flags resultDisposition;
+
+        // We want to delete this constructor but a compiler bug in 4.8 means
+        // the struct is then treated as non-aggregate
+        //AssertionInfo() = delete;
+    };
+
+} // end namespace Catch
+
+// end catch_assertioninfo.h
+// start catch_decomposer.h
+
+// start catch_tostring.h
+
+#include <vector>
+#include <cstddef>
+#include <type_traits>
+#include <string>
+// start catch_stream.h
+
+#include <iosfwd>
+#include <cstddef>
+#include <ostream>
+
+namespace Catch {
+
+    std::ostream& cout();
+    std::ostream& cerr();
+    std::ostream& clog();
+
+    class StringRef;
+
+    struct IStream {
+        virtual ~IStream();
+        virtual std::ostream& stream() const = 0;
+    };
+
+    auto makeStream( StringRef const &filename ) -> IStream const*;
+
+    class ReusableStringStream {
+        std::size_t m_index;
+        std::ostream* m_oss;
+    public:
+        ReusableStringStream();
+        ~ReusableStringStream();
+
+        auto str() const -> std::string;
+
+        template<typename T>
+        auto operator << ( T const& value ) -> ReusableStringStream& {
+            *m_oss << value;
+            return *this;
+        }
+        auto get() -> std::ostream& { return *m_oss; }
+    };
+}
+
+// end catch_stream.h
+
+#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
+#include <string_view>
+#endif
+
+#ifdef __OBJC__
+// start catch_objc_arc.hpp
+
+#import <Foundation/Foundation.h>
+
+#ifdef __has_feature
+#define CATCH_ARC_ENABLED __has_feature(objc_arc)
+#else
+#define CATCH_ARC_ENABLED 0
+#endif
+
+void arcSafeRelease( NSObject* obj );
+id performOptionalSelector( id obj, SEL sel );
+
+#if !CATCH_ARC_ENABLED
+inline void arcSafeRelease( NSObject* obj ) {
+    [obj release];
+}
+inline id performOptionalSelector( id obj, SEL sel ) {
+    if( [obj respondsToSelector: sel] )
+        return [obj performSelector: sel];
+    return nil;
+}
+#define CATCH_UNSAFE_UNRETAINED
+#define CATCH_ARC_STRONG
+#else
+inline void arcSafeRelease( NSObject* ){}
+inline id performOptionalSelector( id obj, SEL sel ) {
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
+#endif
+    if( [obj respondsToSelector: sel] )
+        return [obj performSelector: sel];
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+    return nil;
+}
+#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
+#define CATCH_ARC_STRONG __strong
+#endif
+
+// end catch_objc_arc.hpp
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless
+#endif
+
+namespace Catch {
+    namespace Detail {
+
+        extern const std::string unprintableString;
+
+        std::string rawMemoryToString( const void *object, std::size_t size );
+
+        template<typename T>
+        std::string rawMemoryToString( const T& object ) {
+          return rawMemoryToString( &object, sizeof(object) );
+        }
+
+        template<typename T>
+        class IsStreamInsertable {
+            template<typename SS, typename TT>
+            static auto test(int)
+                -> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type());
+
+            template<typename, typename>
+            static auto test(...)->std::false_type;
+
+        public:
+            static const bool value = decltype(test<std::ostream, const T&>(0))::value;
+        };
+
+        template<typename E>
+        std::string convertUnknownEnumToString( E e );
+
+        template<typename T>
+        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::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
+
+    // If we decide for C++14, change these to enable_if_ts
+    template <typename T, typename = void>
+    struct StringMaker {
+        template <typename Fake = T>
+        static
+        typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
+            convert(const Fake& value) {
+                ReusableStringStream rss;
+                // NB: call using the function-like syntax to avoid ambiguity with
+                // user-defined templated operator<< under clang.
+                rss.operator<<(value);
+                return rss.str();
+        }
+
+        template <typename Fake = T>
+        static
+        typename std::enable_if<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
+            convert( const Fake& value ) {
+#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
+            return Detail::convertUnstreamable(value);
+#else
+            return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);
+#endif
+        }
+    };
+
+    namespace Detail {
+
+        // This function dispatches all stringification requests inside of Catch.
+        // Should be preferably called fully qualified, like ::Catch::Detail::stringify
+        template <typename T>
+        std::string stringify(const T& e) {
+            return ::Catch::StringMaker<typename std::remove_cv<typename std::remove_reference<T>::type>::type>::convert(e);
+        }
+
+        template<typename E>
+        std::string convertUnknownEnumToString( E e ) {
+            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
+
+    template<>
+    struct StringMaker<std::string> {
+        static std::string convert(const std::string& str);
+    };
+
+#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
+    template<>
+    struct StringMaker<std::string_view> {
+        static std::string convert(std::string_view str);
+    };
+#endif
+
+    template<>
+    struct StringMaker<char const *> {
+        static std::string convert(char const * str);
+    };
+    template<>
+    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);
+    };
+    template<>
+    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(char const* str) {
+            return ::Catch::Detail::stringify(std::string{ str });
+        }
+    };
+    template<int SZ>
+    struct StringMaker<signed char[SZ]> {
+        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(unsigned char const* str) {
+            return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) });
+        }
+    };
+
+    template<>
+    struct StringMaker<int> {
+        static std::string convert(int value);
+    };
+    template<>
+    struct StringMaker<long> {
+        static std::string convert(long value);
+    };
+    template<>
+    struct StringMaker<long long> {
+        static std::string convert(long long value);
+    };
+    template<>
+    struct StringMaker<unsigned int> {
+        static std::string convert(unsigned int value);
+    };
+    template<>
+    struct StringMaker<unsigned long> {
+        static std::string convert(unsigned long value);
+    };
+    template<>
+    struct StringMaker<unsigned long long> {
+        static std::string convert(unsigned long long value);
+    };
+
+    template<>
+    struct StringMaker<bool> {
+        static std::string convert(bool b);
+    };
+
+    template<>
+    struct StringMaker<char> {
+        static std::string convert(char c);
+    };
+    template<>
+    struct StringMaker<signed char> {
+        static std::string convert(signed char c);
+    };
+    template<>
+    struct StringMaker<unsigned char> {
+        static std::string convert(unsigned char c);
+    };
+
+    template<>
+    struct StringMaker<std::nullptr_t> {
+        static std::string convert(std::nullptr_t);
+    };
+
+    template<>
+    struct StringMaker<float> {
+        static std::string convert(float value);
+    };
+    template<>
+    struct StringMaker<double> {
+        static std::string convert(double value);
+    };
+
+    template <typename T>
+    struct StringMaker<T*> {
+        template <typename U>
+        static std::string convert(U* p) {
+            if (p) {
+                return ::Catch::Detail::rawMemoryToString(p);
+            } else {
+                return "nullptr";
+            }
+        }
+    };
+
+    template <typename R, typename C>
+    struct StringMaker<R C::*> {
+        static std::string convert(R C::* p) {
+            if (p) {
+                return ::Catch::Detail::rawMemoryToString(p);
+            } else {
+                return "nullptr";
+            }
+        }
+    };
+
+#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) {
+            ReusableStringStream rss;
+            rss << "{ ";
+            if (first != last) {
+                rss << ::Catch::Detail::stringify(*first);
+                for (++first; first != last; ++first)
+                    rss << ", " << ::Catch::Detail::stringify(*first);
+            }
+            rss << " }";
+            return rss.str();
+        }
+    }
+
+#ifdef __OBJC__
+    template<>
+    struct StringMaker<NSString*> {
+        static std::string convert(NSString * nsstring) {
+            if (!nsstring)
+                return "nil";
+            return std::string("@") + [nsstring UTF8String];
+        }
+    };
+    template<>
+    struct StringMaker<NSObject*> {
+        static std::string convert(NSObject* nsObject) {
+            return ::Catch::Detail::stringify([nsObject description]);
+        }
+
+    };
+    namespace Detail {
+        inline std::string stringify( NSString* nsstring ) {
+            return StringMaker<NSString*>::convert( nsstring );
+        }
+
+    } // namespace Detail
+#endif // __OBJC__
+
+} // namespace Catch
+
+//////////////////////////////////////////////////////
+// Separate std-lib types stringification, so it can be selectively enabled
+// This means that we do not bring in
+
+#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
+#endif
+
+// Separate std::pair specialization
+#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER)
+#include <utility>
+namespace Catch {
+    template<typename T1, typename T2>
+    struct StringMaker<std::pair<T1, T2> > {
+        static std::string convert(const std::pair<T1, T2>& pair) {
+            ReusableStringStream rss;
+            rss << "{ "
+                << ::Catch::Detail::stringify(pair.first)
+                << ", "
+                << ::Catch::Detail::stringify(pair.second)
+                << " }";
+            return rss.str();
+        }
+    };
+}
+#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
+
+// Separate std::tuple specialization
+#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
+#include <tuple>
+namespace Catch {
+    namespace Detail {
+        template<
+            typename Tuple,
+            std::size_t N = 0,
+            bool = (N < std::tuple_size<Tuple>::value)
+            >
+            struct TupleElementPrinter {
+            static void print(const Tuple& tuple, std::ostream& os) {
+                os << (N ? ", " : " ")
+                    << ::Catch::Detail::stringify(std::get<N>(tuple));
+                TupleElementPrinter<Tuple, N + 1>::print(tuple, os);
+            }
+        };
+
+        template<
+            typename Tuple,
+            std::size_t N
+        >
+            struct TupleElementPrinter<Tuple, N, false> {
+            static void print(const Tuple&, std::ostream&) {}
+        };
+
+    }
+
+    template<typename ...Types>
+    struct StringMaker<std::tuple<Types...>> {
+        static std::string convert(const std::tuple<Types...>& tuple) {
+            ReusableStringStream rss;
+            rss << '{';
+            Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get());
+            rss << " }";
+            return rss.str();
+        }
+    };
+}
+#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
+
+    // Import begin/ end from std here so they are considered alongside the fallback (...) overloads in this namespace
+    using std::begin;
+    using std::end;
+
+    not_this_one begin( ... );
+    not_this_one end( ... );
+
+    template <typename T>
+    struct is_range {
+        static const bool value =
+            !std::is_same<decltype(begin(std::declval<T>())), not_this_one>::value &&
+            !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 ) );
+    }
+
+    // Handle vector<bool> specially
+    template<typename Allocator>
+    std::string rangeToString( std::vector<bool, Allocator> const& v ) {
+        ReusableStringStream rss;
+        rss << "{ ";
+        bool first = true;
+        for( bool b : v ) {
+            if( first )
+                first = false;
+            else
+                rss << ", ";
+            rss << ::Catch::Detail::stringify( b );
+        }
+        rss << " }";
+        return rss.str();
+    }
+
+    template<typename R>
+    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 );
+        }
+    };
+
+    template <typename T, int SZ>
+    struct StringMaker<T[SZ]> {
+        static std::string convert(T const(&arr)[SZ]) {
+            return rangeToString(arr);
+        }
+    };
+
+} // namespace Catch
+
+// Separate std::chrono::duration specialization
+#if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
+#include <ctime>
+#include <ratio>
+#include <chrono>
+
+namespace Catch {
+
+template <class Ratio>
+struct ratio_string {
+    static std::string symbol();
+};
+
+template <class Ratio>
+std::string ratio_string<Ratio>::symbol() {
+    Catch::ReusableStringStream rss;
+    rss << '[' << Ratio::num << '/'
+        << Ratio::den << ']';
+    return rss.str();
+}
+template <>
+struct ratio_string<std::atto> {
+    static std::string symbol();
+};
+template <>
+struct ratio_string<std::femto> {
+    static std::string symbol();
+};
+template <>
+struct ratio_string<std::pico> {
+    static std::string symbol();
+};
+template <>
+struct ratio_string<std::nano> {
+    static std::string symbol();
+};
+template <>
+struct ratio_string<std::micro> {
+    static std::string symbol();
+};
+template <>
+struct ratio_string<std::milli> {
+    static std::string symbol();
+};
+
+    ////////////
+    // std::chrono::duration specializations
+    template<typename Value, typename Ratio>
+    struct StringMaker<std::chrono::duration<Value, Ratio>> {
+        static std::string convert(std::chrono::duration<Value, Ratio> const& duration) {
+            ReusableStringStream rss;
+            rss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's';
+            return rss.str();
+        }
+    };
+    template<typename Value>
+    struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> {
+        static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) {
+            ReusableStringStream rss;
+            rss << duration.count() << " s";
+            return rss.str();
+        }
+    };
+    template<typename Value>
+    struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> {
+        static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) {
+            ReusableStringStream rss;
+            rss << duration.count() << " m";
+            return rss.str();
+        }
+    };
+    template<typename Value>
+    struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> {
+        static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) {
+            ReusableStringStream rss;
+            rss << duration.count() << " h";
+            return rss.str();
+        }
+    };
+
+    ////////////
+    // std::chrono::time_point specialization
+    // Generic time_point cannot be specialized, only std::chrono::time_point<system_clock>
+    template<typename Clock, typename Duration>
+    struct StringMaker<std::chrono::time_point<Clock, Duration>> {
+        static std::string convert(std::chrono::time_point<Clock, Duration> const& time_point) {
+            return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch";
+        }
+    };
+    // std::chrono::time_point<system_clock> specialization
+    template<typename Duration>
+    struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> {
+        static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration> const& time_point) {
+            auto converted = std::chrono::system_clock::to_time_t(time_point);
+
+#ifdef _MSC_VER
+            std::tm timeInfo = {};
+            gmtime_s(&timeInfo, &converted);
+#else
+            std::tm* timeInfo = std::gmtime(&converted);
+#endif
+
+            auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
+            char timeStamp[timeStampSize];
+            const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
+
+#ifdef _MSC_VER
+            std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
+#else
+            std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
+#endif
+            return std::string(timeStamp);
+        }
+    };
+}
+#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+// end catch_tostring.h
+#include <iosfwd>
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
+#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
+#endif
+
+namespace Catch {
+
+    struct ITransientExpression {
+        auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
+        auto getResult() const -> bool { return m_result; }
+        virtual void streamReconstructedExpression( std::ostream &os ) const = 0;
+
+        ITransientExpression( bool isBinaryExpression, bool result )
+        :   m_isBinaryExpression( isBinaryExpression ),
+            m_result( result )
+        {}
+
+        // We don't actually need a virtual destructor, but many static analysers
+        // complain if it's not here :-(
+        virtual ~ITransientExpression();
+
+        bool m_isBinaryExpression;
+        bool m_result;
+
+    };
+
+    void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );
+
+    template<typename LhsT, typename RhsT>
+    class BinaryExpr  : public ITransientExpression {
+        LhsT m_lhs;
+        StringRef m_op;
+        RhsT m_rhs;
+
+        void streamReconstructedExpression( std::ostream &os ) const override {
+            formatReconstructedExpression
+                    ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) );
+        }
+
+    public:
+        BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )
+        :   ITransientExpression{ true, comparisonResult },
+            m_lhs( lhs ),
+            m_op( op ),
+            m_rhs( rhs )
+        {}
+    };
+
+    template<typename LhsT>
+    class UnaryExpr : public ITransientExpression {
+        LhsT m_lhs;
+
+        void streamReconstructedExpression( std::ostream &os ) const override {
+            os << Catch::Detail::stringify( m_lhs );
+        }
+
+    public:
+        explicit UnaryExpr( LhsT lhs )
+        :   ITransientExpression{ false, lhs ? true : false },
+            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); }
+    template<typename T>
+    auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }
+    template<typename T>
+    auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }
+    template<typename T>
+    auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }
+    template<typename T>
+    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); }
+    template<typename T>
+    auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }
+    template<typename T>
+    auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }
+    template<typename T>
+    auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; }
+    template<typename T>
+    auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; }
+
+    template<typename LhsT>
+    class ExprLhs {
+        LhsT m_lhs;
+    public:
+        explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
+
+        template<typename RhsT>
+        auto operator == ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
+            return { compareEqual( m_lhs, rhs ), m_lhs, "==", rhs };
+        }
+        auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
+            return { m_lhs == rhs, m_lhs, "==", rhs };
+        }
+
+        template<typename RhsT>
+        auto operator != ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
+            return { compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs };
+        }
+        auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
+            return { m_lhs != rhs, m_lhs, "!=", rhs };
+        }
+
+        template<typename RhsT>
+        auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
+            return { static_cast<bool>(m_lhs > rhs), m_lhs, ">", rhs };
+        }
+        template<typename RhsT>
+        auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
+            return { static_cast<bool>(m_lhs < rhs), m_lhs, "<", rhs };
+        }
+        template<typename RhsT>
+        auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
+            return { static_cast<bool>(m_lhs >= rhs), m_lhs, ">=", rhs };
+        }
+        template<typename RhsT>
+        auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
+            return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };
+        }
+
+        auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
+            return UnaryExpr<LhsT>{ m_lhs };
+        }
+    };
+
+    void handleExpression( ITransientExpression const& expr );
+
+    template<typename T>
+    void handleExpression( ExprLhs<T> const& expr ) {
+        handleExpression( expr.makeUnaryExpr() );
+    }
+
+    struct Decomposer {
+        template<typename T>
+        auto operator <= ( T const& lhs ) -> ExprLhs<T const&> {
+            return ExprLhs<T const&>{ lhs };
+        }
+
+        auto operator <=( bool value ) -> ExprLhs<bool> {
+            return ExprLhs<bool>{ value };
+        }
+    };
+
+} // end namespace Catch
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+// end catch_decomposer.h
+// start catch_interfaces_capture.h
+
+#include <string>
+
+namespace Catch {
+
+    class AssertionResult;
+    struct AssertionInfo;
+    struct SectionInfo;
+    struct SectionEndInfo;
+    struct MessageInfo;
+    struct Counts;
+    struct BenchmarkInfo;
+    struct BenchmarkStats;
+    struct AssertionReaction;
+    struct SourceLineInfo;
+
+    struct ITransientExpression;
+    struct IGeneratorTracker;
+
+    struct IResultCapture {
+
+        virtual ~IResultCapture();
+
+        virtual bool sectionStarted(    SectionInfo const& sectionInfo,
+                                        Counts& assertions ) = 0;
+        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 handleFatalErrorCondition( StringRef message ) = 0;
+
+        virtual void handleExpr
+                (   AssertionInfo const& info,
+                    ITransientExpression const& expr,
+                    AssertionReaction& reaction ) = 0;
+        virtual void handleMessage
+                (   AssertionInfo const& info,
+                    ResultWas::OfType resultType,
+                    StringRef const& message,
+                    AssertionReaction& reaction ) = 0;
+        virtual void handleUnexpectedExceptionNotThrown
+                (   AssertionInfo const& info,
+                    AssertionReaction& reaction ) = 0;
+        virtual void handleUnexpectedInflightException
+                (   AssertionInfo const& info,
+                    std::string const& message,
+                    AssertionReaction& reaction ) = 0;
+        virtual void handleIncomplete
+                (   AssertionInfo const& info ) = 0;
+        virtual void handleNonExpr
+                (   AssertionInfo const &info,
+                    ResultWas::OfType resultType,
+                    AssertionReaction &reaction ) = 0;
+
+        virtual bool lastAssertionPassed() = 0;
+        virtual void assertionPassed() = 0;
+
+        // Deprecated, do not use:
+        virtual std::string getCurrentTestName() const = 0;
+        virtual const AssertionResult* getLastResult() const = 0;
+        virtual void exceptionEarlyReported() = 0;
+    };
+
+    IResultCapture& getResultCapture();
+}
+
+// end catch_interfaces_capture.h
+namespace Catch {
+
+    struct TestFailureException{};
+    struct AssertionResultData;
+    struct IResultCapture;
+    class RunContext;
+
+    class LazyExpression {
+        friend class AssertionHandler;
+        friend struct AssertionStats;
+        friend class RunContext;
+
+        ITransientExpression const* m_transientExpression = nullptr;
+        bool m_isNegated;
+    public:
+        LazyExpression( bool isNegated );
+        LazyExpression( LazyExpression const& other );
+        LazyExpression& operator = ( LazyExpression const& ) = delete;
+
+        explicit operator bool() const;
+
+        friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&;
+    };
+
+    struct AssertionReaction {
+        bool shouldDebugBreak = false;
+        bool shouldThrow = false;
+    };
+
+    class AssertionHandler {
+        AssertionInfo m_assertionInfo;
+        AssertionReaction m_reaction;
+        bool m_completed = false;
+        IResultCapture& m_resultCapture;
+
+    public:
+        AssertionHandler
+            (   StringRef const& macroName,
+                SourceLineInfo const& lineInfo,
+                StringRef capturedExpression,
+                ResultDisposition::Flags resultDisposition );
+        ~AssertionHandler() {
+            if ( !m_completed ) {
+                m_resultCapture.handleIncomplete( m_assertionInfo );
+            }
+        }
+
+        template<typename T>
+        void handleExpr( ExprLhs<T> const& expr ) {
+            handleExpr( expr.makeUnaryExpr() );
+        }
+        void handleExpr( ITransientExpression const& expr );
+
+        void handleMessage(ResultWas::OfType resultType, StringRef const& message);
+
+        void handleExceptionThrownAsExpected();
+        void handleUnexpectedExceptionNotThrown();
+        void handleExceptionNotThrownAsExpected();
+        void handleThrowingCallSkipped();
+        void handleUnexpectedInflightException();
+
+        void complete();
+        void setCompleted();
+
+        // query
+        auto allowThrows() const -> bool;
+    };
+
+    void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString );
+
+} // namespace Catch
+
+// end catch_assertionhandler.h
+// start catch_message.h
+
+#include <string>
+#include <vector>
+
+namespace Catch {
+
+    struct MessageInfo {
+        MessageInfo(    StringRef const& _macroName,
+                        SourceLineInfo const& _lineInfo,
+                        ResultWas::OfType _type );
+
+        StringRef macroName;
+        std::string message;
+        SourceLineInfo lineInfo;
+        ResultWas::OfType type;
+        unsigned int sequence;
+
+        bool operator == ( MessageInfo const& other ) const;
+        bool operator < ( MessageInfo const& other ) const;
+    private:
+        static unsigned int globalCount;
+    };
+
+    struct MessageStream {
+
+        template<typename T>
+        MessageStream& operator << ( T const& value ) {
+            m_stream << value;
+            return *this;
+        }
+
+        ReusableStringStream m_stream;
+    };
+
+    struct MessageBuilder : MessageStream {
+        MessageBuilder( StringRef const& macroName,
+                        SourceLineInfo const& lineInfo,
+                        ResultWas::OfType type );
+
+        template<typename T>
+        MessageBuilder& operator << ( T const& value ) {
+            m_stream << value;
+            return *this;
+        }
+
+        MessageInfo m_info;
+    };
+
+    class ScopedMessage {
+    public:
+        explicit ScopedMessage( MessageBuilder const& builder );
+        ~ScopedMessage();
+
+        MessageInfo m_info;
+    };
+
+    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
+
+// end catch_message.h
+#if !defined(CATCH_CONFIG_DISABLE)
+
+#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
+  #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__
+#else
+  #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
+#endif
+
+#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 INTERNAL_CATCH_TRY
+#define INTERNAL_CATCH_CATCH( capturer )
+
+#else // CATCH_CONFIG_FAST_COMPILE
+
+#define INTERNAL_CATCH_TRY try
+#define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); }
+
+#endif
+
+#define INTERNAL_CATCH_REACT( handler ) handler.complete();
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
+    do { \
+        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
+    // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
+    INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
+    if( Catch::getResultCapture().lastAssertionPassed() )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \
+    INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
+    if( !Catch::getResultCapture().lastAssertionPassed() )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
+    do { \
+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
+        try { \
+            static_cast<void>(__VA_ARGS__); \
+            catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
+        } \
+        catch( ... ) { \
+            catchAssertionHandler.handleUnexpectedInflightException(); \
+        } \
+        INTERNAL_CATCH_REACT( catchAssertionHandler ) \
+    } while( false )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
+    do { \
+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
+        if( catchAssertionHandler.allowThrows() ) \
+            try { \
+                static_cast<void>(__VA_ARGS__); \
+                catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
+            } \
+            catch( ... ) { \
+                catchAssertionHandler.handleExceptionThrownAsExpected(); \
+            } \
+        else \
+            catchAssertionHandler.handleThrowingCallSkipped(); \
+        INTERNAL_CATCH_REACT( catchAssertionHandler ) \
+    } while( false )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
+    do { \
+        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); \
+                catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
+            } \
+            catch( exceptionType const& ) { \
+                catchAssertionHandler.handleExceptionThrownAsExpected(); \
+            } \
+            catch( ... ) { \
+                catchAssertionHandler.handleUnexpectedInflightException(); \
+            } \
+        else \
+            catchAssertionHandler.handleThrowingCallSkipped(); \
+        INTERNAL_CATCH_REACT( catchAssertionHandler ) \
+    } while( false )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
+    do { \
+        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_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_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_sr ); \
+            } \
+        else \
+            catchAssertionHandler.handleThrowingCallSkipped(); \
+        INTERNAL_CATCH_REACT( catchAssertionHandler ) \
+    } while( false )
+
+#endif // CATCH_CONFIG_DISABLE
+
+// end catch_capture.hpp
+// start catch_section.h
+
+// start catch_section_info.h
+
+// start catch_totals.h
+
+#include <cstddef>
+
+namespace Catch {
+
+    struct Counts {
+        Counts operator - ( Counts const& other ) const;
+        Counts& operator += ( Counts const& other );
+
+        std::size_t total() const;
+        bool allPassed() const;
+        bool allOk() const;
+
+        std::size_t passed = 0;
+        std::size_t failed = 0;
+        std::size_t failedButOk = 0;
+    };
+
+    struct Totals {
+
+        Totals operator - ( Totals const& other ) const;
+        Totals& operator += ( Totals const& other );
+
+        Totals delta( Totals const& prevTotals ) const;
+
+        int error = 0;
+        Counts assertions;
+        Counts testCases;
+    };
+}
+
+// end catch_totals.h
+#include <string>
+
+namespace Catch {
+
+    struct SectionInfo {
+        SectionInfo
+            (   SourceLineInfo const& _lineInfo,
+                std::string const& _name );
+
+        // Deprecated
+        SectionInfo
+            (   SourceLineInfo const& _lineInfo,
+                std::string const& _name,
+                std::string const& ) : SectionInfo( _lineInfo, _name ) {}
+
+        std::string name;
+        std::string description; // !Deprecated: this will always be empty
+        SourceLineInfo lineInfo;
+    };
+
+    struct SectionEndInfo {
+        SectionInfo sectionInfo;
+        Counts prevAssertions;
+        double durationInSeconds;
+    };
+
+} // end namespace Catch
+
+// end catch_section_info.h
+// start catch_timer.h
+
+#include <cstdint>
+
+namespace Catch {
+
+    auto getCurrentNanosecondsSinceEpoch() -> uint64_t;
+    auto getEstimatedClockResolution() -> uint64_t;
+
+    class Timer {
+        uint64_t m_nanoseconds = 0;
+    public:
+        void start();
+        auto getElapsedNanoseconds() const -> uint64_t;
+        auto getElapsedMicroseconds() const -> uint64_t;
+        auto getElapsedMilliseconds() const -> unsigned int;
+        auto getElapsedSeconds() const -> double;
+    };
+
+} // namespace Catch
+
+// end catch_timer.h
+#include <string>
+
+namespace Catch {
+
+    class Section : NonCopyable {
+    public:
+        Section( SectionInfo const& info );
+        ~Section();
+
+        // This indicates whether the section should be executed or not
+        explicit operator bool() const;
+
+    private:
+        SectionInfo m_info;
+
+        std::string m_name;
+        Counts m_assertions;
+        bool m_sectionIncluded;
+        Timer m_timer;
+    };
+
+} // end namespace Catch
+
+#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
+
+#include <cstdint>
+#include <string>
+
+namespace Catch {
+
+    class BenchmarkLooper {
+
+        std::string m_name;
+        std::size_t m_count = 0;
+        std::size_t m_iterationsToRun = 1;
+        uint64_t m_resolution;
+        Timer m_timer;
+
+        static auto getResolution() -> uint64_t;
+    public:
+        // Keep most of this inline as it's on the code path that is being timed
+        BenchmarkLooper( StringRef name )
+        :   m_name( name ),
+            m_resolution( getResolution() )
+        {
+            reportStart();
+            m_timer.start();
+        }
+
+        explicit operator bool() {
+            if( m_count < m_iterationsToRun )
+                return true;
+            return needsMoreIterations();
+        }
+
+        void increment() {
+            ++m_count;
+        }
+
+        void reportStart();
+        auto needsMoreIterations() -> bool;
+    };
+
+} // end namespace Catch
+
+#define BENCHMARK( name ) \
+    for( Catch::BenchmarkLooper looper( name ); looper; looper.increment() )
+
+// end catch_benchmark.h
+// start catch_interfaces_exception.h
+
+// start catch_interfaces_registry_hub.h
+
+#include <string>
+#include <memory>
+
+namespace Catch {
+
+    class TestCase;
+    struct ITestCaseRegistry;
+    struct IExceptionTranslatorRegistry;
+    struct IExceptionTranslator;
+    struct IReporterRegistry;
+    struct IReporterFactory;
+    struct ITagAliasRegistry;
+    class StartupExceptionRegistry;
+
+    using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;
+
+    struct IRegistryHub {
+        virtual ~IRegistryHub();
+
+        virtual IReporterRegistry const& getReporterRegistry() const = 0;
+        virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
+        virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
+
+        virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0;
+
+        virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
+    };
+
+    struct IMutableRegistryHub {
+        virtual ~IMutableRegistryHub();
+        virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0;
+        virtual void registerListener( IReporterFactoryPtr const& factory ) = 0;
+        virtual void registerTest( TestCase const& testInfo ) = 0;
+        virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
+        virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
+        virtual void registerStartupException() noexcept = 0;
+    };
+
+    IRegistryHub const& getRegistryHub();
+    IMutableRegistryHub& getMutableRegistryHub();
+    void cleanUp();
+    std::string translateActiveException();
+
+}
+
+// end catch_interfaces_registry_hub.h
+#if defined(CATCH_CONFIG_DISABLE)
+    #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \
+        static std::string translatorName( signature )
+#endif
+
+#include <exception>
+#include <string>
+#include <vector>
+
+namespace Catch {
+    using exceptionTranslateFunction = std::string(*)();
+
+    struct IExceptionTranslator;
+    using ExceptionTranslators = std::vector<std::unique_ptr<IExceptionTranslator const>>;
+
+    struct IExceptionTranslator {
+        virtual ~IExceptionTranslator();
+        virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
+    };
+
+    struct IExceptionTranslatorRegistry {
+        virtual ~IExceptionTranslatorRegistry();
+
+        virtual std::string translateActiveException() const = 0;
+    };
+
+    class ExceptionTranslatorRegistrar {
+        template<typename T>
+        class ExceptionTranslator : public IExceptionTranslator {
+        public:
+
+            ExceptionTranslator( std::string(*translateFunction)( T& ) )
+            : m_translateFunction( translateFunction )
+            {}
+
+            std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {
+                try {
+                    if( it == itEnd )
+                        std::rethrow_exception(std::current_exception());
+                    else
+                        return (*it)->translate( it+1, itEnd );
+                }
+                catch( T& ex ) {
+                    return m_translateFunction( ex );
+                }
+            }
+
+        protected:
+            std::string(*m_translateFunction)( T& );
+        };
+
+    public:
+        template<typename T>
+        ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
+            getMutableRegistryHub().registerTranslator
+                ( new ExceptionTranslator<T>( translateFunction ) );
+        }
+    };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
+    static std::string translatorName( signature ); \
+    CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+    namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \
+    CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
+    static std::string translatorName( signature )
+
+#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
+
+// end catch_interfaces_exception.h
+// start catch_approx.h
+
+#include <type_traits>
+
+namespace Catch {
+namespace Detail {
+
+    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.m_epsilon = m_epsilon;
+            approx.m_margin = m_margin;
+            approx.m_scale = m_scale;
+            return approx;
+        }
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        explicit Approx( T const& value ): Approx(static_cast<double>(value))
+        {}
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        friend bool operator == ( const T& lhs, Approx const& rhs ) {
+            auto lhs_v = static_cast<double>(lhs);
+            return rhs.equalityComparisonImpl(lhs_v);
+        }
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        friend bool operator == ( Approx const& lhs, const T& rhs ) {
+            return operator==( rhs, lhs );
+        }
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        friend bool operator != ( T const& lhs, Approx const& rhs ) {
+            return !operator==( lhs, rhs );
+        }
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        friend bool operator != ( Approx const& lhs, T const& rhs ) {
+            return !operator==( rhs, lhs );
+        }
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        friend bool operator <= ( T const& lhs, Approx const& rhs ) {
+            return static_cast<double>(lhs) < rhs.m_value || lhs == rhs;
+        }
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        friend bool operator <= ( Approx const& lhs, T const& rhs ) {
+            return lhs.m_value < static_cast<double>(rhs) || lhs == rhs;
+        }
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        friend bool operator >= ( T const& lhs, Approx const& rhs ) {
+            return static_cast<double>(lhs) > rhs.m_value || lhs == rhs;
+        }
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        friend bool operator >= ( Approx const& lhs, T const& rhs ) {
+            return lhs.m_value > static_cast<double>(rhs) || lhs == rhs;
+        }
+
+        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);
+            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);
+            setMargin(marginAsDouble);
+            return *this;
+        }
+
+        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+        Approx& scale( T const& newScale ) {
+            m_scale = static_cast<double>(newScale);
+            return *this;
+        }
+
+        std::string toString() const;
+
+    private:
+        double m_epsilon;
+        double m_margin;
+        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> {
+    static std::string convert(Catch::Detail::Approx const& value);
+};
+
+} // end namespace Catch
+
+// end catch_approx.h
+// start catch_string_manip.h
+
+#include <string>
+#include <iosfwd>
+
+namespace Catch {
+
+    bool startsWith( std::string const& s, std::string const& prefix );
+    bool startsWith( std::string const& s, char prefix );
+    bool endsWith( std::string const& s, std::string const& suffix );
+    bool endsWith( std::string const& s, char suffix );
+    bool contains( std::string const& s, std::string const& infix );
+    void toLowerInPlace( std::string& s );
+    std::string toLower( std::string const& s );
+    std::string trim( std::string const& str );
+    bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
+
+    struct pluralise {
+        pluralise( std::size_t count, std::string const& label );
+
+        friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
+
+        std::size_t m_count;
+        std::string m_label;
+    };
+}
+
+// end catch_string_manip.h
+#ifndef CATCH_CONFIG_DISABLE_MATCHERS
+// start catch_capture_matchers.h
+
+// start catch_matchers.h
+
+#include <string>
+#include <vector>
+
+namespace Catch {
+namespace Matchers {
+    namespace Impl {
+
+        template<typename ArgT> struct MatchAllOf;
+        template<typename ArgT> struct MatchAnyOf;
+        template<typename ArgT> struct MatchNotOf;
+
+        class MatcherUntypedBase {
+        public:
+            MatcherUntypedBase() = default;
+            MatcherUntypedBase ( MatcherUntypedBase const& ) = default;
+            MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete;
+            std::string toString() const;
+
+        protected:
+            virtual ~MatcherUntypedBase();
+            virtual std::string describe() const = 0;
+            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;
+        };
+
+#ifdef __clang__
+#    pragma clang diagnostic pop
+#endif
+
+        template<typename T>
+        struct MatcherBase : MatcherUntypedBase, MatcherMethod<T> {
+
+            MatchAllOf<T> operator && ( MatcherBase const& other ) const;
+            MatchAnyOf<T> operator || ( MatcherBase const& other ) const;
+            MatchNotOf<T> operator ! () const;
+        };
+
+        template<typename ArgT>
+        struct MatchAllOf : MatcherBase<ArgT> {
+            bool match( ArgT const& arg ) const override {
+                for( auto matcher : m_matchers ) {
+                    if (!matcher->match(arg))
+                        return false;
+                }
+                return true;
+            }
+            std::string describe() const override {
+                std::string description;
+                description.reserve( 4 + m_matchers.size()*32 );
+                description += "( ";
+                bool first = true;
+                for( auto matcher : m_matchers ) {
+                    if( first )
+                        first = false;
+                    else
+                        description += " and ";
+                    description += matcher->toString();
+                }
+                description += " )";
+                return description;
+            }
+
+            MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) {
+                m_matchers.push_back( &other );
+                return *this;
+            }
+
+            std::vector<MatcherBase<ArgT> const*> m_matchers;
+        };
+        template<typename ArgT>
+        struct MatchAnyOf : MatcherBase<ArgT> {
+
+            bool match( ArgT const& arg ) const override {
+                for( auto matcher : m_matchers ) {
+                    if (matcher->match(arg))
+                        return true;
+                }
+                return false;
+            }
+            std::string describe() const override {
+                std::string description;
+                description.reserve( 4 + m_matchers.size()*32 );
+                description += "( ";
+                bool first = true;
+                for( auto matcher : m_matchers ) {
+                    if( first )
+                        first = false;
+                    else
+                        description += " or ";
+                    description += matcher->toString();
+                }
+                description += " )";
+                return description;
+            }
+
+            MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) {
+                m_matchers.push_back( &other );
+                return *this;
+            }
+
+            std::vector<MatcherBase<ArgT> const*> m_matchers;
+        };
+
+        template<typename ArgT>
+        struct MatchNotOf : MatcherBase<ArgT> {
+
+            MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {}
+
+            bool match( ArgT const& arg ) const override {
+                return !m_underlyingMatcher.match( arg );
+            }
+
+            std::string describe() const override {
+                return "not " + m_underlyingMatcher.toString();
+            }
+            MatcherBase<ArgT> const& m_underlyingMatcher;
+        };
+
+        template<typename T>
+        MatchAllOf<T> MatcherBase<T>::operator && ( MatcherBase const& other ) const {
+            return MatchAllOf<T>() && *this && other;
+        }
+        template<typename T>
+        MatchAnyOf<T> MatcherBase<T>::operator || ( MatcherBase const& other ) const {
+            return MatchAnyOf<T>() || *this || other;
+        }
+        template<typename T>
+        MatchNotOf<T> MatcherBase<T>::operator ! () const {
+            return MatchNotOf<T>( *this );
+        }
+
+    } // namespace Impl
+
+} // namespace Matchers
+
+using namespace Matchers;
+using Matchers::Impl::MatcherBase;
+
+} // namespace Catch
+
+// end catch_matchers.h
+// start catch_matchers_floating.h
+
+#include <type_traits>
+#include <cmath>
+
+namespace Catch {
+namespace Matchers {
+
+    namespace Floating {
+
+        enum class FloatingPointKind : uint8_t;
+
+        struct WithinAbsMatcher : MatcherBase<double> {
+            WithinAbsMatcher(double target, double margin);
+            bool match(double const& matchee) const override;
+            std::string describe() const override;
+        private:
+            double m_target;
+            double m_margin;
+        };
+
+        struct WithinUlpsMatcher : MatcherBase<double> {
+            WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType);
+            bool match(double const& matchee) const override;
+            std::string describe() const override;
+        private:
+            double m_target;
+            int m_ulps;
+            FloatingPointKind m_type;
+        };
+
+    } // namespace Floating
+
+    // The following functions create the actual matcher objects.
+    // This allows the types to be inferred
+    Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff);
+    Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff);
+    Floating::WithinAbsMatcher WithinAbs(double target, double margin);
+
+} // namespace Matchers
+} // 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>
+
+namespace Catch {
+namespace Matchers {
+
+    namespace StdString {
+
+        struct CasedString
+        {
+            CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity );
+            std::string adjustString( std::string const& str ) const;
+            std::string caseSensitivitySuffix() const;
+
+            CaseSensitive::Choice m_caseSensitivity;
+            std::string m_str;
+        };
+
+        struct StringMatcherBase : MatcherBase<std::string> {
+            StringMatcherBase( std::string const& operation, CasedString const& comparator );
+            std::string describe() const override;
+
+            CasedString m_comparator;
+            std::string m_operation;
+        };
+
+        struct EqualsMatcher : StringMatcherBase {
+            EqualsMatcher( CasedString const& comparator );
+            bool match( std::string const& source ) const override;
+        };
+        struct ContainsMatcher : StringMatcherBase {
+            ContainsMatcher( CasedString const& comparator );
+            bool match( std::string const& source ) const override;
+        };
+        struct StartsWithMatcher : StringMatcherBase {
+            StartsWithMatcher( CasedString const& comparator );
+            bool match( std::string const& source ) const override;
+        };
+        struct EndsWithMatcher : StringMatcherBase {
+            EndsWithMatcher( CasedString const& comparator );
+            bool match( std::string const& source ) const override;
+        };
+
+        struct RegexMatcher : MatcherBase<std::string> {
+            RegexMatcher( std::string regex, CaseSensitive::Choice caseSensitivity );
+            bool match( std::string const& matchee ) const override;
+            std::string describe() const override;
+
+        private:
+            std::string m_regex;
+            CaseSensitive::Choice m_caseSensitivity;
+        };
+
+    } // namespace StdString
+
+    // The following functions create the actual matcher objects.
+    // This allows the types to be inferred
+
+    StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
+    StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
+    StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
+    StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
+    StdString::RegexMatcher Matches( std::string const& regex, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
+
+} // namespace Matchers
+} // namespace Catch
+
+// end catch_matchers_string.h
+// start catch_matchers_vector.h
+
+#include <algorithm>
+
+namespace Catch {
+namespace Matchers {
+
+    namespace Vector {
+        namespace Detail {
+            template <typename InputIterator, typename T>
+            size_t count(InputIterator first, InputIterator last, T const& item) {
+                size_t cnt = 0;
+                for (; first != last; ++first) {
+                    if (*first == item) {
+                        ++cnt;
+                    }
+                }
+                return cnt;
+            }
+            template <typename InputIterator, typename T>
+            bool contains(InputIterator first, InputIterator last, T const& item) {
+                for (; first != last; ++first) {
+                    if (*first == item) {
+                        return true;
+                    }
+                }
+                return false;
+            }
+        }
+
+        template<typename T>
+        struct ContainsElementMatcher : MatcherBase<std::vector<T>> {
+
+            ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
+
+            bool match(std::vector<T> const &v) const override {
+                for (auto const& el : v) {
+                    if (el == m_comparator) {
+                        return true;
+                    }
+                }
+                return false;
+            }
+
+            std::string describe() const override {
+                return "Contains: " + ::Catch::Detail::stringify( m_comparator );
+            }
+
+            T const& m_comparator;
+        };
+
+        template<typename T>
+        struct ContainsMatcher : MatcherBase<std::vector<T>> {
+
+            ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
+
+            bool match(std::vector<T> const &v) const override {
+                // !TBD: see note in EqualsMatcher
+                if (m_comparator.size() > v.size())
+                    return false;
+                for (auto const& comparator : m_comparator) {
+                    auto present = false;
+                    for (const auto& el : v) {
+                        if (el == comparator) {
+                            present = true;
+                            break;
+                        }
+                    }
+                    if (!present) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+            std::string describe() const override {
+                return "Contains: " + ::Catch::Detail::stringify( m_comparator );
+            }
+
+            std::vector<T> const& m_comparator;
+        };
+
+        template<typename T>
+        struct EqualsMatcher : MatcherBase<std::vector<T>> {
+
+            EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
+
+            bool match(std::vector<T> const &v) const override {
+                // !TBD: This currently works if all elements can be compared using !=
+                // - a more general approach would be via a compare template that defaults
+                // to using !=. but could be specialised for, e.g. std::vector<T> etc
+                // - then just call that directly
+                if (m_comparator.size() != v.size())
+                    return false;
+                for (std::size_t i = 0; i < v.size(); ++i)
+                    if (m_comparator[i] != v[i])
+                        return false;
+                return true;
+            }
+            std::string describe() const override {
+                return "Equals: " + ::Catch::Detail::stringify( m_comparator );
+            }
+            std::vector<T> const& m_comparator;
+        };
+
+        template<typename T>
+        struct UnorderedEqualsMatcher : MatcherBase<std::vector<T>> {
+            UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {}
+            bool match(std::vector<T> const& vec) const override {
+                // Note: This is a reimplementation of std::is_permutation,
+                //       because I don't want to include <algorithm> inside the common path
+                if (m_target.size() != vec.size()) {
+                    return false;
+                }
+                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) {
+                    ++lfirst; ++rfirst;
+                }
+                if (lfirst == llast) {
+                    return true;
+                }
+
+                for (auto mid = lfirst; mid != llast; ++mid) {
+                    // Skip already counted items
+                    if (Detail::contains(lfirst, mid, *mid)) {
+                        continue;
+                    }
+                    size_t num_vec = Detail::count(rfirst, rlast, *mid);
+                    if (num_vec == 0 || Detail::count(lfirst, llast, *mid) != num_vec) {
+                        return false;
+                    }
+                }
+
+                return true;
+            }
+
+            std::string describe() const override {
+                return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
+            }
+        private:
+            std::vector<T> const& m_target;
+        };
+
+    } // namespace Vector
+
+    // The following functions create the actual matcher objects.
+    // This allows the types to be inferred
+
+    template<typename T>
+    Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) {
+        return Vector::ContainsMatcher<T>( comparator );
+    }
+
+    template<typename T>
+    Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) {
+        return Vector::ContainsElementMatcher<T>( comparator );
+    }
+
+    template<typename T>
+    Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) {
+        return Vector::EqualsMatcher<T>( comparator );
+    }
+
+    template<typename T>
+    Vector::UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) {
+        return Vector::UnorderedEqualsMatcher<T>(target);
+    }
+
+} // namespace Matchers
+} // namespace Catch
+
+// end catch_matchers_vector.h
+namespace Catch {
+
+    template<typename ArgT, typename MatcherT>
+    class MatchExpr : public ITransientExpression {
+        ArgT const& m_arg;
+        MatcherT m_matcher;
+        StringRef m_matcherString;
+    public:
+        MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString )
+        :   ITransientExpression{ true, matcher.match( arg ) },
+            m_arg( arg ),
+            m_matcher( matcher ),
+            m_matcherString( matcherString )
+        {}
+
+        void streamReconstructedExpression( std::ostream &os ) const override {
+            auto matcherAsString = m_matcher.toString();
+            os << Catch::Detail::stringify( m_arg ) << ' ';
+            if( matcherAsString == Detail::unprintableString )
+                os << m_matcherString;
+            else
+                os << matcherAsString;
+        }
+    };
+
+    using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
+
+    void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString  );
+
+    template<typename ArgT, typename MatcherT>
+    auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString  ) -> MatchExpr<ArgT, MatcherT> {
+        return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString );
+    }
+
+} // namespace Catch
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
+    do { \
+        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 )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \
+    do { \
+        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##_catch_sr ) ); \
+            } \
+            catch( ... ) { \
+                catchAssertionHandler.handleUnexpectedInflightException(); \
+            } \
+        else \
+            catchAssertionHandler.handleThrowingCallSkipped(); \
+        INTERNAL_CATCH_REACT( catchAssertionHandler ) \
+    } while( false )
+
+// end catch_capture_matchers.h
+#endif
+// start catch_generators.hpp
+
+// start catch_interfaces_generatortracker.h
+
+
+#include <memory>
+
+namespace Catch {
+
+    namespace Generators {
+        class GeneratorBase {
+        protected:
+            size_t m_size = 0;
+
+        public:
+            GeneratorBase( size_t size ) : m_size( size ) {}
+            virtual ~GeneratorBase();
+            auto size() const -> size_t { return m_size; }
+        };
+        using GeneratorBasePtr = std::unique_ptr<GeneratorBase>;
+
+    } // 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;
+        virtual auto getIndex() const -> std::size_t = 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>
+
+namespace Catch {
+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 {
+        virtual ~IGenerator() {}
+        virtual auto get( size_t index ) const -> T = 0;
+    };
+
+    template<typename T>
+    class SingleValueGenerator : public IGenerator<T> {
+        T m_value;
+    public:
+        SingleValueGenerator( T const& value ) : m_value( value ) {}
+
+        auto get( size_t ) const -> T override {
+            return m_value;
+        }
+    };
+
+    template<typename T>
+    class FixedValuesGenerator : public IGenerator<T> {
+        std::vector<T> m_values;
+
+    public:
+        FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {}
+
+        auto get( size_t index ) const -> T override {
+            return m_values[index];
+        }
+    };
+
+    template<typename T>
+    class RangeGenerator : public IGenerator<T> {
+        T const m_first;
+        T const m_last;
+
+    public:
+        RangeGenerator( T const& first, T const& last ) : m_first( first ), m_last( last ) {
+            assert( m_last > m_first );
+        }
+
+        auto get( size_t index ) const -> T override {
+            // ToDo:: introduce a safe cast to catch potential overflows
+            return static_cast<T>(m_first+index);
+        }
+    };
+
+    template<typename T>
+    struct NullGenerator : IGenerator<T> {
+        auto get( size_t ) const -> T override {
+            CATCH_INTERNAL_ERROR("A Null Generator is always empty");
+        }
+    };
+
+    template<typename T>
+    class Generator {
+        std::unique_ptr<IGenerator<T>> m_generator;
+        size_t m_size;
+
+    public:
+        Generator( size_t size, std::unique_ptr<IGenerator<T>> generator )
+        :   m_generator( std::move( generator ) ),
+            m_size( size )
+        {}
+
+        auto size() const -> size_t { return m_size; }
+        auto operator[]( size_t index ) const -> T {
+            assert( index < m_size );
+            return m_generator->get( index );
+        }
+    };
+
+    std::vector<size_t> randomiseIndices( size_t selectionSize, size_t sourceSize );
+
+    template<typename T>
+    class GeneratorRandomiser : public IGenerator<T> {
+        Generator<T> m_baseGenerator;
+
+        std::vector<size_t> m_indices;
+    public:
+        GeneratorRandomiser( Generator<T>&& baseGenerator, size_t numberOfItems )
+        :   m_baseGenerator( std::move( baseGenerator ) ),
+            m_indices( randomiseIndices( numberOfItems, m_baseGenerator.size() ) )
+        {}
+
+        auto get( size_t index ) const -> T override {
+            return m_baseGenerator[m_indices[index]];
+        }
+    };
+
+    template<typename T>
+    struct RequiresASpecialisationFor;
+
+    template<typename T>
+    auto all() -> Generator<T> { return RequiresASpecialisationFor<T>(); }
+
+    template<>
+    auto all<int>() -> Generator<int>;
+
+    template<typename T>
+    auto range( T const& first, T const& last ) -> Generator<T> {
+        return Generator<T>( (last-first), pf::make_unique<RangeGenerator<T>>( first, last ) );
+    }
+
+    template<typename T>
+    auto random( T const& first, T const& last ) -> Generator<T> {
+        auto gen = range( first, last );
+        auto size = gen.size();
+
+        return Generator<T>( size, pf::make_unique<GeneratorRandomiser<T>>( std::move( gen ), size ) );
+    }
+    template<typename T>
+    auto random( size_t size ) -> Generator<T> {
+        return Generator<T>( size, pf::make_unique<GeneratorRandomiser<T>>( all<T>(), size ) );
+    }
+
+    template<typename T>
+    auto values( std::initializer_list<T> values ) -> Generator<T> {
+        return Generator<T>( values.size(), pf::make_unique<FixedValuesGenerator<T>>( values ) );
+    }
+    template<typename T>
+    auto value( T const& val ) -> Generator<T> {
+        return Generator<T>( 1, pf::make_unique<SingleValueGenerator<T>>( val ) );
+    }
+
+    template<typename T>
+    auto as() -> Generator<T> {
+        return Generator<T>( 0, pf::make_unique<NullGenerator<T>>() );
+    }
+
+    template<typename... Ts>
+    auto table( std::initializer_list<std::tuple<Ts...>>&& tuples ) -> Generator<std::tuple<Ts...>> {
+        return values<std::tuple<Ts...>>( std::forward<std::initializer_list<std::tuple<Ts...>>>( tuples ) );
+    }
+
+    template<typename T>
+    struct Generators : GeneratorBase {
+        std::vector<Generator<T>> m_generators;
+
+        using type = T;
+
+        Generators() : GeneratorBase( 0 ) {}
+
+        void populate( T&& val ) {
+            m_size += 1;
+            m_generators.emplace_back( value( std::move( val ) ) );
+        }
+        template<typename U>
+        void populate( U&& val ) {
+            populate( T( std::move( val ) ) );
+        }
+        void populate( Generator<T>&& generator ) {
+            m_size += generator.size();
+            m_generators.emplace_back( std::move( generator ) );
+        }
+
+        template<typename U, typename... Gs>
+        void populate( U&& valueOrGenerator, Gs... moreGenerators ) {
+            populate( std::forward<U>( valueOrGenerator ) );
+            populate( std::forward<Gs>( moreGenerators )... );
+        }
+
+        auto operator[]( size_t index ) const -> T {
+            size_t sizes = 0;
+            for( auto const& gen : m_generators ) {
+                auto localIndex = index-sizes;
+                sizes += gen.size();
+                if( index < sizes )
+                    return gen[localIndex];
+            }
+            CATCH_INTERNAL_ERROR("Index '" << index << "' is out of range (" << sizes << ')');
+        }
+    };
+
+    template<typename T, typename... Gs>
+    auto makeGenerators( Generator<T>&& generator, Gs... moreGenerators ) -> Generators<T> {
+        Generators<T> generators;
+        generators.m_generators.reserve( 1+sizeof...(Gs) );
+        generators.populate( std::move( generator ), std::forward<Gs>( moreGenerators )... );
+        return generators;
+    }
+    template<typename T>
+    auto makeGenerators( Generator<T>&& generator ) -> Generators<T> {
+        Generators<T> generators;
+        generators.populate( std::move( generator ) );
+        return generators;
+    }
+    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( 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())>()[0]) {
+        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<Generators<UnderlyingType> const&>( *tracker.getGenerator() );
+        return generator[tracker.getIndex()];
+    }
+
+} // namespace Generators
+} // namespace Catch
+
+#define GENERATE( ... ) \
+    Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, []{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
+
+// end catch_generators.hpp
+
+// These files are included here so the single_include script doesn't put them
+// in the conditionally compiled sections
+// start catch_test_case_info.h
+
+#include <string>
+#include <vector>
+#include <memory>
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpadded"
+#endif
+
+namespace Catch {
+
+    struct ITestInvoker;
+
+    struct TestCaseInfo {
+        enum SpecialProperties{
+            None = 0,
+            IsHidden = 1 << 1,
+            ShouldFail = 1 << 2,
+            MayFail = 1 << 3,
+            Throws = 1 << 4,
+            NonPortable = 1 << 5,
+            Benchmark = 1 << 6
+        };
+
+        TestCaseInfo(   std::string const& _name,
+                        std::string const& _className,
+                        std::string const& _description,
+                        std::vector<std::string> const& _tags,
+                        SourceLineInfo const& _lineInfo );
+
+        friend void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags );
+
+        bool isHidden() const;
+        bool throws() const;
+        bool okToFail() const;
+        bool expectedToFail() const;
+
+        std::string tagsAsString() const;
+
+        std::string name;
+        std::string className;
+        std::string description;
+        std::vector<std::string> tags;
+        std::vector<std::string> lcaseTags;
+        SourceLineInfo lineInfo;
+        SpecialProperties properties;
+    };
+
+    class TestCase : public TestCaseInfo {
+    public:
+
+        TestCase( ITestInvoker* testCase, TestCaseInfo&& info );
+
+        TestCase withName( std::string const& _newName ) const;
+
+        void invoke() const;
+
+        TestCaseInfo const& getTestCaseInfo() const;
+
+        bool operator == ( TestCase const& other ) const;
+        bool operator < ( TestCase const& other ) const;
+
+    private:
+        std::shared_ptr<ITestInvoker> test;
+    };
+
+    TestCase makeTestCase(  ITestInvoker* testCase,
+                            std::string const& className,
+                            NameAndTags const& nameAndTags,
+                            SourceLineInfo const& lineInfo );
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+// end catch_test_case_info.h
+// start catch_interfaces_runner.h
+
+namespace Catch {
+
+    struct IRunner {
+        virtual ~IRunner();
+        virtual bool aborting() const = 0;
+    };
+}
+
+// end catch_interfaces_runner.h
+
+#ifdef __OBJC__
+// start catch_objc.hpp
+
+#import <objc/runtime.h>
+
+#include <string>
+
+// NB. Any general catch headers included here must be included
+// in catch.hpp first to make sure they are included by the single
+// header for non obj-usage
+
+///////////////////////////////////////////////////////////////////////////////
+// This protocol is really only here for (self) documenting purposes, since
+// all its methods are optional.
+@protocol OcFixture
+
+@optional
+
+-(void) setUp;
+-(void) tearDown;
+
+@end
+
+namespace Catch {
+
+    class OcMethod : public ITestInvoker {
+
+    public:
+        OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
+
+        virtual void invoke() const {
+            id obj = [[m_cls alloc] init];
+
+            performOptionalSelector( obj, @selector(setUp)  );
+            performOptionalSelector( obj, m_sel );
+            performOptionalSelector( obj, @selector(tearDown)  );
+
+            arcSafeRelease( obj );
+        }
+    private:
+        virtual ~OcMethod() {}
+
+        Class m_cls;
+        SEL m_sel;
+    };
+
+    namespace Detail{
+
+        inline std::string getAnnotation(   Class cls,
+                                            std::string const& annotationName,
+                                            std::string const& testCaseName ) {
+            NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
+            SEL sel = NSSelectorFromString( selStr );
+            arcSafeRelease( selStr );
+            id value = performOptionalSelector( cls, sel );
+            if( value )
+                return [(NSString*)value UTF8String];
+            return "";
+        }
+    }
+
+    inline std::size_t registerTestMethods() {
+        std::size_t noTestMethods = 0;
+        int noClasses = objc_getClassList( nullptr, 0 );
+
+        Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
+        objc_getClassList( classes, noClasses );
+
+        for( int c = 0; c < noClasses; c++ ) {
+            Class cls = classes[c];
+            {
+                u_int count;
+                Method* methods = class_copyMethodList( cls, &count );
+                for( u_int m = 0; m < count ; m++ ) {
+                    SEL selector = method_getName(methods[m]);
+                    std::string methodName = sel_getName(selector);
+                    if( startsWith( methodName, "Catch_TestCase_" ) ) {
+                        std::string testCaseName = methodName.substr( 15 );
+                        std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
+                        std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
+                        const char* className = class_getName( cls );
+
+                        getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, NameAndTags( name.c_str(), desc.c_str() ), SourceLineInfo("",0) ) );
+                        noTestMethods++;
+                    }
+                }
+                free(methods);
+            }
+        }
+        return noTestMethods;
+    }
+
+#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
+
+    namespace Matchers {
+        namespace Impl {
+        namespace NSStringMatchers {
+
+            struct StringHolder : MatcherBase<NSString*>{
+                StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
+                StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
+                StringHolder() {
+                    arcSafeRelease( m_substr );
+                }
+
+                bool match( NSString* arg ) const override {
+                    return false;
+                }
+
+                NSString* CATCH_ARC_STRONG m_substr;
+            };
+
+            struct Equals : StringHolder {
+                Equals( NSString* substr ) : StringHolder( substr ){}
+
+                bool match( NSString* str ) const override {
+                    return  (str != nil || m_substr == nil ) &&
+                            [str isEqualToString:m_substr];
+                }
+
+                std::string describe() const override {
+                    return "equals string: " + Catch::Detail::stringify( m_substr );
+                }
+            };
+
+            struct Contains : StringHolder {
+                Contains( NSString* substr ) : StringHolder( substr ){}
+
+                bool match( NSString* str ) const {
+                    return  (str != nil || m_substr == nil ) &&
+                            [str rangeOfString:m_substr].location != NSNotFound;
+                }
+
+                std::string describe() const override {
+                    return "contains string: " + Catch::Detail::stringify( m_substr );
+                }
+            };
+
+            struct StartsWith : StringHolder {
+                StartsWith( NSString* substr ) : StringHolder( substr ){}
+
+                bool match( NSString* str ) const override {
+                    return  (str != nil || m_substr == nil ) &&
+                            [str rangeOfString:m_substr].location == 0;
+                }
+
+                std::string describe() const override {
+                    return "starts with: " + Catch::Detail::stringify( m_substr );
+                }
+            };
+            struct EndsWith : StringHolder {
+                EndsWith( NSString* substr ) : StringHolder( substr ){}
+
+                bool match( NSString* str ) const override {
+                    return  (str != nil || m_substr == nil ) &&
+                            [str rangeOfString:m_substr].location == [str length] - [m_substr length];
+                }
+
+                std::string describe() const override {
+                    return "ends with: " + Catch::Detail::stringify( m_substr );
+                }
+            };
+
+        } // namespace NSStringMatchers
+        } // namespace Impl
+
+        inline Impl::NSStringMatchers::Equals
+            Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
+
+        inline Impl::NSStringMatchers::Contains
+            Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
+
+        inline Impl::NSStringMatchers::StartsWith
+            StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
+
+        inline Impl::NSStringMatchers::EndsWith
+            EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
+
+    } // namespace Matchers
+
+    using namespace Matchers;
+
+#endif // CATCH_CONFIG_DISABLE_MATCHERS
+
+} // namespace Catch
+
+///////////////////////////////////////////////////////////////////////////////
+#define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix
+#define OC_TEST_CASE2( name, desc, uniqueSuffix ) \
++(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \
+{ \
+return @ name; \
+} \
++(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \
+{ \
+return @ desc; \
+} \
+-(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix )
+
+#define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ )
+
+// end catch_objc.hpp
+#endif
+
+#ifdef CATCH_CONFIG_EXTERNAL_INTERFACES
+// start catch_external_interfaces.h
+
+// start catch_reporter_bases.hpp
+
+// start catch_interfaces_reporter.h
+
+// start catch_config.hpp
+
+// start catch_test_spec_parser.h
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpadded"
+#endif
+
+// start catch_test_spec.h
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpadded"
+#endif
+
+// start catch_wildcard_pattern.h
+
+namespace Catch
+{
+    class WildcardPattern {
+        enum WildcardPosition {
+            NoWildcard = 0,
+            WildcardAtStart = 1,
+            WildcardAtEnd = 2,
+            WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
+        };
+
+    public:
+
+        WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity );
+        virtual ~WildcardPattern() = default;
+        virtual bool matches( std::string const& str ) const;
+
+    private:
+        std::string adjustCase( std::string const& str ) const;
+        CaseSensitive::Choice m_caseSensitivity;
+        WildcardPosition m_wildcard = NoWildcard;
+        std::string m_pattern;
+    };
+}
+
+// end catch_wildcard_pattern.h
+#include <string>
+#include <vector>
+#include <memory>
+
+namespace Catch {
+
+    class TestSpec {
+        struct Pattern {
+            virtual ~Pattern();
+            virtual bool matches( TestCaseInfo const& testCase ) const = 0;
+        };
+        using PatternPtr = std::shared_ptr<Pattern>;
+
+        class NamePattern : public Pattern {
+        public:
+            NamePattern( std::string const& name );
+            virtual ~NamePattern();
+            virtual bool matches( TestCaseInfo const& testCase ) const override;
+        private:
+            WildcardPattern m_wildcardPattern;
+        };
+
+        class TagPattern : public Pattern {
+        public:
+            TagPattern( std::string const& tag );
+            virtual ~TagPattern();
+            virtual bool matches( TestCaseInfo const& testCase ) const override;
+        private:
+            std::string m_tag;
+        };
+
+        class ExcludedPattern : public Pattern {
+        public:
+            ExcludedPattern( PatternPtr const& underlyingPattern );
+            virtual ~ExcludedPattern();
+            virtual bool matches( TestCaseInfo const& testCase ) const override;
+        private:
+            PatternPtr m_underlyingPattern;
+        };
+
+        struct Filter {
+            std::vector<PatternPtr> m_patterns;
+
+            bool matches( TestCaseInfo const& testCase ) const;
+        };
+
+    public:
+        bool hasFilters() const;
+        bool matches( TestCaseInfo const& testCase ) const;
+
+    private:
+        std::vector<Filter> m_filters;
+
+        friend class TestSpecParser;
+    };
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+// end catch_test_spec.h
+// start catch_interfaces_tag_alias_registry.h
+
+#include <string>
+
+namespace Catch {
+
+    struct TagAlias;
+
+    struct ITagAliasRegistry {
+        virtual ~ITagAliasRegistry();
+        // Nullptr if not present
+        virtual TagAlias const* find( std::string const& alias ) const = 0;
+        virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
+
+        static ITagAliasRegistry const& get();
+    };
+
+} // end namespace Catch
+
+// end catch_interfaces_tag_alias_registry.h
+namespace Catch {
+
+    class TestSpecParser {
+        enum Mode{ None, Name, QuotedName, Tag, EscapedName };
+        Mode m_mode = None;
+        bool m_exclusion = false;
+        std::size_t m_start = std::string::npos, m_pos = 0;
+        std::string m_arg;
+        std::vector<std::size_t> m_escapeChars;
+        TestSpec::Filter m_currentFilter;
+        TestSpec m_testSpec;
+        ITagAliasRegistry const* m_tagAliases = nullptr;
+
+    public:
+        TestSpecParser( ITagAliasRegistry const& tagAliases );
+
+        TestSpecParser& parse( std::string const& arg );
+        TestSpec testSpec();
+
+    private:
+        void visitChar( char c );
+        void startNewMode( Mode mode, std::size_t start );
+        void escape();
+        std::string subString() const;
+
+        template<typename T>
+        void addPattern() {
+            std::string token = subString();
+            for( std::size_t i = 0; i < m_escapeChars.size(); ++i )
+                token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
+            m_escapeChars.clear();
+            if( startsWith( token, "exclude:" ) ) {
+                m_exclusion = true;
+                token = token.substr( 8 );
+            }
+            if( !token.empty() ) {
+                TestSpec::PatternPtr pattern = std::make_shared<T>( token );
+                if( m_exclusion )
+                    pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern );
+                m_currentFilter.m_patterns.push_back( pattern );
+            }
+            m_exclusion = false;
+            m_mode = None;
+        }
+
+        void addFilter();
+    };
+    TestSpec parseTestSpec( std::string const& arg );
+
+} // namespace Catch
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#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,
+        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
+// Libstdc++ doesn't like incomplete classes for unique_ptr
+
+#include <memory>
+#include <vector>
+#include <string>
+
+#ifndef CATCH_CONFIG_CONSOLE_WIDTH
+#define CATCH_CONFIG_CONSOLE_WIDTH 80
+#endif
+
+namespace Catch {
+
+    struct IStream;
+
+    struct ConfigData {
+        bool listTests = false;
+        bool listTags = false;
+        bool listReporters = false;
+        bool listTestNamesOnly = false;
+
+        bool showSuccessfulTests = false;
+        bool shouldDebugBreak = false;
+        bool noThrow = false;
+        bool showHelp = false;
+        bool showInvisibles = false;
+        bool filenamesAsTags = false;
+        bool libIdentify = false;
+
+        int abortAfter = -1;
+        unsigned int rngSeed = 0;
+        int benchmarkResolutionMultiple = 100;
+
+        Verbosity verbosity = Verbosity::Normal;
+        WarnAbout::What warnings = WarnAbout::Nothing;
+        ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter;
+        RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder;
+        UseColour::YesOrNo useColour = UseColour::Auto;
+        WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
+
+        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> testsOrTags;
+        std::vector<std::string> sectionsToRun;
+    };
+
+    class Config : public IConfig {
+    public:
+
+        Config() = default;
+        Config( ConfigData const& data );
+        virtual ~Config() = default;
+
+        std::string const& getFilename() const;
+
+        bool listTests() const;
+        bool listTestNamesOnly() const;
+        bool listTags() const;
+        bool listReporters() const;
+
+        std::string getProcessName() const;
+        std::string const& getReporterName() 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;
+
+        // IConfig interface
+        bool allowThrows() const override;
+        std::ostream& stream() const override;
+        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;
+        int benchmarkResolutionMultiple() const override;
+        UseColour::YesOrNo useColour() const override;
+        bool shouldDebugBreak() const override;
+        int abortAfter() const override;
+        bool showInvisibles() const override;
+        Verbosity verbosity() const override;
+
+    private:
+
+        IStream const* openStream();
+        ConfigData m_data;
+
+        std::unique_ptr<IStream const> m_stream;
+        TestSpec m_testSpec;
+        bool m_hasTestFilters = false;
+    };
+
+} // end namespace Catch
+
+// end catch_config.hpp
+// start catch_assertionresult.h
+
+#include <string>
+
+namespace Catch {
+
+    struct AssertionResultData
+    {
+        AssertionResultData() = delete;
+
+        AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression );
+
+        std::string message;
+        mutable std::string reconstructedExpression;
+        LazyExpression lazyExpression;
+        ResultWas::OfType resultType;
+
+        std::string reconstructExpression() const;
+    };
+
+    class AssertionResult {
+    public:
+        AssertionResult() = delete;
+        AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
+
+        bool isOk() const;
+        bool succeeded() const;
+        ResultWas::OfType getResultType() const;
+        bool hasExpression() const;
+        bool hasMessage() const;
+        std::string getExpression() const;
+        std::string getExpressionInMacro() const;
+        bool hasExpandedExpression() const;
+        std::string getExpandedExpression() const;
+        std::string getMessage() const;
+        SourceLineInfo getSourceInfo() const;
+        StringRef getTestMacroName() const;
+
+    //protected:
+        AssertionInfo m_info;
+        AssertionResultData m_resultData;
+    };
+
+} // end namespace Catch
+
+// end catch_assertionresult.h
+// start catch_option.hpp
+
+namespace Catch {
+
+    // An optional type
+    template<typename T>
+    class Option {
+    public:
+        Option() : nullableValue( nullptr ) {}
+        Option( T const& _value )
+        : nullableValue( new( storage ) T( _value ) )
+        {}
+        Option( Option const& _other )
+        : nullableValue( _other ? new( storage ) T( *_other ) : nullptr )
+        {}
+
+        ~Option() {
+            reset();
+        }
+
+        Option& operator= ( Option const& _other ) {
+            if( &_other != this ) {
+                reset();
+                if( _other )
+                    nullableValue = new( storage ) T( *_other );
+            }
+            return *this;
+        }
+        Option& operator = ( T const& _value ) {
+            reset();
+            nullableValue = new( storage ) T( _value );
+            return *this;
+        }
+
+        void reset() {
+            if( nullableValue )
+                nullableValue->~T();
+            nullableValue = nullptr;
+        }
+
+        T& operator*() { return *nullableValue; }
+        T const& operator*() const { return *nullableValue; }
+        T* operator->() { return nullableValue; }
+        const T* operator->() const { return nullableValue; }
+
+        T valueOr( T const& defaultValue ) const {
+            return nullableValue ? *nullableValue : defaultValue;
+        }
+
+        bool some() const { return nullableValue != nullptr; }
+        bool none() const { return nullableValue == nullptr; }
+
+        bool operator !() const { return nullableValue == nullptr; }
+        explicit operator bool() const {
+            return some();
+        }
+
+    private:
+        T *nullableValue;
+        alignas(alignof(T)) char storage[sizeof(T)];
+    };
+
+} // end namespace Catch
+
+// end catch_option.hpp
+#include <string>
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <memory>
+
+namespace Catch {
+
+    struct ReporterConfig {
+        explicit ReporterConfig( IConfigPtr const& _fullConfig );
+
+        ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream );
+
+        std::ostream& stream() const;
+        IConfigPtr fullConfig() const;
+
+    private:
+        std::ostream* m_stream;
+        IConfigPtr m_fullConfig;
+    };
+
+    struct ReporterPreferences {
+        bool shouldRedirectStdOut = false;
+        bool shouldReportAllAssertions = false;
+    };
+
+    template<typename T>
+    struct LazyStat : Option<T> {
+        LazyStat& operator=( T const& _value ) {
+            Option<T>::operator=( _value );
+            used = false;
+            return *this;
+        }
+        void reset() {
+            Option<T>::reset();
+            used = false;
+        }
+        bool used = false;
+    };
+
+    struct TestRunInfo {
+        TestRunInfo( std::string const& _name );
+        std::string name;
+    };
+    struct GroupInfo {
+        GroupInfo(  std::string const& _name,
+                    std::size_t _groupIndex,
+                    std::size_t _groupsCount );
+
+        std::string name;
+        std::size_t groupIndex;
+        std::size_t groupsCounts;
+    };
+
+    struct AssertionStats {
+        AssertionStats( AssertionResult const& _assertionResult,
+                        std::vector<MessageInfo> const& _infoMessages,
+                        Totals const& _totals );
+
+        AssertionStats( AssertionStats const& )              = default;
+        AssertionStats( AssertionStats && )                  = default;
+        AssertionStats& operator = ( AssertionStats const& ) = default;
+        AssertionStats& operator = ( AssertionStats && )     = default;
+        virtual ~AssertionStats();
+
+        AssertionResult assertionResult;
+        std::vector<MessageInfo> infoMessages;
+        Totals totals;
+    };
+
+    struct SectionStats {
+        SectionStats(   SectionInfo const& _sectionInfo,
+                        Counts const& _assertions,
+                        double _durationInSeconds,
+                        bool _missingAssertions );
+        SectionStats( SectionStats const& )              = default;
+        SectionStats( SectionStats && )                  = default;
+        SectionStats& operator = ( SectionStats const& ) = default;
+        SectionStats& operator = ( SectionStats && )     = default;
+        virtual ~SectionStats();
+
+        SectionInfo sectionInfo;
+        Counts assertions;
+        double durationInSeconds;
+        bool missingAssertions;
+    };
+
+    struct TestCaseStats {
+        TestCaseStats(  TestCaseInfo const& _testInfo,
+                        Totals const& _totals,
+                        std::string const& _stdOut,
+                        std::string const& _stdErr,
+                        bool _aborting );
+
+        TestCaseStats( TestCaseStats const& )              = default;
+        TestCaseStats( TestCaseStats && )                  = default;
+        TestCaseStats& operator = ( TestCaseStats const& ) = default;
+        TestCaseStats& operator = ( TestCaseStats && )     = default;
+        virtual ~TestCaseStats();
+
+        TestCaseInfo testInfo;
+        Totals totals;
+        std::string stdOut;
+        std::string stdErr;
+        bool aborting;
+    };
+
+    struct TestGroupStats {
+        TestGroupStats( GroupInfo const& _groupInfo,
+                        Totals const& _totals,
+                        bool _aborting );
+        TestGroupStats( GroupInfo const& _groupInfo );
+
+        TestGroupStats( TestGroupStats const& )              = default;
+        TestGroupStats( TestGroupStats && )                  = default;
+        TestGroupStats& operator = ( TestGroupStats const& ) = default;
+        TestGroupStats& operator = ( TestGroupStats && )     = default;
+        virtual ~TestGroupStats();
+
+        GroupInfo groupInfo;
+        Totals totals;
+        bool aborting;
+    };
+
+    struct TestRunStats {
+        TestRunStats(   TestRunInfo const& _runInfo,
+                        Totals const& _totals,
+                        bool _aborting );
+
+        TestRunStats( TestRunStats const& )              = default;
+        TestRunStats( TestRunStats && )                  = default;
+        TestRunStats& operator = ( TestRunStats const& ) = default;
+        TestRunStats& operator = ( TestRunStats && )     = default;
+        virtual ~TestRunStats();
+
+        TestRunInfo runInfo;
+        Totals totals;
+        bool aborting;
+    };
+
+    struct BenchmarkInfo {
+        std::string name;
+    };
+    struct BenchmarkStats {
+        BenchmarkInfo info;
+        std::size_t iterations;
+        uint64_t elapsedTimeInNanoseconds;
+    };
+
+    struct IStreamingReporter {
+        virtual ~IStreamingReporter() = default;
+
+        // Implementing class must also provide the following static methods:
+        // static std::string getDescription();
+        // static std::set<Verbosity> getSupportedVerbosities()
+
+        virtual ReporterPreferences getPreferences() const = 0;
+
+        virtual void noMatchingTestCases( std::string const& spec ) = 0;
+
+        virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
+        virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
+
+        virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
+        virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
+
+        // *** experimental ***
+        virtual void benchmarkStarting( BenchmarkInfo const& ) {}
+
+        virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
+
+        // The return value indicates if the messages buffer should be cleared:
+        virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
+
+        // *** experimental ***
+        virtual void benchmarkEnded( BenchmarkStats const& ) {}
+
+        virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
+        virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
+        virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
+        virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
+
+        virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
+
+        // Default empty implementation provided
+        virtual void fatalErrorEncountered( StringRef name );
+
+        virtual bool isMulti() const;
+    };
+    using IStreamingReporterPtr = std::unique_ptr<IStreamingReporter>;
+
+    struct IReporterFactory {
+        virtual ~IReporterFactory();
+        virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0;
+        virtual std::string getDescription() const = 0;
+    };
+    using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;
+
+    struct IReporterRegistry {
+        using FactoryMap = std::map<std::string, IReporterFactoryPtr>;
+        using Listeners = std::vector<IReporterFactoryPtr>;
+
+        virtual ~IReporterRegistry();
+        virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0;
+        virtual FactoryMap const& getFactories() const = 0;
+        virtual Listeners const& getListeners() const = 0;
+    };
+
+} // end namespace Catch
+
+// end catch_interfaces_reporter.h
+#include <algorithm>
+#include <cstring>
+#include <cfloat>
+#include <cstdio>
+#include <cassert>
+#include <memory>
+#include <ostream>
+
+namespace Catch {
+    void prepareExpandedExpression(AssertionResult& result);
+
+    // Returns double formatted as %.3f (format expected on output)
+    std::string getFormattedDuration( double duration );
+
+    template<typename DerivedT>
+    struct StreamingReporterBase : IStreamingReporter {
+
+        StreamingReporterBase( ReporterConfig const& _config )
+        :   m_config( _config.fullConfig() ),
+            stream( _config.stream() )
+        {
+            m_reporterPrefs.shouldRedirectStdOut = false;
+            if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
+                CATCH_ERROR( "Verbosity level not supported by this reporter" );
+        }
+
+        ReporterPreferences getPreferences() const override {
+            return m_reporterPrefs;
+        }
+
+        static std::set<Verbosity> getSupportedVerbosities() {
+            return { Verbosity::Normal };
+        }
+
+        ~StreamingReporterBase() override = default;
+
+        void noMatchingTestCases(std::string const&) override {}
+
+        void testRunStarting(TestRunInfo const& _testRunInfo) override {
+            currentTestRunInfo = _testRunInfo;
+        }
+        void testGroupStarting(GroupInfo const& _groupInfo) override {
+            currentGroupInfo = _groupInfo;
+        }
+
+        void testCaseStarting(TestCaseInfo const& _testInfo) override  {
+            currentTestCaseInfo = _testInfo;
+        }
+        void sectionStarting(SectionInfo const& _sectionInfo) override {
+            m_sectionStack.push_back(_sectionInfo);
+        }
+
+        void sectionEnded(SectionStats const& /* _sectionStats */) override {
+            m_sectionStack.pop_back();
+        }
+        void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override {
+            currentTestCaseInfo.reset();
+        }
+        void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override {
+            currentGroupInfo.reset();
+        }
+        void testRunEnded(TestRunStats const& /* _testRunStats */) override {
+            currentTestCaseInfo.reset();
+            currentGroupInfo.reset();
+            currentTestRunInfo.reset();
+        }
+
+        void skipTest(TestCaseInfo const&) override {
+            // Don't do anything with this by default.
+            // It can optionally be overridden in the derived class.
+        }
+
+        IConfigPtr m_config;
+        std::ostream& stream;
+
+        LazyStat<TestRunInfo> currentTestRunInfo;
+        LazyStat<GroupInfo> currentGroupInfo;
+        LazyStat<TestCaseInfo> currentTestCaseInfo;
+
+        std::vector<SectionInfo> m_sectionStack;
+        ReporterPreferences m_reporterPrefs;
+    };
+
+    template<typename DerivedT>
+    struct CumulativeReporterBase : IStreamingReporter {
+        template<typename T, typename ChildNodeT>
+        struct Node {
+            explicit Node( T const& _value ) : value( _value ) {}
+            virtual ~Node() {}
+
+            using ChildNodes = std::vector<std::shared_ptr<ChildNodeT>>;
+            T value;
+            ChildNodes children;
+        };
+        struct SectionNode {
+            explicit SectionNode(SectionStats const& _stats) : stats(_stats) {}
+            virtual ~SectionNode() = default;
+
+            bool operator == (SectionNode const& other) const {
+                return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
+            }
+            bool operator == (std::shared_ptr<SectionNode> const& other) const {
+                return operator==(*other);
+            }
+
+            SectionStats stats;
+            using ChildSections = std::vector<std::shared_ptr<SectionNode>>;
+            using Assertions = std::vector<AssertionStats>;
+            ChildSections childSections;
+            Assertions assertions;
+            std::string stdOut;
+            std::string stdErr;
+        };
+
+        struct BySectionInfo {
+            BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
+            BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}
+            bool operator() (std::shared_ptr<SectionNode> const& node) const {
+                return ((node->stats.sectionInfo.name == m_other.name) &&
+                        (node->stats.sectionInfo.lineInfo == m_other.lineInfo));
+            }
+            void operator=(BySectionInfo const&) = delete;
+
+        private:
+            SectionInfo const& m_other;
+        };
+
+        using TestCaseNode = Node<TestCaseStats, SectionNode>;
+        using TestGroupNode = Node<TestGroupStats, TestCaseNode>;
+        using TestRunNode = Node<TestRunStats, TestGroupNode>;
+
+        CumulativeReporterBase( ReporterConfig const& _config )
+        :   m_config( _config.fullConfig() ),
+            stream( _config.stream() )
+        {
+            m_reporterPrefs.shouldRedirectStdOut = false;
+            if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
+                CATCH_ERROR( "Verbosity level not supported by this reporter" );
+        }
+        ~CumulativeReporterBase() override = default;
+
+        ReporterPreferences getPreferences() const override {
+            return m_reporterPrefs;
+        }
+
+        static std::set<Verbosity> getSupportedVerbosities() {
+            return { Verbosity::Normal };
+        }
+
+        void testRunStarting( TestRunInfo const& ) override {}
+        void testGroupStarting( GroupInfo const& ) override {}
+
+        void testCaseStarting( TestCaseInfo const& ) override {}
+
+        void sectionStarting( SectionInfo const& sectionInfo ) override {
+            SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
+            std::shared_ptr<SectionNode> node;
+            if( m_sectionStack.empty() ) {
+                if( !m_rootSection )
+                    m_rootSection = std::make_shared<SectionNode>( incompleteStats );
+                node = m_rootSection;
+            }
+            else {
+                SectionNode& parentNode = *m_sectionStack.back();
+                auto it =
+                    std::find_if(   parentNode.childSections.begin(),
+                                    parentNode.childSections.end(),
+                                    BySectionInfo( sectionInfo ) );
+                if( it == parentNode.childSections.end() ) {
+                    node = std::make_shared<SectionNode>( incompleteStats );
+                    parentNode.childSections.push_back( node );
+                }
+                else
+                    node = *it;
+            }
+            m_sectionStack.push_back( node );
+            m_deepestSection = std::move(node);
+        }
+
+        void assertionStarting(AssertionInfo const&) override {}
+
+        bool assertionEnded(AssertionStats const& assertionStats) override {
+            assert(!m_sectionStack.empty());
+            // AssertionResult holds a pointer to a temporary DecomposedExpression,
+            // which getExpandedExpression() calls to build the expression string.
+            // Our section stack copy of the assertionResult will likely outlive the
+            // temporary, so it must be expanded or discarded now to avoid calling
+            // a destroyed object later.
+            prepareExpandedExpression(const_cast<AssertionResult&>( assertionStats.assertionResult ) );
+            SectionNode& sectionNode = *m_sectionStack.back();
+            sectionNode.assertions.push_back(assertionStats);
+            return true;
+        }
+        void sectionEnded(SectionStats const& sectionStats) override {
+            assert(!m_sectionStack.empty());
+            SectionNode& node = *m_sectionStack.back();
+            node.stats = sectionStats;
+            m_sectionStack.pop_back();
+        }
+        void testCaseEnded(TestCaseStats const& testCaseStats) override {
+            auto node = std::make_shared<TestCaseNode>(testCaseStats);
+            assert(m_sectionStack.size() == 0);
+            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;
+        }
+        void testGroupEnded(TestGroupStats const& testGroupStats) override {
+            auto node = std::make_shared<TestGroupNode>(testGroupStats);
+            node->children.swap(m_testCases);
+            m_testGroups.push_back(node);
+        }
+        void testRunEnded(TestRunStats const& testRunStats) override {
+            auto node = std::make_shared<TestRunNode>(testRunStats);
+            node->children.swap(m_testGroups);
+            m_testRuns.push_back(node);
+            testRunEndedCumulative();
+        }
+        virtual void testRunEndedCumulative() = 0;
+
+        void skipTest(TestCaseInfo const&) override {}
+
+        IConfigPtr m_config;
+        std::ostream& stream;
+        std::vector<AssertionStats> m_assertions;
+        std::vector<std::vector<std::shared_ptr<SectionNode>>> m_sections;
+        std::vector<std::shared_ptr<TestCaseNode>> m_testCases;
+        std::vector<std::shared_ptr<TestGroupNode>> m_testGroups;
+
+        std::vector<std::shared_ptr<TestRunNode>> m_testRuns;
+
+        std::shared_ptr<SectionNode> m_rootSection;
+        std::shared_ptr<SectionNode> m_deepestSection;
+        std::vector<std::shared_ptr<SectionNode>> m_sectionStack;
+        ReporterPreferences m_reporterPrefs;
+    };
+
+    template<char C>
+    char const* getLineOfChars() {
+        static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
+        if( !*line ) {
+            std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
+            line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
+        }
+        return line;
+    }
+
+    struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> {
+        TestEventListenerBase( ReporterConfig const& _config );
+
+        static std::set<Verbosity> getSupportedVerbosities();
+
+        void assertionStarting(AssertionInfo const&) override;
+        bool assertionEnded(AssertionStats const&) override;
+    };
+
+} // end namespace Catch
+
+// end catch_reporter_bases.hpp
+// start catch_console_colour.h
+
+namespace Catch {
+
+    struct Colour {
+        enum Code {
+            None = 0,
+
+            White,
+            Red,
+            Green,
+            Blue,
+            Cyan,
+            Yellow,
+            Grey,
+
+            Bright = 0x10,
+
+            BrightRed = Bright | Red,
+            BrightGreen = Bright | Green,
+            LightGrey = Bright | Grey,
+            BrightWhite = Bright | White,
+            BrightYellow = Bright | Yellow,
+
+            // By intention
+            FileName = LightGrey,
+            Warning = BrightYellow,
+            ResultError = BrightRed,
+            ResultSuccess = BrightGreen,
+            ResultExpectedFailure = Warning,
+
+            Error = BrightRed,
+            Success = Green,
+
+            OriginalExpression = Cyan,
+            ReconstructedExpression = BrightYellow,
+
+            SecondaryText = LightGrey,
+            Headers = White
+        };
+
+        // Use constructed object for RAII guard
+        Colour( Code _colourCode );
+        Colour( Colour&& other ) noexcept;
+        Colour& operator=( Colour&& other ) noexcept;
+        ~Colour();
+
+        // Use static method for one-shot changes
+        static void use( Code _colourCode );
+
+    private:
+        bool m_moved = false;
+    };
+
+    std::ostream& operator << ( std::ostream& os, Colour const& );
+
+} // end namespace Catch
+
+// end catch_console_colour.h
+// start catch_reporter_registrars.hpp
+
+
+namespace Catch {
+
+    template<typename T>
+    class ReporterRegistrar {
+
+        class ReporterFactory : public IReporterFactory {
+
+            virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override {
+                return std::unique_ptr<T>( new T( config ) );
+            }
+
+            virtual std::string getDescription() const override {
+                return T::getDescription();
+            }
+        };
+
+    public:
+
+        explicit ReporterRegistrar( std::string const& name ) {
+            getMutableRegistryHub().registerReporter( name, std::make_shared<ReporterFactory>() );
+        }
+    };
+
+    template<typename T>
+    class ListenerRegistrar {
+
+        class ListenerFactory : public IReporterFactory {
+
+            virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override {
+                return std::unique_ptr<T>( new T( config ) );
+            }
+            virtual std::string getDescription() const override {
+                return std::string();
+            }
+        };
+
+    public:
+
+        ListenerRegistrar() {
+            getMutableRegistryHub().registerListener( std::make_shared<ListenerFactory>() );
+        }
+    };
+}
+
+#if !defined(CATCH_CONFIG_DISABLE)
+
+#define CATCH_REGISTER_REPORTER( name, reporterType ) \
+    CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS          \
+    namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \
+    CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
+
+#define CATCH_REGISTER_LISTENER( listenerType ) \
+     CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS   \
+     namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \
+     CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
+#else // CATCH_CONFIG_DISABLE
+
+#define CATCH_REGISTER_REPORTER(name, reporterType)
+#define CATCH_REGISTER_LISTENER(listenerType)
+
+#endif // CATCH_CONFIG_DISABLE
+
+// end catch_reporter_registrars.hpp
+// Allow users to base their work off existing reporters
+// start catch_reporter_compact.h
+
+namespace Catch {
+
+    struct CompactReporter : StreamingReporterBase<CompactReporter> {
+
+        using StreamingReporterBase::StreamingReporterBase;
+
+        ~CompactReporter() override;
+
+        static std::string getDescription();
+
+        ReporterPreferences getPreferences() const override;
+
+        void noMatchingTestCases(std::string const& spec) override;
+
+        void assertionStarting(AssertionInfo const&) override;
+
+        bool assertionEnded(AssertionStats const& _assertionStats) override;
+
+        void sectionEnded(SectionStats const& _sectionStats) override;
+
+        void testRunEnded(TestRunStats const& _testRunStats) override;
+
+    };
+
+} // end namespace Catch
+
+// end catch_reporter_compact.h
+// start catch_reporter_console.h
+
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch
+                              // Note that 4062 (not all labels are handled
+                              // and default is missing) is enabled
+#endif
+
+namespace Catch {
+    // Fwd decls
+    struct SummaryColumn;
+    class TablePrinter;
+
+    struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> {
+        std::unique_ptr<TablePrinter> m_tablePrinter;
+
+        ConsoleReporter(ReporterConfig const& config);
+        ~ConsoleReporter() override;
+        static std::string getDescription();
+
+        void noMatchingTestCases(std::string const& spec) override;
+
+        void assertionStarting(AssertionInfo const&) override;
+
+        bool assertionEnded(AssertionStats const& _assertionStats) override;
+
+        void sectionStarting(SectionInfo const& _sectionInfo) override;
+        void sectionEnded(SectionStats const& _sectionStats) override;
+
+        void benchmarkStarting(BenchmarkInfo const& info) override;
+        void benchmarkEnded(BenchmarkStats const& stats) override;
+
+        void testCaseEnded(TestCaseStats const& _testCaseStats) override;
+        void testGroupEnded(TestGroupStats const& _testGroupStats) override;
+        void testRunEnded(TestRunStats const& _testRunStats) override;
+
+    private:
+
+        void lazyPrint();
+
+        void lazyPrintWithoutClosingBenchmarkTable();
+        void lazyPrintRunInfo();
+        void lazyPrintGroupInfo();
+        void printTestCaseAndSectionHeader();
+
+        void printClosedHeader(std::string const& _name);
+        void printOpenHeader(std::string const& _name);
+
+        // if string has a : in first line will set indent to follow it on
+        // subsequent lines
+        void printHeaderString(std::string const& _string, std::size_t indent = 0);
+
+        void printTotals(Totals const& totals);
+        void printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row);
+
+        void printTotalsDivider(Totals const& totals);
+        void printSummaryDivider();
+
+    private:
+        bool m_headerPrinted = false;
+    };
+
+} // end namespace Catch
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+// end catch_reporter_console.h
+// start catch_reporter_junit.h
+
+// start catch_xmlwriter.h
+
+#include <vector>
+
+namespace Catch {
+
+    class XmlEncode {
+    public:
+        enum ForWhat { ForTextNodes, ForAttributes };
+
+        XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes );
+
+        void encodeTo( std::ostream& os ) const;
+
+        friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode );
+
+    private:
+        std::string m_str;
+        ForWhat m_forWhat;
+    };
+
+    class XmlWriter {
+    public:
+
+        class ScopedElement {
+        public:
+            ScopedElement( XmlWriter* writer );
+
+            ScopedElement( ScopedElement&& other ) noexcept;
+            ScopedElement& operator=( ScopedElement&& other ) noexcept;
+
+            ~ScopedElement();
+
+            ScopedElement& writeText( std::string const& text, bool indent = true );
+
+            template<typename T>
+            ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
+                m_writer->writeAttribute( name, attribute );
+                return *this;
+            }
+
+        private:
+            mutable XmlWriter* m_writer = nullptr;
+        };
+
+        XmlWriter( std::ostream& os = Catch::cout() );
+        ~XmlWriter();
+
+        XmlWriter( XmlWriter const& ) = delete;
+        XmlWriter& operator=( XmlWriter const& ) = delete;
+
+        XmlWriter& startElement( std::string const& name );
+
+        ScopedElement scopedElement( std::string const& name );
+
+        XmlWriter& endElement();
+
+        XmlWriter& writeAttribute( std::string const& name, std::string const& attribute );
+
+        XmlWriter& writeAttribute( std::string const& name, bool attribute );
+
+        template<typename T>
+        XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
+            ReusableStringStream rss;
+            rss << attribute;
+            return writeAttribute( name, rss.str() );
+        }
+
+        XmlWriter& writeText( std::string const& text, bool indent = true );
+
+        XmlWriter& writeComment( std::string const& text );
+
+        void writeStylesheetRef( std::string const& url );
+
+        XmlWriter& writeBlankLine();
+
+        void ensureTagClosed();
+
+    private:
+
+        void writeDeclaration();
+
+        void newlineIfNecessary();
+
+        bool m_tagIsOpen = false;
+        bool m_needsNewline = false;
+        std::vector<std::string> m_tags;
+        std::string m_indent;
+        std::ostream& m_os;
+    };
+
+}
+
+// end catch_xmlwriter.h
+namespace Catch {
+
+    class JunitReporter : public CumulativeReporterBase<JunitReporter> {
+    public:
+        JunitReporter(ReporterConfig const& _config);
+
+        ~JunitReporter() override;
+
+        static std::string getDescription();
+
+        void noMatchingTestCases(std::string const& /*spec*/) override;
+
+        void testRunStarting(TestRunInfo const& runInfo) override;
+
+        void testGroupStarting(GroupInfo const& groupInfo) override;
+
+        void testCaseStarting(TestCaseInfo const& testCaseInfo) override;
+        bool assertionEnded(AssertionStats const& assertionStats) override;
+
+        void testCaseEnded(TestCaseStats const& testCaseStats) override;
+
+        void testGroupEnded(TestGroupStats const& testGroupStats) override;
+
+        void testRunEndedCumulative() override;
+
+        void writeGroup(TestGroupNode const& groupNode, double suiteTime);
+
+        void writeTestCase(TestCaseNode const& testCaseNode);
+
+        void writeSection(std::string const& className,
+                          std::string const& rootName,
+                          SectionNode const& sectionNode);
+
+        void writeAssertions(SectionNode const& sectionNode);
+        void writeAssertion(AssertionStats const& stats);
+
+        XmlWriter xml;
+        Timer suiteTimer;
+        std::string stdOutForSuite;
+        std::string stdErrForSuite;
+        unsigned int unexpectedExceptions = 0;
+        bool m_okToFail = false;
+    };
+
+} // end namespace Catch
+
+// end catch_reporter_junit.h
+// start catch_reporter_xml.h
+
+namespace Catch {
+    class XmlReporter : public StreamingReporterBase<XmlReporter> {
+    public:
+        XmlReporter(ReporterConfig const& _config);
+
+        ~XmlReporter() override;
+
+        static std::string getDescription();
+
+        virtual std::string getStylesheetRef() const;
+
+        void writeSourceInfo(SourceLineInfo const& sourceInfo);
+
+    public: // StreamingReporterBase
+
+        void noMatchingTestCases(std::string const& s) override;
+
+        void testRunStarting(TestRunInfo const& testInfo) override;
+
+        void testGroupStarting(GroupInfo const& groupInfo) override;
+
+        void testCaseStarting(TestCaseInfo const& testInfo) override;
+
+        void sectionStarting(SectionInfo const& sectionInfo) override;
+
+        void assertionStarting(AssertionInfo const&) override;
+
+        bool assertionEnded(AssertionStats const& assertionStats) override;
+
+        void sectionEnded(SectionStats const& sectionStats) override;
+
+        void testCaseEnded(TestCaseStats const& testCaseStats) override;
+
+        void testGroupEnded(TestGroupStats const& testGroupStats) override;
+
+        void testRunEnded(TestRunStats const& testRunStats) override;
+
+    private:
+        Timer m_testCaseTimer;
+        XmlWriter m_xml;
+        int m_sectionDepth = 0;
+    };
+
+} // end namespace Catch
+
+// end catch_reporter_xml.h
+
+// end catch_external_interfaces.h
+#endif
+
+#endif // ! CATCH_CONFIG_IMPL_ONLY
+
+#ifdef CATCH_IMPL
+// start catch_impl.hpp
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wweak-vtables"
+#endif
+
+// Keep these here for external reporters
+// start catch_test_case_tracker.h
+
+#include <string>
+#include <vector>
+#include <memory>
+
+namespace Catch {
+namespace TestCaseTracking {
+
+    struct NameAndLocation {
+        std::string name;
+        SourceLineInfo location;
+
+        NameAndLocation( std::string const& _name, SourceLineInfo const& _location );
+    };
+
+    struct ITracker;
+
+    using ITrackerPtr = std::shared_ptr<ITracker>;
+
+    struct ITracker {
+        virtual ~ITracker();
+
+        // static queries
+        virtual NameAndLocation const& nameAndLocation() const = 0;
+
+        // dynamic queries
+        virtual bool isComplete() const = 0; // Successfully completed or failed
+        virtual bool isSuccessfullyCompleted() const = 0;
+        virtual bool isOpen() const = 0; // Started but not complete
+        virtual bool hasChildren() const = 0;
+
+        virtual ITracker& parent() = 0;
+
+        // actions
+        virtual void close() = 0; // Successfully complete
+        virtual void fail() = 0;
+        virtual void markAsNeedingAnotherRun() = 0;
+
+        virtual void addChild( ITrackerPtr const& child ) = 0;
+        virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) = 0;
+        virtual void openChild() = 0;
+
+        // Debug/ checking
+        virtual bool isSectionTracker() const = 0;
+        virtual bool isIndexTracker() const = 0;
+    };
+
+    class TrackerContext {
+
+        enum RunState {
+            NotStarted,
+            Executing,
+            CompletedCycle
+        };
+
+        ITrackerPtr m_rootTracker;
+        ITracker* m_currentTracker = nullptr;
+        RunState m_runState = NotStarted;
+
+    public:
+
+        static TrackerContext& instance();
+
+        ITracker& startRun();
+        void endRun();
+
+        void startCycle();
+        void completeCycle();
+
+        bool completedCycle() const;
+        ITracker& currentTracker();
+        void setCurrentTracker( ITracker* tracker );
+    };
+
+    class TrackerBase : public ITracker {
+    protected:
+        enum CycleState {
+            NotStarted,
+            Executing,
+            ExecutingChildren,
+            NeedsAnotherRun,
+            CompletedSuccessfully,
+            Failed
+        };
+
+        using Children = std::vector<ITrackerPtr>;
+        NameAndLocation m_nameAndLocation;
+        TrackerContext& m_ctx;
+        ITracker* m_parent;
+        Children m_children;
+        CycleState m_runState = NotStarted;
+
+    public:
+        TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
+
+        NameAndLocation const& nameAndLocation() const override;
+        bool isComplete() const override;
+        bool isSuccessfullyCompleted() const override;
+        bool isOpen() const override;
+        bool hasChildren() const override;
+
+        void addChild( ITrackerPtr const& child ) override;
+
+        ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override;
+        ITracker& parent() override;
+
+        void openChild() override;
+
+        bool isSectionTracker() const override;
+        bool isIndexTracker() const override;
+
+        void open();
+
+        void close() override;
+        void fail() override;
+        void markAsNeedingAnotherRun() override;
+
+    private:
+        void moveToParent();
+        void moveToThis();
+    };
+
+    class SectionTracker : public TrackerBase {
+        std::vector<std::string> m_filters;
+    public:
+        SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
+
+        bool isSectionTracker() const override;
+
+        static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation );
+
+        void tryOpen();
+
+        void addInitialFilters( std::vector<std::string> const& filters );
+        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
+
+// end catch_test_case_tracker.h
+
+// start catch_leak_detector.h
+
+namespace Catch {
+
+    struct LeakDetector {
+        LeakDetector();
+        ~LeakDetector();
+    };
+
+}
+// end catch_leak_detector.h
+// Cpp files will be included in the single-header file here
+// start catch_approx.cpp
+
+#include <cmath>
+#include <limits>
+
+namespace {
+
+// Performs equivalent check of std::fabs(lhs - rhs) <= margin
+// But without the subtraction to allow for INFINITY in comparison
+bool marginComparison(double lhs, double rhs, double margin) {
+    return (lhs + margin >= rhs) && (rhs + margin >= lhs);
+}
+
+}
+
+namespace Catch {
+namespace Detail {
+
+    Approx::Approx ( double value )
+    :   m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
+        m_margin( 0.0 ),
+        m_scale( 0.0 ),
+        m_value( value )
+    {}
+
+    Approx Approx::custom() {
+        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 ) << " )";
+        return rss.str();
+    }
+
+    bool Approx::equalityComparisonImpl(const double other) const {
+        // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value
+        // Thanks to Richard Harris for his help refining the scaled margin value
+        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();
+}
+
+} // end namespace Catch
+// 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 {
+    bool isDebuggerActive();
+}
+
+#ifdef CATCH_PLATFORM_MAC
+
+    #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
+
+#elif defined(CATCH_PLATFORM_LINUX)
+    // If we can use inline assembler, do it because this allows us to break
+    // directly at the location of the failing check instead of breaking inside
+    // raise() called from it, i.e. one stack frame below.
+    #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
+        #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */
+    #else // Fall back to the generic way.
+        #include <signal.h>
+
+        #define CATCH_TRAP() raise(SIGTRAP)
+    #endif
+#elif defined(_MSC_VER)
+    #define CATCH_TRAP() __debugbreak()
+#elif defined(__MINGW32__)
+    extern "C" __declspec(dllimport) void __stdcall DebugBreak();
+    #define CATCH_TRAP() DebugBreak()
+#endif
+
+#ifdef 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()
+#endif
+
+// end catch_debugger.h
+// start catch_run_context.h
+
+// start catch_fatal_condition.h
+
+// start catch_windows_h_proxy.h
+
+
+#if defined(CATCH_PLATFORM_WINDOWS)
+
+#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
+#  define CATCH_DEFINED_NOMINMAX
+#  define NOMINMAX
+#endif
+#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
+#  define CATCH_DEFINED_WIN32_LEAN_AND_MEAN
+#  define WIN32_LEAN_AND_MEAN
+#endif
+
+#ifdef __AFXDLL
+#include <AfxWin.h>
+#else
+#include <windows.h>
+#endif
+
+#ifdef CATCH_DEFINED_NOMINMAX
+#  undef NOMINMAX
+#endif
+#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN
+#  undef WIN32_LEAN_AND_MEAN
+#endif
+
+#endif // defined(CATCH_PLATFORM_WINDOWS)
+
+// end catch_windows_h_proxy.h
+#if defined( CATCH_CONFIG_WINDOWS_SEH )
+
+namespace Catch {
+
+    struct FatalConditionHandler {
+
+        static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo);
+        FatalConditionHandler();
+        static void reset();
+        ~FatalConditionHandler();
+
+    private:
+        static bool isSet;
+        static ULONG guaranteeSize;
+        static PVOID exceptionHandlerHandle;
+    };
+
+} // namespace Catch
+
+#elif defined ( CATCH_CONFIG_POSIX_SIGNALS )
+
+#include <signal.h>
+
+namespace Catch {
+
+    struct FatalConditionHandler {
+
+        static bool isSet;
+        static struct sigaction oldSigActions[];
+        static stack_t oldSigStack;
+        static char altStackMem[];
+
+        static void handleSignal( int sig );
+
+        FatalConditionHandler();
+        ~FatalConditionHandler();
+        static void reset();
+    };
+
+} // namespace Catch
+
+#else
+
+namespace Catch {
+    struct FatalConditionHandler {
+        void reset();
+    };
+}
+
+#endif
+
+// end catch_fatal_condition.h
+#include <string>
+
+namespace Catch {
+
+    struct IMutableContext;
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    class RunContext : public IResultCapture, public IRunner {
+
+    public:
+        RunContext( RunContext const& ) = delete;
+        RunContext& operator =( RunContext const& ) = delete;
+
+        explicit RunContext( IConfigPtr const& _config, IStreamingReporterPtr&& reporter );
+
+        ~RunContext() override;
+
+        void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount );
+        void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount );
+
+        Totals runTest(TestCase const& testCase);
+
+        IConfigPtr config() const;
+        IStreamingReporter& reporter() const;
+
+    public: // IResultCapture
+
+        // Assertion handlers
+        void handleExpr
+                (   AssertionInfo const& info,
+                    ITransientExpression const& expr,
+                    AssertionReaction& reaction ) override;
+        void handleMessage
+                (   AssertionInfo const& info,
+                    ResultWas::OfType resultType,
+                    StringRef const& message,
+                    AssertionReaction& reaction ) override;
+        void handleUnexpectedExceptionNotThrown
+                (   AssertionInfo const& info,
+                    AssertionReaction& reaction ) override;
+        void handleUnexpectedInflightException
+                (   AssertionInfo const& info,
+                    std::string const& message,
+                    AssertionReaction& reaction ) override;
+        void handleIncomplete
+                (   AssertionInfo const& info ) override;
+        void handleNonExpr
+                (   AssertionInfo const &info,
+                    ResultWas::OfType resultType,
+                    AssertionReaction &reaction ) override;
+
+        bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override;
+
+        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;
+
+        std::string getCurrentTestName() const override;
+
+        const AssertionResult* getLastResult() const override;
+
+        void exceptionEarlyReported() override;
+
+        void handleFatalErrorCondition( StringRef message ) override;
+
+        bool lastAssertionPassed() override;
+
+        void assertionPassed() override;
+
+    public:
+        // !TBD We need to do this another way!
+        bool aborting() const final;
+
+    private:
+
+        void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr );
+        void invokeActiveTestCase();
+
+        void resetAssertionInfo();
+        bool testForMissingAssertions( Counts& assertions );
+
+        void assertionEnded( AssertionResult const& result );
+        void reportExpr
+                (   AssertionInfo const &info,
+                    ResultWas::OfType resultType,
+                    ITransientExpression const *expr,
+                    bool negated );
+
+        void populateReaction( AssertionReaction& reaction );
+
+    private:
+
+        void handleUnfinishedSections();
+
+        TestRunInfo m_runInfo;
+        IMutableContext& m_context;
+        TestCase const* m_activeTestCase = nullptr;
+        ITracker* m_testCaseTracker;
+        Option<AssertionResult> m_lastResult;
+
+        IConfigPtr m_config;
+        Totals m_totals;
+        IStreamingReporterPtr m_reporter;
+        std::vector<MessageInfo> m_messages;
+        AssertionInfo m_lastAssertionInfo;
+        std::vector<SectionEndInfo> m_unfinishedSections;
+        std::vector<ITracker*> m_activeSections;
+        TrackerContext m_trackerContext;
+        bool m_lastAssertionPassed = false;
+        bool m_shouldReportUnexpected = true;
+        bool m_includeSuccessfulResults;
+    };
+
+} // end namespace Catch
+
+// end catch_run_context.h
+namespace Catch {
+
+    namespace {
+        auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& {
+            expr.streamReconstructedExpression( os );
+            return os;
+        }
+    }
+
+    LazyExpression::LazyExpression( bool isNegated )
+    :   m_isNegated( isNegated )
+    {}
+
+    LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {}
+
+    LazyExpression::operator bool() const {
+        return m_transientExpression != nullptr;
+    }
+
+    auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& {
+        if( lazyExpr.m_isNegated )
+            os << "!";
+
+        if( lazyExpr ) {
+            if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() )
+                os << "(" << *lazyExpr.m_transientExpression << ")";
+            else
+                os << *lazyExpr.m_transientExpression;
+        }
+        else {
+            os << "{** error - unchecked empty expression requested **}";
+        }
+        return os;
+    }
+
+    AssertionHandler::AssertionHandler
+        (   StringRef const& macroName,
+            SourceLineInfo const& lineInfo,
+            StringRef capturedExpression,
+            ResultDisposition::Flags resultDisposition )
+    :   m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
+        m_resultCapture( getResultCapture() )
+    {}
+
+    void AssertionHandler::handleExpr( ITransientExpression const& expr ) {
+        m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction );
+    }
+    void AssertionHandler::handleMessage(ResultWas::OfType resultType, StringRef const& message) {
+        m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction );
+    }
+
+    auto AssertionHandler::allowThrows() const -> bool {
+        return getCurrentContext().getConfig()->allowThrows();
+    }
+
+    void AssertionHandler::complete() {
+        setCompleted();
+        if( m_reaction.shouldDebugBreak ) {
+
+            // If you find your debugger stopping you here then go one level up on the
+            // call-stack for the code that caused it (typically a failed assertion)
+
+            // (To go back to the test and change execution, jump over the throw, next)
+            CATCH_BREAK_INTO_DEBUGGER();
+        }
+        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;
+    }
+
+    void AssertionHandler::handleUnexpectedInflightException() {
+        m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction );
+    }
+
+    void AssertionHandler::handleExceptionThrownAsExpected() {
+        m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
+    }
+    void AssertionHandler::handleExceptionNotThrownAsExpected() {
+        m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
+    }
+
+    void AssertionHandler::handleUnexpectedExceptionNotThrown() {
+        m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction );
+    }
+
+    void AssertionHandler::handleThrowingCallSkipped() {
+        m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
+    }
+
+    // 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 const& matcherString  ) {
+        handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString );
+    }
+
+} // namespace Catch
+// end catch_assertionhandler.cpp
+// start catch_assertionresult.cpp
+
+namespace Catch {
+    AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression):
+        lazyExpression(_lazyExpression),
+        resultType(_resultType) {}
+
+    std::string AssertionResultData::reconstructExpression() const {
+
+        if( reconstructedExpression.empty() ) {
+            if( lazyExpression ) {
+                ReusableStringStream rss;
+                rss << lazyExpression;
+                reconstructedExpression = rss.str();
+            }
+        }
+        return reconstructedExpression;
+    }
+
+    AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
+    :   m_info( info ),
+        m_resultData( data )
+    {}
+
+    // Result was a success
+    bool AssertionResult::succeeded() const {
+        return Catch::isOk( m_resultData.resultType );
+    }
+
+    // Result was a success, or failure is suppressed
+    bool AssertionResult::isOk() const {
+        return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
+    }
+
+    ResultWas::OfType AssertionResult::getResultType() const {
+        return m_resultData.resultType;
+    }
+
+    bool AssertionResult::hasExpression() const {
+        return m_info.capturedExpression[0] != 0;
+    }
+
+    bool AssertionResult::hasMessage() const {
+        return !m_resultData.message.empty();
+    }
+
+    std::string AssertionResult::getExpression() const {
+        if( isFalseTest( m_info.resultDisposition ) )
+            return "!(" + m_info.capturedExpression + ")";
+        else
+            return m_info.capturedExpression;
+    }
+
+    std::string AssertionResult::getExpressionInMacro() const {
+        std::string expr;
+        if( m_info.macroName[0] == 0 )
+            expr = m_info.capturedExpression;
+        else {
+            expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
+            expr += m_info.macroName;
+            expr += "( ";
+            expr += m_info.capturedExpression;
+            expr += " )";
+        }
+        return expr;
+    }
+
+    bool AssertionResult::hasExpandedExpression() const {
+        return hasExpression() && getExpandedExpression() != getExpression();
+    }
+
+    std::string AssertionResult::getExpandedExpression() const {
+        std::string expr = m_resultData.reconstructExpression();
+        return expr.empty()
+                ? getExpression()
+                : expr;
+    }
+
+    std::string AssertionResult::getMessage() const {
+        return m_resultData.message;
+    }
+    SourceLineInfo AssertionResult::getSourceInfo() const {
+        return m_info.lineInfo;
+    }
+
+    StringRef AssertionResult::getTestMacroName() const {
+        return m_info.macroName;
+    }
+
+} // end namespace Catch
+// end catch_assertionresult.cpp
+// start catch_benchmark.cpp
+
+namespace Catch {
+
+    auto BenchmarkLooper::getResolution() -> uint64_t {
+        return getEstimatedClockResolution() * getCurrentContext().getConfig()->benchmarkResolutionMultiple();
+    }
+
+    void BenchmarkLooper::reportStart() {
+        getResultCapture().benchmarkStarting( { m_name } );
+    }
+    auto BenchmarkLooper::needsMoreIterations() -> bool {
+        auto elapsed = m_timer.getElapsedNanoseconds();
+
+        // Exponentially increasing iterations until we're confident in our timer resolution
+        if( elapsed < m_resolution ) {
+            m_iterationsToRun *= 10;
+            return true;
+        }
+
+        getResultCapture().benchmarkEnded( { { m_name }, m_count, elapsed } );
+        return false;
+    }
+
+} // end namespace Catch
+// end catch_benchmark.cpp
+// start catch_capture_matchers.cpp
+
+namespace Catch {
+
+    using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
+
+    // This is the general overload that takes a any string matcher
+    // 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 const& matcherString  ) {
+        std::string exceptionMessage = Catch::translateActiveException();
+        MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString );
+        handler.handleExpr( expr );
+    }
+
+} // namespace Catch
+// end catch_capture_matchers.cpp
+// start catch_commandline.cpp
+
+// start catch_commandline.h
+
+// start catch_clara.h
+
+// Use Catch's value for console width (store Clara's off to the side, if present)
+#ifdef CLARA_CONFIG_CONSOLE_WIDTH
+#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
+#undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
+#endif
+#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wweak-vtables"
+#pragma clang diagnostic ignored "-Wexit-time-destructors"
+#pragma clang diagnostic ignored "-Wshadow"
+#endif
+
+// start clara.hpp
+// 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)
+//
+// See https://github.com/philsquared/Clara for more details
+
+// Clara v1.1.5
+
+
+#ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH
+#define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80
+#endif
+
+#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
+#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
+//
+// 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
+
+
+#include <cassert>
+#include <ostream>
+#include <sstream>
+#include <vector>
+
+#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
+#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80
+#endif
+
+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;
+}
+
+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;
+
+public:
+	class iterator {
+		friend Column;
+
+		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;
+
+		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 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]);
+		}
+
+		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;
+
+			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;
+				}
+			}
+		}
+
+		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);
+		}
+
+	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);
+			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);
+			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;
+
+			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;
+
+	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() 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;
+	}
+
+	auto operator + (Column const& other)->Columns;
+
+	auto toString() const -> std::string {
+		std::ostringstream oss;
+		oss << *this;
+		return oss.str();
+	}
+};
+
+class Spacer : public Column {
+
+public:
+	explicit Spacer(size_t spaceWidth) : Column("") {
+		width(spaceWidth);
+	}
+};
+
+class Columns {
+	std::vector<Column> m_columns;
+
+public:
+
+	class iterator {
+		friend Columns;
+		struct EndTag {};
+
+		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());
+
+			for (auto const& col : m_columns)
+				m_iterators.push_back(col.end());
+		}
+
+	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()) {
+			m_iterators.reserve(m_columns.size());
+
+			for (auto const& col : m_columns)
+				m_iterators.push_back(col.begin());
+		}
+
+		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 (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 begin() const -> iterator { return iterator(*this); }
+	auto end() const -> iterator { return { *this, iterator::EndTag() }; }
+
+	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;
+	}
+
+	inline friend std::ostream& operator << (std::ostream& os, Columns const& cols) {
+
+		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 <string>
+#include <memory>
+#include <set>
+#include <algorithm>
+
+#if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) )
+#define CATCH_PLATFORM_WINDOWS
+#endif
+
+namespace Catch { namespace clara {
+namespace detail {
+
+    // Traits for extracting arg and return type of lambdas (for single argument lambdas)
+    template<typename L>
+    struct UnaryLambdaTraits : UnaryLambdaTraits<decltype( &L::operator() )> {};
+
+    template<typename ClassT, typename ReturnT, typename... Args>
+    struct UnaryLambdaTraits<ReturnT( ClassT::* )( Args... ) const> {
+        static const bool isValid = false;
+    };
+
+    template<typename ClassT, typename ReturnT, typename ArgT>
+    struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
+        static const bool isValid = true;
+        using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;
+        using ReturnType = ReturnT;
+    };
+
+    class TokenStream;
+
+    // Transport for raw args (copied from main args, or supplied via init list for testing)
+    class Args {
+        friend TokenStream;
+        std::string m_exeName;
+        std::vector<std::string> m_args;
+
+    public:
+        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() ),
+            m_args( args.begin()+1, args.end() )
+        {}
+
+        auto exeName() const -> std::string {
+            return m_exeName;
+        }
+    };
+
+    // Wraps a token coming from a token stream. These may not directly correspond to strings as a single string
+    // may encode an option + its argument if the : or = form is used
+    enum class TokenType {
+        Option, Argument
+    };
+    struct Token {
+        TokenType type;
+        std::string token;
+    };
+
+    inline auto isOptPrefix( char c ) -> bool {
+        return c == '-'
+#ifdef CATCH_PLATFORM_WINDOWS
+            || c == '/'
+#endif
+        ;
+    }
+
+    // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled
+    class TokenStream {
+        using Iterator = std::vector<std::string>::const_iterator;
+        Iterator it;
+        Iterator itEnd;
+        std::vector<Token> m_tokenBuffer;
+
+        void loadBuffer() {
+            m_tokenBuffer.resize( 0 );
+
+            // Skip any empty strings
+            while( it != itEnd && it->empty() )
+                ++it;
+
+            if( it != itEnd ) {
+                auto const &next = *it;
+                if( isOptPrefix( next[0] ) ) {
+                    auto delimiterPos = next.find_first_of( " :=" );
+                    if( delimiterPos != std::string::npos ) {
+                        m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } );
+                        m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } );
+                    } else {
+                        if( next[1] != '-' && next.size() > 2 ) {
+                            std::string opt = "- ";
+                            for( size_t i = 1; i < next.size(); ++i ) {
+                                opt[1] = next[i];
+                                m_tokenBuffer.push_back( { TokenType::Option, opt } );
+                            }
+                        } else {
+                            m_tokenBuffer.push_back( { TokenType::Option, next } );
+                        }
+                    }
+                } else {
+                    m_tokenBuffer.push_back( { TokenType::Argument, next } );
+                }
+            }
+        }
+
+    public:
+        explicit TokenStream( Args const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {}
+
+        TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) {
+            loadBuffer();
+        }
+
+        explicit operator bool() const {
+            return !m_tokenBuffer.empty() || it != itEnd;
+        }
+
+        auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); }
+
+        auto operator*() const -> Token {
+            assert( !m_tokenBuffer.empty() );
+            return m_tokenBuffer.front();
+        }
+
+        auto operator->() const -> Token const * {
+            assert( !m_tokenBuffer.empty() );
+            return &m_tokenBuffer.front();
+        }
+
+        auto operator++() -> TokenStream & {
+            if( m_tokenBuffer.size() >= 2 ) {
+                m_tokenBuffer.erase( m_tokenBuffer.begin() );
+            } else {
+                if( it != itEnd )
+                    ++it;
+                loadBuffer();
+            }
+            return *this;
+        }
+    };
+
+    class ResultBase {
+    public:
+        enum Type {
+            Ok, LogicError, RuntimeError
+        };
+
+    protected:
+        ResultBase( Type type ) : m_type( type ) {}
+        virtual ~ResultBase() = default;
+
+        virtual void enforceOk() const = 0;
+
+        Type m_type;
+    };
+
+    template<typename T>
+    class ResultValueBase : public ResultBase {
+    public:
+        auto value() const -> T const & {
+            enforceOk();
+            return m_value;
+        }
+
+    protected:
+        ResultValueBase( Type type ) : ResultBase( type ) {}
+
+        ResultValueBase( ResultValueBase const &other ) : ResultBase( other ) {
+            if( m_type == ResultBase::Ok )
+                new( &m_value ) T( other.m_value );
+        }
+
+        ResultValueBase( Type, T const &value ) : ResultBase( Ok ) {
+            new( &m_value ) T( value );
+        }
+
+        auto operator=( ResultValueBase const &other ) -> ResultValueBase & {
+            if( m_type == ResultBase::Ok )
+                m_value.~T();
+            ResultBase::operator=(other);
+            if( m_type == ResultBase::Ok )
+                new( &m_value ) T( other.m_value );
+            return *this;
+        }
+
+        ~ResultValueBase() override {
+            if( m_type == Ok )
+                m_value.~T();
+        }
+
+        union {
+            T m_value;
+        };
+    };
+
+    template<>
+    class ResultValueBase<void> : public ResultBase {
+    protected:
+        using ResultBase::ResultBase;
+    };
+
+    template<typename T = void>
+    class BasicResult : public ResultValueBase<T> {
+    public:
+        template<typename U>
+        explicit BasicResult( BasicResult<U> const &other )
+        :   ResultValueBase<T>( other.type() ),
+            m_errorMessage( other.errorMessage() )
+        {
+            assert( type() != ResultBase::Ok );
+        }
+
+        template<typename U>
+        static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; }
+        static auto ok() -> BasicResult { return { ResultBase::Ok }; }
+        static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; }
+        static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; }
+
+        explicit operator bool() const { return m_type == ResultBase::Ok; }
+        auto type() const -> ResultBase::Type { return m_type; }
+        auto errorMessage() const -> std::string { return m_errorMessage; }
+
+    protected:
+        void enforceOk() const override {
+
+            // 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
+
+        BasicResult( ResultBase::Type type, std::string const &message )
+        :   ResultValueBase<T>(type),
+            m_errorMessage(message)
+        {
+            assert( m_type != ResultBase::Ok );
+        }
+
+        using ResultValueBase<T>::ResultValueBase;
+        using ResultBase::m_type;
+    };
+
+    enum class ParseResultType {
+        Matched, NoMatch, ShortCircuitAll, ShortCircuitSame
+    };
+
+    class ParseState {
+    public:
+
+        ParseState( ParseResultType type, TokenStream const &remainingTokens )
+        : m_type(type),
+          m_remainingTokens( remainingTokens )
+        {}
+
+        auto type() const -> ParseResultType { return m_type; }
+        auto remainingTokens() const -> TokenStream { return m_remainingTokens; }
+
+    private:
+        ParseResultType m_type;
+        TokenStream m_remainingTokens;
+    };
+
+    using Result = BasicResult<void>;
+    using ParserResult = BasicResult<ParseResultType>;
+    using InternalParseResult = BasicResult<ParseState>;
+
+    struct HelpColumns {
+        std::string left;
+        std::string right;
+    };
+
+    template<typename T>
+    inline auto convertInto( std::string const &source, T& target ) -> ParserResult {
+        std::stringstream ss;
+        ss << source;
+        ss >> target;
+        if( ss.fail() )
+            return ParserResult::runtimeError( "Unable to convert '" + source + "' to destination type" );
+        else
+            return ParserResult::ok( ParseResultType::Matched );
+    }
+    inline auto convertInto( std::string const &source, std::string& target ) -> ParserResult {
+        target = source;
+        return ParserResult::ok( ParseResultType::Matched );
+    }
+    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) ); } );
+        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")
+            target = false;
+        else
+            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;
+        NonCopyable( NonCopyable const & ) = delete;
+        NonCopyable( NonCopyable && ) = delete;
+        NonCopyable &operator=( NonCopyable const & ) = delete;
+        NonCopyable &operator=( NonCopyable && ) = delete;
+    };
+
+    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>
+    struct BoundValueRef : BoundValueRefBase {
+        T &m_ref;
+
+        explicit BoundValueRef( T &ref ) : m_ref( ref ) {}
+
+        auto setValue( std::string const &arg ) -> ParserResult override {
+            return convertInto( arg, m_ref );
+        }
+    };
+
+    template<typename T>
+    struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
+        std::vector<T> &m_ref;
+
+        explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {}
+
+        auto isContainer() const -> bool override { return true; }
+
+        auto setValue( std::string const &arg ) -> ParserResult override {
+            T temp;
+            auto result = convertInto( arg, temp );
+            if( result )
+                m_ref.push_back( temp );
+            return result;
+        }
+    };
+
+    struct BoundFlagRef : BoundFlagRefBase {
+        bool &m_ref;
+
+        explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {}
+
+        auto setFlag( bool flag ) -> ParserResult override {
+            m_ref = flag;
+            return ParserResult::ok( ParseResultType::Matched );
+        }
+    };
+
+    template<typename ReturnType>
+    struct LambdaInvoker {
+        static_assert( std::is_same<ReturnType, ParserResult>::value, "Lambda must return void or clara::ParserResult" );
+
+        template<typename L, typename ArgType>
+        static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult {
+            return lambda( arg );
+        }
+    };
+
+    template<>
+    struct LambdaInvoker<void> {
+        template<typename L, typename ArgType>
+        static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult {
+            lambda( arg );
+            return ParserResult::ok( ParseResultType::Matched );
+        }
+    };
+
+    template<typename ArgType, typename L>
+    inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult {
+        ArgType temp{};
+        auto result = convertInto( arg, temp );
+        return !result
+           ? result
+           : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
+    }
+
+    template<typename L>
+    struct BoundLambda : BoundValueRefBase {
+        L m_lambda;
+
+        static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" );
+        explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {}
+
+        auto setValue( std::string const &arg ) -> ParserResult override {
+            return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>( m_lambda, arg );
+        }
+    };
+
+    template<typename L>
+    struct BoundFlagLambda : BoundFlagRefBase {
+        L m_lambda;
+
+        static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" );
+        static_assert( std::is_same<typename UnaryLambdaTraits<L>::ArgType, bool>::value, "flags must be boolean" );
+
+        explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {}
+
+        auto setFlag( bool flag ) -> ParserResult override {
+            return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( m_lambda, flag );
+        }
+    };
+
+    enum class Optionality { Optional, Required };
+
+    struct Parser;
+
+    class ParserBase {
+    public:
+        virtual ~ParserBase() = default;
+        virtual auto validate() const -> Result { return Result::ok(); }
+        virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult  = 0;
+        virtual auto cardinality() const -> size_t { return 1; }
+
+        auto parse( Args const &args ) const -> InternalParseResult {
+            return parse( args.exeName(), TokenStream( args ) );
+        }
+    };
+
+    template<typename DerivedT>
+    class ComposableParserImpl : public ParserBase {
+    public:
+        template<typename T>
+        auto operator|( T const &other ) const -> Parser;
+
+		template<typename T>
+        auto operator+( T const &other ) const -> Parser;
+    };
+
+    // Common code and state for Args and Opts
+    template<typename DerivedT>
+    class ParserRefImpl : public ComposableParserImpl<DerivedT> {
+    protected:
+        Optionality m_optionality = Optionality::Optional;
+        std::shared_ptr<BoundRef> m_ref;
+        std::string m_hint;
+        std::string m_description;
+
+        explicit ParserRefImpl( std::shared_ptr<BoundRef> const &ref ) : m_ref( ref ) {}
+
+    public:
+        template<typename T>
+        ParserRefImpl( T &ref, std::string const &hint )
+        :   m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
+            m_hint( hint )
+        {}
+
+        template<typename LambdaT>
+        ParserRefImpl( LambdaT const &ref, std::string const &hint )
+        :   m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
+            m_hint(hint)
+        {}
+
+        auto operator()( std::string const &description ) -> DerivedT & {
+            m_description = description;
+            return static_cast<DerivedT &>( *this );
+        }
+
+        auto optional() -> DerivedT & {
+            m_optionality = Optionality::Optional;
+            return static_cast<DerivedT &>( *this );
+        };
+
+        auto required() -> DerivedT & {
+            m_optionality = Optionality::Required;
+            return static_cast<DerivedT &>( *this );
+        };
+
+        auto isOptional() const -> bool {
+            return m_optionality == Optionality::Optional;
+        }
+
+        auto cardinality() const -> size_t override {
+            if( m_ref->isContainer() )
+                return 0;
+            else
+                return 1;
+        }
+
+        auto hint() const -> std::string { return m_hint; }
+    };
+
+    class ExeName : public ComposableParserImpl<ExeName> {
+        std::shared_ptr<std::string> m_name;
+        std::shared_ptr<BoundValueRefBase> m_ref;
+
+        template<typename LambdaT>
+        static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundValueRefBase> {
+            return std::make_shared<BoundLambda<LambdaT>>( lambda) ;
+        }
+
+    public:
+        ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {}
+
+        explicit ExeName( std::string &ref ) : ExeName() {
+            m_ref = std::make_shared<BoundValueRef<std::string>>( ref );
+        }
+
+        template<typename LambdaT>
+        explicit ExeName( LambdaT const& lambda ) : ExeName() {
+            m_ref = std::make_shared<BoundLambda<LambdaT>>( lambda );
+        }
+
+        // The exe name is not parsed out of the normal tokens, but is handled specially
+        auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override {
+            return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
+        }
+
+        auto name() const -> std::string { return *m_name; }
+        auto set( std::string const& newName ) -> ParserResult {
+
+            auto lastSlash = newName.find_last_of( "\\/" );
+            auto filename = ( lastSlash == std::string::npos )
+                    ? newName
+                    : newName.substr( lastSlash+1 );
+
+            *m_name = filename;
+            if( m_ref )
+                return m_ref->setValue( filename );
+            else
+                return ParserResult::ok( ParseResultType::Matched );
+        }
+    };
+
+    class Arg : public ParserRefImpl<Arg> {
+    public:
+        using ParserRefImpl::ParserRefImpl;
+
+        auto parse( std::string const &, TokenStream const &tokens ) const -> InternalParseResult override {
+            auto validationResult = validate();
+            if( !validationResult )
+                return InternalParseResult( validationResult );
+
+            auto remainingTokens = tokens;
+            auto const &token = *remainingTokens;
+            if( token.type != TokenType::Argument )
+                return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
+
+            assert( !m_ref->isFlag() );
+            auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
+
+            auto result = valueRef->setValue( remainingTokens->token );
+            if( !result )
+                return InternalParseResult( result );
+            else
+                return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
+        }
+    };
+
+    inline auto normaliseOpt( std::string const &optName ) -> std::string {
+#ifdef CATCH_PLATFORM_WINDOWS
+        if( optName[0] == '/' )
+            return "-" + optName.substr( 1 );
+        else
+#endif
+            return optName;
+    }
+
+    class Opt : public ParserRefImpl<Opt> {
+    protected:
+        std::vector<std::string> m_optNames;
+
+    public:
+        template<typename LambdaT>
+        explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shared<BoundFlagLambda<LambdaT>>( ref ) ) {}
+
+        explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared<BoundFlagRef>( ref ) ) {}
+
+        template<typename LambdaT>
+        Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {}
+
+        template<typename T>
+        Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {}
+
+        auto operator[]( std::string const &optName ) -> Opt & {
+            m_optNames.push_back( optName );
+            return *this;
+        }
+
+        auto getHelpColumns() const -> std::vector<HelpColumns> {
+            std::ostringstream oss;
+            bool first = true;
+            for( auto const &opt : m_optNames ) {
+                if (first)
+                    first = false;
+                else
+                    oss << ", ";
+                oss << opt;
+            }
+            if( !m_hint.empty() )
+                oss << " <" << m_hint << ">";
+            return { { oss.str(), m_description } };
+        }
+
+        auto isMatch( std::string const &optToken ) const -> bool {
+            auto normalisedToken = normaliseOpt( optToken );
+            for( auto const &name : m_optNames ) {
+                if( normaliseOpt( name ) == normalisedToken )
+                    return true;
+            }
+            return false;
+        }
+
+        using ParserBase::parse;
+
+        auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override {
+            auto validationResult = validate();
+            if( !validationResult )
+                return InternalParseResult( validationResult );
+
+            auto remainingTokens = tokens;
+            if( remainingTokens && remainingTokens->type == TokenType::Option ) {
+                auto const &token = *remainingTokens;
+                if( isMatch(token.token ) ) {
+                    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 {
+                        auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
+                        ++remainingTokens;
+                        if( !remainingTokens )
+                            return InternalParseResult::runtimeError( "Expected argument following " + token.token );
+                        auto const &argToken = *remainingTokens;
+                        if( argToken.type != TokenType::Argument )
+                            return InternalParseResult::runtimeError( "Expected argument following " + token.token );
+                        auto result = valueRef->setValue( argToken.token );
+                        if( !result )
+                            return InternalParseResult( result );
+                        if( result.value() == ParseResultType::ShortCircuitAll )
+                            return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
+                    }
+                    return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
+                }
+            }
+            return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
+        }
+
+        auto validate() const -> Result override {
+            if( m_optNames.empty() )
+                return Result::logicError( "No options supplied to Opt" );
+            for( auto const &name : m_optNames ) {
+                if( name.empty() )
+                    return Result::logicError( "Option name cannot be empty" );
+#ifdef CATCH_PLATFORM_WINDOWS
+                if( name[0] != '-' && name[0] != '/' )
+                    return Result::logicError( "Option name must begin with '-' or '/'" );
+#else
+                if( name[0] != '-' )
+                    return Result::logicError( "Option name must begin with '-'" );
+#endif
+            }
+            return ParserRefImpl::validate();
+        }
+    };
+
+    struct Help : Opt {
+        Help( bool &showHelpFlag )
+        :   Opt([&]( bool flag ) {
+                showHelpFlag = flag;
+                return ParserResult::ok( ParseResultType::ShortCircuitAll );
+            })
+        {
+            static_cast<Opt &>( *this )
+                    ("display usage information")
+                    ["-?"]["-h"]["--help"]
+                    .optional();
+        }
+    };
+
+    struct Parser : ParserBase {
+
+        mutable ExeName m_exeName;
+        std::vector<Opt> m_options;
+        std::vector<Arg> m_args;
+
+        auto operator|=( ExeName const &exeName ) -> Parser & {
+            m_exeName = exeName;
+            return *this;
+        }
+
+        auto operator|=( Arg const &arg ) -> Parser & {
+            m_args.push_back(arg);
+            return *this;
+        }
+
+        auto operator|=( Opt const &opt ) -> Parser & {
+            m_options.push_back(opt);
+            return *this;
+        }
+
+        auto operator|=( Parser const &other ) -> Parser & {
+            m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end());
+            m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end());
+            return *this;
+        }
+
+        template<typename T>
+        auto operator|( T const &other ) const -> Parser {
+            return Parser( *this ) |= other;
+        }
+
+        // Forward deprecated interface with '+' instead of '|'
+        template<typename T>
+        auto operator+=( T const &other ) -> Parser & { return operator|=( other ); }
+        template<typename T>
+        auto operator+( T const &other ) const -> Parser { return operator|( other ); }
+
+        auto getHelpColumns() const -> std::vector<HelpColumns> {
+            std::vector<HelpColumns> cols;
+            for (auto const &o : m_options) {
+                auto childCols = o.getHelpColumns();
+                cols.insert( cols.end(), childCols.begin(), childCols.end() );
+            }
+            return cols;
+        }
+
+        void writeToStream( std::ostream &os ) const {
+            if (!m_exeName.name().empty()) {
+                os << "usage:\n" << "  " << m_exeName.name() << " ";
+                bool required = true, first = true;
+                for( auto const &arg : m_args ) {
+                    if (first)
+                        first = false;
+                    else
+                        os << " ";
+                    if( arg.isOptional() && required ) {
+                        os << "[";
+                        required = false;
+                    }
+                    os << "<" << arg.hint() << ">";
+                    if( arg.cardinality() == 0 )
+                        os << " ... ";
+                }
+                if( !required )
+                    os << "]";
+                if( !m_options.empty() )
+                    os << " options";
+                os << "\n\nwhere options are:" << std::endl;
+            }
+
+            auto rows = getHelpColumns();
+            size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH;
+            size_t optWidth = 0;
+            for( auto const &cols : rows )
+                optWidth = (std::max)(optWidth, cols.left.size() + 2);
+
+            optWidth = (std::min)(optWidth, consoleWidth/2);
+
+            for( auto const &cols : rows ) {
+                auto row =
+                        TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +
+                        TextFlow::Spacer(4) +
+                        TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth );
+                os << row << std::endl;
+            }
+        }
+
+        friend auto operator<<( std::ostream &os, Parser const &parser ) -> std::ostream& {
+            parser.writeToStream( os );
+            return os;
+        }
+
+        auto validate() const -> Result override {
+            for( auto const &opt : m_options ) {
+                auto result = opt.validate();
+                if( !result )
+                    return result;
+            }
+            for( auto const &arg : m_args ) {
+                auto result = arg.validate();
+                if( !result )
+                    return result;
+            }
+            return Result::ok();
+        }
+
+        using ParserBase::parse;
+
+        auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override {
+
+            struct ParserInfo {
+                ParserBase const* parser = nullptr;
+                size_t count = 0;
+            };
+            const size_t totalParsers = m_options.size() + m_args.size();
+            assert( totalParsers < 512 );
+            // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do
+            ParserInfo parseInfos[512];
+
+            {
+                size_t i = 0;
+                for (auto const &opt : m_options) parseInfos[i++].parser = &opt;
+                for (auto const &arg : m_args) parseInfos[i++].parser = &arg;
+            }
+
+            m_exeName.set( exeName );
+
+            auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
+            while( result.value().remainingTokens() ) {
+                bool tokenParsed = false;
+
+                for( size_t i = 0; i < totalParsers; ++i ) {
+                    auto&  parseInfo = parseInfos[i];
+                    if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) {
+                        result = parseInfo.parser->parse(exeName, result.value().remainingTokens());
+                        if (!result)
+                            return result;
+                        if (result.value().type() != ParseResultType::NoMatch) {
+                            tokenParsed = true;
+                            ++parseInfo.count;
+                            break;
+                        }
+                    }
+                }
+
+                if( result.value().type() == ParseResultType::ShortCircuitAll )
+                    return result;
+                if( !tokenParsed )
+                    return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token );
+            }
+            // !TBD Check missing required options
+            return result;
+        }
+    };
+
+    template<typename DerivedT>
+    template<typename T>
+    auto ComposableParserImpl<DerivedT>::operator|( T const &other ) const -> Parser {
+        return Parser() | static_cast<DerivedT const &>( *this ) | other;
+    }
+} // namespace detail
+
+// A Combined parser
+using detail::Parser;
+
+// A parser for options
+using detail::Opt;
+
+// A parser for arguments
+using detail::Arg;
+
+// Wrapper for argc, argv from main()
+using detail::Args;
+
+// Specifies the name of the executable
+using detail::ExeName;
+
+// Convenience wrapper for option parser that specifies the help option
+using detail::Help;
+
+// enum of result types from a parse
+using detail::ParseResultType;
+
+// Result type for parser operation
+using detail::ParserResult;
+
+}} // namespace Catch::clara
+
+// end clara.hpp
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+// Restore Clara's value for console width, if present
+#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
+#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
+#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
+#endif
+
+// end catch_clara.h
+namespace Catch {
+
+    clara::Parser makeCommandLineParser( ConfigData& config );
+
+} // end namespace Catch
+
+// end catch_commandline.h
+#include <fstream>
+#include <ctime>
+
+namespace Catch {
+
+    clara::Parser makeCommandLineParser( ConfigData& config ) {
+
+        using namespace clara;
+
+        auto const setWarning = [&]( std::string const& warning ) {
+                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 | warningSet );
+                return ParserResult::ok( ParseResultType::Matched );
+            };
+        auto const loadTestNamesFromFile = [&]( std::string const& filename ) {
+                std::ifstream f( filename.c_str() );
+                if( !f.is_open() )
+                    return ParserResult::runtimeError( "Unable to load input file: '" + filename + "'" );
+
+                std::string line;
+                while( std::getline( f, line ) ) {
+                    line = trim(line);
+                    if( !line.empty() && !startsWith( line, '#' ) ) {
+                        if( !startsWith( line, '"' ) )
+                            line = '"' + line + '"';
+                        config.testsOrTags.push_back( line + ',' );
+                    }
+                }
+                return ParserResult::ok( ParseResultType::Matched );
+            };
+        auto const setTestOrder = [&]( std::string const& order ) {
+                if( startsWith( "declared", order ) )
+                    config.runOrder = RunTests::InDeclarationOrder;
+                else if( startsWith( "lexical", order ) )
+                    config.runOrder = RunTests::InLexicographicalOrder;
+                else if( startsWith( "random", order ) )
+                    config.runOrder = RunTests::InRandomOrder;
+                else
+                    return clara::ParserResult::runtimeError( "Unrecognised ordering: '" + order + "'" );
+                return ParserResult::ok( ParseResultType::Matched );
+            };
+        auto const setRngSeed = [&]( std::string const& seed ) {
+                if( seed != "time" )
+                    return clara::detail::convertInto( seed, config.rngSeed );
+                config.rngSeed = static_cast<unsigned int>( std::time(nullptr) );
+                return ParserResult::ok( ParseResultType::Matched );
+            };
+        auto const setColourUsage = [&]( std::string const& useColour ) {
+                    auto mode = toLower( useColour );
+
+                    if( mode == "yes" )
+                        config.useColour = UseColour::Yes;
+                    else if( mode == "no" )
+                        config.useColour = UseColour::No;
+                    else if( mode == "auto" )
+                        config.useColour = UseColour::Auto;
+                    else
+                        return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" );
+                return ParserResult::ok( ParseResultType::Matched );
+            };
+        auto const setWaitForKeypress = [&]( std::string const& keypress ) {
+                auto keypressLc = toLower( keypress );
+                if( keypressLc == "start" )
+                    config.waitForKeypress = WaitForKeypress::BeforeStart;
+                else if( keypressLc == "exit" )
+                    config.waitForKeypress = WaitForKeypress::BeforeExit;
+                else if( keypressLc == "both" )
+                    config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;
+                else
+                    return ParserResult::runtimeError( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" );
+            return ParserResult::ok( ParseResultType::Matched );
+            };
+        auto const setVerbosity = [&]( std::string const& verbosity ) {
+            auto lcVerbosity = toLower( verbosity );
+            if( lcVerbosity == "quiet" )
+                config.verbosity = Verbosity::Quiet;
+            else if( lcVerbosity == "normal" )
+                config.verbosity = Verbosity::Normal;
+            else if( lcVerbosity == "high" )
+                config.verbosity = Verbosity::High;
+            else
+                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 )
+            | Help( config.showHelp )
+            | Opt( config.listTests )
+                ["-l"]["--list-tests"]
+                ( "list all/matching test cases" )
+            | Opt( config.listTags )
+                ["-t"]["--list-tags"]
+                ( "list all/matching tags" )
+            | Opt( config.showSuccessfulTests )
+                ["-s"]["--success"]
+                ( "include successful tests in output" )
+            | Opt( config.shouldDebugBreak )
+                ["-b"]["--break"]
+                ( "break into debugger on failure" )
+            | Opt( config.noThrow )
+                ["-e"]["--nothrow"]
+                ( "skip exception tests" )
+            | Opt( config.showInvisibles )
+                ["-i"]["--invisibles"]
+                ( "show invisibles (tabs, newlines)" )
+            | Opt( config.outputFilename, "filename" )
+                ["-o"]["--out"]
+                ( "output filename" )
+            | Opt( setReporter, "name" )
+                ["-r"]["--reporter"]
+                ( "reporter to use (defaults to console)" )
+            | Opt( config.name, "name" )
+                ["-n"]["--name"]
+                ( "suite name" )
+            | Opt( [&]( bool ){ config.abortAfter = 1; } )
+                ["-a"]["--abort"]
+                ( "abort at first failure" )
+            | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" )
+                ["-x"]["--abortx"]
+                ( "abort after x failures" )
+            | Opt( setWarning, "warning name" )
+                ["-w"]["--warn"]
+                ( "enable warnings" )
+            | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" )
+                ["-d"]["--durations"]
+                ( "show test durations" )
+            | Opt( loadTestNamesFromFile, "filename" )
+                ["-f"]["--input-file"]
+                ( "load test names to run from a file" )
+            | Opt( config.filenamesAsTags )
+                ["-#"]["--filenames-as-tags"]
+                ( "adds a tag for the filename" )
+            | Opt( config.sectionsToRun, "section name" )
+                ["-c"]["--section"]
+                ( "specify section to run" )
+            | Opt( setVerbosity, "quiet|normal|high" )
+                ["-v"]["--verbosity"]
+                ( "set output verbosity" )
+            | Opt( config.listTestNamesOnly )
+                ["--list-test-names-only"]
+                ( "list all/matching test cases names only" )
+            | Opt( config.listReporters )
+                ["--list-reporters"]
+                ( "list all reporters" )
+            | Opt( setTestOrder, "decl|lex|rand" )
+                ["--order"]
+                ( "test case order (defaults to decl)" )
+            | Opt( setRngSeed, "'time'|number" )
+                ["--rng-seed"]
+                ( "set a specific seed for random numbers" )
+            | Opt( setColourUsage, "yes|no" )
+                ["--use-colour"]
+                ( "should output be colourised" )
+            | Opt( config.libIdentify )
+                ["--libidentify"]
+                ( "report name and version according to libidentify standard" )
+            | Opt( setWaitForKeypress, "start|exit|both" )
+                ["--wait-for-keypress"]
+                ( "waits for a keypress before exiting" )
+            | Opt( config.benchmarkResolutionMultiple, "multiplier" )
+                ["--benchmark-resolution-multiple"]
+                ( "multiple of clock resolution to run benchmarks" )
+
+            | Arg( config.testsOrTags, "test name|pattern|tags" )
+                ( "which test or tests to use" );
+
+        return cli;
+    }
+
+} // end namespace Catch
+// end catch_commandline.cpp
+// start catch_common.cpp
+
+#include <cstring>
+#include <ostream>
+
+namespace Catch {
+
+    bool SourceLineInfo::empty() const noexcept {
+        return file[0] == '\0';
+    }
+    bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept {
+        return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
+    }
+    bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept {
+        // 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 ) {
+#ifndef __GNUG__
+        os << info.file << '(' << info.line << ')';
+#else
+        os << info.file << ':' << info.line;
+#endif
+        return os;
+    }
+
+    std::string StreamEndStop::operator+() const {
+        return std::string();
+    }
+
+    NonCopyable::NonCopyable() = default;
+    NonCopyable::~NonCopyable() = default;
+
+}
+// end catch_common.cpp
+// start catch_config.cpp
+
+namespace Catch {
+
+    Config::Config( ConfigData const& data )
+    :   m_data( data ),
+        m_stream( openStream() )
+    {
+        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();
+    }
+
+    std::string const& Config::getFilename() const {
+        return m_data.outputFilename ;
+    }
+
+    bool Config::listTests() const          { return m_data.listTests; }
+    bool Config::listTestNamesOnly() const  { return m_data.listTestNamesOnly; }
+    bool Config::listTags() const           { return m_data.listTags; }
+    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::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; }
+
+    // IConfig interface
+    bool Config::allowThrows() const                   { return !m_data.noThrow; }
+    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::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; }
+    int Config::benchmarkResolutionMultiple() const    { return m_data.benchmarkResolutionMultiple; }
+    UseColour::YesOrNo Config::useColour() const       { return m_data.useColour; }
+    bool Config::shouldDebugBreak() const              { return m_data.shouldDebugBreak; }
+    int Config::abortAfter() const                     { return m_data.abortAfter; }
+    bool Config::showInvisibles() const                { return m_data.showInvisibles; }
+    Verbosity Config::verbosity() const                { return m_data.verbosity; }
+
+    IStream const* Config::openStream() {
+        return Catch::makeStream(m_data.outputFilename);
+    }
+
+} // end namespace Catch
+// end catch_config.cpp
+// start catch_console_colour.cpp
+
+#if defined(__clang__)
+#    pragma clang diagnostic push
+#    pragma clang diagnostic ignored "-Wexit-time-destructors"
+#endif
+
+// start catch_errno_guard.h
+
+namespace Catch {
+
+    class ErrnoGuard {
+    public:
+        ErrnoGuard();
+        ~ErrnoGuard();
+    private:
+        int m_oldErrno;
+    };
+
+}
+
+// end catch_errno_guard.h
+#include <sstream>
+
+namespace Catch {
+    namespace {
+
+        struct IColourImpl {
+            virtual ~IColourImpl() = default;
+            virtual void use( Colour::Code _colourCode ) = 0;
+        };
+
+        struct NoColourImpl : IColourImpl {
+            void use( Colour::Code ) {}
+
+            static IColourImpl* instance() {
+                static NoColourImpl s_instance;
+                return &s_instance;
+            }
+        };
+
+    } // anon namespace
+} // namespace Catch
+
+#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
+#   ifdef CATCH_PLATFORM_WINDOWS
+#       define CATCH_CONFIG_COLOUR_WINDOWS
+#   else
+#       define CATCH_CONFIG_COLOUR_ANSI
+#   endif
+#endif
+
+#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
+
+namespace Catch {
+namespace {
+
+    class Win32ColourImpl : public IColourImpl {
+    public:
+        Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
+        {
+            CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
+            GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
+            originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
+            originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
+        }
+
+        virtual void use( Colour::Code _colourCode ) override {
+            switch( _colourCode ) {
+                case Colour::None:      return setTextAttribute( originalForegroundAttributes );
+                case Colour::White:     return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
+                case Colour::Red:       return setTextAttribute( FOREGROUND_RED );
+                case Colour::Green:     return setTextAttribute( FOREGROUND_GREEN );
+                case Colour::Blue:      return setTextAttribute( FOREGROUND_BLUE );
+                case Colour::Cyan:      return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
+                case Colour::Yellow:    return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
+                case Colour::Grey:      return setTextAttribute( 0 );
+
+                case Colour::LightGrey:     return setTextAttribute( FOREGROUND_INTENSITY );
+                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" );
+            }
+        }
+
+    private:
+        void setTextAttribute( WORD _textAttribute ) {
+            SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
+        }
+        HANDLE stdoutHandle;
+        WORD originalForegroundAttributes;
+        WORD originalBackgroundAttributes;
+    };
+
+    IColourImpl* platformColourInstance() {
+        static Win32ColourImpl s_instance;
+
+        IConfigPtr config = getCurrentContext().getConfig();
+        UseColour::YesOrNo colourMode = config
+            ? config->useColour()
+            : UseColour::Auto;
+        if( colourMode == UseColour::Auto )
+            colourMode = UseColour::Yes;
+        return colourMode == UseColour::Yes
+            ? &s_instance
+            : NoColourImpl::instance();
+    }
+
+} // end anon namespace
+} // end namespace Catch
+
+#elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
+
+#include <unistd.h>
+
+namespace Catch {
+namespace {
+
+    // use POSIX/ ANSI console terminal codes
+    // Thanks to Adam Strzelecki for original contribution
+    // (http://github.com/nanoant)
+    // https://github.com/philsquared/Catch/pull/131
+    class PosixColourImpl : public IColourImpl {
+    public:
+        virtual void use( Colour::Code _colourCode ) override {
+            switch( _colourCode ) {
+                case Colour::None:
+                case Colour::White:     return setColour( "[0m" );
+                case Colour::Red:       return setColour( "[0;31m" );
+                case Colour::Green:     return setColour( "[0;32m" );
+                case Colour::Blue:      return setColour( "[0;34m" );
+                case Colour::Cyan:      return setColour( "[0;36m" );
+                case Colour::Yellow:    return setColour( "[0;33m" );
+                case Colour::Grey:      return setColour( "[1;30m" );
+
+                case Colour::LightGrey:     return setColour( "[0;37m" );
+                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() {
+            static PosixColourImpl s_instance;
+            return &s_instance;
+        }
+
+    private:
+        void setColour( const char* _escapeCode ) {
+            Catch::cout() << '\033' << _escapeCode;
+        }
+    };
+
+    bool useColourOnPlatform() {
+        return
+#ifdef CATCH_PLATFORM_MAC
+            !isDebuggerActive() &&
+#endif
+#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
+            isatty(STDOUT_FILENO)
+#else
+            false
+#endif
+            ;
+    }
+    IColourImpl* platformColourInstance() {
+        ErrnoGuard guard;
+        IConfigPtr config = getCurrentContext().getConfig();
+        UseColour::YesOrNo colourMode = config
+            ? config->useColour()
+            : UseColour::Auto;
+        if( colourMode == UseColour::Auto )
+            colourMode = useColourOnPlatform()
+                ? UseColour::Yes
+                : UseColour::No;
+        return colourMode == UseColour::Yes
+            ? PosixColourImpl::instance()
+            : NoColourImpl::instance();
+    }
+
+} // end anon namespace
+} // end namespace Catch
+
+#else  // not Windows or ANSI ///////////////////////////////////////////////
+
+namespace Catch {
+
+    static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
+
+} // end namespace Catch
+
+#endif // Windows/ ANSI/ None
+
+namespace Catch {
+
+    Colour::Colour( Code _colourCode ) { use( _colourCode ); }
+    Colour::Colour( Colour&& rhs ) noexcept {
+        m_moved = rhs.m_moved;
+        rhs.m_moved = true;
+    }
+    Colour& Colour::operator=( Colour&& rhs ) noexcept {
+        m_moved = rhs.m_moved;
+        rhs.m_moved  = true;
+        return *this;
+    }
+
+    Colour::~Colour(){ if( !m_moved ) use( None ); }
+
+    void Colour::use( Code _colourCode ) {
+        static IColourImpl* impl = platformColourInstance();
+        impl->use( _colourCode );
+    }
+
+    std::ostream& operator << ( std::ostream& os, Colour const& ) {
+        return os;
+    }
+
+} // end namespace Catch
+
+#if defined(__clang__)
+#    pragma clang diagnostic pop
+#endif
+
+// end catch_console_colour.cpp
+// start catch_context.cpp
+
+namespace Catch {
+
+    class Context : public IMutableContext, NonCopyable {
+
+    public: // IContext
+        virtual IResultCapture* getResultCapture() override {
+            return m_resultCapture;
+        }
+        virtual IRunner* getRunner() override {
+            return m_runner;
+        }
+
+        virtual IConfigPtr const& getConfig() const override {
+            return m_config;
+        }
+
+        virtual ~Context() override;
+
+    public: // IMutableContext
+        virtual void setResultCapture( IResultCapture* resultCapture ) override {
+            m_resultCapture = resultCapture;
+        }
+        virtual void setRunner( IRunner* runner ) override {
+            m_runner = runner;
+        }
+        virtual void setConfig( IConfigPtr const& config ) override {
+            m_config = config;
+        }
+
+        friend IMutableContext& getCurrentMutableContext();
+
+    private:
+        IConfigPtr m_config;
+        IRunner* m_runner = nullptr;
+        IResultCapture* m_resultCapture = nullptr;
+    };
+
+    IMutableContext *IMutableContext::currentContext = nullptr;
+
+    void IMutableContext::createContext()
+    {
+        currentContext = new Context();
+    }
+
+    void cleanUpContext() {
+        delete IMutableContext::currentContext;
+        IMutableContext::currentContext = nullptr;
+    }
+    IContext::~IContext() = default;
+    IMutableContext::~IMutableContext() = default;
+    Context::~Context() = default;
+}
+// end catch_context.cpp
+// start catch_debug_console.cpp
+
+// start catch_debug_console.h
+
+#include <string>
+
+namespace Catch {
+    void writeToDebugConsole( std::string const& text );
+}
+
+// end catch_debug_console.h
+#ifdef CATCH_PLATFORM_WINDOWS
+
+    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
+// end catch_debug_console.cpp
+// start catch_debugger.cpp
+
+#ifdef CATCH_PLATFORM_MAC
+
+#  include <assert.h>
+#  include <stdbool.h>
+#  include <sys/types.h>
+#  include <unistd.h>
+#  include <sys/sysctl.h>
+#  include <cstddef>
+#  include <ostream>
+
+namespace Catch {
+
+        // The following function is taken directly from the following technical note:
+        // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
+
+        // Returns true if the current process is being debugged (either
+        // running under the debugger or has a debugger attached post facto).
+        bool isDebuggerActive(){
+
+            int                 mib[4];
+            struct kinfo_proc   info;
+            std::size_t         size;
+
+            // Initialize the flags so that, if sysctl fails for some bizarre
+            // reason, we get a predictable result.
+
+            info.kp_proc.p_flag = 0;
+
+            // Initialize mib, which tells sysctl the info we want, in this case
+            // we're looking for information about a specific process ID.
+
+            mib[0] = CTL_KERN;
+            mib[1] = KERN_PROC;
+            mib[2] = KERN_PROC_PID;
+            mib[3] = getpid();
+
+            // Call sysctl.
+
+            size = sizeof(info);
+            if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0 ) {
+                Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
+                return false;
+            }
+
+            // We're being debugged if the P_TRACED flag is set.
+
+            return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
+        }
+    } // namespace Catch
+
+#elif defined(CATCH_PLATFORM_LINUX)
+    #include <fstream>
+    #include <string>
+
+    namespace Catch{
+        // The standard POSIX way of detecting a debugger is to attempt to
+        // ptrace() the process, but this needs to be done from a child and not
+        // this process itself to still allow attaching to this process later
+        // if wanted, so is rather heavy. Under Linux we have the PID of the
+        // "debugger" (which doesn't need to be gdb, of course, it could also
+        // be strace, for example) in /proc/$PID/status, so just get it from
+        // there instead.
+        bool isDebuggerActive(){
+            // Libstdc++ has a bug, where std::ifstream sets errno to 0
+            // This way our users can properly assert over errno values
+            ErrnoGuard guard;
+            std::ifstream in("/proc/self/status");
+            for( std::string line; std::getline(in, line); ) {
+                static const int PREFIX_LEN = 11;
+                if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) {
+                    // We're traced if the PID is not 0 and no other PID starts
+                    // with 0 digit, so it's enough to check for just a single
+                    // character.
+                    return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
+                }
+            }
+
+            return false;
+        }
+    } // namespace Catch
+#elif defined(_MSC_VER)
+    extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
+    namespace Catch {
+        bool isDebuggerActive() {
+            return IsDebuggerPresent() != 0;
+        }
+    }
+#elif defined(__MINGW32__)
+    extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
+    namespace Catch {
+        bool isDebuggerActive() {
+            return IsDebuggerPresent() != 0;
+        }
+    }
+#else
+    namespace Catch {
+       bool isDebuggerActive() { return false; }
+    }
+#endif // Platform
+// end catch_debugger.cpp
+// start catch_decomposer.cpp
+
+namespace Catch {
+
+    ITransientExpression::~ITransientExpression() = default;
+
+    void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) {
+        if( lhs.size() + rhs.size() < 40 &&
+                lhs.find('\n') == std::string::npos &&
+                rhs.find('\n') == std::string::npos )
+            os << lhs << " " << op << " " << rhs;
+        else
+            os << lhs << "\n" << op << "\n" << rhs;
+    }
+}
+// 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>
+
+namespace Catch {
+        ErrnoGuard::ErrnoGuard():m_oldErrno(errno){}
+        ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; }
+}
+// end catch_errno_guard.cpp
+// start catch_exception_translator_registry.cpp
+
+// start catch_exception_translator_registry.h
+
+#include <vector>
+#include <string>
+#include <memory>
+
+namespace Catch {
+
+    class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
+    public:
+        ~ExceptionTranslatorRegistry();
+        virtual void registerTranslator( const IExceptionTranslator* translator );
+        virtual std::string translateActiveException() const override;
+        std::string tryTranslators() const;
+
+    private:
+        std::vector<std::unique_ptr<IExceptionTranslator const>> m_translators;
+    };
+}
+
+// end catch_exception_translator_registry.h
+#ifdef __OBJC__
+#import "Foundation/Foundation.h"
+#endif
+
+namespace Catch {
+
+    ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() {
+    }
+
+    void ExceptionTranslatorRegistry::registerTranslator( const IExceptionTranslator* translator ) {
+        m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) );
+    }
+
+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
+    std::string ExceptionTranslatorRegistry::translateActiveException() const {
+        try {
+#ifdef __OBJC__
+            // In Objective-C try objective-c exceptions first
+            @try {
+                return tryTranslators();
+            }
+            @catch (NSException *exception) {
+                return Catch::Detail::stringify( [exception description] );
+            }
+#else
+            // Compiling a mixed mode project with MSVC means that CLR
+            // exceptions will be caught in (...) as well. However, these
+            // do not fill-in std::current_exception and thus lead to crash
+            // when attempting rethrow.
+            // /EHa switch also causes structured exceptions to be caught
+            // here, but they fill-in current_exception properly, so
+            // at worst the output should be a little weird, instead of
+            // causing a crash.
+            if (std::current_exception() == nullptr) {
+                return "Non C++ exception. Possibly a CLR exception.";
+            }
+            return tryTranslators();
+#endif
+        }
+        catch( TestFailureException& ) {
+            std::rethrow_exception(std::current_exception());
+        }
+        catch( std::exception& ex ) {
+            return ex.what();
+        }
+        catch( std::string& msg ) {
+            return msg;
+        }
+        catch( const char* msg ) {
+            return msg;
+        }
+        catch(...) {
+            return "Unknown exception";
+        }
+    }
+
+#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!");
+    }
+#endif
+
+    std::string ExceptionTranslatorRegistry::tryTranslators() const {
+        if( m_translators.empty() )
+            std::rethrow_exception(std::current_exception());
+        else
+            return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
+    }
+}
+// end catch_exception_translator_registry.cpp
+// start catch_fatal_condition.cpp
+
+#if defined(__GNUC__)
+#    pragma GCC diagnostic push
+#    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 ) {
+        Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
+    }
+}
+
+#endif // signals/SEH handling
+
+#if defined( CATCH_CONFIG_WINDOWS_SEH )
+
+namespace Catch {
+    struct SignalDefs { DWORD id; const char* name; };
+
+    // There is no 1-1 mapping between signals and windows exceptions.
+    // Windows can easily distinguish between SO and SigSegV,
+    // but SigInt, SigTerm, etc are handled differently.
+    static SignalDefs signalDefs[] = {
+        { EXCEPTION_ILLEGAL_INSTRUCTION,  "SIGILL - Illegal instruction signal" },
+        { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
+        { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
+        { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
+    };
+
+    LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
+        for (auto const& def : signalDefs) {
+            if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
+                reportFatal(def.name);
+            }
+        }
+        // If its not an exception we care about, pass it along.
+        // This stops us from eating debugger breaks etc.
+        return EXCEPTION_CONTINUE_SEARCH;
+    }
+
+    FatalConditionHandler::FatalConditionHandler() {
+        isSet = true;
+        // 32k seems enough for Catch to handle stack overflow,
+        // but the value was found experimentally, so there is no strong guarantee
+        guaranteeSize = 32 * 1024;
+        exceptionHandlerHandle = nullptr;
+        // Register as first handler in current chain
+        exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
+        // Pass in guarantee size to be filled
+        SetThreadStackGuarantee(&guaranteeSize);
+    }
+
+    void FatalConditionHandler::reset() {
+        if (isSet) {
+            RemoveVectoredExceptionHandler(exceptionHandlerHandle);
+            SetThreadStackGuarantee(&guaranteeSize);
+            exceptionHandlerHandle = nullptr;
+            isSet = false;
+        }
+    }
+
+    FatalConditionHandler::~FatalConditionHandler() {
+        reset();
+    }
+
+bool FatalConditionHandler::isSet = false;
+ULONG FatalConditionHandler::guaranteeSize = 0;
+PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr;
+
+} // namespace Catch
+
+#elif defined( CATCH_CONFIG_POSIX_SIGNALS )
+
+namespace Catch {
+
+    struct SignalDefs {
+        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" },
+        { SIGFPE,  "SIGFPE - Floating point error signal" },
+        { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
+        { SIGTERM, "SIGTERM - Termination request signal" },
+        { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
+    };
+
+    void FatalConditionHandler::handleSignal( int sig ) {
+        char const * name = "<unknown signal>";
+        for (auto const& def : signalDefs) {
+            if (sig == def.id) {
+                name = def.name;
+                break;
+            }
+        }
+        reset();
+        reportFatal(name);
+        raise( sig );
+    }
+
+    FatalConditionHandler::FatalConditionHandler() {
+        isSet = true;
+        stack_t sigStack;
+        sigStack.ss_sp = altStackMem;
+        sigStack.ss_size = sigStackSize;
+        sigStack.ss_flags = 0;
+        sigaltstack(&sigStack, &oldSigStack);
+        struct sigaction sa = { };
+
+        sa.sa_handler = handleSignal;
+        sa.sa_flags = SA_ONSTACK;
+        for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {
+            sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
+        }
+    }
+
+    FatalConditionHandler::~FatalConditionHandler() {
+        reset();
+    }
+
+    void FatalConditionHandler::reset() {
+        if( isSet ) {
+            // Set signals back to previous values -- hopefully nobody overwrote them in the meantime
+            for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
+                sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
+            }
+            // Return the old stack
+            sigaltstack(&oldSigStack, nullptr);
+            isSet = false;
+        }
+    }
+
+    bool FatalConditionHandler::isSet = false;
+    struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
+    stack_t FatalConditionHandler::oldSigStack = {};
+    char FatalConditionHandler::altStackMem[sigStackSize] = {};
+
+} // namespace Catch
+
+#else
+
+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() {}
+
+namespace Generators {
+
+    GeneratorBase::~GeneratorBase() {}
+
+    std::vector<size_t> randomiseIndices( size_t selectionSize, size_t sourceSize ) {
+
+        assert( selectionSize <= sourceSize );
+        std::vector<size_t> indices;
+        indices.reserve( selectionSize );
+        std::uniform_int_distribution<size_t> uid( 0, sourceSize-1 );
+
+        std::set<size_t> seen;
+        // !TBD: improve this algorithm
+        while( indices.size() < selectionSize ) {
+            auto index = uid( rng() );
+            if( seen.insert( index ).second )
+                indices.push_back( index );
+        }
+        return indices;
+    }
+
+    auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
+        return getResultCapture().acquireGeneratorTracker( lineInfo );
+    }
+
+    template<>
+    auto all<int>() -> Generator<int> {
+        return range( std::numeric_limits<int>::min(), std::numeric_limits<int>::max() );
+    }
+
+} // namespace Generators
+} // namespace Catch
+// end catch_generators.cpp
+// start catch_interfaces_capture.cpp
+
+namespace Catch {
+    IResultCapture::~IResultCapture() = default;
+}
+// end catch_interfaces_capture.cpp
+// start catch_interfaces_config.cpp
+
+namespace Catch {
+    IConfig::~IConfig() = default;
+}
+// end catch_interfaces_config.cpp
+// start catch_interfaces_exception.cpp
+
+namespace Catch {
+    IExceptionTranslator::~IExceptionTranslator() = default;
+    IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default;
+}
+// end catch_interfaces_exception.cpp
+// start catch_interfaces_registry_hub.cpp
+
+namespace Catch {
+    IRegistryHub::~IRegistryHub() = default;
+    IMutableRegistryHub::~IMutableRegistryHub() = default;
+}
+// end catch_interfaces_registry_hub.cpp
+// start catch_interfaces_reporter.cpp
+
+// start catch_reporter_listening.h
+
+namespace Catch {
+
+    class ListeningReporter : public IStreamingReporter {
+        using Reporters = std::vector<IStreamingReporterPtr>;
+        Reporters m_listeners;
+        IStreamingReporterPtr m_reporter = nullptr;
+        ReporterPreferences m_preferences;
+
+    public:
+        ListeningReporter();
+
+        void addListener( IStreamingReporterPtr&& listener );
+        void addReporter( IStreamingReporterPtr&& reporter );
+
+    public: // IStreamingReporter
+
+        ReporterPreferences getPreferences() const override;
+
+        void noMatchingTestCases( std::string const& spec ) override;
+
+        static std::set<Verbosity> getSupportedVerbosities();
+
+        void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override;
+        void benchmarkEnded( BenchmarkStats const& benchmarkStats ) override;
+
+        void testRunStarting( TestRunInfo const& testRunInfo ) override;
+        void testGroupStarting( GroupInfo const& groupInfo ) override;
+        void testCaseStarting( TestCaseInfo const& testInfo ) override;
+        void sectionStarting( SectionInfo const& sectionInfo ) override;
+        void assertionStarting( AssertionInfo const& assertionInfo ) override;
+
+        // The return value indicates if the messages buffer should be cleared:
+        bool assertionEnded( AssertionStats const& assertionStats ) override;
+        void sectionEnded( SectionStats const& sectionStats ) override;
+        void testCaseEnded( TestCaseStats const& testCaseStats ) override;
+        void testGroupEnded( TestGroupStats const& testGroupStats ) override;
+        void testRunEnded( TestRunStats const& testRunStats ) override;
+
+        void skipTest( TestCaseInfo const& testInfo ) override;
+        bool isMulti() const override;
+
+    };
+
+} // end namespace Catch
+
+// end catch_reporter_listening.h
+namespace Catch {
+
+    ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig )
+    :   m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
+
+    ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream )
+    :   m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
+
+    std::ostream& ReporterConfig::stream() const { return *m_stream; }
+    IConfigPtr ReporterConfig::fullConfig() const { return m_fullConfig; }
+
+    TestRunInfo::TestRunInfo( std::string const& _name ) : name( _name ) {}
+
+    GroupInfo::GroupInfo(  std::string const& _name,
+                           std::size_t _groupIndex,
+                           std::size_t _groupsCount )
+    :   name( _name ),
+        groupIndex( _groupIndex ),
+        groupsCounts( _groupsCount )
+    {}
+
+     AssertionStats::AssertionStats( AssertionResult const& _assertionResult,
+                                     std::vector<MessageInfo> const& _infoMessages,
+                                     Totals const& _totals )
+    :   assertionResult( _assertionResult ),
+        infoMessages( _infoMessages ),
+        totals( _totals )
+    {
+        assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression;
+
+        if( assertionResult.hasMessage() ) {
+            // Copy message into messages list.
+            // !TBD This should have been done earlier, somewhere
+            MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
+            builder << assertionResult.getMessage();
+            builder.m_info.message = builder.m_stream.str();
+
+            infoMessages.push_back( builder.m_info );
+        }
+    }
+
+     AssertionStats::~AssertionStats() = default;
+
+    SectionStats::SectionStats(  SectionInfo const& _sectionInfo,
+                                 Counts const& _assertions,
+                                 double _durationInSeconds,
+                                 bool _missingAssertions )
+    :   sectionInfo( _sectionInfo ),
+        assertions( _assertions ),
+        durationInSeconds( _durationInSeconds ),
+        missingAssertions( _missingAssertions )
+    {}
+
+    SectionStats::~SectionStats() = default;
+
+    TestCaseStats::TestCaseStats(  TestCaseInfo const& _testInfo,
+                                   Totals const& _totals,
+                                   std::string const& _stdOut,
+                                   std::string const& _stdErr,
+                                   bool _aborting )
+    : testInfo( _testInfo ),
+        totals( _totals ),
+        stdOut( _stdOut ),
+        stdErr( _stdErr ),
+        aborting( _aborting )
+    {}
+
+    TestCaseStats::~TestCaseStats() = default;
+
+    TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo,
+                                    Totals const& _totals,
+                                    bool _aborting )
+    :   groupInfo( _groupInfo ),
+        totals( _totals ),
+        aborting( _aborting )
+    {}
+
+    TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo )
+    :   groupInfo( _groupInfo ),
+        aborting( false )
+    {}
+
+    TestGroupStats::~TestGroupStats() = default;
+
+    TestRunStats::TestRunStats(   TestRunInfo const& _runInfo,
+                    Totals const& _totals,
+                    bool _aborting )
+    :   runInfo( _runInfo ),
+        totals( _totals ),
+        aborting( _aborting )
+    {}
+
+    TestRunStats::~TestRunStats() = default;
+
+    void IStreamingReporter::fatalErrorEncountered( StringRef ) {}
+    bool IStreamingReporter::isMulti() const { return false; }
+
+    IReporterFactory::~IReporterFactory() = default;
+    IReporterRegistry::~IReporterRegistry() = default;
+
+} // end namespace Catch
+// end catch_interfaces_reporter.cpp
+// start catch_interfaces_runner.cpp
+
+namespace Catch {
+    IRunner::~IRunner() = default;
+}
+// end catch_interfaces_runner.cpp
+// start catch_interfaces_testcase.cpp
+
+namespace Catch {
+    ITestInvoker::~ITestInvoker() = default;
+    ITestCaseRegistry::~ITestCaseRegistry() = default;
+}
+// end catch_interfaces_testcase.cpp
+// start catch_leak_detector.cpp
+
+#ifdef CATCH_CONFIG_WINDOWS_CRTDBG
+#include <crtdbg.h>
+
+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);
+    }
+}
+
+#else
+
+    Catch::LeakDetector::LeakDetector() {}
+
+#endif
+
+Catch::LeakDetector::~LeakDetector() {
+    Catch::cleanUp();
+}
+// end catch_leak_detector.cpp
+// start catch_list.cpp
+
+// start catch_list.h
+
+#include <set>
+
+namespace Catch {
+
+    std::size_t listTests( Config const& config );
+
+    std::size_t listTestsNamesOnly( Config const& config );
+
+    struct TagInfo {
+        void add( std::string const& spelling );
+        std::string all() const;
+
+        std::set<std::string> spellings;
+        std::size_t count = 0;
+    };
+
+    std::size_t listTags( Config const& config );
+
+    std::size_t listReporters();
+
+    Option<std::size_t> list( Config const& config );
+
+} // end namespace Catch
+
+// end catch_list.h
+// start catch_text.h
+
+namespace Catch {
+    using namespace clara::TextFlow;
+}
+
+// end catch_text.h
+#include <limits>
+#include <algorithm>
+#include <iomanip>
+
+namespace Catch {
+
+    std::size_t listTests( Config const& config ) {
+        TestSpec testSpec = config.testSpec();
+        if( config.hasTestFilters() )
+            Catch::cout() << "Matching test cases:\n";
+        else {
+            Catch::cout() << "All available test cases:\n";
+        }
+
+        auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
+        for( auto const& testCaseInfo : matchedTestCases ) {
+            Colour::Code colour = testCaseInfo.isHidden()
+                ? Colour::SecondaryText
+                : Colour::None;
+            Colour colourGuard( colour );
+
+            Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << "\n";
+            if( config.verbosity() >= Verbosity::High ) {
+                Catch::cout() << Column( Catch::Detail::stringify( testCaseInfo.lineInfo ) ).indent(4) << std::endl;
+                std::string description = testCaseInfo.description;
+                if( description.empty() )
+                    description = "(NO DESCRIPTION)";
+                Catch::cout() << Column( description ).indent(4) << std::endl;
+            }
+            if( !testCaseInfo.tags.empty() )
+                Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n";
+        }
+
+        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;
+        return matchedTestCases.size();
+    }
+
+    std::size_t listTestsNamesOnly( Config const& config ) {
+        TestSpec testSpec = config.testSpec();
+        std::size_t matchedTests = 0;
+        std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
+        for( auto const& testCaseInfo : matchedTestCases ) {
+            matchedTests++;
+            if( startsWith( testCaseInfo.name, '#' ) )
+               Catch::cout() << '"' << testCaseInfo.name << '"';
+            else
+               Catch::cout() << testCaseInfo.name;
+            if ( config.verbosity() >= Verbosity::High )
+                Catch::cout() << "\t@" << testCaseInfo.lineInfo;
+            Catch::cout() << std::endl;
+        }
+        return matchedTests;
+    }
+
+    void TagInfo::add( std::string const& spelling ) {
+        ++count;
+        spellings.insert( spelling );
+    }
+
+    std::string TagInfo::all() const {
+        std::string out;
+        for( auto const& spelling : spellings )
+            out += "[" + spelling + "]";
+        return out;
+    }
+
+    std::size_t listTags( Config const& config ) {
+        TestSpec testSpec = config.testSpec();
+        if( config.hasTestFilters() )
+            Catch::cout() << "Tags for matching test cases:\n";
+        else {
+            Catch::cout() << "All available tags:\n";
+        }
+
+        std::map<std::string, TagInfo> tagCounts;
+
+        std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
+        for( auto const& testCase : matchedTestCases ) {
+            for( auto const& tagName : testCase.getTestCaseInfo().tags ) {
+                std::string lcaseTagName = toLower( tagName );
+                auto countIt = tagCounts.find( lcaseTagName );
+                if( countIt == tagCounts.end() )
+                    countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
+                countIt->second.add( tagName );
+            }
+        }
+
+        for( auto const& tagCount : tagCounts ) {
+            ReusableStringStream rss;
+            rss << "  " << std::setw(2) << tagCount.second.count << "  ";
+            auto str = rss.str();
+            auto wrapper = Column( tagCount.second.all() )
+                                                    .initialIndent( 0 )
+                                                    .indent( str.size() )
+                                                    .width( CATCH_CONFIG_CONSOLE_WIDTH-10 );
+            Catch::cout() << str << wrapper << '\n';
+        }
+        Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl;
+        return tagCounts.size();
+    }
+
+    std::size_t listReporters() {
+        Catch::cout() << "Available reporters:\n";
+        IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
+        std::size_t maxNameLen = 0;
+        for( auto const& factoryKvp : factories )
+            maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() );
+
+        for( auto const& factoryKvp : factories ) {
+            Catch::cout()
+                    << Column( factoryKvp.first + ":" )
+                            .indent(2)
+                            .width( 5+maxNameLen )
+                    +  Column( factoryKvp.second->getDescription() )
+                            .initialIndent(0)
+                            .indent(2)
+                            .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 )
+                    << "\n";
+        }
+        Catch::cout() << std::endl;
+        return factories.size();
+    }
+
+    Option<std::size_t> list( 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();
+        return listedCount;
+    }
+
+} // end namespace Catch
+// end catch_list.cpp
+// start catch_matchers.cpp
+
+namespace Catch {
+namespace Matchers {
+    namespace Impl {
+
+        std::string MatcherUntypedBase::toString() const {
+            if( m_cachedToString.empty() )
+                m_cachedToString = describe();
+            return m_cachedToString;
+        }
+
+        MatcherUntypedBase::~MatcherUntypedBase() = default;
+
+    } // namespace Impl
+} // namespace Matchers
+
+using namespace Matchers;
+using Matchers::Impl::MatcherBase;
+
+} // namespace Catch
+// 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>
+
+namespace Catch {
+namespace Matchers {
+namespace Floating {
+enum class FloatingPointKind : uint8_t {
+    Float,
+    Double
+};
+}
+}
+}
+
+namespace {
+
+template <typename T>
+struct Converter;
+
+template <>
+struct Converter<float> {
+    static_assert(sizeof(float) == sizeof(int32_t), "Important ULP matcher assumption violated");
+    Converter(float f) {
+        std::memcpy(&i, &f, sizeof(f));
+    }
+    int32_t i;
+};
+
+template <>
+struct Converter<double> {
+    static_assert(sizeof(double) == sizeof(int64_t), "Important ULP matcher assumption violated");
+    Converter(double d) {
+        std::memcpy(&i, &d, sizeof(d));
+    }
+    int64_t i;
+};
+
+template <typename T>
+auto convert(T t) -> Converter<T> {
+    return Converter<T>(t);
+}
+
+template <typename FP>
+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 (Catch::isnan(lhs) || Catch::isnan(rhs)) {
+        return false;
+    }
+
+    auto lc = convert(lhs);
+    auto rc = convert(rhs);
+
+    if ((lc.i < 0) != (rc.i < 0)) {
+        // Potentially we can have +0 and -0
+        return lhs == rhs;
+    }
+
+    auto ulpDiff = std::abs(lc.i - rc.i);
+    return ulpDiff <= maxUlpDiff;
+}
+
+}
+
+namespace Catch {
+namespace Matchers {
+namespace Floating {
+    WithinAbsMatcher::WithinAbsMatcher(double target, double margin)
+        :m_target{ target }, m_margin{ margin } {
+        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 >= matchee);
+    }
+
+    std::string WithinAbsMatcher::describe() const {
+        return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target);
+    }
+
+    WithinUlpsMatcher::WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType)
+        :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
+        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:
+            return almostEqualUlps<float>(static_cast<float>(matchee), static_cast<float>(m_target), m_ulps);
+        case FloatingPointKind::Double:
+            return almostEqualUlps<double>(matchee, m_target, m_ulps);
+        default:
+            CATCH_INTERNAL_ERROR( "Unknown FloatingPointKind value" );
+        }
+    }
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
+    std::string WithinUlpsMatcher::describe() const {
+        return "is within " + Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : "");
+    }
+
+}// namespace Floating
+
+Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff) {
+    return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double);
+}
+
+Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff) {
+    return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float);
+}
+
+Floating::WithinAbsMatcher WithinAbs(double target, double margin) {
+    return Floating::WithinAbsMatcher(target, margin);
+}
+
+} // namespace Matchers
+} // 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>
+
+namespace Catch {
+namespace Matchers {
+
+    namespace StdString {
+
+        CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )
+        :   m_caseSensitivity( caseSensitivity ),
+            m_str( adjustString( str ) )
+        {}
+        std::string CasedString::adjustString( std::string const& str ) const {
+            return m_caseSensitivity == CaseSensitive::No
+                   ? toLower( str )
+                   : str;
+        }
+        std::string CasedString::caseSensitivitySuffix() const {
+            return m_caseSensitivity == CaseSensitive::No
+                   ? " (case insensitive)"
+                   : std::string();
+        }
+
+        StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator )
+        : m_comparator( comparator ),
+          m_operation( operation ) {
+        }
+
+        std::string StringMatcherBase::describe() const {
+            std::string description;
+            description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +
+                                        m_comparator.caseSensitivitySuffix().size());
+            description += m_operation;
+            description += ": \"";
+            description += m_comparator.m_str;
+            description += "\"";
+            description += m_comparator.caseSensitivitySuffix();
+            return description;
+        }
+
+        EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {}
+
+        bool EqualsMatcher::match( std::string const& source ) const {
+            return m_comparator.adjustString( source ) == m_comparator.m_str;
+        }
+
+        ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {}
+
+        bool ContainsMatcher::match( std::string const& source ) const {
+            return contains( m_comparator.adjustString( source ), m_comparator.m_str );
+        }
+
+        StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {}
+
+        bool StartsWithMatcher::match( std::string const& source ) const {
+            return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );
+        }
+
+        EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {}
+
+        bool EndsWithMatcher::match( std::string const& source ) const {
+            return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );
+        }
+
+        RegexMatcher::RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity): m_regex(std::move(regex)), m_caseSensitivity(caseSensitivity) {}
+
+        bool RegexMatcher::match(std::string const& matchee) const {
+            auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax option anyway
+            if (m_caseSensitivity == CaseSensitive::Choice::No) {
+                flags |= std::regex::icase;
+            }
+            auto reg = std::regex(m_regex, flags);
+            return std::regex_match(matchee, reg);
+        }
+
+        std::string RegexMatcher::describe() const {
+            return "matches " + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Choice::Yes)? " case sensitively" : " case insensitively");
+        }
+
+    } // namespace StdString
+
+    StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
+        return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) );
+    }
+    StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
+        return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) );
+    }
+    StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
+        return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) );
+    }
+    StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
+        return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) );
+    }
+
+    StdString::RegexMatcher Matches(std::string const& regex, CaseSensitive::Choice caseSensitivity) {
+        return StdString::RegexMatcher(regex, caseSensitivity);
+    }
+
+} // namespace Matchers
+} // namespace Catch
+// 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(   StringRef const& _macroName,
+                                SourceLineInfo const& _lineInfo,
+                                ResultWas::OfType _type )
+    :   macroName( _macroName ),
+        lineInfo( _lineInfo ),
+        type( _type ),
+        sequence( ++globalCount )
+    {}
+
+    bool MessageInfo::operator==( MessageInfo const& other ) const {
+        return sequence == other.sequence;
+    }
+
+    bool MessageInfo::operator<( MessageInfo const& other ) const {
+        return sequence < other.sequence;
+    }
+
+    // This may need protecting if threading support is added
+    unsigned int MessageInfo::globalCount = 0;
+
+    ////////////////////////////////////////////////////////////////////////////
+
+    Catch::MessageBuilder::MessageBuilder( StringRef const& macroName,
+                                           SourceLineInfo const& lineInfo,
+                                           ResultWas::OfType type )
+        :m_info(macroName, lineInfo, type) {}
+
+    ////////////////////////////////////////////////////////////////////////////
+
+    ScopedMessage::ScopedMessage( MessageBuilder const& builder )
+    : m_info( builder.m_info )
+    {
+        m_info.message = builder.m_stream.str();
+        getResultCapture().pushScopedMessage( m_info );
+    }
+
+    ScopedMessage::~ScopedMessage() {
+        if ( !uncaught_exceptions() ){
+            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
+// end catch_message.cpp
+// start catch_output_redirect.cpp
+
+// start catch_output_redirect.h
+#ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
+#define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_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;
+    };
+
+#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 {
+
+    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(); }
+
+#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();
+    }
+}
+// end catch_random_number_generator.cpp
+// start catch_registry_hub.cpp
+
+// start catch_test_case_registry_impl.h
+
+#include <vector>
+#include <set>
+#include <algorithm>
+#include <ios>
+
+namespace Catch {
+
+    class TestCase;
+    struct IConfig;
+
+    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 );
+
+    std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
+    std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
+
+    class TestRegistry : public ITestCaseRegistry {
+    public:
+        virtual ~TestRegistry() = default;
+
+        virtual void registerTest( TestCase const& testCase );
+
+        std::vector<TestCase> const& getAllTests() const override;
+        std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const override;
+
+    private:
+        std::vector<TestCase> m_functions;
+        mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder;
+        mutable std::vector<TestCase> m_sortedFunctions;
+        std::size_t m_unnamedCount = 0;
+        std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    class TestInvokerAsFunction : public ITestInvoker {
+        void(*m_testAsFunction)();
+    public:
+        TestInvokerAsFunction( void(*testAsFunction)() ) noexcept;
+
+        void invoke() const override;
+    };
+
+    std::string extractClassName( StringRef const& classOrQualifiedMethodName );
+
+    ///////////////////////////////////////////////////////////////////////////
+
+} // end namespace Catch
+
+// end catch_test_case_registry_impl.h
+// start catch_reporter_registry.h
+
+#include <map>
+
+namespace Catch {
+
+    class ReporterRegistry : public IReporterRegistry {
+
+    public:
+
+        ~ReporterRegistry() override;
+
+        IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override;
+
+        void registerReporter( std::string const& name, IReporterFactoryPtr const& factory );
+        void registerListener( IReporterFactoryPtr const& factory );
+
+        FactoryMap const& getFactories() const override;
+        Listeners const& getListeners() const override;
+
+    private:
+        FactoryMap m_factories;
+        Listeners m_listeners;
+    };
+}
+
+// end catch_reporter_registry.h
+// start catch_tag_alias_registry.h
+
+// start catch_tag_alias.h
+
+#include <string>
+
+namespace Catch {
+
+    struct TagAlias {
+        TagAlias(std::string const& _tag, SourceLineInfo _lineInfo);
+
+        std::string tag;
+        SourceLineInfo lineInfo;
+    };
+
+} // end namespace Catch
+
+// end catch_tag_alias.h
+#include <map>
+
+namespace Catch {
+
+    class TagAliasRegistry : public ITagAliasRegistry {
+    public:
+        ~TagAliasRegistry() override;
+        TagAlias const* find( std::string const& alias ) const override;
+        std::string expandAliases( std::string const& unexpandedTestSpec ) const override;
+        void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo );
+
+    private:
+        std::map<std::string, TagAlias> m_registry;
+    };
+
+} // end namespace Catch
+
+// end catch_tag_alias_registry.h
+// start catch_startup_exception_registry.h
+
+#include <vector>
+#include <exception>
+
+namespace Catch {
+
+    class StartupExceptionRegistry {
+    public:
+        void add(std::exception_ptr const& exception) noexcept;
+        std::vector<std::exception_ptr> const& getExceptions() const noexcept;
+    private:
+        std::vector<std::exception_ptr> m_exceptions;
+    };
+
+} // 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 {
+
+        class RegistryHub : public IRegistryHub, public IMutableRegistryHub,
+                            private NonCopyable {
+
+        public: // IRegistryHub
+            RegistryHub() = default;
+            IReporterRegistry const& getReporterRegistry() const override {
+                return m_reporterRegistry;
+            }
+            ITestCaseRegistry const& getTestCaseRegistry() const override {
+                return m_testCaseRegistry;
+            }
+            IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const override {
+                return m_exceptionTranslatorRegistry;
+            }
+            ITagAliasRegistry const& getTagAliasRegistry() const override {
+                return m_tagAliasRegistry;
+            }
+            StartupExceptionRegistry const& getStartupExceptionRegistry() const override {
+                return m_exceptionRegistry;
+            }
+
+        public: // IMutableRegistryHub
+            void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) override {
+                m_reporterRegistry.registerReporter( name, factory );
+            }
+            void registerListener( IReporterFactoryPtr const& factory ) override {
+                m_reporterRegistry.registerListener( factory );
+            }
+            void registerTest( TestCase const& testInfo ) override {
+                m_testCaseRegistry.registerTest( testInfo );
+            }
+            void registerTranslator( const IExceptionTranslator* translator ) override {
+                m_exceptionTranslatorRegistry.registerTranslator( translator );
+            }
+            void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override {
+                m_tagAliasRegistry.add( alias, tag, lineInfo );
+            }
+            void registerStartupException() noexcept override {
+                m_exceptionRegistry.add(std::current_exception());
+            }
+
+        private:
+            TestRegistry m_testCaseRegistry;
+            ReporterRegistry m_reporterRegistry;
+            ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
+            TagAliasRegistry m_tagAliasRegistry;
+            StartupExceptionRegistry m_exceptionRegistry;
+        };
+    }
+
+    using RegistryHubSingleton = Singleton<RegistryHub, IRegistryHub, IMutableRegistryHub>;
+
+    IRegistryHub const& getRegistryHub() {
+        return RegistryHubSingleton::get();
+    }
+    IMutableRegistryHub& getMutableRegistryHub() {
+        return RegistryHubSingleton::getMutable();
+    }
+    void cleanUp() {
+        cleanupSingletons();
+        cleanUpContext();
+    }
+    std::string translateActiveException() {
+        return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
+    }
+
+} // end namespace Catch
+// end catch_registry_hub.cpp
+// start catch_reporter_registry.cpp
+
+namespace Catch {
+
+    ReporterRegistry::~ReporterRegistry() = default;
+
+    IStreamingReporterPtr ReporterRegistry::create( std::string const& name, IConfigPtr const& config ) const {
+        auto it =  m_factories.find( name );
+        if( it == m_factories.end() )
+            return nullptr;
+        return it->second->create( ReporterConfig( config ) );
+    }
+
+    void ReporterRegistry::registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) {
+        m_factories.emplace(name, factory);
+    }
+    void ReporterRegistry::registerListener( IReporterFactoryPtr const& factory ) {
+        m_listeners.push_back( factory );
+    }
+
+    IReporterRegistry::FactoryMap const& ReporterRegistry::getFactories() const {
+        return m_factories;
+    }
+    IReporterRegistry::Listeners const& ReporterRegistry::getListeners() const {
+        return m_listeners;
+    }
+
+}
+// end catch_reporter_registry.cpp
+// start catch_result_type.cpp
+
+namespace Catch {
+
+    bool isOk( ResultWas::OfType resultType ) {
+        return ( resultType & ResultWas::FailureBit ) == 0;
+    }
+    bool isJustInfo( int flags ) {
+        return flags == ResultWas::Info;
+    }
+
+    ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
+        return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
+    }
+
+    bool shouldContinueOnFailure( int flags )    { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
+    bool shouldSuppressFailure( int flags )      { return ( flags & ResultDisposition::SuppressFail ) != 0; }
+
+} // end namespace Catch
+// end catch_result_type.cpp
+// start catch_run_context.cpp
+
+#include <cassert>
+#include <algorithm>
+#include <sstream>
+
+namespace Catch {
+
+    namespace Generators {
+        struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
+            size_t m_index = static_cast<size_t>( -1 );
+            GeneratorBasePtr m_generator;
+
+            GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
+            :   TrackerBase( nameAndLocation, ctx, parent )
+            {}
+            ~GeneratorTracker();
+
+            static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) {
+                std::shared_ptr<GeneratorTracker> tracker;
+
+                ITracker& currentTracker = ctx.currentTracker();
+                if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
+                    assert( childTracker );
+                    assert( childTracker->isIndexTracker() );
+                    tracker = std::static_pointer_cast<GeneratorTracker>( childTracker );
+                }
+                else {
+                    tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, &currentTracker );
+                    currentTracker.addChild( tracker );
+                }
+
+                if( !ctx.completedCycle() && !tracker->isComplete() ) {
+                    if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
+                        tracker->moveNext();
+                    tracker->open();
+                }
+
+                return *tracker;
+            }
+
+            void moveNext() {
+                m_index++;
+                m_children.clear();
+            }
+
+            // TrackerBase interface
+            bool isIndexTracker() const override { return true; }
+            auto hasGenerator() const -> bool override {
+                return !!m_generator;
+            }
+            void close() override {
+                TrackerBase::close();
+                if( m_runState == CompletedSuccessfully && m_index < m_generator->size()-1 )
+                    m_runState = Executing;
+            }
+
+            // IGeneratorTracker interface
+            auto getGenerator() const -> GeneratorBasePtr const& override {
+                return m_generator;
+            }
+            void setGenerator( GeneratorBasePtr&& generator ) override {
+                m_generator = std::move( generator );
+            }
+            auto getIndex() const -> size_t override {
+                return m_index;
+            }
+        };
+        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{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal },
+        m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions )
+    {
+        m_context.setRunner(this);
+        m_context.setConfig(m_config);
+        m_context.setResultCapture(this);
+        m_reporter->testRunStarting(m_runInfo);
+    }
+
+    RunContext::~RunContext() {
+        m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));
+    }
+
+    void RunContext::testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount) {
+        m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount));
+    }
+
+    void RunContext::testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount) {
+        m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting()));
+    }
+
+    Totals RunContext::runTest(TestCase const& testCase) {
+        Totals prevTotals = m_totals;
+
+        std::string redirectedCout;
+        std::string redirectedCerr;
+
+        auto const& testInfo = testCase.getTestCaseInfo();
+
+        m_reporter->testCaseStarting(testInfo);
+
+        m_activeTestCase = &testCase;
+
+        ITracker& rootTracker = m_trackerContext.startRun();
+        assert(rootTracker.isSectionTracker());
+        static_cast<SectionTracker&>(rootTracker).addInitialFilters(m_config->getSectionsToRun());
+        do {
+            m_trackerContext.startCycle();
+            m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo));
+            runCurrentTest(redirectedCout, redirectedCerr);
+        } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting());
+
+        Totals deltaTotals = m_totals.delta(prevTotals);
+        if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) {
+            deltaTotals.assertions.failed++;
+            deltaTotals.testCases.passed--;
+            deltaTotals.testCases.failed++;
+        }
+        m_totals.testCases += deltaTotals.testCases;
+        m_reporter->testCaseEnded(TestCaseStats(testInfo,
+                                  deltaTotals,
+                                  redirectedCout,
+                                  redirectedCerr,
+                                  aborting()));
+
+        m_activeTestCase = nullptr;
+        m_testCaseTracker = nullptr;
+
+        return deltaTotals;
+    }
+
+    IConfigPtr RunContext::config() const {
+        return m_config;
+    }
+
+    IStreamingReporter& RunContext::reporter() const {
+        return *m_reporter;
+    }
+
+    void RunContext::assertionEnded(AssertionResult const & result) {
+        if (result.getResultType() == ResultWas::Ok) {
+            m_totals.assertions.passed++;
+            m_lastAssertionPassed = true;
+        } else if (!result.isOk()) {
+            m_lastAssertionPassed = false;
+            if( m_activeTestCase->getTestCaseInfo().okToFail() )
+                m_totals.assertions.failedButOk++;
+            else
+                m_totals.assertions.failed++;
+        }
+        else {
+            m_lastAssertionPassed = true;
+        }
+
+        // We have no use for the return value (whether messages should be cleared), because messages were made scoped
+        // and should be let to clear themselves out.
+        static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
+
+        // Reset working state
+        resetAssertionInfo();
+        m_lastResult = result;
+    }
+    void RunContext::resetAssertionInfo() {
+        m_lastAssertionInfo.macroName = StringRef();
+        m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr;
+    }
+
+    bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) {
+        ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo));
+        if (!sectionTracker.isOpen())
+            return false;
+        m_activeSections.push_back(&sectionTracker);
+
+        m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
+
+        m_reporter->sectionStarting(sectionInfo);
+
+        assertions = m_totals.assertions;
+
+        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)
+            return false;
+        if (!m_config->warnAboutMissingAssertions())
+            return false;
+        if (m_trackerContext.currentTracker().hasChildren())
+            return false;
+        m_totals.assertions.failed++;
+        assertions.failed++;
+        return true;
+    }
+
+    void RunContext::sectionEnded(SectionEndInfo const & endInfo) {
+        Counts assertions = m_totals.assertions - endInfo.prevAssertions;
+        bool missingAssertions = testForMissingAssertions(assertions);
+
+        if (!m_activeSections.empty()) {
+            m_activeSections.back()->close();
+            m_activeSections.pop_back();
+        }
+
+        m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
+        m_messages.clear();
+    }
+
+    void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) {
+        if (m_unfinishedSections.empty())
+            m_activeSections.back()->fail();
+        else
+            m_activeSections.back()->close();
+        m_activeSections.pop_back();
+
+        m_unfinishedSections.push_back(endInfo);
+    }
+    void RunContext::benchmarkStarting( BenchmarkInfo const& info ) {
+        m_reporter->benchmarkStarting( info );
+    }
+    void RunContext::benchmarkEnded( BenchmarkStats const& stats ) {
+        m_reporter->benchmarkEnded( stats );
+    }
+
+    void RunContext::pushScopedMessage(MessageInfo const & message) {
+        m_messages.push_back(message);
+    }
+
+    void RunContext::popScopedMessage(MessageInfo const & message) {
+        m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
+    }
+
+    std::string RunContext::getCurrentTestName() const {
+        return m_activeTestCase
+            ? m_activeTestCase->getTestCaseInfo().name
+            : std::string();
+    }
+
+    const AssertionResult * RunContext::getLastResult() const {
+        return &(*m_lastResult);
+    }
+
+    void RunContext::exceptionEarlyReported() {
+        m_shouldReportUnexpected = false;
+    }
+
+    void RunContext::handleFatalErrorCondition( StringRef message ) {
+        // First notify reporter that bad things happened
+        m_reporter->fatalErrorEncountered(message);
+
+        // Don't rebuild the result -- the stringification itself can cause more fatal errors
+        // Instead, fake a result data.
+        AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } );
+        tempResult.message = message;
+        AssertionResult result(m_lastAssertionInfo, tempResult);
+
+        assertionEnded(result);
+
+        handleUnfinishedSections();
+
+        // 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);
+
+        Counts assertions;
+        assertions.failed = 1;
+        SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false);
+        m_reporter->sectionEnded(testCaseSectionStats);
+
+        auto const& testInfo = m_activeTestCase->getTestCaseInfo();
+
+        Totals deltaTotals;
+        deltaTotals.testCases.failed = 1;
+        deltaTotals.assertions.failed = 1;
+        m_reporter->testCaseEnded(TestCaseStats(testInfo,
+                                  deltaTotals,
+                                  std::string(),
+                                  std::string(),
+                                  false));
+        m_totals.testCases.failed++;
+        testGroupEnded(std::string(), m_totals, 1, 1);
+        m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false));
+    }
+
+    bool RunContext::lastAssertionPassed() {
+         return m_lastAssertionPassed;
+    }
+
+    void RunContext::assertionPassed() {
+        m_lastAssertionPassed = true;
+        ++m_totals.assertions.passed;
+        resetAssertionInfo();
+    }
+
+    bool RunContext::aborting() const {
+        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);
+        m_reporter->sectionStarting(testCaseSection);
+        Counts prevAssertions = m_totals.assertions;
+        double duration = 0;
+        m_shouldReportUnexpected = true;
+        m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal };
+
+        seedRng(*m_config);
+
+        Timer timer;
+        CATCH_TRY {
+            if (m_reporter->getPreferences().shouldRedirectStdOut) {
+#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
+                RedirectedStdOut redirectedStdOut;
+                RedirectedStdErr redirectedStdErr;
+
+                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_CATCH_ANON (TestFailureException&) {
+            // This just means the test was aborted due to failure
+        } 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 ) {
+                AssertionReaction dummyReaction;
+                handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction );
+            }
+        }
+        Counts assertions = m_totals.assertions - prevAssertions;
+        bool missingAssertions = testForMissingAssertions(assertions);
+
+        m_testCaseTracker->close();
+        handleUnfinishedSections();
+        m_messages.clear();
+
+        SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
+        m_reporter->sectionEnded(testCaseSectionStats);
+    }
+
+    void RunContext::invokeActiveTestCase() {
+        FatalConditionHandler fatalConditionHandler; // Handle signals
+        m_activeTestCase->invoke();
+        fatalConditionHandler.reset();
+    }
+
+    void RunContext::handleUnfinishedSections() {
+        // If sections ended prematurely due to an exception we stored their
+        // infos here so we can tear them down outside the unwind process.
+        for (auto it = m_unfinishedSections.rbegin(),
+             itEnd = m_unfinishedSections.rend();
+             it != itEnd;
+             ++it)
+            sectionEnded(*it);
+        m_unfinishedSections.clear();
+    }
+
+    void RunContext::handleExpr(
+        AssertionInfo const& info,
+        ITransientExpression const& expr,
+        AssertionReaction& reaction
+    ) {
+        m_reporter->assertionStarting( info );
+
+        bool negated = isFalseTest( info.resultDisposition );
+        bool result = expr.getResult() != negated;
+
+        if( result ) {
+            if (!m_includeSuccessfulResults) {
+                assertionPassed();
+            }
+            else {
+                reportExpr(info, ResultWas::Ok, &expr, negated);
+            }
+        }
+        else {
+            reportExpr(info, ResultWas::ExpressionFailed, &expr, negated );
+            populateReaction( reaction );
+        }
+    }
+    void RunContext::reportExpr(
+            AssertionInfo const &info,
+            ResultWas::OfType resultType,
+            ITransientExpression const *expr,
+            bool negated ) {
+
+        m_lastAssertionInfo = info;
+        AssertionResultData data( resultType, LazyExpression( negated ) );
+
+        AssertionResult assertionResult{ info, data };
+        assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
+
+        assertionEnded( assertionResult );
+    }
+
+    void RunContext::handleMessage(
+            AssertionInfo const& info,
+            ResultWas::OfType resultType,
+            StringRef const& message,
+            AssertionReaction& reaction
+    ) {
+        m_reporter->assertionStarting( info );
+
+        m_lastAssertionInfo = info;
+
+        AssertionResultData data( resultType, LazyExpression( false ) );
+        data.message = message;
+        AssertionResult assertionResult{ m_lastAssertionInfo, data };
+        assertionEnded( assertionResult );
+        if( !assertionResult.isOk() )
+            populateReaction( reaction );
+    }
+    void RunContext::handleUnexpectedExceptionNotThrown(
+            AssertionInfo const& info,
+            AssertionReaction& reaction
+    ) {
+        handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction);
+    }
+
+    void RunContext::handleUnexpectedInflightException(
+            AssertionInfo const& info,
+            std::string const& message,
+            AssertionReaction& reaction
+    ) {
+        m_lastAssertionInfo = info;
+
+        AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
+        data.message = message;
+        AssertionResult assertionResult{ info, data };
+        assertionEnded( assertionResult );
+        populateReaction( reaction );
+    }
+
+    void RunContext::populateReaction( AssertionReaction& reaction ) {
+        reaction.shouldDebugBreak = m_config->shouldDebugBreak();
+        reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal);
+    }
+
+    void RunContext::handleIncomplete(
+            AssertionInfo const& info
+    ) {
+        m_lastAssertionInfo = info;
+
+        AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
+        data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
+        AssertionResult assertionResult{ info, data };
+        assertionEnded( assertionResult );
+    }
+    void RunContext::handleNonExpr(
+            AssertionInfo const &info,
+            ResultWas::OfType resultType,
+            AssertionReaction &reaction
+    ) {
+        m_lastAssertionInfo = info;
+
+        AssertionResultData data( resultType, LazyExpression( false ) );
+        AssertionResult assertionResult{ info, data };
+        assertionEnded( assertionResult );
+
+        if( !assertionResult.isOk() )
+            populateReaction( reaction );
+    }
+
+    IResultCapture& getResultCapture() {
+        if (auto* capture = getCurrentContext().getResultCapture())
+            return *capture;
+        else
+            CATCH_INTERNAL_ERROR("No result capture instance");
+    }
+}
+// end catch_run_context.cpp
+// start catch_section.cpp
+
+namespace Catch {
+
+    Section::Section( SectionInfo const& info )
+    :   m_info( info ),
+        m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) )
+    {
+        m_timer.start();
+    }
+
+    Section::~Section() {
+        if( m_sectionIncluded ) {
+            SectionEndInfo endInfo{ m_info, m_assertions, m_timer.getElapsedSeconds() };
+            if( uncaught_exceptions() )
+                getResultCapture().sectionEndedEarly( endInfo );
+            else
+                getResultCapture().sectionEnded( endInfo );
+        }
+    }
+
+    // This indicates whether the section should be executed or not
+    Section::operator bool() const {
+        return m_sectionIncluded;
+    }
+
+} // end namespace Catch
+// end catch_section.cpp
+// start catch_section_info.cpp
+
+namespace Catch {
+
+    SectionInfo::SectionInfo
+        (   SourceLineInfo const& _lineInfo,
+            std::string const& _name )
+    :   name( _name ),
+        lineInfo( _lineInfo )
+    {}
+
+} // end namespace Catch
+// end catch_section_info.cpp
+// start catch_session.cpp
+
+// start catch_session.h
+
+#include <memory>
+
+namespace Catch {
+
+    class Session : NonCopyable {
+    public:
+
+        Session();
+        ~Session() override;
+
+        void showHelp() const;
+        void libIdentify();
+
+        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 );
+
+        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;
+        void cli( clara::Parser const& newParser );
+        ConfigData& configData();
+        Config& config();
+    private:
+        int runInternal();
+
+        clara::Parser m_cli;
+        ConfigData m_configData;
+        std::shared_ptr<Config> m_config;
+        bool m_startupExceptions = false;
+    };
+
+} // end namespace Catch
+
+// end catch_session.h
+// start catch_version.h
+
+#include <iosfwd>
+
+namespace Catch {
+
+    // Versioning information
+    struct Version {
+        Version( Version const& ) = delete;
+        Version& operator=( Version const& ) = delete;
+        Version(    unsigned int _majorVersion,
+                    unsigned int _minorVersion,
+                    unsigned int _patchNumber,
+                    char const * const _branchName,
+                    unsigned int _buildNumber );
+
+        unsigned int const majorVersion;
+        unsigned int const minorVersion;
+        unsigned int const patchNumber;
+
+        // buildNumber is only used if branchName is not null
+        char const * const branchName;
+        unsigned int const buildNumber;
+
+        friend std::ostream& operator << ( std::ostream& os, Version const& version );
+    };
+
+    Version const& libraryVersion();
+}
+
+// end catch_version.h
+#include <cstdlib>
+#include <iomanip>
+
+namespace Catch {
+
+    namespace {
+        const int MaxExitCode = 255;
+
+        IStreamingReporterPtr createReporter(std::string const& reporterName, IConfigPtr const& config) {
+            auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config);
+            CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << "'");
+
+            return reporter;
+        }
+
+        IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) {
+            if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) {
+                return createReporter(config->getReporterName(), config);
+            }
+
+            auto multi = std::unique_ptr<ListeningReporter>(new ListeningReporter);
+
+            auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
+            for (auto const& listener : listeners) {
+                multi->addListener(listener->create(Catch::ReporterConfig(config)));
+            }
+            multi->addReporter(createReporter(config->getReporterName(), config));
+            return std::move(multi);
+        }
+
+        Catch::Totals runTests(std::shared_ptr<Config> const& config) {
+            auto reporter = makeReporter(config);
+
+            RunContext context(config, std::move(reporter));
+
+            Totals totals;
+
+            context.testGroupStarting(config->name(), 1, 1);
+
+            TestSpec testSpec = config->testSpec();
+
+            auto const& allTestCases = getAllTestCasesSorted(*config);
+            for (auto const& testCase : allTestCases) {
+                if (!context.aborting() && matchTest(testCase, testSpec, *config))
+                    totals += context.runTest(testCase);
+                else
+                    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;
+        }
+
+        void applyFilenamesAsTags(Catch::IConfig const& config) {
+            auto& tests = const_cast<std::vector<TestCase>&>(getAllTestCasesSorted(config));
+            for (auto& testCase : tests) {
+                auto tags = testCase.tags;
+
+                std::string filename = testCase.lineInfo.file;
+                auto lastSlash = filename.find_last_of("\\/");
+                if (lastSlash != std::string::npos) {
+                    filename.erase(0, lastSlash);
+                    filename[0] = '#';
+                }
+
+                auto lastDot = filename.find_last_of('.');
+                if (lastDot != std::string::npos) {
+                    filename.erase(lastDot);
+                }
+
+                tags.push_back(std::move(filename));
+                setTags(testCase, tags);
+            }
+        }
+
+    } // anon namespace
+
+    Session::Session() {
+        static bool alreadyInstantiated = false;
+        if( alreadyInstantiated ) {
+            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 occurred during startup!" << '\n';
+            // iterate over all exceptions and notify user
+            for ( const auto& ex_ptr : exceptions ) {
+                try {
+                    std::rethrow_exception(ex_ptr);
+                } catch ( std::exception const& ex ) {
+                    Catch::cerr() << Column( ex.what() ).indent(2) << '\n';
+                }
+            }
+        }
+#endif
+
+        alreadyInstantiated = true;
+        m_cli = makeCommandLineParser( m_configData );
+    }
+    Session::~Session() {
+        Catch::cleanUp();
+    }
+
+    void Session::showHelp() const {
+        Catch::cout()
+                << "\nCatch v" << libraryVersion() << "\n"
+                << m_cli << std::endl
+                << "For more detailed usage please see the project docs\n" << std::endl;
+    }
+    void Session::libIdentify() {
+        Catch::cout()
+                << std::left << std::setw(16) << "description: " << "A Catch test executable\n"
+                << std::left << std::setw(16) << "category: " << "testframework\n"
+                << std::left << std::setw(16) << "framework: " << "Catch Test\n"
+                << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
+    }
+
+    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 ) {
+            Catch::cerr()
+                << Colour( Colour::Red )
+                << "\nError(s) in input:\n"
+                << Column( result.errorMessage() ).indent( 2 )
+                << "\n\n";
+            Catch::cerr() << "Run with -? for usage\n" << std::endl;
+            return MaxExitCode;
+        }
+
+        if( m_configData.showHelp )
+            showHelp();
+        if( m_configData.libIdentify )
+            libIdentify();
+        m_config.reset();
+        return 0;
+    }
+
+#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
+    int Session::applyCommandLine( int argc, wchar_t const * const * argv ) {
+
+        char **utf8Argv = new char *[ argc ];
+
+        for ( int i = 0; i < argc; ++i ) {
+            int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL );
+
+            utf8Argv[ i ] = new char[ bufSize ];
+
+            WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
+        }
+
+        int returnCode = applyCommandLine( argc, utf8Argv );
+
+        for ( int i = 0; i < argc; ++i )
+            delete [] utf8Argv[ i ];
+
+        delete [] utf8Argv;
+
+        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;
+            static_cast<void>(std::getchar());
+        }
+        int exitCode = runInternal();
+        if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
+            Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl;
+            static_cast<void>(std::getchar());
+        }
+        return exitCode;
+    }
+
+    clara::Parser const& Session::cli() const {
+        return m_cli;
+    }
+    void Session::cli( clara::Parser const& newParser ) {
+        m_cli = newParser;
+    }
+    ConfigData& Session::configData() {
+        return m_configData;
+    }
+    Config& Session::config() {
+        if( !m_config )
+            m_config = std::make_shared<Config>( m_configData );
+        return *m_config;
+    }
+
+    int Session::runInternal() {
+        if( m_startupExceptions )
+            return 1;
+
+        if (m_configData.showHelp || m_configData.libIdentify) {
+            return 0;
+        }
+
+        CATCH_TRY {
+            config(); // Force config to be constructed
+
+            seedRng( *m_config );
+
+            if( m_configData.filenamesAsTags )
+                applyFilenamesAsTags( *m_config );
+
+            // Handle list request
+            if( Option<std::size_t> listed = list( 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, (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 {
+        CATCH_TRY {
+            m_exceptions.push_back(exception);
+        } 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();
+        }
+    }
+
+    std::vector<std::exception_ptr> const& StartupExceptionRegistry::getExceptions() const noexcept {
+        return m_exceptions;
+    }
+
+} // end namespace Catch
+// end catch_startup_exception_registry.cpp
+// start catch_stream.cpp
+
+#include <cstdio>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <vector>
+#include <memory>
+
+namespace Catch {
+
+    Catch::IStream::~IStream() = default;
+
+    namespace detail { namespace {
+        template<typename WriterF, std::size_t bufferSize=256>
+        class StreamBufImpl : public std::streambuf {
+            char data[bufferSize];
+            WriterF m_writer;
+
+        public:
+            StreamBufImpl() {
+                setp( data, data + sizeof(data) );
+            }
+
+            ~StreamBufImpl() noexcept {
+                StreamBufImpl::sync();
+            }
+
+        private:
+            int overflow( int c ) override {
+                sync();
+
+                if( c != EOF ) {
+                    if( pbase() == epptr() )
+                        m_writer( std::string( 1, static_cast<char>( c ) ) );
+                    else
+                        sputc( static_cast<char>( c ) );
+                }
+                return 0;
+            }
+
+            int sync() override {
+                if( pbase() != pptr() ) {
+                    m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
+                    setp( pbase(), epptr() );
+                }
+                return 0;
+            }
+        };
+
+        ///////////////////////////////////////////////////////////////////////////
+
+        struct OutputDebugWriter {
+
+            void operator()( std::string const&str ) {
+                writeToDebugConsole( str );
+            }
+        };
+
+        ///////////////////////////////////////////////////////////////////////////
+
+        class FileStream : public IStream {
+            mutable std::ofstream m_ofs;
+        public:
+            FileStream( StringRef filename ) {
+                m_ofs.open( filename.c_str() );
+                CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" );
+            }
+            ~FileStream() override = default;
+        public: // IStream
+            std::ostream& stream() const override {
+                return m_ofs;
+            }
+        };
+
+        ///////////////////////////////////////////////////////////////////////////
+
+        class CoutStream : public IStream {
+            mutable std::ostream m_os;
+        public:
+            // Store the streambuf from cout up-front because
+            // cout may get redirected when running tests
+            CoutStream() : m_os( Catch::cout().rdbuf() ) {}
+            ~CoutStream() override = default;
+
+        public: // IStream
+            std::ostream& stream() const override { return m_os; }
+        };
+
+        ///////////////////////////////////////////////////////////////////////////
+
+        class DebugOutStream : public IStream {
+            std::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf;
+            mutable std::ostream m_os;
+        public:
+            DebugOutStream()
+            :   m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
+                m_os( m_streamBuf.get() )
+            {}
+
+            ~DebugOutStream() override = default;
+
+        public: // IStream
+            std::ostream& stream() const override { return m_os; }
+        };
+
+    }} // namespace anon::detail
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    auto makeStream( StringRef const &filename ) -> IStream const* {
+        if( filename.empty() )
+            return new detail::CoutStream();
+        else if( filename[0] == '%' ) {
+            if( filename == "%debug" )
+                return new detail::DebugOutStream();
+            else
+                CATCH_ERROR( "Unrecognised stream: '" << filename << "'" );
+        }
+        else
+            return new detail::FileStream( filename );
+    }
+
+    // This class encapsulates the idea of a pool of ostringstreams that can be reused.
+    struct StringStreams {
+        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
+
+        auto add() -> std::size_t {
+            if( m_unused.empty() ) {
+                m_streams.push_back( std::unique_ptr<std::ostringstream>( new std::ostringstream ) );
+                return m_streams.size()-1;
+            }
+            else {
+                auto index = m_unused.back();
+                m_unused.pop_back();
+                return index;
+            }
+        }
+
+        void release( std::size_t index ) {
+            m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state
+            m_unused.push_back(index);
+        }
+    };
+
+    ReusableStringStream::ReusableStringStream()
+    :   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();
+        Singleton<StringStreams>::getMutable().release( m_index );
+    }
+
+    auto ReusableStringStream::str() const -> std::string {
+        return static_cast<std::ostringstream*>( m_oss )->str();
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+
+#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
+    std::ostream& cout() { return std::cout; }
+    std::ostream& cerr() { return std::cerr; }
+    std::ostream& clog() { return std::clog; }
+#endif
+}
+// end catch_stream.cpp
+// start catch_string_manip.cpp
+
+#include <algorithm>
+#include <ostream>
+#include <cstring>
+#include <cctype>
+
+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());
+    }
+    bool startsWith( std::string const& s, char prefix ) {
+        return !s.empty() && s[0] == prefix;
+    }
+    bool endsWith( std::string const& s, std::string const& suffix ) {
+        return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
+    }
+    bool endsWith( std::string const& s, char suffix ) {
+        return !s.empty() && s[s.size()-1] == suffix;
+    }
+    bool contains( std::string const& s, std::string const& infix ) {
+        return s.find( infix ) != std::string::npos;
+    }
+    void toLowerInPlace( std::string& s ) {
+        std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
+    }
+    std::string toLower( std::string const& s ) {
+        std::string lc = s;
+        toLowerInPlace( lc );
+        return lc;
+    }
+    std::string trim( std::string const& str ) {
+        static char const* whitespaceChars = "\n\r\t ";
+        std::string::size_type start = str.find_first_not_of( whitespaceChars );
+        std::string::size_type end = str.find_last_not_of( whitespaceChars );
+
+        return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
+    }
+
+    bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
+        bool replaced = false;
+        std::size_t i = str.find( replaceThis );
+        while( i != std::string::npos ) {
+            replaced = true;
+            str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
+            if( i < str.size()-withThis.size() )
+                i = str.find( replaceThis, i+withThis.size() );
+            else
+                i = std::string::npos;
+        }
+        return replaced;
+    }
+
+    pluralise::pluralise( std::size_t count, std::string const& label )
+    :   m_count( count ),
+        m_label( label )
+    {}
+
+    std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
+        os << pluraliser.m_count << ' ' << pluraliser.m_label;
+        if( pluraliser.m_count != 1 )
+            os << 's';
+        return os;
+    }
+
+}
+// end catch_string_manip.cpp
+// start catch_stringref.cpp
+
+#if defined(__clang__)
+#    pragma clang diagnostic push
+#    pragma clang diagnostic ignored "-Wexit-time-destructors"
+#endif
+
+#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
+    : StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) )
+    {}
+
+    StringRef::operator std::string() const {
+        return std::string( m_start, m_size );
+    }
+
+    void StringRef::swap( StringRef& other ) noexcept {
+        std::swap( m_start, other.m_start );
+        std::swap( m_size, other.m_size );
+        std::swap( m_data, other.m_data );
+    }
+
+    auto StringRef::c_str() const -> char const* {
+        if( isSubstring() )
+           const_cast<StringRef*>( this )->takeOwnership();
+        return m_start;
+    }
+    auto StringRef::currentData() const noexcept -> char const* {
+        return m_start;
+    }
+
+    auto StringRef::isOwned() const noexcept -> bool {
+        return m_data != nullptr;
+    }
+    auto StringRef::isSubstring() const noexcept -> bool {
+        return m_start[m_size] != '\0';
+    }
+
+    void StringRef::takeOwnership() {
+        if( !isOwned() ) {
+            m_data = new char[m_size+1];
+            memcpy( m_data, m_start, m_size );
+            m_data[m_size] = '\0';
+            m_start = m_data;
+        }
+    }
+    auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef {
+        if( start < m_size )
+            return StringRef( m_start+start, size );
+        else
+            return StringRef();
+    }
+    auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool {
+        return
+            size() == other.size() &&
+            (std::strncmp( m_start, other.m_start, size() ) == 0);
+    }
+    auto StringRef::operator != ( StringRef const& other ) const noexcept -> bool {
+        return !operator==( other );
+    }
+
+    auto StringRef::operator[](size_type index) const noexcept -> char {
+        return m_start[index];
+    }
+
+    auto StringRef::numberOfCharacters() const noexcept -> size_type {
+        size_type noChars = m_size;
+        // Make adjustments for uft encodings
+        for( size_type i=0; i < m_size; ++i ) {
+            char c = m_start[i];
+            if( ( c & byte_2_lead ) == byte_2_lead ) {
+                noChars--;
+                if (( c & byte_3_lead ) == byte_3_lead )
+                    noChars--;
+                if( ( c & byte_4_lead ) == byte_4_lead )
+                    noChars--;
+            }
+        }
+        return noChars;
+    }
+
+    auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string {
+        std::string str;
+        str.reserve( lhs.size() + rhs.size() );
+        str += lhs;
+        str += rhs;
+        return str;
+    }
+    auto operator + ( StringRef const& lhs, const char* rhs ) -> std::string {
+        return std::string( lhs ) + std::string( rhs );
+    }
+    auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string {
+        return std::string( lhs ) + std::string( rhs );
+    }
+
+    auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& {
+        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
+
+#if defined(__clang__)
+#    pragma clang diagnostic pop
+#endif
+// end catch_stringref.cpp
+// start catch_tag_alias.cpp
+
+namespace Catch {
+    TagAlias::TagAlias(std::string const & _tag, SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {}
+}
+// end catch_tag_alias.cpp
+// start catch_tag_alias_autoregistrar.cpp
+
+namespace Catch {
+
+    RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) {
+        CATCH_TRY {
+            getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo);
+        } CATCH_CATCH_ALL {
+            // Do not throw when constructing global objects, instead register the exception to be processed later
+            getMutableRegistryHub().registerStartupException();
+        }
+    }
+
+}
+// end catch_tag_alias_autoregistrar.cpp
+// start catch_tag_alias_registry.cpp
+
+#include <sstream>
+
+namespace Catch {
+
+    TagAliasRegistry::~TagAliasRegistry() {}
+
+    TagAlias const* TagAliasRegistry::find( std::string const& alias ) const {
+        auto it = m_registry.find( alias );
+        if( it != m_registry.end() )
+            return &(it->second);
+        else
+            return nullptr;
+    }
+
+    std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
+        std::string expandedTestSpec = unexpandedTestSpec;
+        for( auto const& registryKvp : m_registry ) {
+            std::size_t pos = expandedTestSpec.find( registryKvp.first );
+            if( pos != std::string::npos ) {
+                expandedTestSpec =  expandedTestSpec.substr( 0, pos ) +
+                                    registryKvp.second.tag +
+                                    expandedTestSpec.substr( pos + registryKvp.first.size() );
+            }
+        }
+        return expandedTestSpec;
+    }
+
+    void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) {
+        CATCH_ENFORCE( startsWith(alias, "[@") && endsWith(alias, ']'),
+                      "error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo );
+
+        CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second,
+                      "error: tag alias, '" << alias << "' already registered.\n"
+                      << "\tFirst seen at: " << find(alias)->lineInfo << "\n"
+                      << "\tRedefined at: " << lineInfo );
+    }
+
+    ITagAliasRegistry::~ITagAliasRegistry() {}
+
+    ITagAliasRegistry const& ITagAliasRegistry::get() {
+        return getRegistryHub().getTagAliasRegistry();
+    }
+
+} // end namespace Catch
+// end catch_tag_alias_registry.cpp
+// start catch_test_case_info.cpp
+
+#include <cctype>
+#include <exception>
+#include <algorithm>
+#include <sstream>
+
+namespace Catch {
+
+    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,
+                            NameAndTags const& nameAndTags,
+                            SourceLineInfo const& _lineInfo )
+    {
+        bool isHidden = false;
+
+        // Parse out tags
+        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 == '[' )
+                    inTag = true;
+                else
+                    desc += c;
+            }
+            else {
+                if( c == ']' ) {
+                    TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
+                    if( ( prop & TestCaseInfo::IsHidden ) != 0 )
+                        isHidden = true;
+                    else if( prop == TestCaseInfo::None )
+                        enforceNotReservedTag( tag, _lineInfo );
+
+                    tags.push_back( tag );
+                    tag.clear();
+                    inTag = false;
+                }
+                else
+                    tag += c;
+            }
+        }
+        if( isHidden ) {
+            tags.push_back( "." );
+        }
+
+        TestCaseInfo info( nameAndTags.name, _className, desc, tags, _lineInfo );
+        return TestCase( _testCase, std::move(info) );
+    }
+
+    void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) {
+        std::sort(begin(tags), end(tags));
+        tags.erase(std::unique(begin(tags), end(tags)), end(tags));
+        testCaseInfo.lcaseTags.clear();
+
+        for( auto const& tag : tags ) {
+            std::string lcaseTag = toLower( tag );
+            testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
+            testCaseInfo.lcaseTags.push_back( lcaseTag );
+        }
+        testCaseInfo.tags = std::move(tags);
+    }
+
+    TestCaseInfo::TestCaseInfo( std::string const& _name,
+                                std::string const& _className,
+                                std::string const& _description,
+                                std::vector<std::string> const& _tags,
+                                SourceLineInfo const& _lineInfo )
+    :   name( _name ),
+        className( _className ),
+        description( _description ),
+        lineInfo( _lineInfo ),
+        properties( None )
+    {
+        setTags( *this, _tags );
+    }
+
+    bool TestCaseInfo::isHidden() const {
+        return ( properties & IsHidden ) != 0;
+    }
+    bool TestCaseInfo::throws() const {
+        return ( properties & Throws ) != 0;
+    }
+    bool TestCaseInfo::okToFail() const {
+        return ( properties & (ShouldFail | MayFail ) ) != 0;
+    }
+    bool TestCaseInfo::expectedToFail() const {
+        return ( properties & (ShouldFail ) ) != 0;
+    }
+
+    std::string TestCaseInfo::tagsAsString() const {
+        std::string ret;
+        // '[' and ']' per tag
+        std::size_t full_size = 2 * tags.size();
+        for (const auto& tag : tags) {
+            full_size += tag.size();
+        }
+        ret.reserve(full_size);
+        for (const auto& tag : tags) {
+            ret.push_back('[');
+            ret.append(tag);
+            ret.push_back(']');
+        }
+
+        return ret;
+    }
+
+    TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo( std::move(info) ), test( testCase ) {}
+
+    TestCase TestCase::withName( std::string const& _newName ) const {
+        TestCase other( *this );
+        other.name = _newName;
+        return other;
+    }
+
+    void TestCase::invoke() const {
+        test->invoke();
+    }
+
+    bool TestCase::operator == ( TestCase const& other ) const {
+        return  test.get() == other.test.get() &&
+                name == other.name &&
+                className == other.className;
+    }
+
+    bool TestCase::operator < ( TestCase const& other ) const {
+        return name < other.name;
+    }
+
+    TestCaseInfo const& TestCase::getTestCaseInfo() const
+    {
+        return *this;
+    }
+
+} // end namespace Catch
+// end catch_test_case_info.cpp
+// start catch_test_case_registry_impl.cpp
+
+#include <sstream>
+
+namespace Catch {
+
+    std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
+
+        std::vector<TestCase> sorted = unsortedTestCases;
+
+        switch( config.runOrder() ) {
+            case RunTests::InLexicographicalOrder:
+                std::sort( sorted.begin(), sorted.end() );
+                break;
+            case RunTests::InRandomOrder:
+                seedRng( config );
+                std::shuffle( sorted.begin(), sorted.end(), rng() );
+                break;
+            case RunTests::InDeclarationOrder:
+                // already in declaration order
+                break;
+        }
+        return sorted;
+    }
+    bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
+        return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
+    }
+
+    void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
+        std::set<TestCase> seenFunctions;
+        for( auto const& function : functions ) {
+            auto prev = seenFunctions.insert( function );
+            CATCH_ENFORCE( prev.second,
+                    "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n"
+                    << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
+                    << "\tRedefined at " << function.getTestCaseInfo().lineInfo );
+        }
+    }
+
+    std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
+        std::vector<TestCase> filtered;
+        filtered.reserve( testCases.size() );
+        for( auto const& testCase : testCases )
+            if( matchTest( testCase, testSpec, config ) )
+                filtered.push_back( testCase );
+        return filtered;
+    }
+    std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
+        return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
+    }
+
+    void TestRegistry::registerTest( TestCase const& testCase ) {
+        std::string name = testCase.getTestCaseInfo().name;
+        if( name.empty() ) {
+            ReusableStringStream rss;
+            rss << "Anonymous test case " << ++m_unnamedCount;
+            return registerTest( testCase.withName( rss.str() ) );
+        }
+        m_functions.push_back( testCase );
+    }
+
+    std::vector<TestCase> const& TestRegistry::getAllTests() const {
+        return m_functions;
+    }
+    std::vector<TestCase> const& TestRegistry::getAllTestsSorted( IConfig const& config ) const {
+        if( m_sortedFunctions.empty() )
+            enforceNoDuplicateTestCases( m_functions );
+
+        if(  m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
+            m_sortedFunctions = sortTests( config, m_functions );
+            m_currentSortOrder = config.runOrder();
+        }
+        return m_sortedFunctions;
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {}
+
+    void TestInvokerAsFunction::invoke() const {
+        m_testAsFunction();
+    }
+
+    std::string extractClassName( StringRef const& classOrQualifiedMethodName ) {
+        std::string className = classOrQualifiedMethodName;
+        if( startsWith( className, '&' ) )
+        {
+            std::size_t lastColons = className.rfind( "::" );
+            std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
+            if( penultimateColons == std::string::npos )
+                penultimateColons = 1;
+            className = className.substr( penultimateColons, lastColons-penultimateColons );
+        }
+        return className;
+    }
+
+} // end namespace Catch
+// end catch_test_case_registry_impl.cpp
+// start catch_test_case_tracker.cpp
+
+#include <algorithm>
+#include <cassert>
+#include <stdexcept>
+#include <memory>
+#include <sstream>
+
+#if defined(__clang__)
+#    pragma clang diagnostic push
+#    pragma clang diagnostic ignored "-Wexit-time-destructors"
+#endif
+
+namespace Catch {
+namespace TestCaseTracking {
+
+    NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location )
+    :   name( _name ),
+        location( _location )
+    {}
+
+    ITracker::~ITracker() = default;
+
+    TrackerContext& TrackerContext::instance() {
+        static TrackerContext s_instance;
+        return s_instance;
+    }
+
+    ITracker& TrackerContext::startRun() {
+        m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr );
+        m_currentTracker = nullptr;
+        m_runState = Executing;
+        return *m_rootTracker;
+    }
+
+    void TrackerContext::endRun() {
+        m_rootTracker.reset();
+        m_currentTracker = nullptr;
+        m_runState = NotStarted;
+    }
+
+    void TrackerContext::startCycle() {
+        m_currentTracker = m_rootTracker.get();
+        m_runState = Executing;
+    }
+    void TrackerContext::completeCycle() {
+        m_runState = CompletedCycle;
+    }
+
+    bool TrackerContext::completedCycle() const {
+        return m_runState == CompletedCycle;
+    }
+    ITracker& TrackerContext::currentTracker() {
+        return *m_currentTracker;
+    }
+    void TrackerContext::setCurrentTracker( ITracker* tracker ) {
+        m_currentTracker = tracker;
+    }
+
+    TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
+    :   m_nameAndLocation( nameAndLocation ),
+        m_ctx( ctx ),
+        m_parent( parent )
+    {}
+
+    NameAndLocation const& TrackerBase::nameAndLocation() const {
+        return m_nameAndLocation;
+    }
+    bool TrackerBase::isComplete() const {
+        return m_runState == CompletedSuccessfully || m_runState == Failed;
+    }
+    bool TrackerBase::isSuccessfullyCompleted() const {
+        return m_runState == CompletedSuccessfully;
+    }
+    bool TrackerBase::isOpen() const {
+        return m_runState != NotStarted && !isComplete();
+    }
+    bool TrackerBase::hasChildren() const {
+        return !m_children.empty();
+    }
+
+    void TrackerBase::addChild( ITrackerPtr const& child ) {
+        m_children.push_back( child );
+    }
+
+    ITrackerPtr TrackerBase::findChild( NameAndLocation const& 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;
+    }
+    ITracker& TrackerBase::parent() {
+        assert( m_parent ); // Should always be non-null except for root
+        return *m_parent;
+    }
+
+    void TrackerBase::openChild() {
+        if( m_runState != ExecutingChildren ) {
+            m_runState = ExecutingChildren;
+            if( m_parent )
+                m_parent->openChild();
+        }
+    }
+
+    bool TrackerBase::isSectionTracker() const { return false; }
+    bool TrackerBase::isIndexTracker() const { return false; }
+
+    void TrackerBase::open() {
+        m_runState = Executing;
+        moveToThis();
+        if( m_parent )
+            m_parent->openChild();
+    }
+
+    void TrackerBase::close() {
+
+        // Close any still open children (e.g. generators)
+        while( &m_ctx.currentTracker() != this )
+            m_ctx.currentTracker().close();
+
+        switch( m_runState ) {
+            case NeedsAnotherRun:
+                break;
+
+            case Executing:
+                m_runState = CompletedSuccessfully;
+                break;
+            case ExecutingChildren:
+                if( m_children.empty() || m_children.back()->isComplete() )
+                    m_runState = CompletedSuccessfully;
+                break;
+
+            case NotStarted:
+            case CompletedSuccessfully:
+            case Failed:
+                CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState );
+
+            default:
+                CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState );
+        }
+        moveToParent();
+        m_ctx.completeCycle();
+    }
+    void TrackerBase::fail() {
+        m_runState = Failed;
+        if( m_parent )
+            m_parent->markAsNeedingAnotherRun();
+        moveToParent();
+        m_ctx.completeCycle();
+    }
+    void TrackerBase::markAsNeedingAnotherRun() {
+        m_runState = NeedsAnotherRun;
+    }
+
+    void TrackerBase::moveToParent() {
+        assert( m_parent );
+        m_ctx.setCurrentTracker( m_parent );
+    }
+    void TrackerBase::moveToThis() {
+        m_ctx.setCurrentTracker( this );
+    }
+
+    SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
+    :   TrackerBase( nameAndLocation, ctx, parent )
+    {
+        if( parent ) {
+            while( !parent->isSectionTracker() )
+                parent = &parent->parent();
+
+            SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
+            addNextFilters( parentSection.m_filters );
+        }
+    }
+
+    bool SectionTracker::isSectionTracker() const { return true; }
+
+    SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
+        std::shared_ptr<SectionTracker> section;
+
+        ITracker& currentTracker = ctx.currentTracker();
+        if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
+            assert( childTracker );
+            assert( childTracker->isSectionTracker() );
+            section = std::static_pointer_cast<SectionTracker>( childTracker );
+        }
+        else {
+            section = std::make_shared<SectionTracker>( nameAndLocation, ctx, &currentTracker );
+            currentTracker.addChild( section );
+        }
+        if( !ctx.completedCycle() )
+            section->tryOpen();
+        return *section;
+    }
+
+    void SectionTracker::tryOpen() {
+        if( !isComplete() && (m_filters.empty() || m_filters[0].empty() ||  m_filters[0] == m_nameAndLocation.name ) )
+            open();
+    }
+
+    void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) {
+        if( !filters.empty() ) {
+            m_filters.push_back(""); // Root - should never be consulted
+            m_filters.push_back(""); // Test Case - not a section filter
+            m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
+        }
+    }
+    void SectionTracker::addNextFilters( std::vector<std::string> const& filters ) {
+        if( filters.size() > 1 )
+            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
+
+#if defined(__clang__)
+#    pragma clang diagnostic pop
+#endif
+// end catch_test_case_tracker.cpp
+// start catch_test_registry.cpp
+
+namespace Catch {
+
+    auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* {
+        return new(std::nothrow) TestInvokerAsFunction( testAsFunction );
+    }
+
+    NameAndTags::NameAndTags( StringRef const& name_ , StringRef const& tags_ ) noexcept : name( name_ ), tags( tags_ ) {}
+
+    AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept {
+        CATCH_TRY {
+            getMutableRegistryHub()
+                    .registerTest(
+                        makeTestCase(
+                            invoker,
+                            extractClassName( classOrMethod ),
+                            nameAndTags,
+                            lineInfo));
+        } CATCH_CATCH_ALL {
+            // Do not throw when constructing global objects, instead register the exception to be processed later
+            getMutableRegistryHub().registerStartupException();
+        }
+    }
+
+    AutoReg::~AutoReg() = default;
+}
+// end catch_test_registry.cpp
+// start catch_test_spec.cpp
+
+#include <algorithm>
+#include <string>
+#include <vector>
+#include <memory>
+
+namespace Catch {
+
+    TestSpec::Pattern::~Pattern() = default;
+    TestSpec::NamePattern::~NamePattern() = default;
+    TestSpec::TagPattern::~TagPattern() = default;
+    TestSpec::ExcludedPattern::~ExcludedPattern() = default;
+
+    TestSpec::NamePattern::NamePattern( std::string const& name )
+    : m_wildcardPattern( toLower( name ), CaseSensitive::No )
+    {}
+    bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const {
+        return m_wildcardPattern.matches( toLower( testCase.name ) );
+    }
+
+    TestSpec::TagPattern::TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
+    bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const {
+        return std::find(begin(testCase.lcaseTags),
+                         end(testCase.lcaseTags),
+                         m_tag) != end(testCase.lcaseTags);
+    }
+
+    TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
+    bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
+
+    bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const {
+        // All patterns in a filter must match for the filter to be a match
+        for( auto const& pattern : m_patterns ) {
+            if( !pattern->matches( testCase ) )
+                return false;
+        }
+        return true;
+    }
+
+    bool TestSpec::hasFilters() const {
+        return !m_filters.empty();
+    }
+    bool TestSpec::matches( TestCaseInfo const& testCase ) const {
+        // A TestSpec matches if any filter matches
+        for( auto const& filter : m_filters )
+            if( filter.matches( testCase ) )
+                return true;
+        return false;
+    }
+}
+// end catch_test_spec.cpp
+// start catch_test_spec_parser.cpp
+
+namespace Catch {
+
+    TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
+
+    TestSpecParser& TestSpecParser::parse( std::string const& arg ) {
+        m_mode = None;
+        m_exclusion = false;
+        m_start = std::string::npos;
+        m_arg = m_tagAliases->expandAliases( arg );
+        m_escapeChars.clear();
+        for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
+            visitChar( m_arg[m_pos] );
+        if( m_mode == Name )
+            addPattern<TestSpec::NamePattern>();
+        return *this;
+    }
+    TestSpec TestSpecParser::testSpec() {
+        addFilter();
+        return m_testSpec;
+    }
+
+    void TestSpecParser::visitChar( char c ) {
+        if( m_mode == None ) {
+            switch( c ) {
+            case ' ': return;
+            case '~': m_exclusion = true; return;
+            case '[': return startNewMode( Tag, ++m_pos );
+            case '"': return startNewMode( QuotedName, ++m_pos );
+            case '\\': return escape();
+            default: startNewMode( Name, m_pos ); break;
+            }
+        }
+        if( m_mode == Name ) {
+            if( c == ',' ) {
+                addPattern<TestSpec::NamePattern>();
+                addFilter();
+            }
+            else if( c == '[' ) {
+                if( subString() == "exclude:" )
+                    m_exclusion = true;
+                else
+                    addPattern<TestSpec::NamePattern>();
+                startNewMode( Tag, ++m_pos );
+            }
+            else if( c == '\\' )
+                escape();
+        }
+        else if( m_mode == EscapedName )
+            m_mode = Name;
+        else if( m_mode == QuotedName && c == '"' )
+            addPattern<TestSpec::NamePattern>();
+        else if( m_mode == Tag && c == ']' )
+            addPattern<TestSpec::TagPattern>();
+    }
+    void TestSpecParser::startNewMode( Mode mode, std::size_t start ) {
+        m_mode = mode;
+        m_start = start;
+    }
+    void TestSpecParser::escape() {
+        if( m_mode == None )
+            m_start = m_pos;
+        m_mode = EscapedName;
+        m_escapeChars.push_back( m_pos );
+    }
+    std::string TestSpecParser::subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
+
+    void TestSpecParser::addFilter() {
+        if( !m_currentFilter.m_patterns.empty() ) {
+            m_testSpec.m_filters.push_back( m_currentFilter );
+            m_currentFilter = TestSpec::Filter();
+        }
+    }
+
+    TestSpec parseTestSpec( std::string const& arg ) {
+        return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
+    }
+
+} // namespace Catch
+// end catch_test_spec_parser.cpp
+// start catch_timer.cpp
+
+#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();
+    }
+
+    namespace {
+        auto estimateClockResolution() -> uint64_t {
+            uint64_t sum = 0;
+            static const uint64_t iterations = 1000000;
+
+            auto startTime = 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;
+                }
+            }
+
+            // 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();
+        return s_resolution;
+    }
+
+    void Timer::start() {
+       m_nanoseconds = getCurrentNanosecondsSinceEpoch();
+    }
+    auto Timer::getElapsedNanoseconds() const -> uint64_t {
+        return getCurrentNanosecondsSinceEpoch() - m_nanoseconds;
+    }
+    auto Timer::getElapsedMicroseconds() const -> uint64_t {
+        return getElapsedNanoseconds()/1000;
+    }
+    auto Timer::getElapsedMilliseconds() const -> unsigned int {
+        return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
+    }
+    auto Timer::getElapsedSeconds() const -> double {
+        return getElapsedMicroseconds()/1000000.0;
+    }
+
+} // namespace Catch
+// end catch_timer.cpp
+// start catch_tostring.cpp
+
+#if defined(__clang__)
+#    pragma clang diagnostic push
+#    pragma clang diagnostic ignored "-Wexit-time-destructors"
+#    pragma clang diagnostic ignored "-Wglobal-constructors"
+#endif
+
+// Enable specific decls locally
+#if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
+#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
+#endif
+
+#include <cmath>
+#include <iomanip>
+
+namespace Catch {
+
+namespace Detail {
+
+    const std::string unprintableString = "{?}";
+
+    namespace {
+        const int hexThreshold = 255;
+
+        struct Endianness {
+            enum Arch { Big, Little };
+
+            static Arch which() {
+                union _{
+                    int asInt;
+                    char asChar[sizeof (int)];
+                } u;
+
+                u.asInt = 1;
+                return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;
+            }
+        };
+    }
+
+    std::string rawMemoryToString( const void *object, std::size_t size ) {
+        // Reverse order for little endian architectures
+        int i = 0, end = static_cast<int>( size ), inc = 1;
+        if( Endianness::which() == Endianness::Little ) {
+            i = end-1;
+            end = inc = -1;
+        }
+
+        unsigned char const *bytes = static_cast<unsigned char const *>(object);
+        ReusableStringStream rss;
+        rss << "0x" << std::setfill('0') << std::hex;
+        for( ; i != end; i += inc )
+             rss << std::setw(2) << static_cast<unsigned>(bytes[i]);
+       return rss.str();
+    }
+}
+
+template<typename T>
+std::string fpToString( T value, int precision ) {
+    if (Catch::isnan(value)) {
+        return "nan";
+    }
+
+    ReusableStringStream rss;
+    rss << std::setprecision( precision )
+        << std::fixed
+        << value;
+    std::string d = rss.str();
+    std::size_t i = d.find_last_not_of( '0' );
+    if( i != std::string::npos && i != d.size()-1 ) {
+        if( d[i] == '.' )
+            i++;
+        d = d.substr( 0, i+1 );
+    }
+    return d;
+}
+
+//// ======================================================= ////
+//
+//   Out-of-line defs for full specialization of StringMaker
+//
+//// ======================================================= ////
+
+std::string StringMaker<std::string>::convert(const std::string& str) {
+    if (!getCurrentContext().getConfig()->showInvisibles()) {
+        return '"' + str + '"';
+    }
+
+    std::string s("\"");
+    for (char c : str) {
+        switch (c) {
+        case '\n':
+            s.append("\\n");
+            break;
+        case '\t':
+            s.append("\\t");
+            break;
+        default:
+            s.push_back(c);
+            break;
+        }
+    }
+    s.append("\"");
+    return 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) {
+        return ::Catch::Detail::stringify(std::string{ str });
+    } else {
+        return{ "{null string}" };
+    }
+}
+std::string StringMaker<char*>::convert(char* str) {
+    if (str) {
+        return ::Catch::Detail::stringify(std::string{ str });
+    } else {
+        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 });
+    } else {
+        return{ "{null string}" };
+    }
+}
+std::string StringMaker<wchar_t *>::convert(wchar_t * str) {
+    if (str) {
+        return ::Catch::Detail::stringify(std::wstring{ str });
+    } else {
+        return{ "{null string}" };
+    }
+}
+#endif
+
+std::string StringMaker<int>::convert(int value) {
+    return ::Catch::Detail::stringify(static_cast<long long>(value));
+}
+std::string StringMaker<long>::convert(long value) {
+    return ::Catch::Detail::stringify(static_cast<long long>(value));
+}
+std::string StringMaker<long long>::convert(long long value) {
+    ReusableStringStream rss;
+    rss << value;
+    if (value > Detail::hexThreshold) {
+        rss << " (0x" << std::hex << value << ')';
+    }
+    return rss.str();
+}
+
+std::string StringMaker<unsigned int>::convert(unsigned int value) {
+    return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
+}
+std::string StringMaker<unsigned long>::convert(unsigned long value) {
+    return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
+}
+std::string StringMaker<unsigned long long>::convert(unsigned long long value) {
+    ReusableStringStream rss;
+    rss << value;
+    if (value > Detail::hexThreshold) {
+        rss << " (0x" << std::hex << value << ')';
+    }
+    return rss.str();
+}
+
+std::string StringMaker<bool>::convert(bool b) {
+    return b ? "true" : "false";
+}
+
+std::string StringMaker<signed char>::convert(signed char value) {
+    if (value == '\r') {
+        return "'\\r'";
+    } else if (value == '\f') {
+        return "'\\f'";
+    } else if (value == '\n') {
+        return "'\\n'";
+    } else if (value == '\t') {
+        return "'\\t'";
+    } else if ('\0' <= value && value < ' ') {
+        return ::Catch::Detail::stringify(static_cast<unsigned int>(value));
+    } else {
+        char chstr[] = "' '";
+        chstr[1] = value;
+        return chstr;
+    }
+}
+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));
+}
+
+std::string StringMaker<std::nullptr_t>::convert(std::nullptr_t) {
+    return "nullptr";
+}
+
+std::string StringMaker<float>::convert(float value) {
+    return fpToString(value, 5) + 'f';
+}
+std::string StringMaker<double>::convert(double value) {
+    return fpToString(value, 10);
+}
+
+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::micro>::symbol() { return "u"; }
+std::string ratio_string<std::milli>::symbol() { return "m"; }
+
+} // end namespace Catch
+
+#if defined(__clang__)
+#    pragma clang diagnostic pop
+#endif
+
+// end catch_tostring.cpp
+// start catch_totals.cpp
+
+namespace Catch {
+
+    Counts Counts::operator - ( Counts const& other ) const {
+        Counts diff;
+        diff.passed = passed - other.passed;
+        diff.failed = failed - other.failed;
+        diff.failedButOk = failedButOk - other.failedButOk;
+        return diff;
+    }
+
+    Counts& Counts::operator += ( Counts const& other ) {
+        passed += other.passed;
+        failed += other.failed;
+        failedButOk += other.failedButOk;
+        return *this;
+    }
+
+    std::size_t Counts::total() const {
+        return passed + failed + failedButOk;
+    }
+    bool Counts::allPassed() const {
+        return failed == 0 && failedButOk == 0;
+    }
+    bool Counts::allOk() const {
+        return failed == 0;
+    }
+
+    Totals Totals::operator - ( Totals const& other ) const {
+        Totals diff;
+        diff.assertions = assertions - other.assertions;
+        diff.testCases = testCases - other.testCases;
+        return diff;
+    }
+
+    Totals& Totals::operator += ( Totals const& other ) {
+        assertions += other.assertions;
+        testCases += other.testCases;
+        return *this;
+    }
+
+    Totals Totals::delta( Totals const& prevTotals ) const {
+        Totals diff = *this - prevTotals;
+        if( diff.assertions.failed > 0 )
+            ++diff.testCases.failed;
+        else if( diff.assertions.failedButOk > 0 )
+            ++diff.testCases.failedButOk;
+        else
+            ++diff.testCases.passed;
+        return diff;
+    }
+
+}
+// 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>
+
+namespace Catch {
+
+    Version::Version
+        (   unsigned int _majorVersion,
+            unsigned int _minorVersion,
+            unsigned int _patchNumber,
+            char const * const _branchName,
+            unsigned int _buildNumber )
+    :   majorVersion( _majorVersion ),
+        minorVersion( _minorVersion ),
+        patchNumber( _patchNumber ),
+        branchName( _branchName ),
+        buildNumber( _buildNumber )
+    {}
+
+    std::ostream& operator << ( std::ostream& os, Version const& version ) {
+        os  << version.majorVersion << '.'
+            << version.minorVersion << '.'
+            << version.patchNumber;
+        // branchName is never null -> 0th char is \0 if it is empty
+        if (version.branchName[0]) {
+            os << '-' << version.branchName
+               << '.' << version.buildNumber;
+        }
+        return os;
+    }
+
+    Version const& libraryVersion() {
+        static Version version( 2, 5, 0, "", 0 );
+        return version;
+    }
+
+}
+// end catch_version.cpp
+// start catch_wildcard_pattern.cpp
+
+#include <sstream>
+
+namespace Catch {
+
+    WildcardPattern::WildcardPattern( std::string const& pattern,
+                                      CaseSensitive::Choice caseSensitivity )
+    :   m_caseSensitivity( caseSensitivity ),
+        m_pattern( adjustCase( pattern ) )
+    {
+        if( startsWith( m_pattern, '*' ) ) {
+            m_pattern = m_pattern.substr( 1 );
+            m_wildcard = WildcardAtStart;
+        }
+        if( endsWith( m_pattern, '*' ) ) {
+            m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
+            m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
+        }
+    }
+
+    bool WildcardPattern::matches( std::string const& str ) const {
+        switch( m_wildcard ) {
+            case NoWildcard:
+                return m_pattern == adjustCase( str );
+            case WildcardAtStart:
+                return endsWith( adjustCase( str ), m_pattern );
+            case WildcardAtEnd:
+                return startsWith( adjustCase( str ), m_pattern );
+            case WildcardAtBothEnds:
+                return contains( adjustCase( str ), m_pattern );
+            default:
+                CATCH_INTERNAL_ERROR( "Unknown enum" );
+        }
+    }
+
+    std::string WildcardPattern::adjustCase( std::string const& str ) const {
+        return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str;
+    }
+}
+// end catch_wildcard_pattern.cpp
+// start catch_xmlwriter.cpp
+
+#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) {
+        os << "\\x"
+            << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
+            << static_cast<int>(c);
+    }
+
+} // 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 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 (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;
+                }
+
+                // Plain ASCII: Write it to stream
+                if (c < 0x7F) {
+                    os << c;
+                    break;
+                }
+
+                // 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;
+            }
+        }
+    }
+
+    std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
+        xmlEncode.encodeTo( os );
+        return os;
+    }
+
+    XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer )
+    :   m_writer( writer )
+    {}
+
+    XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept
+    :   m_writer( other.m_writer ){
+        other.m_writer = nullptr;
+    }
+    XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept {
+        if ( m_writer ) {
+            m_writer->endElement();
+        }
+        m_writer = other.m_writer;
+        other.m_writer = nullptr;
+        return *this;
+    }
+
+    XmlWriter::ScopedElement::~ScopedElement() {
+        if( m_writer )
+            m_writer->endElement();
+    }
+
+    XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) {
+        m_writer->writeText( text, indent );
+        return *this;
+    }
+
+    XmlWriter::XmlWriter( std::ostream& os ) : m_os( os )
+    {
+        writeDeclaration();
+    }
+
+    XmlWriter::~XmlWriter() {
+        while( !m_tags.empty() )
+            endElement();
+    }
+
+    XmlWriter& XmlWriter::startElement( std::string const& name ) {
+        ensureTagClosed();
+        newlineIfNecessary();
+        m_os << m_indent << '<' << name;
+        m_tags.push_back( name );
+        m_indent += "  ";
+        m_tagIsOpen = true;
+        return *this;
+    }
+
+    XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) {
+        ScopedElement scoped( this );
+        startElement( name );
+        return scoped;
+    }
+
+    XmlWriter& XmlWriter::endElement() {
+        newlineIfNecessary();
+        m_indent = m_indent.substr( 0, m_indent.size()-2 );
+        if( m_tagIsOpen ) {
+            m_os << "/>";
+            m_tagIsOpen = false;
+        }
+        else {
+            m_os << m_indent << "</" << m_tags.back() << ">";
+        }
+        m_os << std::endl;
+        m_tags.pop_back();
+        return *this;
+    }
+
+    XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) {
+        if( !name.empty() && !attribute.empty() )
+            m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
+        return *this;
+    }
+
+    XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) {
+        m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
+        return *this;
+    }
+
+    XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) {
+        if( !text.empty() ){
+            bool tagWasOpen = m_tagIsOpen;
+            ensureTagClosed();
+            if( tagWasOpen && indent )
+                m_os << m_indent;
+            m_os << XmlEncode( text );
+            m_needsNewline = true;
+        }
+        return *this;
+    }
+
+    XmlWriter& XmlWriter::writeComment( std::string const& text ) {
+        ensureTagClosed();
+        m_os << m_indent << "<!--" << text << "-->";
+        m_needsNewline = true;
+        return *this;
+    }
+
+    void XmlWriter::writeStylesheetRef( std::string const& url ) {
+        m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n";
+    }
+
+    XmlWriter& XmlWriter::writeBlankLine() {
+        ensureTagClosed();
+        m_os << '\n';
+        return *this;
+    }
+
+    void XmlWriter::ensureTagClosed() {
+        if( m_tagIsOpen ) {
+            m_os << ">" << std::endl;
+            m_tagIsOpen = false;
+        }
+    }
+
+    void XmlWriter::writeDeclaration() {
+        m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+    }
+
+    void XmlWriter::newlineIfNecessary() {
+        if( m_needsNewline ) {
+            m_os << std::endl;
+            m_needsNewline = false;
+        }
+    }
+}
+// end catch_xmlwriter.cpp
+// start catch_reporter_bases.cpp
+
+#include <cstring>
+#include <cfloat>
+#include <cstdio>
+#include <cassert>
+#include <memory>
+
+namespace Catch {
+    void prepareExpandedExpression(AssertionResult& result) {
+        result.getExpandedExpression();
+    }
+
+    // Because formatting using c++ streams is stateful, drop down to C is required
+    // Alternatively we could use stringstream, but its performance is... not good.
+    std::string getFormattedDuration( double duration ) {
+        // Max exponent + 1 is required to represent the whole part
+        // + 1 for decimal point
+        // + 3 for the 3 decimal places
+        // + 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);
+#endif
+        return std::string(buffer);
+    }
+
+    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 &) {
+        return false;
+    }
+
+} // end namespace Catch
+// end catch_reporter_bases.cpp
+// start catch_reporter_compact.cpp
+
+namespace {
+
+#ifdef CATCH_PLATFORM_MAC
+    const char* failedString() { return "FAILED"; }
+    const char* passedString() { return "PASSED"; }
+#else
+    const char* failedString() { return "failed"; }
+    const char* passedString() { return "passed"; }
+#endif
+
+    // Colour::LightGrey
+    Catch::Colour::Code dimColour() { return Catch::Colour::FileName; }
+
+    std::string bothOrAll( std::size_t count ) {
+        return count == 1 ? std::string() :
+               count == 2 ? "both " : "all " ;
+    }
+
+} // anon namespace
+
+namespace Catch {
+namespace {
+// Colour, message variants:
+// - white: No tests ran.
+// -   red: Failed [both/all] N test cases, failed [both/all] M assertions.
+// - white: Passed [both/all] N test cases (no assertions).
+// -   red: Failed N tests cases, failed M assertions.
+// - green: Passed [both/all] N tests cases with M assertions.
+void printTotals(std::ostream& out, const Totals& totals) {
+    if (totals.testCases.total() == 0) {
+        out << "No tests ran.";
+    } else if (totals.testCases.failed == totals.testCases.total()) {
+        Colour colour(Colour::ResultError);
+        const std::string qualify_assertions_failed =
+            totals.assertions.failed == totals.assertions.total() ?
+            bothOrAll(totals.assertions.failed) : std::string();
+        out <<
+            "Failed " << bothOrAll(totals.testCases.failed)
+            << pluralise(totals.testCases.failed, "test case") << ", "
+            "failed " << qualify_assertions_failed <<
+            pluralise(totals.assertions.failed, "assertion") << '.';
+    } else if (totals.assertions.total() == 0) {
+        out <<
+            "Passed " << bothOrAll(totals.testCases.total())
+            << pluralise(totals.testCases.total(), "test case")
+            << " (no assertions).";
+    } else if (totals.assertions.failed) {
+        Colour colour(Colour::ResultError);
+        out <<
+            "Failed " << pluralise(totals.testCases.failed, "test case") << ", "
+            "failed " << pluralise(totals.assertions.failed, "assertion") << '.';
+    } else {
+        Colour colour(Colour::ResultSuccess);
+        out <<
+            "Passed " << bothOrAll(totals.testCases.passed)
+            << pluralise(totals.testCases.passed, "test case") <<
+            " with " << pluralise(totals.assertions.passed, "assertion") << '.';
+    }
+}
+
+// Implementation of CompactReporter formatting
+class AssertionPrinter {
+public:
+    AssertionPrinter& operator= (AssertionPrinter const&) = delete;
+    AssertionPrinter(AssertionPrinter const&) = delete;
+    AssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages)
+        : stream(_stream)
+        , result(_stats.assertionResult)
+        , messages(_stats.infoMessages)
+        , itMessage(_stats.infoMessages.begin())
+        , printInfoMessages(_printInfoMessages) {}
+
+    void print() {
+        printSourceInfo();
+
+        itMessage = messages.begin();
+
+        switch (result.getResultType()) {
+        case ResultWas::Ok:
+            printResultType(Colour::ResultSuccess, passedString());
+            printOriginalExpression();
+            printReconstructedExpression();
+            if (!result.hasExpression())
+                printRemainingMessages(Colour::None);
+            else
+                printRemainingMessages();
+            break;
+        case ResultWas::ExpressionFailed:
+            if (result.isOk())
+                printResultType(Colour::ResultSuccess, failedString() + std::string(" - but was ok"));
+            else
+                printResultType(Colour::Error, failedString());
+            printOriginalExpression();
+            printReconstructedExpression();
+            printRemainingMessages();
+            break;
+        case ResultWas::ThrewException:
+            printResultType(Colour::Error, failedString());
+            printIssue("unexpected exception with message:");
+            printMessage();
+            printExpressionWas();
+            printRemainingMessages();
+            break;
+        case ResultWas::FatalErrorCondition:
+            printResultType(Colour::Error, failedString());
+            printIssue("fatal error condition with message:");
+            printMessage();
+            printExpressionWas();
+            printRemainingMessages();
+            break;
+        case ResultWas::DidntThrowException:
+            printResultType(Colour::Error, failedString());
+            printIssue("expected exception, got none");
+            printExpressionWas();
+            printRemainingMessages();
+            break;
+        case ResultWas::Info:
+            printResultType(Colour::None, "info");
+            printMessage();
+            printRemainingMessages();
+            break;
+        case ResultWas::Warning:
+            printResultType(Colour::None, "warning");
+            printMessage();
+            printRemainingMessages();
+            break;
+        case ResultWas::ExplicitFailure:
+            printResultType(Colour::Error, failedString());
+            printIssue("explicitly");
+            printRemainingMessages(Colour::None);
+            break;
+            // These cases are here to prevent compiler warnings
+        case ResultWas::Unknown:
+        case ResultWas::FailureBit:
+        case ResultWas::Exception:
+            printResultType(Colour::Error, "** internal error **");
+            break;
+        }
+    }
+
+private:
+    void printSourceInfo() const {
+        Colour colourGuard(Colour::FileName);
+        stream << result.getSourceInfo() << ':';
+    }
+
+    void printResultType(Colour::Code colour, std::string const& passOrFail) const {
+        if (!passOrFail.empty()) {
+            {
+                Colour colourGuard(colour);
+                stream << ' ' << passOrFail;
+            }
+            stream << ':';
+        }
+    }
+
+    void printIssue(std::string const& issue) const {
+        stream << ' ' << issue;
+    }
+
+    void printExpressionWas() {
+        if (result.hasExpression()) {
+            stream << ';';
+            {
+                Colour colour(dimColour());
+                stream << " expression was:";
+            }
+            printOriginalExpression();
+        }
+    }
+
+    void printOriginalExpression() const {
+        if (result.hasExpression()) {
+            stream << ' ' << result.getExpression();
+        }
+    }
+
+    void printReconstructedExpression() const {
+        if (result.hasExpandedExpression()) {
+            {
+                Colour colour(dimColour());
+                stream << " for: ";
+            }
+            stream << result.getExpandedExpression();
+        }
+    }
+
+    void printMessage() {
+        if (itMessage != messages.end()) {
+            stream << " '" << itMessage->message << '\'';
+            ++itMessage;
+        }
+    }
+
+    void printRemainingMessages(Colour::Code colour = dimColour()) {
+        if (itMessage == messages.end())
+            return;
+
+        // using messages.end() directly yields (or auto) compilation error:
+        std::vector<MessageInfo>::const_iterator itEnd = messages.end();
+        const std::size_t N = static_cast<std::size_t>(std::distance(itMessage, itEnd));
+
+        {
+            Colour colourGuard(colour);
+            stream << " with " << pluralise(N, "message") << ':';
+        }
+
+        for (; itMessage != itEnd; ) {
+            // If this assertion is a warning ignore any INFO messages
+            if (printInfoMessages || itMessage->type != ResultWas::Info) {
+                stream << " '" << itMessage->message << '\'';
+                if (++itMessage != itEnd) {
+                    Colour colourGuard(dimColour());
+                    stream << " and";
+                }
+            }
+        }
+    }
+
+private:
+    std::ostream& stream;
+    AssertionResult const& result;
+    std::vector<MessageInfo> messages;
+    std::vector<MessageInfo>::const_iterator itMessage;
+    bool printInfoMessages;
+};
+
+} // anon namespace
+
+        std::string CompactReporter::getDescription() {
+            return "Reports test results on a single line, suitable for IDEs";
+        }
+
+        ReporterPreferences CompactReporter::getPreferences() const {
+            return m_reporterPrefs;
+        }
+
+        void CompactReporter::noMatchingTestCases( std::string const& spec ) {
+            stream << "No test cases matched '" << spec << '\'' << std::endl;
+        }
+
+        void CompactReporter::assertionStarting( AssertionInfo const& ) {}
+
+        bool CompactReporter::assertionEnded( AssertionStats const& _assertionStats ) {
+            AssertionResult const& result = _assertionStats.assertionResult;
+
+            bool printInfoMessages = true;
+
+            // Drop out if result was successful and we're not printing those
+            if( !m_config->includeSuccessfulResults() && result.isOk() ) {
+                if( result.getResultType() != ResultWas::Warning )
+                    return false;
+                printInfoMessages = false;
+            }
+
+            AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
+            printer.print();
+
+            stream << std::endl;
+            return true;
+        }
+
+        void CompactReporter::sectionEnded(SectionStats const& _sectionStats) {
+            if (m_config->showDurations() == ShowDurations::Always) {
+                stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
+            }
+        }
+
+        void CompactReporter::testRunEnded( TestRunStats const& _testRunStats ) {
+            printTotals( stream, _testRunStats.totals );
+            stream << '\n' << std::endl;
+            StreamingReporterBase::testRunEnded( _testRunStats );
+        }
+
+        CompactReporter::~CompactReporter() {}
+
+    CATCH_REGISTER_REPORTER( "compact", CompactReporter )
+
+} // end namespace Catch
+// end catch_reporter_compact.cpp
+// start catch_reporter_console.cpp
+
+#include <cfloat>
+#include <cstdio>
+
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch
+ // Note that 4062 (not all labels are handled
+ // and default is missing) is enabled
+#endif
+
+namespace Catch {
+
+namespace {
+
+// Formatter impl for ConsoleReporter
+class ConsoleAssertionPrinter {
+public:
+    ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter const&) = delete;
+    ConsoleAssertionPrinter(ConsoleAssertionPrinter const&) = delete;
+    ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages)
+        : stream(_stream),
+        stats(_stats),
+        result(_stats.assertionResult),
+        colour(Colour::None),
+        message(result.getMessage()),
+        messages(_stats.infoMessages),
+        printInfoMessages(_printInfoMessages) {
+        switch (result.getResultType()) {
+        case ResultWas::Ok:
+            colour = Colour::Success;
+            passOrFail = "PASSED";
+            //if( result.hasMessage() )
+            if (_stats.infoMessages.size() == 1)
+                messageLabel = "with message";
+            if (_stats.infoMessages.size() > 1)
+                messageLabel = "with messages";
+            break;
+        case ResultWas::ExpressionFailed:
+            if (result.isOk()) {
+                colour = Colour::Success;
+                passOrFail = "FAILED - but was ok";
+            } else {
+                colour = Colour::Error;
+                passOrFail = "FAILED";
+            }
+            if (_stats.infoMessages.size() == 1)
+                messageLabel = "with message";
+            if (_stats.infoMessages.size() > 1)
+                messageLabel = "with messages";
+            break;
+        case ResultWas::ThrewException:
+            colour = Colour::Error;
+            passOrFail = "FAILED";
+            messageLabel = "due to unexpected exception with ";
+            if (_stats.infoMessages.size() == 1)
+                messageLabel += "message";
+            if (_stats.infoMessages.size() > 1)
+                messageLabel += "messages";
+            break;
+        case ResultWas::FatalErrorCondition:
+            colour = Colour::Error;
+            passOrFail = "FAILED";
+            messageLabel = "due to a fatal error condition";
+            break;
+        case ResultWas::DidntThrowException:
+            colour = Colour::Error;
+            passOrFail = "FAILED";
+            messageLabel = "because no exception was thrown where one was expected";
+            break;
+        case ResultWas::Info:
+            messageLabel = "info";
+            break;
+        case ResultWas::Warning:
+            messageLabel = "warning";
+            break;
+        case ResultWas::ExplicitFailure:
+            passOrFail = "FAILED";
+            colour = Colour::Error;
+            if (_stats.infoMessages.size() == 1)
+                messageLabel = "explicitly with message";
+            if (_stats.infoMessages.size() > 1)
+                messageLabel = "explicitly with messages";
+            break;
+            // These cases are here to prevent compiler warnings
+        case ResultWas::Unknown:
+        case ResultWas::FailureBit:
+        case ResultWas::Exception:
+            passOrFail = "** internal error **";
+            colour = Colour::Error;
+            break;
+        }
+    }
+
+    void print() const {
+        printSourceInfo();
+        if (stats.totals.assertions.total() > 0) {
+            printResultType();
+            printOriginalExpression();
+            printReconstructedExpression();
+        } else {
+            stream << '\n';
+        }
+        printMessage();
+    }
+
+private:
+    void printResultType() const {
+        if (!passOrFail.empty()) {
+            Colour colourGuard(colour);
+            stream << passOrFail << ":\n";
+        }
+    }
+    void printOriginalExpression() const {
+        if (result.hasExpression()) {
+            Colour colourGuard(Colour::OriginalExpression);
+            stream << "  ";
+            stream << result.getExpressionInMacro();
+            stream << '\n';
+        }
+    }
+    void printReconstructedExpression() const {
+        if (result.hasExpandedExpression()) {
+            stream << "with expansion:\n";
+            Colour colourGuard(Colour::ReconstructedExpression);
+            stream << Column(result.getExpandedExpression()).indent(2) << '\n';
+        }
+    }
+    void printMessage() const {
+        if (!messageLabel.empty())
+            stream << messageLabel << ':' << '\n';
+        for (auto const& msg : messages) {
+            // If this assertion is a warning ignore any INFO messages
+            if (printInfoMessages || msg.type != ResultWas::Info)
+                stream << Column(msg.message).indent(2) << '\n';
+        }
+    }
+    void printSourceInfo() const {
+        Colour colourGuard(Colour::FileName);
+        stream << result.getSourceInfo() << ": ";
+    }
+
+    std::ostream& stream;
+    AssertionStats const& stats;
+    AssertionResult const& result;
+    Colour::Code colour;
+    std::string passOrFail;
+    std::string messageLabel;
+    std::string message;
+    std::vector<MessageInfo> messages;
+    bool printInfoMessages;
+};
+
+std::size_t makeRatio(std::size_t number, std::size_t total) {
+    std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0;
+    return (ratio == 0 && number > 0) ? 1 : ratio;
+}
+
+std::size_t& findMax(std::size_t& i, std::size_t& j, std::size_t& k) {
+    if (i > j && i > k)
+        return i;
+    else if (j > k)
+        return j;
+    else
+        return k;
+}
+
+struct ColumnInfo {
+    enum Justification { Left, Right };
+    std::string name;
+    int width;
+    Justification justification;
+};
+struct ColumnBreak {};
+struct RowBreak {};
+
+class Duration {
+    enum class Unit {
+        Auto,
+        Nanoseconds,
+        Microseconds,
+        Milliseconds,
+        Seconds,
+        Minutes
+    };
+    static const uint64_t s_nanosecondsInAMicrosecond = 1000;
+    static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond;
+    static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;
+    static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;
+
+    uint64_t m_inNanoseconds;
+    Unit m_units;
+
+public:
+    explicit Duration(uint64_t inNanoseconds, Unit units = Unit::Auto)
+        : m_inNanoseconds(inNanoseconds),
+        m_units(units) {
+        if (m_units == Unit::Auto) {
+            if (m_inNanoseconds < s_nanosecondsInAMicrosecond)
+                m_units = Unit::Nanoseconds;
+            else if (m_inNanoseconds < s_nanosecondsInAMillisecond)
+                m_units = Unit::Microseconds;
+            else if (m_inNanoseconds < s_nanosecondsInASecond)
+                m_units = Unit::Milliseconds;
+            else if (m_inNanoseconds < s_nanosecondsInAMinute)
+                m_units = Unit::Seconds;
+            else
+                m_units = Unit::Minutes;
+        }
+
+    }
+
+    auto value() const -> double {
+        switch (m_units) {
+        case Unit::Microseconds:
+            return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMicrosecond);
+        case Unit::Milliseconds:
+            return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMillisecond);
+        case Unit::Seconds:
+            return m_inNanoseconds / static_cast<double>(s_nanosecondsInASecond);
+        case Unit::Minutes:
+            return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMinute);
+        default:
+            return static_cast<double>(m_inNanoseconds);
+        }
+    }
+    auto unitsAsString() const -> std::string {
+        switch (m_units) {
+        case Unit::Nanoseconds:
+            return "ns";
+        case Unit::Microseconds:
+            return "µs";
+        case Unit::Milliseconds:
+            return "ms";
+        case Unit::Seconds:
+            return "s";
+        case Unit::Minutes:
+            return "m";
+        default:
+            return "** internal error **";
+        }
+
+    }
+    friend auto operator << (std::ostream& os, Duration const& duration) -> std::ostream& {
+        return os << duration.value() << " " << duration.unitsAsString();
+    }
+};
+} // end anon namespace
+
+class TablePrinter {
+    std::ostream& m_os;
+    std::vector<ColumnInfo> m_columnInfos;
+    std::ostringstream m_oss;
+    int m_currentColumn = -1;
+    bool m_isOpen = false;
+
+public:
+    TablePrinter( std::ostream& os, std::vector<ColumnInfo> columnInfos )
+    :   m_os( os ),
+        m_columnInfos( std::move( columnInfos ) ) {}
+
+    auto columnInfos() const -> std::vector<ColumnInfo> const& {
+        return m_columnInfos;
+    }
+
+    void open() {
+        if (!m_isOpen) {
+            m_isOpen = true;
+            *this << RowBreak();
+            for (auto const& info : m_columnInfos)
+                *this << info.name << ColumnBreak();
+            *this << RowBreak();
+            m_os << Catch::getLineOfChars<'-'>() << "\n";
+        }
+    }
+    void close() {
+        if (m_isOpen) {
+            *this << RowBreak();
+            m_os << std::endl;
+            m_isOpen = false;
+        }
+    }
+
+    template<typename T>
+    friend TablePrinter& operator << (TablePrinter& tp, T const& value) {
+        tp.m_oss << value;
+        return tp;
+    }
+
+    friend TablePrinter& operator << (TablePrinter& tp, ColumnBreak) {
+        auto colStr = tp.m_oss.str();
+        // This takes account of utf8 encodings
+        auto strSize = Catch::StringRef(colStr).numberOfCharacters();
+        tp.m_oss.str("");
+        tp.open();
+        if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) {
+            tp.m_currentColumn = -1;
+            tp.m_os << "\n";
+        }
+        tp.m_currentColumn++;
+
+        auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
+        auto padding = (strSize + 2 < static_cast<std::size_t>(colInfo.width))
+            ? std::string(colInfo.width - (strSize + 2), ' ')
+            : std::string();
+        if (colInfo.justification == ColumnInfo::Left)
+            tp.m_os << colStr << padding << " ";
+        else
+            tp.m_os << padding << colStr << " ";
+        return tp;
+    }
+
+    friend TablePrinter& operator << (TablePrinter& tp, RowBreak) {
+        if (tp.m_currentColumn > 0) {
+            tp.m_os << "\n";
+            tp.m_currentColumn = -1;
+        }
+        return tp;
+    }
+};
+
+ConsoleReporter::ConsoleReporter(ReporterConfig const& config)
+    : StreamingReporterBase(config),
+    m_tablePrinter(new TablePrinter(config.stream(),
+    {
+        { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left },
+        { "iters", 8, ColumnInfo::Right },
+        { "elapsed ns", 14, ColumnInfo::Right },
+        { "average", 14, ColumnInfo::Right }
+    })) {}
+ConsoleReporter::~ConsoleReporter() = default;
+
+std::string ConsoleReporter::getDescription() {
+    return "Reports test results as plain lines of text";
+}
+
+void ConsoleReporter::noMatchingTestCases(std::string const& spec) {
+    stream << "No test cases matched '" << spec << '\'' << std::endl;
+}
+
+void ConsoleReporter::assertionStarting(AssertionInfo const&) {}
+
+bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) {
+    AssertionResult const& result = _assertionStats.assertionResult;
+
+    bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
+
+    // Drop out if result was successful but we're not printing them.
+    if (!includeResults && result.getResultType() != ResultWas::Warning)
+        return false;
+
+    lazyPrint();
+
+    ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults);
+    printer.print();
+    stream << std::endl;
+    return true;
+}
+
+void ConsoleReporter::sectionStarting(SectionInfo const& _sectionInfo) {
+    m_headerPrinted = false;
+    StreamingReporterBase::sectionStarting(_sectionInfo);
+}
+void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) {
+    m_tablePrinter->close();
+    if (_sectionStats.missingAssertions) {
+        lazyPrint();
+        Colour colour(Colour::ResultError);
+        if (m_sectionStack.size() > 1)
+            stream << "\nNo assertions in section";
+        else
+            stream << "\nNo assertions in test case";
+        stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
+    }
+    if (m_config->showDurations() == ShowDurations::Always) {
+        stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
+    }
+    if (m_headerPrinted) {
+        m_headerPrinted = false;
+    }
+    StreamingReporterBase::sectionEnded(_sectionStats);
+}
+
+void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) {
+    lazyPrintWithoutClosingBenchmarkTable();
+
+    auto nameCol = Column( info.name ).width( static_cast<std::size_t>( m_tablePrinter->columnInfos()[0].width - 2 ) );
+
+    bool firstLine = true;
+    for (auto line : nameCol) {
+        if (!firstLine)
+            (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak();
+        else
+            firstLine = false;
+
+        (*m_tablePrinter) << line << ColumnBreak();
+    }
+}
+void ConsoleReporter::benchmarkEnded(BenchmarkStats const& stats) {
+    Duration average(stats.elapsedTimeInNanoseconds / stats.iterations);
+    (*m_tablePrinter)
+        << stats.iterations << ColumnBreak()
+        << stats.elapsedTimeInNanoseconds << ColumnBreak()
+        << average << ColumnBreak();
+}
+
+void ConsoleReporter::testCaseEnded(TestCaseStats const& _testCaseStats) {
+    m_tablePrinter->close();
+    StreamingReporterBase::testCaseEnded(_testCaseStats);
+    m_headerPrinted = false;
+}
+void ConsoleReporter::testGroupEnded(TestGroupStats const& _testGroupStats) {
+    if (currentGroupInfo.used) {
+        printSummaryDivider();
+        stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
+        printTotals(_testGroupStats.totals);
+        stream << '\n' << std::endl;
+    }
+    StreamingReporterBase::testGroupEnded(_testGroupStats);
+}
+void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) {
+    printTotalsDivider(_testRunStats.totals);
+    printTotals(_testRunStats.totals);
+    stream << std::endl;
+    StreamingReporterBase::testRunEnded(_testRunStats);
+}
+
+void ConsoleReporter::lazyPrint() {
+
+    m_tablePrinter->close();
+    lazyPrintWithoutClosingBenchmarkTable();
+}
+
+void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() {
+
+    if (!currentTestRunInfo.used)
+        lazyPrintRunInfo();
+    if (!currentGroupInfo.used)
+        lazyPrintGroupInfo();
+
+    if (!m_headerPrinted) {
+        printTestCaseAndSectionHeader();
+        m_headerPrinted = true;
+    }
+}
+void ConsoleReporter::lazyPrintRunInfo() {
+    stream << '\n' << getLineOfChars<'~'>() << '\n';
+    Colour colour(Colour::SecondaryText);
+    stream << currentTestRunInfo->name
+        << " is a Catch v" << libraryVersion() << " host application.\n"
+        << "Run with -? for options\n\n";
+
+    if (m_config->rngSeed() != 0)
+        stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";
+
+    currentTestRunInfo.used = true;
+}
+void ConsoleReporter::lazyPrintGroupInfo() {
+    if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) {
+        printClosedHeader("Group: " + currentGroupInfo->name);
+        currentGroupInfo.used = true;
+    }
+}
+void ConsoleReporter::printTestCaseAndSectionHeader() {
+    assert(!m_sectionStack.empty());
+    printOpenHeader(currentTestCaseInfo->name);
+
+    if (m_sectionStack.size() > 1) {
+        Colour colourGuard(Colour::Headers);
+
+        auto
+            it = m_sectionStack.begin() + 1, // Skip first section (test case)
+            itEnd = m_sectionStack.end();
+        for (; it != itEnd; ++it)
+            printHeaderString(it->name, 2);
+    }
+
+    SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;
+
+    if (!lineInfo.empty()) {
+        stream << getLineOfChars<'-'>() << '\n';
+        Colour colourGuard(Colour::FileName);
+        stream << lineInfo << '\n';
+    }
+    stream << getLineOfChars<'.'>() << '\n' << std::endl;
+}
+
+void ConsoleReporter::printClosedHeader(std::string const& _name) {
+    printOpenHeader(_name);
+    stream << getLineOfChars<'.'>() << '\n';
+}
+void ConsoleReporter::printOpenHeader(std::string const& _name) {
+    stream << getLineOfChars<'-'>() << '\n';
+    {
+        Colour colourGuard(Colour::Headers);
+        printHeaderString(_name);
+    }
+}
+
+// if string has a : in first line will set indent to follow it on
+// subsequent lines
+void ConsoleReporter::printHeaderString(std::string const& _string, std::size_t indent) {
+    std::size_t i = _string.find(": ");
+    if (i != std::string::npos)
+        i += 2;
+    else
+        i = 0;
+    stream << Column(_string).indent(indent + i).initialIndent(indent) << '\n';
+}
+
+struct SummaryColumn {
+
+    SummaryColumn( std::string _label, Colour::Code _colour )
+    :   label( std::move( _label ) ),
+        colour( _colour ) {}
+    SummaryColumn addRow( std::size_t count ) {
+        ReusableStringStream rss;
+        rss << count;
+        std::string row = rss.str();
+        for (auto& oldRow : rows) {
+            while (oldRow.size() < row.size())
+                oldRow = ' ' + oldRow;
+            while (oldRow.size() > row.size())
+                row = ' ' + row;
+        }
+        rows.push_back(row);
+        return *this;
+    }
+
+    std::string label;
+    Colour::Code colour;
+    std::vector<std::string> rows;
+
+};
+
+void ConsoleReporter::printTotals( Totals const& totals ) {
+    if (totals.testCases.total() == 0) {
+        stream << Colour(Colour::Warning) << "No tests ran\n";
+    } else if (totals.assertions.total() > 0 && totals.testCases.allPassed()) {
+        stream << Colour(Colour::ResultSuccess) << "All tests passed";
+        stream << " ("
+            << pluralise(totals.assertions.passed, "assertion") << " in "
+            << pluralise(totals.testCases.passed, "test case") << ')'
+            << '\n';
+    } else {
+
+        std::vector<SummaryColumn> columns;
+        columns.push_back(SummaryColumn("", Colour::None)
+                          .addRow(totals.testCases.total())
+                          .addRow(totals.assertions.total()));
+        columns.push_back(SummaryColumn("passed", Colour::Success)
+                          .addRow(totals.testCases.passed)
+                          .addRow(totals.assertions.passed));
+        columns.push_back(SummaryColumn("failed", Colour::ResultError)
+                          .addRow(totals.testCases.failed)
+                          .addRow(totals.assertions.failed));
+        columns.push_back(SummaryColumn("failed as expected", Colour::ResultExpectedFailure)
+                          .addRow(totals.testCases.failedButOk)
+                          .addRow(totals.assertions.failedButOk));
+
+        printSummaryRow("test cases", columns, 0);
+        printSummaryRow("assertions", columns, 1);
+    }
+}
+void ConsoleReporter::printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row) {
+    for (auto col : cols) {
+        std::string value = col.rows[row];
+        if (col.label.empty()) {
+            stream << label << ": ";
+            if (value != "0")
+                stream << value;
+            else
+                stream << Colour(Colour::Warning) << "- none -";
+        } else if (value != "0") {
+            stream << Colour(Colour::LightGrey) << " | ";
+            stream << Colour(col.colour)
+                << value << ' ' << col.label;
+        }
+    }
+    stream << '\n';
+}
+
+void ConsoleReporter::printTotalsDivider(Totals const& totals) {
+    if (totals.testCases.total() > 0) {
+        std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total());
+        std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total());
+        std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total());
+        while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1)
+            findMax(failedRatio, failedButOkRatio, passedRatio)++;
+        while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1)
+            findMax(failedRatio, failedButOkRatio, passedRatio)--;
+
+        stream << Colour(Colour::Error) << std::string(failedRatio, '=');
+        stream << Colour(Colour::ResultExpectedFailure) << std::string(failedButOkRatio, '=');
+        if (totals.testCases.allPassed())
+            stream << Colour(Colour::ResultSuccess) << std::string(passedRatio, '=');
+        else
+            stream << Colour(Colour::Success) << std::string(passedRatio, '=');
+    } else {
+        stream << Colour(Colour::Warning) << std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1, '=');
+    }
+    stream << '\n';
+}
+void ConsoleReporter::printSummaryDivider() {
+    stream << getLineOfChars<'-'>() << '\n';
+}
+
+CATCH_REGISTER_REPORTER("console", ConsoleReporter)
+
+} // end namespace Catch
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+// end catch_reporter_console.cpp
+// start catch_reporter_junit.cpp
+
+#include <cassert>
+#include <sstream>
+#include <ctime>
+#include <algorithm>
+
+namespace Catch {
+
+    namespace {
+        std::string getCurrentTimestamp() {
+            // Beware, this is not reentrant because of backward compatibility issues
+            // Also, UTC only, again because of backward compatibility (%z is C++11)
+            time_t rawtime;
+            std::time(&rawtime);
+            auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
+
+#ifdef _MSC_VER
+            std::tm timeInfo = {};
+            gmtime_s(&timeInfo, &rawtime);
+#else
+            std::tm* timeInfo;
+            timeInfo = std::gmtime(&rawtime);
+#endif
+
+            char timeStamp[timeStampSize];
+            const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
+
+#ifdef _MSC_VER
+            std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
+#else
+            std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
+#endif
+            return std::string(timeStamp);
+        }
+
+        std::string fileNameTag(const std::vector<std::string> &tags) {
+            auto it = std::find_if(begin(tags),
+                                   end(tags),
+                                   [] (std::string const& tag) {return tag.front() == '#'; });
+            if (it != tags.end())
+                return it->substr(1);
+            return std::string();
+        }
+    } // anonymous namespace
+
+    JunitReporter::JunitReporter( ReporterConfig const& _config )
+        :   CumulativeReporterBase( _config ),
+            xml( _config.stream() )
+        {
+            m_reporterPrefs.shouldRedirectStdOut = true;
+            m_reporterPrefs.shouldReportAllAssertions = true;
+        }
+
+    JunitReporter::~JunitReporter() {}
+
+    std::string JunitReporter::getDescription() {
+        return "Reports test results in an XML format that looks like Ant's junitreport target";
+    }
+
+    void JunitReporter::noMatchingTestCases( std::string const& /*spec*/ ) {}
+
+    void JunitReporter::testRunStarting( TestRunInfo const& runInfo )  {
+        CumulativeReporterBase::testRunStarting( runInfo );
+        xml.startElement( "testsuites" );
+    }
+
+    void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) {
+        suiteTimer.start();
+        stdOutForSuite.clear();
+        stdErrForSuite.clear();
+        unexpectedExceptions = 0;
+        CumulativeReporterBase::testGroupStarting( groupInfo );
+    }
+
+    void JunitReporter::testCaseStarting( TestCaseInfo const& testCaseInfo ) {
+        m_okToFail = testCaseInfo.okToFail();
+    }
+
+    bool JunitReporter::assertionEnded( AssertionStats const& assertionStats ) {
+        if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail )
+            unexpectedExceptions++;
+        return CumulativeReporterBase::assertionEnded( assertionStats );
+    }
+
+    void JunitReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
+        stdOutForSuite += testCaseStats.stdOut;
+        stdErrForSuite += testCaseStats.stdErr;
+        CumulativeReporterBase::testCaseEnded( testCaseStats );
+    }
+
+    void JunitReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {
+        double suiteTime = suiteTimer.getElapsedSeconds();
+        CumulativeReporterBase::testGroupEnded( testGroupStats );
+        writeGroup( *m_testGroups.back(), suiteTime );
+    }
+
+    void JunitReporter::testRunEndedCumulative() {
+        xml.endElement();
+    }
+
+    void JunitReporter::writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
+        XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
+        TestGroupStats const& stats = groupNode.value;
+        xml.writeAttribute( "name", stats.groupInfo.name );
+        xml.writeAttribute( "errors", unexpectedExceptions );
+        xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions );
+        xml.writeAttribute( "tests", stats.totals.assertions.total() );
+        xml.writeAttribute( "hostname", "tbd" ); // !TBD
+        if( m_config->showDurations() == ShowDurations::Never )
+            xml.writeAttribute( "time", "" );
+        else
+            xml.writeAttribute( "time", suiteTime );
+        xml.writeAttribute( "timestamp", getCurrentTimestamp() );
+
+        // Write test cases
+        for( auto const& child : groupNode.children )
+            writeTestCase( *child );
+
+        xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), false );
+        xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), false );
+    }
+
+    void JunitReporter::writeTestCase( TestCaseNode const& testCaseNode ) {
+        TestCaseStats const& stats = testCaseNode.value;
+
+        // All test cases have exactly one section - which represents the
+        // test case itself. That section may have 0-n nested sections
+        assert( testCaseNode.children.size() == 1 );
+        SectionNode const& rootSection = *testCaseNode.children.front();
+
+        std::string className = stats.testInfo.className;
+
+        if( className.empty() ) {
+            className = fileNameTag(stats.testInfo.tags);
+            if ( className.empty() )
+                className = "global";
+        }
+
+        if ( !m_config->name().empty() )
+            className = m_config->name() + "." + className;
+
+        writeSection( className, "", rootSection );
+    }
+
+    void JunitReporter::writeSection(  std::string const& className,
+                        std::string const& rootName,
+                        SectionNode const& sectionNode ) {
+        std::string name = trim( sectionNode.stats.sectionInfo.name );
+        if( !rootName.empty() )
+            name = rootName + '/' + name;
+
+        if( !sectionNode.assertions.empty() ||
+            !sectionNode.stdOut.empty() ||
+            !sectionNode.stdErr.empty() ) {
+            XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
+            if( className.empty() ) {
+                xml.writeAttribute( "classname", name );
+                xml.writeAttribute( "name", "root" );
+            }
+            else {
+                xml.writeAttribute( "classname", className );
+                xml.writeAttribute( "name", name );
+            }
+            xml.writeAttribute( "time", ::Catch::Detail::stringify( sectionNode.stats.durationInSeconds ) );
+
+            writeAssertions( sectionNode );
+
+            if( !sectionNode.stdOut.empty() )
+                xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
+            if( !sectionNode.stdErr.empty() )
+                xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
+        }
+        for( auto const& childNode : sectionNode.childSections )
+            if( className.empty() )
+                writeSection( name, "", *childNode );
+            else
+                writeSection( className, name, *childNode );
+    }
+
+    void JunitReporter::writeAssertions( SectionNode const& sectionNode ) {
+        for( auto const& assertion : sectionNode.assertions )
+            writeAssertion( assertion );
+    }
+
+    void JunitReporter::writeAssertion( AssertionStats const& stats ) {
+        AssertionResult const& result = stats.assertionResult;
+        if( !result.isOk() ) {
+            std::string elementName;
+            switch( result.getResultType() ) {
+                case ResultWas::ThrewException:
+                case ResultWas::FatalErrorCondition:
+                    elementName = "error";
+                    break;
+                case ResultWas::ExplicitFailure:
+                    elementName = "failure";
+                    break;
+                case ResultWas::ExpressionFailed:
+                    elementName = "failure";
+                    break;
+                case ResultWas::DidntThrowException:
+                    elementName = "failure";
+                    break;
+
+                // We should never see these here:
+                case ResultWas::Info:
+                case ResultWas::Warning:
+                case ResultWas::Ok:
+                case ResultWas::Unknown:
+                case ResultWas::FailureBit:
+                case ResultWas::Exception:
+                    elementName = "internalError";
+                    break;
+            }
+
+            XmlWriter::ScopedElement e = xml.scopedElement( elementName );
+
+            xml.writeAttribute( "message", result.getExpandedExpression() );
+            xml.writeAttribute( "type", result.getTestMacroName() );
+
+            ReusableStringStream rss;
+            if( !result.getMessage().empty() )
+                rss << result.getMessage() << '\n';
+            for( auto const& msg : stats.infoMessages )
+                if( msg.type == ResultWas::Info )
+                    rss << msg.message << '\n';
+
+            rss << "at " << result.getSourceInfo();
+            xml.writeText( rss.str(), false );
+        }
+    }
+
+    CATCH_REGISTER_REPORTER( "junit", JunitReporter )
+
+} // end namespace Catch
+// end catch_reporter_junit.cpp
+// start catch_reporter_listening.cpp
+
+#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
+// end catch_reporter_listening.cpp
+// start catch_reporter_xml.cpp
+
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch
+                              // Note that 4062 (not all labels are handled
+                              // and default is missing) is enabled
+#endif
+
+namespace Catch {
+    XmlReporter::XmlReporter( ReporterConfig const& _config )
+    :   StreamingReporterBase( _config ),
+        m_xml(_config.stream())
+    {
+        m_reporterPrefs.shouldRedirectStdOut = true;
+        m_reporterPrefs.shouldReportAllAssertions = true;
+    }
+
+    XmlReporter::~XmlReporter() = default;
+
+    std::string XmlReporter::getDescription() {
+        return "Reports test results as an XML document";
+    }
+
+    std::string XmlReporter::getStylesheetRef() const {
+        return std::string();
+    }
+
+    void XmlReporter::writeSourceInfo( SourceLineInfo const& sourceInfo ) {
+        m_xml
+            .writeAttribute( "filename", sourceInfo.file )
+            .writeAttribute( "line", sourceInfo.line );
+    }
+
+    void XmlReporter::noMatchingTestCases( std::string const& s ) {
+        StreamingReporterBase::noMatchingTestCases( s );
+    }
+
+    void XmlReporter::testRunStarting( TestRunInfo const& testInfo ) {
+        StreamingReporterBase::testRunStarting( testInfo );
+        std::string stylesheetRef = getStylesheetRef();
+        if( !stylesheetRef.empty() )
+            m_xml.writeStylesheetRef( stylesheetRef );
+        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 ) {
+        StreamingReporterBase::testGroupStarting( groupInfo );
+        m_xml.startElement( "Group" )
+            .writeAttribute( "name", groupInfo.name );
+    }
+
+    void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) {
+        StreamingReporterBase::testCaseStarting(testInfo);
+        m_xml.startElement( "TestCase" )
+            .writeAttribute( "name", trim( testInfo.name ) )
+            .writeAttribute( "description", testInfo.description )
+            .writeAttribute( "tags", testInfo.tagsAsString() );
+
+        writeSourceInfo( testInfo.lineInfo );
+
+        if ( m_config->showDurations() == ShowDurations::Always )
+            m_testCaseTimer.start();
+        m_xml.ensureTagClosed();
+    }
+
+    void XmlReporter::sectionStarting( SectionInfo const& sectionInfo ) {
+        StreamingReporterBase::sectionStarting( sectionInfo );
+        if( m_sectionDepth++ > 0 ) {
+            m_xml.startElement( "Section" )
+                .writeAttribute( "name", trim( sectionInfo.name ) );
+            writeSourceInfo( sectionInfo.lineInfo );
+            m_xml.ensureTagClosed();
+        }
+    }
+
+    void XmlReporter::assertionStarting( AssertionInfo const& ) { }
+
+    bool XmlReporter::assertionEnded( AssertionStats const& assertionStats ) {
+
+        AssertionResult const& result = assertionStats.assertionResult;
+
+        bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
+
+        if( includeResults || result.getResultType() == ResultWas::Warning ) {
+            // Print any info messages in <Info> tags.
+            for( auto const& msg : assertionStats.infoMessages ) {
+                if( msg.type == ResultWas::Info && includeResults ) {
+                    m_xml.scopedElement( "Info" )
+                            .writeText( msg.message );
+                } else if ( msg.type == ResultWas::Warning ) {
+                    m_xml.scopedElement( "Warning" )
+                            .writeText( msg.message );
+                }
+            }
+        }
+
+        // Drop out if result was successful but we're not printing them.
+        if( !includeResults && result.getResultType() != ResultWas::Warning )
+            return true;
+
+        // Print the expression if there is one.
+        if( result.hasExpression() ) {
+            m_xml.startElement( "Expression" )
+                .writeAttribute( "success", result.succeeded() )
+                .writeAttribute( "type", result.getTestMacroName() );
+
+            writeSourceInfo( result.getSourceInfo() );
+
+            m_xml.scopedElement( "Original" )
+                .writeText( result.getExpression() );
+            m_xml.scopedElement( "Expanded" )
+                .writeText( result.getExpandedExpression() );
+        }
+
+        // And... Print a result applicable to each result type.
+        switch( result.getResultType() ) {
+            case ResultWas::ThrewException:
+                m_xml.startElement( "Exception" );
+                writeSourceInfo( result.getSourceInfo() );
+                m_xml.writeText( result.getMessage() );
+                m_xml.endElement();
+                break;
+            case ResultWas::FatalErrorCondition:
+                m_xml.startElement( "FatalErrorCondition" );
+                writeSourceInfo( result.getSourceInfo() );
+                m_xml.writeText( result.getMessage() );
+                m_xml.endElement();
+                break;
+            case ResultWas::Info:
+                m_xml.scopedElement( "Info" )
+                    .writeText( result.getMessage() );
+                break;
+            case ResultWas::Warning:
+                // Warning will already have been written
+                break;
+            case ResultWas::ExplicitFailure:
+                m_xml.startElement( "Failure" );
+                writeSourceInfo( result.getSourceInfo() );
+                m_xml.writeText( result.getMessage() );
+                m_xml.endElement();
+                break;
+            default:
+                break;
+        }
+
+        if( result.hasExpression() )
+            m_xml.endElement();
+
+        return true;
+    }
+
+    void XmlReporter::sectionEnded( SectionStats const& sectionStats ) {
+        StreamingReporterBase::sectionEnded( sectionStats );
+        if( --m_sectionDepth > 0 ) {
+            XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
+            e.writeAttribute( "successes", sectionStats.assertions.passed );
+            e.writeAttribute( "failures", sectionStats.assertions.failed );
+            e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk );
+
+            if ( m_config->showDurations() == ShowDurations::Always )
+                e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds );
+
+            m_xml.endElement();
+        }
+    }
+
+    void XmlReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
+        StreamingReporterBase::testCaseEnded( testCaseStats );
+        XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
+        e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() );
+
+        if ( m_config->showDurations() == ShowDurations::Always )
+            e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
+
+        if( !testCaseStats.stdOut.empty() )
+            m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false );
+        if( !testCaseStats.stdErr.empty() )
+            m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false );
+
+        m_xml.endElement();
+    }
+
+    void XmlReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {
+        StreamingReporterBase::testGroupEnded( testGroupStats );
+        // TODO: Check testGroupStats.aborting and act accordingly.
+        m_xml.scopedElement( "OverallResults" )
+            .writeAttribute( "successes", testGroupStats.totals.assertions.passed )
+            .writeAttribute( "failures", testGroupStats.totals.assertions.failed )
+            .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
+        m_xml.endElement();
+    }
+
+    void XmlReporter::testRunEnded( TestRunStats const& testRunStats ) {
+        StreamingReporterBase::testRunEnded( testRunStats );
+        m_xml.scopedElement( "OverallResults" )
+            .writeAttribute( "successes", testRunStats.totals.assertions.passed )
+            .writeAttribute( "failures", testRunStats.totals.assertions.failed )
+            .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );
+        m_xml.endElement();
+    }
+
+    CATCH_REGISTER_REPORTER( "xml", XmlReporter )
+
+} // end namespace Catch
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+// end catch_reporter_xml.cpp
+
+namespace Catch {
+    LeakDetector leakDetector;
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+// end catch_impl.hpp
+#endif
+
+#ifdef CATCH_CONFIG_MAIN
+// start catch_default_main.hpp
+
+#ifndef __OBJC__
+
+#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
+// Standard C/C++ main entry point
+int main (int argc, char * argv[]) {
+#endif
+
+    return Catch::Session().run( argc, argv );
+}
+
+#else // __OBJC__
+
+// Objective-C entry point
+int main (int argc, char * const argv[]) {
+#if !CATCH_ARC_ENABLED
+    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+#endif
+
+    Catch::registerTestMethods();
+    int result = Catch::Session().run( argc, (char**)argv );
+
+#if !CATCH_ARC_ENABLED
+    [pool drain];
+#endif
+
+    return result;
+}
+
+#endif // __OBJC__
+
+// end catch_default_main.hpp
+#endif
+
+#if !defined(CATCH_CONFIG_IMPL_ONLY)
+
+#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
+#  undef CLARA_CONFIG_MAIN
+#endif
+
+#if !defined(CATCH_CONFIG_DISABLE)
+//////
+// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
+#ifdef CATCH_CONFIG_PREFIX_ALL
+
+#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_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)
+#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
+#endif// CATCH_CONFIG_DISABLE_MATCHERS
+#define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
+
+#define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
+#define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
+#define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
+#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_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)
+#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
+#endif // CATCH_CONFIG_DISABLE_MATCHERS
+#define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
+
+#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
+#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
+
+#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
+#endif // CATCH_CONFIG_DISABLE_MATCHERS
+
+#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( ... ) 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__ )
+#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__ ) )
+#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 )     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
+
+#define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__  )
+#define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
+
+#define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
+#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
+#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
+#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
+#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
+#endif // CATCH_CONFIG_DISABLE_MATCHERS
+#define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
+
+#define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
+#define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
+#define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
+#define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
+#define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
+
+#define CHECK_THROWS( ... )  INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
+#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
+#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
+#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
+#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
+#endif // CATCH_CONFIG_DISABLE_MATCHERS
+#define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
+
+#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
+#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
+
+#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
+#endif // CATCH_CONFIG_DISABLE_MATCHERS
+
+#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
+#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, 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__ )
+#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__ ) )
+#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 )
+
+// "BDD-style" convenience wrappers
+#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
+#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
+
+#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 // CATCH_CONFIG_DISABLE
+
+//////
+// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
+#ifdef CATCH_CONFIG_PREFIX_ALL
+
+#define CATCH_REQUIRE( ... )        (void)(0)
+#define CATCH_REQUIRE_FALSE( ... )  (void)(0)
+
+#define CATCH_REQUIRE_THROWS( ... ) (void)(0)
+#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
+#define CATCH_REQUIRE_THROWS_WITH( expr, matcher )     (void)(0)
+#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
+#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
+#endif// CATCH_CONFIG_DISABLE_MATCHERS
+#define CATCH_REQUIRE_NOTHROW( ... ) (void)(0)
+
+#define CATCH_CHECK( ... )         (void)(0)
+#define CATCH_CHECK_FALSE( ... )   (void)(0)
+#define CATCH_CHECKED_IF( ... )    if (__VA_ARGS__)
+#define CATCH_CHECKED_ELSE( ... )  if (!(__VA_ARGS__))
+#define CATCH_CHECK_NOFAIL( ... )  (void)(0)
+
+#define CATCH_CHECK_THROWS( ... )  (void)(0)
+#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
+#define CATCH_CHECK_THROWS_WITH( expr, matcher )     (void)(0)
+#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
+#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
+#endif // CATCH_CONFIG_DISABLE_MATCHERS
+#define CATCH_CHECK_NOTHROW( ... ) (void)(0)
+
+#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
+#define CATCH_CHECK_THAT( arg, matcher )   (void)(0)
+
+#define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0)
+#endif // CATCH_CONFIG_DISABLE_MATCHERS
+
+#define CATCH_INFO( msg )    (void)(0)
+#define CATCH_WARN( msg )    (void)(0)
+#define CATCH_CAPTURE( msg ) (void)(0)
+
+#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
+#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
+#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 )
+#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 ) )
+#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
+
+#define REQUIRE( ... )       (void)(0)
+#define REQUIRE_FALSE( ... ) (void)(0)
+
+#define REQUIRE_THROWS( ... ) (void)(0)
+#define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
+#define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
+#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
+#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
+#endif // CATCH_CONFIG_DISABLE_MATCHERS
+#define REQUIRE_NOTHROW( ... ) (void)(0)
+
+#define CHECK( ... ) (void)(0)
+#define CHECK_FALSE( ... ) (void)(0)
+#define CHECKED_IF( ... ) if (__VA_ARGS__)
+#define CHECKED_ELSE( ... ) if (!(__VA_ARGS__))
+#define CHECK_NOFAIL( ... ) (void)(0)
+
+#define CHECK_THROWS( ... )  (void)(0)
+#define CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
+#define CHECK_THROWS_WITH( expr, matcher ) (void)(0)
+#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
+#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
+#endif // CATCH_CONFIG_DISABLE_MATCHERS
+#define CHECK_NOTHROW( ... ) (void)(0)
+
+#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
+#define CHECK_THAT( arg, matcher ) (void)(0)
+
+#define REQUIRE_THAT( arg, matcher ) (void)(0)
+#endif // CATCH_CONFIG_DISABLE_MATCHERS
+
+#define INFO( msg ) (void)(0)
+#define WARN( msg ) (void)(0)
+#define CAPTURE( msg ) (void)(0)
+
+#define TEST_CASE( ... )  INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
+#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
+#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 )
+#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 ) )
+#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 )
+
+// "BDD-style" convenience wrappers
+#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) )
+#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 )
+#define AND_THEN( desc )
+
+using Catch::Detail::Approx;
+
+#endif
+
+#endif // ! CATCH_CONFIG_IMPL_ONLY
+
+// start catch_reenable_warnings.h
+
+
+#ifdef __clang__
+#    ifdef __ICC // icpc defines the __clang__ macro
+#        pragma warning(pop)
+#    else
+#        pragma clang diagnostic pop
+#    endif
+#elif defined __GNUC__
+#    pragma GCC diagnostic pop
+#endif
+
+// end catch_reenable_warnings.h
+// end catch.hpp
+#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
+
diff --git a/components/rgbd-sources/test/data/image.png b/components/rgbd-sources/test/data/image.png
new file mode 100644
index 0000000000000000000000000000000000000000..31d086c8d4fa1e13b131c9aa2d4e216459bc730f
GIT binary patch
literal 509
zcmeAS@N?(olHy`uVBq!ia0y~yU^oH7983%h3`$m(Cm9$RI14-?iy0WWg+Z8+Vb&Z8
z1_lQ95>H=O_Q!0TY{F`i$_J|%7#L(TLn2C?^K)}k^GX;%z_}<ju_QG`p**uBL&4qC
zHy}kXm7RfsvDnkaF{I+w+e?Om3=AAc3=Zsnew>BbS!v;Qzo3F#l>-qH+{uj_4aANy
zB`50iupT=UA;I0#y3s&Pf;%};$3X1Zp@;;Xp4N@@R5+O20uBaJ!sXFyRz)tBUcc`T
QpMv7W)78&qol`;+0EkGZ-2eap

literal 0
HcmV?d00001

diff --git a/components/rgbd-sources/test/data/video.mp4 b/components/rgbd-sources/test/data/video.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..b8637a3e458d400bb4b744157dfbdac6b52bea6e
GIT binary patch
literal 179698
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

literal 0
HcmV?d00001

diff --git a/components/rgbd-sources/test/source_unit.cpp b/components/rgbd-sources/test/source_unit.cpp
new file mode 100644
index 000000000..8e48a53a0
--- /dev/null
+++ b/components/rgbd-sources/test/source_unit.cpp
@@ -0,0 +1,171 @@
+#include "catch.hpp"
+
+//---- Mocks -------------------------------------------------------------------
+
+#include <ftl/rgbd/source.hpp>
+#include <ftl/config.h>
+
+static std::string last_type = "";
+
+namespace ftl {
+namespace rgbd {
+namespace detail {
+
+class ImageSource : public ftl::rgbd::detail::Source {
+	public:
+	ImageSource(ftl::rgbd::Source *host) : ftl::rgbd::detail::Source(host) {
+		last_type = "image";
+	}
+	ImageSource(ftl::rgbd::Source *host, const std::string &f) : ftl::rgbd::detail::Source(host) {
+		last_type = "image";
+	}
+
+	bool grab() { return true; };
+	bool isReady() { return true; };
+};
+
+class StereoVideoSource : public ftl::rgbd::detail::Source {
+	public:
+	StereoVideoSource(ftl::rgbd::Source *host) : ftl::rgbd::detail::Source(host) {
+		last_type = "video";
+	}
+	StereoVideoSource(ftl::rgbd::Source *host, const std::string &f) : ftl::rgbd::detail::Source(host) {
+		last_type = "video";
+	}
+
+	bool grab() { return true; };
+	bool isReady() { return true; };
+};
+
+class NetSource : public ftl::rgbd::detail::Source {
+	public:
+	NetSource(ftl::rgbd::Source *host) : ftl::rgbd::detail::Source(host) {
+		last_type = "net";
+	}
+
+	bool grab() { return true; };
+	bool isReady() { return true; };
+};
+
+}	
+}	
+}
+
+//---- Sources -----------------------------------------------------------------
+
+// Prevent these headers...
+#define _FTL_RGBD_STEREOVIDEO_HPP_
+#define _FTL_RGBD_NET_HPP_
+#define _FTL_RGBD_SNAPSHOT_SOURCE_HPP_
+#define _FTL_RGBD_IMAGE_HPP_
+
+#include "../src/source.cpp"
+
+
+//---- Tests -------------------------------------------------------------------
+
+using ftl::rgbd::Source;
+using ftl::config::json_t;
+
+TEST_CASE("ftl::create<Source>(cfg)", "[rgbd]") {
+	json_t global = {{"$id","ftl://test"}};
+	ftl::config::configure(global);
+
+	SECTION("with valid image file uri") {
+		json_t cfg = {
+			{"$id","ftl://test/1"},
+			{"uri","file://" FTL_SOURCE_DIRECTORY "/components/rgbd-sources/test/data/image.png"}
+		};
+
+		Source *src = ftl::create<Source>(cfg);
+
+		REQUIRE( src );
+		REQUIRE( src->isReady() );
+		REQUIRE( last_type == "image"); 
+	}
+
+	SECTION("with valid video file uri") {
+		json_t cfg = {
+			{"$id","ftl://test/2"},
+			{"uri","file://" FTL_SOURCE_DIRECTORY "/components/rgbd-sources/test/data/video.mp4"}
+		};
+
+		Source *src = ftl::create<Source>(cfg);
+
+		REQUIRE( src );
+		REQUIRE( src->isReady() );
+		REQUIRE( last_type == "video");
+	}
+
+	SECTION("with valid net uri") {
+		json_t cfg = {
+			{"$id","ftl://test/2"},
+			{"uri","ftl://utu.fi/dummy"}
+		};
+
+		Source *src = ftl::create<Source>(cfg);
+
+		REQUIRE( src );
+		REQUIRE( src->isReady() );
+		REQUIRE( last_type == "net");
+	}
+
+	SECTION("with an invalid uri") {
+		json_t cfg = {
+			{"$id","ftl://test/2"},
+			{"uri","not a uri"}
+		};
+
+		Source *src = ftl::create<Source>(cfg);
+
+		REQUIRE( src );
+		REQUIRE( !src->isReady() );
+	}
+
+	SECTION("with an invalid file uri") {
+		json_t cfg = {
+			{"$id","ftl://test/2"},
+			{"uri","file:///not/a/file"}
+		};
+
+		Source *src = ftl::create<Source>(cfg);
+
+		REQUIRE( src );
+		REQUIRE( !src->isReady() );
+	}
+
+	SECTION("with a missing file") {
+		json_t cfg = {
+			{"$id","ftl://test/2"},
+			{"uri","file:///data/image2.png"}
+		};
+
+		Source *src = ftl::create<Source>(cfg);
+
+		REQUIRE( src );
+		REQUIRE( !src->isReady() );
+	}
+}
+
+TEST_CASE("Source::set(uri)", "[rgbd]") {
+	json_t global = {{"$id","ftl://test"}};
+	ftl::config::configure(global);
+
+	SECTION("change to different valid URI type") {
+		json_t cfg = {
+			{"$id","ftl://test/1"},
+			{"uri","file://" FTL_SOURCE_DIRECTORY "/components/rgbd-sources/test/data/image.png"}
+		};
+
+		Source *src = ftl::create<Source>(cfg);
+
+		REQUIRE( src );
+		REQUIRE( src->isReady() );
+		REQUIRE( last_type == "image" );
+
+		src->set("uri", "file://" FTL_SOURCE_DIRECTORY "/components/rgbd-sources/test/data/video.mp4");
+
+		REQUIRE( src->isReady() );
+		REQUIRE( last_type == "video" ); 
+	}
+}
diff --git a/components/rgbd-sources/test/tests.cpp b/components/rgbd-sources/test/tests.cpp
new file mode 100644
index 000000000..178916eab
--- /dev/null
+++ b/components/rgbd-sources/test/tests.cpp
@@ -0,0 +1,3 @@
+#define CATCH_CONFIG_MAIN
+#include "catch.hpp"
+
-- 
GitLab