From ad0f5eab899fc340f89c5d8d4644d81d8598cd1c Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 7 Nov 2023 22:34:00 +0100 Subject: [PATCH 1/4] DPL GUI: do not hang if quit requested but some devices are stuck --- Framework/Core/src/runDataProcessing.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 61fdef070d874..49c5ebadb6460 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -1073,7 +1073,7 @@ void gui_callback(uv_timer_s* ctx) if (gui->plugin->supportsDeferredClose()) { // For now, there is nothing for which we want to defer the close // so if the flag is set, we simply exit - if (*(gui->guiQuitRequested)) { + if (*(gui->guiQuitRequested) && *(gui->allChildrenGone)) { return; } void* draw_data = nullptr; From 397c3b7d379316c947c28a6e8088f2c2d87f1a46 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 7 Nov 2023 22:34:00 +0100 Subject: [PATCH 2/4] DPL GUI: add GUI to list devices preventing quitting --- Framework/Core/include/Framework/DebugGUI.h | 4 +- Framework/Core/src/runDataProcessing.cxx | 6 +- .../GUISupport/src/FrameworkGUIDebugger.cxx | 110 ++++++++++++------ .../GUISupport/src/FrameworkGUIDebugger.h | 4 +- Framework/GUISupport/src/Plugin.cxx | 5 +- 5 files changed, 87 insertions(+), 42 deletions(-) diff --git a/Framework/Core/include/Framework/DebugGUI.h b/Framework/Core/include/Framework/DebugGUI.h index c7a611d50a1d4..109fd36e27511 100644 --- a/Framework/Core/include/Framework/DebugGUI.h +++ b/Framework/Core/include/Framework/DebugGUI.h @@ -26,6 +26,7 @@ namespace o2::framework { struct ServiceRegistry; +struct GuiCallbackContext; /// Plugin interface for DPL GUIs. struct DebugGUI { virtual std::function getGUIDebugger(std::vector const& infos, @@ -35,7 +36,8 @@ struct DebugGUI { std::vector const& metricsInfos, o2::framework::DriverInfo const& driverInfo, std::vector& controls, - o2::framework::DriverControl& driverControl) = 0; + o2::framework::DriverControl& driverControl, + GuiCallbackContext& context) = 0; virtual void updateMousePos(float x, float y) = 0; virtual void updateMouseButton(bool isClicked) = 0; virtual void updateMouseWheel(int direction) = 0; diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 49c5ebadb6460..44a5c6b4ee94a 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -1302,7 +1302,8 @@ int runStateMachine(DataProcessorSpecs const& workflow, DebugGUI* debugGUI = nullptr; void* window = nullptr; - decltype(debugGUI->getGUIDebugger(infos, runningWorkflow.devices, allStates, dataProcessorInfos, metricsInfos, driverInfo, controls, driverControl)) debugGUICallback; + GuiCallbackContext guiContext; + decltype(debugGUI->getGUIDebugger(infos, runningWorkflow.devices, allStates, dataProcessorInfos, metricsInfos, driverInfo, controls, driverControl, guiContext)) debugGUICallback; // An empty frameworkId means this is the driver, so we initialise the GUI auto initDebugGUI = []() -> DebugGUI* { @@ -1389,7 +1390,6 @@ int runStateMachine(DataProcessorSpecs const& workflow, ServiceRegistryRef ref{serviceRegistry}; ref.registerService(ServiceRegistryHelpers::handleForService(devicesManager)); - GuiCallbackContext guiContext; guiContext.plugin = debugGUI; guiContext.frameLast = uv_hrtime(); guiContext.frameLatency = &driverInfo.frameLatency; @@ -1882,7 +1882,7 @@ int runStateMachine(DataProcessorSpecs const& workflow, uv_timer_stop(gui_timer); } - auto callback = debugGUI->getGUIDebugger(infos, runningWorkflow.devices, allStates, dataProcessorInfos, metricsInfos, driverInfo, controls, driverControl); + auto callback = debugGUI->getGUIDebugger(infos, runningWorkflow.devices, allStates, dataProcessorInfos, metricsInfos, driverInfo, controls, driverControl, guiContext); guiContext.callback = [&serviceRegistry, &driverServices, &debugGUI, &infos, &runningWorkflow, &dataProcessorInfos, &metricsInfos, &driverInfo, &controls, &driverControl, callback]() { callback(); for (auto& service : driverServices) { diff --git a/Framework/GUISupport/src/FrameworkGUIDebugger.cxx b/Framework/GUISupport/src/FrameworkGUIDebugger.cxx index 35e0bc563a22e..375afef1007f9 100644 --- a/Framework/GUISupport/src/FrameworkGUIDebugger.cxx +++ b/Framework/GUISupport/src/FrameworkGUIDebugger.cxx @@ -16,6 +16,7 @@ #include "DebugGUI/imgui_extras.h" #include "Framework/DriverControl.h" #include "Framework/DriverInfo.h" +#include "Framework/GuiCallbackContext.h" #include "Framework/DeviceMetricsHelper.h" #include "Framework/DeviceMetricsInfo.h" #include "FrameworkGUIDeviceInspector.h" @@ -506,7 +507,7 @@ void displayDeviceMetrics(const char* label, case MetricsDisplayStyle::Lines: { auto xAxisFlags = ImPlotAxisFlags_None; auto yAxisFlags = ImPlotAxisFlags_LockMin; - //ImPlot::FitNextPlotAxes(true, true, true, true); + // ImPlot::FitNextPlotAxes(true, true, true, true); if (ImPlot::BeginPlot("##Some plot", {-1, -1}, axisFlags)) { ImPlot::SetupAxes("time", "value", xAxisFlags, yAxisFlags); ImPlot::SetupAxisFormat(ImAxis_Y1, formatSI, nullptr); @@ -1008,6 +1009,71 @@ void popWindowColorDueToStatus() ImGui::PopStyleVar(1); } +int debugPID(int pid) +{ + std::string pidStr = std::to_string(pid); + setenv("O2DEBUGGEDPID", pidStr.c_str(), 1); +#ifdef __APPLE__ + std::string defaultAppleDebugCommand = + "osascript -e 'tell application \"Terminal\"'" + " -e 'activate'" + " -e 'do script \"lldb -p \" & (system attribute \"O2DEBUGGEDPID\") & \"; exit\"'" + " -e 'end tell'"; + setenv("O2DPLDEBUG", defaultAppleDebugCommand.c_str(), 0); +#else + setenv("O2DPLDEBUG", "xterm -hold -e gdb attach $O2DEBUGGEDPID &", 0); +#endif + return system(getenv("O2DPLDEBUG")); +} + +int profilePID(int pid) +{ + std::string pidStr = std::to_string(pid); + setenv("O2PROFILEDPID", pidStr.c_str(), 1); +#ifdef __APPLE__ + auto defaultAppleProfileCommand = fmt::format( + "osascript -e 'tell application \"Terminal\"'" + " -e 'activate'" + " -e 'do script \"xcrun xctrace record --output dpl-profile-{0}.trace" + " --instrument os_signpost --time-limit 30s --template Time\\\\ Profiler --attach {0} " + " && open dpl-profile-{0}.trace && exit\"'" + " -e 'end tell'", + pid); + std::cout << defaultAppleProfileCommand << std::endl; + setenv("O2DPLPROFILE", defaultAppleProfileCommand.c_str(), 0); +#else + setenv("O2DPLPROFILE", "xterm -hold -e perf record -a -g -p $O2PROFILEDPID > perf-$O2PROFILEDPID.data &", 0); +#endif + return system(getenv("O2DPLPROFILE")); +} + +/// Show a window with the list of devices which have not yet exited +/// and provide a few controls to interact with them. +void displayShutdownDialog(std::vector const& specs, std::vector const& infos) +{ + for (size_t i = 0; i < infos.size(); ++i) { + auto& info = infos[i]; + if (info.active == false) { + continue; + } + auto& spec = specs[i]; + ImGui::Text("Unable to quit due to the following devices:"); + ImGui::Text("%s (%d).", spec.name.c_str(), info.pid); + ImGui::SameLine(); + if (ImGui::Button("Force quit")) { + kill(info.pid, SIGKILL); + } + ImGui::SameLine(); + if (ImGui::Button("Debug")) { + debugPID(info.pid); + } + ImGui::SameLine(); + if (ImGui::Button("Profile")) { + profilePID(info.pid); + } + } +} + /// Display information window about the driver /// and its state. void displayDriverInfo(DriverInfo const& driverInfo, DriverControl& driverControl) @@ -1035,42 +1101,12 @@ void displayDriverInfo(DriverInfo const& driverInfo, DriverControl& driverContro } ImGui::SameLine(); if (ImGui::Button("Debug driver")) { - std::string pidStr = std::to_string(pid); - setenv("O2DEBUGGEDPID", pidStr.c_str(), 1); -#ifdef __APPLE__ - std::string defaultAppleDebugCommand = - "osascript -e 'tell application \"Terminal\"'" - " -e 'activate'" - " -e 'do script \"lldb -p \" & (system attribute \"O2DEBUGGEDPID\") & \"; exit\"'" - " -e 'end tell'"; - setenv("O2DPLDEBUG", defaultAppleDebugCommand.c_str(), 0); -#else - setenv("O2DPLDEBUG", "xterm -hold -e gdb attach $O2DEBUGGEDPID &", 0); -#endif - int retVal = system(getenv("O2DPLDEBUG")); - (void)retVal; + debugPID(pid); } ImGui::SameLine(); if (ImGui::Button("Profile")) { - std::string pidStr = std::to_string(pid); - setenv("O2PROFILEDPID", pidStr.c_str(), 1); -#ifdef __APPLE__ - auto defaultAppleProfileCommand = fmt::format( - "osascript -e 'tell application \"Terminal\"'" - " -e 'activate'" - " -e 'do script \"xcrun xctrace record --output dpl-profile-{0}.trace" - " --instrument os_signpost --time-limit 30s --template Time\\\\ Profiler --attach {0} " - " && open dpl-profile-{0}.trace && exit\"'" - " -e 'end tell'", - pid); - std::cout << defaultAppleProfileCommand << std::endl; - setenv("O2DPLPROFILE", defaultAppleProfileCommand.c_str(), 0); -#else - setenv("O2DPLPROFILE", "xterm -hold -e perf record -a -g -p $O2PROFILEDPID > perf-$O2PROFILEDPID.data &", 0); -#endif - int retVal = system(getenv("O2DPLPROFILE")); - (void)retVal; + profilePID(pid); } // FIXME: this should really be a combo box @@ -1110,7 +1146,8 @@ std::function getGUIDebugger(std::vector const& infos, std::vector const& metricsInfos, DriverInfo const& driverInfo, std::vector& controls, - DriverControl& driverControl) + DriverControl& driverControl, + GuiCallbackContext& gui) { static gui::WorkspaceGUIState globalGUIState; gui::WorkspaceGUIState& guiState = globalGUIState; @@ -1141,7 +1178,7 @@ std::function getGUIDebugger(std::vector const& infos, std::vector driverNodesInfos; driverNodesInfos.push_back(TopologyNodeInfo{"driver"}); - return [&infos, &devices, &allStates, &metadata, &controls, &metricsInfos, &driverInfo, &driverControl, deviceNodesInfos, driverNodesInfos]() { + return [&infos, &devices, &allStates, &metadata, &controls, &metricsInfos, &driverInfo, &driverControl, &gui, deviceNodesInfos, driverNodesInfos]() { ImGuiStyle& style = ImGui::GetStyle(); style.FrameRounding = 0.; style.WindowRounding = 0.; @@ -1158,6 +1195,9 @@ std::function getGUIDebugger(std::vector const& infos, metricsStore.specs[DRIVER_METRICS] = gsl::span(driverNodesInfos); displayMetrics(guiState, driverInfo, infos, metadata, controls, metricsStore); displayDriverInfo(driverInfo, driverControl); + if (*(gui.guiQuitRequested) && !*(gui.allChildrenGone)) { + displayShutdownDialog(devices, infos); + } int windowPosStepping = (ImGui::GetIO().DisplaySize.y - 500) / guiState.devices.size(); diff --git a/Framework/GUISupport/src/FrameworkGUIDebugger.h b/Framework/GUISupport/src/FrameworkGUIDebugger.h index 5de5e350ddf8d..98bb50b07fd44 100644 --- a/Framework/GUISupport/src/FrameworkGUIDebugger.h +++ b/Framework/GUISupport/src/FrameworkGUIDebugger.h @@ -26,6 +26,7 @@ namespace o2::framework class DriverInfo; class DriverControl; +class GuiCallbackContext; namespace gui { @@ -37,7 +38,8 @@ std::function getGUIDebugger(std::vector const& infos, std::vector const& metricsInfos, DriverInfo const& driverInfo, std::vector& controls, - DriverControl& driverControl); + DriverControl& driverControl, + GuiCallbackContext& context); void updateMousePos(float x, float y); void updateMouseButton(bool clicked); diff --git a/Framework/GUISupport/src/Plugin.cxx b/Framework/GUISupport/src/Plugin.cxx index 7a356f6e55d9b..022b74174f632 100644 --- a/Framework/GUISupport/src/Plugin.cxx +++ b/Framework/GUISupport/src/Plugin.cxx @@ -36,9 +36,10 @@ struct ImGUIDebugGUI : o2::framework::DebugGUI { std::vector const& metricsInfos, DriverInfo const& driverInfo, std::vector& controls, - DriverControl& driverControl) override + DriverControl& driverControl, + GuiCallbackContext& context) override { - return o2::framework::gui::getGUIDebugger(infos, devices, allStates, metadata, metricsInfos, driverInfo, controls, driverControl); + return o2::framework::gui::getGUIDebugger(infos, devices, allStates, metadata, metricsInfos, driverInfo, controls, driverControl, context); } void updateMousePos(float x, float y) override From b7d30656d4d75df957c321694a25533e96a4bf9c Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 7 Nov 2023 22:34:00 +0100 Subject: [PATCH 3/4] DPL GUI: allow GUI to move between different states --- Framework/Core/src/DataProcessingDevice.cxx | 49 ++++++++++++++++++- Framework/Core/src/WSDriverClient.cxx | 24 +++++++++ Framework/Core/src/runDataProcessing.cxx | 13 ++++- .../GUISupport/src/FrameworkGUIDebugger.cxx | 2 +- .../src/FrameworkGUIDeviceInspector.cxx | 27 +++++++++- .../src/FrameworkGUIDeviceInspector.h | 5 +- .../src/FrameworkGUIDevicesGraph.cxx | 5 +- .../GUISupport/src/FrameworkGUIDevicesGraph.h | 8 ++- 8 files changed, 123 insertions(+), 10 deletions(-) diff --git a/Framework/Core/src/DataProcessingDevice.cxx b/Framework/Core/src/DataProcessingDevice.cxx index 5542be850fb70..3f78543bdc594 100644 --- a/Framework/Core/src/DataProcessingDevice.cxx +++ b/Framework/Core/src/DataProcessingDevice.cxx @@ -25,6 +25,7 @@ #include "Framework/DispatchPolicy.h" #include "Framework/DispatchControl.h" #include "Framework/DanglingContext.h" +#include "Framework/DriverInfo.h" #include "Framework/DomainInfoHeader.h" #include "Framework/DriverClient.h" #include "Framework/EndOfStreamContext.h" @@ -159,16 +160,60 @@ DataProcessingDevice::DataProcessingDevice(RunningDeviceRef running, ServiceRegi std::function stateWatcher = [this, ®istry = mServiceRegistry](const fair::mq::State state) -> void { auto ref = ServiceRegistryRef{registry, ServiceRegistry::globalDeviceSalt()}; + auto controlKind = this->GetConfig()->GetPropertyAsString("control"); auto& deviceState = ref.get(); auto& control = ref.get(); auto& callbacks = ref.get(); - control.notifyDeviceState(fair::mq::GetStateName(state)); + auto stateName = fair::mq::GetStateName(state); + control.notifyDeviceState(stateName); callbacks.call(ServiceRegistryRef{ref}, (int)state); + LOG(detail) << "In state watcher callback " << stateName; + + // If the termination policy is not to wait, we simply ignore all + // user imposed state changes and keep running until we are done. + if (controlKind != "gui") { + return; + } + + static bool runningOnce = false; if (deviceState.nextFairMQState.empty() == false) { + LOG(detail) << "State change requested, changing state to " << deviceState.nextFairMQState.back(); auto state = deviceState.nextFairMQState.back(); - (void)this->ChangeState(state); + bool changed = this->ChangeState(state); + if (!changed) { + LOG(error) << "Failed to change state to " << state; + } deviceState.nextFairMQState.pop_back(); + } else if (state == fair::mq::State::Running && deviceState.nextFairMQState.empty()) { + LOGP(detail, "Device is running and no transition expected. We are done."); + deviceState.transitionHandling = TransitionHandlingState::NoTransition; + } else { + while (runningOnce && deviceState.nextFairMQState.empty() && this->NewStatePending() == false) { + LOG(detail) << "No state change requested, waiting for next state change " << this->NewStatePending(); + if (stateName == "EXITING") { + // Send ctrl c to ourselves. To bad FairMQ does not seem to exit when + // reaching the EXITING state. + kill(getpid(), SIGTERM); + return; + } + uv_run(deviceState.loop, UV_RUN_ONCE); + LOG(detail) << "Woke up from event loop"; + } + if (runningOnce && deviceState.nextFairMQState.empty() == false) { + LOG(detail) << "State change requested, changing state to " << deviceState.nextFairMQState.back(); + auto state = deviceState.nextFairMQState.back(); + bool changed = this->ChangeState(state); + if (!changed) { + LOG(error) << "Failed to change state to " << state; + } + deviceState.nextFairMQState.pop_back(); + } + LOG(detail) << "Exiting callback for state " << state; + } + if (runningOnce == false && state == fair::mq::State::Running) { + LOG(detail) << "First iteration, next time we start the event loop"; + runningOnce = true; } }; diff --git a/Framework/Core/src/WSDriverClient.cxx b/Framework/Core/src/WSDriverClient.cxx index d4ed77b9a004e..91f011e61cda3 100644 --- a/Framework/Core/src/WSDriverClient.cxx +++ b/Framework/Core/src/WSDriverClient.cxx @@ -15,6 +15,8 @@ #include "Framework/ServiceRegistry.h" #include "Framework/DeviceSpec.h" #include "DriverClientContext.h" +#include "Framework/RawDeviceService.h" +#include "Device.h" #include "DPLWebSocket.h" #include #include @@ -134,6 +136,28 @@ void on_connect(uv_connect_t* connection, int status) state.nextFairMQState.emplace_back("STOP"); }); + client->observe("/shutdown", [ref = context->ref](std::string_view) { + auto currentStateName = ref.get().device()->GetCurrentStateName(); + LOGP(info, "Received shutdown request while in {}", currentStateName); + + auto& state = ref.get(); + state.nextFairMQState.emplace_back("END"); + if (currentStateName == "IDLE") { + return; + } + state.nextFairMQState.emplace_back("AUTO"); + state.nextFairMQState.emplace_back("RESET DEVICE"); + if (currentStateName == "DEVICE READY") { + return; + } + state.nextFairMQState.emplace_back("AUTO"); + state.nextFairMQState.emplace_back("RESET TASK"); + if (currentStateName == "READY") { + return; + } + state.nextFairMQState.emplace_back("STOP"); + }); + client->observe("/trace", [ref = context->ref](std::string_view cmd) { auto& state = ref.get(); static constexpr int prefixSize = std::string_view{"/trace "}.size(); diff --git a/Framework/Core/src/runDataProcessing.cxx b/Framework/Core/src/runDataProcessing.cxx index 44a5c6b4ee94a..c7a57acd83971 100644 --- a/Framework/Core/src/runDataProcessing.cxx +++ b/Framework/Core/src/runDataProcessing.cxx @@ -29,6 +29,7 @@ #include "Framework/DeviceMetricsInfo.h" #include "Framework/DeviceMetricsHelper.h" #include "Framework/DeviceConfigInfo.h" +#include "Framework/DeviceController.h" #include "Framework/DeviceSpec.h" #include "Framework/DeviceState.h" #include "Framework/DeviceConfig.h" @@ -2068,7 +2069,17 @@ int runStateMachine(DataProcessorSpecs const& workflow, // We send SIGCONT to make sure stopped children are resumed killChildren(infos, SIGCONT); // We send SIGTERM to make sure we do the STOP transition in FairMQ - killChildren(infos, SIGTERM); + if (driverInfo.processingPolicies.termination == TerminationPolicy::WAIT) { + for (size_t di = 0; di < infos.size(); ++di) { + auto& info = infos[di]; + auto& control = controls[di]; + if (info.active == true) { + control.controller->write("/shutdown", strlen("/shutdown")); + } + } + } else { + killChildren(infos, SIGTERM); + } // We have a timer to send SIGUSR1 to make sure we advance all devices // in a timely manner. force_step_timer.data = &infos; diff --git a/Framework/GUISupport/src/FrameworkGUIDebugger.cxx b/Framework/GUISupport/src/FrameworkGUIDebugger.cxx index 375afef1007f9..cc5180093ec94 100644 --- a/Framework/GUISupport/src/FrameworkGUIDebugger.cxx +++ b/Framework/GUISupport/src/FrameworkGUIDebugger.cxx @@ -1185,7 +1185,7 @@ std::function getGUIDebugger(std::vector const& infos, style.Colors[ImGuiCol_WindowBg] = ImVec4(0x1b / 255.f, 0x1b / 255.f, 0x1b / 255.f, 1.00f); style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0x1b / 255.f, 0x1b / 255.f, 0x1b / 255.f, 1.00f); - showTopologyNodeGraph(guiState, infos, devices, allStates, metadata, controls, metricsInfos); + showTopologyNodeGraph(guiState, infos, devices, allStates, metadata, controls, metricsInfos, driverInfo.processingPolicies.termination); AllMetricsStore metricsStore; diff --git a/Framework/GUISupport/src/FrameworkGUIDeviceInspector.cxx b/Framework/GUISupport/src/FrameworkGUIDeviceInspector.cxx index a82753eb5af1f..9febb93858cb8 100644 --- a/Framework/GUISupport/src/FrameworkGUIDeviceInspector.cxx +++ b/Framework/GUISupport/src/FrameworkGUIDeviceInspector.cxx @@ -11,6 +11,7 @@ #include "FrameworkGUIDeviceInspector.h" #include "Framework/DataProcessorInfo.h" +#include "Framework/ProcessingPolicies.h" #include "Framework/DeviceControl.h" #include "Framework/DeviceSpec.h" @@ -251,7 +252,8 @@ void displayDeviceInspector(DeviceSpec const& spec, DataProcessingStates const& states, DeviceMetricsInfo const& metrics, DataProcessorInfo const& metadata, - DeviceControl& control) + DeviceControl& control, + TerminationPolicy terminationPolicy) { ImGui::Text("Name: %s", spec.name.c_str()); ImGui::Text("Executable: %s", metadata.executable.c_str()); @@ -340,12 +342,33 @@ void displayDeviceInspector(DeviceSpec const& spec, } if (control.requestedState > info.providedState) { - ImGui::Text(ICON_FA_CLOCK_O); + ImGui::TextUnformatted(ICON_FA_CLOCK_O "Requested transition in progress"); } else { + // We only allow navigation if the termination policy is "WAIT" + ImGui::BeginDisabled(terminationPolicy == TerminationPolicy::QUIT); if (ImGui::Button("Restart")) { control.requestedState = info.providedState + 1; control.controller->write("/restart", strlen("/restart")); } + if (info.deviceState == "RUNNING") { + ImGui::SameLine(); + if (ImGui::Button(ICON_FA_STOP)) { + control.requestedState = info.providedState + 1; + control.controller->write("/stop", strlen("/stop")); + } + } else if (info.deviceState == "READY") { + ImGui::SameLine(); + if (ImGui::Button(ICON_FA_PLAY)) { + control.requestedState = info.providedState + 1; + control.controller->write("/start", strlen("/start")); + } + ImGui::SameLine(); + if (ImGui::Button(ICON_FA_POWER_OFF)) { + control.requestedState = info.providedState + 1; + control.controller->write("/shutdown", strlen("/shutdown")); + } + } + ImGui::EndDisabled(); } } diff --git a/Framework/GUISupport/src/FrameworkGUIDeviceInspector.h b/Framework/GUISupport/src/FrameworkGUIDeviceInspector.h index 8dac3204ea3ab..b69c6e9286215 100644 --- a/Framework/GUISupport/src/FrameworkGUIDeviceInspector.h +++ b/Framework/GUISupport/src/FrameworkGUIDeviceInspector.h @@ -18,12 +18,15 @@ struct DeviceInfo; struct DeviceMetricsInfo; struct DataProcessorInfo; struct DataProcessingStates; +enum struct TerminationPolicy; namespace gui { /// Helper to display information about a device -void displayDeviceInspector(DeviceSpec const& spec, DeviceInfo const& info, DataProcessingStates const& states, DeviceMetricsInfo const& metrics, DataProcessorInfo const& metadata, DeviceControl& control); +void displayDeviceInspector(DeviceSpec const& spec, DeviceInfo const& info, DataProcessingStates const& states, + DeviceMetricsInfo const& metrics, DataProcessorInfo const& metadata, DeviceControl& control, + TerminationPolicy TerminationPolicy); } // namespace gui } // namespace o2::framework diff --git a/Framework/GUISupport/src/FrameworkGUIDevicesGraph.cxx b/Framework/GUISupport/src/FrameworkGUIDevicesGraph.cxx index 0b6ca07a9c86d..639122153e599 100644 --- a/Framework/GUISupport/src/FrameworkGUIDevicesGraph.cxx +++ b/Framework/GUISupport/src/FrameworkGUIDevicesGraph.cxx @@ -365,7 +365,8 @@ void showTopologyNodeGraph(WorkspaceGUIState& state, std::vector const& allStates, std::vector const& metadata, std::vector& controls, - std::vector const& metricsInfos) + std::vector const& metricsInfos, + enum TerminationPolicy terminationPolicy) { ImGui::SetNextWindowPos(ImVec2(0, 0), 0); if (state.bottomPaneVisible) { @@ -893,7 +894,7 @@ void showTopologyNodeGraph(WorkspaceGUIState& state, auto& metadatum = metadata[group.metadataId]; if (state.rightPaneVisible) { - gui::displayDeviceInspector(spec, info, states, metrics, metadatum, control); + gui::displayDeviceInspector(spec, info, states, metrics, metadatum, control, terminationPolicy); } } else { ImGui::TextWrapped("Select a node in the topology to display information about it"); diff --git a/Framework/GUISupport/src/FrameworkGUIDevicesGraph.h b/Framework/GUISupport/src/FrameworkGUIDevicesGraph.h index 7950f1893ebba..d53cdf26dd5a8 100644 --- a/Framework/GUISupport/src/FrameworkGUIDevicesGraph.h +++ b/Framework/GUISupport/src/FrameworkGUIDevicesGraph.h @@ -19,6 +19,11 @@ #include +namespace o2::framework +{ +enum struct TerminationPolicy; +} // namespace o2::framework + namespace o2::framework::gui { @@ -30,7 +35,8 @@ void showTopologyNodeGraph(WorkspaceGUIState& state, std::vector const& allStates, std::vector const& metadata, std::vector& controls, - std::vector const& metricsInfos); + std::vector const& metricsInfos, + TerminationPolicy terminationPolicy); } // namespace o2::framework::gui From 2aa06d700dd97b2a86a46fb27ee882bff8d068c2 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Wed, 8 Nov 2023 07:50:25 +0000 Subject: [PATCH 4/4] Please consider the following formatting changes --- .../CTP/workflowScalers/src/ctp-qc-proxy.cxx | 2 +- .../DCS/testWorkflow/src/DCStoDPLconverter.h | 2 +- .../DCS/testWorkflow/src/dcs-config-proxy.cxx | 2 +- .../EMCALCalibration/EMCALCalibParams.h | 20 +- .../DetectorsVertexing/PVertexerParams.h | 12 +- Framework/Core/src/PropertyTreeHelpers.h | 3 +- Framework/Core/test/test_Root2ArrowTable.cxx | 6 +- .../3rdparty/catch2/catch_amalgamated.cxx | 2109 +++++----- .../3rdparty/catch2/catch_amalgamated.hpp | 3385 +++++++++-------- .../src/DataSamplingReadoutAdapter.cxx | 2 +- run/o2sim_mctracks_proxy.cxx | 2 +- 11 files changed, 2817 insertions(+), 2728 deletions(-) diff --git a/Detectors/CTP/workflowScalers/src/ctp-qc-proxy.cxx b/Detectors/CTP/workflowScalers/src/ctp-qc-proxy.cxx index 2372ba07a28f7..a1f9b385fd81a 100644 --- a/Detectors/CTP/workflowScalers/src/ctp-qc-proxy.cxx +++ b/Detectors/CTP/workflowScalers/src/ctp-qc-proxy.cxx @@ -47,7 +47,7 @@ InjectorFunction dcs2dpl() // InjectorFunction dcs2dpl() { return [](TimingInfo&, ServiceRegistryRef const& services, fair::mq::Parts& parts, ChannelRetriever channelRetriever, size_t newTimesliceId, bool&) -> bool { - auto *device = services.get().device(); + auto* device = services.get().device(); std::string messageHeader{static_cast(parts.At(0)->GetData()), parts.At(0)->GetSize()}; size_t dataSize = parts.At(1)->GetSize(); std::string messageData{static_cast(parts.At(1)->GetData()), parts.At(1)->GetSize()}; diff --git a/Detectors/DCS/testWorkflow/src/DCStoDPLconverter.h b/Detectors/DCS/testWorkflow/src/DCStoDPLconverter.h index 4384628d01f4c..74bc332d31b88 100644 --- a/Detectors/DCS/testWorkflow/src/DCStoDPLconverter.h +++ b/Detectors/DCS/testWorkflow/src/DCStoDPLconverter.h @@ -54,7 +54,7 @@ o2f::InjectorFunction dcs2dpl(std::unordered_map& dp { return [dpid2group, fbiFirst, verbose, FBIPerInterval](o2::framework::TimingInfo& tinfo, framework::ServiceRegistryRef const& services, fair::mq::Parts& parts, o2f::ChannelRetriever channelRetriever, size_t newTimesliceId, bool& stop) -> bool { - auto *device = services.get().device(); + auto* device = services.get().device(); static std::unordered_map cache; // will keep only the latest measurement in the 1-second wide window for each DPID static std::unordered_map sentToChannel; static auto timer = std::chrono::high_resolution_clock::now(); diff --git a/Detectors/DCS/testWorkflow/src/dcs-config-proxy.cxx b/Detectors/DCS/testWorkflow/src/dcs-config-proxy.cxx index 9b697da428ad2..1cee1c71fd240 100644 --- a/Detectors/DCS/testWorkflow/src/dcs-config-proxy.cxx +++ b/Detectors/DCS/testWorkflow/src/dcs-config-proxy.cxx @@ -68,7 +68,7 @@ auto getDataOriginFromFilename(const std::string& filename) InjectorFunction dcs2dpl(const std::string& acknowledge) { return [acknowledge](TimingInfo&, ServiceRegistryRef const& services, fair::mq::Parts& parts, ChannelRetriever channelRetriever, size_t newTimesliceId, bool&) -> bool { - auto *device = services.get().device(); + auto* device = services.get().device(); if (parts.Size() == 0) { // received at ^c, ignore LOG(info) << "ignoring empty message"; return false; diff --git a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibParams.h b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibParams.h index daf2451843b5a..9277512ef36e3 100644 --- a/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibParams.h +++ b/Detectors/EMCAL/calibration/include/EMCALCalibration/EMCALCalibParams.h @@ -70,16 +70,16 @@ struct EMCALCalibParams : public o2::conf::ConfigurableParamHelper this value in \mus if >0, if <0: mult factor to ITS ROF - float maxZDiffDebrisExtra = 0.05; ///< don't consider vertices separated by Z > this value in cm - float maxMultRatDebrisExtra = 1.0; ///< don't consider vertices with multiplicity ratio above this - float maxChi2TZDebrisExtra = 100.; ///< don't consider vertices with mutual chi2 exceeding this (for pp should be ~10) - float addTimeSigma2DebrisExtra = 225.; ///< increment time error^2 by this amount when calculating vertex-to-vertex chi2 - float addZSigma2DebrisExtra = 1.e-3; ///< increment z error^2 by this amount when calculating vertex-to-vertex chi2 + float maxTDiffDebrisExtra = 0; ///< when reducing debris, don't consider vertices separated by time > this value in \mus if >0, if <0: mult factor to ITS ROF + float maxZDiffDebrisExtra = 0.05; ///< don't consider vertices separated by Z > this value in cm + float maxMultRatDebrisExtra = 1.0; ///< don't consider vertices with multiplicity ratio above this + float maxChi2TZDebrisExtra = 100.; ///< don't consider vertices with mutual chi2 exceeding this (for pp should be ~10) + float addTimeSigma2DebrisExtra = 225.; ///< increment time error^2 by this amount when calculating vertex-to-vertex chi2 + float addZSigma2DebrisExtra = 1.e-3; ///< increment z error^2 by this amount when calculating vertex-to-vertex chi2 float maxITSOnlyFraction = 1.0; ///< max ITS-only tracks fraction to accept, recommended value for PbPb = 0.85 float minITSOnlyFraction = 0.0; ///< min ITS-only tracks fraction to accept diff --git a/Framework/Core/src/PropertyTreeHelpers.h b/Framework/Core/src/PropertyTreeHelpers.h index fb200335585b4..d6589ff104b17 100644 --- a/Framework/Core/src/PropertyTreeHelpers.h +++ b/Framework/Core/src/PropertyTreeHelpers.h @@ -51,7 +51,8 @@ struct PropertyTreeHelpers { std::string const& propertyLabel); //using WalkerFunction = std::function; - template using WalkerFunction = std::function; + template + using WalkerFunction = std::function; /// Traverse the tree recursively calling @a WalkerFunction on each leaf. template static void traverse(boost::property_tree::ptree const& parent, WalkerFunction& method); diff --git a/Framework/Core/test/test_Root2ArrowTable.cxx b/Framework/Core/test/test_Root2ArrowTable.cxx index b22432d8565a5..178fb644681b5 100644 --- a/Framework/Core/test/test_Root2ArrowTable.cxx +++ b/Framework/Core/test/test_Root2ArrowTable.cxx @@ -92,9 +92,9 @@ TEST_CASE("RootTree2Table") REQUIRE(array->length() == 3000); const float* c = reinterpret_cast(array->values()->data()); - //auto array = std::static_pointer_cast(table->column(0)->chunk(0)); - //CHECK_EQUAL(array->byte_width(), sizeof(float[3])); - //const float* c = reinterpret_cast(array->Value(0)); + // auto array = std::static_pointer_cast(table->column(0)->chunk(0)); + // CHECK_EQUAL(array->byte_width(), sizeof(float[3])); + // const float* c = reinterpret_cast(array->Value(0)); CHECK(c[0] == 1); CHECK(c[1] == 2); diff --git a/Framework/Foundation/3rdparty/catch2/catch_amalgamated.cxx b/Framework/Foundation/3rdparty/catch2/catch_amalgamated.cxx index eba3f00ac4868..e99598db045eb 100644 --- a/Framework/Foundation/3rdparty/catch2/catch_amalgamated.cxx +++ b/Framework/Foundation/3rdparty/catch2/catch_amalgamated.cxx @@ -58,9 +58,6 @@ namespace Catch { } // namespace Benchmark } // namespace Catch - - - #include namespace Catch { @@ -97,171 +94,179 @@ namespace Catch { #include #endif -namespace Catch { - namespace Benchmark { - namespace Detail { - namespace { - - template - static sample - resample( URng& rng, - unsigned int resamples, - std::vector::const_iterator first, - std::vector::const_iterator last, - Estimator& estimator ) { - auto n = static_cast( last - first ); - std::uniform_int_distribution dist( 0, - n - 1 ); - - sample out; - out.reserve( resamples ); - // We allocate the vector outside the loop to avoid realloc - // per resample - std::vector resampled; - resampled.reserve( n ); - for ( size_t i = 0; i < resamples; ++i ) { - resampled.clear(); - for ( size_t s = 0; s < n; ++s ) { - resampled.push_back( - first[static_cast( - dist( rng ) )] ); - } - const auto estimate = - estimator( resampled.begin(), resampled.end() ); - out.push_back( estimate ); - } - std::sort( out.begin(), out.end() ); - return out; - } +namespace Catch +{ +namespace Benchmark +{ +namespace Detail +{ +namespace +{ + +template +static sample + resample(URng& rng, + unsigned int resamples, + std::vector::const_iterator first, + std::vector::const_iterator last, + Estimator& estimator) +{ + auto n = static_cast(last - first); + std::uniform_int_distribution dist(0, + n - 1); + + sample out; + out.reserve(resamples); + // We allocate the vector outside the loop to avoid realloc + // per resample + std::vector resampled; + resampled.reserve(n); + for (size_t i = 0; i < resamples; ++i) { + resampled.clear(); + for (size_t s = 0; s < n; ++s) { + resampled.push_back( + first[static_cast( + dist(rng))]); + } + const auto estimate = + estimator(resampled.begin(), resampled.end()); + out.push_back(estimate); + } + std::sort(out.begin(), out.end()); + return out; +} - static double outlier_variance( Estimate mean, - Estimate stddev, - int n ) { - double sb = stddev.point; - double mn = mean.point / n; - double mg_min = mn / 2.; - double sg = (std::min)( mg_min / 4., sb / std::sqrt( n ) ); - double sg2 = sg * sg; - double sb2 = sb * sb; - - auto c_max = [n, mn, sb2, sg2]( double x ) -> double { - double k = mn - x; - double d = k * k; - double nd = n * d; - double k0 = -n * nd; - double k1 = sb2 - n * sg2 + nd; - double det = k1 * k1 - 4 * sg2 * k0; - return static_cast( -2. * k0 / - ( k1 + std::sqrt( det ) ) ); - }; - - auto var_out = [n, sb2, sg2]( double c ) { - double nc = n - c; - return ( nc / n ) * ( sb2 - nc * sg2 ); - }; - - return (std::min)( var_out( 1 ), - var_out( - (std::min)( c_max( 0. ), - c_max( mg_min ) ) ) ) / - sb2; - } +static double outlier_variance(Estimate mean, + Estimate stddev, + int n) +{ + double sb = stddev.point; + double mn = mean.point / n; + double mg_min = mn / 2.; + double sg = (std::min)(mg_min / 4., sb / std::sqrt(n)); + double sg2 = sg * sg; + double sb2 = sb * sb; + + auto c_max = [n, mn, sb2, sg2](double x) -> double { + double k = mn - x; + double d = k * k; + double nd = n * d; + double k0 = -n * nd; + double k1 = sb2 - n * sg2 + nd; + double det = k1 * k1 - 4 * sg2 * k0; + return static_cast(-2. * k0 / + (k1 + std::sqrt(det))); + }; + + auto var_out = [n, sb2, sg2](double c) { + double nc = n - c; + return (nc / n) * (sb2 - nc * sg2); + }; + + return (std::min)(var_out(1), + var_out( + (std::min)(c_max(0.), + c_max(mg_min)))) / + sb2; +} - static double erf_inv( double x ) { - // Code accompanying the article "Approximating the erfinv - // function" in GPU Computing Gems, Volume 2 - double w, p; - - w = -log( ( 1.0 - x ) * ( 1.0 + x ) ); - - if ( w < 6.250000 ) { - w = w - 3.125000; - p = -3.6444120640178196996e-21; - p = -1.685059138182016589e-19 + p * w; - p = 1.2858480715256400167e-18 + p * w; - p = 1.115787767802518096e-17 + p * w; - p = -1.333171662854620906e-16 + p * w; - p = 2.0972767875968561637e-17 + p * w; - p = 6.6376381343583238325e-15 + p * w; - p = -4.0545662729752068639e-14 + p * w; - p = -8.1519341976054721522e-14 + p * w; - p = 2.6335093153082322977e-12 + p * w; - p = -1.2975133253453532498e-11 + p * w; - p = -5.4154120542946279317e-11 + p * w; - p = 1.051212273321532285e-09 + p * w; - p = -4.1126339803469836976e-09 + p * w; - p = -2.9070369957882005086e-08 + p * w; - p = 4.2347877827932403518e-07 + p * w; - p = -1.3654692000834678645e-06 + p * w; - p = -1.3882523362786468719e-05 + p * w; - p = 0.0001867342080340571352 + p * w; - p = -0.00074070253416626697512 + p * w; - p = -0.0060336708714301490533 + p * w; - p = 0.24015818242558961693 + p * w; - p = 1.6536545626831027356 + p * w; - } else if ( w < 16.000000 ) { - w = sqrt( w ) - 3.250000; - p = 2.2137376921775787049e-09; - p = 9.0756561938885390979e-08 + p * w; - p = -2.7517406297064545428e-07 + p * w; - p = 1.8239629214389227755e-08 + p * w; - p = 1.5027403968909827627e-06 + p * w; - p = -4.013867526981545969e-06 + p * w; - p = 2.9234449089955446044e-06 + p * w; - p = 1.2475304481671778723e-05 + p * w; - p = -4.7318229009055733981e-05 + p * w; - p = 6.8284851459573175448e-05 + p * w; - p = 2.4031110387097893999e-05 + p * w; - p = -0.0003550375203628474796 + p * w; - p = 0.00095328937973738049703 + p * w; - p = -0.0016882755560235047313 + p * w; - p = 0.0024914420961078508066 + p * w; - p = -0.0037512085075692412107 + p * w; - p = 0.005370914553590063617 + p * w; - p = 1.0052589676941592334 + p * w; - p = 3.0838856104922207635 + p * w; - } else { - w = sqrt( w ) - 5.000000; - p = -2.7109920616438573243e-11; - p = -2.5556418169965252055e-10 + p * w; - p = 1.5076572693500548083e-09 + p * w; - p = -3.7894654401267369937e-09 + p * w; - p = 7.6157012080783393804e-09 + p * w; - p = -1.4960026627149240478e-08 + p * w; - p = 2.9147953450901080826e-08 + p * w; - p = -6.7711997758452339498e-08 + p * w; - p = 2.2900482228026654717e-07 + p * w; - p = -9.9298272942317002539e-07 + p * w; - p = 4.5260625972231537039e-06 + p * w; - p = -1.9681778105531670567e-05 + p * w; - p = 7.5995277030017761139e-05 + p * w; - p = -0.00021503011930044477347 + p * w; - p = -0.00013871931833623122026 + p * w; - p = 1.0103004648645343977 + p * w; - p = 4.8499064014085844221 + p * w; - } - return p * x; - } +static double erf_inv(double x) +{ + // Code accompanying the article "Approximating the erfinv + // function" in GPU Computing Gems, Volume 2 + double w, p; + + w = -log((1.0 - x) * (1.0 + x)); + + if (w < 6.250000) { + w = w - 3.125000; + p = -3.6444120640178196996e-21; + p = -1.685059138182016589e-19 + p * w; + p = 1.2858480715256400167e-18 + p * w; + p = 1.115787767802518096e-17 + p * w; + p = -1.333171662854620906e-16 + p * w; + p = 2.0972767875968561637e-17 + p * w; + p = 6.6376381343583238325e-15 + p * w; + p = -4.0545662729752068639e-14 + p * w; + p = -8.1519341976054721522e-14 + p * w; + p = 2.6335093153082322977e-12 + p * w; + p = -1.2975133253453532498e-11 + p * w; + p = -5.4154120542946279317e-11 + p * w; + p = 1.051212273321532285e-09 + p * w; + p = -4.1126339803469836976e-09 + p * w; + p = -2.9070369957882005086e-08 + p * w; + p = 4.2347877827932403518e-07 + p * w; + p = -1.3654692000834678645e-06 + p * w; + p = -1.3882523362786468719e-05 + p * w; + p = 0.0001867342080340571352 + p * w; + p = -0.00074070253416626697512 + p * w; + p = -0.0060336708714301490533 + p * w; + p = 0.24015818242558961693 + p * w; + p = 1.6536545626831027356 + p * w; + } else if (w < 16.000000) { + w = sqrt(w) - 3.250000; + p = 2.2137376921775787049e-09; + p = 9.0756561938885390979e-08 + p * w; + p = -2.7517406297064545428e-07 + p * w; + p = 1.8239629214389227755e-08 + p * w; + p = 1.5027403968909827627e-06 + p * w; + p = -4.013867526981545969e-06 + p * w; + p = 2.9234449089955446044e-06 + p * w; + p = 1.2475304481671778723e-05 + p * w; + p = -4.7318229009055733981e-05 + p * w; + p = 6.8284851459573175448e-05 + p * w; + p = 2.4031110387097893999e-05 + p * w; + p = -0.0003550375203628474796 + p * w; + p = 0.00095328937973738049703 + p * w; + p = -0.0016882755560235047313 + p * w; + p = 0.0024914420961078508066 + p * w; + p = -0.0037512085075692412107 + p * w; + p = 0.005370914553590063617 + p * w; + p = 1.0052589676941592334 + p * w; + p = 3.0838856104922207635 + p * w; + } else { + w = sqrt(w) - 5.000000; + p = -2.7109920616438573243e-11; + p = -2.5556418169965252055e-10 + p * w; + p = 1.5076572693500548083e-09 + p * w; + p = -3.7894654401267369937e-09 + p * w; + p = 7.6157012080783393804e-09 + p * w; + p = -1.4960026627149240478e-08 + p * w; + p = 2.9147953450901080826e-08 + p * w; + p = -6.7711997758452339498e-08 + p * w; + p = 2.2900482228026654717e-07 + p * w; + p = -9.9298272942317002539e-07 + p * w; + p = 4.5260625972231537039e-06 + p * w; + p = -1.9681778105531670567e-05 + p * w; + p = 7.5995277030017761139e-05 + p * w; + p = -0.00021503011930044477347 + p * w; + p = -0.00013871931833623122026 + p * w; + p = 1.0103004648645343977 + p * w; + p = 4.8499064014085844221 + p * w; + } + return p * x; +} - static double - standard_deviation( std::vector::const_iterator first, - std::vector::const_iterator last ) { - auto m = Catch::Benchmark::Detail::mean( first, last ); - double variance = - std::accumulate( first, - last, - 0., - [m]( double a, double b ) { - double diff = b - m; - return a + diff * diff; - } ) / - ( last - first ); - return std::sqrt( variance ); - } +static double + standard_deviation(std::vector::const_iterator first, + std::vector::const_iterator last) +{ + auto m = Catch::Benchmark::Detail::mean(first, last); + double variance = + std::accumulate(first, + last, + 0., + [m](double a, double b) { + double diff = b - m; + return a + diff * diff; + }) / + (last - first); + return std::sqrt(variance); +} - } // namespace - } // namespace Detail - } // namespace Benchmark +} // namespace +} // namespace Detail +} // namespace Benchmark } // namespace Catch namespace Catch { @@ -293,47 +298,48 @@ namespace Catch { } OutlierClassification - classify_outliers( std::vector::const_iterator first, - std::vector::const_iterator last ) { - std::vector copy( first, last ); - - auto q1 = weighted_average_quantile( 1, 4, copy.begin(), copy.end() ); - auto q3 = weighted_average_quantile( 3, 4, copy.begin(), copy.end() ); - auto iqr = q3 - q1; - auto los = q1 - ( iqr * 3. ); - auto lom = q1 - ( iqr * 1.5 ); - auto him = q3 + ( iqr * 1.5 ); - auto his = q3 + ( iqr * 3. ); - - OutlierClassification o; - for ( ; first != last; ++first ) { - const double t = *first; - if ( t < los ) { - ++o.low_severe; - } else if ( t < lom ) { - ++o.low_mild; - } else if ( t > his ) { - ++o.high_severe; - } else if ( t > him ) { - ++o.high_mild; - } - ++o.samples_seen; + classify_outliers(std::vector::const_iterator first, + std::vector::const_iterator last) + { + std::vector copy(first, last); + + auto q1 = weighted_average_quantile(1, 4, copy.begin(), copy.end()); + auto q3 = weighted_average_quantile(3, 4, copy.begin(), copy.end()); + auto iqr = q3 - q1; + auto los = q1 - (iqr * 3.); + auto lom = q1 - (iqr * 1.5); + auto him = q3 + (iqr * 1.5); + auto his = q3 + (iqr * 3.); + + OutlierClassification o; + for (; first != last; ++first) { + const double t = *first; + if (t < los) { + ++o.low_severe; + } else if (t < lom) { + ++o.low_mild; + } else if (t > his) { + ++o.high_severe; + } else if (t > him) { + ++o.high_mild; } - return o; + ++o.samples_seen; + } + return o; } - double mean( std::vector::const_iterator first, - std::vector::const_iterator last ) { - auto count = last - first; - double sum = 0.; - while (first != last) { - sum += *first; - ++first; - } - return sum / static_cast(count); + double mean(std::vector::const_iterator first, + std::vector::const_iterator last) + { + auto count = last - first; + double sum = 0.; + while (first != last) { + sum += *first; + ++first; + } + return sum / static_cast(count); } - double erfc_inv(double x) { return erf_inv(1.0 - x); } @@ -357,44 +363,45 @@ namespace Catch { bootstrap_analysis analyse_samples(double confidence_level, unsigned int n_resamples, std::vector::iterator first, - std::vector::iterator last) { - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS - static std::random_device entropy; - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION + std::vector::iterator last) + { + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS + static std::random_device entropy; + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION - auto n = static_cast(last - first); // seriously, one can't use integral types without hell in C++ + auto n = static_cast(last - first); // seriously, one can't use integral types without hell in C++ - auto mean = &Detail::mean; - auto stddev = &standard_deviation; + auto mean = &Detail::mean; + auto stddev = &standard_deviation; #if defined(CATCH_CONFIG_USE_ASYNC) - auto Estimate = [=](double(*f)(std::vector::const_iterator, - std::vector::const_iterator)) { - auto seed = entropy(); - return std::async(std::launch::async, [=] { - std::mt19937 rng(seed); - auto resampled = resample(rng, n_resamples, first, last, f); - return bootstrap(confidence_level, first, last, resampled, f); - }); - }; - - auto mean_future = Estimate(mean); - auto stddev_future = Estimate(stddev); - - auto mean_estimate = mean_future.get(); - auto stddev_estimate = stddev_future.get(); + auto Estimate = [=](double (*f)(std::vector::const_iterator, + std::vector::const_iterator)) { + auto seed = entropy(); + return std::async(std::launch::async, [=] { + std::mt19937 rng(seed); + auto resampled = resample(rng, n_resamples, first, last, f); + return bootstrap(confidence_level, first, last, resampled, f); + }); + }; + + auto mean_future = Estimate(mean); + auto stddev_future = Estimate(stddev); + + auto mean_estimate = mean_future.get(); + auto stddev_estimate = stddev_future.get(); #else - auto Estimate = [=](double(*f)(std::vector::const_iterator, - std::vector::const_iterator)) { - auto seed = entropy(); - std::mt19937 rng(seed); - auto resampled = resample(rng, n_resamples, first, last, f); - return bootstrap(confidence_level, first, last, resampled, f); - }; - - auto mean_estimate = Estimate(mean); - auto stddev_estimate = Estimate(stddev); + auto Estimate = [=](double (*f)(std::vector::const_iterator, + std::vector::const_iterator)) { + auto seed = entropy(); + std::mt19937 rng(seed); + auto resampled = resample(rng, n_resamples, first, last, f); + return bootstrap(confidence_level, first, last, resampled, f); + }; + + auto mean_estimate = Estimate(mean); + auto stddev_estimate = Estimate(stddev); #endif // CATCH_USE_ASYNC double outlier_variance = Detail::outlier_variance(mean_estimate, stddev_estimate, n); @@ -543,16 +550,16 @@ namespace Catch { } std::string AssertionResult::getExpressionInMacro() const { - if ( m_info.macroName.empty() ) { - return static_cast( m_info.capturedExpression ); - } - std::string expr; - expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 ); - expr += m_info.macroName; - expr += "( "; - expr += m_info.capturedExpression; - expr += " )"; - return expr; + if (m_info.macroName.empty()) { + return static_cast(m_info.capturedExpression); + } + std::string expr; + 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 { @@ -848,39 +855,38 @@ namespace Catch { } } - - Capturer::Capturer( StringRef macroName, - SourceLineInfo const& lineInfo, - ResultWas::OfType resultType, - StringRef names ): - m_resultCapture( getResultCapture() ) { - auto trimmed = [&] (size_t start, size_t end) { - while (names[start] == ',' || isspace(static_cast(names[start]))) { - ++start; - } - while (names[end] == ',' || isspace(static_cast(names[end]))) { - --end; - } - return names.substr(start, end - start + 1); - }; - auto skipq = [&] (size_t start, char quote) { - for (auto i = start + 1; i < names.size() ; ++i) { - if (names[i] == quote) - return i; - if (names[i] == '\\') - ++i; - } - CATCH_INTERNAL_ERROR("CAPTURE parsing encountered unmatched quote"); - }; - - size_t start = 0; - std::stack openings; - for (size_t pos = 0; pos < names.size(); ++pos) { - char c = names[pos]; - switch (c) { - case '[': - case '{': - case '(': + Capturer::Capturer(StringRef macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType resultType, + StringRef names) : m_resultCapture(getResultCapture()) + { + auto trimmed = [&](size_t start, size_t end) { + while (names[start] == ',' || isspace(static_cast(names[start]))) { + ++start; + } + while (names[end] == ',' || isspace(static_cast(names[end]))) { + --end; + } + return names.substr(start, end - start + 1); + }; + auto skipq = [&](size_t start, char quote) { + for (auto i = start + 1; i < names.size(); ++i) { + if (names[i] == quote) + return i; + if (names[i] == '\\') + ++i; + } + CATCH_INTERNAL_ERROR("CAPTURE parsing encountered unmatched quote"); + }; + + size_t start = 0; + std::stack 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 '<': @@ -927,9 +933,6 @@ namespace Catch { } // end namespace Catch - - - #include namespace Catch { @@ -942,8 +945,9 @@ namespace Catch { public: // IRegistryHub RegistryHub() = default; - ReporterRegistry const& getReporterRegistry() const override { - return m_reporterRegistry; + ReporterRegistry const& getReporterRegistry() const override + { + return m_reporterRegistry; } ITestCaseRegistry const& getTestCaseRegistry() const override { return m_testCaseRegistry; @@ -1501,40 +1505,40 @@ namespace Catch { for (size_t idx = 0; idx < originalTags.size(); ++idx) { auto c = originalTags[idx]; if (c == '[') { - CATCH_ENFORCE( - !inTag, - "Found '[' inside a tag while registering test case '" - << _nameAndTags.name << "' at " << _lineInfo ); + CATCH_ENFORCE( + !inTag, + "Found '[' inside a tag while registering test case '" + << _nameAndTags.name << "' at " << _lineInfo); - inTag = true; - tagStart = idx; + inTag = true; + tagStart = idx; } if (c == ']') { - CATCH_ENFORCE( - inTag, - "Found unmatched ']' while registering test case '" - << _nameAndTags.name << "' at " << _lineInfo ); - - inTag = false; - tagEnd = idx; - assert(tagStart < tagEnd); - - // We need to check the tag for special meanings, copy - // it over to backing storage and actually reference the - // backing storage in the saved tags - StringRef tagStr = originalTags.substr(tagStart+1, tagEnd - tagStart - 1); - CATCH_ENFORCE( !tagStr.empty(), - "Found an empty tag while registering test case '" - << _nameAndTags.name << "' at " - << _lineInfo ); - - enforceNotReservedTag(tagStr, lineInfo); - properties |= parseSpecialTag(tagStr); - // When copying a tag to the backing storage, we need to - // check if it is a merged hide tag, such as [.foo], and - // if it is, we need to handle it as if it was [foo]. - if (tagStr.size() > 1 && tagStr[0] == '.') { - tagStr = tagStr.substr(1, tagStr.size() - 1); + CATCH_ENFORCE( + inTag, + "Found unmatched ']' while registering test case '" + << _nameAndTags.name << "' at " << _lineInfo); + + inTag = false; + tagEnd = idx; + assert(tagStart < tagEnd); + + // We need to check the tag for special meanings, copy + // it over to backing storage and actually reference the + // backing storage in the saved tags + StringRef tagStr = originalTags.substr(tagStart + 1, tagEnd - tagStart - 1); + CATCH_ENFORCE(!tagStr.empty(), + "Found an empty tag while registering test case '" + << _nameAndTags.name << "' at " + << _lineInfo); + + enforceNotReservedTag(tagStr, lineInfo); + properties |= parseSpecialTag(tagStr); + // When copying a tag to the backing storage, we need to + // check if it is a merged hide tag, such as [.foo], and + // if it is, we need to handle it as if it was [foo]. + if (tagStr.size() > 1 && tagStr[0] == '.') { + tagStr = tagStr.substr(1, tagStr.size() - 1); } // We skip over dealing with the [.] tag, as we will add // it later unconditionally and then sort and unique all @@ -1542,10 +1546,9 @@ namespace Catch { internalAppendTag(tagStr); } } - CATCH_ENFORCE( !inTag, - "Found an unclosed tag while registering test case '" - << _nameAndTags.name << "' at " << _lineInfo ); - + CATCH_ENFORCE(!inTag, + "Found an unclosed tag while registering test case '" + << _nameAndTags.name << "' at " << _lineInfo); // Add [.] if relevant if (isHidden()) { @@ -1722,19 +1725,20 @@ namespace Catch { return std::any_of( m_filters.begin(), m_filters.end(), [&]( Filter const& f ){ return f.matches( testCase ); } ); } - TestSpec::Matches TestSpec::matchesByFilter( std::vector const& testCases, IConfig const& config ) const { - Matches matches; - matches.reserve( m_filters.size() ); - for ( auto const& filter : m_filters ) { - std::vector currentMatches; - for ( auto const& test : testCases ) - if ( isThrowSafe( test, config ) && - filter.matches( test.getTestCaseInfo() ) ) - currentMatches.emplace_back( &test ); - matches.push_back( - FilterMatch{ extractFilterName( filter ), currentMatches } ); - } - return matches; + TestSpec::Matches TestSpec::matchesByFilter(std::vector const& testCases, IConfig const& config) const + { + Matches matches; + matches.reserve(m_filters.size()); + for (auto const& filter : m_filters) { + std::vector currentMatches; + for (auto const& test : testCases) + if (isThrowSafe(test, config) && + filter.matches(test.getTestCaseInfo())) + currentMatches.emplace_back(&test); + matches.push_back( + FilterMatch{extractFilterName(filter), currentMatches}); + } + return matches; } const TestSpec::vectorStrings& TestSpec::getInvalidSpecs() const { @@ -2089,20 +2093,19 @@ namespace Catch { } - - - -namespace Catch { - namespace Detail { - void registerTranslatorImpl( - Detail::unique_ptr&& translator ) { - getMutableRegistryHub().registerTranslator( - CATCH_MOVE( translator ) ); - } - } // namespace Detail +namespace Catch +{ +namespace Detail +{ +void registerTranslatorImpl( + Detail::unique_ptr&& translator) +{ + getMutableRegistryHub().registerTranslator( + CATCH_MOVE(translator)); +} +} // namespace Detail } // namespace Catch - #include namespace Catch { @@ -2133,8 +2136,8 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 3, 4, 0, "", 0 ); - return version; + static Version version(3, 4, 0, "", 0); + return version; } } @@ -2284,14 +2287,14 @@ namespace Catch { infoMessages( _infoMessages ), totals( _totals ) { - 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.m_info.message = static_cast(assertionResult.getMessage()); + 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.m_info.message = static_cast(assertionResult.getMessage()); - infoMessages.push_back( CATCH_MOVE(builder.m_info) ); - } + infoMessages.push_back(CATCH_MOVE(builder.m_info)); + } } SectionStats::SectionStats( SectionInfo&& _sectionInfo, @@ -2304,17 +2307,16 @@ namespace Catch { missingAssertions( _missingAssertions ) {} - - TestCaseStats::TestCaseStats( TestCaseInfo const& _testInfo, - Totals const& _totals, - std::string&& _stdOut, - std::string&& _stdErr, - bool _aborting ) - : testInfo( &_testInfo ), - totals( _totals ), - stdOut( CATCH_MOVE(_stdOut) ), - stdErr( CATCH_MOVE(_stdErr) ), - aborting( _aborting ) + TestCaseStats::TestCaseStats(TestCaseInfo const& _testInfo, + Totals const& _totals, + std::string&& _stdOut, + std::string&& _stdErr, + bool _aborting) + : testInfo(&_testInfo), + totals(_totals), + stdOut(CATCH_MOVE(_stdOut)), + stdErr(CATCH_MOVE(_stdErr)), + aborting(_aborting) {} @@ -2338,15 +2340,11 @@ namespace Catch { EventListenerFactory::~EventListenerFactory() = default; } - - - -namespace Catch { - ITestCaseRegistry::~ITestCaseRegistry() = default; +namespace Catch +{ +ITestCaseRegistry::~ITestCaseRegistry() = default; } - - namespace Catch { AssertionHandler::AssertionHandler @@ -2357,7 +2355,7 @@ namespace Catch { : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition }, m_resultCapture( getResultCapture() ) { - m_resultCapture.notifyAssertionStarted( m_assertionInfo ); + m_resultCapture.notifyAssertionStarted(m_assertionInfo); } void AssertionHandler::handleExpr( ITransientExpression const& expr ) { @@ -2372,20 +2370,20 @@ namespace Catch { } void AssertionHandler::complete() { - m_completed = true; - if( m_reaction.shouldDebugBreak ) { + m_completed = true; + 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) + // 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(); + // (To go back to the test and change execution, jump over the throw, next) + CATCH_BREAK_INTO_DEBUGGER(); } if (m_reaction.shouldThrow) { throw_test_failure_exception(); } if ( m_reaction.shouldSkip ) { - throw_test_skip_exception(); + throw_test_skip_exception(); } } @@ -3015,7 +3013,7 @@ namespace Catch { auto const& reporterSpec = *parsed; auto const& factories = - getRegistryHub().getReporterRegistry().getFactories(); + getRegistryHub().getReporterRegistry().getFactories(); auto result = factories.find( reporterSpec.name() ); if ( result == factories.end() ) { @@ -3252,13 +3250,14 @@ namespace Catch { namespace { //! A do-nothing implementation of colour, used as fallback for unknown //! platforms, and when the user asks to deactivate all colours. - class NoColourImpl final : public ColourImpl { - public: - NoColourImpl( IStream* stream ): ColourImpl( stream ) {} + class NoColourImpl final : public ColourImpl + { + public: + NoColourImpl(IStream* stream) : ColourImpl(stream) {} - private: - void use( Colour::Code ) const override {} - }; + private: + void use(Colour::Code) const override {} + }; } // namespace @@ -3270,57 +3269,75 @@ namespace Catch { namespace Catch { namespace { - class Win32ColourImpl final : public ColourImpl { - public: - Win32ColourImpl(IStream* stream): - ColourImpl(stream) { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE ), - &csbiInfo ); - originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); - originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); - } - - static bool useImplementationForStream(IStream const& stream) { - // Win32 text colour APIs can only be used on console streams - // We cannot check that the output hasn't been redirected, - // so we just check that the original stream is console stream. - return stream.isConsole(); - } - - private: - void use( Colour::Code _colourCode ) const 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 ); +class Win32ColourImpl final : public ColourImpl +{ + public: + Win32ColourImpl(IStream* stream) : ColourImpl(stream) + { + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), + &csbiInfo); + originalForegroundAttributes = csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY); + originalBackgroundAttributes = csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY); + } - case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" ); + static bool useImplementationForStream(IStream const& stream) + { + // Win32 text colour APIs can only be used on console streams + // We cannot check that the output hasn't been redirected, + // so we just check that the original stream is console stream. + return stream.isConsole(); + } - default: - CATCH_ERROR( "Unknown colour requested" ); - } - } + private: + void use(Colour::Code _colourCode) const 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"); + } + } - void setTextAttribute( WORD _textAttribute ) const { - SetConsoleTextAttribute( GetStdHandle( STD_OUTPUT_HANDLE ), - _textAttribute | - originalBackgroundAttributes ); - } - WORD originalForegroundAttributes; - WORD originalBackgroundAttributes; - }; + void setTextAttribute(WORD _textAttribute) const + { + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), + _textAttribute | + originalBackgroundAttributes); + } + WORD originalForegroundAttributes; + WORD originalBackgroundAttributes; +}; } // end anon namespace } // end namespace Catch @@ -3336,19 +3353,21 @@ namespace { namespace Catch { namespace { - class ANSIColourImpl final : public ColourImpl { - public: - ANSIColourImpl( IStream* stream ): ColourImpl( stream ) {} - - static bool useImplementationForStream(IStream const& stream) { - // This is kinda messy due to trying to support a bunch of - // different platforms at once. - // The basic idea is that if we are asked to do autodetection (as - // opposed to being told to use posixy colours outright), then we - // only want to use the colours if we are writing to console. - // However, console might be redirected, so we make an attempt at - // checking for that on platforms where we know how to do that. - bool useColour = stream.isConsole(); +class ANSIColourImpl final : public ColourImpl +{ + public: + ANSIColourImpl(IStream* stream) : ColourImpl(stream) {} + + static bool useImplementationForStream(IStream const& stream) + { + // This is kinda messy due to trying to support a bunch of + // different platforms at once. + // The basic idea is that if we are asked to do autodetection (as + // opposed to being told to use posixy colours outright), then we + // only want to use the colours if we are writing to console. + // However, console might be redirected, so we make an attempt at + // checking for that on platforms where we know how to do that. + bool useColour = stream.isConsole(); #if defined( CATCH_INTERNAL_HAS_ISATTY ) && \ !( defined( __DJGPP__ ) && defined( __STRICT_ANSI__ ) ) ErrnoGuard _; // for isatty @@ -3390,7 +3409,7 @@ namespace { default: CATCH_INTERNAL_ERROR( "Unknown colour requested" ); } } - }; +}; } // end anon namespace } // end namespace Catch @@ -3452,31 +3471,38 @@ namespace Catch { namespace Catch { - Context* Context::currentContext = nullptr; +Context* Context::currentContext = nullptr; - void cleanUpContext() { - delete Context::currentContext; - Context::currentContext = nullptr; - } - void Context::createContext() { - currentContext = new Context(); - } +void cleanUpContext() +{ + delete Context::currentContext; + Context::currentContext = nullptr; +} +void Context::createContext() +{ + currentContext = new Context(); +} - Context& getCurrentMutableContext() { - if ( !Context::currentContext ) { Context::createContext(); } - // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn) - return *Context::currentContext; - } +Context& getCurrentMutableContext() +{ + if (!Context::currentContext) { + Context::createContext(); + } + // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn) + return *Context::currentContext; +} - void Context::setResultCapture( IResultCapture* resultCapture ) { - m_resultCapture = resultCapture; - } +void Context::setResultCapture(IResultCapture* resultCapture) +{ + m_resultCapture = resultCapture; +} - void Context::setConfig( IConfig const* config ) { m_config = config; } +void Context::setConfig(IConfig const* config) { m_config = config; } - SimplePcg32& sharedRng() { - static SimplePcg32 s_rng; - return s_rng; +SimplePcg32& sharedRng() +{ + static SimplePcg32 s_rng; + return s_rng; } } @@ -3753,25 +3779,25 @@ namespace Catch { ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; } } - - #include namespace Catch { - namespace { - static std::string tryTranslators( - std::vector< - Detail::unique_ptr> const& translators ) { - if ( translators.empty() ) { - std::rethrow_exception( std::current_exception() ); - } else { - return translators[0]->translate( translators.begin() + 1, - translators.end() ); - } - } +namespace +{ +static std::string tryTranslators( + std::vector< + Detail::unique_ptr> const& translators) +{ + if (translators.empty()) { + std::rethrow_exception(std::current_exception()); + } else { + return translators[0]->translate(translators.begin() + 1, + translators.end()); + } +} - } +} // namespace ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() { } @@ -3797,7 +3823,7 @@ namespace Catch { // First we try user-registered translators. If none of them can // handle the exception, it will be rethrown handled by our defaults. try { - return tryTranslators(m_translators); + return tryTranslators(m_translators); } // To avoid having to handle TFE explicitly everywhere, we just // rethrow it so that it goes back up the caller. @@ -3826,7 +3852,6 @@ namespace Catch { CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!"); } #endif - } @@ -4130,41 +4155,46 @@ namespace Catch { namespace Detail { namespace { - template - class StreamBufImpl final : public std::streambuf { - char data[bufferSize]; - WriterF m_writer; + template + class StreamBufImpl final : public std::streambuf + { + char data[bufferSize]; + WriterF m_writer; - public: - StreamBufImpl() { - setp( data, data + sizeof(data) ); - } + public: + StreamBufImpl() + { + setp(data, data + sizeof(data)); + } - ~StreamBufImpl() noexcept override { - StreamBufImpl::sync(); - } + ~StreamBufImpl() noexcept override + { + StreamBufImpl::sync(); + } - private: - int overflow( int c ) override { - sync(); + private: + int overflow(int c) override + { + sync(); - if( c != EOF ) { - if( pbase() == epptr() ) - m_writer( std::string( 1, static_cast( c ) ) ); - else - sputc( static_cast( c ) ); - } - return 0; - } + if (c != EOF) { + if (pbase() == epptr()) + m_writer(std::string(1, static_cast(c))); + else + sputc(static_cast(c)); + } + return 0; + } - int sync() override { - if( pbase() != pptr() ) { - m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); - setp( pbase(), epptr() ); - } - return 0; - } - }; + int sync() override + { + if (pbase() != pptr()) { + m_writer(std::string(pbase(), static_cast(pptr() - pbase()))); + setp(pbase(), epptr()); + } + return 0; + } + }; /////////////////////////////////////////////////////////////////////////// @@ -4179,34 +4209,41 @@ namespace Detail { /////////////////////////////////////////////////////////////////////////// - class FileStream final : public IStream { - std::ofstream m_ofs; - public: - FileStream( std::string const& filename ) { - m_ofs.open( filename.c_str() ); - CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << '\'' ); - m_ofs << std::unitbuf; - } - ~FileStream() override = default; - public: // IStream - std::ostream& stream() override { - return m_ofs; - } + class FileStream final : public IStream + { + std::ofstream m_ofs; + + public: + FileStream(std::string const& filename) + { + m_ofs.open(filename.c_str()); + CATCH_ENFORCE(!m_ofs.fail(), "Unable to open file: '" << filename << '\''); + m_ofs << std::unitbuf; + } + ~FileStream() override = default; + + public: // IStream + std::ostream& stream() override + { + return m_ofs; + } }; /////////////////////////////////////////////////////////////////////////// - class CoutStream final : public IStream { - 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; + class CoutStream final : public IStream + { + std::ostream m_os; - public: // IStream - std::ostream& stream() override { return m_os; } - bool isConsole() const override { return true; } + 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() override { return m_os; } + bool isConsole() const override { return true; } }; class CerrStream : public IStream { @@ -4225,19 +4262,22 @@ namespace Detail { /////////////////////////////////////////////////////////////////////////// - class DebugOutStream final : public IStream { - Detail::unique_ptr> m_streamBuf; - std::ostream m_os; - public: - DebugOutStream() - : m_streamBuf( Detail::make_unique>() ), - m_os( m_streamBuf.get() ) - {} + class DebugOutStream final : public IStream + { + Detail::unique_ptr> m_streamBuf; + std::ostream m_os; - ~DebugOutStream() override = default; + public: + DebugOutStream() + : m_streamBuf(Detail::make_unique>()), + m_os(m_streamBuf.get()) + { + } - public: // IStream - std::ostream& stream() override { return m_os; } + ~DebugOutStream() override = default; + + public: // IStream + std::ostream& stream() override { return m_os; } }; } // unnamed namespace @@ -4774,75 +4814,76 @@ namespace Catch { namespace Catch { - struct ReporterRegistry::ReporterRegistryImpl { - std::vector> listeners; - std::map - factories; - }; +struct ReporterRegistry::ReporterRegistryImpl { + std::vector> listeners; + std::map + factories; +}; - ReporterRegistry::ReporterRegistry(): - m_impl( Detail::make_unique() ) { - // Because it is impossible to move out of initializer list, - // we have to add the elements manually - m_impl->factories["Automake"] = - Detail::make_unique>(); - m_impl->factories["compact"] = - Detail::make_unique>(); - m_impl->factories["console"] = - Detail::make_unique>(); - m_impl->factories["JUnit"] = - Detail::make_unique>(); - m_impl->factories["SonarQube"] = - Detail::make_unique>(); - m_impl->factories["TAP"] = - Detail::make_unique>(); - m_impl->factories["TeamCity"] = - Detail::make_unique>(); - m_impl->factories["XML"] = - Detail::make_unique>(); - } +ReporterRegistry::ReporterRegistry() : m_impl(Detail::make_unique()) +{ + // Because it is impossible to move out of initializer list, + // we have to add the elements manually + m_impl->factories["Automake"] = + Detail::make_unique>(); + m_impl->factories["compact"] = + Detail::make_unique>(); + m_impl->factories["console"] = + Detail::make_unique>(); + m_impl->factories["JUnit"] = + Detail::make_unique>(); + m_impl->factories["SonarQube"] = + Detail::make_unique>(); + m_impl->factories["TAP"] = + Detail::make_unique>(); + m_impl->factories["TeamCity"] = + Detail::make_unique>(); + m_impl->factories["XML"] = + Detail::make_unique>(); +} ReporterRegistry::~ReporterRegistry() = default; IEventListenerPtr - ReporterRegistry::create( std::string const& name, - ReporterConfig&& config ) const { - auto it = m_impl->factories.find( name ); - if ( it == m_impl->factories.end() ) return nullptr; - return it->second->create( CATCH_MOVE( config ) ); - } - - void ReporterRegistry::registerReporter( std::string const& name, - IReporterFactoryPtr factory ) { - CATCH_ENFORCE( name.find( "::" ) == name.npos, - "'::' is not allowed in reporter name: '" + name + - '\'' ); - auto ret = m_impl->factories.emplace( name, CATCH_MOVE( factory ) ); - CATCH_ENFORCE( ret.second, - "reporter using '" + name + - "' as name was already registered" ); + ReporterRegistry::create(std::string const& name, + ReporterConfig&& config) const + { + auto it = m_impl->factories.find(name); + if (it == m_impl->factories.end()) + return nullptr; + return it->second->create(CATCH_MOVE(config)); + } + + void ReporterRegistry::registerReporter(std::string const& name, + IReporterFactoryPtr factory) + { + CATCH_ENFORCE(name.find("::") == name.npos, + "'::' is not allowed in reporter name: '" + name + + '\''); + auto ret = m_impl->factories.emplace(name, CATCH_MOVE(factory)); + CATCH_ENFORCE(ret.second, + "reporter using '" + name + + "' as name was already registered"); } void ReporterRegistry::registerListener( Detail::unique_ptr factory ) { - m_impl->listeners.push_back( CATCH_MOVE( factory ) ); + m_impl->listeners.push_back(CATCH_MOVE(factory)); } std::map const& - ReporterRegistry::getFactories() const { - return m_impl->factories; + ReporterRegistry::getFactories() const + { + return m_impl->factories; } std::vector> const& - ReporterRegistry::getListeners() const { - return m_impl->listeners; + ReporterRegistry::getListeners() const + { + return m_impl->listeners; } -} // namespace Catch - - - - + } // namespace Catch #include @@ -4854,12 +4895,12 @@ namespace Catch { }; kvPair splitKVPair(StringRef kvString) { - auto splitPos = static_cast( - std::find( kvString.begin(), kvString.end(), '=' ) - - kvString.begin() ); + auto splitPos = static_cast( + std::find(kvString.begin(), kvString.end(), '=') - + kvString.begin()); - return { kvString.substr( 0, splitPos ), - kvString.substr( splitPos + 1, kvString.size() ) }; + return {kvString.substr(0, splitPos), + kvString.substr(splitPos + 1, kvString.size())}; } } @@ -5088,153 +5129,164 @@ namespace Catch { namespace Catch { namespace Generators { - namespace { - struct GeneratorTracker final : TestCaseTracking::TrackerBase, - IGeneratorTracker { - GeneratorBasePtr m_generator; - - GeneratorTracker( - TestCaseTracking::NameAndLocation&& nameAndLocation, - TrackerContext& ctx, - ITracker* parent ): - TrackerBase( CATCH_MOVE( nameAndLocation ), ctx, parent ) {} - ~GeneratorTracker() override = default; - - static GeneratorTracker* - acquire( TrackerContext& ctx, - TestCaseTracking::NameAndLocationRef const& - nameAndLocation ) { - GeneratorTracker* tracker; - - ITracker& currentTracker = ctx.currentTracker(); - // Under specific circumstances, the generator we want - // to acquire is also the current tracker. If this is - // the case, we have to avoid looking through current - // tracker's children, and instead return the current - // tracker. - // A case where this check is important is e.g. - // for (int i = 0; i < 5; ++i) { - // int n = GENERATE(1, 2); - // } - // - // without it, the code above creates 5 nested generators. - if ( currentTracker.nameAndLocation() == nameAndLocation ) { - auto thisTracker = currentTracker.parent()->findChild( - nameAndLocation ); - assert( thisTracker ); - assert( thisTracker->isGeneratorTracker() ); - tracker = static_cast( thisTracker ); - } else if ( ITracker* childTracker = - currentTracker.findChild( - nameAndLocation ) ) { - assert( childTracker ); - assert( childTracker->isGeneratorTracker() ); - tracker = - static_cast( childTracker ); - } else { - return nullptr; - } + namespace + { + struct GeneratorTracker final : TestCaseTracking::TrackerBase, + IGeneratorTracker { + GeneratorBasePtr m_generator; + + GeneratorTracker( + TestCaseTracking::NameAndLocation&& nameAndLocation, + TrackerContext& ctx, + ITracker* parent) : TrackerBase(CATCH_MOVE(nameAndLocation), ctx, parent) {} + ~GeneratorTracker() override = default; + + static GeneratorTracker* + acquire(TrackerContext& ctx, + TestCaseTracking::NameAndLocationRef const& + nameAndLocation) + { + GeneratorTracker* tracker; - if ( !tracker->isComplete() ) { tracker->open(); } + ITracker& currentTracker = ctx.currentTracker(); + // Under specific circumstances, the generator we want + // to acquire is also the current tracker. If this is + // the case, we have to avoid looking through current + // tracker's children, and instead return the current + // tracker. + // A case where this check is important is e.g. + // for (int i = 0; i < 5; ++i) { + // int n = GENERATE(1, 2); + // } + // + // without it, the code above creates 5 nested generators. + if (currentTracker.nameAndLocation() == nameAndLocation) { + auto thisTracker = currentTracker.parent()->findChild( + nameAndLocation); + assert(thisTracker); + assert(thisTracker->isGeneratorTracker()); + tracker = static_cast(thisTracker); + } else if (ITracker* childTracker = + currentTracker.findChild( + nameAndLocation)) { + assert(childTracker); + assert(childTracker->isGeneratorTracker()); + tracker = + static_cast(childTracker); + } else { + return nullptr; + } - return tracker; - } + if (!tracker->isComplete()) { + tracker->open(); + } - // TrackerBase interface - bool isGeneratorTracker() const override { return true; } - auto hasGenerator() const -> bool override { - return !!m_generator; - } - void close() override { - TrackerBase::close(); - // If a generator has a child (it is followed by a section) - // and none of its children have started, then we must wait - // until later to start consuming its values. - // This catches cases where `GENERATE` is placed between two - // `SECTION`s. - // **The check for m_children.empty cannot be removed**. - // doing so would break `GENERATE` _not_ followed by - // `SECTION`s. - const bool should_wait_for_child = [&]() { - // No children -> nobody to wait for - if ( m_children.empty() ) { return false; } - // If at least one child started executing, don't wait - if ( std::find_if( - m_children.begin(), - m_children.end(), - []( TestCaseTracking::ITrackerPtr const& - tracker ) { - return tracker->hasStarted(); - } ) != m_children.end() ) { - return false; - } + return tracker; + } - // No children have started. We need to check if they - // _can_ start, and thus we should wait for them, or - // they cannot start (due to filters), and we shouldn't - // wait for them - ITracker* parent = m_parent; - // This is safe: there is always at least one section - // tracker in a test case tracking tree - while ( !parent->isSectionTracker() ) { - parent = parent->parent(); - } - assert( parent && - "Missing root (test case) level section" ); - - auto const& parentSection = - static_cast( *parent ); - auto const& filters = parentSection.getFilters(); - // No filters -> no restrictions on running sections - if ( filters.empty() ) { return true; } - - for ( auto const& child : m_children ) { - if ( child->isSectionTracker() && - std::find( filters.begin(), - filters.end(), - static_cast( - *child ) - .trimmedName() ) != - filters.end() ) { - return true; - } - } - return false; - }(); - - // This check is a bit tricky, because m_generator->next() - // has a side-effect, where it consumes generator's current - // value, but we do not want to invoke the side-effect if - // this generator is still waiting for any child to start. - assert( m_generator && "Tracker without generator" ); - if ( should_wait_for_child || - ( m_runState == CompletedSuccessfully && - m_generator->countedNext() ) ) { - m_children.clear(); - m_runState = Executing; - } - } + // TrackerBase interface + bool isGeneratorTracker() const override { return true; } + auto hasGenerator() const -> bool override + { + return !!m_generator; + } + void close() override + { + TrackerBase::close(); + // If a generator has a child (it is followed by a section) + // and none of its children have started, then we must wait + // until later to start consuming its values. + // This catches cases where `GENERATE` is placed between two + // `SECTION`s. + // **The check for m_children.empty cannot be removed**. + // doing so would break `GENERATE` _not_ followed by + // `SECTION`s. + const bool should_wait_for_child = [&]() { + // No children -> nobody to wait for + if (m_children.empty()) { + return false; + } + // If at least one child started executing, don't wait + if (std::find_if( + m_children.begin(), + m_children.end(), + [](TestCaseTracking::ITrackerPtr const& + tracker) { + return tracker->hasStarted(); + }) != m_children.end()) { + return false; + } + + // No children have started. We need to check if they + // _can_ start, and thus we should wait for them, or + // they cannot start (due to filters), and we shouldn't + // wait for them + ITracker* parent = m_parent; + // This is safe: there is always at least one section + // tracker in a test case tracking tree + while (!parent->isSectionTracker()) { + parent = parent->parent(); + } + assert(parent && + "Missing root (test case) level section"); + + auto const& parentSection = + static_cast(*parent); + auto const& filters = parentSection.getFilters(); + // No filters -> no restrictions on running sections + if (filters.empty()) { + return true; + } + + for (auto const& child : m_children) { + if (child->isSectionTracker() && + std::find(filters.begin(), + filters.end(), + static_cast( + *child) + .trimmedName()) != + filters.end()) { + return true; + } + } + return false; + }(); + + // This check is a bit tricky, because m_generator->next() + // has a side-effect, where it consumes generator's current + // value, but we do not want to invoke the side-effect if + // this generator is still waiting for any child to start. + assert(m_generator && "Tracker without generator"); + if (should_wait_for_child || + (m_runState == CompletedSuccessfully && + m_generator->countedNext())) { + m_children.clear(); + m_runState = Executing; + } + } - // IGeneratorTracker interface - auto getGenerator() const -> GeneratorBasePtr const& override { - return m_generator; - } - void setGenerator( GeneratorBasePtr&& generator ) override { - m_generator = CATCH_MOVE( generator ); - } - }; - } // namespace + // IGeneratorTracker interface + auto getGenerator() const -> GeneratorBasePtr const& override + { + return m_generator; + } + void setGenerator(GeneratorBasePtr&& generator) override + { + m_generator = CATCH_MOVE(generator); + } + }; + } // namespace } RunContext::RunContext(IConfig const* _config, IEventListenerPtr&& reporter) - : m_runInfo(_config->name()), + : m_runInfo(_config->name()), m_config(_config), m_reporter(CATCH_MOVE(reporter)), - m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal }, - m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions ) + m_lastAssertionInfo{StringRef(), SourceLineInfo("", 0), StringRef(), ResultDisposition::Normal}, + m_includeSuccessfulResults(m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions) { - getCurrentMutableContext().setResultCapture( this ); - m_reporter->testRunStarting(m_runInfo); + getCurrentMutableContext().setResultCapture(this); + m_reporter->testRunStarting(m_runInfo); } RunContext::~RunContext() { @@ -5316,10 +5368,10 @@ namespace Catch { } m_totals.testCases += deltaTotals.testCases; m_reporter->testCaseEnded(TestCaseStats(testInfo, - deltaTotals, - CATCH_MOVE(redirectedCout), - CATCH_MOVE(redirectedCerr), - aborting())); + deltaTotals, + CATCH_MOVE(redirectedCout), + CATCH_MOVE(redirectedCerr), + aborting())); m_activeTestCase = nullptr; m_testCaseTracker = nullptr; @@ -5327,66 +5379,66 @@ namespace Catch { return deltaTotals; } + void RunContext::assertionEnded(AssertionResult&& result) + { + if (result.getResultType() == ResultWas::Ok) { + m_totals.assertions.passed++; + m_lastAssertionPassed = true; + } else if (result.getResultType() == ResultWas::ExplicitSkip) { + m_totals.assertions.skipped++; + m_lastAssertionPassed = true; + } else if (!result.succeeded()) { + m_lastAssertionPassed = false; + if (result.isOk()) { + } else if (m_activeTestCase->getTestCaseInfo().okToFail()) + m_totals.assertions.failedButOk++; + else + m_totals.assertions.failed++; + } else { + m_lastAssertionPassed = true; + } - void RunContext::assertionEnded(AssertionResult&& result) { - if (result.getResultType() == ResultWas::Ok) { - m_totals.assertions.passed++; - m_lastAssertionPassed = true; - } else if (result.getResultType() == ResultWas::ExplicitSkip) { - m_totals.assertions.skipped++; - m_lastAssertionPassed = true; - } else if (!result.succeeded()) { - m_lastAssertionPassed = false; - if (result.isOk()) { - } - else if( m_activeTestCase->getTestCaseInfo().okToFail() ) - m_totals.assertions.failedButOk++; - else - m_totals.assertions.failed++; - } - else { - m_lastAssertionPassed = true; - } - - m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)); + m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)); - if ( result.getResultType() != ResultWas::Warning ) { - m_messageScopes.clear(); - } + if (result.getResultType() != ResultWas::Warning) { + m_messageScopes.clear(); + } - // Reset working state - resetAssertionInfo(); - m_lastResult = CATCH_MOVE( result ); + // Reset working state + resetAssertionInfo(); + m_lastResult = CATCH_MOVE(result); } void RunContext::resetAssertionInfo() { m_lastAssertionInfo.macroName = StringRef(); m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr; } - void RunContext::notifyAssertionStarted( AssertionInfo const& info ) { - m_reporter->assertionStarting( info ); + void RunContext::notifyAssertionStarted(AssertionInfo const& info) + { + m_reporter->assertionStarting(info); } - bool RunContext::sectionStarted( StringRef sectionName, - SourceLineInfo const& sectionLineInfo, - Counts& assertions ) { - ITracker& sectionTracker = - SectionTracker::acquire( m_trackerContext, - TestCaseTracking::NameAndLocationRef( - sectionName, sectionLineInfo ) ); + bool RunContext::sectionStarted(StringRef sectionName, + SourceLineInfo const& sectionLineInfo, + Counts& assertions) + { + ITracker& sectionTracker = + SectionTracker::acquire(m_trackerContext, + TestCaseTracking::NameAndLocationRef( + sectionName, sectionLineInfo)); - if (!sectionTracker.isOpen()) - return false; - m_activeSections.push_back(§ionTracker); + if (!sectionTracker.isOpen()) + return false; + m_activeSections.push_back(§ionTracker); - SectionInfo sectionInfo( sectionLineInfo, static_cast(sectionName) ); - m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + SectionInfo sectionInfo(sectionLineInfo, static_cast(sectionName)); + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; - m_reporter->sectionStarting(sectionInfo); + m_reporter->sectionStarting(sectionInfo); - assertions = m_totals.assertions; + assertions = m_totals.assertions; - return true; + return true; } IGeneratorTracker* RunContext::acquireGeneratorTracker( StringRef generatorName, @@ -5507,7 +5559,7 @@ namespace Catch { tempResult.message = static_cast(message); AssertionResult result(m_lastAssertionInfo, CATCH_MOVE(tempResult)); - assertionEnded(CATCH_MOVE(result) ); + assertionEnded(CATCH_MOVE(result)); handleUnfinishedSections(); @@ -5625,25 +5677,23 @@ namespace Catch { } void RunContext::handleExpr( - AssertionInfo const& info, - ITransientExpression const& expr, - AssertionReaction& reaction - ) { - bool negated = isFalseTest( info.resultDisposition ); - bool result = expr.getResult() != negated; + AssertionInfo const& info, + ITransientExpression const& expr, + AssertionReaction& reaction) + { + 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 ); + 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, @@ -5657,31 +5707,31 @@ namespace Catch { AssertionResult assertionResult{ info, CATCH_MOVE( data ) }; assertionResult.m_resultData.lazyExpression.m_transientExpression = expr; - assertionEnded( CATCH_MOVE(assertionResult) ); + assertionEnded(CATCH_MOVE(assertionResult)); } void RunContext::handleMessage( - AssertionInfo const& info, - ResultWas::OfType resultType, - StringRef message, - AssertionReaction& reaction - ) { - m_lastAssertionInfo = info; - - AssertionResultData data( resultType, LazyExpression( false ) ); - data.message = static_cast(message); - AssertionResult assertionResult{ m_lastAssertionInfo, - CATCH_MOVE( data ) }; - - const auto isOk = assertionResult.isOk(); - assertionEnded( CATCH_MOVE(assertionResult) ); - if ( !isOk ) { - populateReaction( reaction ); - } else if ( resultType == ResultWas::ExplicitSkip ) { - // TODO: Need to handle this explicitly, as ExplicitSkip is - // considered "OK" - reaction.shouldSkip = true; - } + AssertionInfo const& info, + ResultWas::OfType resultType, + StringRef message, + AssertionReaction& reaction) + { + m_lastAssertionInfo = info; + + AssertionResultData data(resultType, LazyExpression(false)); + data.message = static_cast(message); + AssertionResult assertionResult{m_lastAssertionInfo, + CATCH_MOVE(data)}; + + const auto isOk = assertionResult.isOk(); + assertionEnded(CATCH_MOVE(assertionResult)); + if (!isOk) { + populateReaction(reaction); + } else if (resultType == ResultWas::ExplicitSkip) { + // TODO: Need to handle this explicitly, as ExplicitSkip is + // considered "OK" + reaction.shouldSkip = true; + } } void RunContext::handleUnexpectedExceptionNotThrown( AssertionInfo const& info, @@ -5691,17 +5741,17 @@ namespace Catch { } void RunContext::handleUnexpectedInflightException( - AssertionInfo const& info, - std::string&& message, - AssertionReaction& reaction - ) { - m_lastAssertionInfo = info; + AssertionInfo const& info, + std::string&& message, + AssertionReaction& reaction) + { + m_lastAssertionInfo = info; - AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) ); - data.message = CATCH_MOVE(message); - AssertionResult assertionResult{ info, CATCH_MOVE(data) }; - assertionEnded( CATCH_MOVE(assertionResult) ); - populateReaction( reaction ); + AssertionResultData data(ResultWas::ThrewException, LazyExpression(false)); + data.message = CATCH_MOVE(message); + AssertionResult assertionResult{info, CATCH_MOVE(data)}; + assertionEnded(CATCH_MOVE(assertionResult)); + populateReaction(reaction); } void RunContext::populateReaction( AssertionReaction& reaction ) { @@ -5712,13 +5762,13 @@ namespace Catch { void RunContext::handleIncomplete( AssertionInfo const& info ) { - using namespace std::string_literals; - m_lastAssertionInfo = info; + using namespace std::string_literals; + m_lastAssertionInfo = info; - AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) ); - data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"s; - AssertionResult assertionResult{ info, CATCH_MOVE( data ) }; - assertionEnded( CATCH_MOVE(assertionResult) ); + AssertionResultData data(ResultWas::ThrewException, LazyExpression(false)); + data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"s; + AssertionResult assertionResult{info, CATCH_MOVE(data)}; + assertionEnded(CATCH_MOVE(assertionResult)); } void RunContext::handleNonExpr( AssertionInfo const &info, @@ -5728,11 +5778,13 @@ namespace Catch { m_lastAssertionInfo = info; AssertionResultData data( resultType, LazyExpression( false ) ); - AssertionResult assertionResult{ info, CATCH_MOVE( data ) }; + AssertionResult assertionResult{info, CATCH_MOVE(data)}; const auto isOk = assertionResult.isOk(); - assertionEnded( CATCH_MOVE(assertionResult) ); - if ( !isOk ) { populateReaction( reaction ); } + assertionEnded(CATCH_MOVE(assertionResult)); + if (!isOk) { + populateReaction(reaction); + } } @@ -5768,21 +5820,21 @@ namespace Catch { } } - Section::Section( SourceLineInfo const& _lineInfo, - StringRef _name, - const char* const ): - m_info( { "invalid", static_cast( -1 ) }, std::string{} ), - m_sectionIncluded( - getResultCapture().sectionStarted( _name, _lineInfo, m_assertions ) ) { - // We delay initialization the SectionInfo member until we know - // this section needs it, so we avoid allocating std::string for name. - // We also delay timer start to avoid the potential syscall unless we - // will actually use the result. - if ( m_sectionIncluded ) { - m_info.name = static_cast( _name ); - m_info.lineInfo = _lineInfo; - m_timer.start(); - } + Section::Section(SourceLineInfo const& _lineInfo, + StringRef _name, + const char* const) : m_info({"invalid", static_cast(-1)}, std::string{}), + m_sectionIncluded( + getResultCapture().sectionStarted(_name, _lineInfo, m_assertions)) + { + // We delay initialization the SectionInfo member until we know + // this section needs it, so we avoid allocating std::string for name. + // We also delay timer start to avoid the potential syscall unless we + // will actually use the result. + if (m_sectionIncluded) { + m_info.name = static_cast(_name); + m_info.lineInfo = _lineInfo; + m_timer.start(); + } } Section::~Section() { @@ -5899,8 +5951,6 @@ namespace Catch { } // namespace Catch - - #include #include #include @@ -5924,9 +5974,9 @@ namespace Catch { return s.find( infix ) != std::string::npos; } void toLowerInPlace( std::string& s ) { - for ( char& c : s ) { - c = toLower( c ); - } + for (char& c : s) { + c = toLower(c); + } } std::string toLower( std::string const& s ) { std::string lc = s; @@ -6007,7 +6057,6 @@ namespace Catch { : StringRef( rawChars, std::strlen(rawChars) ) {} - bool StringRef::operator<(StringRef rhs) const noexcept { if (m_size < rhs.m_size) { return strncmp(m_start, rhs.m_start, m_size) <= 0; @@ -6140,37 +6189,40 @@ namespace Catch { namespace Catch { - namespace { - static void enforceNoDuplicateTestCases( - std::vector const& tests ) { - auto testInfoCmp = []( TestCaseInfo const* lhs, - TestCaseInfo const* rhs ) { - return *lhs < *rhs; - }; - std::set seenTests( - testInfoCmp ); - for ( auto const& test : tests ) { - const auto infoPtr = &test.getTestCaseInfo(); - const auto prev = seenTests.insert( infoPtr ); - CATCH_ENFORCE( prev.second, - "error: test case \"" - << infoPtr->name << "\", with tags \"" - << infoPtr->tagsAsString() - << "\" already defined.\n" - << "\tFirst seen at " - << ( *prev.first )->lineInfo << "\n" - << "\tRedefined at " << infoPtr->lineInfo ); - } - } +namespace +{ +static void enforceNoDuplicateTestCases( + std::vector const& tests) +{ + auto testInfoCmp = [](TestCaseInfo const* lhs, + TestCaseInfo const* rhs) { + return *lhs < *rhs; + }; + std::set seenTests( + testInfoCmp); + for (auto const& test : tests) { + const auto infoPtr = &test.getTestCaseInfo(); + const auto prev = seenTests.insert(infoPtr); + CATCH_ENFORCE(prev.second, + "error: test case \"" + << infoPtr->name << "\", with tags \"" + << infoPtr->tagsAsString() + << "\" already defined.\n" + << "\tFirst seen at " + << (*prev.first)->lineInfo << "\n" + << "\tRedefined at " << infoPtr->lineInfo); + } +} - static bool matchTest( TestCaseHandle const& testCase, - TestSpec const& testSpec, - IConfig const& config ) { - return testSpec.matches( testCase.getTestCaseInfo() ) && - isThrowSafe( testCase, config ); - } +static bool matchTest(TestCaseHandle const& testCase, + TestSpec const& testSpec, + IConfig const& config) +{ + return testSpec.matches(testCase.getTestCaseInfo()) && + isThrowSafe(testCase, config); +} - } // end unnamed namespace +} // end unnamed namespace std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { switch (config.runOrder()) { @@ -6300,19 +6352,20 @@ namespace TestCaseTracking { m_children.push_back( CATCH_MOVE(child) ); } - ITracker* ITracker::findChild( NameAndLocationRef const& nameAndLocation ) { - auto it = std::find_if( - m_children.begin(), - m_children.end(), - [&nameAndLocation]( ITrackerPtr const& tracker ) { - auto const& tnameAndLoc = tracker->nameAndLocation(); - if ( tnameAndLoc.location.line != - nameAndLocation.location.line ) { - return false; - } - return tnameAndLoc == nameAndLocation; - } ); - return ( it != m_children.end() ) ? it->get() : nullptr; + ITracker* ITracker::findChild(NameAndLocationRef const& nameAndLocation) + { + auto it = std::find_if( + m_children.begin(), + m_children.end(), + [&nameAndLocation](ITrackerPtr const& tracker) { + auto const& tnameAndLoc = tracker->nameAndLocation(); + if (tnameAndLoc.location.line != + nameAndLocation.location.line) { + return false; + } + return tnameAndLoc == nameAndLocation; + }); + return (it != m_children.end()) ? it->get() : nullptr; } bool ITracker::isSectionTracker() const { return false; } @@ -6417,8 +6470,8 @@ namespace TestCaseTracking { m_ctx.setCurrentTracker( this ); } - SectionTracker::SectionTracker( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent ) - : TrackerBase( CATCH_MOVE(nameAndLocation), ctx, parent ), + SectionTracker::SectionTracker(NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent) + : TrackerBase(CATCH_MOVE(nameAndLocation), ctx, parent), m_trimmed_name(trim(StringRef(ITracker::nameAndLocation().name))) { if( parent ) { @@ -6444,30 +6497,31 @@ namespace TestCaseTracking { bool SectionTracker::isSectionTracker() const { return true; } - SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocationRef const& nameAndLocation ) { - SectionTracker* tracker; - - ITracker& currentTracker = ctx.currentTracker(); - if ( ITracker* childTracker = - currentTracker.findChild( nameAndLocation ) ) { - assert( childTracker ); - assert( childTracker->isSectionTracker() ); - tracker = static_cast( childTracker ); - } else { - auto newTracker = Catch::Detail::make_unique( - NameAndLocation{ static_cast(nameAndLocation.name), - nameAndLocation.location }, - ctx, - ¤tTracker ); - tracker = newTracker.get(); - currentTracker.addChild( CATCH_MOVE( newTracker ) ); - } + SectionTracker& SectionTracker::acquire(TrackerContext& ctx, NameAndLocationRef const& nameAndLocation) + { + SectionTracker* tracker; + + ITracker& currentTracker = ctx.currentTracker(); + if (ITracker* childTracker = + currentTracker.findChild(nameAndLocation)) { + assert(childTracker); + assert(childTracker->isSectionTracker()); + tracker = static_cast(childTracker); + } else { + auto newTracker = Catch::Detail::make_unique( + NameAndLocation{static_cast(nameAndLocation.name), + nameAndLocation.location}, + ctx, + ¤tTracker); + tracker = newTracker.get(); + currentTracker.addChild(CATCH_MOVE(newTracker)); + } - if ( !ctx.completedCycle() ) { - tracker->tryOpen(); - } + if (!ctx.completedCycle()) { + tracker->tryOpen(); + } - return *tracker; + return *tracker; } void SectionTracker::tryOpen() { @@ -6513,11 +6567,12 @@ namespace Catch { #endif } - void throw_test_skip_exception() { -#if !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS ) - throw Catch::TestSkipException(); + void throw_test_skip_exception() + { +#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) + throw Catch::TestSkipException(); #else - CATCH_ERROR( "Explicitly skipping tests during runtime requires exceptions" ); + CATCH_ERROR("Explicitly skipping tests during runtime requires exceptions"); #endif } @@ -6529,47 +6584,49 @@ namespace Catch { #include namespace Catch { - ITestInvoker::~ITestInvoker() = default; - - namespace { - static StringRef extractClassName( StringRef classOrMethodName ) { - if ( !startsWith( classOrMethodName, '&' ) ) { - return classOrMethodName; - } +ITestInvoker::~ITestInvoker() = default; + +namespace +{ +static StringRef extractClassName(StringRef classOrMethodName) +{ + if (!startsWith(classOrMethodName, '&')) { + return classOrMethodName; + } - // Remove the leading '&' to avoid having to special case it later - const auto methodName = - classOrMethodName.substr( 1, classOrMethodName.size() ); + // Remove the leading '&' to avoid having to special case it later + const auto methodName = + classOrMethodName.substr(1, classOrMethodName.size()); - auto reverseStart = std::make_reverse_iterator( methodName.end() ); - auto reverseEnd = std::make_reverse_iterator( methodName.begin() ); + auto reverseStart = std::make_reverse_iterator(methodName.end()); + auto reverseEnd = std::make_reverse_iterator(methodName.begin()); - // We make a simplifying assumption that ":" is only present - // in the input as part of "::" from C++ typenames (this is - // relatively safe assumption because the input is generated - // as stringification of type through preprocessor). - auto lastColons = std::find( reverseStart, reverseEnd, ':' ) + 1; - auto secondLastColons = - std::find( lastColons + 1, reverseEnd, ':' ); + // We make a simplifying assumption that ":" is only present + // in the input as part of "::" from C++ typenames (this is + // relatively safe assumption because the input is generated + // as stringification of type through preprocessor). + auto lastColons = std::find(reverseStart, reverseEnd, ':') + 1; + auto secondLastColons = + std::find(lastColons + 1, reverseEnd, ':'); - auto const startIdx = reverseEnd - secondLastColons; - auto const classNameSize = secondLastColons - lastColons - 1; + auto const startIdx = reverseEnd - secondLastColons; + auto const classNameSize = secondLastColons - lastColons - 1; - return methodName.substr( - static_cast( startIdx ), - static_cast( classNameSize ) ); - } + return methodName.substr( + static_cast(startIdx), + static_cast(classNameSize)); +} - class TestInvokerAsFunction final : public ITestInvoker { - using TestType = void ( * )(); - TestType m_testAsFunction; +class TestInvokerAsFunction final : public ITestInvoker +{ + using TestType = void (*)(); + TestType m_testAsFunction; - public: - TestInvokerAsFunction( TestType testAsFunction ) noexcept: - m_testAsFunction( testAsFunction ) {} + public: + TestInvokerAsFunction(TestType testAsFunction) noexcept : m_testAsFunction(testAsFunction) {} - void invoke() const override { m_testAsFunction(); } - }; + void invoke() const override { m_testAsFunction(); } +}; } // namespace @@ -6806,9 +6863,9 @@ namespace Catch { if (token.size() > 1 && token[0] == '.') { token.erase(token.begin()); if (m_exclusion) { - m_currentFilter.m_forbidden.emplace_back(Detail::make_unique(".", m_substring)); + m_currentFilter.m_forbidden.emplace_back(Detail::make_unique(".", m_substring)); } else { - m_currentFilter.m_required.emplace_back(Detail::make_unique(".", m_substring)); + m_currentFilter.m_required.emplace_back(Detail::make_unique(".", m_substring)); } } if (m_exclusion) { @@ -7750,20 +7807,20 @@ WithinRelMatcher WithinRel(float target) { return WithinRelMatcher(target, std::numeric_limits::epsilon() * 100); } - - -bool IsNaNMatcher::match( double const& matchee ) const { - return std::isnan( matchee ); +bool IsNaNMatcher::match(double const& matchee) const +{ + return std::isnan(matchee); } -std::string IsNaNMatcher::describe() const { - using namespace std::string_literals; - return "is NaN"s; +std::string IsNaNMatcher::describe() const +{ + using namespace std::string_literals; + return "is NaN"s; } IsNaNMatcher IsNaN() { return IsNaNMatcher(); } - } // namespace Matchers +} // namespace Matchers } // namespace Catch @@ -8290,22 +8347,23 @@ class ConsoleAssertionPrinter { ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter const&) = delete; ConsoleAssertionPrinter(ConsoleAssertionPrinter const&) = delete; ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, ColourImpl* colourImpl_, bool _printInfoMessages) - : stream(_stream), + : stream(_stream), stats(_stats), result(_stats.assertionResult), colour(Colour::None), messages(_stats.infoMessages), colourImpl(colourImpl_), - printInfoMessages(_printInfoMessages) { - switch (result.getResultType()) { + printInfoMessages(_printInfoMessages) + { + switch (result.getResultType()) { case ResultWas::Ok: colour = Colour::Success; passOrFail = "PASSED"_sr; //if( result.hasMessage() ) if (messages.size() == 1) - messageLabel = "with message"_sr; + messageLabel = "with message"_sr; if (messages.size() > 1) - messageLabel = "with messages"_sr; + messageLabel = "with messages"_sr; break; case ResultWas::ExpressionFailed: if (result.isOk()) { @@ -8316,21 +8374,22 @@ class ConsoleAssertionPrinter { passOrFail = "FAILED"_sr; } if (messages.size() == 1) - messageLabel = "with message"_sr; + messageLabel = "with message"_sr; if (messages.size() > 1) - messageLabel = "with messages"_sr; + messageLabel = "with messages"_sr; break; case ResultWas::ThrewException: colour = Colour::Error; passOrFail = "FAILED"_sr; // todo switch - switch (messages.size()) { case 0: + switch (messages.size()) { + case 0: messageLabel = "due to unexpected exception with "_sr; break; - case 1: + case 1: messageLabel = "due to unexpected exception with message"_sr; break; - default: + default: messageLabel = "due to unexpected exception with messages"_sr; break; } @@ -8346,26 +8405,26 @@ class ConsoleAssertionPrinter { messageLabel = "because no exception was thrown where one was expected"_sr; break; case ResultWas::Info: - messageLabel = "info"_sr; - break; + messageLabel = "info"_sr; + break; case ResultWas::Warning: - messageLabel = "warning"_sr; - break; + messageLabel = "warning"_sr; + break; case ResultWas::ExplicitFailure: passOrFail = "FAILED"_sr; colour = Colour::Error; if (messages.size() == 1) - messageLabel = "explicitly with message"_sr; + messageLabel = "explicitly with message"_sr; if (messages.size() > 1) - messageLabel = "explicitly with messages"_sr; + messageLabel = "explicitly with messages"_sr; break; case ResultWas::ExplicitSkip: colour = Colour::Skip; passOrFail = "SKIPPED"_sr; if (messages.size() == 1) - messageLabel = "explicitly with message"_sr; + messageLabel = "explicitly with message"_sr; if (messages.size() > 1) - messageLabel = "explicitly with messages"_sr; + messageLabel = "explicitly with messages"_sr; break; // These cases are here to prevent compiler warnings case ResultWas::Unknown: @@ -9432,7 +9491,7 @@ namespace Catch { gmtime_s(&timeInfo, &rawtime); #elif defined (CATCH_PLATFORM_PLAYSTATION) gmtime_s(&rawtime, &timeInfo); -#elif defined (__IAR_SYSTEMS_ICC__) +#elif defined(__IAR_SYSTEMS_ICC__) timeInfo = *std::gmtime(&rawtime); #else gmtime_r(&rawtime, &timeInfo); @@ -9694,8 +9753,8 @@ namespace Catch { } } - if( result.hasMessage() ) - rss << result.getMessage() << '\n'; + if (result.hasMessage()) + rss << result.getMessage() << '\n'; for( auto const& msg : stats.infoMessages ) if( msg.type == ResultWas::Info ) rss << msg.message << '\n'; @@ -9915,11 +9974,11 @@ namespace Catch { } } - void registerListenerImpl( Detail::unique_ptr listenerFactory ) { - getMutableRegistryHub().registerListener( CATCH_MOVE(listenerFactory) ); + void registerListenerImpl(Detail::unique_ptr listenerFactory) + { + getMutableRegistryHub().registerListener(CATCH_MOVE(listenerFactory)); } - } // namespace Detail } // namespace Catch @@ -10060,7 +10119,7 @@ namespace Catch { } if (result.hasMessage()) - textRss << result.getMessage() << '\n'; + textRss << result.getMessage() << '\n'; for (auto const& msg : stats.infoMessages) if (msg.type == ResultWas::Info) @@ -10090,8 +10149,6 @@ namespace Catch { } // end namespace Catch - - #include #include @@ -10513,10 +10570,10 @@ namespace Catch { if( !stylesheetRef.empty() ) m_xml.writeStylesheetRef( stylesheetRef ); m_xml.startElement("Catch2TestRun") - .writeAttribute("name"_sr, m_config->name()) - .writeAttribute("rng-seed"_sr, m_config->rngSeed()) - .writeAttribute("xml-format-version"_sr, 3) - .writeAttribute("catch2-version"_sr, libraryVersion()); + .writeAttribute("name"_sr, m_config->name()) + .writeAttribute("rng-seed"_sr, m_config->rngSeed()) + .writeAttribute("xml-format-version"_sr, 3) + .writeAttribute("catch2-version"_sr, libraryVersion()); if ( m_config->testSpec().hasFilters() ) { m_xml.writeAttribute( "filters"_sr, m_config->testSpec() ); } @@ -10524,9 +10581,9 @@ namespace Catch { void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) { StreamingReporterBase::testCaseStarting(testInfo); - m_xml.startElement( "TestCase" ) - .writeAttribute( "name"_sr, trim( StringRef(testInfo.name) ) ) - .writeAttribute( "tags"_sr, testInfo.tagsAsString() ); + m_xml.startElement("TestCase") + .writeAttribute("name"_sr, trim(StringRef(testInfo.name))) + .writeAttribute("tags"_sr, testInfo.tagsAsString()); writeSourceInfo( testInfo.lineInfo ); @@ -10538,10 +10595,10 @@ namespace Catch { void XmlReporter::sectionStarting( SectionInfo const& sectionInfo ) { StreamingReporterBase::sectionStarting( sectionInfo ); if( m_sectionDepth++ > 0 ) { - m_xml.startElement( "Section" ) - .writeAttribute( "name"_sr, trim( StringRef(sectionInfo.name) ) ); - writeSourceInfo( sectionInfo.lineInfo ); - m_xml.ensureTagClosed(); + m_xml.startElement("Section") + .writeAttribute("name"_sr, trim(StringRef(sectionInfo.name))); + writeSourceInfo(sectionInfo.lineInfo); + m_xml.ensureTagClosed(); } } @@ -10557,13 +10614,13 @@ namespace Catch { // Print any info messages in tags. for( auto const& msg : assertionStats.infoMessages ) { if( msg.type == ResultWas::Info && includeResults ) { - auto t = m_xml.scopedElement( "Info" ); - writeSourceInfo( msg.lineInfo ); - t.writeText( msg.message ); + auto t = m_xml.scopedElement("Info"); + writeSourceInfo(msg.lineInfo); + t.writeText(msg.message); } else if ( msg.type == ResultWas::Warning ) { - auto t = m_xml.scopedElement( "Warning" ); - writeSourceInfo( msg.lineInfo ); - t.writeText( msg.message ); + auto t = m_xml.scopedElement("Warning"); + writeSourceInfo(msg.lineInfo); + t.writeText(msg.message); } } } @@ -10654,11 +10711,11 @@ namespace Catch { e.writeAttribute( "skips"_sr, testCaseStats.totals.assertions.skipped ); if ( m_config->showDurations() == ShowDurations::Always ) - e.writeAttribute( "durationInSeconds"_sr, m_testCaseTimer.getElapsedSeconds() ); + e.writeAttribute("durationInSeconds"_sr, m_testCaseTimer.getElapsedSeconds()); if( !testCaseStats.stdOut.empty() ) - m_xml.scopedElement( "StdOut" ).writeText( trim( StringRef(testCaseStats.stdOut) ), XmlFormatting::Newline ); + m_xml.scopedElement("StdOut").writeText(trim(StringRef(testCaseStats.stdOut)), XmlFormatting::Newline); if( !testCaseStats.stdErr.empty() ) - m_xml.scopedElement( "StdErr" ).writeText( trim( StringRef(testCaseStats.stdErr) ), XmlFormatting::Newline ); + m_xml.scopedElement("StdErr").writeText(trim(StringRef(testCaseStats.stdErr)), XmlFormatting::Newline); m_xml.endElement(); } diff --git a/Framework/Foundation/3rdparty/catch2/catch_amalgamated.hpp b/Framework/Foundation/3rdparty/catch2/catch_amalgamated.hpp index 694fe1e4d81b3..b1c4b3a28c694 100644 --- a/Framework/Foundation/3rdparty/catch2/catch_amalgamated.hpp +++ b/Framework/Foundation/3rdparty/catch2/catch_amalgamated.hpp @@ -57,8 +57,6 @@ #ifndef CATCH_BENCHMARK_HPP_INCLUDED #define CATCH_BENCHMARK_HPP_INCLUDED - - #ifndef CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED #define CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED @@ -134,8 +132,8 @@ # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" ) -# define CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \ - _Pragma( "GCC diagnostic ignored \"-Wunused-result\"" ) +#define CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \ + _Pragma("GCC diagnostic ignored \"-Wunused-result\"") # define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ _Pragma( "GCC diagnostic ignored \"-Wunused-variable\"" ) @@ -143,17 +141,17 @@ # define CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ _Pragma( "GCC diagnostic ignored \"-Wuseless-cast\"" ) -# define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ - _Pragma( "GCC diagnostic ignored \"-Wshadow\"" ) +#define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ + _Pragma("GCC diagnostic ignored \"-Wshadow\"") # define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) #endif #if defined(__NVCOMPILER) -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "diag push" ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "diag pop" ) -# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "diag_suppress declared_but_not_referenced" ) +#define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma("diag push") +#define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma("diag pop") +#define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma("diag_suppress declared_but_not_referenced") #endif #if defined(__CUDACC__) && !defined(__clang__) @@ -218,8 +216,8 @@ # define CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \ _Pragma( "clang diagnostic ignored \"-Wcomma\"" ) -# define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wshadow\"" ) +#define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ + _Pragma("clang diagnostic ignored \"-Wshadow\"") #endif // __clang__ @@ -459,7 +457,7 @@ # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT) -# define CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT +#define CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT #endif #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS @@ -470,17 +468,16 @@ #if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS #endif -#if !defined( CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS ) -# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) +#define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS #endif -#if !defined( CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS ) -# define CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS +#if !defined(CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS) +#define CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS #endif -#if !defined( CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS ) -# define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS +#if !defined(CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS) +#define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS #endif - // The goal of this macro is to avoid evaluation of the arguments, but // still have the compiler warn on problems inside... #if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) @@ -493,7 +490,6 @@ # undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS #endif - #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) #define CATCH_TRY if ((true)) #define CATCH_CATCH_ALL if ((false)) @@ -538,31 +534,35 @@ namespace Catch { class IResultCapture; class IConfig; - class Context { - IConfig const* m_config = nullptr; - IResultCapture* m_resultCapture = nullptr; + class Context + { + IConfig const* m_config = nullptr; + IResultCapture* m_resultCapture = nullptr; - CATCH_EXPORT static Context* currentContext; - friend Context& getCurrentMutableContext(); - friend Context const& getCurrentContext(); - static void createContext(); - friend void cleanUpContext(); + CATCH_EXPORT static Context* currentContext; + friend Context& getCurrentMutableContext(); + friend Context const& getCurrentContext(); + static void createContext(); + friend void cleanUpContext(); - public: - IResultCapture* getResultCapture() const { return m_resultCapture; } - IConfig const* getConfig() const { return m_config; } - void setResultCapture( IResultCapture* resultCapture ); - void setConfig( IConfig const* config ); + public: + IResultCapture* getResultCapture() const { return m_resultCapture; } + IConfig const* getConfig() const { return m_config; } + void setResultCapture(IResultCapture* resultCapture); + void setConfig(IConfig const* config); }; Context& getCurrentMutableContext(); - inline Context const& getCurrentContext() { - // We duplicate the logic from `getCurrentMutableContext` here, - // to avoid paying the call overhead in debug mode. - if ( !Context::currentContext ) { Context::createContext(); } - // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn) - return *Context::currentContext; + inline Context const& getCurrentContext() + { + // We duplicate the logic from `getCurrentMutableContext` here, + // to avoid paying the call overhead in debug mode. + if (!Context::currentContext) { + Context::createContext(); + } + // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn) + return *Context::currentContext; } void cleanUpContext(); @@ -573,7 +573,6 @@ namespace Catch { #endif // CATCH_CONTEXT_HPP_INCLUDED - #ifndef CATCH_MOVE_AND_FORWARD_HPP_INCLUDED #define CATCH_MOVE_AND_FORWARD_HPP_INCLUDED @@ -587,42 +586,39 @@ namespace Catch { #endif // CATCH_MOVE_AND_FORWARD_HPP_INCLUDED - #ifndef CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED #define CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED namespace Catch { - //! Used to signal that an assertion macro failed - struct TestFailureException{}; - //! Used to signal that the remainder of a test should be skipped - struct TestSkipException {}; +//! Used to signal that an assertion macro failed +struct TestFailureException { +}; +//! Used to signal that the remainder of a test should be skipped +struct TestSkipException { +}; - /** - * Outlines throwing of `TestFailureException` into a single TU - * - * Also handles `CATCH_CONFIG_DISABLE_EXCEPTIONS` for callers. - */ - [[noreturn]] void throw_test_failure_exception(); +/** + * Outlines throwing of `TestFailureException` into a single TU + * + * Also handles `CATCH_CONFIG_DISABLE_EXCEPTIONS` for callers. + */ +[[noreturn]] void throw_test_failure_exception(); - /** - * Outlines throwing of `TestSkipException` into a single TU - * - * Also handles `CATCH_CONFIG_DISABLE_EXCEPTIONS` for callers. - */ - [[noreturn]] void throw_test_skip_exception(); +/** + * Outlines throwing of `TestSkipException` into a single TU + * + * Also handles `CATCH_CONFIG_DISABLE_EXCEPTIONS` for callers. + */ +[[noreturn]] void throw_test_skip_exception(); } // namespace Catch #endif // CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED - #ifndef CATCH_UNIQUE_NAME_HPP_INCLUDED #define CATCH_UNIQUE_NAME_HPP_INCLUDED - - - /** \file * Wrapper for the CONFIG configuration option * @@ -635,38 +631,33 @@ namespace Catch { #ifndef CATCH_CONFIG_COUNTER_HPP_INCLUDED #define CATCH_CONFIG_COUNTER_HPP_INCLUDED - -#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) - #define CATCH_INTERNAL_CONFIG_COUNTER +#if (!defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L) +#define CATCH_INTERNAL_CONFIG_COUNTER #endif -#if defined( CATCH_INTERNAL_CONFIG_COUNTER ) && \ - !defined( CATCH_CONFIG_NO_COUNTER ) && \ - !defined( CATCH_CONFIG_COUNTER ) -# define CATCH_CONFIG_COUNTER +#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && \ + !defined(CATCH_CONFIG_NO_COUNTER) && \ + !defined(CATCH_CONFIG_COUNTER) +#define CATCH_CONFIG_COUNTER #endif - #endif // CATCH_CONFIG_COUNTER_HPP_INCLUDED -#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 ) +#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__ ) +#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__ ) +#define INTERNAL_CATCH_UNIQUE_NAME(name) INTERNAL_CATCH_UNIQUE_NAME_LINE(name, __LINE__) #endif #endif // CATCH_UNIQUE_NAME_HPP_INCLUDED - #ifndef CATCH_INTERFACES_CAPTURE_HPP_INCLUDED #define CATCH_INTERFACES_CAPTURE_HPP_INCLUDED #include #include - - #ifndef CATCH_STRINGREF_HPP_INCLUDED #define CATCH_STRINGREF_HPP_INCLUDED @@ -679,110 +670,119 @@ namespace Catch { namespace Catch { - /// 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. - class StringRef { - public: - using size_type = std::size_t; - using const_iterator = const char*; - - private: - static constexpr char const* const s_empty = ""; - - char const* m_start = s_empty; - size_type m_size = 0; - - public: // construction - constexpr StringRef() noexcept = default; - - StringRef( char const* rawChars ) noexcept; - - constexpr 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() ) - {} - - explicit operator std::string() const { - return std::string(m_start, m_size); - } - - public: // operators - auto operator == ( StringRef other ) const noexcept -> bool { - return m_size == other.m_size - && (std::memcmp( m_start, other.m_start, m_size ) == 0); - } - auto operator != (StringRef other) const noexcept -> bool { - return !(*this == other); - } - - constexpr auto operator[] ( size_type index ) const noexcept -> char { - assert(index < m_size); - return m_start[index]; - } - - bool operator<(StringRef rhs) const noexcept; - - public: // named queries - constexpr auto empty() const noexcept -> bool { - return m_size == 0; - } - constexpr auto size() const noexcept -> size_type { - return m_size; - } - - // Returns a substring of [start, start + length). - // If start + length > size(), then the substring is [start, start + size()). - // If start > size(), then the substring is empty. - constexpr StringRef substr(size_type start, size_type length) const noexcept { - if (start < m_size) { - const auto shortened_size = m_size - start; - return StringRef(m_start + start, (shortened_size < length) ? shortened_size : length); - } else { - return StringRef(); - } - } - - // Returns the current start pointer. May not be null-terminated. - constexpr char const* data() const noexcept { - return m_start; - } - - constexpr const_iterator begin() const { return m_start; } - constexpr const_iterator end() const { return m_start + m_size; } - - - friend std::string& operator += (std::string& lhs, StringRef sr); - friend std::ostream& operator << (std::ostream& os, StringRef sr); - friend std::string operator+(StringRef lhs, StringRef rhs); - - /** - * Provides a three-way comparison with rhs - * - * Returns negative number if lhs < rhs, 0 if lhs == rhs, and a positive - * number if lhs > rhs - */ - int compare( StringRef rhs ) const; - }; - - - constexpr auto operator ""_sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { - return StringRef( rawChars, size ); +/// 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. +class StringRef +{ + public: + using size_type = std::size_t; + using const_iterator = const char*; + + private: + static constexpr char const* const s_empty = ""; + + char const* m_start = s_empty; + size_type m_size = 0; + + public: // construction + constexpr StringRef() noexcept = default; + + StringRef(char const* rawChars) noexcept; + + constexpr 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()) + { + } + + explicit operator std::string() const + { + return std::string(m_start, m_size); + } + + public: // operators + auto operator==(StringRef other) const noexcept -> bool + { + return m_size == other.m_size && (std::memcmp(m_start, other.m_start, m_size) == 0); + } + auto operator!=(StringRef other) const noexcept -> bool + { + return !(*this == other); + } + + constexpr auto operator[](size_type index) const noexcept -> char + { + assert(index < m_size); + return m_start[index]; + } + + bool operator<(StringRef rhs) const noexcept; + + public: // named queries + constexpr auto empty() const noexcept -> bool + { + return m_size == 0; + } + constexpr auto size() const noexcept -> size_type + { + return m_size; + } + + // Returns a substring of [start, start + length). + // If start + length > size(), then the substring is [start, start + size()). + // If start > size(), then the substring is empty. + constexpr StringRef substr(size_type start, size_type length) const noexcept + { + if (start < m_size) { + const auto shortened_size = m_size - start; + return StringRef(m_start + start, (shortened_size < length) ? shortened_size : length); + } else { + return StringRef(); } + } + + // Returns the current start pointer. May not be null-terminated. + constexpr char const* data() const noexcept + { + return m_start; + } + + constexpr const_iterator begin() const { return m_start; } + constexpr const_iterator end() const { return m_start + m_size; } + + friend std::string& operator+=(std::string& lhs, StringRef sr); + friend std::ostream& operator<<(std::ostream& os, StringRef sr); + friend std::string operator+(StringRef lhs, StringRef rhs); + + /** + * Provides a three-way comparison with rhs + * + * Returns negative number if lhs < rhs, 0 if lhs == rhs, and a positive + * number if lhs > rhs + */ + int compare(StringRef rhs) const; +}; + +constexpr auto operator""_sr(char const* rawChars, std::size_t size) noexcept -> StringRef +{ + return StringRef(rawChars, size); +} } // namespace Catch -constexpr auto operator ""_catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { - return Catch::StringRef( rawChars, size ); +constexpr auto operator""_catch_sr(char const* rawChars, std::size_t size) noexcept -> Catch::StringRef +{ + return Catch::StringRef(rawChars, size); } #endif // CATCH_STRINGREF_HPP_INCLUDED - #ifndef CATCH_RESULT_TYPE_HPP_INCLUDED #define CATCH_RESULT_TYPE_HPP_INCLUDED @@ -834,14 +834,12 @@ namespace Catch { #endif // CATCH_RESULT_TYPE_HPP_INCLUDED - #ifndef CATCH_UNIQUE_PTR_HPP_INCLUDED #define CATCH_UNIQUE_PTR_HPP_INCLUDED #include #include - namespace Catch { namespace Detail { /** @@ -946,19 +944,19 @@ namespace Detail { #endif // CATCH_UNIQUE_PTR_HPP_INCLUDED - #ifndef CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED #define CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED #include -namespace Catch { +namespace Catch +{ - // We cannot forward declare the type with default template argument - // multiple times, so it is split out into a separate header so that - // we can prevent multiple declarations in dependees - template > - struct BenchmarkStats; +// We cannot forward declare the type with default template argument +// multiple times, so it is split out into a separate header so that +// we can prevent multiple declarations in dependees +template > +struct BenchmarkStats; } // end namespace Catch @@ -991,7 +989,7 @@ namespace Catch { public: virtual ~IResultCapture(); - virtual void notifyAssertionStarted( AssertionInfo const& info ) = 0; + virtual void notifyAssertionStarted(AssertionInfo const& info) = 0; virtual bool sectionStarted( StringRef sectionName, SourceLineInfo const& sectionLineInfo, Counts& assertions ) = 0; @@ -1030,10 +1028,9 @@ namespace Catch { virtual void handleUnexpectedExceptionNotThrown ( AssertionInfo const& info, AssertionReaction& reaction ) = 0; - virtual void handleUnexpectedInflightException - ( AssertionInfo const& info, - std::string&& message, - AssertionReaction& reaction ) = 0; + virtual void handleUnexpectedInflightException(AssertionInfo const& info, + std::string&& message, + AssertionReaction& reaction) = 0; virtual void handleIncomplete ( AssertionInfo const& info ) = 0; virtual void handleNonExpr @@ -1057,30 +1054,29 @@ namespace Catch { #endif // CATCH_INTERFACES_CAPTURE_HPP_INCLUDED - #ifndef CATCH_INTERFACES_CONFIG_HPP_INCLUDED #define CATCH_INTERFACES_CONFIG_HPP_INCLUDED - - #ifndef CATCH_NONCOPYABLE_HPP_INCLUDED #define CATCH_NONCOPYABLE_HPP_INCLUDED namespace Catch { - namespace Detail { +namespace Detail +{ - //! Deriving classes become noncopyable and nonmovable - class NonCopyable { - NonCopyable( NonCopyable const& ) = delete; - NonCopyable( NonCopyable&& ) = delete; - NonCopyable& operator=( NonCopyable const& ) = delete; - NonCopyable& operator=( NonCopyable&& ) = delete; +//! Deriving classes become noncopyable and nonmovable +class NonCopyable +{ + NonCopyable(NonCopyable const&) = delete; + NonCopyable(NonCopyable&&) = delete; + NonCopyable& operator=(NonCopyable const&) = delete; + NonCopyable& operator=(NonCopyable&&) = delete; - protected: - NonCopyable() noexcept = default; - }; + protected: + NonCopyable() noexcept = default; +}; - } // namespace Detail +} // namespace Detail } // namespace Catch #endif // CATCH_NONCOPYABLE_HPP_INCLUDED @@ -1092,197 +1088,204 @@ namespace Catch { namespace Catch { - enum class Verbosity { - Quiet = 0, - Normal, - High - }; +enum class Verbosity { + Quiet = 0, + Normal, + High +}; - struct WarnAbout { enum What { - Nothing = 0x00, - //! A test case or leaf section did not run any assertions - NoAssertions = 0x01, - //! A command line test spec matched no test cases - UnmatchedTestSpec = 0x02, - }; }; +struct WarnAbout { + enum What { + Nothing = 0x00, + //! A test case or leaf section did not run any assertions + NoAssertions = 0x01, + //! A command line test spec matched no test cases + UnmatchedTestSpec = 0x02, + }; +}; - enum class ShowDurations { - DefaultForReporter, - Always, - Never - }; - enum class TestRunOrder { - Declared, - LexicographicallySorted, - Randomized - }; - enum class ColourMode : std::uint8_t { - //! Let Catch2 pick implementation based on platform detection - PlatformDefault, - //! Use ANSI colour code escapes - ANSI, - //! Use Win32 console colour API - Win32, - //! Don't use any colour - None - }; - struct WaitForKeypress { enum When { - Never, - BeforeStart = 1, - BeforeExit = 2, - BeforeStartAndExit = BeforeStart | BeforeExit - }; }; +enum class ShowDurations { + DefaultForReporter, + Always, + Never +}; +enum class TestRunOrder { + Declared, + LexicographicallySorted, + Randomized +}; +enum class ColourMode : std::uint8_t { + //! Let Catch2 pick implementation based on platform detection + PlatformDefault, + //! Use ANSI colour code escapes + ANSI, + //! Use Win32 console colour API + Win32, + //! Don't use any colour + None +}; +struct WaitForKeypress { + enum When { + Never, + BeforeStart = 1, + BeforeExit = 2, + BeforeStartAndExit = BeforeStart | BeforeExit + }; +}; - class TestSpec; - class IStream; +class TestSpec; +class IStream; - class IConfig : public Detail::NonCopyable { - public: - virtual ~IConfig(); - - virtual bool allowThrows() const = 0; - virtual StringRef name() const = 0; - virtual bool includeSuccessfulResults() const = 0; - virtual bool shouldDebugBreak() const = 0; - virtual bool warnAboutMissingAssertions() const = 0; - virtual bool warnAboutUnmatchedTestSpecs() const = 0; - virtual bool zeroTestsCountAsSuccess() const = 0; - virtual int abortAfter() const = 0; - virtual bool showInvisibles() const = 0; - virtual ShowDurations showDurations() const = 0; - virtual double minDuration() const = 0; - virtual TestSpec const& testSpec() const = 0; - virtual bool hasTestFilters() const = 0; - virtual std::vector const& getTestsOrTags() const = 0; - virtual TestRunOrder runOrder() const = 0; - virtual uint32_t rngSeed() const = 0; - virtual unsigned int shardCount() const = 0; - virtual unsigned int shardIndex() const = 0; - virtual ColourMode defaultColourMode() const = 0; - virtual std::vector const& getSectionsToRun() const = 0; - virtual Verbosity verbosity() const = 0; - - virtual bool skipBenchmarks() const = 0; - virtual bool benchmarkNoAnalysis() const = 0; - virtual unsigned int benchmarkSamples() const = 0; - virtual double benchmarkConfidenceInterval() const = 0; - virtual unsigned int benchmarkResamples() const = 0; - virtual std::chrono::milliseconds benchmarkWarmupTime() const = 0; - }; -} +class IConfig : public Detail::NonCopyable +{ + public: + virtual ~IConfig(); + + virtual bool allowThrows() const = 0; + virtual StringRef name() const = 0; + virtual bool includeSuccessfulResults() const = 0; + virtual bool shouldDebugBreak() const = 0; + virtual bool warnAboutMissingAssertions() const = 0; + virtual bool warnAboutUnmatchedTestSpecs() const = 0; + virtual bool zeroTestsCountAsSuccess() const = 0; + virtual int abortAfter() const = 0; + virtual bool showInvisibles() const = 0; + virtual ShowDurations showDurations() const = 0; + virtual double minDuration() const = 0; + virtual TestSpec const& testSpec() const = 0; + virtual bool hasTestFilters() const = 0; + virtual std::vector const& getTestsOrTags() const = 0; + virtual TestRunOrder runOrder() const = 0; + virtual uint32_t rngSeed() const = 0; + virtual unsigned int shardCount() const = 0; + virtual unsigned int shardIndex() const = 0; + virtual ColourMode defaultColourMode() const = 0; + virtual std::vector const& getSectionsToRun() const = 0; + virtual Verbosity verbosity() const = 0; + + virtual bool skipBenchmarks() const = 0; + virtual bool benchmarkNoAnalysis() const = 0; + virtual unsigned int benchmarkSamples() const = 0; + virtual double benchmarkConfidenceInterval() const = 0; + virtual unsigned int benchmarkResamples() const = 0; + virtual std::chrono::milliseconds benchmarkWarmupTime() const = 0; +}; +} // namespace Catch #endif // CATCH_INTERFACES_CONFIG_HPP_INCLUDED - #ifndef CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED #define CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED - #include -namespace Catch { - - class TestCaseHandle; - struct TestCaseInfo; - class ITestCaseRegistry; - class IExceptionTranslatorRegistry; - class IExceptionTranslator; - class ReporterRegistry; - class IReporterFactory; - class ITagAliasRegistry; - class ITestInvoker; - class IMutableEnumValuesRegistry; - struct SourceLineInfo; +namespace Catch +{ - class StartupExceptionRegistry; - class EventListenerFactory; +class TestCaseHandle; +struct TestCaseInfo; +class ITestCaseRegistry; +class IExceptionTranslatorRegistry; +class IExceptionTranslator; +class ReporterRegistry; +class IReporterFactory; +class ITagAliasRegistry; +class ITestInvoker; +class IMutableEnumValuesRegistry; +struct SourceLineInfo; - using IReporterFactoryPtr = Detail::unique_ptr; +class StartupExceptionRegistry; +class EventListenerFactory; - class IRegistryHub { - public: - virtual ~IRegistryHub(); // = default +using IReporterFactoryPtr = Detail::unique_ptr; - virtual ReporterRegistry const& getReporterRegistry() const = 0; - virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; - virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; - virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0; +class IRegistryHub +{ + public: + virtual ~IRegistryHub(); // = default + virtual ReporterRegistry 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; - }; + virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0; +}; - class IMutableRegistryHub { - public: - virtual ~IMutableRegistryHub(); // = default - virtual void registerReporter( std::string const& name, IReporterFactoryPtr factory ) = 0; - virtual void registerListener( Detail::unique_ptr factory ) = 0; - virtual void registerTest(Detail::unique_ptr&& testInfo, Detail::unique_ptr&& invoker) = 0; - virtual void registerTranslator( Detail::unique_ptr&& translator ) = 0; - virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; - virtual void registerStartupException() noexcept = 0; - virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0; - }; +class IMutableRegistryHub +{ + public: + virtual ~IMutableRegistryHub(); // = default + virtual void registerReporter(std::string const& name, IReporterFactoryPtr factory) = 0; + virtual void registerListener(Detail::unique_ptr factory) = 0; + virtual void registerTest(Detail::unique_ptr&& testInfo, Detail::unique_ptr&& invoker) = 0; + virtual void registerTranslator(Detail::unique_ptr&& translator) = 0; + virtual void registerTagAlias(std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo) = 0; + virtual void registerStartupException() noexcept = 0; + virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0; +}; - IRegistryHub const& getRegistryHub(); - IMutableRegistryHub& getMutableRegistryHub(); - void cleanUp(); - std::string translateActiveException(); +IRegistryHub const& getRegistryHub(); +IMutableRegistryHub& getMutableRegistryHub(); +void cleanUp(); +std::string translateActiveException(); -} +} // namespace Catch #endif // CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED - #ifndef CATCH_BENCHMARK_STATS_HPP_INCLUDED #define CATCH_BENCHMARK_STATS_HPP_INCLUDED - - // Adapted from donated nonius code. #ifndef CATCH_ESTIMATE_HPP_INCLUDED #define CATCH_ESTIMATE_HPP_INCLUDED -namespace Catch { - namespace Benchmark { - template - struct Estimate { - Duration point; - Duration lower_bound; - Duration upper_bound; - double confidence_interval; - - template - operator Estimate() const { - return { point, lower_bound, upper_bound, confidence_interval }; - } - }; - } // namespace Benchmark +namespace Catch +{ +namespace Benchmark +{ +template +struct Estimate { + Duration point; + Duration lower_bound; + Duration upper_bound; + double confidence_interval; + + template + operator Estimate() const + { + return {point, lower_bound, upper_bound, confidence_interval}; + } +}; +} // namespace Benchmark } // namespace Catch #endif // CATCH_ESTIMATE_HPP_INCLUDED - // Adapted from donated nonius code. #ifndef CATCH_OUTLIER_CLASSIFICATION_HPP_INCLUDED #define CATCH_OUTLIER_CLASSIFICATION_HPP_INCLUDED -namespace Catch { - namespace Benchmark { - struct OutlierClassification { - int samples_seen = 0; - int low_severe = 0; // more than 3 times IQR below Q1 - int low_mild = 0; // 1.5 to 3 times IQR below Q1 - int high_mild = 0; // 1.5 to 3 times IQR above Q3 - int high_severe = 0; // more than 3 times IQR above Q3 - - int total() const { - return low_severe + low_mild + high_mild + high_severe; - } - }; - } // namespace Benchmark +namespace Catch +{ +namespace Benchmark +{ +struct OutlierClassification { + int samples_seen = 0; + int low_severe = 0; // more than 3 times IQR below Q1 + int low_mild = 0; // 1.5 to 3 times IQR below Q1 + int high_mild = 0; // 1.5 to 3 times IQR above Q3 + int high_severe = 0; // more than 3 times IQR above Q3 + + int total() const + { + return low_severe + low_mild + high_mild + high_severe; + } +}; +} // namespace Benchmark } // namespace Catch #endif // CATCH_OUTLIERS_CLASSIFICATION_HPP_INCLUDED @@ -1292,16 +1295,17 @@ namespace Catch { #include #include -namespace Catch { +namespace Catch +{ - struct BenchmarkInfo { - std::string name; - double estimatedDuration; - int iterations; - unsigned int samples; - unsigned int resamples; - double clockResolution; - double clockCost; +struct BenchmarkInfo { + std::string name; + double estimatedDuration; + int iterations; + unsigned int samples; + unsigned int resamples; + double clockResolution; + double clockCost; }; template @@ -1332,13 +1336,11 @@ namespace Catch { } }; - -} // end namespace Catch + } // end namespace Catch #endif // CATCH_BENCHMARK_STATS_HPP_INCLUDED - -// Adapted from donated nonius code. + // Adapted from donated nonius code. #ifndef CATCH_CLOCK_HPP_INCLUDED #define CATCH_CLOCK_HPP_INCLUDED @@ -1371,58 +1373,52 @@ namespace Catch { #endif // CATCH_CLOCK_HPP_INCLUDED - // Adapted from donated nonius code. #ifndef CATCH_ENVIRONMENT_HPP_INCLUDED #define CATCH_ENVIRONMENT_HPP_INCLUDED - -namespace Catch { - namespace Benchmark { - template - struct EnvironmentEstimate { - Duration mean; - OutlierClassification outliers; - - template - operator EnvironmentEstimate() const { - return { mean, outliers }; - } - }; - template - struct Environment { - using clock_type = Clock; - EnvironmentEstimate> clock_resolution; - EnvironmentEstimate> clock_cost; - }; - } // namespace Benchmark +namespace Catch +{ +namespace Benchmark +{ +template +struct EnvironmentEstimate { + Duration mean; + OutlierClassification outliers; + + template + operator EnvironmentEstimate() const + { + return {mean, outliers}; + } +}; +template +struct Environment { + using clock_type = Clock; + EnvironmentEstimate> clock_resolution; + EnvironmentEstimate> clock_cost; +}; +} // namespace Benchmark } // namespace Catch #endif // CATCH_ENVIRONMENT_HPP_INCLUDED - // Adapted from donated nonius code. #ifndef CATCH_EXECUTION_PLAN_HPP_INCLUDED #define CATCH_EXECUTION_PLAN_HPP_INCLUDED - - // Adapted from donated nonius code. #ifndef CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED #define CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED - - // Adapted from donated nonius code. #ifndef CATCH_CHRONOMETER_HPP_INCLUDED #define CATCH_CHRONOMETER_HPP_INCLUDED - - // Adapted from donated nonius code. #ifndef CATCH_OPTIMIZER_HPP_INCLUDED @@ -1454,13 +1450,14 @@ namespace Catch { #if defined(_MSVC_VER) #pragma optimize("", off) #elif defined(__IAR_SYSTEMS_ICC__) -// For IAR the pragma only affects the following function -#pragma optimize=disable + // For IAR the pragma only affects the following function +#pragma optimize = disable #endif - template - inline void keep_memory(T* p) { - // thanks @milleniumbug - *reinterpret_cast(p) = *reinterpret_cast(p); + template + inline void keep_memory(T* p) + { + // thanks @milleniumbug + *reinterpret_cast(p) = *reinterpret_cast(p); } // TODO equivalent keep_memory() #if defined(_MSVC_VER) @@ -1494,7 +1491,6 @@ namespace Catch { #endif // CATCH_OPTIMIZER_HPP_INCLUDED - #ifndef CATCH_META_HPP_INCLUDED #define CATCH_META_HPP_INCLUDED @@ -1558,39 +1554,44 @@ namespace Catch { TimePoint started; TimePoint finished; }; - } // namespace Detail + } // namespace Detail - struct Chronometer { - public: - template - void measure(Fun&& fun) { measure(CATCH_FORWARD(fun), is_callable()); } + struct Chronometer { + public: + template + void measure(Fun&& fun) + { + measure(CATCH_FORWARD(fun), is_callable()); + } - int runs() const { return repeats; } + int runs() const { return repeats; } - Chronometer(Detail::ChronometerConcept& meter, int repeats_) - : impl(&meter) - , repeats(repeats_) {} + Chronometer(Detail::ChronometerConcept& meter, int repeats_) + : impl(&meter), repeats(repeats_) {} - private: - template - void measure(Fun&& fun, std::false_type) { + private: + template + void measure(Fun&& fun, std::false_type) + { measure([&fun](int) { return fun(); }, std::true_type()); - } + } - template - void measure(Fun&& fun, std::true_type) { + template + void measure(Fun&& fun, std::true_type) + { Detail::optimizer_barrier(); impl->start(); - for (int i = 0; i < repeats; ++i) invoke_deoptimized(fun, i); + for (int i = 0; i < repeats; ++i) + invoke_deoptimized(fun, i); impl->finish(); Detail::optimizer_barrier(); - } + } - Detail::ChronometerConcept* impl; - int repeats; - }; - } // namespace Benchmark -} // namespace Catch + Detail::ChronometerConcept* impl; + int repeats; + }; + } // namespace Benchmark + } // namespace Catch #endif // CATCH_CHRONOMETER_HPP_INCLUDED @@ -1728,59 +1729,68 @@ namespace Catch { #ifndef CATCH_MEASURE_HPP_INCLUDED #define CATCH_MEASURE_HPP_INCLUDED - - // Adapted from donated nonius code. #ifndef CATCH_COMPLETE_INVOKE_HPP_INCLUDED #define CATCH_COMPLETE_INVOKE_HPP_INCLUDED +namespace Catch +{ +namespace Benchmark +{ +namespace Detail +{ +template +struct CompleteType { + using type = T; +}; +template <> +struct CompleteType { + struct type { + }; +}; -namespace Catch { - namespace Benchmark { - namespace Detail { - template - struct CompleteType { using type = T; }; - template <> - struct CompleteType { struct type {}; }; - - template - using CompleteType_t = typename CompleteType::type; - - template - struct CompleteInvoker { - template - static Result invoke(Fun&& fun, Args&&... args) { - return CATCH_FORWARD(fun)(CATCH_FORWARD(args)...); - } - }; - template <> - struct CompleteInvoker { - template - static CompleteType_t invoke(Fun&& fun, Args&&... args) { - CATCH_FORWARD(fun)(CATCH_FORWARD(args)...); - return {}; - } - }; +template +using CompleteType_t = typename CompleteType::type; + +template +struct CompleteInvoker { + template + static Result invoke(Fun&& fun, Args&&... args) + { + return CATCH_FORWARD(fun)(CATCH_FORWARD(args)...); + } +}; +template <> +struct CompleteInvoker { + template + static CompleteType_t invoke(Fun&& fun, Args&&... args) + { + CATCH_FORWARD(fun) + (CATCH_FORWARD(args)...); + return {}; + } +}; - // invoke and not return void :( - template - CompleteType_t> complete_invoke(Fun&& fun, Args&&... args) { - return CompleteInvoker>::invoke(CATCH_FORWARD(fun), CATCH_FORWARD(args)...); - } +// invoke and not return void :( +template +CompleteType_t> complete_invoke(Fun&& fun, Args&&... args) +{ + return CompleteInvoker>::invoke(CATCH_FORWARD(fun), CATCH_FORWARD(args)...); +} - } // namespace Detail +} // namespace Detail - template - Detail::CompleteType_t> user_code(Fun&& fun) { - return Detail::complete_invoke(CATCH_FORWARD(fun)); - } - } // namespace Benchmark +template +Detail::CompleteType_t> user_code(Fun&& fun) +{ + return Detail::complete_invoke(CATCH_FORWARD(fun)); +} +} // namespace Benchmark } // namespace Catch #endif // CATCH_COMPLETE_INVOKE_HPP_INCLUDED - // Adapted from donated nonius code. #ifndef CATCH_TIMING_HPP_INCLUDED @@ -1891,15 +1901,15 @@ namespace Catch { std::vector> times; const auto num_samples = cfg.benchmarkSamples(); - times.reserve( num_samples ); - for ( size_t i = 0; i < num_samples; ++i ) { - Detail::ChronometerModel model; - this->benchmark( Chronometer( model, iterations_per_sample ) ); - auto sample_time = model.elapsed() - env.clock_cost.mean; - if ( sample_time < FloatDuration::zero() ) { - sample_time = FloatDuration::zero(); - } - times.push_back(sample_time / iterations_per_sample); + times.reserve(num_samples); + for (size_t i = 0; i < num_samples; ++i) { + Detail::ChronometerModel model; + this->benchmark(Chronometer(model, iterations_per_sample)); + auto sample_time = model.elapsed() - env.clock_cost.mean; + if (sample_time < FloatDuration::zero()) { + sample_time = FloatDuration::zero(); + } + times.push_back(sample_time / iterations_per_sample); } return times; } @@ -1939,28 +1949,29 @@ namespace Catch { double weighted_average_quantile(int k, int q, std::vector::iterator first, std::vector::iterator last); OutlierClassification - classify_outliers( std::vector::const_iterator first, - std::vector::const_iterator last ); + classify_outliers(std::vector::const_iterator first, + std::vector::const_iterator last); - double mean( std::vector::const_iterator first, - std::vector::const_iterator last ); + double mean(std::vector::const_iterator first, + std::vector::const_iterator last); template sample jackknife(Estimator&& estimator, std::vector::iterator first, - std::vector::iterator last) { - auto n = static_cast(last - first); - auto second = first; - ++second; - sample results; - results.reserve(n); - - for (auto it = first; it != last; ++it) { - std::iter_swap(it, first); - results.push_back(estimator(second, last)); - } + std::vector::iterator last) + { + auto n = static_cast(last - first); + auto second = first; + ++second; + sample results; + results.reserve(n); - return results; + for (auto it = first; it != last; ++it) { + std::iter_swap(it, first); + results.push_back(estimator(second, last)); + } + + return results; } inline double normal_cdf(double x) { @@ -1972,50 +1983,53 @@ namespace Catch { double normal_quantile(double p); template - Estimate bootstrap( double confidence_level, - std::vector::iterator first, - std::vector::iterator last, - sample const& resample, - Estimator&& estimator ) { - auto n_samples = last - first; - - double point = estimator(first, last); - // Degenerate case with a single sample - if (n_samples == 1) return { point, point, point, confidence_level }; - - sample jack = jackknife(estimator, first, last); - double jack_mean = mean(jack.begin(), jack.end()); - double sum_squares = 0, sum_cubes = 0; - for (double x : jack) { - auto difference = jack_mean - x; - auto square = difference * difference; - auto cube = square * difference; - sum_squares += square; sum_cubes += cube; - } - - double accel = sum_cubes / (6 * std::pow(sum_squares, 1.5)); - long n = static_cast(resample.size()); - double prob_n = std::count_if(resample.begin(), resample.end(), [point](double x) { return x < point; }) / static_cast(n); - // degenerate case with uniform samples - if ( directCompare( prob_n, 0. ) ) { - return { point, point, point, confidence_level }; - } - - double bias = normal_quantile(prob_n); - double z1 = normal_quantile((1. - confidence_level) / 2.); - - auto cumn = [n]( double x ) -> long { - return std::lround( normal_cdf( x ) * static_cast(n) ); - }; - auto a = [bias, accel](double b) { return bias + b / (1. - accel * b); }; - double b1 = bias + z1; - double b2 = bias - z1; - double a1 = a(b1); - double a2 = a(b2); - auto lo = static_cast((std::max)(cumn(a1), 0l)); - auto hi = static_cast((std::min)(cumn(a2), n - 1)); - - return { point, resample[lo], resample[hi], confidence_level }; + Estimate bootstrap(double confidence_level, + std::vector::iterator first, + std::vector::iterator last, + sample const& resample, + Estimator&& estimator) + { + auto n_samples = last - first; + + double point = estimator(first, last); + // Degenerate case with a single sample + if (n_samples == 1) + return {point, point, point, confidence_level}; + + sample jack = jackknife(estimator, first, last); + double jack_mean = mean(jack.begin(), jack.end()); + double sum_squares = 0, sum_cubes = 0; + for (double x : jack) { + auto difference = jack_mean - x; + auto square = difference * difference; + auto cube = square * difference; + sum_squares += square; + sum_cubes += cube; + } + + double accel = sum_cubes / (6 * std::pow(sum_squares, 1.5)); + long n = static_cast(resample.size()); + double prob_n = std::count_if(resample.begin(), resample.end(), [point](double x) { return x < point; }) / static_cast(n); + // degenerate case with uniform samples + if (directCompare(prob_n, 0.)) { + return {point, point, point, confidence_level}; + } + + double bias = normal_quantile(prob_n); + double z1 = normal_quantile((1. - confidence_level) / 2.); + + auto cumn = [n](double x) -> long { + return std::lround(normal_cdf(x) * static_cast(n)); + }; + auto a = [bias, accel](double b) { return bias + b / (1. - accel * b); }; + double b1 = bias + z1; + double b2 = bias - z1; + double a1 = a(b1); + double a2 = a(b2); + auto lo = static_cast((std::max)(cumn(a1), 0l)); + auto hi = static_cast((std::min)(cumn(a2), n - 1)); + + return {point, resample[lo], resample[hi], confidence_level}; } struct bootstrap_analysis { @@ -2045,15 +2059,15 @@ namespace Catch { std::vector resolution(int k) { std::vector> times; times.reserve(static_cast(k + 1)); - for ( int i = 0; i < k + 1; ++i ) { - times.push_back( Clock::now() ); + for (int i = 0; i < k + 1; ++i) { + times.push_back(Clock::now()); } std::vector deltas; deltas.reserve(static_cast(k)); - for ( size_t idx = 1; idx < times.size(); ++idx ) { - deltas.push_back( static_cast( - ( times[idx] - times[idx - 1] ).count() ) ); + for (size_t idx = 1; idx < times.size(); ++idx) { + deltas.push_back(static_cast( + (times[idx] - times[idx - 1]).count())); } return deltas; @@ -2102,10 +2116,10 @@ namespace Catch { std::vector times; int nsamples = static_cast(std::ceil(time_limit / r.elapsed)); times.reserve(static_cast(nsamples)); - for ( int s = 0; s < nsamples; ++s ) { - times.push_back( static_cast( - ( time_clock( r.iterations ) / r.iterations ) - .count() ) ); + for (int s = 0; s < nsamples; ++s) { + times.push_back(static_cast( + (time_clock(r.iterations) / r.iterations) + .count())); } return { FloatDuration(mean(times.begin(), times.end())), @@ -2153,7 +2167,6 @@ namespace Catch { #ifndef CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED #define CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED - #include namespace Catch { @@ -2171,7 +2184,7 @@ namespace Catch { std::vector samples2; samples2.reserve(samples.size()); for (auto const& d : samples) { - samples2.push_back(Duration2(d)); + samples2.push_back(Duration2(d)); } return { CATCH_MOVE(samples2), @@ -2198,7 +2211,7 @@ namespace Catch { std::vector samples; samples.reserve(static_cast(last - first)); for (auto current = first; current != last; ++current) { - samples.push_back( current->count() ); + samples.push_back(current->count()); } auto analysis = Catch::Benchmark::Detail::analyse_samples(cfg.benchmarkConfidenceInterval(), cfg.benchmarkResamples(), samples.begin(), samples.end()); @@ -2215,7 +2228,7 @@ namespace Catch { std::vector samples2; samples2.reserve(samples.size()); for (auto s : samples) { - samples2.push_back( Duration( s ) ); + samples2.push_back(Duration(s)); } return { @@ -2310,13 +2323,17 @@ namespace Catch { auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end()); BenchmarkStats> stats{ CATCH_MOVE(info), CATCH_MOVE(analysis.samples), analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance }; getResultCapture().benchmarkEnded(stats); - } CATCH_CATCH_ANON (TestFailureException const&) { - getResultCapture().benchmarkFailed("Benchmark failed due to failed assertion"_sr); - } CATCH_CATCH_ALL{ - getResultCapture().benchmarkFailed(translateActiveException()); - // We let the exception go further up so that the - // test case is marked as failed. - std::rethrow_exception(std::current_exception()); + } + CATCH_CATCH_ANON(TestFailureException const&) + { + getResultCapture().benchmarkFailed("Benchmark failed due to failed assertion"_sr); + } + CATCH_CATCH_ALL + { + getResultCapture().benchmarkFailed(translateActiveException()); + // We let the exception go further up so that the + // test case is marked as failed. + std::rethrow_exception(std::current_exception()); } } @@ -2478,7 +2495,6 @@ namespace Catch { #ifndef CATCH_CONFIG_WCHAR_HPP_INCLUDED #define CATCH_CONFIG_WCHAR_HPP_INCLUDED - // We assume that WCHAR should be enabled by default, and only disabled // for a shortlist (so far only DJGPP) of compilers. @@ -2701,7 +2717,6 @@ namespace Catch { } // namespace Detail - template struct StringMaker { template @@ -3302,211 +3317,220 @@ namespace Catch { } template ::value>> - friend bool operator != ( Approx const& lhs, T const& rhs ) { - return !operator==( rhs, lhs ); + friend bool operator!=(Approx const& lhs, T const& rhs) + { + return !operator==(rhs, lhs); } template ::value>> - friend bool operator <= ( T const& lhs, Approx const& rhs ) { - return static_cast(lhs) < rhs.m_value || lhs == rhs; + friend bool operator<=(T const& lhs, Approx const& rhs) + { + return static_cast(lhs) < rhs.m_value || lhs == rhs; } template ::value>> - friend bool operator <= ( Approx const& lhs, T const& rhs ) { - return lhs.m_value < static_cast(rhs) || lhs == rhs; + friend bool operator<=(Approx const& lhs, T const& rhs) + { + return lhs.m_value < static_cast(rhs) || lhs == rhs; } template ::value>> - friend bool operator >= ( T const& lhs, Approx const& rhs ) { - return static_cast(lhs) > rhs.m_value || lhs == rhs; + friend bool operator>=(T const& lhs, Approx const& rhs) + { + return static_cast(lhs) > rhs.m_value || lhs == rhs; } template ::value>> - friend bool operator >= ( Approx const& lhs, T const& rhs ) { - return lhs.m_value > static_cast(rhs) || lhs == rhs; + friend bool operator>=(Approx const& lhs, T const& rhs) + { + return lhs.m_value > static_cast(rhs) || lhs == rhs; } template ::value>> - Approx& epsilon( T const& newEpsilon ) { - const auto epsilonAsDouble = static_cast(newEpsilon); - setEpsilon(epsilonAsDouble); - return *this; + Approx& epsilon(T const& newEpsilon) + { + const auto epsilonAsDouble = static_cast(newEpsilon); + setEpsilon(epsilonAsDouble); + return *this; } template ::value>> - Approx& margin( T const& newMargin ) { - const auto marginAsDouble = static_cast(newMargin); - setMargin(marginAsDouble); - return *this; + Approx& margin(T const& newMargin) + { + const auto marginAsDouble = static_cast(newMargin); + setMargin(marginAsDouble); + return *this; } template ::value>> - Approx& scale( T const& newScale ) { - m_scale = static_cast(newScale); - return *this; + Approx& scale(T const& newScale) + { + m_scale = static_cast(newScale); + return *this; } std::string toString() const; - private: + private: double m_epsilon; double m_margin; double m_scale; double m_value; }; -namespace literals { - Approx operator ""_a(long double val); - Approx operator ""_a(unsigned long long val); -} // end namespace literals + namespace literals + { + Approx operator""_a(long double val); + Approx operator""_a(unsigned long long val); + } // end namespace literals -template<> -struct StringMaker { - static std::string convert(Catch::Approx const& value); -}; + template <> + struct StringMaker { + static std::string convert(Catch::Approx const& value); + }; -} // end namespace Catch + } // end namespace Catch #endif // CATCH_APPROX_HPP_INCLUDED - #ifndef CATCH_ASSERTION_INFO_HPP_INCLUDED #define CATCH_ASSERTION_INFO_HPP_INCLUDED - - #ifndef CATCH_SOURCE_LINE_INFO_HPP_INCLUDED #define CATCH_SOURCE_LINE_INFO_HPP_INCLUDED #include #include -namespace Catch { + namespace Catch + { struct SourceLineInfo { - SourceLineInfo() = delete; - constexpr SourceLineInfo( char const* _file, std::size_t _line ) noexcept: - file( _file ), - line( _line ) - {} + SourceLineInfo() = delete; + constexpr SourceLineInfo(char const* _file, std::size_t _line) noexcept : file(_file), + line(_line) + { + } - bool operator == ( SourceLineInfo const& other ) const noexcept; - bool operator < ( SourceLineInfo const& other ) const noexcept; + bool operator==(SourceLineInfo const& other) const noexcept; + bool operator<(SourceLineInfo const& other) const noexcept; - char const* file; - std::size_t line; + char const* file; + std::size_t line; - friend std::ostream& operator << (std::ostream& os, SourceLineInfo const& info); + friend std::ostream& operator<<(std::ostream& os, SourceLineInfo const& info); }; -} + } // namespace Catch #define CATCH_INTERNAL_LINEINFO \ - ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) + ::Catch::SourceLineInfo(__FILE__, static_cast(__LINE__)) #endif // CATCH_SOURCE_LINE_INFO_HPP_INCLUDED -namespace Catch { + namespace Catch + { struct AssertionInfo { - // AssertionInfo() = delete; + // AssertionInfo() = delete; - StringRef macroName; - SourceLineInfo lineInfo; - StringRef capturedExpression; - ResultDisposition::Flags resultDisposition; + StringRef macroName; + SourceLineInfo lineInfo; + StringRef capturedExpression; + ResultDisposition::Flags resultDisposition; }; -} // end namespace Catch + } // end namespace Catch #endif // CATCH_ASSERTION_INFO_HPP_INCLUDED - #ifndef CATCH_ASSERTION_RESULT_HPP_INCLUDED #define CATCH_ASSERTION_RESULT_HPP_INCLUDED - - #ifndef CATCH_LAZY_EXPR_HPP_INCLUDED #define CATCH_LAZY_EXPR_HPP_INCLUDED #include -namespace Catch { + namespace Catch + { class ITransientExpression; - class LazyExpression { - friend class AssertionHandler; - friend struct AssertionStats; - friend 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 ): - m_isNegated(isNegated) - {} - LazyExpression(LazyExpression const& other) = default; - LazyExpression& operator = ( LazyExpression const& ) = delete; + ITransientExpression const* m_transientExpression = nullptr; + bool m_isNegated; - explicit operator bool() const { - return m_transientExpression != nullptr; - } + public: + LazyExpression(bool isNegated) : m_isNegated(isNegated) + { + } + LazyExpression(LazyExpression const& other) = default; + LazyExpression& operator=(LazyExpression const&) = delete; - friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&; + explicit operator bool() const + { + return m_transientExpression != nullptr; + } + + friend auto operator<<(std::ostream& os, LazyExpression const& lazyExpr) -> std::ostream&; }; -} // namespace Catch + } // namespace Catch #endif // CATCH_LAZY_EXPR_HPP_INCLUDED #include -namespace Catch { - - struct AssertionResultData + namespace Catch { - AssertionResultData() = delete; - AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ); + struct AssertionResultData { + AssertionResultData() = delete; - std::string message; - mutable std::string reconstructedExpression; - LazyExpression lazyExpression; - ResultWas::OfType resultType; + AssertionResultData(ResultWas::OfType _resultType, LazyExpression const& _lazyExpression); - std::string reconstructExpression() const; - }; + std::string message; + mutable std::string reconstructedExpression; + LazyExpression lazyExpression; + ResultWas::OfType resultType; - class AssertionResult { - public: - AssertionResult() = delete; - AssertionResult( AssertionInfo const& info, AssertionResultData&& 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; - StringRef getMessage() const; - SourceLineInfo getSourceInfo() const; - StringRef getTestMacroName() const; - - //protected: - AssertionInfo m_info; - AssertionResultData m_resultData; + std::string reconstructExpression() const; }; -} // end namespace Catch + class AssertionResult + { + public: + AssertionResult() = delete; + AssertionResult(AssertionInfo const& info, AssertionResultData&& 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; + StringRef getMessage() const; + SourceLineInfo getSourceInfo() const; + StringRef getTestMacroName() const; + + // protected: + AssertionInfo m_info; + AssertionResultData m_resultData; + }; + + } // end namespace Catch #endif // CATCH_ASSERTION_RESULT_HPP_INCLUDED - #ifndef CATCH_CONFIG_HPP_INCLUDED #define CATCH_CONFIG_HPP_INCLUDED @@ -3671,7 +3695,6 @@ namespace Catch { #ifndef CATCH_OPTIONAL_HPP_INCLUDED #define CATCH_OPTIONAL_HPP_INCLUDED - #include namespace Catch { @@ -3680,50 +3703,54 @@ namespace Catch { template class Optional { public: - Optional(): nullableValue( nullptr ) {} - ~Optional() { reset(); } - - Optional( T const& _value ): - nullableValue( new ( storage ) T( _value ) ) {} - Optional( T&& _value ): - nullableValue( new ( storage ) T( CATCH_MOVE( _value ) ) ) {} - - Optional& operator=( T const& _value ) { - reset(); - nullableValue = new ( storage ) T( _value ); - return *this; - } - Optional& operator=( T&& _value ) { - reset(); - nullableValue = new ( storage ) T( CATCH_MOVE( _value ) ); - return *this; - } - - Optional( Optional const& _other ): - nullableValue( _other ? new ( storage ) T( *_other ) : nullptr ) {} - Optional( Optional&& _other ): - nullableValue( _other ? new ( storage ) T( CATCH_MOVE( *_other ) ) - : nullptr ) {} - - Optional& operator=( Optional const& _other ) { - if ( &_other != this ) { - reset(); - if ( _other ) { nullableValue = new ( storage ) T( *_other ); } - } - return *this; - } - Optional& operator=( Optional&& _other ) { - if ( &_other != this ) { - reset(); - if ( _other ) { - nullableValue = new ( storage ) T( CATCH_MOVE( *_other ) ); - } - } - return *this; - } + Optional() : nullableValue(nullptr) {} + ~Optional() { reset(); } + + Optional(T const& _value) : nullableValue(new (storage) T(_value)) {} + Optional(T&& _value) : nullableValue(new (storage) T(CATCH_MOVE(_value))) {} + + Optional& operator=(T const& _value) + { + reset(); + nullableValue = new (storage) T(_value); + return *this; + } + Optional& operator=(T&& _value) + { + reset(); + nullableValue = new (storage) T(CATCH_MOVE(_value)); + return *this; + } + + Optional(Optional const& _other) : nullableValue(_other ? new (storage) T(*_other) : nullptr) {} + Optional(Optional&& _other) : nullableValue(_other ? new (storage) T(CATCH_MOVE(*_other)) + : nullptr) {} + + Optional& operator=(Optional const& _other) + { + if (&_other != this) { + reset(); + if (_other) { + nullableValue = new (storage) T(*_other); + } + } + return *this; + } + Optional& operator=(Optional&& _other) + { + if (&_other != this) { + reset(); + if (_other) { + nullableValue = new (storage) T(CATCH_MOVE(*_other)); + } + } + return *this; + } void reset() { - if ( nullableValue ) { nullableValue->~T(); } + if (nullableValue) { + nullableValue->~T(); + } nullableValue = nullptr; } @@ -3770,8 +3797,8 @@ namespace Catch { } private: - T* nullableValue; - alignas(alignof(T)) char storage[sizeof(T)]; + T* nullableValue; + alignas(alignof(T)) char storage[sizeof(T)]; }; } // end namespace Catch @@ -4177,47 +4204,50 @@ namespace Catch { // as well as // << stuff +StreamEndStop struct StreamEndStop { - constexpr StringRef operator+() const { return StringRef(); } + constexpr StringRef operator+() const { return StringRef(); } - template - constexpr friend T const& operator+( T const& value, StreamEndStop ) { - return value; - } + template + constexpr friend T const& operator+(T const& value, StreamEndStop) + { + return value; + } }; } // namespace Catch #endif // CATCH_STREAM_END_STOP_HPP_INCLUDED - #ifndef CATCH_MESSAGE_INFO_HPP_INCLUDED #define CATCH_MESSAGE_INFO_HPP_INCLUDED - #include -namespace Catch { - - struct MessageInfo { - MessageInfo( StringRef _macroName, - SourceLineInfo const& _lineInfo, - ResultWas::OfType _type ); - - StringRef macroName; - std::string message; - SourceLineInfo lineInfo; - ResultWas::OfType type; - unsigned int sequence; +namespace Catch +{ - bool operator == (MessageInfo const& other) const { - return sequence == other.sequence; - } - bool operator < (MessageInfo const& other) const { - return sequence < other.sequence; - } - private: - static unsigned int globalCount; - }; +struct MessageInfo { + MessageInfo(StringRef _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 + { + return sequence == other.sequence; + } + bool operator<(MessageInfo const& other) const + { + return sequence < other.sequence; + } + + private: + static unsigned int globalCount; +}; } // end namespace Catch @@ -4305,12 +4335,12 @@ namespace Catch { } while( false ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \ - Catch::Capturer varName( macroName##_catch_sr, \ - CATCH_INTERNAL_LINEINFO, \ - Catch::ResultWas::Info, \ - #__VA_ARGS__##_catch_sr ); \ - varName.captureValues( 0, __VA_ARGS__ ) +#define INTERNAL_CATCH_CAPTURE(varName, macroName, ...) \ + Catch::Capturer varName(macroName##_catch_sr, \ + CATCH_INTERNAL_LINEINFO, \ + Catch::ResultWas::Info, \ + #__VA_ARGS__##_catch_sr); \ + varName.captureValues(0, __VA_ARGS__) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_INFO( macroName, log ) \ @@ -4356,76 +4386,74 @@ namespace Catch { #endif // CATCH_MESSAGE_HPP_INCLUDED - #ifndef CATCH_SECTION_INFO_HPP_INCLUDED #define CATCH_SECTION_INFO_HPP_INCLUDED - - #ifndef CATCH_TOTALS_HPP_INCLUDED #define CATCH_TOTALS_HPP_INCLUDED #include -namespace Catch { +namespace Catch +{ - struct Counts { - Counts operator - ( Counts const& other ) const; - Counts& operator += ( Counts const& other ); +struct Counts { + Counts operator-(Counts const& other) const; + Counts& operator+=(Counts const& other); - std::uint64_t total() const; - bool allPassed() const; - bool allOk() const; + std::uint64_t total() const; + bool allPassed() const; + bool allOk() const; - std::uint64_t passed = 0; - std::uint64_t failed = 0; - std::uint64_t failedButOk = 0; - std::uint64_t skipped = 0; - }; + std::uint64_t passed = 0; + std::uint64_t failed = 0; + std::uint64_t failedButOk = 0; + std::uint64_t skipped = 0; +}; - struct Totals { +struct Totals { - Totals operator - ( Totals const& other ) const; - Totals& operator += ( Totals const& other ); + Totals operator-(Totals const& other) const; + Totals& operator+=(Totals const& other); - Totals delta( Totals const& prevTotals ) const; + Totals delta(Totals const& prevTotals) const; - Counts assertions; - Counts testCases; - }; -} + Counts assertions; + Counts testCases; +}; +} // namespace Catch #endif // CATCH_TOTALS_HPP_INCLUDED #include -namespace Catch { - - struct SectionInfo { - // The last argument is ignored, so that people can write - // SECTION("ShortName", "Proper description that is long") and - // still use the `-c` flag comfortably. - SectionInfo( SourceLineInfo const& _lineInfo, std::string _name, - const char* const = nullptr ): - name(CATCH_MOVE(_name)), - lineInfo(_lineInfo) - {} +namespace Catch +{ - std::string name; - SourceLineInfo lineInfo; - }; +struct SectionInfo { + // The last argument is ignored, so that people can write + // SECTION("ShortName", "Proper description that is long") and + // still use the `-c` flag comfortably. + SectionInfo(SourceLineInfo const& _lineInfo, std::string _name, + const char* const = nullptr) : name(CATCH_MOVE(_name)), + lineInfo(_lineInfo) + { + } + + std::string name; + SourceLineInfo lineInfo; +}; - struct SectionEndInfo { - SectionInfo sectionInfo; - Counts prevAssertions; - double durationInSeconds; - }; +struct SectionEndInfo { + SectionInfo sectionInfo; + Counts prevAssertions; + double durationInSeconds; +}; } // end namespace Catch #endif // CATCH_SECTION_INFO_HPP_INCLUDED - #ifndef CATCH_SESSION_HPP_INCLUDED #define CATCH_SESSION_HPP_INCLUDED @@ -5752,15 +5780,13 @@ namespace Catch { #endif // CATCH_ASSERTION_HANDLER_HPP_INCLUDED - #ifndef CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED #define CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED - #if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) - #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__##_catch_sr +#define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__##_catch_sr #else - #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"_catch_sr +#define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"_catch_sr #endif #endif // CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED @@ -5834,73 +5860,67 @@ namespace Catch { } 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 { \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \ - CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ - static_cast(__VA_ARGS__); \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ - catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ - } \ - catch( ... ) { \ - catchAssertionHandler.handleExceptionThrownAsExpected(); \ - } \ - else \ - catchAssertionHandler.handleThrowingCallSkipped(); \ - 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 { \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \ + CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ + static_cast(__VA_ARGS__); \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ + 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 { \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \ - CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ - static_cast(expr); \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ - catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ - } \ - catch( exceptionType const& ) { \ - catchAssertionHandler.handleExceptionThrownAsExpected(); \ - } \ - catch( ... ) { \ - catchAssertionHandler.handleUnexpectedInflightException(); \ - } \ - 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 { \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \ + CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ + static_cast(expr); \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ + catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ + } catch (exceptionType const&) { \ + catchAssertionHandler.handleExceptionThrownAsExpected(); \ + } catch (...) { \ + catchAssertionHandler.handleUnexpectedInflightException(); \ + } \ + else \ + catchAssertionHandler.handleThrowingCallSkipped(); \ + INTERNAL_CATCH_REACT(catchAssertionHandler) \ + } while (false) /////////////////////////////////////////////////////////////////////////////// // 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 { \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \ - CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ - static_cast(__VA_ARGS__); \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ - catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ - } \ - catch( ... ) { \ - Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher ); \ - } \ - else \ - catchAssertionHandler.handleThrowingCallSkipped(); \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ - } while( false ) +#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 { \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \ + CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ + static_cast(__VA_ARGS__); \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ + catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ + } catch (...) { \ + Catch::handleExceptionMatchExpr(catchAssertionHandler, matcher); \ + } \ + else \ + catchAssertionHandler.handleThrowingCallSkipped(); \ + INTERNAL_CATCH_REACT(catchAssertionHandler) \ + } while (false) #endif // CATCH_CONFIG_DISABLE @@ -5910,9 +5930,6 @@ namespace Catch { #ifndef CATCH_SECTION_HPP_INCLUDED #define CATCH_SECTION_HPP_INCLUDED - - - /** \file * Wrapper for the STATIC_ANALYSIS_SUPPORT configuration option * @@ -5925,21 +5942,18 @@ namespace Catch { #ifndef CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED #define CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED - #if defined(__clang_analyzer__) || defined(__COVERITY__) - #define CATCH_INTERNAL_CONFIG_STATIC_ANALYSIS_SUPPORT +#define CATCH_INTERNAL_CONFIG_STATIC_ANALYSIS_SUPPORT #endif -#if defined( CATCH_INTERNAL_CONFIG_STATIC_ANALYSIS_SUPPORT ) && \ - !defined( CATCH_CONFIG_NO_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT ) && \ - !defined( CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT ) -# define CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT +#if defined(CATCH_INTERNAL_CONFIG_STATIC_ANALYSIS_SUPPORT) && \ + !defined(CATCH_CONFIG_NO_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT) && \ + !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT) +#define CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT #endif - #endif // CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED - #ifndef CATCH_TIMER_HPP_INCLUDED #define CATCH_TIMER_HPP_INCLUDED @@ -5985,24 +5999,24 @@ namespace Catch { } // end namespace Catch #if !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT) -# define INTERNAL_CATCH_SECTION( ... ) \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ - if ( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( \ - catch_internal_Section ) = \ - Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION - -# define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ - if ( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( \ - catch_internal_Section ) = \ - Catch::SectionInfo( \ - CATCH_INTERNAL_LINEINFO, \ - ( Catch::ReusableStringStream() << __VA_ARGS__ ) \ - .str() ) ) \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +#define INTERNAL_CATCH_SECTION(...) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + if (Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( \ + catch_internal_Section) = \ + Catch::Section(CATCH_INTERNAL_LINEINFO, __VA_ARGS__)) \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION + +#define INTERNAL_CATCH_DYNAMIC_SECTION(...) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + if (Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( \ + catch_internal_Section) = \ + Catch::SectionInfo( \ + CATCH_INTERNAL_LINEINFO, \ + (Catch::ReusableStringStream() << __VA_ARGS__) \ + .str())) \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION #else @@ -6010,46 +6024,44 @@ namespace Catch { // will be intered (because only one section's __LINE__ can be equal to // the dummy `catchInternalSectionHint` variable from `TEST_CASE`). -namespace Catch { - namespace Detail { - // Intentionally without linkage, as it should only be used as a dummy - // symbol for static analysis. - int GetNewSectionHint(); - } // namespace Detail +namespace Catch +{ +namespace Detail +{ +// Intentionally without linkage, as it should only be used as a dummy +// symbol for static analysis. +int GetNewSectionHint(); +} // namespace Detail } // namespace Catch +#define INTERNAL_CATCH_SECTION(...) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ + if ([[maybe_unused]] int catchInternalPreviousSectionHint = \ + catchInternalSectionHint, \ + catchInternalSectionHint = Catch::Detail::GetNewSectionHint(); \ + catchInternalPreviousSectionHint == __LINE__) \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION -# define INTERNAL_CATCH_SECTION( ... ) \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ - CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ - if ( [[maybe_unused]] int catchInternalPreviousSectionHint = \ - catchInternalSectionHint, \ - catchInternalSectionHint = Catch::Detail::GetNewSectionHint(); \ - catchInternalPreviousSectionHint == __LINE__ ) \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION - -# define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ - CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ - if ( [[maybe_unused]] int catchInternalPreviousSectionHint = \ - catchInternalSectionHint, \ - catchInternalSectionHint = Catch::Detail::GetNewSectionHint(); \ - catchInternalPreviousSectionHint == __LINE__ ) \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +#define INTERNAL_CATCH_DYNAMIC_SECTION(...) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ + if ([[maybe_unused]] int catchInternalPreviousSectionHint = \ + catchInternalSectionHint, \ + catchInternalSectionHint = Catch::Detail::GetNewSectionHint(); \ + catchInternalPreviousSectionHint == __LINE__) \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION #endif - #endif // CATCH_SECTION_HPP_INCLUDED #ifndef CATCH_TEST_REGISTRY_HPP_INCLUDED #define CATCH_TEST_REGISTRY_HPP_INCLUDED - - #ifndef CATCH_INTERFACES_TEST_INVOKER_HPP_INCLUDED #define CATCH_INTERFACES_TEST_INVOKER_HPP_INCLUDED @@ -6057,15 +6069,14 @@ namespace Catch { class ITestInvoker { public: - virtual void invoke() const = 0; - virtual ~ITestInvoker(); // = default + virtual void invoke() const = 0; + virtual ~ITestInvoker(); // = default }; -} // namespace Catch + } // namespace Catch #endif // CATCH_INTERFACES_TEST_INVOKER_HPP_INCLUDED - #ifndef CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED #define CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED @@ -6135,31 +6146,34 @@ struct AutoReg : Detail::NonCopyable { void TestName::test() #endif - #if !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT) - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ - static void TestName(); \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ - namespace{ const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ - static void TestName() - #define INTERNAL_CATCH_TESTCASE( ... ) \ - INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__ ) - -#else // ^^ !CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT | vv CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT - +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TESTCASE2(TestName, ...) \ + static void TestName(); \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + namespace \ + { \ + const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME(autoRegistrar)(Catch::makeTestInvoker(&TestName), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{__VA_ARGS__}); \ + } /* NOLINT */ \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ + static void TestName() +#define INTERNAL_CATCH_TESTCASE(...) \ + INTERNAL_CATCH_TESTCASE2(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_TEST_), __VA_ARGS__) + +#else // ^^ !CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT | vv CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT // Dummy registrator for the dumy test case macros -namespace Catch { - namespace Detail { - struct DummyUse { - DummyUse( void ( * )( int ) ); - }; - } // namespace Detail +namespace Catch +{ +namespace Detail +{ +struct DummyUse { + DummyUse(void (*)(int)); +}; +} // namespace Detail } // namespace Catch // Note that both the presence of the argument and its exact name are @@ -6169,67 +6183,66 @@ namespace Catch { // tests can compile. The redefined `TEST_CASE` shadows this with param. static int catchInternalSectionHint = 0; -# define INTERNAL_CATCH_TESTCASE2( fname ) \ - static void fname( int ); \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ - static const Catch::Detail::DummyUse INTERNAL_CATCH_UNIQUE_NAME( \ - dummyUser )( &fname ); \ - CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ - static void fname( [[maybe_unused]] int catchInternalSectionHint ) \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION -# define INTERNAL_CATCH_TESTCASE( ... ) \ - INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( dummyFunction ) ) - +#define INTERNAL_CATCH_TESTCASE2(fname) \ + static void fname(int); \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + static const Catch::Detail::DummyUse INTERNAL_CATCH_UNIQUE_NAME( \ + dummyUser)(&fname); \ + CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ + static void fname([[maybe_unused]] int catchInternalSectionHint) \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +#define INTERNAL_CATCH_TESTCASE(...) \ + INTERNAL_CATCH_TESTCASE2(INTERNAL_CATCH_UNIQUE_NAME(dummyFunction)) #endif // CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ - namespace{ \ - struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ - void test(); \ - }; \ - const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \ - Catch::makeTestInvoker( &TestName::test ), \ - CATCH_INTERNAL_LINEINFO, \ - #ClassName##_catch_sr, \ - Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ - } \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ - void TestName::test() - #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ - INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), ClassName, __VA_ARGS__ ) - - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ - namespace { \ - const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \ - Catch::makeTestInvoker( &QualifiedMethod ), \ - CATCH_INTERNAL_LINEINFO, \ - "&" #QualifiedMethod##_catch_sr, \ - Catch::NameAndTags{ __VA_ARGS__ } ); \ - } /* NOLINT */ \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TEST_CASE_METHOD2(TestName, ClassName, ...) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + namespace \ + { \ + struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ + void test(); \ + }; \ + const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME(autoRegistrar)( \ + Catch::makeTestInvoker(&TestName::test), \ + CATCH_INTERNAL_LINEINFO, \ + #ClassName##_catch_sr, \ + Catch::NameAndTags{__VA_ARGS__}); /* NOLINT */ \ + } \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ + void TestName::test() +#define INTERNAL_CATCH_TEST_CASE_METHOD(ClassName, ...) \ + INTERNAL_CATCH_TEST_CASE_METHOD2(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_TEST_), ClassName, __VA_ARGS__) +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_METHOD_AS_TEST_CASE(QualifiedMethod, ...) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + namespace \ + { \ + const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME(autoRegistrar)( \ + Catch::makeTestInvoker(&QualifiedMethod), \ + CATCH_INTERNAL_LINEINFO, \ + "&" #QualifiedMethod##_catch_sr, \ + Catch::NameAndTags{__VA_ARGS__}); \ + } /* NOLINT */ \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ - do { \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ - } while(false) +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_REGISTER_TESTCASE(Function, ...) \ + do { \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME(autoRegistrar)(Catch::makeTestInvoker(Function), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{__VA_ARGS__}); /* NOLINT */ \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ + } while (false) #endif // CATCH_TEST_REGISTRY_HPP_INCLUDED @@ -6820,80 +6833,87 @@ static int catchInternalSectionHint = 0; #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename T,__VA_ARGS__) #else - #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename T, __VA_ARGS__ ) ) -#endif - -#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR - #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ - INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__) -#else - #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ - INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ ) ) -#endif - - #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ - CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ - CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \ - template static void TestFunc(); \ - namespace {\ - namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\ - INTERNAL_CATCH_TYPE_GEN\ - template \ - struct TestName { \ - void reg_tests() { \ - size_t index = 0; \ - using expander = size_t[]; \ - (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\ - } \ - };\ - static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ - using TestInit = typename convert::type; \ - TestInit t; \ - t.reg_tests(); \ - return 0; \ - }(); \ - }}\ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ - template \ - static void TestFunc() - - #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \ - INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, TmplList ) - - - #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ - CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ - CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ - namespace {\ - namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \ - INTERNAL_CATCH_TYPE_GEN\ - INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\ - INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\ - INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))\ - template \ - struct TestNameClass{\ - TestNameClass(){\ - size_t index = 0; \ - constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\ - using expander = size_t[];\ - (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \ - }\ - };\ - static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ - TestNameClass();\ - return 0;\ - }();\ - }\ - }\ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ - INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature)) + #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename T, __VA_ARGS__ ) ) +#endif + +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR + #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ + INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__) +#else + #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\ + INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ ) ) +#endif + +#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \ + template \ + static void TestFunc(); \ + namespace \ + { \ + namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) \ + { \ + INTERNAL_CATCH_TYPE_GEN \ + template \ + struct TestName { \ + void reg_tests() \ + { \ + size_t index = 0; \ + using expander = size_t[]; \ + (void)expander{(Catch::AutoReg(Catch::makeTestInvoker(&TestFunc), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags}), index++)...}; /* NOLINT */ \ + } \ + }; \ + static int INTERNAL_CATCH_UNIQUE_NAME(globalRegistrar) = []() { \ + using TestInit = typename convert::type; \ + TestInit t; \ + t.reg_tests(); \ + return 0; \ + }(); \ + } \ + } \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ + template \ + static void TestFunc() + +#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \ + INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_TEMPLATE_TEST_), INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_TEMPLATE_TEST_), Name, Tags, TmplList) + +#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, ...) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + namespace \ + { \ + namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) \ + { \ + INTERNAL_CATCH_TYPE_GEN \ + INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature)) \ + INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature)); \ + INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature)) \ + template \ + struct TestNameClass { \ + TestNameClass() \ + { \ + size_t index = 0; \ + constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)}; \ + using expander = size_t[]; \ + (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{Name " - " + std::string(tmpl_types[index]), Tags}), index++)...}; /* NOLINT */ \ + } \ + }; \ + static int INTERNAL_CATCH_UNIQUE_NAME(globalRegistrar) = []() { \ + TestNameClass(); \ + return 0; \ + }(); \ + } \ + } \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ + INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature)) #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ @@ -6964,37 +6984,41 @@ static int catchInternalSectionHint = 0; INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, Signature,__VA_ARGS__ ) ) #endif - #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ - CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ - CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \ - template \ - struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName ) { \ - void test();\ - };\ - namespace {\ - namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \ - INTERNAL_CATCH_TYPE_GEN\ - template\ - struct TestNameClass{\ - void reg_tests(){\ - size_t index = 0;\ - using expander = size_t[];\ - (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName##_catch_sr, Catch::NameAndTags{ Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \ - }\ - };\ - static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ - using TestInit = typename convert::type;\ - TestInit t;\ - t.reg_tests();\ - return 0;\ - }(); \ - }}\ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ - template \ - void TestName::test() +#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, TmplList) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \ + template \ + struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ + void test(); \ + }; \ + namespace \ + { \ + namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) \ + { \ + INTERNAL_CATCH_TYPE_GEN \ + template \ + struct TestNameClass { \ + void reg_tests() \ + { \ + size_t index = 0; \ + using expander = size_t[]; \ + (void)expander{(Catch::AutoReg(Catch::makeTestInvoker(&TestName::test), CATCH_INTERNAL_LINEINFO, #ClassName##_catch_sr, Catch::NameAndTags{Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags}), index++)...}; /* NOLINT */ \ + } \ + }; \ + static int INTERNAL_CATCH_UNIQUE_NAME(globalRegistrar) = []() { \ + using TestInit = typename convert::type; \ + TestInit t; \ + t.reg_tests(); \ + return 0; \ + }(); \ + } \ + } \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ + template \ + void TestName::test() #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \ INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, TmplList ) @@ -7263,10 +7287,11 @@ namespace Catch { #include namespace Catch { - namespace Detail { - void registerTranslatorImpl( - Detail::unique_ptr&& translator ); - } +namespace Detail +{ +void registerTranslatorImpl( + Detail::unique_ptr&& translator); +} class ExceptionTranslatorRegistrar { template @@ -7300,9 +7325,9 @@ namespace Catch { public: template ExceptionTranslatorRegistrar( std::string(*translateFunction)( T const& ) ) { - Detail::registerTranslatorImpl( - Detail::make_unique>( - translateFunction ) ); + Detail::registerTranslatorImpl( + Detail::make_unique>( + translateFunction)); } }; @@ -7727,21 +7752,21 @@ namespace Detail { } // namespace Generators } // namespace Catch -#define CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL( ... ) #__VA_ARGS__##_catch_sr +#define CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL(...) #__VA_ARGS__##_catch_sr #define CATCH_INTERNAL_GENERATOR_STRINGIZE(...) CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL(__VA_ARGS__) -#define GENERATE( ... ) \ - Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ - CATCH_INTERNAL_LINEINFO, \ - [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) -#define GENERATE_COPY( ... ) \ - Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ - CATCH_INTERNAL_LINEINFO, \ - [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) -#define GENERATE_REF( ... ) \ - Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ - CATCH_INTERNAL_LINEINFO, \ - [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace) +#define GENERATE(...) \ + Catch::Generators::generate(CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ + CATCH_INTERNAL_LINEINFO, \ + [] { using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); }) // NOLINT(google-build-using-namespace) +#define GENERATE_COPY(...) \ + Catch::Generators::generate(CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ + CATCH_INTERNAL_LINEINFO, \ + [=] { using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); }) // NOLINT(google-build-using-namespace) +#define GENERATE_REF(...) \ + Catch::Generators::generate(CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \ + CATCH_INTERNAL_LINEINFO, \ + [&] { using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); }) // NOLINT(google-build-using-namespace) #endif // CATCH_GENERATORS_HPP_INCLUDED @@ -8223,12 +8248,10 @@ GeneratorWrapper from_range(Container const& cnt) { } // namespace Generators } // namespace Catch - #endif // CATCH_GENERATORS_RANGE_HPP_INCLUDED #endif // CATCH_GENERATORS_ALL_HPP_INCLUDED - /** \file * This is a convenience header for Catch2's interfaces. It includes * **all** of Catch2 headers related to interfaces. @@ -8242,27 +8265,22 @@ GeneratorWrapper from_range(Container const& cnt) { * the corresponding internal subfolder, it should be added here. */ - #ifndef CATCH_INTERFACES_ALL_HPP_INCLUDED #define CATCH_INTERFACES_ALL_HPP_INCLUDED - - #ifndef CATCH_INTERFACES_REPORTER_HPP_INCLUDED #define CATCH_INTERFACES_REPORTER_HPP_INCLUDED - - #ifndef CATCH_TEST_RUN_INFO_HPP_INCLUDED #define CATCH_TEST_RUN_INFO_HPP_INCLUDED +namespace Catch +{ -namespace Catch { - - struct TestRunInfo { - constexpr TestRunInfo(StringRef _name) : name(_name) {} - StringRef name; - }; +struct TestRunInfo { + constexpr TestRunInfo(StringRef _name) : name(_name) {} + StringRef name; +}; } // end namespace Catch @@ -8273,207 +8291,209 @@ namespace Catch { #include #include -namespace Catch { - - struct ReporterDescription; - struct ListenerDescription; - struct TagInfo; - struct TestCaseInfo; - class TestCaseHandle; - class IConfig; - class IStream; - enum class ColourMode : std::uint8_t; - - struct ReporterConfig { - ReporterConfig( IConfig const* _fullConfig, - Detail::unique_ptr _stream, - ColourMode colourMode, - std::map customOptions ); - - ReporterConfig( ReporterConfig&& ) = default; - ReporterConfig& operator=( ReporterConfig&& ) = default; - ~ReporterConfig(); // = default - - Detail::unique_ptr takeStream() &&; - IConfig const* fullConfig() const; - ColourMode colourMode() const; - std::map const& customOptions() const; - - private: - Detail::unique_ptr m_stream; - IConfig const* m_fullConfig; - ColourMode m_colourMode; - std::map m_customOptions; - }; - - struct AssertionStats { - AssertionStats( AssertionResult const& _assertionResult, - std::vector const& _infoMessages, - Totals const& _totals ); - - AssertionStats( AssertionStats const& ) = default; - AssertionStats( AssertionStats && ) = default; - AssertionStats& operator = ( AssertionStats const& ) = delete; - AssertionStats& operator = ( AssertionStats && ) = delete; - - AssertionResult assertionResult; - std::vector infoMessages; - Totals totals; - }; - - struct SectionStats { - SectionStats( SectionInfo&& _sectionInfo, - Counts const& _assertions, - double _durationInSeconds, - bool _missingAssertions ); - - SectionInfo sectionInfo; - Counts assertions; - double durationInSeconds; - bool missingAssertions; - }; - - struct TestCaseStats { - TestCaseStats( TestCaseInfo const& _testInfo, - Totals const& _totals, - std::string&& _stdOut, - std::string&& _stdErr, - bool _aborting ); - - TestCaseInfo const * testInfo; - Totals totals; - std::string stdOut; - std::string stdErr; - bool aborting; - }; - - struct TestRunStats { - TestRunStats( TestRunInfo const& _runInfo, - Totals const& _totals, - bool _aborting ); - - TestRunInfo runInfo; - Totals totals; - bool aborting; - }; +namespace Catch +{ - //! By setting up its preferences, a reporter can modify Catch2's behaviour - //! in some regards, e.g. it can request Catch2 to capture writes to - //! stdout/stderr during test execution, and pass them to the reporter. - struct ReporterPreferences { - //! Catch2 should redirect writes to stdout and pass them to the - //! reporter - bool shouldRedirectStdOut = false; - //! Catch2 should call `Reporter::assertionEnded` even for passing - //! assertions - bool shouldReportAllAssertions = false; - }; +struct ReporterDescription; +struct ListenerDescription; +struct TagInfo; +struct TestCaseInfo; +class TestCaseHandle; +class IConfig; +class IStream; +enum class ColourMode : std::uint8_t; + +struct ReporterConfig { + ReporterConfig(IConfig const* _fullConfig, + Detail::unique_ptr _stream, + ColourMode colourMode, + std::map customOptions); + + ReporterConfig(ReporterConfig&&) = default; + ReporterConfig& operator=(ReporterConfig&&) = default; + ~ReporterConfig(); // = default + + Detail::unique_ptr takeStream() &&; + IConfig const* fullConfig() const; + ColourMode colourMode() const; + std::map const& customOptions() const; + + private: + Detail::unique_ptr m_stream; + IConfig const* m_fullConfig; + ColourMode m_colourMode; + std::map m_customOptions; +}; - /** - * The common base for all reporters and event listeners - * - * Implementing classes must also implement: - * - * //! User-friendly description of the reporter/listener type - * static std::string getDescription() - * - * Generally shouldn't be derived from by users of Catch2 directly, - * instead they should derive from one of the utility bases that - * derive from this class. - */ - class IEventListener { - protected: - //! Derived classes can set up their preferences here - ReporterPreferences m_preferences; - //! The test run's config as filled in from CLI and defaults - IConfig const* m_config; +struct AssertionStats { + AssertionStats(AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals); - public: - IEventListener( IConfig const* config ): m_config( config ) {} + AssertionStats(AssertionStats const&) = default; + AssertionStats(AssertionStats&&) = default; + AssertionStats& operator=(AssertionStats const&) = delete; + AssertionStats& operator=(AssertionStats&&) = delete; - virtual ~IEventListener(); // = default; + AssertionResult assertionResult; + std::vector infoMessages; + Totals totals; +}; - // Implementing class must also provide the following static methods: - // static std::string getDescription(); +struct SectionStats { + SectionStats(SectionInfo&& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions); - ReporterPreferences const& getPreferences() const { - return m_preferences; - } + SectionInfo sectionInfo; + Counts assertions; + double durationInSeconds; + bool missingAssertions; +}; - //! Called when no test cases match provided test spec - virtual void noMatchingTestCases( StringRef unmatchedSpec ) = 0; - //! Called for all invalid test specs from the cli - virtual void reportInvalidTestSpec( StringRef invalidArgument ) = 0; +struct TestCaseStats { + TestCaseStats(TestCaseInfo const& _testInfo, + Totals const& _totals, + std::string&& _stdOut, + std::string&& _stdErr, + bool _aborting); + + TestCaseInfo const* testInfo; + Totals totals; + std::string stdOut; + std::string stdErr; + bool aborting; +}; - /** - * Called once in a testing run before tests are started - * - * Not called if tests won't be run (e.g. only listing will happen) - */ - virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; - - //! Called _once_ for each TEST_CASE, no matter how many times it is entered - virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; - //! Called _every time_ a TEST_CASE is entered, including repeats (due to sections) - virtual void testCasePartialStarting( TestCaseInfo const& testInfo, uint64_t partNumber ) = 0; - //! Called when a `SECTION` is being entered. Not called for skipped sections - virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; - - //! Called when user-code is being probed before the actual benchmark runs - virtual void benchmarkPreparing( StringRef benchmarkName ) = 0; - //! Called after probe but before the user-code is being benchmarked - virtual void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) = 0; - //! Called with the benchmark results if benchmark successfully finishes - virtual void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) = 0; - //! Called if running the benchmarks fails for any reason - virtual void benchmarkFailed( StringRef benchmarkName ) = 0; - - //! Called before assertion success/failure is evaluated - virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; - - //! Called after assertion was fully evaluated - virtual void assertionEnded( AssertionStats const& assertionStats ) = 0; - - //! Called after a `SECTION` has finished running - virtual void sectionEnded( SectionStats const& sectionStats ) = 0; - //! Called _every time_ a TEST_CASE is entered, including repeats (due to sections) - virtual void testCasePartialEnded(TestCaseStats const& testCaseStats, uint64_t partNumber ) = 0; - //! Called _once_ for each TEST_CASE, no matter how many times it is entered - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; - /** - * Called once after all tests in a testing run are finished - * - * Not called if tests weren't run (e.g. only listings happened) - */ - virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; +struct TestRunStats { + TestRunStats(TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting); - /** - * Called with test cases that are skipped due to the test run aborting. - * NOT called for test cases that are explicitly skipped using the `SKIP` macro. - * - * Deprecated - will be removed in the next major release. - */ - virtual void skipTest( TestCaseInfo const& testInfo ) = 0; + TestRunInfo runInfo; + Totals totals; + bool aborting; +}; - //! Called if a fatal error (signal/structured exception) occurred - virtual void fatalErrorEncountered( StringRef error ) = 0; +//! By setting up its preferences, a reporter can modify Catch2's behaviour +//! in some regards, e.g. it can request Catch2 to capture writes to +//! stdout/stderr during test execution, and pass them to the reporter. +struct ReporterPreferences { + //! Catch2 should redirect writes to stdout and pass them to the + //! reporter + bool shouldRedirectStdOut = false; + //! Catch2 should call `Reporter::assertionEnded` even for passing + //! assertions + bool shouldReportAllAssertions = false; +}; - //! Writes out information about provided reporters using reporter-specific format - virtual void listReporters(std::vector const& descriptions) = 0; - //! Writes out the provided listeners descriptions using reporter-specific format - virtual void listListeners(std::vector const& descriptions) = 0; - //! Writes out information about provided tests using reporter-specific format - virtual void listTests(std::vector const& tests) = 0; - //! Writes out information about the provided tags using reporter-specific format - virtual void listTags(std::vector const& tags) = 0; - }; - using IEventListenerPtr = Detail::unique_ptr; +/** + * The common base for all reporters and event listeners + * + * Implementing classes must also implement: + * + * //! User-friendly description of the reporter/listener type + * static std::string getDescription() + * + * Generally shouldn't be derived from by users of Catch2 directly, + * instead they should derive from one of the utility bases that + * derive from this class. + */ +class IEventListener +{ + protected: + //! Derived classes can set up their preferences here + ReporterPreferences m_preferences; + //! The test run's config as filled in from CLI and defaults + IConfig const* m_config; + + public: + IEventListener(IConfig const* config) : m_config(config) {} + + virtual ~IEventListener(); // = default; + + // Implementing class must also provide the following static methods: + // static std::string getDescription(); + + ReporterPreferences const& getPreferences() const + { + return m_preferences; + } + + //! Called when no test cases match provided test spec + virtual void noMatchingTestCases(StringRef unmatchedSpec) = 0; + //! Called for all invalid test specs from the cli + virtual void reportInvalidTestSpec(StringRef invalidArgument) = 0; + + /** + * Called once in a testing run before tests are started + * + * Not called if tests won't be run (e.g. only listing will happen) + */ + virtual void testRunStarting(TestRunInfo const& testRunInfo) = 0; + + //! Called _once_ for each TEST_CASE, no matter how many times it is entered + virtual void testCaseStarting(TestCaseInfo const& testInfo) = 0; + //! Called _every time_ a TEST_CASE is entered, including repeats (due to sections) + virtual void testCasePartialStarting(TestCaseInfo const& testInfo, uint64_t partNumber) = 0; + //! Called when a `SECTION` is being entered. Not called for skipped sections + virtual void sectionStarting(SectionInfo const& sectionInfo) = 0; + + //! Called when user-code is being probed before the actual benchmark runs + virtual void benchmarkPreparing(StringRef benchmarkName) = 0; + //! Called after probe but before the user-code is being benchmarked + virtual void benchmarkStarting(BenchmarkInfo const& benchmarkInfo) = 0; + //! Called with the benchmark results if benchmark successfully finishes + virtual void benchmarkEnded(BenchmarkStats<> const& benchmarkStats) = 0; + //! Called if running the benchmarks fails for any reason + virtual void benchmarkFailed(StringRef benchmarkName) = 0; + + //! Called before assertion success/failure is evaluated + virtual void assertionStarting(AssertionInfo const& assertionInfo) = 0; + + //! Called after assertion was fully evaluated + virtual void assertionEnded(AssertionStats const& assertionStats) = 0; + + //! Called after a `SECTION` has finished running + virtual void sectionEnded(SectionStats const& sectionStats) = 0; + //! Called _every time_ a TEST_CASE is entered, including repeats (due to sections) + virtual void testCasePartialEnded(TestCaseStats const& testCaseStats, uint64_t partNumber) = 0; + //! Called _once_ for each TEST_CASE, no matter how many times it is entered + virtual void testCaseEnded(TestCaseStats const& testCaseStats) = 0; + /** + * Called once after all tests in a testing run are finished + * + * Not called if tests weren't run (e.g. only listings happened) + */ + virtual void testRunEnded(TestRunStats const& testRunStats) = 0; + + /** + * Called with test cases that are skipped due to the test run aborting. + * NOT called for test cases that are explicitly skipped using the `SKIP` macro. + * + * Deprecated - will be removed in the next major release. + */ + virtual void skipTest(TestCaseInfo const& testInfo) = 0; + + //! Called if a fatal error (signal/structured exception) occurred + virtual void fatalErrorEncountered(StringRef error) = 0; + + //! Writes out information about provided reporters using reporter-specific format + virtual void listReporters(std::vector const& descriptions) = 0; + //! Writes out the provided listeners descriptions using reporter-specific format + virtual void listListeners(std::vector const& descriptions) = 0; + //! Writes out information about provided tests using reporter-specific format + virtual void listTests(std::vector const& tests) = 0; + //! Writes out information about the provided tags using reporter-specific format + virtual void listTags(std::vector const& tags) = 0; +}; +using IEventListenerPtr = Detail::unique_ptr; } // end namespace Catch #endif // CATCH_INTERFACES_REPORTER_HPP_INCLUDED - #ifndef CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED #define CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED @@ -8511,31 +8531,31 @@ namespace Catch { #endif // CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED - #ifndef CATCH_INTERFACES_TAG_ALIAS_REGISTRY_HPP_INCLUDED #define CATCH_INTERFACES_TAG_ALIAS_REGISTRY_HPP_INCLUDED #include -namespace Catch { +namespace Catch +{ - struct TagAlias; +struct TagAlias; - class ITagAliasRegistry { - public: - virtual ~ITagAliasRegistry(); // = default - // Nullptr if not present - virtual TagAlias const* find( std::string const& alias ) const = 0; - virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; +class ITagAliasRegistry +{ + public: + virtual ~ITagAliasRegistry(); // = default + // 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(); - }; + static ITagAliasRegistry const& get(); +}; } // end namespace Catch #endif // CATCH_INTERFACES_TAG_ALIAS_REGISTRY_HPP_INCLUDED - #ifndef CATCH_INTERFACES_TESTCASE_HPP_INCLUDED #define CATCH_INTERFACES_TESTCASE_HPP_INCLUDED @@ -8543,51 +8563,50 @@ namespace Catch { namespace Catch { - struct TestCaseInfo; - class TestCaseHandle; - class IConfig; +struct TestCaseInfo; +class TestCaseHandle; +class IConfig; - class ITestCaseRegistry { - public: - virtual ~ITestCaseRegistry(); // = default - // TODO: this exists only for adding filenames to test cases -- let's expose this in a saner way later - virtual std::vector const& getAllInfos() const = 0; - virtual std::vector const& getAllTests() const = 0; - virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; - }; +class ITestCaseRegistry +{ + public: + virtual ~ITestCaseRegistry(); // = default + // TODO: this exists only for adding filenames to test cases -- let's expose this in a saner way later + virtual std::vector const& getAllInfos() const = 0; + virtual std::vector const& getAllTests() const = 0; + virtual std::vector const& getAllTestsSorted(IConfig const& config) const = 0; +}; -} +} // namespace Catch #endif // CATCH_INTERFACES_TESTCASE_HPP_INCLUDED #endif // CATCH_INTERFACES_ALL_HPP_INCLUDED - #ifndef CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED #define CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED +namespace Catch +{ +namespace Detail +{ +//! Provides case-insensitive `op<` semantics when called +struct CaseInsensitiveLess { + bool operator()(StringRef lhs, + StringRef rhs) const; +}; -namespace Catch { - namespace Detail { - //! Provides case-insensitive `op<` semantics when called - struct CaseInsensitiveLess { - bool operator()( StringRef lhs, - StringRef rhs ) const; - }; - - //! Provides case-insensitive `op==` semantics when called - struct CaseInsensitiveEqualTo { - bool operator()( StringRef lhs, - StringRef rhs ) const; - }; +//! Provides case-insensitive `op==` semantics when called +struct CaseInsensitiveEqualTo { + bool operator()(StringRef lhs, + StringRef rhs) const; +}; - } // namespace Detail +} // namespace Detail } // namespace Catch #endif // CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED - - /** \file * Wrapper for ANDROID_LOGWRITE configuration option * @@ -8626,7 +8645,6 @@ namespace Catch { #ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED #define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED - #if defined(_MSC_VER) # if _MSC_VER >= 1900 // Visual Studio 2015 or newer # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS @@ -8918,7 +8936,7 @@ namespace Catch { void registerTranslator( Detail::unique_ptr&& translator ); std::string translateActiveException() const override; - private: + private: ExceptionTranslators m_translators; }; } @@ -9110,140 +9128,154 @@ namespace Detail { #endif // CATCH_GETENV_HPP_INCLUDED - #ifndef CATCH_IS_PERMUTATION_HPP_INCLUDED #define CATCH_IS_PERMUTATION_HPP_INCLUDED #include #include -namespace Catch { - namespace Detail { +namespace Catch +{ +namespace Detail +{ - template - ForwardIter find_sentinel( ForwardIter start, - Sentinel sentinel, - T const& value, - Comparator cmp ) { - while ( start != sentinel ) { - if ( cmp( *start, value ) ) { break; } - ++start; - } - return start; - } - - template - std::ptrdiff_t count_sentinel( ForwardIter start, - Sentinel sentinel, - T const& value, - Comparator cmp ) { - std::ptrdiff_t count = 0; - while ( start != sentinel ) { - if ( cmp( *start, value ) ) { ++count; } - ++start; - } - return count; - } +template +ForwardIter find_sentinel(ForwardIter start, + Sentinel sentinel, + T const& value, + Comparator cmp) +{ + while (start != sentinel) { + if (cmp(*start, value)) { + break; + } + ++start; + } + return start; +} - template - std::enable_if_t::value, - std::ptrdiff_t> - sentinel_distance( ForwardIter iter, const Sentinel sentinel ) { - std::ptrdiff_t dist = 0; - while ( iter != sentinel ) { - ++iter; - ++dist; - } - return dist; - } - - template - std::ptrdiff_t sentinel_distance( ForwardIter first, - ForwardIter last ) { - return std::distance( first, last ); - } - - template - bool check_element_counts( ForwardIter1 first_1, - const Sentinel1 end_1, - ForwardIter2 first_2, - const Sentinel2 end_2, - Comparator cmp ) { - auto cursor = first_1; - while ( cursor != end_1 ) { - if ( find_sentinel( first_1, cursor, *cursor, cmp ) == - cursor ) { - // we haven't checked this element yet - const auto count_in_range_2 = - count_sentinel( first_2, end_2, *cursor, cmp ); - // Not a single instance in 2nd range, so it cannot be a - // permutation of 1st range - if ( count_in_range_2 == 0 ) { return false; } - - const auto count_in_range_1 = - count_sentinel( cursor, end_1, *cursor, cmp ); - if ( count_in_range_1 != count_in_range_2 ) { - return false; - } - } +template +std::ptrdiff_t count_sentinel(ForwardIter start, + Sentinel sentinel, + T const& value, + Comparator cmp) +{ + std::ptrdiff_t count = 0; + while (start != sentinel) { + if (cmp(*start, value)) { + ++count; + } + ++start; + } + return count; +} - ++cursor; - } +template +std::enable_if_t::value, + std::ptrdiff_t> + sentinel_distance(ForwardIter iter, const Sentinel sentinel) +{ + std::ptrdiff_t dist = 0; + while (iter != sentinel) { + ++iter; + ++dist; + } + return dist; +} - return true; - } +template +std::ptrdiff_t sentinel_distance(ForwardIter first, + ForwardIter last) +{ + return std::distance(first, last); +} - template - bool is_permutation( ForwardIter1 first_1, - const Sentinel1 end_1, - ForwardIter2 first_2, - const Sentinel2 end_2, - Comparator cmp ) { - // TODO: no optimization for stronger iterators, because we would also have to constrain on sentinel vs not sentinel types - // TODO: Comparator has to be "both sides", e.g. a == b => b == a - // This skips shared prefix of the two ranges - while (first_1 != end_1 && first_2 != end_2 && cmp(*first_1, *first_2)) { - ++first_1; - ++first_2; - } +template +bool check_element_counts(ForwardIter1 first_1, + const Sentinel1 end_1, + ForwardIter2 first_2, + const Sentinel2 end_2, + Comparator cmp) +{ + auto cursor = first_1; + while (cursor != end_1) { + if (find_sentinel(first_1, cursor, *cursor, cmp) == + cursor) { + // we haven't checked this element yet + const auto count_in_range_2 = + count_sentinel(first_2, end_2, *cursor, cmp); + // Not a single instance in 2nd range, so it cannot be a + // permutation of 1st range + if (count_in_range_2 == 0) { + return false; + } - // We need to handle case where at least one of the ranges has no more elements - if (first_1 == end_1 || first_2 == end_2) { - return first_1 == end_1 && first_2 == end_2; - } + const auto count_in_range_1 = + count_sentinel(cursor, end_1, *cursor, cmp); + if (count_in_range_1 != count_in_range_2) { + return false; + } + } - // pair counting is n**2, so we pay linear walk to compare the sizes first - auto dist_1 = sentinel_distance( first_1, end_1 ); - auto dist_2 = sentinel_distance( first_2, end_2 ); + ++cursor; + } - if (dist_1 != dist_2) { return false; } + return true; +} - // Since we do not try to handle stronger iterators pair (e.g. - // bidir) optimally, the only thing left to do is to check counts in - // the remaining ranges. - return check_element_counts( first_1, end_1, first_2, end_2, cmp ); - } +template +bool is_permutation(ForwardIter1 first_1, + const Sentinel1 end_1, + ForwardIter2 first_2, + const Sentinel2 end_2, + Comparator cmp) +{ + // TODO: no optimization for stronger iterators, because we would also have to constrain on sentinel vs not sentinel types + // TODO: Comparator has to be "both sides", e.g. a == b => b == a + // This skips shared prefix of the two ranges + while (first_1 != end_1 && first_2 != end_2 && cmp(*first_1, *first_2)) { + ++first_1; + ++first_2; + } + + // We need to handle case where at least one of the ranges has no more elements + if (first_1 == end_1 || first_2 == end_2) { + return first_1 == end_1 && first_2 == end_2; + } + + // pair counting is n**2, so we pay linear walk to compare the sizes first + auto dist_1 = sentinel_distance(first_1, end_1); + auto dist_2 = sentinel_distance(first_2, end_2); + + if (dist_1 != dist_2) { + return false; + } + + // Since we do not try to handle stronger iterators pair (e.g. + // bidir) optimally, the only thing left to do is to check counts in + // the remaining ranges. + return check_element_counts(first_1, end_1, first_2, end_2, cmp); +} - } // namespace Detail +} // namespace Detail } // namespace Catch #endif // CATCH_IS_PERMUTATION_HPP_INCLUDED - #ifndef CATCH_ISTREAM_HPP_INCLUDED #define CATCH_ISTREAM_HPP_INCLUDED @@ -9482,38 +9514,39 @@ namespace Catch { namespace Catch { - class IEventListener; - using IEventListenerPtr = Detail::unique_ptr; - class IReporterFactory; - using IReporterFactoryPtr = Detail::unique_ptr; - struct ReporterConfig; - class EventListenerFactory; +class IEventListener; +using IEventListenerPtr = Detail::unique_ptr; +class IReporterFactory; +using IReporterFactoryPtr = Detail::unique_ptr; +struct ReporterConfig; +class EventListenerFactory; - class ReporterRegistry { - struct ReporterRegistryImpl; - Detail::unique_ptr m_impl; +class ReporterRegistry +{ + struct ReporterRegistryImpl; + Detail::unique_ptr m_impl; - public: - ReporterRegistry(); - ~ReporterRegistry(); // = default; + public: + ReporterRegistry(); + ~ReporterRegistry(); // = default; - IEventListenerPtr create( std::string const& name, - ReporterConfig&& config ) const; + IEventListenerPtr create(std::string const& name, + ReporterConfig&& config) const; - void registerReporter( std::string const& name, - IReporterFactoryPtr factory ); + void registerReporter(std::string const& name, + IReporterFactoryPtr factory); - void - registerListener( Detail::unique_ptr factory ); + void + registerListener(Detail::unique_ptr factory); - std::map const& - getFactories() const; + std::map const& + getFactories() const; - std::vector> const& - getListeners() const; - }; + std::vector> const& + getListeners() const; +}; } // end namespace Catch @@ -9541,12 +9574,14 @@ namespace TestCaseTracking { NameAndLocation( std::string&& _name, SourceLineInfo const& _location ); friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) { - // This is a very cheap check that should have a very high hit rate. - // If we get to SourceLineInfo::operator==, we will redo it, but the - // cost of repeating is trivial at that point (we will be paying - // multiple strcmp/memcmps at that point). - if ( lhs.location.line != rhs.location.line ) { return false; } - return lhs.name == rhs.name && lhs.location == rhs.location; + // This is a very cheap check that should have a very high hit rate. + // If we get to SourceLineInfo::operator==, we will redo it, but the + // cost of repeating is trivial at that point (we will be paying + // multiple strcmp/memcmps at that point). + if (lhs.location.line != rhs.location.line) { + return false; + } + return lhs.name == rhs.name && lhs.location == rhs.location; } friend bool operator!=(NameAndLocation const& lhs, NameAndLocation const& rhs) { @@ -9569,19 +9604,23 @@ namespace TestCaseTracking { SourceLineInfo location_ ): name( name_ ), location( location_ ) {} - friend bool operator==( NameAndLocation const& lhs, - NameAndLocationRef const& rhs ) { - // This is a very cheap check that should have a very high hit rate. - // If we get to SourceLineInfo::operator==, we will redo it, but the - // cost of repeating is trivial at that point (we will be paying - // multiple strcmp/memcmps at that point). - if ( lhs.location.line != rhs.location.line ) { return false; } - return StringRef( lhs.name ) == rhs.name && - lhs.location == rhs.location; + friend bool operator==(NameAndLocation const& lhs, + NameAndLocationRef const& rhs) + { + // This is a very cheap check that should have a very high hit rate. + // If we get to SourceLineInfo::operator==, we will redo it, but the + // cost of repeating is trivial at that point (we will be paying + // multiple strcmp/memcmps at that point). + if (lhs.location.line != rhs.location.line) { + return false; + } + return StringRef(lhs.name) == rhs.name && + lhs.location == rhs.location; } - friend bool operator==( NameAndLocationRef const& lhs, - NameAndLocation const& rhs ) { - return rhs == lhs; + friend bool operator==(NameAndLocationRef const& lhs, + NameAndLocation const& rhs) + { + return rhs == lhs; } }; @@ -9631,8 +9670,9 @@ namespace TestCaseTracking { //! Returns true if tracker run to completion (successfully or not) virtual bool isComplete() const = 0; //! Returns true if tracker run to completion successfully - bool isSuccessfullyCompleted() const { - return m_runState == CompletedSuccessfully; + bool isSuccessfullyCompleted() const + { + return m_runState == CompletedSuccessfully; } //! Returns true if tracker has started but hasn't been completed bool isOpen() const; @@ -9651,7 +9691,7 @@ namespace TestCaseTracking { * * Returns nullptr if not found. */ - ITracker* findChild( NameAndLocationRef const& nameAndLocation ); + ITracker* findChild(NameAndLocationRef const& nameAndLocation); //! Have any children been added? bool hasChildren() const { return !m_children.empty(); @@ -9690,13 +9730,13 @@ namespace TestCaseTracking { RunState m_runState = NotStarted; public: + ITracker& startRun(); - ITracker& startRun(); - - void startCycle() { - m_currentTracker = m_rootTracker.get(); - m_runState = Executing; - } + void startCycle() + { + m_currentTracker = m_rootTracker.get(); + m_runState = Executing; + } void completeCycle(); bool completedCycle() const; @@ -9731,14 +9771,15 @@ namespace TestCaseTracking { // to not own the name, the name still has to outlive the `ITracker` parent, so // this should still be safe. StringRef m_trimmed_name; - public: + + public: SectionTracker( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent ); bool isSectionTracker() const override; bool isComplete() const override; - static SectionTracker& acquire( TrackerContext& ctx, NameAndLocationRef const& nameAndLocation ); + static SectionTracker& acquire(TrackerContext& ctx, NameAndLocationRef const& nameAndLocation); void tryOpen(); @@ -9771,126 +9812,116 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////// - class RunContext final : public IResultCapture { - - public: - RunContext( RunContext const& ) = delete; - RunContext& operator =( RunContext const& ) = delete; - - explicit RunContext( IConfig const* _config, IEventListenerPtr&& reporter ); - - ~RunContext() override; - - Totals runTest(TestCaseHandle const& testCase); - - public: // IResultCapture - - // Assertion handlers - void handleExpr - ( AssertionInfo const& info, - ITransientExpression const& expr, - AssertionReaction& reaction ) override; - void handleMessage - ( AssertionInfo const& info, - ResultWas::OfType resultType, - StringRef message, - AssertionReaction& reaction ) override; - void handleUnexpectedExceptionNotThrown - ( AssertionInfo const& info, - AssertionReaction& reaction ) override; - void handleUnexpectedInflightException - ( AssertionInfo const& info, - std::string&& message, - AssertionReaction& reaction ) override; - void handleIncomplete - ( AssertionInfo const& info ) override; - void handleNonExpr - ( AssertionInfo const &info, - ResultWas::OfType resultType, - AssertionReaction &reaction ) override; - - void notifyAssertionStarted( AssertionInfo const& info ) override; - bool sectionStarted( StringRef sectionName, - SourceLineInfo const& sectionLineInfo, - Counts& assertions ) override; + class RunContext final : public IResultCapture + { - void sectionEnded( SectionEndInfo&& endInfo ) override; - void sectionEndedEarly( SectionEndInfo&& endInfo ) override; + public: + RunContext(RunContext const&) = delete; + RunContext& operator=(RunContext const&) = delete; + + explicit RunContext(IConfig const* _config, IEventListenerPtr&& reporter); + + ~RunContext() override; + + Totals runTest(TestCaseHandle const& testCase); - IGeneratorTracker* - acquireGeneratorTracker( StringRef generatorName, - SourceLineInfo const& lineInfo ) override; - IGeneratorTracker* createGeneratorTracker( - StringRef generatorName, - SourceLineInfo lineInfo, - Generators::GeneratorBasePtr&& generator ) override; + public: // IResultCapture + // Assertion handlers + void handleExpr(AssertionInfo const& info, + ITransientExpression const& expr, + AssertionReaction& reaction) override; + void handleMessage(AssertionInfo const& info, + ResultWas::OfType resultType, + StringRef message, + AssertionReaction& reaction) override; + void handleUnexpectedExceptionNotThrown(AssertionInfo const& info, + AssertionReaction& reaction) override; + void handleUnexpectedInflightException(AssertionInfo const& info, + std::string&& message, + AssertionReaction& reaction) override; + void handleIncomplete(AssertionInfo const& info) override; + void handleNonExpr(AssertionInfo const& info, + ResultWas::OfType resultType, + AssertionReaction& reaction) override; + void notifyAssertionStarted(AssertionInfo const& info) override; + bool sectionStarted(StringRef sectionName, + SourceLineInfo const& sectionLineInfo, + Counts& assertions) override; - void benchmarkPreparing( StringRef name ) override; - void benchmarkStarting( BenchmarkInfo const& info ) override; - void benchmarkEnded( BenchmarkStats<> const& stats ) override; - void benchmarkFailed( StringRef error ) override; + void sectionEnded(SectionEndInfo&& endInfo) override; + void sectionEndedEarly(SectionEndInfo&& endInfo) override; - void pushScopedMessage( MessageInfo const& message ) override; - void popScopedMessage( MessageInfo const& message ) override; + IGeneratorTracker* + acquireGeneratorTracker(StringRef generatorName, + SourceLineInfo const& lineInfo) override; + IGeneratorTracker* createGeneratorTracker( + StringRef generatorName, + SourceLineInfo lineInfo, + Generators::GeneratorBasePtr&& generator) override; - void emplaceUnscopedMessage( MessageBuilder&& builder ) override; + void benchmarkPreparing(StringRef name) override; + void benchmarkStarting(BenchmarkInfo const& info) override; + void benchmarkEnded(BenchmarkStats<> const& stats) override; + void benchmarkFailed(StringRef error) override; - std::string getCurrentTestName() const override; + void pushScopedMessage(MessageInfo const& message) override; + void popScopedMessage(MessageInfo const& message) override; - const AssertionResult* getLastResult() const override; + void emplaceUnscopedMessage(MessageBuilder&& builder) override; - void exceptionEarlyReported() override; + std::string getCurrentTestName() const override; - void handleFatalErrorCondition( StringRef message ) override; + const AssertionResult* getLastResult() const override; - bool lastAssertionPassed() override; + void exceptionEarlyReported() override; - void assertionPassed() override; + void handleFatalErrorCondition(StringRef message) override; - public: - // !TBD We need to do this another way! - bool aborting() const; + bool lastAssertionPassed() override; - private: + void assertionPassed() override; - void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ); - void invokeActiveTestCase(); + public: + // !TBD We need to do this another way! + bool aborting() const; - void resetAssertionInfo(); - bool testForMissingAssertions( Counts& assertions ); + private: + void runCurrentTest(std::string& redirectedCout, std::string& redirectedCerr); + void invokeActiveTestCase(); - void assertionEnded( AssertionResult&& result ); - void reportExpr - ( AssertionInfo const &info, - ResultWas::OfType resultType, - ITransientExpression const *expr, - bool negated ); + void resetAssertionInfo(); + bool testForMissingAssertions(Counts& assertions); - void populateReaction( AssertionReaction& reaction ); + void assertionEnded(AssertionResult&& result); + void reportExpr(AssertionInfo const& info, + ResultWas::OfType resultType, + ITransientExpression const* expr, + bool negated); - private: + void populateReaction(AssertionReaction& reaction); - void handleUnfinishedSections(); + private: + void handleUnfinishedSections(); - TestRunInfo m_runInfo; - TestCaseHandle const* m_activeTestCase = nullptr; - ITracker* m_testCaseTracker = nullptr; - Optional m_lastResult; + TestRunInfo m_runInfo; + TestCaseHandle const* m_activeTestCase = nullptr; + ITracker* m_testCaseTracker = nullptr; + Optional m_lastResult; - IConfig const* m_config; - Totals m_totals; - IEventListenerPtr m_reporter; - std::vector m_messages; - std::vector m_messageScopes; /* Keeps owners of so-called unscoped messages. */ - AssertionInfo m_lastAssertionInfo; - std::vector m_unfinishedSections; - std::vector m_activeSections; - TrackerContext m_trackerContext; - FatalConditionHandler m_fatalConditionhandler; - bool m_lastAssertionPassed = false; - bool m_shouldReportUnexpected = true; - bool m_includeSuccessfulResults; + IConfig const* m_config; + Totals m_totals; + IEventListenerPtr m_reporter; + std::vector m_messages; + std::vector m_messageScopes; /* Keeps owners of so-called unscoped messages. */ + AssertionInfo m_lastAssertionInfo; + std::vector m_unfinishedSections; + std::vector m_activeSections; + TrackerContext m_trackerContext; + FatalConditionHandler m_fatalConditionhandler; + bool m_lastAssertionPassed = false; + bool m_shouldReportUnexpected = true; + bool m_includeSuccessfulResults; }; void seedRng(IConfig const& config); @@ -10137,7 +10168,7 @@ namespace Catch { std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ); - bool isThrowSafe( TestCaseHandle const& testCase, IConfig const& config ); + bool isThrowSafe(TestCaseHandle const& testCase, IConfig const& config); std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); std::vector const& getAllTestCasesSorted( IConfig const& config ); @@ -10166,7 +10197,6 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////// - } // end namespace Catch @@ -10613,7 +10643,6 @@ namespace Catch { #ifndef CATCH_MATCHERS_IMPL_HPP_INCLUDED #define CATCH_MATCHERS_IMPL_HPP_INCLUDED - #include namespace Catch { @@ -11308,11 +11337,14 @@ namespace Catch { } template - bool match( RangeLike&& rng ) const { - for ( auto&& elem : rng ) { - if ( m_eq( elem, m_desired ) ) { return true; } + bool match(RangeLike&& rng) const + { + for (auto&& elem : rng) { + if (m_eq(elem, m_desired)) { + return true; } - return false; + } + return false; } }; @@ -11454,9 +11486,7 @@ namespace Matchers { }; //! Creates a matcher that accepts numbers within certain range of target - WithinAbsMatcher WithinAbs( double target, double margin ); - - + WithinAbsMatcher WithinAbs(double target, double margin); class WithinUlpsMatcher final : public MatcherBase { public: @@ -11476,8 +11506,6 @@ namespace Matchers { //! Creates a matcher that accepts floats within certain ULP range of target WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff); - - // Given IEEE-754 format for floats and doubles, we can assume // that float -> double promotion is lossless. Given this, we can // assume that if we do the standard relative comparison of @@ -11503,13 +11531,12 @@ namespace Matchers { //! Creates a matcher that accepts floats within 100*FLT_EPS relative range of target WithinRelMatcher WithinRel(float target); - - - class IsNaNMatcher final : public MatcherBase { - public: - IsNaNMatcher() = default; - bool match( double const& matchee ) const override; - std::string describe() const override; + class IsNaNMatcher final : public MatcherBase + { + public: + IsNaNMatcher() = default; + bool match(double const& matchee) const override; + std::string describe() const override; }; IsNaNMatcher IsNaN(); @@ -11732,7 +11759,6 @@ namespace Catch { #ifndef CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED #define CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED - #include #include @@ -11757,19 +11783,19 @@ namespace Catch { template bool match( RangeLike&& rng ) const { - auto rng_start = begin( rng ); - const auto rng_end = end( rng ); - auto target_start = begin( m_desired ); - const auto target_end = end( m_desired ); - - while (rng_start != rng_end && target_start != target_end) { - if (!m_predicate(*rng_start, *target_start)) { - return false; - } - ++rng_start; - ++target_start; + auto rng_start = begin(rng); + const auto rng_end = end(rng); + auto target_start = begin(m_desired); + const auto target_end = end(m_desired); + + while (rng_start != rng_end && target_start != target_end) { + if (!m_predicate(*rng_start, *target_start)) { + return false; } - return rng_start == rng_end && target_start == target_end; + ++rng_start; + ++target_start; + } + return rng_start == rng_end && target_start == target_end; } std::string describe() const override { @@ -11797,11 +11823,11 @@ namespace Catch { bool match( RangeLike&& rng ) const { using std::begin; using std::end; - return Catch::Detail::is_permutation( begin( m_desired ), - end( m_desired ), - begin( rng ), - end( rng ), - m_predicate ); + return Catch::Detail::is_permutation(begin(m_desired), + end(m_desired), + begin(rng), + end(rng), + m_predicate); } std::string describe() const override { @@ -12021,9 +12047,13 @@ namespace Matchers { // - a more general approach would be via a compare template that defaults // to using !=. but could be specialised for, e.g. std::vector 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; } + 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; } @@ -12528,15 +12558,15 @@ namespace Catch { void skipTest(TestCaseInfo const&) override {} protected: - //! Should the cumulative base store the assertion expansion for successful assertions? - bool m_shouldStoreSuccesfulAssertions = true; - //! Should the cumulative base store the assertion expansion for failed assertions? - bool m_shouldStoreFailedAssertions = true; + //! Should the cumulative base store the assertion expansion for successful assertions? + bool m_shouldStoreSuccesfulAssertions = true; + //! Should the cumulative base store the assertion expansion for failed assertions? + bool m_shouldStoreFailedAssertions = true; - // We need lazy construction here. We should probably refactor it - // later, after the events are redone. - //! The root node of the test run tree. - Detail::unique_ptr m_testRun; + // We need lazy construction here. We should probably refactor it + // later, after the events are redone. + //! The root node of the test run tree. + Detail::unique_ptr m_testRun; private: // Note: We rely on pointer identity being stable, which is why @@ -12836,7 +12866,7 @@ namespace Catch { void registerReporterImpl( std::string const& name, IReporterFactoryPtr reporterPtr ); //! Actually registers the factory, independent on listener's concrete type - void registerListenerImpl( Detail::unique_ptr listenerFactory ); + void registerListenerImpl(Detail::unique_ptr listenerFactory); } // namespace Detail class IEventListener; @@ -12897,7 +12927,7 @@ namespace Catch { public: ListenerRegistrar(StringRef listenerName) { - registerListenerImpl( Detail::make_unique(listenerName) ); + registerListenerImpl(Detail::make_unique(listenerName)); } }; } @@ -12913,14 +12943,15 @@ namespace Catch { } \ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION -# define CATCH_REGISTER_LISTENER( listenerType ) \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace { \ - Catch::ListenerRegistrar INTERNAL_CATCH_UNIQUE_NAME( \ - catch_internal_RegistrarFor )( #listenerType##_catch_sr ); \ - } \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +#define CATCH_REGISTER_LISTENER(listenerType) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace \ + { \ + Catch::ListenerRegistrar INTERNAL_CATCH_UNIQUE_NAME( \ + catch_internal_RegistrarFor)(#listenerType##_catch_sr); \ + } \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION #else // CATCH_CONFIG_DISABLE diff --git a/Utilities/DataSampling/src/DataSamplingReadoutAdapter.cxx b/Utilities/DataSampling/src/DataSamplingReadoutAdapter.cxx index 66a872e265baf..601968573d3a2 100644 --- a/Utilities/DataSampling/src/DataSamplingReadoutAdapter.cxx +++ b/Utilities/DataSampling/src/DataSamplingReadoutAdapter.cxx @@ -25,7 +25,7 @@ using DataHeader = o2::header::DataHeader; InjectorFunction dataSamplingReadoutAdapter(OutputSpec const& spec) { return [spec](TimingInfo&, ServiceRegistryRef const& ref, fair::mq::Parts& parts, ChannelRetriever channelRetriever, size_t newTimesliceId, bool& stop) { - auto *device = ref.get().device(); + auto* device = ref.get().device(); for (size_t i = 0; i < parts.Size(); ++i) { diff --git a/run/o2sim_mctracks_proxy.cxx b/run/o2sim_mctracks_proxy.cxx index 8b40c6a647cca..a17d9b415d71c 100644 --- a/run/o2sim_mctracks_proxy.cxx +++ b/run/o2sim_mctracks_proxy.cxx @@ -94,7 +94,7 @@ InjectorFunction o2simKinematicsConverter(std::vector const& specs, auto Nparts = std::make_shared(nPerTF); return [timesliceId, specs, step, nevents, nPerTF, totalEventCounter, eventCounter, TFcounter, Nparts, MCHeadersMessageCache = MCHeadersMessageCache, MCTracksMessageCache = MCTracksMessageCache](TimingInfo& ti, ServiceRegistryRef const& services, fair::mq::Parts& parts, ChannelRetriever channelRetriever, size_t newTimesliceId, bool& stop) mutable -> bool { - auto*device = services.get().device(); + auto* device = services.get().device(); bool didSendData = false; if (nPerTF < 0) { // if no aggregation requested, forward each message with the DPL header